-
Notifications
You must be signed in to change notification settings - Fork 899
Ignore Case via Repository.PathComparer #344
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
Conversation
@@ -56,7 +56,7 @@ private List<Conflict> AllConflicts() | |||
continue; | |||
} | |||
|
|||
if (currentPath != null && !entry.Path.Equals(currentPath, StringComparison.Ordinal)) | |||
if (currentPath != null && !repo.PathComparer.Equals(entry.Path, currentPath)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I have conflicts for both FILE
and file
, this will overwrite one with the other. I think we need to sort the Conflict
s after having coalesced the index entries into a single object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we would just need to to presort the IndexEntry
s by Path
with repo.PathComparer
.
A better option might be to let LINQ do the grouping:
private static Conflict BuildConflict(string path, IEnumerable<IndexEntry> entries)
{
IndexEntry ancestor = null, ours = null, theirs = null;
foreach (var entry in entries)
{
switch (entry.StageLevel)
{
case StageLevel.Ancestor:
ancestor = entry;
break;
case StageLevel.Ours:
ours = entry;
break;
case StageLevel.Theirs:
theirs = entry;
break;
default:
throw new InvalidOperationException(string.Format(
CultureInfo.InvariantCulture,
"Entry '{0}' bears an unexpected StageLevel '{1}'",
entry.Path, entry.StageLevel));
}
}
return new Conflict(ancestor, ours, theirs);
}
public virtual IEnumerator<Conflict> GetEnumerator()
{
return repo.Index
.Where(e => e.StageLevel != StageLevel.Staged)
.GroupBy(e => e.Path, BuildConflict, repo.PathComparer)
.GetEnumerator();
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The appropriate implementation here depends on how #345 is resolved.
ReferenceEquals(y, null) ? null : valueSelector(y)); | ||
} | ||
} | ||
} No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And I thought I was so careful... Darn R# 😦
Some random findings:
or
I haven't got any issue diverging from git implementation, but we'll have to be backed up by a thick test suite to express, platform by platform, what is the proposed behavior. Thoughts? |
Mine too, I was on the fence about changing this.
That's what I'm afraid of. Realistically, I'm using More generally, I'm still on the fence about |
I don't think I understand this PR. What is the goal here? I do agree that there are some places in libgit2sharp where we need to understand the case-sensitive or case-insensitive nature of the underlying filesystem. For example, I think there is a method on Index (Index.Stage?) where we take in an absolute path and have to check to see whether or not that absolute path is underneath the working directory for the repository. I noticed a while back that that string comparer was Ordinal, all the time, which isn't right on Windows. (But it is on some platforms where Libgit2sharp runs under Mono.) So we need some logic for picking a path comparer in that context. But isn't ignorecase support the purview of libgit2? These are just bindings. |
Case-insensitivity where it's necessary. Identifying where it's necessary is a work in progress. I started by using
For the most part, but there are cases where we do things like sort index entries that depend on case-sensitivity. If I do a In the |
Thanks Keith for the explanation and your patience with me. I think you can make the argument either way on that Index.Stage() example as to what the best implementation is. Probably it's more correct to try to detect what platform we're running on and determine case-sensitivity that way -- but it's easier to just look at core.ignorecase. I think either one is acceptable. I'm not sure that we should start guaranteeing a sort order on collections that we get back from libgit2 -- refs, index entries, etc. There is a perf cost to sorting, and ownership of the sort order probably ought to be a guarantee that either originates all the way down the stack and flows up from there, or is applied at the top of the stack by the eventual consumer. But applying a sort in the middle of the stack (which is what Libgit2sharp is) feels weird to me. |
I tend to agree with @phkelley about the sorting on things like refs and the like. Me personally, I would expect enumerating the For something like I presume that as a consumer I would have some control over sorting, but I just thought I'd throw that out there. |
I'm the one to blame here. I think I did add the initial 👍 to drop them.
One thing to note though regarding loose references: IIRC @carlosmn explained me once that there's no guarantee that |
Right, a directory listing will be in whatever order the OS feels like (at least on unix). The index and trees have inherent order (and the trees have odd sorting so these both match) inside them, but there is no particular sorting of refs that makes more sense, particularly since you usually want to filter them by type anyway. |
Let's try this again... I've refocused on places where we use case-sensitive comparison for paths within the working directory ( I also included 07fc2c3ddae3367410763134ec3ff043fe29e2cd to remove sorting - from a consumer standpoint, this is a UX-breaking change. |
DirectoryHelper.DeleteDirectory(directory); | ||
for (var i = 0; i < 3; i++) | ||
{ | ||
try |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not, will kill the next time around.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gone.
Updated with fixes for the failing Travis tests around the sorting change. |
Down to one failing test:
@carlosmn If |
Looks like this goes down to "Is there a way to make I can think of a hack to make this work, though. Beware, it's ugly and greedy:
Ugly and greedy, isn't it? I told you. 😉 There's an additional bonus drawback, this couldn't support glob patterns that are about to be introduced by #343 (through the diff-based approach). |
Yes Ultimately I think our behavior needs to mimic git.git here. Does it even try to support |
The EDIT: it does support it on unix if you mount NTFS for example. It's not about the OS but about the filesystem, you can have either on OSX. |
What do you think of 4673aa7 to skip |
@@ -778,6 +780,21 @@ public virtual IEnumerable<MergeHead> MergeHeads | |||
} | |||
} | |||
|
|||
private PathCase PathCase | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it boils down to a personal preference, but maybe we could remove the private property and directly access pathCase.Value
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or another idea: maybe we could change the access modifier to internal
, rename the property to something like PathCaseSupport
, and just access the .Comparer
and .StartsWith()
directly?
That would allow us to get rid of the other property and method below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I lean toward inlining the PathCase
property, but I guess there's not much difference between repo.PathComparer
and repo.PathCase.Comparer
.
@dahlbyk Travis doesn't look happy... Could you please peek at those?
|
Should be fixed now...missed a test that I thought I'd rolled back. |
Update on top of latest, but...what seems to be an unrelated test is failing. Naturally it works on my machine... Ideas?
|
It looks like the failure comes from 8e8ba01. I've cherry picked it onto the top of vNext and ran it on TeamCity. The Mono build configuration failed as well. |
Good call...overlooked the use of unsorted Refs. 💚 |
❤️ Thanks a lot for this very cool piece of work. Merged! |
Round-about path to initial ignore case support.
IPathComparable
(implemented in last four commits), or just usingStringPropertyComparer<>
with lambdas.Also, I included 9bcc2c1 because I don't want to create a dedicated issue unless I'm not alone... on Win8 I'm seeing sporadic Access Denied errors that I haven't seen in quite a while. Just me, or are others seeing it too? Is a retry worth keeping?