CVS on Mac OS X with XCode
I've sung the praises of XCode and its support for Source Code Management (SCM) systems like the Concurrent Versions System (CVS) before, even on behalf of Apple, but it is no secret that support is incomplete and somewhat buggy. Nonetheless it can work!
The steps required to actually get CVS working through XCode are scattered over a variety of resources. However, there is no one reference that I could find which walked a developer through the process of getting their project into CVS such that XCode was happy. Having very recently worked through a proceedure that actually works (rather than hacking at it all the time to get it working) it is time to put my money where my gob is, and describe the process.
Read on for a tutorial on moving an existing XCode project into a CVS repository, and importantly, inviting XCode to join the party. As a bonus, I'll descrive how to access that repository remotely over an ssh connection.
Firstly, you need to have an XCode project. If you don't, you can just create one in XCode. I'll refer to it as your project.
1. Clean your project.
1.1. In XCode with your project open, select Clean All Targets from the Build menu. Close your project.
1.2. In the Finder, search through all your project's folders and delete any called CVS. They may be present if you have previously tried to add CVS support and will only cause confusion and frustration at this point, so start afresh and delete them.
2. Set up a system CVS repository. The best instructions for this I found from Apple. Only follow the instructions in the "Getting Started" section. The rest will be covered here. In brief, you need to:
2.1. Make a directory for the repository. For example, at the command line (where % is your Terminal prompt):
% sudo mkdir /usr/local/cvsrep
2.2. Make it writable for yourself ***fixed as per coke's comment***
% sudo chmod g+w /usr/local/cvsrep
Note that I also had to change the group to admin because I wasn't in the wheel group!
% sudo chgrp admin /usr/local/cvsrep
2.3. Set the CVSROOT environment variable
% export CVSROOT=/usr/local/cvsrep
Also copy this to .bash_profile or equivalent.
% echo "export CVSROOT=/usr/local/cvsrep" >> ~/.bash_profile
2.4. Initialise the CVS repository:
% cvs init
3. Update the CVS wrappers so CVS actually works with XCode projects. The cvswrappers file (/usr/local/cvsrep/CVSROOT/cvswrappers) tells CVS how to handle particular files which can't be treated as text. The best cvswrappers file I've found is actually supplied along with the Developer Tools and lives in /Developer/Tools. You could just copy this file over to the repository, but I strongly recommend declaring peace with the CVS gods and doing it the CVS way:
3.1. Check out and modify the CVSROOT "project". In any writable folder (your home directory will do) execute these commands:
% cvs co CVSROOT
co is short for checkout, which should copy the CVSROOT "project" to your current folder.
% cd CVSROOT
% cp /Developer/Tools/cvswrappers ./
% cvs commit -m "Updated the cvswrappers file to the Apple supplied one in /Developer/Tools"
% cd ..
% rm -R CVSROOT
3.2. Also copy the cvswrappers file into your home directory prefixing it with a period (.) to hide it. This should be redundant (it should complement the repository's cvswrappers) but this may help with remote CVS access and importantly, wont hurt:
% cp /Developer/Tools/cvswrappers ~/.cvswrappers
4. Import your project into the CVS repository. First, move to your project's directory, and then use the cvs import command:
% cd /path/to/your/project
% cvs import -m "Initial import" MyProject vendor-tag start
The -m allows you to supply a comment. MyProject should be the name of your project as it will appear in the CVS repository. It is also the name of the directory which will be produced, so it is a good idea to use your Project's directory name (which could be the same as your Project's name). Read about the vendor-tag here, but I just use the name of my company. The start option is the release tag. There is more information about the import command and these options here.
5. Check your project out of the repository. This seemingly redundant step is critical! You'll need to checkout the project you just imported. You also need to move your current copy of the project out of the way while you checkout the repository copy. Checking out the project over the top of the old one will not work!
% cd /path/to/your/project
% cd ..
% mv project project-before-CVS
% cvs co MyProject
6. You now have a CVS capable version of your project. Go ahead and double click the project file in your fresh project folder to open it in XCode. Get Info on your project to show the Project inspector window. Check the "Enable SCM" box in the General tab and select CVS from the drop down if it is not selected. Also press the "Edit..." button and make sure the "Use ssh" checkbox is checked. This will become important when we go to access the repository remotely. You'll know CVS is working if when you select the SCM tab in the Info dialog, a "1.1" and "1.1.1.1" Revision appears in the list. These may appear differently depending on how exactly you imported your project, but if connection to the repository is successful, you should see more entries than just the "Local" one. If it doesn't appear to be working, there are a number of ways you can try to "kick" XCode into CVS action:
6.1. Select the CVS smart group in your project tree.
6.2. Control-click a file in your project and choose one of the three CVS commands (Update, Compare, Diff).
6.3. Choose "Show SCM" from the SCM menu. Try "Refresh SCM Status" from the same menu.
6.4. Make a change to a file and save it, with the SCM window open.
Hopefully you have some SCM love by now. Try a commit from XCode to confirm things are working. Note that in one case, I had to fiddle around until the .xcode file itself appeared for committing and commit that, before I could successfully checkout a working project.
7. Finally we can get to the exciting part - sharing the repository. In my case, I wanted to be able to access the repository on my iMac from my Powerbook. The two computers were connected by Airport but these steps should work regardless of the network and computer setup. Firstly, set up the repository machine (which I'll refer to as the iMac for brevity sake) for remote access.
7.1. Make sure you have ssh (secure shell) access to the iMac turned on. If you haven't done this, it is as easy as selecting the Remote Login option from System Preferences->Sharing->Services.
7.2. Set the CVS_RSH environment variable to ssh:
% export CVS_RSH=ssh
% echo "export CVS_RSH=ssh" >> ~/.bash_profile
7.3. Make sure the computers are connected via a network, and you know how to reach the iMac from the network. I use Rendezvous because it all works automatically, so my iMac's name is Hemi.local.
8. Set the other machine (which I'll call the Powerbook) for connection to the iMac.
8.1. Test the connection to the iMac from the Powerbook:
% ssh username@Hemi.local.
In my case, my username on the two machines is the same, so I can leave the username@ bit out. You would normally have to enter your password at this point to connect, and since you'll likely be making a lot of connections this way, I recommend using password-less ssh connections via private/public keys, as described in many places, but probably best here.
8.2. Set the same CVS_RSH variable as for the iMac on the Powerbook. Then set the CVSROOT environment variable to :ext:username@Hemi.local.:/usr/local/cvsrep
Of course, you'll have to use your own username and address for the iMac in place of username and Hemi.local. respectively.
8.3. Put the cvswrappers file from /Developer/Tools in your home directory on the Powerbook, as you did with the iMac, prefixing it with a period again.
9. Now we can test the remote CVS connection. Move to a writable directory you want your project to appear in and execute this command:
% cvs co MyProject
That should fetch your project from the repository on the iMac, and make a local copy on the Powerbook.
10. All that is left is to test your project still works in XCode.
10.1. Go ahead and double click the project file in your freshly checked out project on the Powerbook.
10.2. In XCode, confirm you can do all the CVS things you could on the iMac. In particular, try to commit and change, then confirm it appears on the iMac. Commit a change on the iMac and confirm it appears on the Powerbook.
10.3. One bug I was not able to squash was that when I bring up the SCM window on the Powerbook, it would immediately prompt me for a password for the repository. Of course, it shouldn't be necessary because I'm using password-less ssh and CVS access from the command line works fine. Sure enough, regardless of what I entered for a password or even if I cancelled, I could not get a connection to the repository this way. Instead, I needed to close the SCM window and invoke a connection in one of the other ways as described in (6.1, 6.2, 6.4) or via the project info inspector.
That's it! I'm now happily CVS'ing between the two computers, and despite a bit of manual labour required in keeping the status up to date and monitoring the status of files, it appears to work very well.
Comments
I received a bit of feedback on the XCode-Users mailing list about these instructions, and felt it rather important to at least mention the main themes brought up.
The fundamental concern some people had was that use of cvswrappers is outright wrong and will cause problems in the future (and some said the same of CVS altogether). I'd recommend looking at these concerns, starting with these two references, and then reading on for as long as you like through the endless discussions:
http://cocoa.mamasam.com/COCOADEV/2002/09/1/43996.php
http://www.omnigroup.com/mailman/archive/webobjects-dev/2001-February/006876.html
The solution I described in the blog works for me, and will not work without cvswrappers. However, I am very wary now of problems in the future. One alternative solution I'm considering is to separate SCM and coding altogether, and to not rely on XCode to do updates or commits. That opens up the opportunity to use dedicated applications as faces for any SCM system you like - Subversion is getting some glowing reviews over CVS.
One other important point which came up, was that having a ~/.cvswrappers file setup might require moving it away when accessing different repositories - in particular, SourceForge, which doesn't support cvswrappers.
The whole XCode-Users thread is browsable/searchable here:
http://haoli.dnsalias.com/forums/viewtopic.php?t=59618
Posted by: Heath | July 16, 2004 4:01 PM
thank you very much
awesome guide
worked very well for me 2 =)
Posted by: coke | August 28, 2004 1:44 PM
ah well almost forgot about it =P
change
2.2. Make it writable for yourself
% sudo g+w /usr/local/cvsrep
to sudo chmod g+w /usr/local/cvsrep
hope that helps =)
Posted by: coke | August 28, 2004 1:49 PM
Hi Heath,
Thanks for the tips; I've got Xcode and CVS working together on my desktop :-)
Like you, I'm getting nowhere with the password problem on my PowerBook. Did you ever figure how a way around the problem?
-Neil
PS Nice comment spam collection; don't cha just love'em :-(
Posted by: Neil | November 8, 2004 6:23 AM
Thanks for the article. Solved all my problems with cvs access thanks to the information you presented.
Posted by: damaged1130 | September 2, 2006 7:29 AM
Great guide I must say but I have a problem.
I tried to find the cvswrappers in /Developer/Tools but there is no such file.
I have Xcode 3.2, do you know how can I get installed this file?
Thanks
Posted by: Daniel Sanchez Cisneros | September 23, 2009 2:53 AM
Hmm, you're right, the cvswrappers file is gone. Must be time to switch to Subversion! Most of these issues are gone now.
Posted by: Heath Raftery | September 23, 2009 7:48 AM