[PATCH STABLE] icasefs: abort update, if added/removed files in working causes case folding collision
mpm at selenic.com
Mon Apr 9 15:49:02 CDT 2012
On Mon, 2012-04-09 at 21:06 +0900, FUJIWARA Katsunori wrote:
> At Thu, 05 Apr 2012 14:26:21 -0500,
> Matt Mackall wrote:
> > > > diff -r 1d8eab6dfe65 mercurial/merge.py
> > > > --- a/mercurial/merge.py Tue Apr 03 22:02:04 2012 +0200
> > > > +++ b/mercurial/merge.py Wed Apr 04 11:45:59 2012 -0500
> > > > @@ -568,7 +568,7 @@
> > > > action = 
> > > > folding = not util.checkcase(repo.path)
> > > > if folding:
> > > > - _checkcollision(p2, branchmerge and p1)
> > > > + _checkcollision(p2, wc)
> > > > if not force:
> > > > _checkunknown(repo, wc, p2)
> > > > action += _forgetremoved(wc, p2, branchmerge)
> > Unfortunately, what doesn't work with my patch is that if I rename 'a'
> > to 'A', commit, then try to go backwards, it fails. So it seems we need
> > some rename-awareness in _checkcollision. On the other hand, without my
> > patch, it will clobber newly-added files that collide with old files
> > when going backwards.
> Hi, Matt.
> I want some suggestions about my work.
> At first, I added below logic to collision detection:
> - check rename/copy if collision is detected BETWEEN working and
> target context
> if colliding file in target context is copy of collided file in
> working context, collision can be ignored: colliding file maybe
> rename of collided one, because collision is not detected IN
> target context and it ensures that collided file does not exist in
> this is achieved by result copies.pathcopies(),
> Then, it is assumed that there are two revisions in linear history
> #1: has 'a' and 'b'
> #2: has 'A' renamed from 'b', and 'C' renamed from 'a'
> On updating from #1 to #2, collision between 'a'@#1 and 'A'@#2 is
> recognized as not ignorable collision, because 'A'@#2 is not copy of
> 'a'@#1, even though it can be renamed to 'C'@#2 safely.
Ok, so your test is this:
hg init a
echo a1 > a
echo b1 > b
hg ci -Am0
hg mv a C
hg mv b A
hg ci -Am1
hg up 0
echo a2 > a
echo b2 > b
On a case-sensitive system, Mercurial does:
merging a and C to C
merging b and A to A
..and gives us 'b2' in A and 'a2' in C. Anyone who does this sort of
nonsense is asking for trouble, but we manage to handle it correctly in
But I'm not sure I really care how we handle this on case-insensitive
systems, as it's a mish-mash of "we changed case" and "we changed file
identities in ways that are hard to untangle". We definitely don't/won't
honor criss-crossing renames in merges, so when we do criss-crossing
I'm mostly concerned about the a -> A case, and I'm frankly fine with
having other things be collisions.
> Should I check whether files copied from 'a'@#1 exist in #2 or not ?
> In another case, it is also assumed that there are two revisions:
> #1: has 'a' and 'b'
> #2: has 'A' renamed from 'b', but no 'a' which was removed
> On updating from #1 to #2, there is no file copied from 'a'@#1 in #2,
> so this will be recognized as not ignorable collision, even though 'a'
> is clean in working context.
..meaning it can be safely deleted, and thus not conflict. Hmm.
> If 'a' is modified in working context in above case, aborting by
> collision seems to be reasonable. But should I abort updating after
> confirmation like below ?
> local changed 'a' which remote deleted
> use (c)hanged version or (d)elete?
> # abort updating if 'changed' is chosen
That seems annoying, as I may have carefully answered several other
prompts before getting to this point.
> Perhaps, should I examine case-folding collision not at current point,
> but after manifest merging ? It seems to figure out renaming, coping,
> collision between modifying and removing, and so on: all about what we
> want to know for collision detection.
Perhaps. But it's significantly trickier, I think.
Also note that we want to ignore all these issues on update -C:
colliding files should always win and end up with the target case.
Mathematics is the supreme nostalgia of our time.
More information about the Mercurial-devel