##// END OF EJS Templates
commitctx: extract all the manual logic to process the files...
marmoute -
r45794:0c468fef default
parent child Browse files
Show More
@@ -1,390 +1,399
1 # commit.py - fonction to perform commit
1 # commit.py - fonction to perform commit
2 #
2 #
3 # This software may be used and distributed according to the terms of the
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.
4 # GNU General Public License version 2 or any later version.
5
5
6 from __future__ import absolute_import
6 from __future__ import absolute_import
7
7
8 import errno
8 import errno
9
9
10 from .i18n import _
10 from .i18n import _
11 from .node import (
11 from .node import (
12 hex,
12 hex,
13 nullid,
13 nullid,
14 nullrev,
14 nullrev,
15 )
15 )
16
16
17 from . import (
17 from . import (
18 context,
18 context,
19 mergestate,
19 mergestate,
20 metadata,
20 metadata,
21 phases,
21 phases,
22 scmutil,
22 scmutil,
23 subrepoutil,
23 subrepoutil,
24 )
24 )
25
25
26
26
27 def _write_copy_meta(repo):
27 def _write_copy_meta(repo):
28 """return a (changelog, filelog) boolean tuple
28 """return a (changelog, filelog) boolean tuple
29
29
30 changelog: copy related information should be stored in the changeset
30 changelog: copy related information should be stored in the changeset
31 filelof: copy related information should be written in the file revision
31 filelof: copy related information should be written in the file revision
32 """
32 """
33 if repo.filecopiesmode == b'changeset-sidedata':
33 if repo.filecopiesmode == b'changeset-sidedata':
34 writechangesetcopy = True
34 writechangesetcopy = True
35 writefilecopymeta = True
35 writefilecopymeta = True
36 else:
36 else:
37 writecopiesto = repo.ui.config(b'experimental', b'copies.write-to')
37 writecopiesto = repo.ui.config(b'experimental', b'copies.write-to')
38 writefilecopymeta = writecopiesto != b'changeset-only'
38 writefilecopymeta = writecopiesto != b'changeset-only'
39 writechangesetcopy = writecopiesto in (
39 writechangesetcopy = writecopiesto in (
40 b'changeset-only',
40 b'changeset-only',
41 b'compatibility',
41 b'compatibility',
42 )
42 )
43 return writechangesetcopy, writefilecopymeta
43 return writechangesetcopy, writefilecopymeta
44
44
45
45
46 def commitctx(repo, ctx, error=False, origctx=None):
46 def commitctx(repo, ctx, error=False, origctx=None):
47 """Add a new revision to the target repository.
47 """Add a new revision to the target repository.
48 Revision information is passed via the context argument.
48 Revision information is passed via the context argument.
49
49
50 ctx.files() should list all files involved in this commit, i.e.
50 ctx.files() should list all files involved in this commit, i.e.
51 modified/added/removed files. On merge, it may be wider than the
51 modified/added/removed files. On merge, it may be wider than the
52 ctx.files() to be committed, since any file nodes derived directly
52 ctx.files() to be committed, since any file nodes derived directly
53 from p1 or p2 are excluded from the committed ctx.files().
53 from p1 or p2 are excluded from the committed ctx.files().
54
54
55 origctx is for convert to work around the problem that bug
55 origctx is for convert to work around the problem that bug
56 fixes to the files list in changesets change hashes. For
56 fixes to the files list in changesets change hashes. For
57 convert to be the identity, it can pass an origctx and this
57 convert to be the identity, it can pass an origctx and this
58 function will use the same files list when it makes sense to
58 function will use the same files list when it makes sense to
59 do so.
59 do so.
60 """
60 """
61 repo = repo.unfiltered()
61 repo = repo.unfiltered()
62
62
63 p1, p2 = ctx.p1(), ctx.p2()
63 p1, p2 = ctx.p1(), ctx.p2()
64 user = ctx.user()
64 user = ctx.user()
65
65
66 writechangesetcopy, writefilecopymeta = _write_copy_meta(repo)
66 writechangesetcopy, writefilecopymeta = _write_copy_meta(repo)
67
67
68 p1copies, p2copies = None, None
68 p1copies, p2copies = None, None
69 if writechangesetcopy:
69 if writechangesetcopy:
70 p1copies = ctx.p1copies()
70 p1copies = ctx.p1copies()
71 p2copies = ctx.p2copies()
71 p2copies = ctx.p2copies()
72 filesadded, filesremoved = None, None
72 filesadded, filesremoved = None, None
73 with repo.lock(), repo.transaction(b"commit") as tr:
73 with repo.lock(), repo.transaction(b"commit") as tr:
74 if ctx.manifestnode():
74 if ctx.manifestnode():
75 # reuse an existing manifest revision
75 # reuse an existing manifest revision
76 repo.ui.debug(b'reusing known manifest\n')
76 repo.ui.debug(b'reusing known manifest\n')
77 mn = ctx.manifestnode()
77 mn = ctx.manifestnode()
78 files = ctx.files()
78 files = ctx.files()
79 if writechangesetcopy:
79 if writechangesetcopy:
80 filesadded = ctx.filesadded()
80 filesadded = ctx.filesadded()
81 filesremoved = ctx.filesremoved()
81 filesremoved = ctx.filesremoved()
82 elif not ctx.files():
82 elif not ctx.files():
83 repo.ui.debug(b'reusing manifest from p1 (no file change)\n')
83 repo.ui.debug(b'reusing manifest from p1 (no file change)\n')
84 mn = p1.manifestnode()
84 mn = p1.manifestnode()
85 files = []
85 files = []
86 else:
86 else:
87 m1ctx = p1.manifestctx()
87 mn, files, added, removed = _process_files(tr, ctx, error=error)
88 m2ctx = p2.manifestctx()
89 mctx = m1ctx.copy()
90
91 m = mctx.read()
92 m1 = m1ctx.read()
93 m2 = m2ctx.read()
94
95 # check in files
96 added = []
97 files_added = []
98 removed = list(ctx.removed())
99 touched = []
100 linkrev = len(repo)
101 repo.ui.note(_(b"committing files:\n"))
102 uipathfn = scmutil.getuipathfn(repo)
103 for f in sorted(ctx.modified() + ctx.added()):
104 repo.ui.note(uipathfn(f) + b"\n")
105 try:
106 fctx = ctx[f]
107 if fctx is None:
108 removed.append(f)
109 else:
110 added.append(f)
111 m[f], is_touched = _filecommit(
112 repo, fctx, m1, m2, linkrev, tr, writefilecopymeta,
113 )
114 if is_touched:
115 touched.append(f)
116 if is_touched == 'added':
117 files_added.append(f)
118 m.setflag(f, fctx.flags())
119 except OSError:
120 repo.ui.warn(_(b"trouble committing %s!\n") % uipathfn(f))
121 raise
122 except IOError as inst:
123 errcode = getattr(inst, 'errno', errno.ENOENT)
124 if error or errcode and errcode != errno.ENOENT:
125 repo.ui.warn(
126 _(b"trouble committing %s!\n") % uipathfn(f)
127 )
128 raise
129
130 # update manifest
131 removed = [f for f in removed if f in m1 or f in m2]
132 drop = sorted([f for f in removed if f in m])
133 for f in drop:
134 del m[f]
135 if p2.rev() != nullrev:
136 rf = metadata.get_removal_filter(ctx, (p1, p2, m1, m2))
137 removed = [f for f in removed if not rf(f)]
138
139 touched.extend(removed)
140
141 files = touched
142 mn = _commit_manifest(tr, linkrev, ctx, mctx, files, added, drop)
143
144 if writechangesetcopy:
88 if writechangesetcopy:
145 filesremoved = removed
89 filesremoved = removed
146 filesadded = files_added
90 filesadded = added
147
91
148 if not writefilecopymeta:
92 if not writefilecopymeta:
149 # If writing only to changeset extras, use None to indicate that
93 # If writing only to changeset extras, use None to indicate that
150 # no entry should be written. If writing to both, write an empty
94 # no entry should be written. If writing to both, write an empty
151 # entry to prevent the reader from falling back to reading
95 # entry to prevent the reader from falling back to reading
152 # filelogs.
96 # filelogs.
153 p1copies = p1copies or None
97 p1copies = p1copies or None
154 p2copies = p2copies or None
98 p2copies = p2copies or None
155 filesadded = filesadded or None
99 filesadded = filesadded or None
156 filesremoved = filesremoved or None
100 filesremoved = filesremoved or None
157
101
158 if origctx and origctx.manifestnode() == mn:
102 if origctx and origctx.manifestnode() == mn:
159 files = origctx.files()
103 files = origctx.files()
160
104
161 # update changelog
105 # update changelog
162 repo.ui.note(_(b"committing changelog\n"))
106 repo.ui.note(_(b"committing changelog\n"))
163 repo.changelog.delayupdate(tr)
107 repo.changelog.delayupdate(tr)
164 n = repo.changelog.add(
108 n = repo.changelog.add(
165 mn,
109 mn,
166 files,
110 files,
167 ctx.description(),
111 ctx.description(),
168 tr,
112 tr,
169 p1.node(),
113 p1.node(),
170 p2.node(),
114 p2.node(),
171 user,
115 user,
172 ctx.date(),
116 ctx.date(),
173 ctx.extra().copy(),
117 ctx.extra().copy(),
174 p1copies,
118 p1copies,
175 p2copies,
119 p2copies,
176 filesadded,
120 filesadded,
177 filesremoved,
121 filesremoved,
178 )
122 )
179 xp1, xp2 = p1.hex(), p2 and p2.hex() or b''
123 xp1, xp2 = p1.hex(), p2 and p2.hex() or b''
180 repo.hook(
124 repo.hook(
181 b'pretxncommit', throw=True, node=hex(n), parent1=xp1, parent2=xp2,
125 b'pretxncommit', throw=True, node=hex(n), parent1=xp1, parent2=xp2,
182 )
126 )
183 # set the new commit is proper phase
127 # set the new commit is proper phase
184 targetphase = subrepoutil.newcommitphase(repo.ui, ctx)
128 targetphase = subrepoutil.newcommitphase(repo.ui, ctx)
185 if targetphase:
129 if targetphase:
186 # retract boundary do not alter parent changeset.
130 # retract boundary do not alter parent changeset.
187 # if a parent have higher the resulting phase will
131 # if a parent have higher the resulting phase will
188 # be compliant anyway
132 # be compliant anyway
189 #
133 #
190 # if minimal phase was 0 we don't need to retract anything
134 # if minimal phase was 0 we don't need to retract anything
191 phases.registernew(repo, tr, targetphase, [n])
135 phases.registernew(repo, tr, targetphase, [n])
192 return n
136 return n
193
137
194
138
139 def _process_files(tr, ctx, error=False):
140 repo = ctx.repo()
141 p1 = ctx.p1()
142 p2 = ctx.p2()
143
144 writechangesetcopy, writefilecopymeta = _write_copy_meta(repo)
145
146 m1ctx = p1.manifestctx()
147 m2ctx = p2.manifestctx()
148 mctx = m1ctx.copy()
149
150 m = mctx.read()
151 m1 = m1ctx.read()
152 m2 = m2ctx.read()
153
154 # check in files
155 added = []
156 filesadded = []
157 removed = list(ctx.removed())
158 touched = []
159 linkrev = len(repo)
160 repo.ui.note(_(b"committing files:\n"))
161 uipathfn = scmutil.getuipathfn(repo)
162 for f in sorted(ctx.modified() + ctx.added()):
163 repo.ui.note(uipathfn(f) + b"\n")
164 try:
165 fctx = ctx[f]
166 if fctx is None:
167 removed.append(f)
168 else:
169 added.append(f)
170 m[f], is_touched = _filecommit(
171 repo, fctx, m1, m2, linkrev, tr, writefilecopymeta,
172 )
173 if is_touched:
174 touched.append(f)
175 if is_touched == 'added':
176 filesadded.append(f)
177 m.setflag(f, fctx.flags())
178 except OSError:
179 repo.ui.warn(_(b"trouble committing %s!\n") % uipathfn(f))
180 raise
181 except IOError as inst:
182 errcode = getattr(inst, 'errno', errno.ENOENT)
183 if error or errcode and errcode != errno.ENOENT:
184 repo.ui.warn(_(b"trouble committing %s!\n") % uipathfn(f))
185 raise
186
187 # update manifest
188 removed = [f for f in removed if f in m1 or f in m2]
189 drop = sorted([f for f in removed if f in m])
190 for f in drop:
191 del m[f]
192 if p2.rev() != nullrev:
193 rf = metadata.get_removal_filter(ctx, (p1, p2, m1, m2))
194 removed = [f for f in removed if not rf(f)]
195
196 touched.extend(removed)
197
198 files = touched
199 mn = _commit_manifest(tr, linkrev, ctx, mctx, files, added, drop)
200
201 return mn, files, filesadded, removed
202
203
195 def _filecommit(
204 def _filecommit(
196 repo, fctx, manifest1, manifest2, linkrev, tr, includecopymeta,
205 repo, fctx, manifest1, manifest2, linkrev, tr, includecopymeta,
197 ):
206 ):
198 """
207 """
199 commit an individual file as part of a larger transaction
208 commit an individual file as part of a larger transaction
200
209
201 input:
210 input:
202
211
203 fctx: a file context with the content we are trying to commit
212 fctx: a file context with the content we are trying to commit
204 manifest1: manifest of changeset first parent
213 manifest1: manifest of changeset first parent
205 manifest2: manifest of changeset second parent
214 manifest2: manifest of changeset second parent
206 linkrev: revision number of the changeset being created
215 linkrev: revision number of the changeset being created
207 tr: current transation
216 tr: current transation
208 individual: boolean, set to False to skip storing the copy data
217 individual: boolean, set to False to skip storing the copy data
209 (only used by the Google specific feature of using
218 (only used by the Google specific feature of using
210 changeset extra as copy source of truth).
219 changeset extra as copy source of truth).
211
220
212 output: (filenode, touched)
221 output: (filenode, touched)
213
222
214 filenode: the filenode that should be used by this changeset
223 filenode: the filenode that should be used by this changeset
215 touched: one of: None (mean untouched), 'added' or 'modified'
224 touched: one of: None (mean untouched), 'added' or 'modified'
216 """
225 """
217
226
218 fname = fctx.path()
227 fname = fctx.path()
219 fparent1 = manifest1.get(fname, nullid)
228 fparent1 = manifest1.get(fname, nullid)
220 fparent2 = manifest2.get(fname, nullid)
229 fparent2 = manifest2.get(fname, nullid)
221 touched = None
230 touched = None
222 if fparent1 == fparent2 == nullid:
231 if fparent1 == fparent2 == nullid:
223 touched = 'added'
232 touched = 'added'
224
233
225 if isinstance(fctx, context.filectx):
234 if isinstance(fctx, context.filectx):
226 # This block fast path most comparisons which are usually done. It
235 # This block fast path most comparisons which are usually done. It
227 # assumes that bare filectx is used and no merge happened, hence no
236 # assumes that bare filectx is used and no merge happened, hence no
228 # need to create a new file revision in this case.
237 # need to create a new file revision in this case.
229 node = fctx.filenode()
238 node = fctx.filenode()
230 if node in [fparent1, fparent2]:
239 if node in [fparent1, fparent2]:
231 repo.ui.debug(b'reusing %s filelog entry\n' % fname)
240 repo.ui.debug(b'reusing %s filelog entry\n' % fname)
232 if (
241 if (
233 fparent1 != nullid and manifest1.flags(fname) != fctx.flags()
242 fparent1 != nullid and manifest1.flags(fname) != fctx.flags()
234 ) or (
243 ) or (
235 fparent2 != nullid and manifest2.flags(fname) != fctx.flags()
244 fparent2 != nullid and manifest2.flags(fname) != fctx.flags()
236 ):
245 ):
237 touched = 'modified'
246 touched = 'modified'
238 return node, touched
247 return node, touched
239
248
240 flog = repo.file(fname)
249 flog = repo.file(fname)
241 meta = {}
250 meta = {}
242 cfname = fctx.copysource()
251 cfname = fctx.copysource()
243 fnode = None
252 fnode = None
244
253
245 if cfname and cfname != fname:
254 if cfname and cfname != fname:
246 # Mark the new revision of this file as a copy of another
255 # Mark the new revision of this file as a copy of another
247 # file. This copy data will effectively act as a parent
256 # file. This copy data will effectively act as a parent
248 # of this new revision. If this is a merge, the first
257 # of this new revision. If this is a merge, the first
249 # parent will be the nullid (meaning "look up the copy data")
258 # parent will be the nullid (meaning "look up the copy data")
250 # and the second one will be the other parent. For example:
259 # and the second one will be the other parent. For example:
251 #
260 #
252 # 0 --- 1 --- 3 rev1 changes file foo
261 # 0 --- 1 --- 3 rev1 changes file foo
253 # \ / rev2 renames foo to bar and changes it
262 # \ / rev2 renames foo to bar and changes it
254 # \- 2 -/ rev3 should have bar with all changes and
263 # \- 2 -/ rev3 should have bar with all changes and
255 # should record that bar descends from
264 # should record that bar descends from
256 # bar in rev2 and foo in rev1
265 # bar in rev2 and foo in rev1
257 #
266 #
258 # this allows this merge to succeed:
267 # this allows this merge to succeed:
259 #
268 #
260 # 0 --- 1 --- 3 rev4 reverts the content change from rev2
269 # 0 --- 1 --- 3 rev4 reverts the content change from rev2
261 # \ / merging rev3 and rev4 should use bar@rev2
270 # \ / merging rev3 and rev4 should use bar@rev2
262 # \- 2 --- 4 as the merge base
271 # \- 2 --- 4 as the merge base
263 #
272 #
264
273
265 cnode = manifest1.get(cfname)
274 cnode = manifest1.get(cfname)
266 newfparent = fparent2
275 newfparent = fparent2
267
276
268 if manifest2: # branch merge
277 if manifest2: # branch merge
269 if fparent2 == nullid or cnode is None: # copied on remote side
278 if fparent2 == nullid or cnode is None: # copied on remote side
270 if cfname in manifest2:
279 if cfname in manifest2:
271 cnode = manifest2[cfname]
280 cnode = manifest2[cfname]
272 newfparent = fparent1
281 newfparent = fparent1
273
282
274 # Here, we used to search backwards through history to try to find
283 # Here, we used to search backwards through history to try to find
275 # where the file copy came from if the source of a copy was not in
284 # where the file copy came from if the source of a copy was not in
276 # the parent directory. However, this doesn't actually make sense to
285 # the parent directory. However, this doesn't actually make sense to
277 # do (what does a copy from something not in your working copy even
286 # do (what does a copy from something not in your working copy even
278 # mean?) and it causes bugs (eg, issue4476). Instead, we will warn
287 # mean?) and it causes bugs (eg, issue4476). Instead, we will warn
279 # the user that copy information was dropped, so if they didn't
288 # the user that copy information was dropped, so if they didn't
280 # expect this outcome it can be fixed, but this is the correct
289 # expect this outcome it can be fixed, but this is the correct
281 # behavior in this circumstance.
290 # behavior in this circumstance.
282
291
283 if cnode:
292 if cnode:
284 repo.ui.debug(b" %s: copy %s:%s\n" % (fname, cfname, hex(cnode)))
293 repo.ui.debug(b" %s: copy %s:%s\n" % (fname, cfname, hex(cnode)))
285 if includecopymeta:
294 if includecopymeta:
286 meta[b"copy"] = cfname
295 meta[b"copy"] = cfname
287 meta[b"copyrev"] = hex(cnode)
296 meta[b"copyrev"] = hex(cnode)
288 fparent1, fparent2 = nullid, newfparent
297 fparent1, fparent2 = nullid, newfparent
289 else:
298 else:
290 repo.ui.warn(
299 repo.ui.warn(
291 _(
300 _(
292 b"warning: can't find ancestor for '%s' "
301 b"warning: can't find ancestor for '%s' "
293 b"copied from '%s'!\n"
302 b"copied from '%s'!\n"
294 )
303 )
295 % (fname, cfname)
304 % (fname, cfname)
296 )
305 )
297
306
298 elif fparent1 == nullid:
307 elif fparent1 == nullid:
299 fparent1, fparent2 = fparent2, nullid
308 fparent1, fparent2 = fparent2, nullid
300 elif fparent2 != nullid:
309 elif fparent2 != nullid:
301 # is one parent an ancestor of the other?
310 # is one parent an ancestor of the other?
302 fparentancestors = flog.commonancestorsheads(fparent1, fparent2)
311 fparentancestors = flog.commonancestorsheads(fparent1, fparent2)
303 if fparent1 in fparentancestors:
312 if fparent1 in fparentancestors:
304 fparent1, fparent2 = fparent2, nullid
313 fparent1, fparent2 = fparent2, nullid
305 elif fparent2 in fparentancestors:
314 elif fparent2 in fparentancestors:
306 fparent2 = nullid
315 fparent2 = nullid
307 elif not fparentancestors:
316 elif not fparentancestors:
308 # TODO: this whole if-else might be simplified much more
317 # TODO: this whole if-else might be simplified much more
309 ms = mergestate.mergestate.read(repo)
318 ms = mergestate.mergestate.read(repo)
310 if (
319 if (
311 fname in ms
320 fname in ms
312 and ms[fname] == mergestate.MERGE_RECORD_MERGED_OTHER
321 and ms[fname] == mergestate.MERGE_RECORD_MERGED_OTHER
313 ):
322 ):
314 fparent1, fparent2 = fparent2, nullid
323 fparent1, fparent2 = fparent2, nullid
315
324
316 # is the file changed?
325 # is the file changed?
317 text = fctx.data()
326 text = fctx.data()
318 if fparent2 != nullid or meta or flog.cmp(fparent1, text):
327 if fparent2 != nullid or meta or flog.cmp(fparent1, text):
319 if touched is None: # do not overwrite added
328 if touched is None: # do not overwrite added
320 touched = 'modified'
329 touched = 'modified'
321 fnode = flog.add(text, meta, tr, linkrev, fparent1, fparent2)
330 fnode = flog.add(text, meta, tr, linkrev, fparent1, fparent2)
322 # are just the flags changed during merge?
331 # are just the flags changed during merge?
323 elif fname in manifest1 and manifest1.flags(fname) != fctx.flags():
332 elif fname in manifest1 and manifest1.flags(fname) != fctx.flags():
324 touched = 'modified'
333 touched = 'modified'
325 fnode = fparent1
334 fnode = fparent1
326 else:
335 else:
327 fnode = fparent1
336 fnode = fparent1
328 return fnode, touched
337 return fnode, touched
329
338
330
339
331 def _commit_manifest(tr, linkrev, ctx, mctx, files, added, drop):
340 def _commit_manifest(tr, linkrev, ctx, mctx, files, added, drop):
332 """make a new manifest entry (or reuse a new one)
341 """make a new manifest entry (or reuse a new one)
333
342
334 given an initialised manifest context and precomputed list of
343 given an initialised manifest context and precomputed list of
335 - files: files affected by the commit
344 - files: files affected by the commit
336 - added: new entries in the manifest
345 - added: new entries in the manifest
337 - drop: entries present in parents but absent of this one
346 - drop: entries present in parents but absent of this one
338
347
339 Create a new manifest revision, reuse existing ones if possible.
348 Create a new manifest revision, reuse existing ones if possible.
340
349
341 Return the nodeid of the manifest revision.
350 Return the nodeid of the manifest revision.
342 """
351 """
343 repo = ctx.repo()
352 repo = ctx.repo()
344
353
345 md = None
354 md = None
346
355
347 # all this is cached, so it is find to get them all from the ctx.
356 # all this is cached, so it is find to get them all from the ctx.
348 p1 = ctx.p1()
357 p1 = ctx.p1()
349 p2 = ctx.p2()
358 p2 = ctx.p2()
350 m1ctx = p1.manifestctx()
359 m1ctx = p1.manifestctx()
351
360
352 m1 = m1ctx.read()
361 m1 = m1ctx.read()
353
362
354 manifest = mctx.read()
363 manifest = mctx.read()
355
364
356 if not files:
365 if not files:
357 # if no "files" actually changed in terms of the changelog,
366 # if no "files" actually changed in terms of the changelog,
358 # try hard to detect unmodified manifest entry so that the
367 # try hard to detect unmodified manifest entry so that the
359 # exact same commit can be reproduced later on convert.
368 # exact same commit can be reproduced later on convert.
360 md = m1.diff(manifest, scmutil.matchfiles(repo, ctx.files()))
369 md = m1.diff(manifest, scmutil.matchfiles(repo, ctx.files()))
361 if not files and md:
370 if not files and md:
362 repo.ui.debug(
371 repo.ui.debug(
363 b'not reusing manifest (no file change in '
372 b'not reusing manifest (no file change in '
364 b'changelog, but manifest differs)\n'
373 b'changelog, but manifest differs)\n'
365 )
374 )
366 if files or md:
375 if files or md:
367 repo.ui.note(_(b"committing manifest\n"))
376 repo.ui.note(_(b"committing manifest\n"))
368 # we're using narrowmatch here since it's already applied at
377 # we're using narrowmatch here since it's already applied at
369 # other stages (such as dirstate.walk), so we're already
378 # other stages (such as dirstate.walk), so we're already
370 # ignoring things outside of narrowspec in most cases. The
379 # ignoring things outside of narrowspec in most cases. The
371 # one case where we might have files outside the narrowspec
380 # one case where we might have files outside the narrowspec
372 # at this point is merges, and we already error out in the
381 # at this point is merges, and we already error out in the
373 # case where the merge has files outside of the narrowspec,
382 # case where the merge has files outside of the narrowspec,
374 # so this is safe.
383 # so this is safe.
375 mn = mctx.write(
384 mn = mctx.write(
376 tr,
385 tr,
377 linkrev,
386 linkrev,
378 p1.manifestnode(),
387 p1.manifestnode(),
379 p2.manifestnode(),
388 p2.manifestnode(),
380 added,
389 added,
381 drop,
390 drop,
382 match=repo.narrowmatch(),
391 match=repo.narrowmatch(),
383 )
392 )
384 else:
393 else:
385 repo.ui.debug(
394 repo.ui.debug(
386 b'reusing manifest from p1 (listed files ' b'actually unchanged)\n'
395 b'reusing manifest from p1 (listed files ' b'actually unchanged)\n'
387 )
396 )
388 mn = p1.manifestnode()
397 mn = p1.manifestnode()
389
398
390 return mn
399 return mn
General Comments 0
You need to be logged in to leave comments. Login now