Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore case only changes in export from git to tfs #1063

Merged
merged 2 commits into from Apr 25, 2017

Conversation

EdorianDark
Copy link
Contributor

@EdorianDark EdorianDark commented Apr 13, 2017

Rewrite my last pull request.
Fixes #1060
Is this ok?

Copy link
Member

@pmiossec pmiossec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for the work and the abnegation!!!

I have one big question (see comment on line 36) that I will be pleased if you could explain to me.

And some other small comments.

Thanks again!

workspace.Rename(Path, PathTo, Score);
var workspaceFile = workspace.GetLocalPath(PathTo);
_repository.CopyBlob(NewSha, workspaceFile);
if (Path.ToLower() != PathTo.ToLower())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I prefer using string.Equals(Path, PathTo, StringComparison.OrdinalIgnoreCase) here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I will change this.

}

//From https://support.microsoft.com/en-us/help/320348/how-to-create-a-file-compare-function-in-visual-c
private bool FileCompare(string file1, string file2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this method could be extracted in a helper and unit tested (takes 2 streams following the previous comments).

}

// Open the two files.
fs1 = new FileStream(file1, FileMode.Open);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not use using(var fs1 = new FileStream(file1, FileMode.Open))?

If you refactor to take 2 Streams, the using() will indeed be outside of the method...

// Return the success of the comparison. "file1byte" is
// equal to "file2byte" at this point only if the files are
// the same.
return ((file1byte - file2byte) == 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return (file1byte == file2byte); instead ?

//From https://support.microsoft.com/en-us/help/320348/how-to-create-a-file-compare-function-in-visual-c
private bool FileCompare(string file1, string file2)
{
int file1byte;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These definitions could be made closer to the use...

//This change can not be mapped to TFS, since TFS is case insensitive
var workspaceFile = workspace.GetLocalPath(Path);
var newTestFile = workspaceFile + NewSha;
_repository.CopyBlob(NewSha, newTestFile);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we should not use CopyBlob() but write a new method that return a Stream that will be compared by the method bool FileCompare(Stream stream1, Stream stream2).

That way, we are not obliged to write the 2 contents in new files to read and delete them after. All will be made in memory.

Look at the code of CopyBlob(). There is the lines needed to return the streams
You could have a look

if (fs1.Length != fs2.Length)
{
// Close the file
fs1.Close();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Close() could be removed if using using(). That will make the code shorter...

else
{
//This change can not be mapped to TFS, since TFS is case insensitive
var workspaceFile = workspace.GetLocalPath(Path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry but I don't understand exactly what we try to achieve here (it should be my fault because I was not there at the beginning).

I understand that we compare the content of 2 blobs but what does the content of the 2 blobs represent exactly?
What is changeInfo ?

Because I see that you use changeInfo.newSha and changeInfo.oldSha to name the files and because that's sha, these 2 values will be the same if the content is the same and different if the content is different!

So, it seems that we don't need to compare the content, no? Does I miss something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was under the impression, that the file name is used for calculating the hash.
Since this is not the case, the file comparison is unnecessary.

@EdorianDark
Copy link
Contributor Author

I noticed, that sometimes a rename is split into an add and a delete.
This means there is filtering needed in the GitRepository.
But the change would be too complicated for me.

@EdorianDark EdorianDark reopened this Apr 20, 2017
@EdorianDark
Copy link
Contributor Author

@pmiossec I want to to filter needed the changes in GitRepository. For that I would need to collect the changes first and then look at for case-only renames in the add, delete and rename changes.

Would this change to the collection removing the yield be too big?

@EdorianDark
Copy link
Contributor Author

I tried the the other approach. I hope this is ok now.

@spraints
Copy link
Member

@EdorianDark I like this implementation. Can you extract the new code to a separate method or class and add some unit tests for it?

@pmiossec pmiossec changed the title Ignore case only changes in export from git to tfs 2 Ignore case only changes in export from git to tfs Apr 24, 2017
Copy link
Member

@pmiossec pmiossec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again for the work.
You could find here some small things to change.
We are near the end ;)

And at the end, feel free to squash your commits and force push.

@@ -46,15 +47,72 @@ public struct ChangeType
public static IEnumerable<GitChangeInfo> GetChangedFiles(TextReader reader)
{
string line;
List<GitChangeInfo> changes = new List<GitChangeInfo>(); ;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I prefer using var is this special case. What do you think?
  2. Remove the leading ;

return filterd;
}

private static IEnumerable<GitChangeInfo> FilterNotRepresentable(IEnumerable<GitChangeInfo> changed)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could your rename changed to changes?

}
var filterd = FilterNotRepresentable(changes);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could your rename to filtered? Or even better return directly.

String.Compare(cha.path, cha.pathTo, System.StringComparison.OrdinalIgnoreCase) != 0 ||
cha.newSha != cha.oldSha).ToList();

foreach (var cha in remainingChanges)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer naming the variable change instead of only cha (and below too...)


var deletes = remainingChanges.Where(cha => cha.Status == GitChangeInfo.ChangeType.DELETE).ToArray();
var adds = remainingChanges.Where(cha => cha.Status == GitChangeInfo.ChangeType.ADD).ToArray();
var removeElement = "RemoveElement";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract as a const...

@@ -484,6 +484,7 @@ public IEnumerable<IGitChangedFile> GetChangedFiles(string from, string to)
using (var diffOutput = CommandOutputPipe("diff-tree", "-r", "-M", "-z", from, to))
{
var changes = GitChangeInfo.GetChangedFiles(diffOutput);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove changes done on this file?

}
}

remainingChanges.RemoveAll(cha => cha.Status == removeElement);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just use a .Where() to not introduce sideeffects?


foreach (var cha in remainingChanges)
{
if(cha.Status == GitChangeInfo.ChangeType.RENAMEEDIT)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will be happy if we could extract a method and name it as mucha as possible clearly after what we do.
From what I understand, something like ReconsiderChangeWithCaseRenamingAsModification()...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean something like FilterAddDeleted and FilterRenameEdit?
Or which operations should I extract?

if (cha.Status == GitChangeInfo.ChangeType.ADD)
{
if (deletes.Any(del => String.Equals(cha.path, del.path, System.StringComparison.OrdinalIgnoreCase)))
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For efficiency and readability, isn't it possible to that at the same time we handle the DELETE change (line 90)?
We already search for the ADD change corresponding to the DELETE. We just have to update it at the same time.
This way we prevent 2 more searches (and remove most of this code)....

@@ -245,5 +245,28 @@ public void MultipleChangesWithJapanese()
Assert.Equal("TestFiles/試し4.txt", changes[4].path);
}
}

[Fact]
public void NotRepresentableChanges()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you cut this test in 2 (one for Add/Delete case and one for Renaming) with a naming explicit (I know that the other tests are not very well named :( )

@EdorianDark
Copy link
Contributor Author

EdorianDark commented Apr 24, 2017

I did not understand which part to factor out of FilterNotRepresentable.
Can you explain it again?

@pmiossec
Copy link
Member

I have made the changes in a branch that you could find here: https://github.com/pmiossec/git-tfs/tree/EdorianDark-master2

I have cut all the changes in small commits to make your review easier.
Feel free to fetch them and put them in your pull request if that please you!
Don't forget to squash all that if you do so...

@EdorianDark
Copy link
Contributor Author

Thank you very much!! 👍

Copy link
Member

@pmiossec pmiossec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok to merge it. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants