##// END OF EJS Templates
commitctx: gather more preparation code within the lock context...
marmoute -
r45796:bd751527 default
parent child Browse files
Show More
@@ -1,399 +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 with repo.lock(), repo.transaction(b"commit") as tr:
66 writechangesetcopy, writefilecopymeta = _write_copy_meta(repo)
67 writechangesetcopy, writefilecopymeta = _write_copy_meta(repo)
67
68
68 p1copies, p2copies = None, None
69 p1copies, p2copies = None, None
69 if writechangesetcopy:
70 if writechangesetcopy:
70 p1copies = ctx.p1copies()
71 p1copies = ctx.p1copies()
71 p2copies = ctx.p2copies()
72 p2copies = ctx.p2copies()
72 filesadded, filesremoved = None, None
73 filesadded, filesremoved = None, None
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 mn, files, added, removed = _process_files(tr, ctx, error=error)
87 mn, files, added, removed = _process_files(tr, ctx, error=error)
88 if writechangesetcopy:
88 if writechangesetcopy:
89 filesremoved = removed
89 filesremoved = removed
90 filesadded = added
90 filesadded = added
91
91
92 if origctx and origctx.manifestnode() == mn:
92 if origctx and origctx.manifestnode() == mn:
93 files = origctx.files()
93 files = origctx.files()
94
94
95 if not writefilecopymeta:
95 if not writefilecopymeta:
96 # If writing only to changeset extras, use None to indicate that
96 # If writing only to changeset extras, use None to indicate that
97 # no entry should be written. If writing to both, write an empty
97 # no entry should be written. If writing to both, write an empty
98 # entry to prevent the reader from falling back to reading
98 # entry to prevent the reader from falling back to reading
99 # filelogs.
99 # filelogs.
100 p1copies = p1copies or None
100 p1copies = p1copies or None
101 p2copies = p2copies or None
101 p2copies = p2copies or None
102 filesadded = filesadded or None
102 filesadded = filesadded or None
103 filesremoved = filesremoved or None
103 filesremoved = filesremoved or None
104
104
105 # update changelog
105 # update changelog
106 repo.ui.note(_(b"committing changelog\n"))
106 repo.ui.note(_(b"committing changelog\n"))
107 repo.changelog.delayupdate(tr)
107 repo.changelog.delayupdate(tr)
108 n = repo.changelog.add(
108 n = repo.changelog.add(
109 mn,
109 mn,
110 files,
110 files,
111 ctx.description(),
111 ctx.description(),
112 tr,
112 tr,
113 p1.node(),
113 p1.node(),
114 p2.node(),
114 p2.node(),
115 user,
115 user,
116 ctx.date(),
116 ctx.date(),
117 ctx.extra().copy(),
117 ctx.extra().copy(),
118 p1copies,
118 p1copies,
119 p2copies,
119 p2copies,
120 filesadded,
120 filesadded,
121 filesremoved,
121 filesremoved,
122 )
122 )
123 xp1, xp2 = p1.hex(), p2 and p2.hex() or b''
123 xp1, xp2 = p1.hex(), p2 and p2.hex() or b''
124 repo.hook(
124 repo.hook(
125 b'pretxncommit', throw=True, node=hex(n), parent1=xp1, parent2=xp2,
125 b'pretxncommit', throw=True, node=hex(n), parent1=xp1, parent2=xp2,
126 )
126 )
127 # set the new commit is proper phase
127 # set the new commit is proper phase
128 targetphase = subrepoutil.newcommitphase(repo.ui, ctx)
128 targetphase = subrepoutil.newcommitphase(repo.ui, ctx)
129 if targetphase:
129 if targetphase:
130 # retract boundary do not alter parent changeset.
130 # retract boundary do not alter parent changeset.
131 # if a parent have higher the resulting phase will
131 # if a parent have higher the resulting phase will
132 # be compliant anyway
132 # be compliant anyway
133 #
133 #
134 # 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
135 phases.registernew(repo, tr, targetphase, [n])
135 phases.registernew(repo, tr, targetphase, [n])
136 return n
136 return n
137
137
138
138
139 def _process_files(tr, ctx, error=False):
139 def _process_files(tr, ctx, error=False):
140 repo = ctx.repo()
140 repo = ctx.repo()
141 p1 = ctx.p1()
141 p1 = ctx.p1()
142 p2 = ctx.p2()
142 p2 = ctx.p2()
143
143
144 writechangesetcopy, writefilecopymeta = _write_copy_meta(repo)
144 writechangesetcopy, writefilecopymeta = _write_copy_meta(repo)
145
145
146 m1ctx = p1.manifestctx()
146 m1ctx = p1.manifestctx()
147 m2ctx = p2.manifestctx()
147 m2ctx = p2.manifestctx()
148 mctx = m1ctx.copy()
148 mctx = m1ctx.copy()
149
149
150 m = mctx.read()
150 m = mctx.read()
151 m1 = m1ctx.read()
151 m1 = m1ctx.read()
152 m2 = m2ctx.read()
152 m2 = m2ctx.read()
153
153
154 # check in files
154 # check in files
155 added = []
155 added = []
156 filesadded = []
156 filesadded = []
157 removed = list(ctx.removed())
157 removed = list(ctx.removed())
158 touched = []
158 touched = []
159 linkrev = len(repo)
159 linkrev = len(repo)
160 repo.ui.note(_(b"committing files:\n"))
160 repo.ui.note(_(b"committing files:\n"))
161 uipathfn = scmutil.getuipathfn(repo)
161 uipathfn = scmutil.getuipathfn(repo)
162 for f in sorted(ctx.modified() + ctx.added()):
162 for f in sorted(ctx.modified() + ctx.added()):
163 repo.ui.note(uipathfn(f) + b"\n")
163 repo.ui.note(uipathfn(f) + b"\n")
164 try:
164 try:
165 fctx = ctx[f]
165 fctx = ctx[f]
166 if fctx is None:
166 if fctx is None:
167 removed.append(f)
167 removed.append(f)
168 else:
168 else:
169 added.append(f)
169 added.append(f)
170 m[f], is_touched = _filecommit(
170 m[f], is_touched = _filecommit(
171 repo, fctx, m1, m2, linkrev, tr, writefilecopymeta,
171 repo, fctx, m1, m2, linkrev, tr, writefilecopymeta,
172 )
172 )
173 if is_touched:
173 if is_touched:
174 touched.append(f)
174 touched.append(f)
175 if is_touched == 'added':
175 if is_touched == 'added':
176 filesadded.append(f)
176 filesadded.append(f)
177 m.setflag(f, fctx.flags())
177 m.setflag(f, fctx.flags())
178 except OSError:
178 except OSError:
179 repo.ui.warn(_(b"trouble committing %s!\n") % uipathfn(f))
179 repo.ui.warn(_(b"trouble committing %s!\n") % uipathfn(f))
180 raise
180 raise
181 except IOError as inst:
181 except IOError as inst:
182 errcode = getattr(inst, 'errno', errno.ENOENT)
182 errcode = getattr(inst, 'errno', errno.ENOENT)
183 if error or errcode and errcode != errno.ENOENT:
183 if error or errcode and errcode != errno.ENOENT:
184 repo.ui.warn(_(b"trouble committing %s!\n") % uipathfn(f))
184 repo.ui.warn(_(b"trouble committing %s!\n") % uipathfn(f))
185 raise
185 raise
186
186
187 # update manifest
187 # update manifest
188 removed = [f for f in removed if f in m1 or f in m2]
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])
189 drop = sorted([f for f in removed if f in m])
190 for f in drop:
190 for f in drop:
191 del m[f]
191 del m[f]
192 if p2.rev() != nullrev:
192 if p2.rev() != nullrev:
193 rf = metadata.get_removal_filter(ctx, (p1, p2, m1, m2))
193 rf = metadata.get_removal_filter(ctx, (p1, p2, m1, m2))
194 removed = [f for f in removed if not rf(f)]
194 removed = [f for f in removed if not rf(f)]
195
195
196 touched.extend(removed)
196 touched.extend(removed)
197
197
198 files = touched
198 files = touched
199 mn = _commit_manifest(tr, linkrev, ctx, mctx, files, added, drop)
199 mn = _commit_manifest(tr, linkrev, ctx, mctx, files, added, drop)
200
200
201 return mn, files, filesadded, removed
201 return mn, files, filesadded, removed
202
202
203
203
204 def _filecommit(
204 def _filecommit(
205 repo, fctx, manifest1, manifest2, linkrev, tr, includecopymeta,
205 repo, fctx, manifest1, manifest2, linkrev, tr, includecopymeta,
206 ):
206 ):
207 """
207 """
208 commit an individual file as part of a larger transaction
208 commit an individual file as part of a larger transaction
209
209
210 input:
210 input:
211
211
212 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
213 manifest1: manifest of changeset first parent
213 manifest1: manifest of changeset first parent
214 manifest2: manifest of changeset second parent
214 manifest2: manifest of changeset second parent
215 linkrev: revision number of the changeset being created
215 linkrev: revision number of the changeset being created
216 tr: current transation
216 tr: current transation
217 individual: boolean, set to False to skip storing the copy data
217 individual: boolean, set to False to skip storing the copy data
218 (only used by the Google specific feature of using
218 (only used by the Google specific feature of using
219 changeset extra as copy source of truth).
219 changeset extra as copy source of truth).
220
220
221 output: (filenode, touched)
221 output: (filenode, touched)
222
222
223 filenode: the filenode that should be used by this changeset
223 filenode: the filenode that should be used by this changeset
224 touched: one of: None (mean untouched), 'added' or 'modified'
224 touched: one of: None (mean untouched), 'added' or 'modified'
225 """
225 """
226
226
227 fname = fctx.path()
227 fname = fctx.path()
228 fparent1 = manifest1.get(fname, nullid)
228 fparent1 = manifest1.get(fname, nullid)
229 fparent2 = manifest2.get(fname, nullid)
229 fparent2 = manifest2.get(fname, nullid)
230 touched = None
230 touched = None
231 if fparent1 == fparent2 == nullid:
231 if fparent1 == fparent2 == nullid:
232 touched = 'added'
232 touched = 'added'
233
233
234 if isinstance(fctx, context.filectx):
234 if isinstance(fctx, context.filectx):
235 # This block fast path most comparisons which are usually done. It
235 # This block fast path most comparisons which are usually done. It
236 # 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
237 # need to create a new file revision in this case.
237 # need to create a new file revision in this case.
238 node = fctx.filenode()
238 node = fctx.filenode()
239 if node in [fparent1, fparent2]:
239 if node in [fparent1, fparent2]:
240 repo.ui.debug(b'reusing %s filelog entry\n' % fname)
240 repo.ui.debug(b'reusing %s filelog entry\n' % fname)
241 if (
241 if (
242 fparent1 != nullid and manifest1.flags(fname) != fctx.flags()
242 fparent1 != nullid and manifest1.flags(fname) != fctx.flags()
243 ) or (
243 ) or (
244 fparent2 != nullid and manifest2.flags(fname) != fctx.flags()
244 fparent2 != nullid and manifest2.flags(fname) != fctx.flags()
245 ):
245 ):
246 touched = 'modified'
246 touched = 'modified'
247 return node, touched
247 return node, touched
248
248
249 flog = repo.file(fname)
249 flog = repo.file(fname)
250 meta = {}
250 meta = {}
251 cfname = fctx.copysource()
251 cfname = fctx.copysource()
252 fnode = None
252 fnode = None
253
253
254 if cfname and cfname != fname:
254 if cfname and cfname != fname:
255 # 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
256 # file. This copy data will effectively act as a parent
256 # file. This copy data will effectively act as a parent
257 # of this new revision. If this is a merge, the first
257 # of this new revision. If this is a merge, the first
258 # parent will be the nullid (meaning "look up the copy data")
258 # parent will be the nullid (meaning "look up the copy data")
259 # and the second one will be the other parent. For example:
259 # and the second one will be the other parent. For example:
260 #
260 #
261 # 0 --- 1 --- 3 rev1 changes file foo
261 # 0 --- 1 --- 3 rev1 changes file foo
262 # \ / rev2 renames foo to bar and changes it
262 # \ / rev2 renames foo to bar and changes it
263 # \- 2 -/ rev3 should have bar with all changes and
263 # \- 2 -/ rev3 should have bar with all changes and
264 # should record that bar descends from
264 # should record that bar descends from
265 # bar in rev2 and foo in rev1
265 # bar in rev2 and foo in rev1
266 #
266 #
267 # this allows this merge to succeed:
267 # this allows this merge to succeed:
268 #
268 #
269 # 0 --- 1 --- 3 rev4 reverts the content change from rev2
269 # 0 --- 1 --- 3 rev4 reverts the content change from rev2
270 # \ / merging rev3 and rev4 should use bar@rev2
270 # \ / merging rev3 and rev4 should use bar@rev2
271 # \- 2 --- 4 as the merge base
271 # \- 2 --- 4 as the merge base
272 #
272 #
273
273
274 cnode = manifest1.get(cfname)
274 cnode = manifest1.get(cfname)
275 newfparent = fparent2
275 newfparent = fparent2
276
276
277 if manifest2: # branch merge
277 if manifest2: # branch merge
278 if fparent2 == nullid or cnode is None: # copied on remote side
278 if fparent2 == nullid or cnode is None: # copied on remote side
279 if cfname in manifest2:
279 if cfname in manifest2:
280 cnode = manifest2[cfname]
280 cnode = manifest2[cfname]
281 newfparent = fparent1
281 newfparent = fparent1
282
282
283 # 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
284 # 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
285 # the parent directory. However, this doesn't actually make sense to
285 # the parent directory. However, this doesn't actually make sense to
286 # 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
287 # mean?) and it causes bugs (eg, issue4476). Instead, we will warn
287 # mean?) and it causes bugs (eg, issue4476). Instead, we will warn
288 # 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
289 # 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
290 # behavior in this circumstance.
290 # behavior in this circumstance.
291
291
292 if cnode:
292 if cnode:
293 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)))
294 if includecopymeta:
294 if includecopymeta:
295 meta[b"copy"] = cfname
295 meta[b"copy"] = cfname
296 meta[b"copyrev"] = hex(cnode)
296 meta[b"copyrev"] = hex(cnode)
297 fparent1, fparent2 = nullid, newfparent
297 fparent1, fparent2 = nullid, newfparent
298 else:
298 else:
299 repo.ui.warn(
299 repo.ui.warn(
300 _(
300 _(
301 b"warning: can't find ancestor for '%s' "
301 b"warning: can't find ancestor for '%s' "
302 b"copied from '%s'!\n"
302 b"copied from '%s'!\n"
303 )
303 )
304 % (fname, cfname)
304 % (fname, cfname)
305 )
305 )
306
306
307 elif fparent1 == nullid:
307 elif fparent1 == nullid:
308 fparent1, fparent2 = fparent2, nullid
308 fparent1, fparent2 = fparent2, nullid
309 elif fparent2 != nullid:
309 elif fparent2 != nullid:
310 # is one parent an ancestor of the other?
310 # is one parent an ancestor of the other?
311 fparentancestors = flog.commonancestorsheads(fparent1, fparent2)
311 fparentancestors = flog.commonancestorsheads(fparent1, fparent2)
312 if fparent1 in fparentancestors:
312 if fparent1 in fparentancestors:
313 fparent1, fparent2 = fparent2, nullid
313 fparent1, fparent2 = fparent2, nullid
314 elif fparent2 in fparentancestors:
314 elif fparent2 in fparentancestors:
315 fparent2 = nullid
315 fparent2 = nullid
316 elif not fparentancestors:
316 elif not fparentancestors:
317 # TODO: this whole if-else might be simplified much more
317 # TODO: this whole if-else might be simplified much more
318 ms = mergestate.mergestate.read(repo)
318 ms = mergestate.mergestate.read(repo)
319 if (
319 if (
320 fname in ms
320 fname in ms
321 and ms[fname] == mergestate.MERGE_RECORD_MERGED_OTHER
321 and ms[fname] == mergestate.MERGE_RECORD_MERGED_OTHER
322 ):
322 ):
323 fparent1, fparent2 = fparent2, nullid
323 fparent1, fparent2 = fparent2, nullid
324
324
325 # is the file changed?
325 # is the file changed?
326 text = fctx.data()
326 text = fctx.data()
327 if fparent2 != nullid or meta or flog.cmp(fparent1, text):
327 if fparent2 != nullid or meta or flog.cmp(fparent1, text):
328 if touched is None: # do not overwrite added
328 if touched is None: # do not overwrite added
329 touched = 'modified'
329 touched = 'modified'
330 fnode = flog.add(text, meta, tr, linkrev, fparent1, fparent2)
330 fnode = flog.add(text, meta, tr, linkrev, fparent1, fparent2)
331 # are just the flags changed during merge?
331 # are just the flags changed during merge?
332 elif fname in manifest1 and manifest1.flags(fname) != fctx.flags():
332 elif fname in manifest1 and manifest1.flags(fname) != fctx.flags():
333 touched = 'modified'
333 touched = 'modified'
334 fnode = fparent1
334 fnode = fparent1
335 else:
335 else:
336 fnode = fparent1
336 fnode = fparent1
337 return fnode, touched
337 return fnode, touched
338
338
339
339
340 def _commit_manifest(tr, linkrev, ctx, mctx, files, added, drop):
340 def _commit_manifest(tr, linkrev, ctx, mctx, files, added, drop):
341 """make a new manifest entry (or reuse a new one)
341 """make a new manifest entry (or reuse a new one)
342
342
343 given an initialised manifest context and precomputed list of
343 given an initialised manifest context and precomputed list of
344 - files: files affected by the commit
344 - files: files affected by the commit
345 - added: new entries in the manifest
345 - added: new entries in the manifest
346 - drop: entries present in parents but absent of this one
346 - drop: entries present in parents but absent of this one
347
347
348 Create a new manifest revision, reuse existing ones if possible.
348 Create a new manifest revision, reuse existing ones if possible.
349
349
350 Return the nodeid of the manifest revision.
350 Return the nodeid of the manifest revision.
351 """
351 """
352 repo = ctx.repo()
352 repo = ctx.repo()
353
353
354 md = None
354 md = None
355
355
356 # 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.
357 p1 = ctx.p1()
357 p1 = ctx.p1()
358 p2 = ctx.p2()
358 p2 = ctx.p2()
359 m1ctx = p1.manifestctx()
359 m1ctx = p1.manifestctx()
360
360
361 m1 = m1ctx.read()
361 m1 = m1ctx.read()
362
362
363 manifest = mctx.read()
363 manifest = mctx.read()
364
364
365 if not files:
365 if not files:
366 # if no "files" actually changed in terms of the changelog,
366 # if no "files" actually changed in terms of the changelog,
367 # try hard to detect unmodified manifest entry so that the
367 # try hard to detect unmodified manifest entry so that the
368 # exact same commit can be reproduced later on convert.
368 # exact same commit can be reproduced later on convert.
369 md = m1.diff(manifest, scmutil.matchfiles(repo, ctx.files()))
369 md = m1.diff(manifest, scmutil.matchfiles(repo, ctx.files()))
370 if not files and md:
370 if not files and md:
371 repo.ui.debug(
371 repo.ui.debug(
372 b'not reusing manifest (no file change in '
372 b'not reusing manifest (no file change in '
373 b'changelog, but manifest differs)\n'
373 b'changelog, but manifest differs)\n'
374 )
374 )
375 if files or md:
375 if files or md:
376 repo.ui.note(_(b"committing manifest\n"))
376 repo.ui.note(_(b"committing manifest\n"))
377 # we're using narrowmatch here since it's already applied at
377 # we're using narrowmatch here since it's already applied at
378 # other stages (such as dirstate.walk), so we're already
378 # other stages (such as dirstate.walk), so we're already
379 # ignoring things outside of narrowspec in most cases. The
379 # ignoring things outside of narrowspec in most cases. The
380 # one case where we might have files outside the narrowspec
380 # one case where we might have files outside the narrowspec
381 # 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
382 # case where the merge has files outside of the narrowspec,
382 # case where the merge has files outside of the narrowspec,
383 # so this is safe.
383 # so this is safe.
384 mn = mctx.write(
384 mn = mctx.write(
385 tr,
385 tr,
386 linkrev,
386 linkrev,
387 p1.manifestnode(),
387 p1.manifestnode(),
388 p2.manifestnode(),
388 p2.manifestnode(),
389 added,
389 added,
390 drop,
390 drop,
391 match=repo.narrowmatch(),
391 match=repo.narrowmatch(),
392 )
392 )
393 else:
393 else:
394 repo.ui.debug(
394 repo.ui.debug(
395 b'reusing manifest from p1 (listed files ' b'actually unchanged)\n'
395 b'reusing manifest from p1 (listed files ' b'actually unchanged)\n'
396 )
396 )
397 mn = p1.manifestnode()
397 mn = p1.manifestnode()
398
398
399 return mn
399 return mn
General Comments 0
You need to be logged in to leave comments. Login now