Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save grenade/d118ddad899fee947cc0 to your computer and use it in GitHub Desktop.
Save grenade/d118ddad899fee947cc0 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
namespace AuthorFileGenerator
{
/// <summary>
/// The entry point for the console application.
/// </summary>
public static class Program
{
/// <summary>
/// Execute the author file generator.
/// </summary>
public static void Main()
{
new AuthorGenerator().Scan("http://tfs:8080/tfs");
}
}
/// <summary>
/// Generates a git-tfs author mapping for all users found on a TFS server.
/// </summary>
/// <remarks>
/// This script is used to generate a git-tfs author mapping for migrating from TFS to git. It
/// will generate a list like the following:
/// <code>
/// DOMAIN\john.smith = John Smith &lt;[email protected]&gt;
/// DOMAIN\roni.scheutz = Roni Scheutz &lt;[email protected]&gt;
/// DOMAIN\shanel.jones = Shanel Jones &lt;[email protected]&gt;
/// </code>
/// See https://github.com/git-tfs/git-tfs/wiki/Clone. This is based on a code sample
/// by Roni Scheutz @ http://netrsc.blogspot.ca/2010/07/retrieve-list-with-all-your-tfs-users.html.
/// </remarks>
public class AuthorGenerator
{
/// <summary>
/// Connect to a TFS server and generate a git-tfs author file for all users found.
/// </summary>
/// <param name="url">The root TFS URL, like "http://team:8080/tfs".</param>
public void Scan(string url)
{
// scan for TFS users
var identities = new List<Identity>();
var server = GetServer(url, CredentialCache.DefaultCredentials);
Console.WriteLine("Scanning TFS for users...");
foreach (var collection in GetProjectCollections(server))
{
Console.WriteLine(" collection: {0}", collection.Name);
foreach (var project in GetProjects(collection))
{
Console.WriteLine(" project: {0}", project.Name);
try
{
identities.AddRange(GetUsers(project, collection));
}
catch (Exception ex)
{
Console.WriteLine("\tThe Project: '{0}' throws an exception: {1} and will be ignored.", project.Name, ex.Message);
}
}
}
// get unique users
var users = identities
.GroupBy(x => x.DistinguishedName)
.Select(x => x.First())
.OrderBy(x => string.Concat(x.Domain, x.AccountName));
// display list
Console.Write("\n\nDetected users\n--------------\n");
foreach (var user in users)
Console.WriteLine(@"{0}\{1} = {2} <{3}>", user.Domain, user.AccountName, user.DisplayName, user.MailAddress);
}
/*********
** Protected methods
*********/
/// <summary>Get the TFS configuration server.</summary>
/// <param name="url">The root TFS URL, like "http://team:8080/tfs".</param>
/// <param name="credentials">The TFS credentials with which to access the server.</param>
protected TfsConfigurationServer GetServer(string url, ICredentials credentials)
{
// get server
var server = new TfsConfigurationServer(new Uri(url), credentials, new UICredentialsProvider());
// authenticate
server.EnsureAuthenticated();
server.Authenticate();
if (!server.HasAuthenticated)
throw new InvalidOperationException("Authentication to TFS failed.");
return server;
}
/// <summary>Get the TFS project collections.</summary>
/// <param name="server">The TFS server from which to read the project collections.</param>
protected IEnumerable<TfsTeamProjectCollection> GetProjectCollections(TfsConfigurationServer server)
{
ReadOnlyCollection<CatalogNode> projectNodes = server.CatalogNode.QueryChildren(new[] { CatalogResourceTypes.ProjectCollection }, false, CatalogQueryOptions.None);
return projectNodes.Select(projectNode => server.GetTeamProjectCollection(new Guid(projectNode.Resource.Properties["InstanceId"])));
}
/// <summary>Get the TFS projects in a collection.</summary>
/// <param name="collection">The TFS project collection.</param>
protected IEnumerable<Project> GetProjects(TfsTeamProjectCollection collection)
{
var workItemStore = collection.GetService<WorkItemStore>();
return workItemStore.Projects.Cast<Project>();
}
/// <summary>Get the users in a TFS project.</summary>
/// <param name="project">The TFS project.</param>
/// <param name="collection">The TFS project collection.</param>
protected IEnumerable<Identity> GetUsers(Project project, TfsTeamProjectCollection collection)
{
// get identity service
var versionControl = collection.GetService<VersionControlServer>();
var teamProject = versionControl.GetTeamProject(project.Name);
var securityService = collection.GetService<IGroupSecurityService>();
return securityService.ListApplicationGroups(teamProject.ArtifactUri.AbsoluteUri).SelectMany(g => securityService.ReadIdentities(SearchFactor.Sid, new[] { g.Sid }, QueryMembership.Expanded).Where(x => x.Members != null).SelectMany(x => x.Members.Select(sid => securityService.ReadIdentity(SearchFactor.Sid, sid, QueryMembership.None)).Where(id => id.Type == IdentityType.WindowsUser)));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment