mergestate reading although cheap is not free. Let's read mergestate once on top
and pass it into _filecommit().
In upcoming patches, we will be reading mergestate more in _filecommit().
marmoute |
hg-reviewers |
mergestate reading although cheap is not free. Let's read mergestate once on top
and pass it into _filecommit().
In upcoming patches, we will be reading mergestate more in _filecommit().
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
Path | Packages | |||
---|---|---|---|---|
M | mercurial/commit.py (12 lines) | |||
M | tests/test-annotate.t (2 lines) | |||
M | tests/test-fastannotate-hg.t (2 lines) |
m1ctx = p1.manifestctx() | m1ctx = p1.manifestctx() | ||||
m2ctx = p2.manifestctx() | m2ctx = p2.manifestctx() | ||||
mctx = m1ctx.copy() | mctx = m1ctx.copy() | ||||
m = mctx.read() | m = mctx.read() | ||||
m1 = m1ctx.read() | m1 = m1ctx.read() | ||||
m2 = m2ctx.read() | m2 = m2ctx.read() | ||||
ms = mergestate.mergestate.read(repo) | |||||
files = metadata.ChangingFiles() | files = metadata.ChangingFiles() | ||||
# check in files | # check in files | ||||
added = [] | added = [] | ||||
removed = list(ctx.removed()) | removed = list(ctx.removed()) | ||||
linkrev = len(repo) | linkrev = len(repo) | ||||
repo.ui.note(_(b"committing files:\n")) | repo.ui.note(_(b"committing files:\n")) | ||||
uipathfn = scmutil.getuipathfn(repo) | uipathfn = scmutil.getuipathfn(repo) | ||||
for f in sorted(ctx.modified() + ctx.added()): | for f in sorted(ctx.modified() + ctx.added()): | ||||
repo.ui.note(uipathfn(f) + b"\n") | repo.ui.note(uipathfn(f) + b"\n") | ||||
try: | try: | ||||
fctx = ctx[f] | fctx = ctx[f] | ||||
if fctx is None: | if fctx is None: | ||||
removed.append(f) | removed.append(f) | ||||
else: | else: | ||||
added.append(f) | added.append(f) | ||||
m[f], is_touched = _filecommit( | m[f], is_touched = _filecommit( | ||||
repo, fctx, m1, m2, linkrev, tr, writefilecopymeta, | repo, fctx, m1, m2, linkrev, tr, writefilecopymeta, ms | ||||
) | ) | ||||
if is_touched: | if is_touched: | ||||
if is_touched == 'added': | if is_touched == 'added': | ||||
files.mark_added(f) | files.mark_added(f) | ||||
else: | else: | ||||
files.mark_touched(f) | files.mark_touched(f) | ||||
m.setflag(f, fctx.flags()) | m.setflag(f, fctx.flags()) | ||||
except OSError: | except OSError: | ||||
files.mark_removed(f) | files.mark_removed(f) | ||||
mn = _commit_manifest(tr, linkrev, ctx, mctx, m, files.touched, added, drop) | mn = _commit_manifest(tr, linkrev, ctx, mctx, m, files.touched, added, drop) | ||||
return mn, files | return mn, files | ||||
def _filecommit( | def _filecommit( | ||||
repo, fctx, manifest1, manifest2, linkrev, tr, includecopymeta, | repo, fctx, manifest1, manifest2, linkrev, tr, includecopymeta, ms, | ||||
): | ): | ||||
""" | """ | ||||
commit an individual file as part of a larger transaction | commit an individual file as part of a larger transaction | ||||
input: | input: | ||||
fctx: a file context with the content we are trying to commit | fctx: a file context with the content we are trying to commit | ||||
manifest1: manifest of changeset first parent | manifest1: manifest of changeset first parent | ||||
manifest2: manifest of changeset second parent | manifest2: manifest of changeset second parent | ||||
linkrev: revision number of the changeset being created | linkrev: revision number of the changeset being created | ||||
tr: current transation | tr: current transation | ||||
includecopymeta: boolean, set to False to skip storing the copy data | includecopymeta: boolean, set to False to skip storing the copy data | ||||
(only used by the Google specific feature of using | (only used by the Google specific feature of using | ||||
changeset extra as copy source of truth). | changeset extra as copy source of truth). | ||||
ms: mergestate object | |||||
output: (filenode, touched) | output: (filenode, touched) | ||||
filenode: the filenode that should be used by this changeset | filenode: the filenode that should be used by this changeset | ||||
touched: one of: None (mean untouched), 'added' or 'modified' | touched: one of: None (mean untouched), 'added' or 'modified' | ||||
""" | """ | ||||
fname = fctx.path() | fname = fctx.path() | ||||
# is one parent an ancestor of the other? | # is one parent an ancestor of the other? | ||||
fparentancestors = flog.commonancestorsheads(fparent1, fparent2) | fparentancestors = flog.commonancestorsheads(fparent1, fparent2) | ||||
if fparent1 in fparentancestors: | if fparent1 in fparentancestors: | ||||
fparent1, fparent2 = fparent2, nullid | fparent1, fparent2 = fparent2, nullid | ||||
elif fparent2 in fparentancestors: | elif fparent2 in fparentancestors: | ||||
fparent2 = nullid | fparent2 = nullid | ||||
elif not fparentancestors: | elif not fparentancestors: | ||||
# TODO: this whole if-else might be simplified much more | # TODO: this whole if-else might be simplified much more | ||||
ms = mergestate.mergestate.read(repo) | if ( | ||||
if ms.extras(fname).get(b'filenode-source') == b'other': | ms.active() | ||||
and ms.extras(fname).get(b'filenode-source') == b'other' | |||||
): | |||||
fparent1, fparent2 = fparent2, nullid | fparent1, fparent2 = fparent2, nullid | ||||
# is the file changed? | # is the file changed? | ||||
text = fctx.data() | text = fctx.data() | ||||
if fparent2 != nullid or meta or flog.cmp(fparent1, text): | if fparent2 != nullid or meta or flog.cmp(fparent1, text): | ||||
if touched is None: # do not overwrite added | if touched is None: # do not overwrite added | ||||
touched = 'modified' | touched = 'modified' | ||||
fnode = flog.add(text, meta, tr, linkrev, fparent1, fparent2) | fnode = flog.add(text, meta, tr, linkrev, fparent1, fparent2) |
"hg debugsetparents" to merge without ancestor check by "hg merge", | "hg debugsetparents" to merge without ancestor check by "hg merge", | ||||
and (2) the extension to allow filelog merging between the revision | and (2) the extension to allow filelog merging between the revision | ||||
and its ancestor by overriding "repo._filecommit". | and its ancestor by overriding "repo._filecommit". | ||||
$ cat > ../legacyrepo.py <<EOF | $ cat > ../legacyrepo.py <<EOF | ||||
> from __future__ import absolute_import | > from __future__ import absolute_import | ||||
> from mercurial import commit, error, extensions, node | > from mercurial import commit, error, extensions, node | ||||
> def _filecommit(orig, repo, fctx, manifest1, manifest2, | > def _filecommit(orig, repo, fctx, manifest1, manifest2, | ||||
> linkrev, tr, includecopymeta): | > linkrev, tr, includecopymeta, ms): | ||||
> fname = fctx.path() | > fname = fctx.path() | ||||
> text = fctx.data() | > text = fctx.data() | ||||
> flog = repo.file(fname) | > flog = repo.file(fname) | ||||
> fparent1 = manifest1.get(fname, node.nullid) | > fparent1 = manifest1.get(fname, node.nullid) | ||||
> fparent2 = manifest2.get(fname, node.nullid) | > fparent2 = manifest2.get(fname, node.nullid) | ||||
> meta = {} | > meta = {} | ||||
> copy = fctx.copysource() | > copy = fctx.copysource() | ||||
> if copy and copy != fname: | > if copy and copy != fname: |
"hg debugsetparents" to merge without ancestor check by "hg merge", | "hg debugsetparents" to merge without ancestor check by "hg merge", | ||||
and (2) the extension to allow filelog merging between the revision | and (2) the extension to allow filelog merging between the revision | ||||
and its ancestor by overriding "repo._filecommit". | and its ancestor by overriding "repo._filecommit". | ||||
$ cat > ../legacyrepo.py <<EOF | $ cat > ../legacyrepo.py <<EOF | ||||
> from __future__ import absolute_import | > from __future__ import absolute_import | ||||
> from mercurial import commit, error, extensions, node | > from mercurial import commit, error, extensions, node | ||||
> def _filecommit(orig, repo, fctx, manifest1, manifest2, | > def _filecommit(orig, repo, fctx, manifest1, manifest2, | ||||
> linkrev, tr, includecopymeta): | > linkrev, tr, includecopymeta, ms): | ||||
> fname = fctx.path() | > fname = fctx.path() | ||||
> text = fctx.data() | > text = fctx.data() | ||||
> flog = repo.file(fname) | > flog = repo.file(fname) | ||||
> fparent1 = manifest1.get(fname, node.nullid) | > fparent1 = manifest1.get(fname, node.nullid) | ||||
> fparent2 = manifest2.get(fname, node.nullid) | > fparent2 = manifest2.get(fname, node.nullid) | ||||
> meta = {} | > meta = {} | ||||
> copy = fctx.copysource() | > copy = fctx.copysource() | ||||
> if copy and copy != fname: | > if copy and copy != fname: |