This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.

MIND

Virtual Source Code Control Systems: Promoting and Managing Projects using Visual SourceSafe

Ken Ramirez
This article assumes you�re familiar with ASP, Visual SourceSafe, VBScript
Level of Difficulty   1   2   3 
Code for this article: Ramirez0500.exe (449KB)

Source code control systems like Microsoft Visual SourceSafe can simplify just about any development project, and make it easier for your code to move safely among individual programmers, development teams, and project stages.
      Visual SourceSafe provides an object model that you can use as the basis of your own customized source code control environment. To give you an idea of what is possible, we�ll walk you through the elements of a browser-based source code control system built with Visual SourceSafe, ASP, and VBScript. This simple system lets members of your team build, label, and promote individual files or entire projects, and to reverse promotions.

U

nless you�ve been stranded on a deserted island for the last few years, chances are good that you�ve heard of source code control systems. Several companies, including Microsoft®, have developed applications that allow development teams to share and control source code files by checking project files into and out of a central repository. To extend the standard functionality provided by these source code control systems, I�ll show you how to use the Microsoft Visual SourceSafe™ automation model to build a Web-based tool that lets your team label and promote your company�s projects.
      There are several objectives to meet in trying to develop solid source control procedures. In my current consulting project, I�m developing a product for a large brokerage house. My team includes several hundred individuals. The application will eventually go through several lifecycle steps, including development, unit integration, system integration, and production release.
      In this project, developers are required to check in their source code every night before going home, while individuals who need the latest working, compile-ready code must still have access to it.
      Requiring team members to remember label names for keeping track of versions is not an option. Today a label might be Beta Version 1.1; next week it may be Beta Version 1.1.1. This can become confusing. It�s much better to simply direct the source code control system to get the latest working version of a file or project. To enforce the rules specific to this project, and to provide on-the-go access for developers, I built a Web-based system that uses the automation object model exposed by Visual SourceSafe.

The Plan

      The custom source code control system I built consists of four fundamental actions: building, labeling, and promoting projects, and reversing promotions. Along with these steps, I also needed to maintain a predetermined directory structure to provide a means for sharing files among the members of the various teams that may be in different stages. This structure is illustrated by the folders shown in Figure 1.
Figure 1 Structure
Figure 1Structure

      Expanding one of the folders exposes the projects inside it. The project subfolders are always duplicated from one root folder to the next. For example, if I created a project named My Project, it would appear in both the 0 Development folder and the 1 Unit folder. (Numbers were included in the folder names to make sorting them easier.)
      When developers start working on a project, they can check files in and out at will. Each night before they go home, they check their files in so that everything can be backed up. Even if their source code hasn�t been completed or tested, it will not affect anyone else�s work.
      Development files, for example, are kept in the 0 Development folder. Members of the Q/A team would retrieve files from folders such as 1 Unit or 2 Integration, where they have already been labeled and pinned so they will not affect the development files. Pinning is the process of locking a file from further change. If you lock a file in the 0 Development folder, it cannot be changed until it has been unpinned. In the system I built, files in the 0 Development folder will never be pinned. However, the advantage of pinning becomes apparent when you pin a shared file from a different folder.

Figure 2 Get Latest Version       If you share My File.cpp from 0 Development\My Project to 1 Unit\My Project, you can pin this file at version 1.5 in the 1 Unit\My Project folder. This means that regardless of how many times My File.cpp changes in 0 Development\My Project, 1 Unit\My Project will always point to version 1.5 of this file, back in the 0 Development\My Project folder. Even if My File.cpp goes to version 2.0, 1 Unit\My Project will continue to point to version 1.5 of the file until it is unpinned and pinned again. This means that someone from the Q/A team can simply go to the 1 Unit\My Project folder and retrieve the latest versions of the files in that folder without worrying about the label or version number (see Figure 2).
Figure 2 Get Latest Version
Figure 2 Get Latest Version

      For this process to work, the project is labeled at some point within the development folder. The files must also be shared to the other folders before they�re pinned. Finally, when they are pinned, a label must be supplied for that pinning. For example, if My Project is labeled as Ready for QAâ€"Version 1.0 within the 0 Development folder, this name is supplied when the file is pinned. Files can be pinned manually using Visual SourceSafe. Pressing the Pin button shows a thumbtack next to the version number (see Figure 3).
Figure 3 Pinning a File
Figure 3Pinning a File

      Labeling and pinning help to establish two of the four requirements for promoting projects. The third is the ability to build the project. I can�t tell you how to do this since I don�t know what your development environment will be. Regardless of what tool you use, it can be incorporated into the promotion methodology by simply plugging it into the tool used to maintain the promotions. Later, I�ll show you how I created a tool like this using Visual InterDev®, Dynamic HTML (DHTML), ASP, JScript®, and VBScript.
      The last of the requirements is the ability to simply reverse the action of promoting a project. This means that all of the pinned files should be unpinned and repinned on previous versions of the files. Obviously, the user must supply the label to be used for repinning.

The Visual SourceSafe Object Model

      Before you can understand the code used to build the promotion tool, you need to know a bit about the Visual SourceSafe object model. I�ll show you enough here to get you started. For a more detailed explanation of the Visual SourceSafe object model, take a look at the MSDNâ„¢ Online article entitled, "Visual SourceSafe 6.0 Automation" at https://msdn.microsoft.com/library/techart/vssauto.htm.
      Whether you�re going to use the Visual SourceSafe model from Visual Basic or from ASP will determine what objects you�ll need to create. For example, from Visual Basic you simply set your references to Microsoft SourceSafe® 6.0 Type Library and open the SourceSafe database as shown in the following code:

Dim Database as new VSSDatabase
Database.Open txtSrcSafeIni, txtUserName, txtPassword

      From Visual InterDev, things are done a bit differently. For example, the following code will open the Visual SourceSafe database using VBScript:


Dim objVSSDb
Set objVSSDb = Server.CreateObject("SourceSafe")
objVSSDb.Open Session("VSSDbPath"),Session("Name"),
 Session("Password")

      The rest of the examples here will use ASP. Keep this in mind if you look at the articles mentioned earlier because they use Visual Basic.
      The Visual SourceSafe object model follows a hierarchical structure as illustrated in Figure 4. The first object you�ll need to acquire is VSSDatabase, which is the entry point into the Visual SourceSafe database. A call to the Open method follows the creation of the object. In the call, you pass the path to the INI file of the Visual SourceSafe database that you�re attempting to open. The call also requires that you pass a user name and password. These are used to verify that the caller has permission to open and access the database.

Figure 4 The Visual SourceSafe Object Model
Figure 4The Visual SourceSafe Object Model

      Most of the actions performed on an opened Visual SourceSafe database require a VSSItem. These objects are retrieved through the VSSItems collection of your VSSDatabase object. The VSSItem property is a collection property. It takes parameters as in the following code:


Dim objProjectItem
Set objProjectItem = objVSSDb.VSSItem(strProjectName)

Here, I am passing the path to a project that I want to manipulate. The path must be a complete path (including the root name and root project path, if it exists). The following example creates a path from several strings:


strProjectName = "$/" & Request.Form("optLevel") & "/"
& _ Request.Form("txtProjectName")

This code receives optLevel from the form, which might contain values such as 1 Unit, 2 Integration, 3 System, or 4 Production. The txtProjectName is retrieved from the form based on a value that the user has provided for it.
      After a VSSItem has been created, it becomes the target of most operations. You�ll use it to create new labels, pin files, check files in or out, or retrieve files.

Dissecting the Promotion Application

      Before a user can use the application, they must be verified as a valid user of the Visual SourceSafe database. To verify the user, an attempt to open the database with a user name and password can be performed. However, the user must first be presented with a page that collects this information and a button for submitting the request to the server. Furthermore, this screen should only be presented in the beginning of the session or if the session expires.
      For this reason, I placed code into the Session_OnStart method within the global.asa file. While I was at it, I also placed default values into Session variables within the OnStart method. Take a look at the Session_OnStart method in Figure 5. As you can see, the real starting point is PromptUserIDAndPassword.htm.
      When the Session_OnStart method redirects the user to the PromptUserIDAndPassword.htm file, the user is presented with the page shown in Figure 6.

Figure 6 PromptUserIDAndPassword.htm
Figure 6PromptUserIDAndPassword.htm

      This page is where users can enter a name and password. The input boxes and Submit and Reset buttons are in a form whose action is set to LogonUser.asp. The code for the form is contained in PromptUserIDAndPassword.htm.
      The user name and password are sent to LogonUser.asp, which attempts to open the Visual SourceSafe database using the user�s credentials (see Figure 7). If the attempt fails, the user isn�t permitted to proceed.
      Once the user�s permissions have been validated, the user is redirected to home.asp (see Figure 8). While the session remains open, the user can click on the Home link from most of the other pages to arrive back at home.asp. However, if the session is closed or expires, the user will be redirected back to the PromptUserIDAndPassword.htm page and asked for his user ID.

Figure 8 Home.asp
Figure 8Home.asp

      The home page contains links to other pages that actually perform the app�s work. As you can see, the home page also provides a flowchart that illustrates the promotion process. Following this chart, you can see that the steps a user would take include promoting the project, then building it. If the build was successful, the project is labeled. Otherwise, the project is unpromoted; developers are notified, flags are raised, alarms are sounded, and so on.

Labeling Projects Programmatically

      The page used to label projects is self-submitting. This means that the input is passed to the same page, which has two different functions. The first, when the page is initially presented, displays the fields shown in Figure 9. The second action occurs once the page is submittedâ€"passing the data back to the same page, but through a different path.

Figure 9 Labeling Projects
Figure 9Labeling Projects

      The first action receives the user input for the promotion level, the name of the project that will be labeled, and the new label that should be applied. The Submit button is disabled until these three values have been filled in or selected (see Figure 10).
      Once the page is submitted, the program enters the ASP code located at the top of the page (see Figure 11). The ASP code begins by checking REQUEST_METHOD, which is one of the standard Server variables. If REQUEST_METHOD contains the value POST, processing begins. Otherwise the HTML code following the ASP code is sent back to the browser. This is how the initial HTML code is displayed to the user. This check is performed with the following line of code:


If Request.ServerVariables("REQUEST_METHOD") = "POST" Then

      The next piece of code defines variables to hold the project name and the label, then fills both variables with the values passed by the user.


Dim strProjectName, strLabelName
strProjectName = "$/" & Request.Form("optLevel") & "/" & _
                 Request.Form("txtProjectName")
strLabelName = Request.Form("txtLabelName")

Once again, you need to open the database. This time you�ll use the credentials stored in the Session object. First you must create a SourceSafe object, then call its Open method, passing it the Visual SourceSafe INI path, the user name, and the password. When the ASP processing is complete, the client is redirected to the home page.

Promoting a Project

      Promoting a project is an involved process. First, the user must be prompted to gather the necessary information about the project to be promoted (see Figure 12). In addition to specifying the level for promoting the project, the user must also specify the project name and, optionally, the individual files that require promotion.

Figure 12 Promoting the Project
Figure 12Promoting the Project

      I designed the Promote.asp page as a self-submitting page with multiple entry paths. The first displays the initial page to the user. The initial page waits for the user to select the promotion level and the project name. The user then selects the Load button to retrieve the list of files or subprojects for the project. This is where the second entry path is taken; the list of files and subprojects is placed in the listbox located on the page, and the page is redisplayed in the browser.
      When the user finishes selecting the files and subprojects for promotion, she must press the Submit button, which remains disabled until the selection process has been completed. Upon submitting the data to the server, the third entry path is entered. At this point, the real meat of the processing begins.
      Back when the user pressed the Load button, I passed an extra parameter named Load to the page. I set this value to TRUE to let the ASP page know that it�s going into the page using the second entry path. I also passed the project name and promotion level. The following code demonstrates this functionality:


function btnLoad_onclick(frm) {
  var strLevel = getPromotionLevel();
  var strProjectName = frm.txtProjectName.value;
  var strUrl = window.location.pathname;
  strUrl += "?Load=TRUE&optLevel=" + strLevel + _
            "&txtProjectName=" + strProjectName;

  return window.navigate(strUrl);
}

Once the string has been assembled, I merge it with the path name of the current ASP file (Promote.asp) and pass the entire string to the window object�s navigate method.
      When the ASP code is executed on the server, the server variable REQUEST_METHOD is checked. If this variable contains Get, and the LOAD parameter contains TRUE, the portion of the code in the If block in Figure 13 is executed.
      The first thing this code needs to do is open the Visual SourceSafe database. This time I wrote two functions to handle opening and closing the database, OpenVSSObjects and CloseVSSObjects (see Figure 14).
      Instead of simply opening the Visual SourceSafe database object, I added code to open the VSSItem object as well. To open the item, I need a full path to the project. This path is essentially the source path, or the path of the project that is being promoted. When the actual promotion occurs, I�ll also need to construct the path to the destination. When the user is initially prompted for the information, they specify the promotion level. This level is used as the destination. From this level, you can easily determine the source level. Notice that I called a function named GetSrcLevel from within the OpenVSSObjects function in Figure 14. This function is coded as follows:


Function GetSrcLevel(strDestLevel)
  If strDestLevel = "1 Unit" Then
    GetSrcLevel = "0 Development"
  ElseIf strDestLevel = "2 Integration" Then
    GetSrcLevel = "1 Unit"
  ElseIf strDestLevel = "3 System" Then
    GetSrcLevel = "2 Integration"
  End If
End Function

The strSrcProjectName, strDstProjectName, objVSSDb, and objProjectItem variables are all globals.
      The point of all this code is to finally construct the list of options for the listbox. The list of files is retrieved from the item object, which was opened in the OpenVSSObjects function. Once this item is opened, the item can be traversed to retrieve any files or subfolders located within the item. Again, take a look at the code in Figure 13. There you�ll find a for each...next loop that controls the list of options and places the entire string in a global variable named strEligibleFiles.
      The strEligibleFiles variable is later used in the HTML code sent back to the browser. The first time through this page, the strEligibleFiles variable is empty. However, once the variable is filled, it is returned to the browser as HTML code.


<p>Eligible Files/Projects for promotions:<br>
   <select id="lbxEligibleFiles" multiple>
     <% = strEligibleFiles %>
   </select>
</p>

      When the promotion page is initially requested or the Load button is pressed, the ASP processing arrives at the following line of code:


If Request.ServerVariables("REQUEST_METHOD") = "GET" Then

The HTML code that follows it is sent back to the client browser. When the user presses the Load button, she is presented with a screen similar to the one in Figure 12. Notice how the listbox now contains items. Once the user selects the various items, she must then press the Submit button, which forces the server to enter the ASP page through the third entry path.
      Look through the code in Figure 13 until you reach this line:


ElseIf Request.ServerVariables("REQUEST_METHOD") = "POST" Then

The code that is executed within this block handles the work of promoting a project. Once again, the OpenVSSObjects function is called to open the Visual SourceSafe database and the project item. For the OpenVSSObjects function to open the project within the correct root folder, the optLevel variable is passed to it. After calling OpenVSSObjects, the PromoteProjectFiles function is called. Finally, the CloseVSSObjects function is called to close the Visual SourceSafe database object and the item object.
      When promoting a project, the PromoteProjectFiles function (see Figure 15) is where the fun begins. The objective in promoting a project is to take files or projects from a lower level and pin them at a certain higher level (or in a given parent folder, which is what the level value represents).
      First, you determine if all files in the specified project are being promoted or if only selected files are being promoted. This is accomplished by checking how many items in the listbox are selected. If the count is equal to zero, then a project name must have been passed, in which case you�re promoting every file or subproject within the specified project. If you�re promoting the whole project and everything within it, you check the type of the specified project item. You can check the type by accessing the Type property of the item object created in OpenVSSObjects against the constant value VSSITEM_PROJECT, which is a constant specified in the Visual SourceSafe type library. I set a reference to this library at the top of my global.asa file as follows:


<!--METADATA TYPE="TypeLib" NAME="Microsoft SourceSafe 6.0
Type Library" UUID="{783CD4E0-9D54-11CF-B8EE-00608CC9A71F}"
VERSION="5.1"-->

You�ll need to do this if you want to have access to the type library�s defined constants.
      If the item object is pointing to a project (or folder) instead of a file, control is passed to the PromoteProject function, and the item object and destination project name are passed to this function. However, if you�re simply pointing to a single file that needs to be promoted, then you�ll call the PromoteFile function, passing it the item object and destination project name.
      Before I look at PromoteProject and PromoteFile, let�s see what happens when files are selected in the listbox. A for...next loop is established to iterate each file or project selected in the listbox and process the files appropriately. Again, if the item happens to be a project, it is passed to PromoteProject; otherwise it is passed to PromoteFile.
       Figure 16 shows both PromoteProject and PromoteFile. The PromoteProject function just iterates through all of the items in the project and checks their type. If the item is a project, it is recursively passed to PromoteProject for further processing. If the item is a file, it is passed to PromoteFile.
      PromoteFile establishes a known label for the passed file in the source project path, and then calls yet another function to perform the pinning work. This function is appropriately named PinFile (see Figure 17).
      One problem I discovered is that pinning is not supported from within the Visual SourceSafe object model. However, you can call the Visual SourceSafe command-line executable directly and pass it parameters to perform the pinning. But how do you make a call to an executable file from your ASP file? Furthermore, you have to make sure that the ASP doesn�t perform any further work until pinning is complete, which means you have to wait for the process object to complete. That�s quite a lot for an ASP page to handle. The answer is to create an ActiveX® object that calls Visual SourceSafe, waits for the process object, and returns when pinning is complete.
      I created an ATL ActiveX object, which would sit within the same process and thread as my page. I kept it generic so I could use it for other projects in the future. From within the PinFile function, I create the ATL object by calling the CreateObject function and passing it the ProgID for my ATL object, ExecCmdSvr.ExecCmdObj. I then call ExecCmd, which returns only after pinning is complete or the pinning fails. I then destroy the ATL object and return. Similar functionality occurs in the UnpinFile.
      The unpromote functionality is practically identical to the promotion functionality, except that it works in reverse. I hope I�ve been able to illustrate the idea that although it takes some work to set up, a custom source control system will make life easier for you and members of your team.

For related articles see:
Visual SourceSafe 6.0 Automation


Background information:
Managing Projects in Visual SourceSafe
Inside Distributed COM (Microsoft Press, 1998) by Guy Eddon and Henry Eddon.


Ken Ramirez is a senior software engineer, consultant, author, and trainer who builds client/server and Web architectures. He is also president of Master-Mind Consulting Services Inc. Ken can be reached at kramirez@mastermind.com or https://www.mastermind.com.

From the May 2000 issue of MSDN Magazine.