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