D6643: convert: add a config option to help doing identity hg->hg conversion
valentin.gatienbaron (Valentin Gatien-Baron)
phabricator at mercurial-scm.org
Thu Jul 18 01:02:04 EDT 2019
Closed by commit rHG7a44de54490a: convert: add a config option to help doing identity hg->hg conversion (authored by valentin.gatienbaron).
This revision was automatically updated to reflect the committed changes.
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D6643?vs=15916&id=15949
CHANGES SINCE LAST ACTION
https://phab.mercurial-scm.org/D6643/new/
REVISION DETAIL
https://phab.mercurial-scm.org/D6643
AFFECTED FILES
hgext/convert/__init__.py
hgext/convert/common.py
hgext/convert/hg.py
hgext/eol.py
hgext/keyword.py
hgext/lfs/__init__.py
hgext/remotefilelog/shallowrepo.py
mercurial/configitems.py
mercurial/localrepo.py
mercurial/repository.py
tests/test-commandserver.t
tests/test-convert-identity.t
tests/test-convert.t
CHANGE DETAILS
diff --git a/tests/test-convert.t b/tests/test-convert.t
--- a/tests/test-convert.t
+++ b/tests/test-convert.t
@@ -373,6 +373,11 @@
records the given string as a 'convert_source' extra value
on each commit made in the target repository. The default is
None.
+ convert.hg.preserve-hash
+ only works with mercurial sources. Make convert prevent
+ performance improvement to the list of modified files in
+ commits when such an improvement would cause the hash of a
+ commit to change. The default is False.
All Destinations
################
diff --git a/tests/test-convert-identity.t b/tests/test-convert-identity.t
new file mode 100644
--- /dev/null
+++ b/tests/test-convert-identity.t
@@ -0,0 +1,40 @@
+Testing that convert.hg.preserve-hash=true can be used to make hg
+convert from hg repo to hg repo preserve hashes, even if the
+computation of the files list in commits change slightly between hg
+versions.
+
+ $ cat <<'EOF' >> "$HGRCPATH"
+ > [extensions]
+ > convert =
+ > EOF
+ $ cat <<'EOF' > changefileslist.py
+ > from mercurial import (changelog, extensions)
+ > def wrap(orig, clog, manifest, files, *args, **kwargs):
+ > return orig(clog, manifest, ["a"], *args, **kwargs)
+ > def extsetup(ui):
+ > extensions.wrapfunction(changelog.changelog, 'add', wrap)
+ > EOF
+
+ $ hg init repo
+ $ cd repo
+ $ echo a > a; hg commit -qAm a
+ $ echo b > a; hg commit -qAm b
+ $ hg up -qr 0; echo c > c; hg commit -qAm c
+ $ hg merge -qr 1
+ $ hg commit -m_ --config extensions.x=../changefileslist.py
+ $ hg log -r . -T '{node|short} {files|json}\n'
+ c085bbe93d59 ["a"]
+
+Now that we have a commit with a files list that's not what the
+current hg version would create, check that convert either fixes it or
+keeps it depending on config:
+
+ $ hg convert -q . ../convert
+ $ hg --cwd ../convert log -r tip -T '{node|short} {files|json}\n'
+ b7c4d4bbacd3 []
+ $ rm -rf ../convert
+
+ $ hg convert -q . ../convert --config convert.hg.preserve-hash=true
+ $ hg --cwd ../convert log -r tip -T '{node|short} {files|json}\n'
+ c085bbe93d59 ["a"]
+ $ rm -rf ../convert
diff --git a/tests/test-commandserver.t b/tests/test-commandserver.t
--- a/tests/test-commandserver.t
+++ b/tests/test-commandserver.t
@@ -917,13 +917,13 @@
> raise error.Abort(b'fail after finalization')
> def reposetup(ui, repo):
> class failrepo(repo.__class__):
- > def commitctx(self, ctx, error=False):
+ > def commitctx(self, ctx, error=False, origctx=None):
> if self.ui.configbool(b'failafterfinalize', b'fail'):
> # 'sorted()' by ASCII code on category names causes
> # invoking 'fail' after finalization of changelog
> # using "'cl-%i' % id(self)" as category name
> self.currenttransaction().addfinalize(b'zzzzzzzz', fail)
- > return super(failrepo, self).commitctx(ctx, error)
+ > return super(failrepo, self).commitctx(ctx, error, origctx)
> repo.__class__ = failrepo
> EOF
diff --git a/mercurial/repository.py b/mercurial/repository.py
--- a/mercurial/repository.py
+++ b/mercurial/repository.py
@@ -1656,7 +1656,7 @@
editor=False, extra=None):
"""Add a new revision to the repository."""
- def commitctx(ctx, error=False):
+ def commitctx(ctx, error=False, origctx=None):
"""Commit a commitctx instance to the repository."""
def destroying():
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -2578,7 +2578,7 @@
return ret
@unfilteredmethod
- def commitctx(self, ctx, error=False):
+ def commitctx(self, ctx, error=False, origctx=None):
"""Add a new revision to current repository.
Revision information is passed via the context argument.
@@ -2586,6 +2586,12 @@
modified/added/removed files. On merge, it may be wider than the
ctx.files() to be committed, since any file nodes derived directly
from p1 or p2 are excluded from the committed ctx.files().
+
+ origctx is for convert to work around the problem that bug
+ fixes to the files list in changesets change hashes. For
+ convert to be the identity, it can pass an origctx and this
+ function will use the same files list when it makes sense to
+ do so.
"""
p1, p2 = ctx.p1(), ctx.p2()
@@ -2701,6 +2707,9 @@
filesadded = filesadded or None
filesremoved = filesremoved or None
+ if origctx and origctx.manifestnode() == mn:
+ files = origctx.files()
+
# update changelog
self.ui.note(_("committing changelog\n"))
self.changelog.delayupdate(tr)
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -291,6 +291,9 @@
coreconfigitem('convert', 'hg.ignoreerrors',
default=False,
)
+coreconfigitem('convert', 'hg.preserve-hash',
+ default=False,
+)
coreconfigitem('convert', 'hg.revs',
default=None,
)
diff --git a/hgext/remotefilelog/shallowrepo.py b/hgext/remotefilelog/shallowrepo.py
--- a/hgext/remotefilelog/shallowrepo.py
+++ b/hgext/remotefilelog/shallowrepo.py
@@ -161,7 +161,7 @@
**kwargs)
@localrepo.unfilteredmethod
- def commitctx(self, ctx, error=False):
+ def commitctx(self, ctx, error=False, origctx=None):
"""Add a new revision to current repository.
Revision information is passed via the context argument.
"""
@@ -179,7 +179,8 @@
files.append((f, hex(fparent1)))
self.fileservice.prefetch(files)
return super(shallowrepository, self).commitctx(ctx,
- error=error)
+ error=error,
+ origctx=origctx)
def backgroundprefetch(self, revs, base=None, repack=False, pats=None,
opts=None):
diff --git a/hgext/lfs/__init__.py b/hgext/lfs/__init__.py
--- a/hgext/lfs/__init__.py
+++ b/hgext/lfs/__init__.py
@@ -227,9 +227,9 @@
class lfsrepo(repo.__class__):
@localrepo.unfilteredmethod
- def commitctx(self, ctx, error=False):
+ def commitctx(self, ctx, error=False, origctx=None):
repo.svfs.options['lfstrack'] = _trackedmatcher(self)
- return super(lfsrepo, self).commitctx(ctx, error)
+ return super(lfsrepo, self).commitctx(ctx, error, origctx=origctx)
repo.__class__ = lfsrepo
diff --git a/hgext/keyword.py b/hgext/keyword.py
--- a/hgext/keyword.py
+++ b/hgext/keyword.py
@@ -785,8 +785,8 @@
finally:
del self.commitctx
- def kwcommitctx(self, ctx, error=False):
- n = super(kwrepo, self).commitctx(ctx, error)
+ def kwcommitctx(self, ctx, error=False, origctx=None):
+ n = super(kwrepo, self).commitctx(ctx, error, origctx)
# no lock needed, only called from repo.commit() which already locks
if not kwt.postcommit:
restrict = kwt.restrict
diff --git a/hgext/eol.py b/hgext/eol.py
--- a/hgext/eol.py
+++ b/hgext/eol.py
@@ -400,7 +400,7 @@
if wlock is not None:
wlock.release()
- def commitctx(self, ctx, error=False):
+ def commitctx(self, ctx, error=False, origctx=None):
for f in sorted(ctx.added() + ctx.modified()):
if not self._eolmatch(f):
continue
@@ -416,6 +416,6 @@
if inconsistenteol(data):
raise errormod.Abort(_("inconsistent newline style "
"in %s\n") % f)
- return super(eolrepo, self).commitctx(ctx, error)
+ return super(eolrepo, self).commitctx(ctx, error, origctx)
repo.__class__ = eolrepo
repo._hgcleardirstate()
diff --git a/hgext/convert/hg.py b/hgext/convert/hg.py
--- a/hgext/convert/hg.py
+++ b/hgext/convert/hg.py
@@ -339,7 +339,11 @@
phases.phasenames[commit.phase], 'convert')
with self.repo.transaction("convert") as tr:
- node = nodemod.hex(self.repo.commitctx(ctx))
+ if self.repo.ui.config('convert', 'hg.preserve-hash'):
+ origctx = commit.ctx
+ else:
+ origctx = None
+ node = nodemod.hex(self.repo.commitctx(ctx, origctx=origctx))
# If the node value has changed, but the phase is lower than
# draft, set it back to draft since it hasn't been exposed
@@ -591,7 +595,8 @@
extra=ctx.extra(),
sortkey=ctx.rev(),
saverev=self.saverev,
- phase=ctx.phase())
+ phase=ctx.phase(),
+ ctx=ctx)
def numcommits(self):
return len(self.repo)
diff --git a/hgext/convert/common.py b/hgext/convert/common.py
--- a/hgext/convert/common.py
+++ b/hgext/convert/common.py
@@ -114,7 +114,7 @@
class commit(object):
def __init__(self, author, date, desc, parents, branch=None, rev=None,
extra=None, sortkey=None, saverev=True, phase=phases.draft,
- optparents=None):
+ optparents=None, ctx=None):
self.author = author or 'unknown'
self.date = date or '0 0'
self.desc = desc
@@ -126,6 +126,7 @@
self.sortkey = sortkey
self.saverev = saverev
self.phase = phase
+ self.ctx = ctx # for hg to hg conversions
class converter_source(object):
"""Conversion source interface"""
diff --git a/hgext/convert/__init__.py b/hgext/convert/__init__.py
--- a/hgext/convert/__init__.py
+++ b/hgext/convert/__init__.py
@@ -439,6 +439,11 @@
:convert.hg.sourcename: records the given string as a 'convert_source' extra
value on each commit made in the target repository. The default is None.
+ :convert.hg.preserve-hash: only works with mercurial sources. Make convert
+ prevent performance improvement to the list of modified files in commits
+ when such an improvement would cause the hash of a commit to change.
+ The default is False.
+
All Destinations
################
To: valentin.gatienbaron, #hg-reviewers, mharbison72, durin42
Cc: mharbison72, mjpieters, mercurial-devel
More information about the Mercurial-devel
mailing list