D6186: changelog: parse copy metadata if available in extras
martinvonz (Martin von Zweigbergk)
phabricator at mercurial-scm.org
Sat Apr 13 18:21:45 EDT 2019
martinvonz updated this revision to Diff 14737.
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D6186?vs=14736&id=14737
REVISION DETAIL
https://phab.mercurial-scm.org/D6186
AFFECTED FILES
mercurial/changelog.py
mercurial/context.py
mercurial/copies.py
tests/test-copies-in-changeset.t
tests/test-copies.t
CHANGE DETAILS
diff --git a/tests/test-copies.t b/tests/test-copies.t
--- a/tests/test-copies.t
+++ b/tests/test-copies.t
@@ -1,4 +1,4 @@
-#testcases filelog compatibility
+#testcases filelog compatibility changeset
$ cat >> $HGRCPATH << EOF
> [extensions]
@@ -14,6 +14,14 @@
> EOF
#endif
+#if changeset
+ $ cat >> $HGRCPATH << EOF
+ > [experimental]
+ > copies.read-from = changeset-only
+ > copies.write-to = changeset-only
+ > EOF
+#endif
+
$ REPONUM=0
$ newrepo() {
> cd $TESTTMP
@@ -376,11 +384,13 @@
o 0 add x on branch 1
x
$ hg debugp1copies -r 2
+ x -> z (changeset !)
$ hg debugp2copies -r 2
- x -> z
+ x -> z (no-changeset !)
$ hg debugpathcopies 1 2
+ x -> z (changeset !)
$ hg debugpathcopies 0 2
- x -> z
+ x -> z (no-changeset !)
Copy x->y on one side of merge and copy x->z on the other side. Pathcopies from one parent
of the merge to the merge should include the copy from the other side.
@@ -539,6 +549,9 @@
Grafting revision 4 on top of revision 2, showing that it respect the rename:
+TODO: Make this work with copy info in changesets (probably by writing a
+changeset-centric version of copies.mergecopies())
+#if no-changeset
$ hg up 2 -q
$ hg graft -r 4 --base 3 --hidden
grafting 4:af28412ec03c "added d, modified b" (tip)
@@ -554,6 +567,8 @@
b
+baba
+#endif
+
Test to make sure that fullcopytracing algorithm don't fail when both the merging csets are dirty
(a dirty cset is one who is not the descendant of merge base)
-------------------------------------------------------------------------------------------------
diff --git a/tests/test-copies-in-changeset.t b/tests/test-copies-in-changeset.t
--- a/tests/test-copies-in-changeset.t
+++ b/tests/test-copies-in-changeset.t
@@ -2,9 +2,11 @@
$ cat >> $HGRCPATH << EOF
> [experimental]
> copies.write-to=changeset-only
+ > copies.read-from=changeset-only
> [alias]
> changesetcopies = log -r . -T 'files: {files}
> {extras % "{ifcontains("copies", key, "{key}: {value}\n")}"}'
+ > showcopies = log -r . -T '{file_copies % "{source} -> {name}\n"}'
> EOF
Check that copies are recorded correctly
@@ -23,14 +25,25 @@
p1copies: b\x00a (esc)
c\x00a (esc)
d\x00a (esc)
+ $ hg showcopies
+ a -> b
+ a -> c
+ a -> d
+ $ hg showcopies --config experimental.copies.read-from=compatibility
+ a -> b
+ a -> c
+ a -> d
+ $ hg showcopies --config experimental.copies.read-from=filelog-only
Check that renames are recorded correctly
$ hg mv b b2
$ hg ci -m 'rename b to b2'
$ hg changesetcopies
files: b b2
p1copies: b2\x00b (esc)
+ $ hg showcopies
+ b -> b2
Rename onto existing file. This should get recorded in the changeset files list and in the extras,
even though there is no filelog entry.
@@ -46,6 +59,8 @@
$ hg changesetcopies
files: c
p1copies: c\x00b2 (esc)
+ $ hg showcopies
+ b2 -> c
$ hg debugindex c
rev linkrev nodeid p1 p2
0 1 b789fdd96dc2 000000000000 000000000000
@@ -74,6 +89,10 @@
p1copies: g\x00a (esc)
i\x00f (esc)
p2copies: h\x00d (esc)
+ $ hg showcopies
+ a -> g
+ d -> h
+ f -> i
Test writing to both changeset and filelog
@@ -88,6 +107,12 @@
copyrev: b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
\x01 (esc)
a
+ $ hg showcopies
+ a -> j
+ $ hg showcopies --config experimental.copies.read-from=compatibility
+ a -> j
+ $ hg showcopies --config experimental.copies.read-from=filelog-only
+ a -> j
Test writing only to filelog
@@ -101,5 +126,10 @@
copyrev: b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
\x01 (esc)
a
+ $ hg showcopies
+ $ hg showcopies --config experimental.copies.read-from=compatibility
+ a -> k
+ $ hg showcopies --config experimental.copies.read-from=filelog-only
+ a -> k
$ cd ..
diff --git a/mercurial/copies.py b/mercurial/copies.py
--- a/mercurial/copies.py
+++ b/mercurial/copies.py
@@ -162,8 +162,8 @@
def usechangesetcentricalgo(repo):
"""Checks if we should use changeset-centric copy algorithms"""
- return (repo.ui.config('experimental', 'copies.read-from') ==
- 'compatibility')
+ return (repo.ui.config('experimental', 'copies.read-from') in
+ ('changeset-only', 'compatibility'))
def _committedforwardcopies(a, b, match):
"""Like _forwardcopies(), but b.rev() cannot be None (working copy)"""
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -441,6 +441,21 @@
return self._changeset.files
@propertycache
def _copies(self):
+ source = self._repo.ui.config('experimental', 'copies.read-from')
+ p1copies = self._changeset.p1copies
+ p2copies = self._changeset.p2copies
+ # If config says to get copy metadata only from changeset, then return
+ # that, defaulting to {} if there was no copy metadata.
+ # In compatibility mode, we return copy data from the changeset if
+ # it was recorded there, and otherwise we fall back to getting it from
+ # the filelogs (below).
+ if (source == 'changeset-only' or
+ (source == 'compatibility' and p1copies is not None)):
+ return p1copies or {}, p2copies or {}
+
+ # Otherwise (config said to read only from filelog, or we are in
+ # compatiblity mode and there is not data in the changeset), we get
+ # the copy metadata from the filelogs.
p1copies = {}
p2copies = {}
p1 = self.p1()
diff --git a/mercurial/changelog.py b/mercurial/changelog.py
--- a/mercurial/changelog.py
+++ b/mercurial/changelog.py
@@ -87,6 +87,18 @@
]
return "\n".join(items)
+def decodecopies(data):
+ try:
+ copies = {}
+ for l in data.split('\n'):
+ k, v = l.split('\0')
+ copies[_string_unescape(k)] = _string_unescape(v)
+ return copies
+ except ValueError:
+ # Perhaps someone had chosen the same key name (e.g. "p1copies") and
+ # used different syntax for the value.
+ return None
+
def stripdesc(desc):
"""strip trailing whitespace and leading and trailing empty lines"""
return '\n'.join([l.rstrip() for l in desc.splitlines()]).strip('\n')
@@ -286,6 +298,16 @@
return self._text[off[2] + 1:off[3]].split('\n')
@property
+ def p1copies(self):
+ rawcopies = self.extra.get('p1copies')
+ return rawcopies and decodecopies(rawcopies)
+
+ @property
+ def p2copies(self):
+ rawcopies = self.extra.get('p2copies')
+ return rawcopies and decodecopies(rawcopies)
+
+ @property
def description(self):
return encoding.tolocal(self._text[self._offsets[3] + 2:])
To: martinvonz, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list