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 |
|
|
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