Mercurial > hg
comparison mercurial/localrepo.py @ 39111:46da52f4b820
commit: try hard to reuse p1 manifest if nothing changed
This is all for commit reproducibility on "hg convert".
With this change, p1 manifest is reused if ctx.files() *to be committed* is
empty, and if new manifest entry is identical to p1. This is important
property for "hg convert" since memctx.files() built from a convert source
may be either a) more narrowed thanks to a committed ctx.files() which
provides more accurate status, or b) containing redundant files because of
sloppy filtering on e.g. octopus merge.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sat, 07 Jul 2018 22:40:39 +0900 |
parents | a915db9a5e77 |
children | 7a9f15ed3b96 |
comparison
equal
deleted
inserted
replaced
39110:f0c2653ca706 | 39111:46da52f4b820 |
---|---|
2037 | 2037 |
2038 @unfilteredmethod | 2038 @unfilteredmethod |
2039 def commitctx(self, ctx, error=False): | 2039 def commitctx(self, ctx, error=False): |
2040 """Add a new revision to current repository. | 2040 """Add a new revision to current repository. |
2041 Revision information is passed via the context argument. | 2041 Revision information is passed via the context argument. |
2042 | |
2043 ctx.files() should list all files involved in this commit, i.e. | |
2044 modified/added/removed files. On merge, it may be wider than the | |
2045 ctx.files() to be committed, since any file nodes derived directly | |
2046 from p1 or p2 are excluded from the committed ctx.files(). | |
2042 """ | 2047 """ |
2043 | 2048 |
2044 tr = None | 2049 tr = None |
2045 p1, p2 = ctx.p1(), ctx.p2() | 2050 p1, p2 = ctx.p1(), ctx.p2() |
2046 user = ctx.user() | 2051 user = ctx.user() |
2089 if error or errcode and errcode != errno.ENOENT: | 2094 if error or errcode and errcode != errno.ENOENT: |
2090 self.ui.warn(_("trouble committing %s!\n") % f) | 2095 self.ui.warn(_("trouble committing %s!\n") % f) |
2091 raise | 2096 raise |
2092 | 2097 |
2093 # update manifest | 2098 # update manifest |
2094 self.ui.note(_("committing manifest\n")) | |
2095 removed = [f for f in sorted(removed) if f in m1 or f in m2] | 2099 removed = [f for f in sorted(removed) if f in m1 or f in m2] |
2096 drop = [f for f in removed if f in m] | 2100 drop = [f for f in removed if f in m] |
2097 for f in drop: | 2101 for f in drop: |
2098 del m[f] | 2102 del m[f] |
2099 mn = mctx.write(trp, linkrev, | |
2100 p1.manifestnode(), p2.manifestnode(), | |
2101 added, drop) | |
2102 files = changed + removed | 2103 files = changed + removed |
2104 md = None | |
2105 if not files: | |
2106 # if no "files" actually changed in terms of the changelog, | |
2107 # try hard to detect unmodified manifest entry so that the | |
2108 # exact same commit can be reproduced later on convert. | |
2109 md = m1.diff(m, scmutil.matchfiles(self, ctx.files())) | |
2110 if not files and md: | |
2111 self.ui.debug('not reusing manifest (no file change in ' | |
2112 'changelog, but manifest differs)\n') | |
2113 if files or md: | |
2114 self.ui.note(_("committing manifest\n")) | |
2115 mn = mctx.write(trp, linkrev, | |
2116 p1.manifestnode(), p2.manifestnode(), | |
2117 added, drop) | |
2118 else: | |
2119 self.ui.debug('reusing manifest form p1 (listed files ' | |
2120 'actually unchanged)\n') | |
2121 mn = p1.manifestnode() | |
2103 else: | 2122 else: |
2104 self.ui.debug('reusing manifest from p1 (no file change)\n') | 2123 self.ui.debug('reusing manifest from p1 (no file change)\n') |
2105 mn = p1.manifestnode() | 2124 mn = p1.manifestnode() |
2106 files = [] | 2125 files = [] |
2107 | 2126 |