Sunday, March 18, 2007

At work we currently use Serena Version Manager and Tracker products (PVCS) for our source control and issue tracking. As previously (albeit briefly) mentioned, we are in the process of converting to Team System. Ultimately we decided to start the source control repository clean instead of importing our source trees from Version Manager. I did some exploratory work on figuring out how to do an import, and although it's not fully fleshed out, I'd like to throw my findings out there in the hopes this will help someone.

Okay, now to my (rough) approach. The first goal was to retrieve all version history from VM. After many fruitless online searches I eventually found what I needed, a command line utility which provides an interface to VM. This utility is pcli.exe, which I found in C:\Program Files\PVCS\win32\bin, but obviously your installation will differ. I had trouble finding documentation online for this program, however if you type "pcli -h" you will see a list of commands. You can type "pcli command -h" to get assistance on options for a particular command.

I used this utility to retrieve a list of all files within a particular folder (and all its subfolders) including all revision information for each file. I ran the following command to retrieve this list: pcli.exe vlog -z -idUSERNAME:PASSWORD -fOUTPUT.TXT -pr"PROJECT NAME" PATH_IN_VM

The "vlog" command reports archive/revision information. If you type "pcli vlog -h" you can see a full list of options. Several things to note about the command line I used. The "-z" argument recursively processes the path. Username and password are separated by a single colon. The project name should be in the form \\NAME with no trailing backslash. The PATH_IN_VM, however, must use forward slashes, with a forward slash starting the path and no trailing slash. I believe I tried different combinations and settled on these - other combinations might work, but I know for a fact that these will.

If you execute this on a VM project you should have an OUTPUT.TXT that contains information such as what follows next. I'll first show example contents and then discuss how to parse it and use the information. Before discussing this file, I should again caution that I barely scratched the surface of parsing this file. My focus was narrow, simply only needing each revision number of a particular file and some extra information such as author, check in comments, etc. Okay, here's a sample OUTPUT.TXT

Archive:          \\SampleProject\archives\Dev\Web\PrototypeSite\Default.aspx-arc
Workfile:         Default.aspx
Archive created:  Oct 10 2006 13:37:44
Split mode:       Split
\\SampleProject\archives\Dev\Web\PrototypeSite\Default.aspx-arc
Owner:            jeff
Last trunk rev:   1.2
Locks:           
Groups:          
Rev count:        3
Attributes:
   WRITEPROTECT
   CHECKLOCK
   NOEXCLUSIVELOCK
   EXPANDKEYWORDS
   NOTRANSLATE
   NOCOMPRESSDELTA
   NOCOMPRESSWORKIMAGE
   GENERATEDELTA
   COMMENTPREFIX = ""
   NEWLINE = "\r\n"
Version labels:
   "Baseline 1.0" = 1.2
   "SCR-1" = 1.2
Description:
Baseline 1.0

-----------------------------------
Rev 1.2
Checked in:     Oct 11 2006 11:53:04
Last modified:  Oct 11 2006 11:52:14
Author id: jeff     lines deleted/added/moved: 6/6/0
added custom httpmodule
Resolution for 1: baseline
-----------------------------------
Rev 1.1
Checked in:     Oct 10 2006 17:43:24
Last modified:  Oct 10 2006 17:40:46
Author id: jeff     lines deleted/added/moved: 0/7/0
added login screen
Resolution for 1: baseline
-----------------------------------
Rev 1.0
Checked in:     Oct 10 2006 13:37:44
Last modified:  Sep 27 2006 16:48:04
Author id: jeff     lines deleted/added/moved: 0/0/0
creation of web project
===================================

The first line of the file (and first line of text after any line containing only equal signs, ====) provides the full path to the file, however you need to strip the -arc at the end and also take out the archives\ directory. Since we want revision information, the next step is to skip ahead to the first line of dashes. After each dashed line we can read the revision number that appears after "Rev". In my parser I also parsed out check-in date, author ID, etc., but we only need revision numbers to retrieve a particular revision from VM. Also note that revisions are listed in reverse check-in order, so the latest revision comes first. When reading the revision information, either place this into a Stack (which you can then convert to an array via ToArray(), which will then be in the order you want) or process a List in reverse order. Again, each file is separated by a line of equal signs, so when you hit this line you know to stop processing the current file.

Now that we have all files in our repository and all revision information for each file, we have to construct a call to PCLI to retrieve a particular revision. This is the part that is ridiculously slow and sets off my internal alarms that scream THERE IS A BETTER WAY TO DO THIS! I just didn't dig in deep enough to find out the better way and I couldn't be bothered to do so now.

The command to retrieve a particular revision of a file is: pcli.exe run -y -ns get -id USERNAME:PASSWORD -o -a"c:\local\path\here" -wREV# -pr"PROJECTNAME" PATHNAME

"run" is the command, which we use to execute a specific PCLI command which, in this case, is "get"

The -y and -ns options stand alone, -y specifying that all prompts should be answered "yes" (I ran this from a C# program and did not want any user interaction) and -ns prevents extra stripping of quotes from command line.

The -id option is used again to specify credentials.

The -o option is used to override work file location so we can pull the file down to a directory of our choosing without needing to deal with work file locations.

The -a option is used to specify where the retrieved file should go.

The -w option specifies which revision number we want, such as -w1.0

The -pr option is used to specify the project and should be in the same format as our previous invocation of PCLI, for example, \\SampleProject

Now we have all the pieces to get a full list of files/revision history from VM and automatically retrieve a particular revision of a file. You can write a program to automatically invoke PCLI to create the revision history file, parse that file and pull down revisions one by one. I would suggest first processing all 1.0 revisions of all files within a particular root folder and then using Team Foundation Server's source control API to add these files. Then process all 1.1 revisions, checking these into Team Foundation server. And so on... Along with your check ins to TFS you can include original information such as author ID, check in comments, check in date, etc., so you can maintain a reasonable degree of information, hopefully alleviating the need to keep VM around for historical purposes. I'm leaving out details of the TFS source control API since it is documented well in many other places, but if you would like some suggestions or help, please leave a comment.

I'm almost ashamed to document such a clunky method of export/import, but without devoting significantly more time to exploring PCLI and various VM interfaces, this method was the best I found that I knew would work. There are (at least) two ways to improve on what I discussed, but I did not figure out how to do either. First, I believe there is a way to do batch operations with PCLI so you don't need to pull down a single revision at a time. Second, I came across a client API, but did not readily see how to do authentication so I was not sure how to properly connect to a repository and perform the calls needed.

I really hope this helps someone out there :)

Sunday, March 18, 2007 5:46:23 PM (Eastern Standard Time, UTC-05:00)  #    Comments [1]  |  Trackback
Thursday, October 26, 2006

Just because your assemblies are GAC'ed does not mean that they automatically appear in the .NET tab of "Add Reference" in Visual Studio 2003/2005. You can make your assemblies appear here by a registry tweak. First, decide which directory you want to store your assemblies. For example, say your projects copy the built assemblies to d:\build\output

Open the registry editor and navigate to the key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\AssemblyFolders

Create a new key beneath AssemblyFolders. The name is arbitrary, so give it a name that applies to the assemblies in the directory, perhaps "INITECH UI 1.0" Next, single click this new key, and in the right pane you'll see (Default) with no value. Set the default value to your directory, d:\build\output

Here's a screenshot of what this looks like for the already-present "SQL Server Assemblies" on my machine.

Also note that this can be set on a per-user basis by performing the same action in the HKCU hive, specifically HKEY_CURRENT_USER\SOFTWARE\Microsoft\.NETFramework\AssemblyFolders

If you want multiple directories, create multiple keys.

[Add standard registry disclaimer here] Back up your registry before making changes if you're not used to editing the registry directly.

Thursday, October 26, 2006 10:42:08 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  |  Trackback