Instantly share code, notes, and snippets.
Forked from Pathoschild/generate-git-tfs-author-file.cs
Last active
August 29, 2015 14:01
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save grenade/d118ddad899fee947cc0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 <[email protected]> | |
/// DOMAIN\roni.scheutz = Roni Scheutz <[email protected]> | |
/// DOMAIN\shanel.jones = Shanel Jones <[email protected]> | |
/// </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