Tuesday, October 31, 2006

How to handle paths with TFS Version Control object model

After I have been developing with TFS Version Control object model for quite a while, I have come across very helpful class. I wish I did that couple of months before, as it would have saved me quite a bit of time in writing them string parsing functions.
I am talking about VersionControlPath class. This is a static class located in Microsoft.TeamFoundation.VersionControl.Common assembly, and it contains ton of routines you might need when working with version control items.

To give you a small sampling:


// Returns folder name from item path ("$/Project/Folder" from "$/Project/Folder/File.txt")


public static string GetFolderName(string item)


// Returns project name from item path ("Project" from "$/Project/Folder/File.txt")


public static string GetTeamProjectName(string item)


// Check whether specified path conforms to Windows or TFS path syntax (basically contains / or \ delimiter)


public static bool IsServerItem(string path)


// Prepends path with root $ char if required


public static string PrependRootIfNeeded(string folder)


// Parses item path and returns folder and file item paths


public static void Parse(string item, out string parent, out string name)




There is a dearth of other methods in VersionControlPath. Most of them are self-explanatory named, but may be a bit tricky to work with. For example, IsValidPath method will return true both for "$/Project/Folder" and "/Project/Folder" paths.

I wish I could direct you to MSDN, but documentation there is pretty thin (to be diplomatic about it).

If you find any interesting gotchas in that class, I would be delighted to know. Drop me a line.

Tuesday, October 24, 2006

HasTrailingSlash in MSBuild scripts

There is useful undocumented function that may be used in MSBuild scripts conditions, called HasTrailingSlash. As its name implies, the function checks its only argument for trailing backward slash:

Sample updated at 01-Fev-2008 (recently somebody complained that while function works my old sample does not :):

<!-- Initial target will be always called first to verify properties -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
InitialTargets="VerifyInputParameters">
 
    <!-- Target verifies that the property is not empty (throws error) -->
    <!-- and has trailing slash (adds one if no slash provided)        -->
    <Target Name="VerifyInputParameters">

        <Error Condition="'$(ExternalPath)' == ''" Text="ExternalPath is empty" />

        <CreateProperty Condition="!HasTrailingSlash('$(ExternalPath)')" 
        Value="$(ExternalPath)\">

              <Output TaskParameter="Value" PropertyName="ExternalPath" />

        </CreateProperty>
    </Target>
    <!-- Here goes the rest of the project -->
</Project>


<PropertyGroup>


 <OutputPath Condition=" !HasTrailingSlash('$(OutputPath)') ">


  $(OutputPath)\


 </OutputPath>


</PropertyGroup>



The thing is, the function is used extensively in Microsoft system targets files (for example, in Microsoft.TeamFoundation.Build.targets file) and still does not appear in MSBuild documentation. Beats me...

See also new TFSBuild site for more details.

Monday, October 16, 2006

Getting associated work items for changeset

Lately we have been working at next version of our Team Foundation Sidekicks application (more specifically at labels-related Sidekick), and as part of the development it was required to retrieve all work items associated with changeset.
Initially, the following simple code was used:

Changeset changeset = server.GetChangeset(changesetId);


Once Changeset object is instantiated, its WorkItems property readily makes all associated work items available.

The problem was the method performance; so after some search I found Naren Datha's post solving the same task. The code there uses WorkItemStore and ILinking objects and looks much more complex (as compared to one liner we used before). Heck, it must work quicker (or so I thought)!

But after some benchmarks, it turned out that those two approaches have very similar performance. I did not perform exhaustive research, but the execution time was essentially the same (within 10% delta).

So my guess would be that both methods use same core queries; and as far as complexity goes we shall stay with our previous one liner. Wouldn't you?

Removing iteration hidden goodies

I have just found a new feature in TFS! That still amazes me how after a whole year I am involved with TFS, there are still hidden and unexplored places to go.

In short, I was going to remove iteration path I have created by mistake, and there TFS goes displaying the window shown below:



Frankly, I was not thinking about work items at the time as I knew the iteration path was without any items assigned, but TFS thinking about that on my part - that is all goodness. Sure, if I had some work items I would like to migrate them, and the thoughtful dialog displayed is not a bad way of doing it.

I guess the possible usage of the feature (besides deleting iterations created by mistake :) would be for moving work items in iterative development. For example, in one setup we frequently assign all strange low priority tasks to iteration "Backlog" in milestone; so it would be convenient to delete that backlog and move all leftover backlog work items to next milestone.

It would be interesting to see if someone out there is in fact using that feature.

Wednesday, October 11, 2006

Renaming Team Project

When you create new Team project, give some serious consideration to its name. The Team project cannot be renamed in TFS v1 (No comment about it - you may find some opinions in MSDN usergroups).

The rename operation seems so obvious to the folks that I thought it is worth to post about it. You may well imagine with what incredulity the absense of the feature is met when need to rename project arises (there you have some really colorful language :).

If you already named your project and looking at ways to rename it, you may use the following workaround (sort of workaround, because you won't really end up with renamed project with identical contents):
1) Create new project with desired name
2) Copy work items from old project to a new one (one-by-one, as there is no bulk copy option).
3) Move all source control folders from under old project folder to a new project folder
4) Sharepoint portal documents cannot be moved in bulk (as far as I know), so you do that manually
Move of source code will retain the files history, and work items will also have partial history, but overall I would say the workaround does not worth the labour (and Sharepoint docs will not have their history). At any rate, selecting right name in the beginning beats any workaround by far.

So be circumspect when you name your Team project!

Update: I stand corrected, as there exist freeware utility for moving work items between Team Projects (written by Eric Lee); see posts here and here.