19

I need to programmatically find out information about branches in TFS. For instance the main thing i am interested is given root folder $/MyProject/Project1 I neeed to find out what other folders have been branched from it. I am just after the right API methods.

Say i have connection to TFS server and have access to VersionControlServer and Workspace class instances.

Captain Comic
  • 15,744
  • 43
  • 110
  • 148

2 Answers2

22

Ok, this was both easier and more difficult than I thought it would be. I was able to pull this together from a few different sources, but this seems to work. I will warn you, there's no error handling here, and if the itemSpec doesn't exist, it bombs with an exception.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;

static void Main(string[] args)
{
    TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(
                                            new Uri("http://tfs:8080"));    
    string srcFolder = "$/ProjectName";    
    var versionControl = tfs.GetService<VersionControlServer>();    
    ItemSpec[] specs = new ItemSpec[]{new ItemSpec(srcFolder, RecursionType.None)};

    System.Console.WriteLine(string.Format("Source folder {0} was branched to:",
                                           srcFolder));    
    BranchHistoryTreeItem[][] branchHistory =
        versionControl.GetBranchHistory(specs, VersionSpec.Latest);

    foreach (BranchHistoryTreeItem item in branchHistory[0][0].Children)
    {
        ShowChildren(item);
    } 

    System.Console.WriteLine();
    System.Console.WriteLine("Hit Enter to continue");
    System.Console.ReadLine();    
}

static void ShowChildren(BranchHistoryTreeItem parent)
{
    foreach (BranchHistoryTreeItem item in parent.Children)
    {
        System.Console.WriteLine(
            string.Format("Branched to {0}", 
                          item.Relative.BranchToItem.ServerItem));
        if (item.Children.Count > 0)
        {
            foreach(BranchHistoryTreeItem child in item.Children)
            {
                ShowChildren(child);
            }                       
        }
    }
}
John Saunders
  • 160,644
  • 26
  • 247
  • 397
Robaticus
  • 22,857
  • 5
  • 54
  • 63
  • Please note that in the ShowChildren you also need to show the relative items of the parent. So add this above the Foreach loop. System.Console.WriteLine( string.Format("Branched to {0}", parent.Relative.BranchToItem.ServerItem)); – Craig B Apr 23 '20 at 03:22
2

The code in the primary answer does not always return all target branches. In my testing, it returned one fewer branch than did the Visual Studio merge dialog box.

There is a simpler and safer way to get the list of target branches. This is the same way that Visual Studio obtains the list for the Merge dialog box:

using System;
using System.Collections.Generic;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;

class Program
{
    static void Main(string[] args)
    {
        string tfsUri = "http://tfs:8080/tfs/MyCollection";
        string tfsItemSpec = "$/MyTeamProject/Folder";

        List<string> branches = GetPathsEligibleForMerge(tfsUri, tfsItemSpec);

        foreach (string branch in branches)
        {
            Console.WriteLine(branch);
        }
    }

    public static List<string> GetPathsEligibleForMerge(
        string tfsUri, string tfsBranchPath)
    {
        List<string> tfsEligibleMergePaths = new List<string>();

        using (TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(new Uri(tfsUri)))
        {
            VersionControlServer vcs =
                (VersionControlServer)tfs.GetService(typeof(VersionControlServer));

            foreach (ItemIdentifier mergeItem in vcs.QueryMergeRelationships(tfsBranchPath))
            {
                if (!mergeItem.IsDeleted && !string.IsNullOrWhiteSpace(mergeItem.Item))
                {
                    tfsEligibleMergePaths.Add(mergeItem.Item);
                }
            }
        }

        tfsEligibleMergePaths.Sort(StringComparer.OrdinalIgnoreCase);

        return tfsEligibleMergePaths;
    }
}

This code always returns the same list as the Merge dialog box.

Thomas F. Abraham
  • 2,082
  • 1
  • 19
  • 24
  • I might be missing something here but it seems that QueryMergeRelationships returns a list of items where there is any relationship at all, including a parent relationship, contrary to your variable naming; your code assumes that you are using the root branch, and will then provide a list of all children because it is the root. But if you pass in a child branch, it will also return the parent branch, which would not meet the requirements of Captain Comic's question, "I need to find out what other folders have been branched from it", which implicitly means only the child branches are required. – paulyphonic Apr 19 '14 at 20:25
  • True. I modified the variables and method name. There may be a way in the API to identify which path is a parent and exclude it. – Thomas F. Abraham Apr 28 '14 at 04:14