How to extract a list of changesets
I had exactly this requirement in order to create patches for releases. I couldn't find anything in tfs or tfs power tools to do this, so I wrote my own.
To use, the syntax is a follows:
GetTfsChangeSet.exe TfsServerUrl changsetIdList fileOutputPath [merge]
where:
- TfsServerUrl: The TFS server Url
- changsetIdList : comma separated list of changesets
- fileOutputPath: Output path (does not need to be mapped)
- merge: With Merge param, combines all changesets into one folder. Without the param, each change set is output to a different folder.
e.g.
GetTfsChangeSet.exe http://asdpwiap017:8080/tfs 1233,4555,3332 c:\deploy merge
Create a console application solution.
Add these assembly references:
- Microsoft.TeamFoundation.Client
- Microsoft.TeamFoundation.Common
- Microsoft.TeamFoundation.VersionControl.Client
Program.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
namespace GetTfsChangeSet
{
class Program
{
static void Main(string[] args)
{
if (args.Length < 3)
{
Console.WriteLine("Usage:");
Console.WriteLine("GetTfsChangeSet.exe TfsServerUrl changsetIds fileOutputPath [merge]");
Console.WriteLine();
Console.WriteLine("where:");
Console.WriteLine("- changsetIdList : comma separated list of changesets");
Console.WriteLine("- merge: With Merge param, combines all changesets into one folder. Without the param, each change set is output to a different folder.");
Console.WriteLine();
Console.WriteLine("e.g.");
Console.WriteLine(@"GetTfsChangeSet.exe http://asdpwiap017:8080/tfs 1233,4555,3332 c:\deploy merge");
//Console.ReadKey();
return;
}
string teamProjectCollectionUrl = args[0]; // "http://asdpwiap017:8080/tfs";
var changesets = args[1].Split(',');
string outputDir = args[2];
bool mergeChangeSets = args.Length >= 4 && args[3].ToLower().Equals("merge");
if (mergeChangeSets)
{
Console.WriteLine("Merge changesets " + args[1]);
}
TfsTeamProjectCollection teamProjectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(teamProjectCollectionUrl));
string downloadPath = "";
if (mergeChangeSets)
{
downloadPath = args[1].Replace(',', '-');
if (downloadPath.Length > 30)
{
downloadPath = downloadPath.Substring(0, 15) + "..." + downloadPath.Substring(downloadPath.Length-15);
}
downloadPath = Path.Combine(outputDir, downloadPath);
}
foreach (var changesetStr in changesets.OrderBy(c=>c))
{
var changeset = Convert.ToInt32(changesetStr);
if (!mergeChangeSets)
{
downloadPath = Path.Combine(outputDir, changeset.ToString());
}
var files = GetFilesAssociatedWithBuild(teamProjectCollection, changeset, downloadPath);
Console.WriteLine(string.Format("ChangeSet {0}: {1} files extracted.", changeset, files.Count));
}
Console.WriteLine("Done.");
//Console.ReadKey();
}
private static List<string> GetFilesAssociatedWithBuild(TfsTeamProjectCollection teamProjectCollection, int changesetId, string downloadPath)
{
List<string> files = new List<string>();
VersionControlServer versionControlServer = teamProjectCollection.GetService(typeof(VersionControlServer)) as VersionControlServer;
Changeset changeset = versionControlServer.GetChangeset(changesetId);
if (changeset.Changes != null)
{
foreach (var changedItem in changeset.Changes)
{
var item = changedItem.Item;
if (item.ItemType != ItemType.File || item.DeletionId != 0)
continue;
var outFilename = Path.Combine(downloadPath, item.ServerItem.Replace("$/", "").Replace("/", @"\"));
item.DownloadFile(outFilename);
files.Add(outFilename);
}
}
return files;
}
}
}