##// END OF EJS Templates
copies: add config option for writing copy metadata to file and/or changset...
Martin von Zweigbergk -
r42317:0e41f40b default
parent child Browse files
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 return "\0".join(items)
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 def stripdesc(desc):
90 def stripdesc(desc):
84 """strip trailing whitespace and leading and trailing empty lines"""
91 """strip trailing whitespace and leading and trailing empty lines"""
85 return '\n'.join([l.rstrip() for l in desc.splitlines()]).strip('\n')
92 return '\n'.join([l.rstrip() for l in desc.splitlines()]).strip('\n')
@@ -533,7 +540,7 b' class changelog(revlog.revlog):'
533 return l[3:]
540 return l[3:]
534
541
535 def add(self, manifest, files, desc, transaction, p1, p2,
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 # Convert to UTF-8 encoded bytestrings as the very first
544 # Convert to UTF-8 encoded bytestrings as the very first
538 # thing: calling any method on a localstr object will turn it
545 # thing: calling any method on a localstr object will turn it
539 # into a str object and the cached UTF-8 string is thus lost.
546 # into a str object and the cached UTF-8 string is thus lost.
@@ -562,6 +569,13 b' class changelog(revlog.revlog):'
562 elif branch in (".", "null", "tip"):
569 elif branch in (".", "null", "tip"):
563 raise error.StorageError(_('the name \'%s\' is reserved')
570 raise error.StorageError(_('the name \'%s\' is reserved')
564 % branch)
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 if extra:
579 if extra:
566 extra = encodeextra(extra)
580 extra = encodeextra(extra)
567 parseddate = "%s %s" % (parseddate, extra)
581 parseddate = "%s %s" % (parseddate, extra)
@@ -488,6 +488,9 b" coreconfigitem('experimental', 'copytrac"
488 coreconfigitem('experimental', 'copies.read-from',
488 coreconfigitem('experimental', 'copies.read-from',
489 default="filelog-only",
489 default="filelog-only",
490 )
490 )
491 coreconfigitem('experimental', 'copies.write-to',
492 default='filelog-only',
493 )
491 coreconfigitem('experimental', 'crecordtest',
494 coreconfigitem('experimental', 'crecordtest',
492 default=None,
495 default=None,
493 )
496 )
@@ -2324,7 +2324,8 b' class localrepository(object):'
2324 """Returns the wlock if it's held, or None if it's not."""
2324 """Returns the wlock if it's held, or None if it's not."""
2325 return self._currentlock(self._wlockref)
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 commit an individual file as part of a larger transaction
2330 commit an individual file as part of a larger transaction
2330 """
2331 """
@@ -2383,8 +2384,9 b' class localrepository(object):'
2383
2384
2384 if cnode:
2385 if cnode:
2385 self.ui.debug(" %s: copy %s:%s\n" % (fname, cfname, hex(cnode)))
2386 self.ui.debug(" %s: copy %s:%s\n" % (fname, cfname, hex(cnode)))
2386 meta["copy"] = cfname
2387 if includecopymeta:
2387 meta["copyrev"] = hex(cnode)
2388 meta["copy"] = cfname
2389 meta["copyrev"] = hex(cnode)
2388 fparent1, fparent2 = nullid, newfparent
2390 fparent1, fparent2 = nullid, newfparent
2389 else:
2391 else:
2390 self.ui.warn(_("warning: can't find ancestor for '%s' "
2392 self.ui.warn(_("warning: can't find ancestor for '%s' "
@@ -2552,6 +2554,12 b' class localrepository(object):'
2552 p1, p2 = ctx.p1(), ctx.p2()
2554 p1, p2 = ctx.p1(), ctx.p2()
2553 user = ctx.user()
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 with self.lock(), self.transaction("commit") as tr:
2563 with self.lock(), self.transaction("commit") as tr:
2556 trp = weakref.proxy(tr)
2564 trp = weakref.proxy(tr)
2557
2565
@@ -2585,7 +2593,8 b' class localrepository(object):'
2585 else:
2593 else:
2586 added.append(f)
2594 added.append(f)
2587 m[f] = self._filecommit(fctx, m1, m2, linkrev,
2595 m[f] = self._filecommit(fctx, m1, m2, linkrev,
2588 trp, changed)
2596 trp, changed,
2597 writefilecopymeta)
2589 m.setflag(f, fctx.flags())
2598 m.setflag(f, fctx.flags())
2590 except OSError:
2599 except OSError:
2591 self.ui.warn(_("trouble committing %s!\n") %
2600 self.ui.warn(_("trouble committing %s!\n") %
@@ -2639,7 +2648,8 b' class localrepository(object):'
2639 self.changelog.delayupdate(tr)
2648 self.changelog.delayupdate(tr)
2640 n = self.changelog.add(mn, files, ctx.description(),
2649 n = self.changelog.add(mn, files, ctx.description(),
2641 trp, p1.node(), p2.node(),
2650 trp, p1.node(), p2.node(),
2642 user, ctx.date(), ctx.extra().copy())
2651 user, ctx.date(), ctx.extra().copy(),
2652 p1copies, p2copies)
2643 xp1, xp2 = p1.hex(), p2 and p2.hex() or ''
2653 xp1, xp2 = p1.hex(), p2 and p2.hex() or ''
2644 self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
2654 self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
2645 parent2=xp2)
2655 parent2=xp2)
@@ -438,7 +438,7 b' and its ancestor by overriding "repo._fi'
438 > def reposetup(ui, repo):
438 > def reposetup(ui, repo):
439 > class legacyrepo(repo.__class__):
439 > class legacyrepo(repo.__class__):
440 > def _filecommit(self, fctx, manifest1, manifest2,
440 > def _filecommit(self, fctx, manifest1, manifest2,
441 > linkrev, tr, changelist):
441 > linkrev, tr, changelist, includecopymeta):
442 > fname = fctx.path()
442 > fname = fctx.path()
443 > text = fctx.data()
443 > text = fctx.data()
444 > flog = self.file(fname)
444 > flog = self.file(fname)
@@ -443,7 +443,7 b' and its ancestor by overriding "repo._fi'
443 > def reposetup(ui, repo):
443 > def reposetup(ui, repo):
444 > class legacyrepo(repo.__class__):
444 > class legacyrepo(repo.__class__):
445 > def _filecommit(self, fctx, manifest1, manifest2,
445 > def _filecommit(self, fctx, manifest1, manifest2,
446 > linkrev, tr, changelist):
446 > linkrev, tr, changelist, includecopymeta):
447 > fname = fctx.path()
447 > fname = fctx.path()
448 > text = fctx.data()
448 > text = fctx.data()
449 > flog = self.file(fname)
449 > flog = self.file(fname)
General Comments 0
You need to be logged in to leave comments. Login now