Merge pull request #336 from l3m/correct-authors

Correct author attribution
This commit is contained in:
Matt Burke
2013-04-12 06:31:01 -07:00
15 changed files with 318 additions and 28 deletions
+5 -2
View File
@@ -6,7 +6,7 @@ namespace Sep.Git.Tfs.VsCommon
{
public partial class WrapperForWorkspace
{
public int Checkin(IPendingChange[] changes, string comment, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges,
public int Checkin(IPendingChange[] changes, string comment, string author, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges,
TfsPolicyOverrideInfo policyOverrideInfo, bool overrideGatedCheckIn)
{
var checkinParameters = new WorkspaceCheckInParameters(_bridge.Unwrap<PendingChange>(changes), comment)
@@ -14,9 +14,12 @@ namespace Sep.Git.Tfs.VsCommon
CheckinNotes = _bridge.Unwrap<CheckinNote>(checkinNote),
AssociatedWorkItems = _bridge.Unwrap<WorkItemCheckinInfo>(workItemChanges),
PolicyOverride = ToTfs(policyOverrideInfo),
OverrideGatedCheckIn = overrideGatedCheckIn
OverrideGatedCheckIn = overrideGatedCheckIn,
};
if (author != null)
checkinParameters.Author = author;
return _workspace.CheckIn(checkinParameters);
}
}
+14 -1
View File
@@ -6,9 +6,20 @@ namespace Sep.Git.Tfs.VsCommon
{
public partial class WrapperForWorkspace
{
public int Checkin(IPendingChange[] changes, string comment, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges,
public int Checkin(IPendingChange[] changes, string comment, string author, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges,
TfsPolicyOverrideInfo policyOverrideInfo, bool overrideGatedCheckIn)
{
if (author != null)
{
return _workspace.CheckIn(
_bridge.Unwrap<PendingChange>(changes),
comment,
author,
_bridge.Unwrap<CheckinNote>(checkinNote),
_bridge.Unwrap<WorkItemCheckinInfo>(workItemChanges),
ToTfs(policyOverrideInfo));
}
return _workspace.CheckIn(
_bridge.Unwrap<PendingChange>(changes),
comment,
@@ -16,5 +27,7 @@ namespace Sep.Git.Tfs.VsCommon
_bridge.Unwrap<WorkItemCheckinInfo>(workItemChanges),
ToTfs(policyOverrideInfo));
}
}
}
+7 -2
View File
@@ -6,8 +6,8 @@ namespace Sep.Git.Tfs.VsCommon
{
public partial class WrapperForWorkspace
{
public int Checkin(IPendingChange[] changes, string comment, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges,
TfsPolicyOverrideInfo policyOverrideInfo, bool overrideGatedCheckIn)
public int Checkin(IPendingChange[] changes, string comment, string author, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges,
TfsPolicyOverrideInfo policyOverrideInfo, bool overrideGatedCheckIn)
{
var checkinParameters = new WorkspaceCheckInParameters(_bridge.Unwrap<PendingChange>(changes), comment)
{
@@ -17,7 +17,12 @@ namespace Sep.Git.Tfs.VsCommon
OverrideGatedCheckIn = overrideGatedCheckIn
};
if (author != null)
checkinParameters.Author = author;
return _workspace.CheckIn(checkinParameters);
}
}
}
+2 -1
View File
@@ -416,8 +416,9 @@ namespace Sep.Git.Tfs.VsCommon
_bridge.Unwrap<PolicyFailure>(policyOverrideInfo.Failures));
}
public ICheckinEvaluationResult EvaluateCheckin(TfsCheckinEvaluationOptions options, IPendingChange[] allChanges, IPendingChange[] changes,
string comment, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges)
string comment, string author, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges)
{
return _bridge.Wrap<WrapperForCheckinEvaluationResult, CheckinEvaluationResult>(_workspace.EvaluateCheckin(
_bridge.Convert<CheckinEvaluationOptions>(options),
+6 -1
View File
@@ -238,12 +238,17 @@ namespace Sep.Git.Tfs.VsFake
throw new NotImplementedException();
}
public ICheckinEvaluationResult EvaluateCheckin(TfsCheckinEvaluationOptions options, IPendingChange[] allChanges, IPendingChange[] changes, string comment, string authors, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges)
{
throw new NotImplementedException();
}
public void Shelve(IShelveset shelveset, IPendingChange[] changes, TfsShelvingOptions options)
{
throw new NotImplementedException();
}
public int Checkin(IPendingChange[] changes, string comment, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges, TfsPolicyOverrideInfo policyOverrideInfo, bool overrideGatedCheckIn)
public int Checkin(IPendingChange[] changes, string comment, string author, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges, TfsPolicyOverrideInfo policyOverrideInfo, bool overrideGatedCheckIn)
{
throw new NotImplementedException();
}
+6 -1
View File
@@ -34,13 +34,14 @@ namespace Sep.Git.Tfs.Commands
(reviewer) => { CheckinNotes["Performance Reviewer"] = reviewer; } },
{ "no-gate", "Disables gated checkin.",
v => { OverrideGatedCheckIn = true; } },
{ "A|authors=", "Path to an Authors file to map TFS users to Git users", v => AuthorsFilePath = v },
};
}
}
private List<string> _workItemsToAssociate = new List<string>();
private List<string> _workItemsToResolve = new List<string>();
private Dictionary<string, string> _checkinNotes = new Dictionary<string,string>();
private Dictionary<string, string> _checkinNotes = new Dictionary<string, string>();
public string CheckinComment { get; set; }
// This can be extended to checkin when the $EDITOR is invoked.
@@ -52,5 +53,9 @@ namespace Sep.Git.Tfs.Commands
public List<string> WorkItemsToAssociate { get { return _workItemsToAssociate; } }
public List<string> WorkItemsToResolve { get { return _workItemsToResolve; } }
public Dictionary<string, string> CheckinNotes { get { return _checkinNotes; } }
public string AuthorsFilePath { get; set; }
public string AuthorTfsUserId { get; set; }
}
}
+5 -1
View File
@@ -158,7 +158,11 @@ namespace Sep.Git.Tfs.Commands
string commitMessage = _checkinOptions.NoGenerateCheckinComment
? repo.GetCommitMessage(target)
: repo.GetCommitMessage(target, tfsLatest);
var commitSpecificCheckinOptions = _checkinOptionsFactory.BuildCommitSpecificCheckinOptions(_checkinOptions, commitMessage);
GitCommit commit = repo.GetCommit(target);
var commitSpecificCheckinOptions = _checkinOptionsFactory.BuildCommitSpecificCheckinOptions(_checkinOptions, commitMessage, commit);
_stdout.WriteLine("Starting checkin of {0} '{1}'", target.Substring(0, 8), commitSpecificCheckinOptions.CheckinComment);
long newChangesetId = tfsRemote.Checkin(target, parentChangeset, commitSpecificCheckinOptions);
tfsRemote.FetchWithMerge(newChangesetId, gitParents);
+1 -1
View File
@@ -9,7 +9,7 @@ namespace Sep.Git.Tfs.Core
public CheckinPolicyEvaluationResult EvaluateCheckin(IWorkspace workspace, IPendingChange[] pendingChanges, string comment, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemInfo)
{
var result = workspace.EvaluateCheckin(TfsCheckinEvaluationOptions.All, pendingChanges,
pendingChanges, comment, checkinNote,
pendingChanges, comment, null, checkinNote,
workItemInfo);
return new CheckinPolicyEvaluationResult(result);
}
+12 -2
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using LibGit2Sharp;
@@ -37,5 +38,14 @@ namespace Sep.Git.Tfs.Core
}
}
}
public Tuple<string,string> AuthorAndEmail
{
get
{
return new Tuple<string,string>(_commit.Author.Name, _commit.Author.Email);
}
}
}
}
}
+2 -2
View File
@@ -5,9 +5,9 @@ namespace Sep.Git.Tfs.Core.TfsInterop
public interface IWorkspace
{
IPendingChange[] GetPendingChanges();
ICheckinEvaluationResult EvaluateCheckin(TfsCheckinEvaluationOptions options, IPendingChange[] allChanges, IPendingChange[] changes, string comment, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges);
ICheckinEvaluationResult EvaluateCheckin(TfsCheckinEvaluationOptions options, IPendingChange[] allChanges, IPendingChange[] changes, string comment, string author, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges);
void Shelve(IShelveset shelveset, IPendingChange[] changes, TfsShelvingOptions options);
int Checkin(IPendingChange[] changes, string comment, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges, TfsPolicyOverrideInfo policyOverrideInfo, bool overrideGatedCheckIn);
int Checkin(IPendingChange[] changes, string comment, string author, ICheckinNote checkinNote, IEnumerable<IWorkItemCheckinInfo> workItemChanges, TfsPolicyOverrideInfo policyOverrideInfo, bool overrideGatedCheckIn);
int PendAdd(string path);
int PendEdit(string path);
int PendDelete(string path);
+1 -1
View File
@@ -104,7 +104,7 @@ namespace Sep.Git.Tfs.Core
}
var policyOverride = GetPolicyOverrides(options, checkinProblems.Result);
var newChangeset = _workspace.Checkin(pendingChanges, options.CheckinComment, checkinNote, workItemInfos, policyOverride, options.OverrideGatedCheckIn);
var newChangeset = _workspace.Checkin(pendingChanges, options.CheckinComment, options.AuthorTfsUserId, checkinNote, workItemInfos, policyOverride, options.OverrideGatedCheckIn);
if (newChangeset == 0)
{
throw new GitTfsException("Checkin failed!");
+87 -10
View File
@@ -9,27 +9,96 @@ namespace Sep.Git.Tfs.Util
{
public class Author
{
public string Name;
public string Email;
public Author(string tfsUserId, string name, string email)
{
TfsUserId = tfsUserId;
_gitAuthor = new Tuple<string, string>(name, email);
_gitUserId = BuildGitUserId(_gitAuthor);
}
public string Name
{
get
{
return _gitAuthor.Item1;
}
}
public string Email
{
get
{
return _gitAuthor.Item2;
}
}
public string TfsUserId { get; set; }
public string GitUserId
{
get
{
return _gitUserId;
}
}
// we only use the trimmed email address as identity
// (dictionary key) to avoid mismatches because of
// active directory name formatting rules.
public static string BuildGitUserId(string email)
{
return email.Trim();
}
public static string BuildGitUserId(Tuple<string,string> gitUser)
{
return BuildGitUserId(gitUser.Item2);
}
#region (private)
private Tuple<string, string> _gitAuthor;
private string _gitUserId;
#endregion
}
[StructureMapSingleton]
public class AuthorsFile
{
private readonly Dictionary<string, Author> authors = new Dictionary<string, Author>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, Author> _authorsByTfsUserId = new Dictionary<string, Author>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, Author> _authorsByGitUserId = new Dictionary<string, Author>(StringComparer.OrdinalIgnoreCase);
public AuthorsFile()
{ }
{}
public Dictionary<string, Author> Authors
{
get
{
return this.authors;
return this._authorsByTfsUserId;
}
}
public Dictionary<string, Author> AuthorsByGitUserId
{
get
{
return this._authorsByGitUserId;
}
}
public Author FindAuthor(Tuple<string,string> gitUser)
{
string key = Author.BuildGitUserId(gitUser);
Author a;
return _authorsByGitUserId.TryGetValue(key, out a) ? a : null;
}
// The first time a tfs user id or a git id is encountered, it is used as lookup key.
public void Parse(TextReader authorsFileStream)
{
if (authorsFileStream != null)
@@ -50,11 +119,19 @@ namespace Sep.Git.Tfs.Util
}
else
{
if (!authors.ContainsKey(match.Groups[1].Value))
{
//git svn doesn't trim, but maybe this should?
authors.Add(match.Groups[1].Value, new Author() { Name = match.Groups[2].Value, Email = match.Groups[3].Value });
}
//git svn doesn't trim, but maybe this should?
string tfsUserId = match.Groups[1].Value;//.Trim();
string name = match.Groups[2].Value;//.Trim();
string email = match.Groups[3].Value;//.Trim();
Author a = new Author(tfsUserId, name, email);
if (!_authorsByTfsUserId.ContainsKey(a.TfsUserId))
_authorsByTfsUserId.Add(a.TfsUserId, a);
if (!_authorsByGitUserId.ContainsKey(a.GitUserId))
_authorsByGitUserId.Add(a.GitUserId, a);
}
}
line = authorsFileStream.ReadLine();
@@ -1,7 +1,9 @@
using System;
using System.IO;
using Sep.Git.Tfs.Commands;
using Sep.Git.Tfs.Core;
using System.Text.RegularExpressions;
using StructureMap;
namespace Sep.Git.Tfs.Util
{
@@ -38,6 +40,23 @@ namespace Sep.Git.Tfs.Util
return customCheckinOptions;
}
public CheckinOptions BuildCommitSpecificCheckinOptions(CheckinOptions sourceCheckinOptions, string commitMessage, GitCommit commit)
{
var customCheckinOptions = Clone(sourceCheckinOptions);
customCheckinOptions.CheckinComment = commitMessage;
ProcessWorkItemCommands(customCheckinOptions, writer);
ProcessCheckinNoteCommands(customCheckinOptions, writer);
ProcessForceCommand(customCheckinOptions, writer);
ProcessAuthor(customCheckinOptions, writer, commit);
return customCheckinOptions;
}
private CheckinOptions Clone(CheckinOptions source)
{
CheckinOptions clone = new CheckinOptions();
@@ -50,6 +69,8 @@ namespace Sep.Git.Tfs.Util
clone.OverrideGatedCheckIn = source.OverrideGatedCheckIn;
clone.WorkItemsToAssociate.AddRange(source.WorkItemsToAssociate);
clone.WorkItemsToResolve.AddRange(source.WorkItemsToResolve);
clone.AuthorsFilePath = source.AuthorsFilePath;
clone.AuthorTfsUserId = source.AuthorTfsUserId;
foreach (var note in source.CheckinNotes)
{
clone.CheckinNotes[note.Key] = note.Value;
@@ -108,6 +129,8 @@ namespace Sep.Git.Tfs.Util
checkinOptions.CheckinComment = GitTfsConstants.TfsReviewerRegex.Replace(checkinOptions.CheckinComment, "").Trim(' ', '\r', '\n');
}
private void ProcessForceCommand(CheckinOptions checkinOptions, TextWriter writer)
{
MatchCollection workitemMatches;
@@ -124,5 +147,32 @@ namespace Sep.Git.Tfs.Util
checkinOptions.CheckinComment = GitTfsConstants.TfsForceRegex.Replace(checkinOptions.CheckinComment, "").Trim(' ', '\r', '\n');
}
}
private void ProcessAuthor(CheckinOptions checkinOptions, TextWriter writer, GitCommit commit)
{
if (checkinOptions.AuthorsFilePath == null)
{
writer.WriteLine("Author file was not set.");
return;
}
// get authors file FIXME
AuthorsFile af = new AuthorsFile();
TextReader tr = new StreamReader(checkinOptions.AuthorsFilePath);
af.Parse(tr);
Author a = af.FindAuthor(commit.AuthorAndEmail);
if (a == null)
{
checkinOptions.AuthorTfsUserId = null;
return;
}
checkinOptions.AuthorTfsUserId = a.TfsUserId;
writer.WriteLine("Commit was authored by git user {0} {1} ({2})", a.Name, a.Email, a.TfsUserId);
}
}
}
+8
View File
@@ -61,6 +61,7 @@ namespace Sep.Git.Tfs.Test.Core
Arg<IPendingChange[]>.Is.Anything,
Arg<IPendingChange[]>.Is.Anything,
Arg<string>.Is.Anything,
Arg<string>.Is.Anything,
Arg<ICheckinNote>.Is.Anything,
Arg<IEnumerable<IWorkItemCheckinInfo>>.Is.Anything))
.Return(checkinEvaluationResult);
@@ -68,6 +69,7 @@ namespace Sep.Git.Tfs.Test.Core
workspace.Expect(w => w.Checkin(
Arg<IPendingChange[]>.Is.Anything,
Arg<string>.Is.Anything,
Arg<string>.Is.Anything,
Arg<ICheckinNote>.Is.Anything,
Arg<IEnumerable<IWorkItemCheckinInfo>>.Is.Anything,
Arg<TfsPolicyOverrideInfo>.Is.Anything,
@@ -109,6 +111,7 @@ namespace Sep.Git.Tfs.Test.Core
Arg<IPendingChange[]>.Is.Anything,
Arg<IPendingChange[]>.Is.Anything,
Arg<string>.Is.Anything,
Arg<string>.Is.Anything,
Arg<ICheckinNote>.Is.Anything,
Arg<IEnumerable<IWorkItemCheckinInfo>>.Is.Anything))
.Return(checkinEvaluationResult);
@@ -116,6 +119,7 @@ namespace Sep.Git.Tfs.Test.Core
workspace.Expect(w => w.Checkin(
Arg<IPendingChange[]>.Is.Anything,
Arg<string>.Is.Anything,
Arg<string>.Is.Anything,
Arg<ICheckinNote>.Is.Anything,
Arg<IEnumerable<IWorkItemCheckinInfo>>.Is.Anything,
Arg<TfsPolicyOverrideInfo>.Is.Anything,
@@ -160,6 +164,7 @@ namespace Sep.Git.Tfs.Test.Core
Arg<IPendingChange[]>.Is.Anything,
Arg<IPendingChange[]>.Is.Anything,
Arg<string>.Is.Anything,
Arg<string>.Is.Anything,
Arg<ICheckinNote>.Is.Anything,
Arg<IEnumerable<IWorkItemCheckinInfo>>.Is.Anything))
.Return(checkinEvaluationResult);
@@ -167,6 +172,7 @@ namespace Sep.Git.Tfs.Test.Core
workspace.Expect(w => w.Checkin(
Arg<IPendingChange[]>.Is.Anything,
Arg<string>.Is.Anything,
Arg<string>.Is.Anything,
Arg<ICheckinNote>.Is.Anything,
Arg<IEnumerable<IWorkItemCheckinInfo>>.Is.Anything,
Arg<TfsPolicyOverrideInfo>.Is.Anything,
@@ -212,6 +218,7 @@ namespace Sep.Git.Tfs.Test.Core
Arg<IPendingChange[]>.Is.Anything,
Arg<IPendingChange[]>.Is.Anything,
Arg<string>.Is.Anything,
Arg<string>.Is.Anything,
Arg<ICheckinNote>.Is.Anything,
Arg<IEnumerable<IWorkItemCheckinInfo>>.Is.Anything))
.Return(checkinEvaluationResult);
@@ -219,6 +226,7 @@ namespace Sep.Git.Tfs.Test.Core
workspace.Expect(w => w.Checkin(
Arg<IPendingChange[]>.Is.Anything,
Arg<string>.Is.Anything,
Arg<string>.Is.Anything,
Arg<ICheckinNote>.Is.Anything,
Arg<IEnumerable<IWorkItemCheckinInfo>>.Is.Anything,
Arg<TfsPolicyOverrideInfo>.Is.Anything,
+112 -3
View File
@@ -53,19 +53,19 @@ namespace Sep.Git.Tfs.Test.Util
[Fact]
public void AuthorsFileMultiLineRecord()
{
string author =
string author =
@"Domain\Test.User = Test User <TestUser@example.com>
Domain\Different.User = Three Name User < TestUser@example.com >";
AuthorsFile authFile = new AuthorsFile();
authFile.Parse(new StreamReader(new MemoryStream(Encoding.ASCII.GetBytes(author))));
Assert.NotNull(authFile.Authors);
Assert.Equal<int>(2, authFile.Authors.Count);
Assert.True(authFile.Authors.ContainsKey(@"Domain\Test.User"));
Author auth = authFile.Authors[@"Domain\Test.User"];
Assert.Equal<string>("Test User", auth.Name);
Assert.Equal<string>("TestUser@example.com", auth.Email);
Assert.True(authFile.Authors.ContainsKey(@"Domain\Different.User"));
auth = authFile.Authors[@"Domain\Different.User"];
Assert.Equal<string>("Three Name User", auth.Name);
@@ -167,5 +167,114 @@ differentDomain\Blåbærsyltetøy = ÆØÅ User <ÆØÅ@example.com>";
Assert.Equal<int>(1, authFile.Authors.Count);
Assert.True(authFile.Authors.ContainsKey(@"domain\Blåbærsyltetøy"));
}
private string _MergeAuthorsIntoString(string[] authors)
{
string result = @"";
for (int i = 0; i < authors.Length; ++i)
{
if (i != 0)
result += Environment.NewLine;
result += authors[i];
}
return result;
}
private AuthorsFile _SetupAuthorsFile(string[] authors)
{
string author = _MergeAuthorsIntoString(authors);
AuthorsFile authFile = new AuthorsFile();
authFile.Parse(new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(author))));
return authFile;
}
[Fact]
public void AuthorsFileMultipleUsers()
{
string[] authors = {
@"Domain\Test.User = Test User <TestUser@example.com>",
@"Domain\Different.User = Three Name User < DiffUser@example.com >",
@"Domain\Yet.Another.User = Mr. 3 <yau@example.com>"
};
AuthorsFile authFile = _SetupAuthorsFile(authors);
Assert.Equal<int>(authors.Length, authFile.Authors.Count);
Assert.Equal<int>(authors.Length, authFile.AuthorsByGitUserId.Count);
// contains all tfs users
Assert.True(authFile.Authors.ContainsKey(@"Domain\Test.User"));
Assert.True(authFile.Authors.ContainsKey(@"Domain\Different.User"));
Assert.True(authFile.Authors.ContainsKey(@"Domain\Yet.Another.User"));
// contains all git users
Assert.True(authFile.AuthorsByGitUserId.ContainsKey(Author.BuildGitUserId("TestUser@example.com")));
Assert.True(authFile.AuthorsByGitUserId.ContainsKey(Author.BuildGitUserId("DiffUser@example.com")));
Assert.True(authFile.AuthorsByGitUserId.ContainsKey(Author.BuildGitUserId("YAU@example.com")));
}
[Fact]
public void AuthorsFileDifferentIdsForUsersWithSameEmail()
{
string[] authors = {
@"Domain\Test.User = Test User <TestUser@example.com>",
@"Domain\Different.User = Three Name User < TestUser@example.com >",
@"Domain\Yet.Another.User = Mr. 3 <testuser@example.com>"
};
AuthorsFile authFile = _SetupAuthorsFile(authors);
Assert.NotNull(authFile.AuthorsByGitUserId);
// multiple users with the same email -> 3 tfs users, 1 git user
Assert.Equal<int>(authors.Length, authFile.Authors.Count);
Assert.Equal<int>(1, authFile.AuthorsByGitUserId.Count);
// contains all tfs users
Assert.True(authFile.Authors.ContainsKey(@"Domain\Test.User"));
Assert.True(authFile.Authors.ContainsKey(@"Domain\Different.User"));
Assert.True(authFile.Authors.ContainsKey(@"Domain\Yet.Another.User"));
// contains all git users
Assert.True(authFile.AuthorsByGitUserId.ContainsKey(Author.BuildGitUserId("TestUser@example.com")));
// return the first tfs user id in the authors file when multiple
// match to the same git id.
Tuple<string, string> git_author = new Tuple<string, string>("Test User", "TestUser@example.com");
Author a = authFile.FindAuthor(git_author);
Assert.NotNull(a);
Assert.Equal(a.TfsUserId, @"Domain\Test.User");
}
[Fact]
public void AuthorsFileFindAuthors()
{
string[] authors = {
@"Domain\Test.User = Test User <TestUser@example.com>",
@"Domain\Different.User = Three Name User < TestUser@example.com >",
@"Domain\Yet.Another.User = Mr. 3 <testuser@example.com>"
};
AuthorsFile authFile = _SetupAuthorsFile(authors);
// find existing author
Tuple<string, string> gitAuthor = new Tuple<string, string>("Test User", "TestUser@example.com");
Author existingAuthor = authFile.FindAuthor(gitAuthor);
Assert.NotNull(existingAuthor);
// try to find unknown author
Tuple<string, string> gitUnknownAuthor = new Tuple<string, string>("Test User", "TestFailUser@example.com");
Author unknownAuthor = authFile.FindAuthor(gitUnknownAuthor);
Assert.Null(unknownAuthor);
}
}
}