Click here to Skip to main content
Click here to Skip to main content

TFS SDK: Compare Changesets programmatically

, 22 Aug 2011
Rate this:
Please Sign up or sign in to vote.
I will be covering three things in this blog post Get the history i.e. all change sets of an item programmatically using the TFS API. Download the change sets programmatically using the TFS API Use WinMerge to compare those change sets programmatically 1. How do i get the history o

I will be covering three things in this blog post

  • Get the history i.e. all change sets of an item programmatically using the TFS API.
  • Download the change sets programmatically using the TFS API
  • Use WinMerge to compare those change sets programmatically

1. How do I get the history of a file using TFS API?

The VersionControlServer Class exposes the QueryHistory method that gets you all changesets that have impacted a file or folder you are querying for.

public IEnumerable QueryHistory(
    // The local path to an item for which history will be queried. 
    // This parameter can include wildcards
    string path, 
    
    // The version of the item for which history will be queried.
    VersionSpec version, 
    
    // The unique deletion ID for the item, if it is deleted. Otherwise, specify 0
    int deletionId, 
    
    // A flag describing whether history will be recursively queried
    RecursionType recursion, 
    
    // The user for whom history will be queried. Specify null for any user
    string user, 
    
    // The earliest version for which history will be queried.
    // Specify null to begin with the first changeset
    VersionSpec versionFrom, 
    
    // The latest version for which history will be queried. 
    // Specify null to end with the latest changeset
    VersionSpec versionTo, 
    
    // The maximum number of history entries to return. 
    // Specify Int32.MaxValue to get all changes
    int maxCount, 
    
    // A flag that describes whether the individual item
    // changes will be included with the changesets. Otherwise,
    // only changeset metadata is included
    bool includeChanges, 
    
    // A flag that describes how history entries are searched.
    bool slotMode 
}

Example: Query the history of file TfsRepository.cs placed in the source control at ‘$/Temp_UK_1/Development/Prod/Source/TfsWorkspaceManager/TfsWorkspaceManager/TfsRepository.cs

    var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("https://tfs2010:8080/defaultcollection"));
    var vsStore = tfs.GetService<VersionControlServer>();

    var histories =
        vsStore.QueryHistory( //filepath
                    "$/Temp_UK_1/Development/Prod/Source/TfsWorkspaceManager/TfsWorkspaceManager/TfsRepository.cs",
                    VersionSpec.Latest, 0, RecursionType.OneLevel, null, null, null, Int32.MaxValue, true, false, true);
 
    foreach (Changeset history in histories)
    {
        // Break to see what values history has
    }

Histories is IEnumerable, as we enumerate we convert history to type changeset. Let’s see the results,

image

There are two overloads,

  • bool includeDownloadInfo: A flag that describes whether to get the information necessary to download the change sets from the server
  • bool sortAscending: A flag that describes whether to sort the results in ascending order. Specify false to not sort the results.

2. Download the files in the changeset programmatically

The Item Class exposes the DownloadFile Method that downloads the content for this version of the item.

Example: Download all changesets of the TfsRepository.cs file to Windows Temp folder.

public static void DownloadHistoryChangesetsToTempFolder()
{
    var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("https://tfs2010:8080/defaultcollection"));
    tfs.EnsureAuthenticated();
    var vsStore = tfs.GetService<VersionControlServer>();

    var histories =
           vsStore.QueryHistory( //filepath
                    "$/Temp_UK_1/Development/Prod/Source/TfsWorkspaceManager/TfsRepository.cs",
                    VersionSpec.Latest, 0, RecursionType.OneLevel, null, null, null, Int32.MaxValue, true, false, true);

    foreach (Changeset history in histories)
    {
       foreach (Change change in history.Changes)
       {
           change.Item.DownloadFile(System.IO.Path.GetTempPath() + change.Item.ChangesetId + 
                                      change.Item.ServerItem.Split('/')[change.Item.ServerItem.Split('/').Length - 1]);
       }
    }
}

Screen shot of the windows temp folder,

image

3. Compare the downloaded versions programmatically using WinMerge

Download and Install WinMerge. WinMerge is an Open Source differencing and merging tool for Windows. WinMerge can compare both folders and files, presenting differences in a visual text format that is easy to understand and handle. You can read more about how to change the default Compare and Merge tool in Team Foundation Sever in my earlier blog post here.

Example: Compare the earlier downloaded history versions of TfsRepository.cs from the windows temp folder

WinMerge command line access with a bunch of useful arguments. You can do WinMergeU.exe /? to get the details of the arguments.

WinMerge[U] [/r] [/e] [/f filter] [/x] [/s] [/ul] [/ur] [/u] [/wl] [/wr] [/minimize] [/maximize] [/dl leftdesc] [/dr rightdesc] leftpath rightpath [outputpath]

WinMerge[U] conflictfile

public static void CompareTwoChangeSets()
{
    var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("https://tfs2010:8080/defaultcollection"));
    tfs.EnsureAuthenticated();
    var vsStore = tfs.GetService<VersionControlServer>();

    var histories =
               vsStore.QueryHistory( //filepath
                   "$/Temp_UK_1/Development/Prod/Source/TfsWorkspaceManager/TfsWorkspaceManager/TfsWorkspaceManager/TfsRepository.cs",
                   VersionSpec.Latest, 0, RecursionType.OneLevel, null, null, null, Int32.MaxValue, true, false, true);

        foreach (Changeset history in histories)
        {
            foreach (Change change in history.Changes)
            {
                change.Item.DownloadFile(System.IO.Path.GetTempPath() +
                                            change.Item.ChangesetId +
                                            change.Item.ServerItem.Split('/')[
                                                change.Item.ServerItem.Split('/').Length - 1]);
        }
    }

    var winmerge = Process.Start(@"C:\Program Files (x86)\WinMerge\WinMergeU.exe",
                                        String.Format("{0}{1} {0}{2}", System.IO.Path.GetTempPath(),
                                                      @"\36TfsRepository.cs", @"\37TfsRepository.cs"));
}

So, I am starting a Process to consume the WinMergeU.exe and passing the 2 versions of the file that i want to compare. You can also use the following arguments,

  • /r compares all files in all subfolders (recursive compare). Unique folders (occurring only on one side) are listed in the compare result as separate items. Note that including subfolders can increase compare time significantly. Without this parameter, WinMerge lists only files and subfolders at the top level of the two target folders. It does not compare the subfolders.
  • /dl specifies a description in the left side title bar, overriding the default folder or filename text. For example: /dl "Version 1.0" or /dl WorkingCopy. Use quotation marks around descriptions that contain spaces.
  • /dr specifies a description in the right side title bar, just like /dl.

Screen Shot of execution of the above method,

image

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Tarun_Arora
Software Developer (Senior) Avanade
United Kingdom United Kingdom
Solution Developer - C# .NET, ALM
 
Tarun Arora is a Microsoft Certified professional developer for Enterprise Applications. He has over 5 years of experience developing 'Energy Trading & Risk Management' solutions using Microsoft Technologies. Tarun has great passion for technology and travel (not necessarily in the same order)!
Follow on   Twitter

Comments and Discussions

 
QuestionIs there a way retrieve all the source files from multiple changesets something like range which should basiclly start from desc order? PinmemberVenkat Chaitanya Kanumukula12-Jun-13 20:03 
QuestionAnother way to show compare Pinmember-=SerP=-5-Jun-13 21:52 
Show standart tfs dialog compare:
using Microsoft.TeamFoundation.VersionControl.Client;
 
... 
 
public void ShowDialogCompare(string dbFile, string tfsFile)
{
    var meth = typeof(Difference).GetMethod("RunExternalDiffTool", BindingFlags.Static | BindingFlags.NonPublic);
    if (meth == null)
        return;
 
    // string sourcePath, string targetPath, string sourceLabel, string targetLabel, string commandLineOptions, EventHandler exitedHandler, bool wait
    var args = new object[] { dbFile, tfsFile, "DB version", "TFS version", "", null, true };
    meth.Invoke(null, args);
}

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 22 Aug 2011
Article Copyright 2011 by Tarun_Arora
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid