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