The Good, The Bad and The Ugly
In this session, we will look at what SourceSafe is, what it can do for you, and how to implement it. We'll look at issues involved in installation, maintaining and updating installed copies, and how to maintain the database. We'll also review how to integrate SourceSafe into the VFP Project Manager and why you may choose not to do that. Finally, we'll look at some third party product that can make SourceSafe easier to use.
This document is based on my experiences with Visual SourceSafe 6.0 and earlier versions. Rumors abound that Visual SourceSafe 7.0 will address many of these issues, ad may indeed be a radical step forward. Past history certainly indicates that with each version of SourceSafe, the issues have changed. Stay tuned.
Source code control can be a very useful tool to the solo developer as well as a key tool for multiple-developer teams. For the solo developer, source code control provides backup facilities and the ability to perform a "grand undo" as well as retrieve early builds or versions. With a multiple-developer team, source code control can ensure that all members of the team work with the latest revision of source code, protect the members of the team from inadvertently overwriting each others work, and provides a simple method to keep track of multiple releases of the software to the same or different clients.
Source code control programs have been around for quite some time but, like difficult backup programs, programs that prove too hard to use are too easy to avoid. With the increasing complexity of projects and the improved accessibility of these products, they are tools are worth the effort to learn. Integration of source code control directly into the development environment is a relatively recent feature that makes these programs easier to use. Bear in mind that Visual SourceSafe, or any other source code control program, is its own product and you must learn its terminology and operations to get the greatest benefit from it. While many operations can easily be performed from within the FoxPro interface, you should become familiar with the less frequently needed maintenance functions that may only be available within the program itself.
Installation of Visual SourceSafe is a two-step process: first, the data structures, administrative tools, and the setup for the client tools is loaded onto a network share (the "Server Installation") and then the client tools setup is run, either from this installation, or from the original source media. This is a pretty standard Microsoft install program, without too many surprises. Ensure that the target directory for the server install is accessible from your workstations.
A problem with this model occurs when the inevitable service pack appears. Service Packs are designed to update the configuration on individual machines, and not on both server and client installs. When the Service Pack is run on the server machines, only the binary files are updated; the setup files for the client install still contain the original files. Hence, clients need to have the Service Pack run on them as well. Each future installation of the client software from the server will also require that the Service Pack be run on the target machine after the installation. In past versions of SourceSafe, Microsoft has provided the instructions to manually update the client installation files to the latest service pack, but unless a large number of installations must be performed, this is both more time-consuming and difficult that just running the Service Pack on each client machine.
Currently, Visual SourceSafe maintains its own user list and, if enabled, individual rights can be granted or revoked on individual projects. While most small development shops will not want to add the administrative burden of maintaining this feature, larger shops often find it necessary, and an onerous task to maintain. It is hoped in future versions that integration with the Windows security model, with the ability to assign group rights, will make this task much easier. Since Visual SourceSafe maintains source code as separate files on disk, and since anyone with permission to use SourceSafe must have complete rights to the data directories, login and security are really only an inconvenience to someone determined to access source code. If tighter security is required, setting up separate databases and using the network rights mechanism is required to prevent unauthorized access to source code.
Analyze is an essential utility for analyzing the health of a VSS databases, detecting inconsistencies and errors, repairing some of the more simple errors, and compacting unused space in the database. ANALYZE should be run periodically (at least weekly) on production databases. The results of Analyze can be a little difficult to decipher, but the Administrator help file (and also Microsoft KnowledgeBase article Q152807) list the more common errors and documents fixes, where available, for these errors. After making a backup of the database and attempting to fix it, always run Analyze again to verify that the problem has been fixed, and to find out if fixing this error brought forth any other errors the first problem may have been masking. In many cases, the Analyze, Backup, Fix cycle may need to be run several times.
With the tools available within Windows NT or Windows 2000, it is not difficult to set up a scheduled task to run the Analyze program on a regular basis, and send the results to a text file. From there, you can process the file into your email system, compare it against previous values, or parse it in FoxPro to determine if actions are required.
Visual SourceSafe stores the entire tree of source code, as well as the tree structure itself, as a large number of files. The files are generated with a sequential series of alphabetic names. There are two files with each name, one with no extension, and the second with a ".A" or ".B" file extension. The file with no extension stores the history of changes to that node in the tree. The file with the extension is the actual contents of that node. If the node is a folder, it contains the folder name and pointers to the files contained in that node. If the node is an actual file (a leaf node), the file with an extension contains the source code itself. Each time the file is changed, a new copy of the file is written out, with whichever extension is available. If the write is completed successfully, the original file is deleted. So, knowing how these obscurely named files match up to the files in your project can give you the ability to recover your source code even if the database was to become severely corrupted.
The format for generating a Physical File List is:
<PATH>\SS PHYSICAL $/ -R -O@Physical.Txt
Where <PATH>\SS points to the SS.EXE file (installed in the Win32 subdirectory of the SourceSafe install), PHYSICAL is the keyword that tells SourceSafe what to do, $/ tells SourceSafe to start from the root of the projects tree, -R to act recursively through the entire tree, and -O@ designates the name of the output file. A word of caution: this command appends to an existing file, if it exists. You'll want to delete the existing file if this is not the desired behavior.
Visual SourceSafe lacks an interface to provide you with some key management information. For example, if you find that your database has grown significantly in size, how to do you determine what caused the size change? Using the physical file list, you can write programs in VFP to help you determine this information:
* Program....: PARSEPHY.PRG
* Version....: 1.0
* Author.....: Ted Roche
* Date.......: June 7, 2000
* Notice.....: Copyright © 2000 Ted Roche, All Rights Reserved.
* Compiler...: Visual FoxPro 06.00.8492.00 for Windows
* Abstract...: Parse the physical file list
* Create a working cursor
create cursor curlist (mFilePath M, ;
cFileName C(8), ;
iFileSize i, ;
index on cFilename tag cFilename
local lcFileName, lcList, laList, lcLine, lnLine
lnLine = 1
lcFilename = "S:\Current\Physical.txt"
IF NOT FILE(lcFileName)
lcFileName = LOCFILE(lcFileName, "TXT", "File?")
* Low-level and array techniques proved difficult
* for this 2+ Mb file.
* MEMLINES() would appear to hang with > 64k lines
* lcList = FileToStr(lcFileName)
* ALINES() is limited to 64k lines - Current is ~75K
* lnLine = ALINES(laList, lcList, .T.) && convert to an array
create cursor fred (cString C(254))
append from (lcFilename) type sdf
* First line is different from all others, so
* fake a record into the table
lcLine = ALLTRIM(Fred.cString)
* First line is the sourceSafe root: $\, usually aaaaaaaa
lcPath = "$\:"
insert into curList values ("Root", ALLTRIM(lcLine), 0, 0)
lcLine = ALLTRIM(Fred.cString)
IF EMPTY(lcLine) && skip empty lines
IF RIGHT(lcLine,1) = ":" && it's a path
lcPath = lcLine
ELSE && if it's not a path, it's a file
insert into curlist values ;
(lcPath + alltrim(LEFT(lcLine,32)), RIGHT(lcLine,8), 0, 0)
* Now update the files for size
local laDir, lnCount, lcSubDir
lcPath = "S:\Current\Data\"
IF NOT DIRECTORY(lcPath)
lcPath = GETDIR(lcPath, "Data?")
* Loop through each subdirectory, "A" through "Z"
FOR m.i = 0 to 25
lcSubDir = lcPath + CHR(ASC("A")+ m.i) + "\*.*"
lnCount = ADIR(laDir, lcSubDir)
? "Updating directory " + lcSubDir
FOR m.j = 1 to lnCount
lcFile = UPPER(laDir[m.j,1])
* For each file, see if it exists in the cursor, and
* if so, update the size of the file
* LOCATE FOR cFileName = UPPER(laDir[m.j,1])
* We use SEEK rather than UPDATE because we only
* want to save the size once -
* shared files are referred to more than once.
IF EMPTY(JUSTEXT(lcFile)) && it's a VSS delta file
REPLACE iFileSize with laDir[m.j,2]
ELSE && it's source
REPLACE iSrcSize with laDir[m.j,2]
ENDFOR &&* m.j = 1 to lnCount
ENDFOR &&* m.i = 0 to 25
* Display the results
brow fields x=left(mFilePath,50), cFilename, iFileSize, iSrcSize
*!* sum iFileSize, iSrcSize, iFileSize + iSrcSize
*!* * 1,637,080,265 by calculation here.
* Get top Groups with:
* Top groups are the nodes off the root path in the form
* of $/Project/subproj/subproj/subproj....
select PADR(LEFT(mFilePath,AT("/",mFilePath,2)),20) ;
as cTopGroup, ;
from current ;
having NOT EMPTY(cTopGroup) ;
group by 1 ;
order by 1 ;
into cursor TopGroup
* Total the sizes for each group
select topgroup.cTopGroup, sum(iFileSize), SUM(iSrcSize),
SUM(iFileSize+iSrcSize) as iTotal ;
from TopGroup inner join Current on ;
Current.mFilePath = ALLTRIM(cTopGroup) ;
group by 1 order by 3 DESC
Microsoft's suggested technique for moving projects between different databases is to use the Archive and Restore options within the SourceSafe Administrator. The advantage of such a technique is that all history is preserved between databases. However, in many cases, the history is not required. It is far simpler to perform a "Get Latest Version" on all files from the source database and "Add" all files into the target database. Also, I have encountered problems with Archive and Restore reporting satisfactory performance, while Analyze reports numerous file problems. This may have been caused by very old and poorly maintained databases so, if preserving the history is important to you, this avenue is worth a try.
Each database is uniquely tagged with a GUID to distinguish it from all others. While VSS will work fine switching between databases with identical GUIDs, Backup and Restore will fail if an attempt is made to transfer files between two databases of identical GUIDs. The Restore program mistakenly thinks it is writing to the original database, and it can produce error messages and corruption of the target database.
Microsoft documents this problem in Microsoft Knowledge Base article Q176780, and provides links to an executable, GUIDSCAN.EXE that, it claims, allows the operator to reset the GUID, stored in the UM.DAT file, to make the databases unique. However, this program does not work in version 6.0 and has corrupted UM.DAT files on several installations on which I tried it. Fortunately, the precaution of making backups before attempting this operation has saved me from a costly rebuilding of my database. Microsoft has been aware of this issue since at least April of 2000, have admitted to me that it is a problem, but continue to have the executable on their website! Amazing.
Regular maintenance of Visual SourceSafe databases insure that, when repairs are needed, most errors can be fixed easily, or backups will minimize the amount of code lost. Microsoft's Knowledge Base contains an article (Q152807) that duplicates the information available within the Administrator Guide (part of SSUSEXP.CHM, installed as part of the client install) that lists common problems reported by Analyze and fixes for them, if possible.
However, more than a handful of developers have reported problems with the integrated source code control. These problems include:
These are legitimate beefs, and each should be addressed.
Multiple checkouts seem to be required by the original design of the source code control integration scheme, but it is possible to work around this. I have had reports from several shops that, instead of having everyone check out the PJM (jointly) and then merging, each developer checks out the file, one at a time, before performing an "Update Project List." to resynchronize their project with the master stored in Visual SourceSafe. As best as I can tell, this technique should work as well.
Finally, there are a couple of advanced topics that are beyond the scope of what I can cover in this session, but I did want to alert you to the possibilities they provide:
The October '97 issue of FoxPro Advisor has an excellent article by Mark Wilden with several suggestions on changes to SCCTEXT.PRG. One issue he identified was a problem with SCX and VCX files jumbling the order of methods each time they were saved. When SCCTEXT generated the method code for the corresponding SCA or VCA file, the methods were not sorted, so viewing differences in the files was difficult. Mark proposed a simple change to the SCCTEXT program to sort these methods before writing out the file.
Part of the limitations of using integrated source code control requires that all source code elements need to be located within the directory and subdirectories of the location of the project file itself. For those of us who use common code libraries, shared class libraries, and pre-built frameworks and components, this is a real inconvenience. The quick-and-dirty manual answer is to use the SourceSafe interface to share all the components into the project tree in SourceSafe, use "Get latest version" to create a copy on disk, then rebuild the project list, adding all of those items into source code control, and answering the messagebox about "Already under source code control. Delete the local version and get the one in source control?" as "Yes" a few dozen times. I believe that someone has come up with an automated solution to this one, but I have been unable to locate it by press time.
Visual SourceSafe supports Automation to allow you to traverse the project tree, check out, modify, check in, and query the status of each individual tree element. This could be the basis for third-party tools that emulate (or improve!) on the Project Manger integrated source code control. Documentation on the Automation interface is available on the Visual SourceSafe web site at http://msdn.microsoft.com/ssafe.
SourceGear Corporation markets a product called SourceOffSite (http://www.sourceoffsite.com) that integrates into your web server and provides client-side access to a SourceSafe database, over the web. Client-side integration provides most of the features available within the SourceSafe product itself, including integration with the IDEs of all of the Visual Studio products. If you have a need for remote access, this is a product I have heard many people rave about.