Mercurial > hg
comparison mercurial/commit.py @ 45203:ae5c1a3bc339
commitctx: extract the function in a dedicated module
the function have few callers (< 15) is quite long a mostly independent from the
repository itself. It seems like a good candidate to reduce the bloatness of the
localrepository class. Extracting it will help us cleaning the code up and
splitting it into more reasonable-size function.
We don't use a copy trick because the amount of code extract is quite small
(<5%) and the de-indent means every single line change anyway. So this is not
deemed valuable to do so.
This is part of a larger refactoring/cleanup of the commitctx code to clarify
and augment the logic gathering metadata useful for copy tracing. The current
code is a tad too long and entangled to make such update easy.
Differential Revision: https://phab.mercurial-scm.org/D8709
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Mon, 06 Jul 2020 23:14:52 +0200 |
parents | |
children | ce9ee81df9ff |
comparison
equal
deleted
inserted
replaced
45202:31393ec06cef | 45203:ae5c1a3bc339 |
---|---|
1 # commit.py - fonction to perform commit | |
2 # | |
3 # This software may be used and distributed according to the terms of the | |
4 # GNU General Public License version 2 or any later version. | |
5 | |
6 from __future__ import absolute_import | |
7 | |
8 import errno | |
9 import weakref | |
10 | |
11 from .i18n import _ | |
12 from .node import ( | |
13 hex, | |
14 nullrev, | |
15 ) | |
16 | |
17 from . import ( | |
18 metadata, | |
19 phases, | |
20 scmutil, | |
21 subrepoutil, | |
22 ) | |
23 | |
24 | |
25 def commitctx(repo, ctx, error=False, origctx=None): | |
26 """Add a new revision to the target repository. | |
27 Revision information is passed via the context argument. | |
28 | |
29 ctx.files() should list all files involved in this commit, i.e. | |
30 modified/added/removed files. On merge, it may be wider than the | |
31 ctx.files() to be committed, since any file nodes derived directly | |
32 from p1 or p2 are excluded from the committed ctx.files(). | |
33 | |
34 origctx is for convert to work around the problem that bug | |
35 fixes to the files list in changesets change hashes. For | |
36 convert to be the identity, it can pass an origctx and this | |
37 function will use the same files list when it makes sense to | |
38 do so. | |
39 """ | |
40 repo = repo.unfiltered() | |
41 | |
42 p1, p2 = ctx.p1(), ctx.p2() | |
43 user = ctx.user() | |
44 | |
45 if repo.filecopiesmode == b'changeset-sidedata': | |
46 writechangesetcopy = True | |
47 writefilecopymeta = True | |
48 writecopiesto = None | |
49 else: | |
50 writecopiesto = repo.ui.config(b'experimental', b'copies.write-to') | |
51 writefilecopymeta = writecopiesto != b'changeset-only' | |
52 writechangesetcopy = writecopiesto in ( | |
53 b'changeset-only', | |
54 b'compatibility', | |
55 ) | |
56 p1copies, p2copies = None, None | |
57 if writechangesetcopy: | |
58 p1copies = ctx.p1copies() | |
59 p2copies = ctx.p2copies() | |
60 filesadded, filesremoved = None, None | |
61 with repo.lock(), repo.transaction(b"commit") as tr: | |
62 trp = weakref.proxy(tr) | |
63 | |
64 if ctx.manifestnode(): | |
65 # reuse an existing manifest revision | |
66 repo.ui.debug(b'reusing known manifest\n') | |
67 mn = ctx.manifestnode() | |
68 files = ctx.files() | |
69 if writechangesetcopy: | |
70 filesadded = ctx.filesadded() | |
71 filesremoved = ctx.filesremoved() | |
72 elif not ctx.files(): | |
73 repo.ui.debug(b'reusing manifest from p1 (no file change)\n') | |
74 mn = p1.manifestnode() | |
75 files = [] | |
76 else: | |
77 m1ctx = p1.manifestctx() | |
78 m2ctx = p2.manifestctx() | |
79 mctx = m1ctx.copy() | |
80 | |
81 m = mctx.read() | |
82 m1 = m1ctx.read() | |
83 m2 = m2ctx.read() | |
84 | |
85 # check in files | |
86 added = [] | |
87 filesadded = [] | |
88 removed = list(ctx.removed()) | |
89 touched = [] | |
90 linkrev = len(repo) | |
91 repo.ui.note(_(b"committing files:\n")) | |
92 uipathfn = scmutil.getuipathfn(repo) | |
93 for f in sorted(ctx.modified() + ctx.added()): | |
94 repo.ui.note(uipathfn(f) + b"\n") | |
95 try: | |
96 fctx = ctx[f] | |
97 if fctx is None: | |
98 removed.append(f) | |
99 else: | |
100 added.append(f) | |
101 m[f], is_touched = repo._filecommit( | |
102 fctx, m1, m2, linkrev, trp, writefilecopymeta, | |
103 ) | |
104 if is_touched: | |
105 touched.append(f) | |
106 if writechangesetcopy and is_touched == 'added': | |
107 filesadded.append(f) | |
108 m.setflag(f, fctx.flags()) | |
109 except OSError: | |
110 repo.ui.warn(_(b"trouble committing %s!\n") % uipathfn(f)) | |
111 raise | |
112 except IOError as inst: | |
113 errcode = getattr(inst, 'errno', errno.ENOENT) | |
114 if error or errcode and errcode != errno.ENOENT: | |
115 repo.ui.warn( | |
116 _(b"trouble committing %s!\n") % uipathfn(f) | |
117 ) | |
118 raise | |
119 | |
120 # update manifest | |
121 removed = [f for f in removed if f in m1 or f in m2] | |
122 drop = sorted([f for f in removed if f in m]) | |
123 for f in drop: | |
124 del m[f] | |
125 if p2.rev() != nullrev: | |
126 rf = metadata.get_removal_filter(ctx, (p1, p2, m1, m2)) | |
127 removed = [f for f in removed if not rf(f)] | |
128 | |
129 touched.extend(removed) | |
130 | |
131 if writechangesetcopy: | |
132 filesremoved = removed | |
133 | |
134 files = touched | |
135 md = None | |
136 if not files: | |
137 # if no "files" actually changed in terms of the changelog, | |
138 # try hard to detect unmodified manifest entry so that the | |
139 # exact same commit can be reproduced later on convert. | |
140 md = m1.diff(m, scmutil.matchfiles(repo, ctx.files())) | |
141 if not files and md: | |
142 repo.ui.debug( | |
143 b'not reusing manifest (no file change in ' | |
144 b'changelog, but manifest differs)\n' | |
145 ) | |
146 if files or md: | |
147 repo.ui.note(_(b"committing manifest\n")) | |
148 # we're using narrowmatch here since it's already applied at | |
149 # other stages (such as dirstate.walk), so we're already | |
150 # ignoring things outside of narrowspec in most cases. The | |
151 # one case where we might have files outside the narrowspec | |
152 # at this point is merges, and we already error out in the | |
153 # case where the merge has files outside of the narrowspec, | |
154 # so this is safe. | |
155 mn = mctx.write( | |
156 trp, | |
157 linkrev, | |
158 p1.manifestnode(), | |
159 p2.manifestnode(), | |
160 added, | |
161 drop, | |
162 match=repo.narrowmatch(), | |
163 ) | |
164 else: | |
165 repo.ui.debug( | |
166 b'reusing manifest from p1 (listed files ' | |
167 b'actually unchanged)\n' | |
168 ) | |
169 mn = p1.manifestnode() | |
170 | |
171 if writecopiesto == b'changeset-only': | |
172 # If writing only to changeset extras, use None to indicate that | |
173 # no entry should be written. If writing to both, write an empty | |
174 # entry to prevent the reader from falling back to reading | |
175 # filelogs. | |
176 p1copies = p1copies or None | |
177 p2copies = p2copies or None | |
178 filesadded = filesadded or None | |
179 filesremoved = filesremoved or None | |
180 | |
181 if origctx and origctx.manifestnode() == mn: | |
182 files = origctx.files() | |
183 | |
184 # update changelog | |
185 repo.ui.note(_(b"committing changelog\n")) | |
186 repo.changelog.delayupdate(tr) | |
187 n = repo.changelog.add( | |
188 mn, | |
189 files, | |
190 ctx.description(), | |
191 trp, | |
192 p1.node(), | |
193 p2.node(), | |
194 user, | |
195 ctx.date(), | |
196 ctx.extra().copy(), | |
197 p1copies, | |
198 p2copies, | |
199 filesadded, | |
200 filesremoved, | |
201 ) | |
202 xp1, xp2 = p1.hex(), p2 and p2.hex() or b'' | |
203 repo.hook( | |
204 b'pretxncommit', throw=True, node=hex(n), parent1=xp1, parent2=xp2, | |
205 ) | |
206 # set the new commit is proper phase | |
207 targetphase = subrepoutil.newcommitphase(repo.ui, ctx) | |
208 if targetphase: | |
209 # retract boundary do not alter parent changeset. | |
210 # if a parent have higher the resulting phase will | |
211 # be compliant anyway | |
212 # | |
213 # if minimal phase was 0 we don't need to retract anything | |
214 phases.registernew(repo, tr, targetphase, [n]) | |
215 return n |