Filter case-only file renames, as they cannot be applied in tfs. (#1063)
This commit is contained in:
committed by
Philippe Miossec
parent
f6930c3697
commit
4e9a5a0312
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using StructureMap;
|
||||
@@ -11,6 +12,7 @@ namespace Sep.Git.Tfs.Core
|
||||
{
|
||||
public class GitChangeInfo
|
||||
{
|
||||
const string ElementToRemove = "[ElementToRemove]";
|
||||
public struct ChangeType
|
||||
{
|
||||
public const string ADD = "A";
|
||||
@@ -46,6 +48,7 @@ namespace Sep.Git.Tfs.Core
|
||||
public static IEnumerable<GitChangeInfo> GetChangedFiles(TextReader reader)
|
||||
{
|
||||
string line;
|
||||
var changes = new List<GitChangeInfo>();
|
||||
while (null != (line = GetDiffTreeLine(reader)))
|
||||
{
|
||||
var change = Parse(line);
|
||||
@@ -53,10 +56,58 @@ namespace Sep.Git.Tfs.Core
|
||||
if (FileMode.GitLink == change.NewMode)
|
||||
continue;
|
||||
|
||||
yield return change;
|
||||
changes.Add(change);
|
||||
}
|
||||
return FilterChangesIntroducedByCaseRenaming(changes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filter changes made when renames are "case only" because such changes are not supported by TFS
|
||||
/// </summary>
|
||||
/// <param name="changes">changes to filter</param>
|
||||
/// <returns>changes once filtered</returns>
|
||||
private static IEnumerable<GitChangeInfo> FilterChangesIntroducedByCaseRenaming(IEnumerable<GitChangeInfo> changes)
|
||||
{
|
||||
//filter out "case only renames" because they cannot be represented in TFS
|
||||
var remainingChanges = changes.Where(change => change.Status != ChangeType.RENAMEEDIT ||
|
||||
String.Compare(change.path, change.pathTo, StringComparison.OrdinalIgnoreCase) != 0 ||
|
||||
change.newSha != change.oldSha).ToList();
|
||||
|
||||
UpdateChangeStatusForCaseOnlyRenames(remainingChanges);
|
||||
|
||||
UpdateChangeStatusForAddedAndDeletedCaseOnlyRenames(remainingChanges);
|
||||
|
||||
return remainingChanges.Where(c => c.Status != ElementToRemove);
|
||||
}
|
||||
|
||||
private static void UpdateChangeStatusForCaseOnlyRenames(List<GitChangeInfo> remainingChanges)
|
||||
{
|
||||
foreach (var change in remainingChanges.Where(c => c.Status == ChangeType.RENAMEEDIT))
|
||||
{
|
||||
if (String.Compare(change.path, change.pathTo, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
change.Status = ChangeType.MODIFY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateChangeStatusForAddedAndDeletedCaseOnlyRenames(List<GitChangeInfo> remainingChanges)
|
||||
{
|
||||
var deletes = remainingChanges.Where(c => c.Status == ChangeType.DELETE).ToArray();
|
||||
foreach (var addChange in remainingChanges.Where(c => c.Status == ChangeType.ADD))
|
||||
{
|
||||
//change adds to renameedit, if the file name is the same as a delete
|
||||
var matchingDelete = deletes.FirstOrDefault(
|
||||
d => String.Equals(addChange.path, d.path, StringComparison.OrdinalIgnoreCase));
|
||||
if (matchingDelete != null)
|
||||
{
|
||||
addChange.Status = addChange.newSha != matchingDelete.oldSha ? ChangeType.MODIFY : ElementToRemove;
|
||||
matchingDelete.Status = ElementToRemove;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static string GetDiffTreeLine(TextReader reader)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
@@ -121,14 +172,15 @@ namespace Sep.Git.Tfs.Core
|
||||
}
|
||||
|
||||
private readonly Match _match;
|
||||
public string Status { get; set; }
|
||||
|
||||
private GitChangeInfo(Match match)
|
||||
{
|
||||
_match = match;
|
||||
Status = _match.Groups["status"].Value;
|
||||
}
|
||||
|
||||
public LibGit2Sharp.Mode NewMode { get { return _match.Groups["dstmode"].Value.ToFileMode(); } }
|
||||
public string Status { get { return _match.Groups["status"].Value; } }
|
||||
|
||||
public string oldMode { get { return _match.Groups["srcmode"].Value; } }
|
||||
public string newMode { get { return _match.Groups["dstmode"].Value; } }
|
||||
|
||||
@@ -245,5 +245,104 @@ namespace Sep.Git.Tfs.Test.Core
|
||||
Assert.Equal("TestFiles/試し4.txt", changes[4].path);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldDetectNormalRename_AndReturnOneRenameChange()
|
||||
{
|
||||
string input = ":100644 100644 ab6422c94fcb11e61378a231b0f3ce36958206d4 bb6422c94fcb11e61378a231b0f3ce36958206d4 R100\0TestFiles/Test0.txt\0TestFiles/Test_moved.txt\0";
|
||||
|
||||
using (var reader = new System.IO.StringReader(input))
|
||||
{
|
||||
var changes = GitChangeInfo.GetChangedFiles(reader).ToArray();
|
||||
|
||||
Assert.Equal(1, changes.Length);
|
||||
|
||||
Assert.Equal("R", changes[0].Status);
|
||||
Assert.Equal("TestFiles/Test_moved.txt", changes[0].pathTo);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldDetectCaseOnlyRenameWithNoContentChange_AndReturnNoChanges()
|
||||
{
|
||||
string input = ":100644 100644 fb6422c94fcb11e61378a231b0f3ce36958206d4 fb6422c94fcb11e61378a231b0f3ce36958206d4 R100\0TestFiles/Test2.txt\0TestFiles/test2.txt\0";
|
||||
|
||||
using (var reader = new System.IO.StringReader(input))
|
||||
{
|
||||
var changes = GitChangeInfo.GetChangedFiles(reader).ToArray();
|
||||
|
||||
Assert.Empty(changes);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldDetectCaseOnlyRenameWithContentChange_AndReturnOneModificationChanges()
|
||||
{
|
||||
string input = ":100644 100644 aaaac94fcb11e61378a231b0f3ce36958206d4dd bbbb22c94fcb11e61378a231b0f3ce36958206d4 R100\0TestFiles/Test1.txt\0TestFiles/test1.txt\0";
|
||||
|
||||
using (var reader = new System.IO.StringReader(input))
|
||||
{
|
||||
var changes = GitChangeInfo.GetChangedFiles(reader).ToArray();
|
||||
|
||||
Assert.Equal(1, changes.Length);
|
||||
|
||||
Assert.Equal("M", changes[0].Status);
|
||||
Assert.Equal("TestFiles/Test1.txt", changes[0].path);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldDetectAddDeleteCorrespondingToCaseRenameWithContentChange_AndReturnOneModificationChange()
|
||||
{
|
||||
string input =
|
||||
":000000 100644 0000000000000000000000000000000000000000 ed61b923604692e7c8b14763bd94412f471d91cc A\0TestFiles/Test0.txt\0" +
|
||||
":100644 000000 de4ea28b4e441777cf99329788d545986456183f 0000000000000000000000000000000000000000 D\0TestFiles/test0.txt\0";
|
||||
|
||||
using (var reader = new System.IO.StringReader(input))
|
||||
{
|
||||
var changes = GitChangeInfo.GetChangedFiles(reader).ToArray();
|
||||
|
||||
Assert.Equal(1, changes.Length);
|
||||
|
||||
Assert.Equal("M", changes[0].Status);
|
||||
Assert.Equal("TestFiles/Test0.txt", changes[0].path);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldDetectAddDeleteNotCorrespondingToCaseRenameWithContentChange_AndReturnOneAdditionAndOneDeletionChange()
|
||||
{
|
||||
string input =
|
||||
":100644 000000 de4ea28b4e441777cf99329788d545986456183f 0000000000000000000000000000000000000000 D\0TestFiles/Test1.txt\0" +
|
||||
":000000 100644 0000000000000000000000000000000000000000 ed61b923604692e7c8b14763bd94412f471d91cc A\0TestFiles/Test2.txt\0";
|
||||
|
||||
using (var reader = new System.IO.StringReader(input))
|
||||
{
|
||||
var changes = GitChangeInfo.GetChangedFiles(reader).ToArray();
|
||||
|
||||
Assert.Equal(2, changes.Length);
|
||||
|
||||
Assert.Equal("D", changes[0].Status);
|
||||
Assert.Equal("TestFiles/Test1.txt", changes[0].path);
|
||||
|
||||
Assert.Equal("A", changes[1].Status);
|
||||
Assert.Equal("TestFiles/Test2.txt", changes[1].path);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldDetectAddDeleteCorrespondingToCaseRenameWithoutContentChange_AndReturnNoChanges()
|
||||
{
|
||||
string input =
|
||||
":000000 100644 0000000000000000000000000000000000000000 ed61b923604692e7c8b14763bd94412f471d91cc A\0TestFiles/Test3.txt\0" +
|
||||
":100644 000000 ed61b923604692e7c8b14763bd94412f471d91cc 0000000000000000000000000000000000000000 D\0TestFiles/test3.txt\0";
|
||||
|
||||
using (var reader = new System.IO.StringReader(input))
|
||||
{
|
||||
var changes = GitChangeInfo.GetChangedFiles(reader).ToArray();
|
||||
|
||||
Assert.Empty(changes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user