Skip to content

Instantly share code, notes, and snippets.

@jclement
Created August 8, 2017 14:59
Show Gist options
  • Save jclement/1f9ba741c8bdcdffab5615477fb32791 to your computer and use it in GitHub Desktop.
Save jclement/1f9ba741c8bdcdffab5615477fb32791 to your computer and use it in GitHub Desktop.
Quick script to dump TFS check-in history to CSV for further analysis
/* ========= NUGET PACKAGES ==============================================================
Id Versions ProjectName
-- -------- -----------
CsvHelper {2.16.3.0} TFSHistoryDumper
Microsoft.AspNet.WebApi.Client {5.2.2} TFSHistoryDumper
Microsoft.AspNet.WebApi.Core {5.2.2} TFSHistoryDumper
Microsoft.IdentityModel.Clients.... {3.13.5} TFSHistoryDumper
Microsoft.TeamFoundation.Distrib... {15.112.1} TFSHistoryDumper
Microsoft.TeamFoundationServer.C... {15.112.1} TFSHistoryDumper
Microsoft.TeamFoundationServer.E... {15.112.1} TFSHistoryDumper
Microsoft.Tpl.Dataflow {4.5.24} TFSHistoryDumper
Microsoft.VisualStudio.Services.... {15.112.1} TFSHistoryDumper
Microsoft.VisualStudio.Services.... {15.112.1} TFSHistoryDumper
Newtonsoft.Json {8.0.3} TFSHistoryDumper
System.IdentityModel.Tokens.Jwt {4.0.2.206221351} TFSHistoryDumper
WindowsAzure.ServiceBus {3.3.2} TFSHistoryDumper
=========================================================================================== */
using CsvHelper;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.VersionControl.Client;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TFSHistoryDumper
{
class Program
{
static void Main(string[] args)
{
var tfsUri = new Uri("http://server:8080/tfs");
var tfsProjectCollectionName = "server\\project_collection";
var tfsProjectName = "project";
var tfsConfigurationServer = TfsConfigurationServerFactory.GetConfigurationServer(tfsUri);
var collectionNodes = tfsConfigurationServer.CatalogNode.QueryChildren(new[] { CatalogResourceTypes.ProjectCollection }, false, CatalogQueryOptions.None);
using (var textWriter = File.CreateText("C:\\temp\\changes.csv"))
{
var csv = new CsvWriter(textWriter);
foreach (var catalogNode in collectionNodes)
{
var collectionId = new Guid(catalogNode.Resource.Properties["InstanceId"]);
var teamProjectCollection = tfsConfigurationServer.GetTeamProjectCollection(collectionId);
teamProjectCollection.Authenticate();
Console.WriteLine($"{collectionId} - {teamProjectCollection.Name}");
if (teamProjectCollection.Name == tfsProjectCollectionName)
{
var versionControl = teamProjectCollection.GetService<VersionControlServer>();
var tp = versionControl.GetTeamProject(tfsProjectName);
var path = tp.ServerItem;
var q = versionControl.QueryHistory(path, VersionSpec.Latest, 0, RecursionType.Full, null, new ChangesetVersionSpec(1), VersionSpec.Latest, Int32.MaxValue, true, true, false, false);
foreach (Changeset cs in q)
{
foreach (var c in cs.Changes)
{
csv.WriteField(cs.CreationDate);
csv.WriteField(cs.Owner);
csv.WriteField(cs.OwnerDisplayName);
csv.WriteField(cs.Comment);
csv.WriteField(cs.ChangesetId);
csv.WriteField(c.ChangeType);
csv.WriteField(c.Item.ServerItem);
csv.WriteField(String.Join(",", cs.AssociatedWorkItems.Select(x=>x.Id)));
csv.NextRecord();
}
Console.WriteLine($"${cs.CreationDate} - ${cs.ChangesetId} - ${cs.Owner} - ${cs.Comment}");
}
}
}
}
Console.WriteLine("Completed");
Console.ReadKey();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment