##// END OF EJS Templates
dirstate: preserve path components case on renames (issue3402)...
Patrick Mezard -
r16542:e596a631 stable
parent child Browse files
Show More
@@ -268,6 +268,11 b' def copy(ui, repo, pats, opts, rename=Fa'
268 268 # otarget: ossep
269 269 def copyfile(abssrc, relsrc, otarget, exact):
270 270 abstarget = scmutil.canonpath(repo.root, cwd, otarget)
271 if '/' in abstarget:
272 # We cannot normalize abstarget itself, this would prevent
273 # case only renames, like a => A.
274 abspath, absname = abstarget.rsplit('/', 1)
275 abstarget = repo.dirstate.normalize(abspath) + '/' + absname
271 276 reltarget = repo.pathto(abstarget, cwd)
272 277 target = repo.wjoin(abstarget)
273 278 src = repo.wjoin(abssrc)
@@ -408,32 +408,48 b' class dirstate(object):'
408 408 self._droppath(f)
409 409 del self._map[f]
410 410
411 def _normalize(self, path, isknown):
411 def _normalize(self, path, isknown, ignoremissing=False, exists=None):
412 412 normed = util.normcase(path)
413 413 folded = self._foldmap.get(normed, None)
414 414 if folded is None:
415 if isknown or not os.path.lexists(os.path.join(self._root, path)):
415 if isknown:
416 416 folded = path
417 417 else:
418 # recursively normalize leading directory components
419 # against dirstate
420 if '/' in normed:
421 d, f = normed.rsplit('/', 1)
422 d = self._normalize(d, isknown)
423 r = self._root + "/" + d
424 folded = d + "/" + util.fspath(f, r)
418 if exists is None:
419 exists = os.path.lexists(os.path.join(self._root, path))
420 if not exists:
421 # Maybe a path component exists
422 if not ignoremissing and '/' in path:
423 d, f = path.rsplit('/', 1)
424 d = self._normalize(d, isknown, ignoremissing, None)
425 folded = d + "/" + f
426 else:
427 # No path components, preserve original case
428 folded = path
425 429 else:
426 folded = util.fspath(normed, self._root)
427 self._foldmap[normed] = folded
430 # recursively normalize leading directory components
431 # against dirstate
432 if '/' in normed:
433 d, f = normed.rsplit('/', 1)
434 d = self._normalize(d, isknown, ignoremissing, True)
435 r = self._root + "/" + d
436 folded = d + "/" + util.fspath(f, r)
437 else:
438 folded = util.fspath(normed, self._root)
439 self._foldmap[normed] = folded
428 440
429 441 return folded
430 442
431 def normalize(self, path, isknown=False):
443 def normalize(self, path, isknown=False, ignoremissing=False):
432 444 '''
433 445 normalize the case of a pathname when on a casefolding filesystem
434 446
435 447 isknown specifies whether the filename came from walking the
436 disk, to avoid extra filesystem access
448 disk, to avoid extra filesystem access.
449
450 If ignoremissing is True, missing path are returned
451 unchanged. Otherwise, we try harder to normalize possibly
452 existing path components.
437 453
438 454 The normalized case is determined based on the following precedence:
439 455
@@ -443,7 +459,7 b' class dirstate(object):'
443 459 '''
444 460
445 461 if self._checkcase:
446 return self._normalize(path, isknown)
462 return self._normalize(path, isknown, ignoremissing)
447 463 return path
448 464
449 465 def clear(self):
@@ -575,7 +591,7 b' class dirstate(object):'
575 591 normalize = self._normalize
576 592 skipstep3 = False
577 593 else:
578 normalize = lambda x, y: x
594 normalize = lambda x, y, z: x
579 595
580 596 files = sorted(match.files())
581 597 subrepos.sort()
@@ -596,7 +612,7 b' class dirstate(object):'
596 612
597 613 # step 1: find all explicit files
598 614 for ff in files:
599 nf = normalize(normpath(ff), False)
615 nf = normalize(normpath(ff), False, True)
600 616 if nf in results:
601 617 continue
602 618
@@ -646,7 +662,7 b' class dirstate(object):'
646 662 continue
647 663 raise
648 664 for f, kind, st in entries:
649 nf = normalize(nd and (nd + "/" + f) or f, True)
665 nf = normalize(nd and (nd + "/" + f) or f, True, True)
650 666 if nf not in results:
651 667 if kind == dirkind:
652 668 if not ignore(nf):
@@ -32,6 +32,42 b' Case-changing renames should work:'
32 32 $ hg mv a A
33 33 $ hg mv A a
34 34 $ hg st
35
36 test changing case of path components
37
38 $ mkdir D
39 $ echo b > D/b
40 $ hg ci -Am addb D/b
41 $ hg mv D/b d/b
42 D/b: not overwriting - file exists
43 $ hg mv D/b d/c
44 $ hg st
45 A D/c
46 R D/b
47 $ mv D temp
48 $ mv temp d
49 $ hg st
50 A D/c
51 R D/b
52 $ hg revert -aq
53 $ rm d/c
54 $ echo c > D/c
55 $ hg add D/c
56 $ hg st
57 A D/c
58 $ hg ci -m addc D/c
59 $ hg mv d/b d/e
60 moving D/b to D/e
61 $ hg st
62 A D/e
63 R D/b
64 $ hg revert -aq
65 $ rm d/e
66 $ hg mv d/b D/B
67 moving D/b to D/B
68 $ hg st
69 A D/B
70 R D/b
35 71 $ cd ..
36 72
37 73 test case collision between revisions (issue912)
General Comments 0
You need to be logged in to leave comments. Login now