by Christof Wollenhaupt, Foxpert
For many years version control in Visual FoxPro and Visual SourceSafe were synonyms. Sessions and articles covering team development exclusively referred to Visual SourceSafe. Most commercial alternatives were designed to be used in a bigger team, not in the small teams that are so typical for Visual FoxPro. Moreover, Visual SourceSafe is a Microsoft product. As it is part of Visual Studio and because Microsoft made earlier versions available for free to conference attendees, most developers had access to Visual SourceSafe in some way.
But does that mean that Visual SourceSafe is the best choice?
There's no doubt that using any version control system has many advantages. Version control systems allow multiple developers to work on the same project without having to resist to error-prone manual synchronisation of directories. They allow for documenting every change. Virtually every version control system supports labelling all files of the current version. Later you can retrieve files by label enabling you to restore a particular version of your application. This feature is priceless if a customer reports a bug that isn't reproducible in the current version.
Nonetheless, Visual SourceSafe has got a number of disadvantages, too. Visual SourceSafe is not a client/server solution. Because the SourceSafe client directly accesses the VSS database, this automatically increases the payload on the network. While this is only a minor issue for local network, it makes it virtually impossible to access a VSS database even across a DSL line. In addition you are deeply dependent on the quality of the network connection. A single machine with a defective network adapter, a single computer with tendency to crash is sufficient to destroy the entire history of a file in the database.
Microsoft released version 6.0 Visual SourceSafe in 1998 along with VFP 6.0. For the following almost eight years, Microsoft released three more Versions of Visual FoxPro, many new operating systems, versions of offices, with .NET even a complete new development platform. However, for Visual SourceSafe they only released minor patches. Visual SourceSafe 2005 is the latest version of VSS. It does have a few new features for Visual FoxPro Users.
With Visual Studio 2005 Team System Microsoft made it pretty clear what the future path for team development and collaboration will be. Since VS.NET is the main development tool at Microsoft, there's obviously not much of a future for VSS for developers. Indeed, VSS 2005 is targeted at two groups: The VS 2003 developer and mostly Office developers that are not yet integrated into Visual Studio. Once that happens, Visual FoxPro remains the only product that would benefit from Visual SourceSafe.
To access a VSS database via a VPN or any other network connection with low bandwidth, there are only few commercial solutions available. The most popular one is SourceOffSite. Even though this is a good and stable product, it introduces two more problems. For one, the increase in licensing costs is substantial. SourceGear, the maker of SourceOffSite, also offers their own version control system named SourceVault. This inevitably raises the question how long the company supports both products, considering that Microsoft is reducing its support for SourceSafe.
Finally, security becomes an increasing issue, too. Even though you can grant permissions to users in VSS, this is all smoke and mirror. As a file server based system, a user needs write access to the entire VSS database folder in order to check in any file. Hence, instead of going through the client, a user could search the file directly in the database folder.
CVS and SubVersion are open source alternatives for Visual SourceSafe.
CVS consists of two components: a server and a client. Like in many open source projects there are several different tools available for a number of platforms. These tools share some parts, but differ in others. This document only covers the Windows version. You can download the most recent version from the following web sites:
CVSNT is an implementation of CVS for Windows that was so successful that it has been ported over to UNIX. CVSNT is the server component. As the name indicates, you need a server machine to install CVSNT. The operating system doesn't have to be Windows Server, Windows XP works just as well. When choosing the computer you should consider the following criteria:
As you expect from any Windows application, the installation procedure is self-explanatory. Launch cvsnt-2.0.58a.exe as an administrator. If you install CVSNT on your desktop machine, you are most likely not logged on as an administrator. Therefore right click the application and choose "Run as…". On Windows 2000 you need to hold down the Shift key while you click the right mouse button. On Windows NT you have to log on as an Administrator. Accept the license agreement and use the default settings in all following steps.
CVSNT installs itself as a Windows service that is launched when the computer starts up. For configuring the service, you find a new option CVSNT in the Control Panel. On a desktop machine, hold down the Shift key while right-clicking the icon in order to execute the configuration dialog as an Administrator. CVSNT actually consists of two services. The "CVS Service" provides access to the CVS database. The "CVS Lock Service" manages file locks.
The configuration dialog provides a quick overview on the state of the service. Normally, the default configuration is sufficient. To complete the installation you only have to create a repository.
A repository corresponds to a Visual SourceSafe database. The repository contains all files and projects that the CVS server manages. Normally you have a single repository for each server to which you add all your projects. You only need multiple repositories, if you not only want to restrict access to projects inside the repository, but also want to prevent developers from seeing a list of other projects, at all. Another reason to maintain multiple repositories is when you need to hand over the repository to your client when you are done with the project.
You create a new repository on the Repositories page in the CVSNT configuration dialog. Click on Add. You are prompted to pick a directory that is used to store the repository files:
Please write down the value of "Name". You will need it every time you access the repository. Create a new directory on your computer and pick it. After clicking on OK, CVS asks you whether it should initialize the repository. Choose Yes.
After that the repository is ready to use. With the default settings CVSNT uses the Windows user management to validate access to the repository. By granting or denying users access to the newly created repository directory, you can control which user can log onto the CVSNT server. How you structure access depends on your situation. To simplify your administration, it's recommended to create user groups for CVS. Then assign the groups to your users.
If you are logged on as a regular user on your computer – always a good thing to do – and you don't want to create a user group for CVS, you have to grant yourself write access to the repository directory.
Aside from the repository, the CVS server requires write access permissions to the TEMP directory. By default, this is C:\program Files\CVSNT\Temp. Regular users do not have write access to this directory, by default. You either have to grant users in general, or the CVS group write permissions to this directory.
CVSNT installs CVS.EXE. This is a command line program to access the CVS server. If that's sufficiently comfortable for you, you can read everything about the syntax in the extensive help file and skip this section. However, most Windows and DOS developers don't feel comfortable with pure command line tools, as the success of tools like Norton Commander or PC Tools made clear. For those developers WinCVS is an excellent interface.
You install CVSNT only on the server. WinCVS, on the other hand, must be installed on every machine from which you want to access the repository. Launch the setup program as Administrator, accept the license agreement and leave all settings at their default.
When WinCVS completed its own setup, the setup launches the CVSNT setup. Even if you installed CVSNT on this machine already, you have to complete the setup. WinCVS uses CVSNT to install the client tools that it needs to communicate with the CVS Server. You can ignore any warning regarding the existing installation of CVSNT. The first time you start WinCVS you must do so as an administrator. WinCVS wants to create some settings directories and registry keys. Otherwise WinCVS will crash when you close it. Subsequently, you can run WinCVS with your regular user account.
Launch WinCVS using the Start > Programs < WinCVS < WinCVS menu item. You should see the main window:
Developers that are used to Visual SourceSafe often find CVS a bit strange. WinCVS looks a lot like the VSS Explorer, but it works quite differently. This starts with accessing the repository. VSS is an integrated system. The Explorer contains all the code needed to access the database. WinCVS, however, sits on top of CVS.EXE. Every action in WinCVS results in a call to the external EXE. All parameters are passed as command line parameters. WinCVS shows all output of CVS.EXE in the lower pane.
The second difference is the so called CVSROOT. This environment variable defines on which server you access which repository using what user name. This setting isn't stored globally, but project specific. More precisely, it's stored separately for every folder. You need to know this when you change the server name.
Just like with Visual SourceSafe, in CVS developers don't work in a common directory. Every developer has his own local directory that in the terminology of CVS is called a sandbox. The developers loads those modules into the sandbox on which he's currently working. This process is called a check out, but doesn't have to do anything with checking out in VSS. Before you can check out a module from the repository, you first have to create a new module in the repository. This process is called an import. In the following sections I'll use the Tastrade project.
When you import into a repository, CVS adds all files to the repository that exist in the directory. During the process you can only include or exclude file extensions, not single files. Therefore it's recommended not to import directly from your development directory. Instead copy the project into a new directory and delete all files that you don't want to add to the repository. These are, for example, all data tables, FXP files and so on.
A further difference is the handling of binary files. Contrary to VSS, CVS doesn't support exclusive check outs. In fact, everybody can edit every file anytime. Upon checking in (in CVS called a commit) CVS analyses the differences and merges your changes into the master copy. This isn't a problem with text files, but it's impossible to do with binary files such as VCX class libraries or SCX forms.
This alone wouldn't be impossible to solve. CVS offers options to indicate that others shouldn't edit a binary file. The real problem is Visual FoxPro, though. A VCX library doesn't only contain source code, but also compiled code. The compiled code changes every time a class library is recompiled. If you are building the EXE, CVS considers all VCXes to be changed. Therefore you can't simply get the current version from the repository. Instead you would have to reject the changes (get the clean copy operation in CVS). Before you do this you definitely need to know which files you really have changed, because you don't want to undo the changes for that file.
I wrote a tool named TwoFox, because in practice it's impossible to deal with binary VCXes. TwoFox consists of two components: GenXML and GenCode. GenXML takes a VFP project and produces XML files for all binary files. GenCode reverts these XML files into code files. Unlike the SCCText.prg tool that is used in conjunction with Visual SourceSafe, TwoFox is a true two-way tool.
Let's start the import of a project by creating a copy of the project directory. In this directory create a subdirectory named Tools. Copy GenCode.APP and GenXML.APP into that directory. In my experience it's good idea to keep a copy of these tools in the project directory to avoid versioning problems if you have multiple projects that need different versions of TwoFox. Launch VFP and switch to the project directory. In the command window enter
You are prompted for a project file. GenXML then creates XML files for every binary file. Because GenXML basically uses the xml functions provided by Visual FoxPro, the conversion doesn't take very long, even for huge projects. Close VFP and open the project directory in Windows Explorer. Delete all files that you don't want to place under version control. This includes test programs, generated files, and so on. In case of Tastrade delete the following files:
By using GenXML you can also delete any file for which GenXML created an XML file. These are the class libraries, forms, reports, labels and the project file.
Before you import a module, you have to log onto the CVS server. From the menu choose Admin > Login. You'll get the login dialog. Upon the first time, the CVSROOT field is empty. Click on the "…" button on the right side of the text field, to get the dialog for entering the path. This dialog looks like this:
In the Protocol combobox select sspi. As Repository path enter the name of the repository. This doesn't have to be the physical directory name. In the CVSNT configuration dialog this value corresponds to the first column. Please note that you have to use "/" as a path separator instead of the "\" commonly used in Windows. The Hostname is the name of the computer on which you installed CVSNT. Here you can also enter an internet address, or a TCP/IP address, To change a value in the list click on the entry and then on "Edit…". In Username enter the normal Windows logon name. For security reasons you shouldn't fill out the field Password.
Close the dialog with OK. Close the login dialog with OK, too. WinCVS now attempts to log you onto the CVS Server. Eventually, you are prompted for a password. Then enter the password, you normally use to log onto Windows. When you have been logged on successfully, you see the following text in the output pane:
cvs -d :sspi;username=Christof;hostname=fpl5:/repository login
Logging in to :sspi:Christof@fpl5:2401:/repository
***** CVS exited normally with code 0 *****
When there was an error, you get the following result:
cvs -d :sspi;username=Christof;hostname=fpl5:/repository login
Logging in to :sspi:Christof@fpl5:2401:/repository
cvs [login aborted]: Logon failure: unknown user name or bad password.
In general you need to pay attention to the output pane. If an error occurs while executing a command, you won't get a dialog, but an error message in the output pane. The successful execution of a command always results in the following message
***** CVS exited normally with code 1 *****
Most times the code is either 0 or 1. After you removed all unnecessary files from the project directory, activate the tree view of the project directory in WinCVS. In the menu go to Remote > Import module… Verify that you only have those files in the list that you expect. Also check whether the distinction between TEXT and BINARY has worked out properly, because you can't change that afterwards.
In the next dialog you have to enter some additional information. Very important is the "Repository Path" textbox. Here you define the name of the module on the CVS server. Choose this name carefully as you cannot easily change it later. Also verify that the specified CVSROOT is correct. Start the import by clicking the Ok button. After a successful import, you can delete the directory. Now you can share the project with other developers of the team.
Before you can work on a project that has been imported into CVS, you have to create a local working copy in your local working folder (sandbox). In the tree view select the directory in which you want to create the project directory. For example, if the project directory should be C:\Projects\MyApp, you need to navigate to the C:\Projects folder in CVS. The subdirectory is automatically created. The focus must be in the list on the left side. Then pick Remote > Checkout Module…
If the CVSROOT textbox is empty, you can select an existing CVSROOT entry with the combo box. Then you can enter the name of the imported module in "Module name and path on server". If you can't recall the name, you can click the "…" button to get a list of all modules on the server. To query the server for the list, you have to check the "List" option and select the CVSROOT.
If the directory shouldn't have the same name as the module, you can overwrite the option "Checkout into directory". In the following sample, the directory is C:\Fox\Temp. Checking out the module produces the C:\Fox\Temp\Tastrade directory. This directory contains the module Tastrade from the repository.
After checking out the module you have a directory that contains all files in the repository. As we had to generate text files for a number of VFP files, we now have to revert this process. Launch VFP and switch to the newly generated directory. Launch GenCode with the following command line:
Select the .twofox file of your project. In my example this is Tastrade.twofox. You receive a security dialog that reminds you that GenCode now generates code. There's no risk of loosing data, because GenCode creates a backup of every file before it overwrites it. Nonetheless, this is the right moment to think whether you made any change that you haven't yet checked in.
Close the dialog by hitting Yes. GenCode now generates and compiles all binary files. After checking out a module from CVS, you only have the files that were in the repository. If needed you must copy or create those files that are not under version control. In the case of Tastrade, for example, you have to copy the Data directory. Normally you would get these files by using a StoneField data dictionary that you checked into the repository, by using an XCase model or by maintaining a directory with test data.
Now finally, you can open the project in VFP and start editing all files. You only have to follow this huge list of steps once for every project. After the project and the local working copy is set up, the following steps are sufficient.
You can edit a file time without having to explicitly check it out. When you have completed your changes and tested them, you have to add these changes to the repository. With CVS this is a two step process that consists of the actions Update and Commit. In Visual FoxPro you need an additional step to generate the XML files. First of all execute the GenXML program in Visual FoxPro:
Do Tools\GenXML with "Tastrade.pjx"
This converts all modified files into XML files. If a binary file hasn't changed, GenXML doesn't touch the associated XML file. This permits WinCVS to use the file stamp to detect all modified files. When using the so called Flat mode and the filters, you can see all modified files of the project in a single list in WinCVS.
Before you can transfer any files back to the server, you need to perform an Update. In the directory tree on the left side select the project directory. Then pick from the menu bar the Modify > Update item. In CVS updating doesn't mean that you update the repository, rather that your working folder is updated with the current version in the repository.
CVS checks which files other developers have changed in the meantime and downloads the most recent version. If you and other developers modified the same file, modifications of the other developer are merged into your version. In the file list those files appear with a file stamp of "Result of merge". Additionally, the output pane gives details on which versions have been merged together.
If both changes caused a conflict, CVS generates a file that contains both versions. It's your job to edit the file with a text editor to solve the conflict. In practice, this only happens if developers do not commit changes regularly. When CVS encounters a conflict it reports the conflict in the output pane.
Force yourself to check the entire CVS output after you updated the project. This requires discipline, but is the only way to discover problems. The first character explains what happened to a file:
CVS downloaded the file from the server. Another developer either added the file to the repository, or your local version differs significantly from the remote version.
CVS patched your local file downloading only the changes from the server. This usually saves bandwidth.
You have modified a file locally that you haven't yet committed to the server.
You marked a file for addition to the repository, but haven't yet committed the file.
You marked a file for deletion. The file will be deleted when you commit it.
The file is not in the repository. If certain files should not be added to the repository, you can create a file called ".cvsignore" (watch the period at the beginning of the file name). In this file you create one line for each file that you don't want to see in WinCVS. You can use wildcards such as * and ? to exclude group of files, eg. "*.vc?", to ignore all VCX, VCT and VCA files.
To solve conflicts it's useful to view the difference between your version and the version in the repository. WinCVS can show you these differences. The result, however, will only satisfy you think graphical user interfaces are a waste of time even in Linux. Therefore it's useful to rely on an external tool to compare files in a more intuitive manner. One such alternative is the open source project WinMerge that you can download from http://winmerge.sourceforge.net/. I personally favour a commercial tool such as Beyond Compare (http://www.scootersoftware.com/).
You enter the external diff tool in WinCVS by choosing Admin > Preferences in the menu. On the WinCvs page enter the path to your external application in the "External Diff" textbox. The application is called with the full path to the two files you want to compare. To compare a file with a version from the repository, right click the file and pick the "Diff" option. In the dialog check the "Use the external diff" option, if you want to use the external program that you specified in the options dialog.
Even though it's an extra burden at the beginning I strongly recommend you to compare your own version of a file with the version in the repository before committing any change. Only by doing this you can ensure that:
After you solved all conflicts and verified all modifications, you can transfer all changes back to the CVS server (commit). Right click the file that you want to send back and choose "Commit" in the menu. You get the commit dialog:
Because it's really important to check all modifications, WinCVS offers a Diff button right on the commit dialog. This gives you a final opportunity to compare your files with the one in the repository.
You can also enter a comment that describes what you have changed. You should make it a habit to always enter something here without exception. Otherwise you make it really hard to trace back changes. Of course, you can easily view the differences between 1.1.15 and 1.1.43. In reality, though, you want to know when a particular block of code has been changed. Without useful comments, you have to diff all versions until you find the one that introduced the new code.
After committing all changes switch to the tree view and run Modify > Update again. This time you shouldn't see any modified files, unsolved conflicts, etc. In the file list of WinCVS, you shouldn't see any red file. If that's the case, you local version is a complete copy of the repository and, hence, the most recent program version.
Changes made by others are so far only reflected in the XML files. After committing files you therefore have to execute GenCode to convert these XML files into executable binary files. Launch Visual FoxPro, switch to your project directory and enter:
Do Tools\GenCode with "Tastrade.twofox"
Obviously, you use the name of your project. If you don't specify the optional twofox file, GenCode prompts you for a file in a file open dialog. After GenCode generated all binary files, you can continue to work on the project. If you work in a team it's a good idea to test your project regularly to verify that it is still working. If the repository contains your master copy and you make it a rule that only working and tested code may ever be submitted into the repository, you can modify the previous process a little bit:
After you committed many versions, you might want to know what has changed. To obtain a list of changes right-click a file and choose the Log… item. This function prints the version history of a file into the output pane. To keep the history manageable, you can use filters to limit the number of versions. This filter is available on the second page of the Log… dialog.
Alternatively, you can use the Graph function. It displays a graphical tree of the entire version history. By clicking on one version, you get the details of a change in the output pane. The most important part is the comment that you entered when you committed the file.
SubVersion is a more recent product than CVS that intends to replace CVS. Even though CollabNet pays a number of developers on the SubVersion team, SubVersion is an open source product. If you wonder how that pays off for CollabNet: The core business of the company is to provide the infrastructure for out-sourcing software projects.
While CVS is a file based system, SubVersion is organized around directories. Therefore you can easily rename files and directories in SubVersion without loosing the history. Increasingly important in bigger projects is the availability of transactions. In subversion, you always check in all files in a single atomic operation. If there's a problem with one file, the other files aren't checked in. This way you can ensure that the repository always remains in a healthy and workable state. Additionally, SubVersion maintains meta data for each file (called properties). Meta data is versioned just like files. If you do a lot tagging and branching, you will benefit from the increased speed for these operations.
You can download the latest version from http://subversion.tigris.org/.
The installation of SubVersion is straight forward. Double click the executable, accept the license agreement and leave all settings at their default. Unlike CVSNT, however, the installed application is not immediately usable.
SubVersion provides a server that can be executed in a number of different ways and be accessed by different protocols. The two main configurations are running SubVersion as an Apache module and as a stand-alone process.
Running SubVersion as an Apache module requires that you install and configure Apache 2.x. If you haven't done any work with Apache before, the setup is a bit more complex. In exchange you gain some advantages. For one, SubVersion uses the WebDAV protocol. Therefore you can use existing WebDAV clients to access a subset of the features of SubVersion. Furthermore, the range of supported authentication and encryption methods is much broader.
The easier setup is using the svnserve.EXE server process. You can launch it from the command line. SubVersion is immediately ready to server requests. If you run SubVersion on an unattended server, that's not a good solution. You rather want to run subversion as a Windows service.
First of all, you have to create a repository. Open a command line (CMD.EXE) and switch to the \Program Files\SubVersion\bin directory. Then enter the following command:
SVNADMIN create C:\svnrep
The last part is the path to the repository. If you already installed TortoiseSVN, you can create an empty directory in Explorer. Then right click and choose TortoiseSVN > Create repository here…
Before you can connect to the repository, you have to specify who is allowed to log on. When you install SubVersion as an Apache module, you can use NTLM authorization. That means, the client automatically logs onto the SubVersion server using you Windows user name and password. On the server side you can grant access by using Apaches build-in permission handling to grant access to the repository.
With the lightweight server, on the other hand, you have to configure user logins specifically for SubVersion. Each repository has a list of users and passwords. Start by opening \repository\conf\svnserve.conf. The format used by SubVersion is similar to the one used by Apache or Windows INI files. First of all remove the comment (#) from the following two lines:
# password-db = passwd
Next, open the passwd file that is located in the same directory. Remove the "#" from the following line:
Then enter user names in the format
username = password
christof = 1234
The password must be specified in plain text. It's not encrypted in any way. The user name is not case sensitive. Remains one thing to do: Installing SubVersion as a service. There's no built-in support for Windows services. However, Magnus Norddahl wrote a little utility named SVNService for that purpose. The installation is pretty simple.
Download his tool from http://dark.clansoft.dk/~mbn/svnservice/. Copy SVNSERVICE.EXE into your SubVersion bin directory (the one that contains SVNSERVE.EXE). You can ignore any of the other files. Then launch a command line as an administrator, activate the SubVersion bin directory and execute the following command:
SVNSERVICE -install –d –r c:\svnrep
The last parameter is the location of your repository. Change it as needed. Now you should find a service named "SVNService" in the Services console. You can either run it from the console, or enter the following command to start SubVersion:
NET START SVNService
From now on SubVersion starts with your computer. If you've got a firewall, you must allow SVNSERVE.EXE to access TCP and UDP ports 3690 for inbound and outbound traffic.
SubVersion bases on the same principles as CVS. Consequently, everything said about CVS also applies to SubVersion. Instead of specifying a CVSROOT value, you have to connect to the repository using a URL. If you installed SubVersion as described previously, the URL would be:
svn is the protocol name for accessing the SVNSERVE.EXE server. If you had used Apache, you would use the http:// protocol. For any write access you are prompted to enter the password. Use the login and password that you specified in the passwd file.
In CVS you specified the module (directory in the repository) separately from the CVSROOT. In SubVersion you add the module name after the initial path. This is important if you want to import a directory. If you would just specify the address as above, all files are imported into the root of the repository. Therefore you need to specify an address like:
To access SubVersion, you can use several tools. Just like with CVS you can use the command line version. The name is SVN.EXE. All parameters are described more in detail in the help file.
Another option is TortoiseSVN. It's a shell extension that adds checking in/out files, browsing the repository, etc. right into Windows Explorer. In addition, the tool offers icon overlays. That means, TortoiseSVN uses the icon for the file type and then adds a symbol that indicates if the file is current or has been modified.
For many developers this is a key feature to use TortoiseSVN as well as to avoid TortoiseSVN.
If you belong to the latter group doesn't like to work in Explorer, or don't like the impact of having an Explorer extension, you can use SmartSVN. It's a commercial product that is free for use in foundations. SmartSVN provides a more WinCVS like interface:
CVS SCC plug-in (commercial): http://www.pushok.com/soft_cvs.php
SVN Service: http://dark.clansoft.dk/~mbn/svnservice/
SmartSVN (commercial): http://www.smartcvs.com/smartsvn/index.html
Beyond Compare (commercial): http://www.scootersoftware.com/