CVS vs SVN for QNX

Hi there,

Look, I am evaluating the alternative to use SVN instead of CVS as source repository, wich we are using since almost ever.

After my (maybe too) quick reading of SVN documentation, I personally do not find a “serious” reason to use SVN instead of CVS.

Certainly it has some advantages (flexibility, moving, adding, and deleting, atomicity, less BW over the network, metadata, keep track of directories structures, transparent working with differentes file types), but some things still worry to me: data storage is not transparent as a “,v” file is (what with the Murphys law?, repository backups maybe), branches and tagging are copies within the repository according to what I understood, and the storage capacity is not less important. Cached files locally in .svn could still be a problem rather than a solution in some cases.

Concerning to QNX use, QNX could act as CVS local server itself, I suppose it’s not posible under SVN so easily, isn’t it?

I read SVN is a “from the scratch” development based on CVS idea, thats sounds good, in the other hand CVS was from the beggining a wrap for RCS, and that sounds not soooo bad…

SVN documentation complains too much about CVS limitations. Ok, there are they. But we survived them during years without too much effort

Ok, I am still looking for the “GREAT”, “BIG” or at least “SIGNIFICANT” difference, that it means that the big effort to change really worth the pain.

QNX source code itself is under SVN it could be a good answer to my question, but maybe not. We have lot of development under CVS and now is time to make a new choice (or to reaffirm an old one).

Perhaps my lack of experience using SVN is the reason of my prejudices.

I will appreciate your own comments and experience on the matter

Thanks in advance!!
Juan Manuel

The big reason to use SVN is when you have a lot of people spread out over a large area. If you’ve got 10 people on a LAN there’s not much difference. If you have a 1000 people on 4 continents using the Internet to access the repository SVN makes a lot more sense.

SVN is also more “in” at the moment, meaning that there’s more forward progress. For example, the CVS that comes with QNX is dated 2003.

-James Ingraham
Sage Automation, Inc.

We’re in the same boat and see no compelling reason to change.

We have made the switch from CVS and SVN. I wouldn’t go back to CVS. For me the killer feature is that every time you make a commit the revision number applies to the complete repository. That’s like creating a tag automatically each time a commit is performed. Each time we link an executable we get that revision number and stuff it in the executable with “usemsg”. As a matter of fact our release system doesn’t use tag any more, the tag is the URL and revision number.

If in 10 years from now someone finds a USB key covered with dust in the back of a drawer, by running use -i we can obtain all the information we need to get to the history of that executable and rebuild it if need be. That’s true for every executable ever build, assuming all the files were committed obviously, not just official release.

Doing more and more C++ re-factoring is more common, with CVS renaming a file mean loosing it’s history, but not with SVN. That important to us as well. There are also small details that I’m sure you read in the SVN documentation that appears minor but make day to day work more enjoyable.

Also CVS seems like a dead end, with no new feature added, it looks like none of its short coming will ever be addressed.

We use cvs2svn to convert our 1.2G CVS repository, to my surprise it work flawlessly.

Hey Mario!.. Thanks a lot for your observations… Yes, yes… I had in mind the stuff about the $Revision$ and we had the problem you mention. We have “executable” revision but you just can’t know in a simple manner which modules are linked against…

Definitively, this is the BIG difference I was looking for…

I actually can´t bealive that you convert your entery repository with no problems… thats the other thing that worry me…

I think the way is clear, there we go (if I convince my colleagues :slight_smile: )…

Thanks!

Regards,
Juan Manuel

I ran the conversion on a Linux machine which is hosting our CVS and now SVN server. During the conversion I tried to do it on QNX6 but gave up, the convert script is written in python and needs a some add-on module. I didn’t want to waste time on getting that to work, don’t know a thing about python :wink:

I managed to get a SVN server to work on QNX6 but it’s much simpler to setup in Linux because we wanted to go through Apache to support https. Also less problem keeping up with the lastest version since binaries are available for Linux.

I should also add that some stuff is slower then CVS mainly the initial checkout. Some commit can take more time too, over the rest is much faster.

Mario, can you help me telling how do you achieve this job? How can you differentiate between your release version and a version is still in the development instance?. You said that you don’t use tags. But you still use branches?

I want to use only one line of development (let’s say trunk) but I also want to differentiate if this version is in production or not.

But if I can hook the global revision number into usemsg I have what I want, I believe… But ours source files are in Neutrino not Windows, so I know there is no $GlobalRev$ supported, and I need to do this job from the outside. How can I do this directly in QNX?

Thank you very much!!! I will appreciate your answer!!

Regards,
Juan Manuel

PS: Hey, I don’t want to get back to CVS anymore!!..

For us the trunk is always in development. Every time a release is done we create a branch for it. When doing experiment development we also create a branch .

I use the following command in the Makefile :

usemsg -i BUILDER="$(MYNAME)" -iBUILDMACHINE=hostname -iVERSION=ch -c get_version.ch $(ROOTPATH) -iURL=ch -c get_url.ch $(target)

get_version.ch and get_url.ch are two C Shell scripts that we use to extra the information we need. We use C Shell scripts because we can more easily run these scripts in either Windows or QNX6. You should be able to compile them to generate executable or write a KornShell equivalent.

With this any executable that is created get tagged and is traceable.

When we make a release we build a zip file ( actually .7z ) of all the files making up the firmware. That files gets named
firmware__<revision_number>.7z. Also inside the firmware we include a revision.txt file which contains the output of svn info, with all these we’re pretty much covered ;-)

Here is get_url.ch:

#!/bin/ch

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>

int main ( int argc, char *argv[] )
{

FILE *fd;
char buffer[255];
string_t cmd;

	if ( getenv( "SYSNAME" ) != NULL )
		cmd = "svn info";
	else
		cmd = "c:/progra~1/subversion/bin/svn info" ;

	fd = popen( cmd , "r" );
	if ( fd != NULL )
	{
		while ( fgets( buffer, sizeof ( buffer ), fd )  != NULL )
		{

			if ( strstr ( buffer, "URL:" ) )
			{
				printf( "%s", &buffer[5]  );
			}
		}
		fclose ( fd );
	}


}

Here is get_version.ch

#!/bin/ch

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>

int main ( int argc, char *argv[] )
{

FILE *fd;
char buffer[255];
static char delim[] = ":";
int version=-1;
int modifflag = 0;
string_t bin;
string_t cmd;

	if ( getenv( "SYSNAME" ) != NULL )
		bin = "svn";
	else
		bin = "c:/progra~1/subversion/bin/svn" ;
	
	
// En premier, cherche pour voir si y'a des fichiers non commiter

	cmd = bin;
	strcat ( cmd, " status " );
	strcat ( cmd, argv[1] );

	fd = popen( cmd , "r" );
	if ( fd != NULL )
	{
		while ( fgets( buffer, sizeof ( buffer ), fd )  != NULL )
		{
			if ( buffer[0] != '?' && buffer[0] != ' ' && buffer[0] != 'I')
			{
				modifflag = 1;
			}
		}
		fclose ( fd );
	}
	else
	{
		fprintf(stderr, "Can't run command %s\n", cmd);
	}

// Vas chercher ensuite numero de version 

	cmd = bin;
	strcat ( cmd, " info " );
	strcat ( cmd, argv[1] );


	fd = popen( cmd, "r" );
	if ( fd != NULL )
	{
		while ( fgets( buffer, sizeof ( buffer ), fd )  != NULL )
		{
			if ( strstr ( buffer, "Last Changed Rev" ) )
			{
				char *p = strtok( &buffer[1], delim );
				if ( p )
				{
					char *p = strtok( NULL, delim );
					if ( p )
					{
						version = atoi ( p );
						if ( modifflag == 0  )
							printf("%d", version );
					  	else
							printf("*%d", version );
					}
				}
			}
		}
		fclose ( fd );
	}
	else
	{
		fprintf(stderr, "Can't run command %s\n", cmd);
	}

	if ( version == -1 )
		printf("Unknown" );

	printf("\n");

}

Thank you very much Mario!! I close to what I need, but still with some doubts.

  1. What’s $ROOTPATH for you exactly?

  2. Is the revison number attached to the executable the LAST revison number of the whole repository?

  3. if not, how can I rebuild the information about how was the repository when I build THAT file?

Thank you again!!

Regards,
Juan Manuel

BTW: Where can I find a binary compiled ch for Neutrino?

Thanks again!

1 ) ROOTPATH is the path of the project. It’s specific to our build environment.

2 ) Yes the LAST revision

3 ) See 2)

You can get it from : softintegration.com/download/ , there are versions for a variety of platfom.

We use the Windows and QNX6 version. For use as a company it’s a great because all C/C++ program can write scripts without having to learn yet another language ( shell, ruby, python etc)

Yes Mario, thanks! I got it and is working fine!.

Can you help me with SVN bulk of question, please? Thanks…

Juan Manuel

I’m no SVN expert but I’ll try :wink:

:slight_smile: :slight_smile: Thanks Mario!! :slight_smile: :slight_smile:

Hey!.. I did’n see your answers… There’s some strange delay, or my eyes are very slow…

I didn`t see your question !?!? Maybe I miss understood what you meant by “SVN bulk of question”

Sorry Mario, my “bulk” of questions were the only 3 you already answered me!. Thank you! But…

I was trying the ideas you give me (they’re very good ones, and what I was lookig for), but I realize one simple thing. After commiting some module of the project, the “Last Changed Rev” number returned by “svn info” is not updated until “svn update” is run (maybe in the root of the project to keep your $ROOTPATH updated too. Right?) … If not, “svn info” returns an old Rev number. So, do you make “svn update in the root” after every commit?, and just “after that” you compile in order to hook the correct Rev into your ELF?

How do you manage this (expected) behavior of svn?.

Thank you very much again!

Regards,
Juan Manuel

Our release procedure imply that we grab the source from scratch. It’s true that for non release this problem needs to be address but I haven’t got to that ;-) Maybe a simple svn update in the makefile would do it.

Yes… I was thinking the same idea… could work!

Thanks for all Mario !

Hey… I was thinking that doing ‘svn update’ in the Makefile could be a little dangerous…

If somebody else has modified the repository previously, the svn update will ‘update’ the source, and then I’ll compile something I just don’t know what actually is…

I think the only way of having the lastest version to hook inside de executable is a manual and careful ‘svn update’ (after svn status) before compiling…

What do you think?