Show More
@@ -0,0 +1,105 b'' | |||
|
1 | ||
|
2 | $ cat >> $HGRCPATH << EOF | |
|
3 | > [experimental] | |
|
4 | > copies.write-to=changeset-only | |
|
5 | > [alias] | |
|
6 | > changesetcopies = log -r . -T 'files: {files} | |
|
7 | > {extras % "{ifcontains("copies", key, "{key}: {value}\n")}"}' | |
|
8 | > EOF | |
|
9 | ||
|
10 | Check that copies are recorded correctly | |
|
11 | ||
|
12 | $ hg init repo | |
|
13 | $ cd repo | |
|
14 | $ echo a > a | |
|
15 | $ hg add a | |
|
16 | $ hg ci -m initial | |
|
17 | $ hg cp a b | |
|
18 | $ hg cp a c | |
|
19 | $ hg cp a d | |
|
20 | $ hg ci -m 'copy a to b, c, and d' | |
|
21 | $ hg changesetcopies | |
|
22 | files: b c d | |
|
23 | p1copies: b\x00a (esc) | |
|
24 | c\x00a (esc) | |
|
25 | d\x00a (esc) | |
|
26 | ||
|
27 | Check that renames are recorded correctly | |
|
28 | ||
|
29 | $ hg mv b b2 | |
|
30 | $ hg ci -m 'rename b to b2' | |
|
31 | $ hg changesetcopies | |
|
32 | files: b b2 | |
|
33 | p1copies: b2\x00b (esc) | |
|
34 | ||
|
35 | Rename onto existing file. This should get recorded in the changeset files list and in the extras, | |
|
36 | even though there is no filelog entry. | |
|
37 | ||
|
38 | $ hg cp b2 c --force | |
|
39 | $ hg st --copies | |
|
40 | M c | |
|
41 | b2 | |
|
42 | $ hg debugindex c | |
|
43 | rev linkrev nodeid p1 p2 | |
|
44 | 0 1 b789fdd96dc2 000000000000 000000000000 | |
|
45 | $ hg ci -m 'move b onto d' | |
|
46 | $ hg changesetcopies | |
|
47 | files: c | |
|
48 | p1copies: c\x00b2 (esc) | |
|
49 | $ hg debugindex c | |
|
50 | rev linkrev nodeid p1 p2 | |
|
51 | 0 1 b789fdd96dc2 000000000000 000000000000 | |
|
52 | ||
|
53 | Create a merge commit with copying done during merge. | |
|
54 | ||
|
55 | $ hg co 0 | |
|
56 | 0 files updated, 0 files merged, 3 files removed, 0 files unresolved | |
|
57 | $ hg cp a e | |
|
58 | $ hg cp a f | |
|
59 | $ hg ci -m 'copy a to e and f' | |
|
60 | created new head | |
|
61 | $ hg merge 3 | |
|
62 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
|
63 | (branch merge, don't forget to commit) | |
|
64 | File 'a' exists on both sides, so 'g' could be recorded as being from p1 or p2, but we currently | |
|
65 | always record it as being from p1 | |
|
66 | $ hg cp a g | |
|
67 | File 'd' exists only in p2, so 'h' should be from p2 | |
|
68 | $ hg cp d h | |
|
69 | File 'f' exists only in p1, so 'i' should be from p1 | |
|
70 | $ hg cp f i | |
|
71 | $ hg ci -m 'merge' | |
|
72 | $ hg changesetcopies | |
|
73 | files: g h i | |
|
74 | p1copies: g\x00a (esc) | |
|
75 | i\x00f (esc) | |
|
76 | p2copies: h\x00d (esc) | |
|
77 | ||
|
78 | Test writing to both changeset and filelog | |
|
79 | ||
|
80 | $ hg cp a j | |
|
81 | $ hg ci -m 'copy a to j' --config experimental.copies.write-to=compatibility | |
|
82 | $ hg changesetcopies | |
|
83 | files: j | |
|
84 | p1copies: j\x00a (esc) | |
|
85 | $ hg debugdata j 0 | |
|
86 | \x01 (esc) | |
|
87 | copy: a | |
|
88 | copyrev: b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 | |
|
89 | \x01 (esc) | |
|
90 | a | |
|
91 | ||
|
92 | Test writing only to filelog | |
|
93 | ||
|
94 | $ hg cp a k | |
|
95 | $ hg ci -m 'copy a to k' --config experimental.copies.write-to=filelog-only | |
|
96 | $ hg changesetcopies | |
|
97 | files: k | |
|
98 | $ hg debugdata k 0 | |
|
99 | \x01 (esc) | |
|
100 | copy: a | |
|
101 | copyrev: b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 | |
|
102 | \x01 (esc) | |
|
103 | a | |
|
104 | ||
|
105 | $ cd .. |
@@ -80,6 +80,13 b' def encodeextra(d):' | |||
|
80 | 80 | ] |
|
81 | 81 | return "\0".join(items) |
|
82 | 82 | |
|
83 | def encodecopies(copies): | |
|
84 | items = [ | |
|
85 | '%s\0%s' % (k, copies[k]) | |
|
86 | for k in sorted(copies) | |
|
87 | ] | |
|
88 | return "\n".join(items) | |
|
89 | ||
|
83 | 90 | def stripdesc(desc): |
|
84 | 91 | """strip trailing whitespace and leading and trailing empty lines""" |
|
85 | 92 | return '\n'.join([l.rstrip() for l in desc.splitlines()]).strip('\n') |
@@ -533,7 +540,7 b' class changelog(revlog.revlog):' | |||
|
533 | 540 | return l[3:] |
|
534 | 541 | |
|
535 | 542 | def add(self, manifest, files, desc, transaction, p1, p2, |
|
536 | user, date=None, extra=None): | |
|
543 | user, date=None, extra=None, p1copies=None, p2copies=None): | |
|
537 | 544 | # Convert to UTF-8 encoded bytestrings as the very first |
|
538 | 545 | # thing: calling any method on a localstr object will turn it |
|
539 | 546 | # into a str object and the cached UTF-8 string is thus lost. |
@@ -562,6 +569,13 b' class changelog(revlog.revlog):' | |||
|
562 | 569 | elif branch in (".", "null", "tip"): |
|
563 | 570 | raise error.StorageError(_('the name \'%s\' is reserved') |
|
564 | 571 | % branch) |
|
572 | if (p1copies or p2copies) and extra is None: | |
|
573 | extra = {} | |
|
574 | if p1copies: | |
|
575 | extra['p1copies'] = encodecopies(p1copies) | |
|
576 | if p2copies: | |
|
577 | extra['p2copies'] = encodecopies(p2copies) | |
|
578 | ||
|
565 | 579 | if extra: |
|
566 | 580 | extra = encodeextra(extra) |
|
567 | 581 | parseddate = "%s %s" % (parseddate, extra) |
@@ -488,6 +488,9 b" coreconfigitem('experimental', 'copytrac" | |||
|
488 | 488 | coreconfigitem('experimental', 'copies.read-from', |
|
489 | 489 | default="filelog-only", |
|
490 | 490 | ) |
|
491 | coreconfigitem('experimental', 'copies.write-to', | |
|
492 | default='filelog-only', | |
|
493 | ) | |
|
491 | 494 | coreconfigitem('experimental', 'crecordtest', |
|
492 | 495 | default=None, |
|
493 | 496 | ) |
@@ -2324,7 +2324,8 b' class localrepository(object):' | |||
|
2324 | 2324 | """Returns the wlock if it's held, or None if it's not.""" |
|
2325 | 2325 | return self._currentlock(self._wlockref) |
|
2326 | 2326 | |
|
2327 |
def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist |
|
|
2327 | def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist, | |
|
2328 | includecopymeta): | |
|
2328 | 2329 | """ |
|
2329 | 2330 | commit an individual file as part of a larger transaction |
|
2330 | 2331 | """ |
@@ -2383,8 +2384,9 b' class localrepository(object):' | |||
|
2383 | 2384 | |
|
2384 | 2385 | if cnode: |
|
2385 | 2386 | self.ui.debug(" %s: copy %s:%s\n" % (fname, cfname, hex(cnode))) |
|
2386 | meta["copy"] = cfname | |
|
2387 |
meta["copy |
|
|
2387 | if includecopymeta: | |
|
2388 | meta["copy"] = cfname | |
|
2389 | meta["copyrev"] = hex(cnode) | |
|
2388 | 2390 | fparent1, fparent2 = nullid, newfparent |
|
2389 | 2391 | else: |
|
2390 | 2392 | self.ui.warn(_("warning: can't find ancestor for '%s' " |
@@ -2552,6 +2554,12 b' class localrepository(object):' | |||
|
2552 | 2554 | p1, p2 = ctx.p1(), ctx.p2() |
|
2553 | 2555 | user = ctx.user() |
|
2554 | 2556 | |
|
2557 | writecopiesto = self.ui.config('experimental', 'copies.write-to') | |
|
2558 | writefilecopymeta = writecopiesto != 'changeset-only' | |
|
2559 | p1copies, p2copies = None, None | |
|
2560 | if writecopiesto in ('changeset-only', 'compatibility'): | |
|
2561 | p1copies = ctx.p1copies() | |
|
2562 | p2copies = ctx.p2copies() | |
|
2555 | 2563 | with self.lock(), self.transaction("commit") as tr: |
|
2556 | 2564 | trp = weakref.proxy(tr) |
|
2557 | 2565 | |
@@ -2585,7 +2593,8 b' class localrepository(object):' | |||
|
2585 | 2593 | else: |
|
2586 | 2594 | added.append(f) |
|
2587 | 2595 | m[f] = self._filecommit(fctx, m1, m2, linkrev, |
|
2588 |
trp, changed |
|
|
2596 | trp, changed, | |
|
2597 | writefilecopymeta) | |
|
2589 | 2598 | m.setflag(f, fctx.flags()) |
|
2590 | 2599 | except OSError: |
|
2591 | 2600 | self.ui.warn(_("trouble committing %s!\n") % |
@@ -2639,7 +2648,8 b' class localrepository(object):' | |||
|
2639 | 2648 | self.changelog.delayupdate(tr) |
|
2640 | 2649 | n = self.changelog.add(mn, files, ctx.description(), |
|
2641 | 2650 | trp, p1.node(), p2.node(), |
|
2642 |
user, ctx.date(), ctx.extra().copy() |
|
|
2651 | user, ctx.date(), ctx.extra().copy(), | |
|
2652 | p1copies, p2copies) | |
|
2643 | 2653 | xp1, xp2 = p1.hex(), p2 and p2.hex() or '' |
|
2644 | 2654 | self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1, |
|
2645 | 2655 | parent2=xp2) |
@@ -438,7 +438,7 b' and its ancestor by overriding "repo._fi' | |||
|
438 | 438 | > def reposetup(ui, repo): |
|
439 | 439 | > class legacyrepo(repo.__class__): |
|
440 | 440 | > def _filecommit(self, fctx, manifest1, manifest2, |
|
441 | > linkrev, tr, changelist): | |
|
441 | > linkrev, tr, changelist, includecopymeta): | |
|
442 | 442 | > fname = fctx.path() |
|
443 | 443 | > text = fctx.data() |
|
444 | 444 | > flog = self.file(fname) |
@@ -443,7 +443,7 b' and its ancestor by overriding "repo._fi' | |||
|
443 | 443 | > def reposetup(ui, repo): |
|
444 | 444 | > class legacyrepo(repo.__class__): |
|
445 | 445 | > def _filecommit(self, fctx, manifest1, manifest2, |
|
446 | > linkrev, tr, changelist): | |
|
446 | > linkrev, tr, changelist, includecopymeta): | |
|
447 | 447 | > fname = fctx.path() |
|
448 | 448 | > text = fctx.data() |
|
449 | 449 | > flog = self.file(fname) |
General Comments 0
You need to be logged in to leave comments.
Login now