##// END OF EJS Templates
obsfate: rename obsfate into obsolete in changeset_printer...
Boris Feld -
r34901:3a3adbcb default
parent child Browse files
Show More
@@ -1,3965 +1,3965 b''
1 # cmdutil.py - help for command processing in mercurial
1 # cmdutil.py - help for command processing in mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11 import itertools
11 import itertools
12 import os
12 import os
13 import re
13 import re
14 import tempfile
14 import tempfile
15
15
16 from .i18n import _
16 from .i18n import _
17 from .node import (
17 from .node import (
18 hex,
18 hex,
19 nullid,
19 nullid,
20 nullrev,
20 nullrev,
21 short,
21 short,
22 )
22 )
23
23
24 from . import (
24 from . import (
25 bookmarks,
25 bookmarks,
26 changelog,
26 changelog,
27 copies,
27 copies,
28 crecord as crecordmod,
28 crecord as crecordmod,
29 dagop,
29 dagop,
30 dirstateguard,
30 dirstateguard,
31 encoding,
31 encoding,
32 error,
32 error,
33 formatter,
33 formatter,
34 graphmod,
34 graphmod,
35 match as matchmod,
35 match as matchmod,
36 mdiff,
36 mdiff,
37 obsolete,
37 obsolete,
38 patch,
38 patch,
39 pathutil,
39 pathutil,
40 pycompat,
40 pycompat,
41 registrar,
41 registrar,
42 revlog,
42 revlog,
43 revset,
43 revset,
44 scmutil,
44 scmutil,
45 smartset,
45 smartset,
46 templatekw,
46 templatekw,
47 templater,
47 templater,
48 util,
48 util,
49 vfs as vfsmod,
49 vfs as vfsmod,
50 )
50 )
51 stringio = util.stringio
51 stringio = util.stringio
52
52
53 # templates of common command options
53 # templates of common command options
54
54
55 dryrunopts = [
55 dryrunopts = [
56 ('n', 'dry-run', None,
56 ('n', 'dry-run', None,
57 _('do not perform actions, just print output')),
57 _('do not perform actions, just print output')),
58 ]
58 ]
59
59
60 remoteopts = [
60 remoteopts = [
61 ('e', 'ssh', '',
61 ('e', 'ssh', '',
62 _('specify ssh command to use'), _('CMD')),
62 _('specify ssh command to use'), _('CMD')),
63 ('', 'remotecmd', '',
63 ('', 'remotecmd', '',
64 _('specify hg command to run on the remote side'), _('CMD')),
64 _('specify hg command to run on the remote side'), _('CMD')),
65 ('', 'insecure', None,
65 ('', 'insecure', None,
66 _('do not verify server certificate (ignoring web.cacerts config)')),
66 _('do not verify server certificate (ignoring web.cacerts config)')),
67 ]
67 ]
68
68
69 walkopts = [
69 walkopts = [
70 ('I', 'include', [],
70 ('I', 'include', [],
71 _('include names matching the given patterns'), _('PATTERN')),
71 _('include names matching the given patterns'), _('PATTERN')),
72 ('X', 'exclude', [],
72 ('X', 'exclude', [],
73 _('exclude names matching the given patterns'), _('PATTERN')),
73 _('exclude names matching the given patterns'), _('PATTERN')),
74 ]
74 ]
75
75
76 commitopts = [
76 commitopts = [
77 ('m', 'message', '',
77 ('m', 'message', '',
78 _('use text as commit message'), _('TEXT')),
78 _('use text as commit message'), _('TEXT')),
79 ('l', 'logfile', '',
79 ('l', 'logfile', '',
80 _('read commit message from file'), _('FILE')),
80 _('read commit message from file'), _('FILE')),
81 ]
81 ]
82
82
83 commitopts2 = [
83 commitopts2 = [
84 ('d', 'date', '',
84 ('d', 'date', '',
85 _('record the specified date as commit date'), _('DATE')),
85 _('record the specified date as commit date'), _('DATE')),
86 ('u', 'user', '',
86 ('u', 'user', '',
87 _('record the specified user as committer'), _('USER')),
87 _('record the specified user as committer'), _('USER')),
88 ]
88 ]
89
89
90 # hidden for now
90 # hidden for now
91 formatteropts = [
91 formatteropts = [
92 ('T', 'template', '',
92 ('T', 'template', '',
93 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
93 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
94 ]
94 ]
95
95
96 templateopts = [
96 templateopts = [
97 ('', 'style', '',
97 ('', 'style', '',
98 _('display using template map file (DEPRECATED)'), _('STYLE')),
98 _('display using template map file (DEPRECATED)'), _('STYLE')),
99 ('T', 'template', '',
99 ('T', 'template', '',
100 _('display with template'), _('TEMPLATE')),
100 _('display with template'), _('TEMPLATE')),
101 ]
101 ]
102
102
103 logopts = [
103 logopts = [
104 ('p', 'patch', None, _('show patch')),
104 ('p', 'patch', None, _('show patch')),
105 ('g', 'git', None, _('use git extended diff format')),
105 ('g', 'git', None, _('use git extended diff format')),
106 ('l', 'limit', '',
106 ('l', 'limit', '',
107 _('limit number of changes displayed'), _('NUM')),
107 _('limit number of changes displayed'), _('NUM')),
108 ('M', 'no-merges', None, _('do not show merges')),
108 ('M', 'no-merges', None, _('do not show merges')),
109 ('', 'stat', None, _('output diffstat-style summary of changes')),
109 ('', 'stat', None, _('output diffstat-style summary of changes')),
110 ('G', 'graph', None, _("show the revision DAG")),
110 ('G', 'graph', None, _("show the revision DAG")),
111 ] + templateopts
111 ] + templateopts
112
112
113 diffopts = [
113 diffopts = [
114 ('a', 'text', None, _('treat all files as text')),
114 ('a', 'text', None, _('treat all files as text')),
115 ('g', 'git', None, _('use git extended diff format')),
115 ('g', 'git', None, _('use git extended diff format')),
116 ('', 'binary', None, _('generate binary diffs in git mode (default)')),
116 ('', 'binary', None, _('generate binary diffs in git mode (default)')),
117 ('', 'nodates', None, _('omit dates from diff headers'))
117 ('', 'nodates', None, _('omit dates from diff headers'))
118 ]
118 ]
119
119
120 diffwsopts = [
120 diffwsopts = [
121 ('w', 'ignore-all-space', None,
121 ('w', 'ignore-all-space', None,
122 _('ignore white space when comparing lines')),
122 _('ignore white space when comparing lines')),
123 ('b', 'ignore-space-change', None,
123 ('b', 'ignore-space-change', None,
124 _('ignore changes in the amount of white space')),
124 _('ignore changes in the amount of white space')),
125 ('B', 'ignore-blank-lines', None,
125 ('B', 'ignore-blank-lines', None,
126 _('ignore changes whose lines are all blank')),
126 _('ignore changes whose lines are all blank')),
127 ('Z', 'ignore-space-at-eol', None,
127 ('Z', 'ignore-space-at-eol', None,
128 _('ignore changes in whitespace at EOL')),
128 _('ignore changes in whitespace at EOL')),
129 ]
129 ]
130
130
131 diffopts2 = [
131 diffopts2 = [
132 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
132 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
133 ('p', 'show-function', None, _('show which function each change is in')),
133 ('p', 'show-function', None, _('show which function each change is in')),
134 ('', 'reverse', None, _('produce a diff that undoes the changes')),
134 ('', 'reverse', None, _('produce a diff that undoes the changes')),
135 ] + diffwsopts + [
135 ] + diffwsopts + [
136 ('U', 'unified', '',
136 ('U', 'unified', '',
137 _('number of lines of context to show'), _('NUM')),
137 _('number of lines of context to show'), _('NUM')),
138 ('', 'stat', None, _('output diffstat-style summary of changes')),
138 ('', 'stat', None, _('output diffstat-style summary of changes')),
139 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
139 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
140 ]
140 ]
141
141
142 mergetoolopts = [
142 mergetoolopts = [
143 ('t', 'tool', '', _('specify merge tool')),
143 ('t', 'tool', '', _('specify merge tool')),
144 ]
144 ]
145
145
146 similarityopts = [
146 similarityopts = [
147 ('s', 'similarity', '',
147 ('s', 'similarity', '',
148 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
148 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
149 ]
149 ]
150
150
151 subrepoopts = [
151 subrepoopts = [
152 ('S', 'subrepos', None,
152 ('S', 'subrepos', None,
153 _('recurse into subrepositories'))
153 _('recurse into subrepositories'))
154 ]
154 ]
155
155
156 debugrevlogopts = [
156 debugrevlogopts = [
157 ('c', 'changelog', False, _('open changelog')),
157 ('c', 'changelog', False, _('open changelog')),
158 ('m', 'manifest', False, _('open manifest')),
158 ('m', 'manifest', False, _('open manifest')),
159 ('', 'dir', '', _('open directory manifest')),
159 ('', 'dir', '', _('open directory manifest')),
160 ]
160 ]
161
161
162 # special string such that everything below this line will be ingored in the
162 # special string such that everything below this line will be ingored in the
163 # editor text
163 # editor text
164 _linebelow = "^HG: ------------------------ >8 ------------------------$"
164 _linebelow = "^HG: ------------------------ >8 ------------------------$"
165
165
166 def ishunk(x):
166 def ishunk(x):
167 hunkclasses = (crecordmod.uihunk, patch.recordhunk)
167 hunkclasses = (crecordmod.uihunk, patch.recordhunk)
168 return isinstance(x, hunkclasses)
168 return isinstance(x, hunkclasses)
169
169
170 def newandmodified(chunks, originalchunks):
170 def newandmodified(chunks, originalchunks):
171 newlyaddedandmodifiedfiles = set()
171 newlyaddedandmodifiedfiles = set()
172 for chunk in chunks:
172 for chunk in chunks:
173 if ishunk(chunk) and chunk.header.isnewfile() and chunk not in \
173 if ishunk(chunk) and chunk.header.isnewfile() and chunk not in \
174 originalchunks:
174 originalchunks:
175 newlyaddedandmodifiedfiles.add(chunk.header.filename())
175 newlyaddedandmodifiedfiles.add(chunk.header.filename())
176 return newlyaddedandmodifiedfiles
176 return newlyaddedandmodifiedfiles
177
177
178 def parsealiases(cmd):
178 def parsealiases(cmd):
179 return cmd.lstrip("^").split("|")
179 return cmd.lstrip("^").split("|")
180
180
181 def setupwrapcolorwrite(ui):
181 def setupwrapcolorwrite(ui):
182 # wrap ui.write so diff output can be labeled/colorized
182 # wrap ui.write so diff output can be labeled/colorized
183 def wrapwrite(orig, *args, **kw):
183 def wrapwrite(orig, *args, **kw):
184 label = kw.pop('label', '')
184 label = kw.pop('label', '')
185 for chunk, l in patch.difflabel(lambda: args):
185 for chunk, l in patch.difflabel(lambda: args):
186 orig(chunk, label=label + l)
186 orig(chunk, label=label + l)
187
187
188 oldwrite = ui.write
188 oldwrite = ui.write
189 def wrap(*args, **kwargs):
189 def wrap(*args, **kwargs):
190 return wrapwrite(oldwrite, *args, **kwargs)
190 return wrapwrite(oldwrite, *args, **kwargs)
191 setattr(ui, 'write', wrap)
191 setattr(ui, 'write', wrap)
192 return oldwrite
192 return oldwrite
193
193
194 def filterchunks(ui, originalhunks, usecurses, testfile, operation=None):
194 def filterchunks(ui, originalhunks, usecurses, testfile, operation=None):
195 if usecurses:
195 if usecurses:
196 if testfile:
196 if testfile:
197 recordfn = crecordmod.testdecorator(testfile,
197 recordfn = crecordmod.testdecorator(testfile,
198 crecordmod.testchunkselector)
198 crecordmod.testchunkselector)
199 else:
199 else:
200 recordfn = crecordmod.chunkselector
200 recordfn = crecordmod.chunkselector
201
201
202 return crecordmod.filterpatch(ui, originalhunks, recordfn, operation)
202 return crecordmod.filterpatch(ui, originalhunks, recordfn, operation)
203
203
204 else:
204 else:
205 return patch.filterpatch(ui, originalhunks, operation)
205 return patch.filterpatch(ui, originalhunks, operation)
206
206
207 def recordfilter(ui, originalhunks, operation=None):
207 def recordfilter(ui, originalhunks, operation=None):
208 """ Prompts the user to filter the originalhunks and return a list of
208 """ Prompts the user to filter the originalhunks and return a list of
209 selected hunks.
209 selected hunks.
210 *operation* is used for to build ui messages to indicate the user what
210 *operation* is used for to build ui messages to indicate the user what
211 kind of filtering they are doing: reverting, committing, shelving, etc.
211 kind of filtering they are doing: reverting, committing, shelving, etc.
212 (see patch.filterpatch).
212 (see patch.filterpatch).
213 """
213 """
214 usecurses = crecordmod.checkcurses(ui)
214 usecurses = crecordmod.checkcurses(ui)
215 testfile = ui.config('experimental', 'crecordtest')
215 testfile = ui.config('experimental', 'crecordtest')
216 oldwrite = setupwrapcolorwrite(ui)
216 oldwrite = setupwrapcolorwrite(ui)
217 try:
217 try:
218 newchunks, newopts = filterchunks(ui, originalhunks, usecurses,
218 newchunks, newopts = filterchunks(ui, originalhunks, usecurses,
219 testfile, operation)
219 testfile, operation)
220 finally:
220 finally:
221 ui.write = oldwrite
221 ui.write = oldwrite
222 return newchunks, newopts
222 return newchunks, newopts
223
223
224 def dorecord(ui, repo, commitfunc, cmdsuggest, backupall,
224 def dorecord(ui, repo, commitfunc, cmdsuggest, backupall,
225 filterfn, *pats, **opts):
225 filterfn, *pats, **opts):
226 from . import merge as mergemod
226 from . import merge as mergemod
227 opts = pycompat.byteskwargs(opts)
227 opts = pycompat.byteskwargs(opts)
228 if not ui.interactive():
228 if not ui.interactive():
229 if cmdsuggest:
229 if cmdsuggest:
230 msg = _('running non-interactively, use %s instead') % cmdsuggest
230 msg = _('running non-interactively, use %s instead') % cmdsuggest
231 else:
231 else:
232 msg = _('running non-interactively')
232 msg = _('running non-interactively')
233 raise error.Abort(msg)
233 raise error.Abort(msg)
234
234
235 # make sure username is set before going interactive
235 # make sure username is set before going interactive
236 if not opts.get('user'):
236 if not opts.get('user'):
237 ui.username() # raise exception, username not provided
237 ui.username() # raise exception, username not provided
238
238
239 def recordfunc(ui, repo, message, match, opts):
239 def recordfunc(ui, repo, message, match, opts):
240 """This is generic record driver.
240 """This is generic record driver.
241
241
242 Its job is to interactively filter local changes, and
242 Its job is to interactively filter local changes, and
243 accordingly prepare working directory into a state in which the
243 accordingly prepare working directory into a state in which the
244 job can be delegated to a non-interactive commit command such as
244 job can be delegated to a non-interactive commit command such as
245 'commit' or 'qrefresh'.
245 'commit' or 'qrefresh'.
246
246
247 After the actual job is done by non-interactive command, the
247 After the actual job is done by non-interactive command, the
248 working directory is restored to its original state.
248 working directory is restored to its original state.
249
249
250 In the end we'll record interesting changes, and everything else
250 In the end we'll record interesting changes, and everything else
251 will be left in place, so the user can continue working.
251 will be left in place, so the user can continue working.
252 """
252 """
253
253
254 checkunfinished(repo, commit=True)
254 checkunfinished(repo, commit=True)
255 wctx = repo[None]
255 wctx = repo[None]
256 merge = len(wctx.parents()) > 1
256 merge = len(wctx.parents()) > 1
257 if merge:
257 if merge:
258 raise error.Abort(_('cannot partially commit a merge '
258 raise error.Abort(_('cannot partially commit a merge '
259 '(use "hg commit" instead)'))
259 '(use "hg commit" instead)'))
260
260
261 def fail(f, msg):
261 def fail(f, msg):
262 raise error.Abort('%s: %s' % (f, msg))
262 raise error.Abort('%s: %s' % (f, msg))
263
263
264 force = opts.get('force')
264 force = opts.get('force')
265 if not force:
265 if not force:
266 vdirs = []
266 vdirs = []
267 match.explicitdir = vdirs.append
267 match.explicitdir = vdirs.append
268 match.bad = fail
268 match.bad = fail
269
269
270 status = repo.status(match=match)
270 status = repo.status(match=match)
271 if not force:
271 if not force:
272 repo.checkcommitpatterns(wctx, vdirs, match, status, fail)
272 repo.checkcommitpatterns(wctx, vdirs, match, status, fail)
273 diffopts = patch.difffeatureopts(ui, opts=opts, whitespace=True)
273 diffopts = patch.difffeatureopts(ui, opts=opts, whitespace=True)
274 diffopts.nodates = True
274 diffopts.nodates = True
275 diffopts.git = True
275 diffopts.git = True
276 diffopts.showfunc = True
276 diffopts.showfunc = True
277 originaldiff = patch.diff(repo, changes=status, opts=diffopts)
277 originaldiff = patch.diff(repo, changes=status, opts=diffopts)
278 originalchunks = patch.parsepatch(originaldiff)
278 originalchunks = patch.parsepatch(originaldiff)
279
279
280 # 1. filter patch, since we are intending to apply subset of it
280 # 1. filter patch, since we are intending to apply subset of it
281 try:
281 try:
282 chunks, newopts = filterfn(ui, originalchunks)
282 chunks, newopts = filterfn(ui, originalchunks)
283 except error.PatchError as err:
283 except error.PatchError as err:
284 raise error.Abort(_('error parsing patch: %s') % err)
284 raise error.Abort(_('error parsing patch: %s') % err)
285 opts.update(newopts)
285 opts.update(newopts)
286
286
287 # We need to keep a backup of files that have been newly added and
287 # We need to keep a backup of files that have been newly added and
288 # modified during the recording process because there is a previous
288 # modified during the recording process because there is a previous
289 # version without the edit in the workdir
289 # version without the edit in the workdir
290 newlyaddedandmodifiedfiles = newandmodified(chunks, originalchunks)
290 newlyaddedandmodifiedfiles = newandmodified(chunks, originalchunks)
291 contenders = set()
291 contenders = set()
292 for h in chunks:
292 for h in chunks:
293 try:
293 try:
294 contenders.update(set(h.files()))
294 contenders.update(set(h.files()))
295 except AttributeError:
295 except AttributeError:
296 pass
296 pass
297
297
298 changed = status.modified + status.added + status.removed
298 changed = status.modified + status.added + status.removed
299 newfiles = [f for f in changed if f in contenders]
299 newfiles = [f for f in changed if f in contenders]
300 if not newfiles:
300 if not newfiles:
301 ui.status(_('no changes to record\n'))
301 ui.status(_('no changes to record\n'))
302 return 0
302 return 0
303
303
304 modified = set(status.modified)
304 modified = set(status.modified)
305
305
306 # 2. backup changed files, so we can restore them in the end
306 # 2. backup changed files, so we can restore them in the end
307
307
308 if backupall:
308 if backupall:
309 tobackup = changed
309 tobackup = changed
310 else:
310 else:
311 tobackup = [f for f in newfiles if f in modified or f in \
311 tobackup = [f for f in newfiles if f in modified or f in \
312 newlyaddedandmodifiedfiles]
312 newlyaddedandmodifiedfiles]
313 backups = {}
313 backups = {}
314 if tobackup:
314 if tobackup:
315 backupdir = repo.vfs.join('record-backups')
315 backupdir = repo.vfs.join('record-backups')
316 try:
316 try:
317 os.mkdir(backupdir)
317 os.mkdir(backupdir)
318 except OSError as err:
318 except OSError as err:
319 if err.errno != errno.EEXIST:
319 if err.errno != errno.EEXIST:
320 raise
320 raise
321 try:
321 try:
322 # backup continues
322 # backup continues
323 for f in tobackup:
323 for f in tobackup:
324 fd, tmpname = tempfile.mkstemp(prefix=f.replace('/', '_')+'.',
324 fd, tmpname = tempfile.mkstemp(prefix=f.replace('/', '_')+'.',
325 dir=backupdir)
325 dir=backupdir)
326 os.close(fd)
326 os.close(fd)
327 ui.debug('backup %r as %r\n' % (f, tmpname))
327 ui.debug('backup %r as %r\n' % (f, tmpname))
328 util.copyfile(repo.wjoin(f), tmpname, copystat=True)
328 util.copyfile(repo.wjoin(f), tmpname, copystat=True)
329 backups[f] = tmpname
329 backups[f] = tmpname
330
330
331 fp = stringio()
331 fp = stringio()
332 for c in chunks:
332 for c in chunks:
333 fname = c.filename()
333 fname = c.filename()
334 if fname in backups:
334 if fname in backups:
335 c.write(fp)
335 c.write(fp)
336 dopatch = fp.tell()
336 dopatch = fp.tell()
337 fp.seek(0)
337 fp.seek(0)
338
338
339 # 2.5 optionally review / modify patch in text editor
339 # 2.5 optionally review / modify patch in text editor
340 if opts.get('review', False):
340 if opts.get('review', False):
341 patchtext = (crecordmod.diffhelptext
341 patchtext = (crecordmod.diffhelptext
342 + crecordmod.patchhelptext
342 + crecordmod.patchhelptext
343 + fp.read())
343 + fp.read())
344 reviewedpatch = ui.edit(patchtext, "",
344 reviewedpatch = ui.edit(patchtext, "",
345 action="diff",
345 action="diff",
346 repopath=repo.path)
346 repopath=repo.path)
347 fp.truncate(0)
347 fp.truncate(0)
348 fp.write(reviewedpatch)
348 fp.write(reviewedpatch)
349 fp.seek(0)
349 fp.seek(0)
350
350
351 [os.unlink(repo.wjoin(c)) for c in newlyaddedandmodifiedfiles]
351 [os.unlink(repo.wjoin(c)) for c in newlyaddedandmodifiedfiles]
352 # 3a. apply filtered patch to clean repo (clean)
352 # 3a. apply filtered patch to clean repo (clean)
353 if backups:
353 if backups:
354 # Equivalent to hg.revert
354 # Equivalent to hg.revert
355 m = scmutil.matchfiles(repo, backups.keys())
355 m = scmutil.matchfiles(repo, backups.keys())
356 mergemod.update(repo, repo.dirstate.p1(),
356 mergemod.update(repo, repo.dirstate.p1(),
357 False, True, matcher=m)
357 False, True, matcher=m)
358
358
359 # 3b. (apply)
359 # 3b. (apply)
360 if dopatch:
360 if dopatch:
361 try:
361 try:
362 ui.debug('applying patch\n')
362 ui.debug('applying patch\n')
363 ui.debug(fp.getvalue())
363 ui.debug(fp.getvalue())
364 patch.internalpatch(ui, repo, fp, 1, eolmode=None)
364 patch.internalpatch(ui, repo, fp, 1, eolmode=None)
365 except error.PatchError as err:
365 except error.PatchError as err:
366 raise error.Abort(str(err))
366 raise error.Abort(str(err))
367 del fp
367 del fp
368
368
369 # 4. We prepared working directory according to filtered
369 # 4. We prepared working directory according to filtered
370 # patch. Now is the time to delegate the job to
370 # patch. Now is the time to delegate the job to
371 # commit/qrefresh or the like!
371 # commit/qrefresh or the like!
372
372
373 # Make all of the pathnames absolute.
373 # Make all of the pathnames absolute.
374 newfiles = [repo.wjoin(nf) for nf in newfiles]
374 newfiles = [repo.wjoin(nf) for nf in newfiles]
375 return commitfunc(ui, repo, *newfiles, **opts)
375 return commitfunc(ui, repo, *newfiles, **opts)
376 finally:
376 finally:
377 # 5. finally restore backed-up files
377 # 5. finally restore backed-up files
378 try:
378 try:
379 dirstate = repo.dirstate
379 dirstate = repo.dirstate
380 for realname, tmpname in backups.iteritems():
380 for realname, tmpname in backups.iteritems():
381 ui.debug('restoring %r to %r\n' % (tmpname, realname))
381 ui.debug('restoring %r to %r\n' % (tmpname, realname))
382
382
383 if dirstate[realname] == 'n':
383 if dirstate[realname] == 'n':
384 # without normallookup, restoring timestamp
384 # without normallookup, restoring timestamp
385 # may cause partially committed files
385 # may cause partially committed files
386 # to be treated as unmodified
386 # to be treated as unmodified
387 dirstate.normallookup(realname)
387 dirstate.normallookup(realname)
388
388
389 # copystat=True here and above are a hack to trick any
389 # copystat=True here and above are a hack to trick any
390 # editors that have f open that we haven't modified them.
390 # editors that have f open that we haven't modified them.
391 #
391 #
392 # Also note that this racy as an editor could notice the
392 # Also note that this racy as an editor could notice the
393 # file's mtime before we've finished writing it.
393 # file's mtime before we've finished writing it.
394 util.copyfile(tmpname, repo.wjoin(realname), copystat=True)
394 util.copyfile(tmpname, repo.wjoin(realname), copystat=True)
395 os.unlink(tmpname)
395 os.unlink(tmpname)
396 if tobackup:
396 if tobackup:
397 os.rmdir(backupdir)
397 os.rmdir(backupdir)
398 except OSError:
398 except OSError:
399 pass
399 pass
400
400
401 def recordinwlock(ui, repo, message, match, opts):
401 def recordinwlock(ui, repo, message, match, opts):
402 with repo.wlock():
402 with repo.wlock():
403 return recordfunc(ui, repo, message, match, opts)
403 return recordfunc(ui, repo, message, match, opts)
404
404
405 return commit(ui, repo, recordinwlock, pats, opts)
405 return commit(ui, repo, recordinwlock, pats, opts)
406
406
407
407
408 # extracted at module level as it's required each time a file will be added
408 # extracted at module level as it's required each time a file will be added
409 # to dirnode class object below
409 # to dirnode class object below
410 pathsep = pycompat.ossep
410 pathsep = pycompat.ossep
411
411
412 class dirnode(object):
412 class dirnode(object):
413 """
413 """
414 Represent a directory in user working copy with information required for
414 Represent a directory in user working copy with information required for
415 the purpose of tersing its status.
415 the purpose of tersing its status.
416
416
417 path is the path to the directory
417 path is the path to the directory
418
418
419 statuses is a set of statuses of all files in this directory (this includes
419 statuses is a set of statuses of all files in this directory (this includes
420 all the files in all the subdirectories too)
420 all the files in all the subdirectories too)
421
421
422 files is a list of files which are direct child of this directory
422 files is a list of files which are direct child of this directory
423
423
424 subdirs is a dictionary of sub-directory name as the key and it's own
424 subdirs is a dictionary of sub-directory name as the key and it's own
425 dirnode object as the value
425 dirnode object as the value
426 """
426 """
427
427
428 def __init__(self, dirpath):
428 def __init__(self, dirpath):
429 self.path = dirpath
429 self.path = dirpath
430 self.statuses = set([])
430 self.statuses = set([])
431 self.files = []
431 self.files = []
432 self.subdirs = {}
432 self.subdirs = {}
433
433
434 def _addfileindir(self, filename, status):
434 def _addfileindir(self, filename, status):
435 """Add a file in this directory as a direct child."""
435 """Add a file in this directory as a direct child."""
436 self.files.append((filename, status))
436 self.files.append((filename, status))
437
437
438 def addfile(self, filename, status):
438 def addfile(self, filename, status):
439 """
439 """
440 Add a file to this directory or to its direct parent directory.
440 Add a file to this directory or to its direct parent directory.
441
441
442 If the file is not direct child of this directory, we traverse to the
442 If the file is not direct child of this directory, we traverse to the
443 directory of which this file is a direct child of and add the file
443 directory of which this file is a direct child of and add the file
444 there.
444 there.
445 """
445 """
446
446
447 # the filename contains a path separator, it means it's not the direct
447 # the filename contains a path separator, it means it's not the direct
448 # child of this directory
448 # child of this directory
449 if pathsep in filename:
449 if pathsep in filename:
450 subdir, filep = filename.split(pathsep, 1)
450 subdir, filep = filename.split(pathsep, 1)
451
451
452 # does the dirnode object for subdir exists
452 # does the dirnode object for subdir exists
453 if subdir not in self.subdirs:
453 if subdir not in self.subdirs:
454 subdirpath = os.path.join(self.path, subdir)
454 subdirpath = os.path.join(self.path, subdir)
455 self.subdirs[subdir] = dirnode(subdirpath)
455 self.subdirs[subdir] = dirnode(subdirpath)
456
456
457 # try adding the file in subdir
457 # try adding the file in subdir
458 self.subdirs[subdir].addfile(filep, status)
458 self.subdirs[subdir].addfile(filep, status)
459
459
460 else:
460 else:
461 self._addfileindir(filename, status)
461 self._addfileindir(filename, status)
462
462
463 if status not in self.statuses:
463 if status not in self.statuses:
464 self.statuses.add(status)
464 self.statuses.add(status)
465
465
466 def iterfilepaths(self):
466 def iterfilepaths(self):
467 """Yield (status, path) for files directly under this directory."""
467 """Yield (status, path) for files directly under this directory."""
468 for f, st in self.files:
468 for f, st in self.files:
469 yield st, os.path.join(self.path, f)
469 yield st, os.path.join(self.path, f)
470
470
471 def tersewalk(self, terseargs):
471 def tersewalk(self, terseargs):
472 """
472 """
473 Yield (status, path) obtained by processing the status of this
473 Yield (status, path) obtained by processing the status of this
474 dirnode.
474 dirnode.
475
475
476 terseargs is the string of arguments passed by the user with `--terse`
476 terseargs is the string of arguments passed by the user with `--terse`
477 flag.
477 flag.
478
478
479 Following are the cases which can happen:
479 Following are the cases which can happen:
480
480
481 1) All the files in the directory (including all the files in its
481 1) All the files in the directory (including all the files in its
482 subdirectories) share the same status and the user has asked us to terse
482 subdirectories) share the same status and the user has asked us to terse
483 that status. -> yield (status, dirpath)
483 that status. -> yield (status, dirpath)
484
484
485 2) Otherwise, we do following:
485 2) Otherwise, we do following:
486
486
487 a) Yield (status, filepath) for all the files which are in this
487 a) Yield (status, filepath) for all the files which are in this
488 directory (only the ones in this directory, not the subdirs)
488 directory (only the ones in this directory, not the subdirs)
489
489
490 b) Recurse the function on all the subdirectories of this
490 b) Recurse the function on all the subdirectories of this
491 directory
491 directory
492 """
492 """
493
493
494 if len(self.statuses) == 1:
494 if len(self.statuses) == 1:
495 onlyst = self.statuses.pop()
495 onlyst = self.statuses.pop()
496
496
497 # Making sure we terse only when the status abbreviation is
497 # Making sure we terse only when the status abbreviation is
498 # passed as terse argument
498 # passed as terse argument
499 if onlyst in terseargs:
499 if onlyst in terseargs:
500 yield onlyst, self.path + pycompat.ossep
500 yield onlyst, self.path + pycompat.ossep
501 return
501 return
502
502
503 # add the files to status list
503 # add the files to status list
504 for st, fpath in self.iterfilepaths():
504 for st, fpath in self.iterfilepaths():
505 yield st, fpath
505 yield st, fpath
506
506
507 #recurse on the subdirs
507 #recurse on the subdirs
508 for dirobj in self.subdirs.values():
508 for dirobj in self.subdirs.values():
509 for st, fpath in dirobj.tersewalk(terseargs):
509 for st, fpath in dirobj.tersewalk(terseargs):
510 yield st, fpath
510 yield st, fpath
511
511
512 def tersedir(statuslist, terseargs):
512 def tersedir(statuslist, terseargs):
513 """
513 """
514 Terse the status if all the files in a directory shares the same status.
514 Terse the status if all the files in a directory shares the same status.
515
515
516 statuslist is scmutil.status() object which contains a list of files for
516 statuslist is scmutil.status() object which contains a list of files for
517 each status.
517 each status.
518 terseargs is string which is passed by the user as the argument to `--terse`
518 terseargs is string which is passed by the user as the argument to `--terse`
519 flag.
519 flag.
520
520
521 The function makes a tree of objects of dirnode class, and at each node it
521 The function makes a tree of objects of dirnode class, and at each node it
522 stores the information required to know whether we can terse a certain
522 stores the information required to know whether we can terse a certain
523 directory or not.
523 directory or not.
524 """
524 """
525 # the order matters here as that is used to produce final list
525 # the order matters here as that is used to produce final list
526 allst = ('m', 'a', 'r', 'd', 'u', 'i', 'c')
526 allst = ('m', 'a', 'r', 'd', 'u', 'i', 'c')
527
527
528 # checking the argument validity
528 # checking the argument validity
529 for s in pycompat.bytestr(terseargs):
529 for s in pycompat.bytestr(terseargs):
530 if s not in allst:
530 if s not in allst:
531 raise error.Abort(_("'%s' not recognized") % s)
531 raise error.Abort(_("'%s' not recognized") % s)
532
532
533 # creating a dirnode object for the root of the repo
533 # creating a dirnode object for the root of the repo
534 rootobj = dirnode('')
534 rootobj = dirnode('')
535 pstatus = ('modified', 'added', 'deleted', 'clean', 'unknown',
535 pstatus = ('modified', 'added', 'deleted', 'clean', 'unknown',
536 'ignored', 'removed')
536 'ignored', 'removed')
537
537
538 tersedict = {}
538 tersedict = {}
539 for attrname in pstatus:
539 for attrname in pstatus:
540 statuschar = attrname[0:1]
540 statuschar = attrname[0:1]
541 for f in getattr(statuslist, attrname):
541 for f in getattr(statuslist, attrname):
542 rootobj.addfile(f, statuschar)
542 rootobj.addfile(f, statuschar)
543 tersedict[statuschar] = []
543 tersedict[statuschar] = []
544
544
545 # we won't be tersing the root dir, so add files in it
545 # we won't be tersing the root dir, so add files in it
546 for st, fpath in rootobj.iterfilepaths():
546 for st, fpath in rootobj.iterfilepaths():
547 tersedict[st].append(fpath)
547 tersedict[st].append(fpath)
548
548
549 # process each sub-directory and build tersedict
549 # process each sub-directory and build tersedict
550 for subdir in rootobj.subdirs.values():
550 for subdir in rootobj.subdirs.values():
551 for st, f in subdir.tersewalk(terseargs):
551 for st, f in subdir.tersewalk(terseargs):
552 tersedict[st].append(f)
552 tersedict[st].append(f)
553
553
554 tersedlist = []
554 tersedlist = []
555 for st in allst:
555 for st in allst:
556 tersedict[st].sort()
556 tersedict[st].sort()
557 tersedlist.append(tersedict[st])
557 tersedlist.append(tersedict[st])
558
558
559 return tersedlist
559 return tersedlist
560
560
561 def _commentlines(raw):
561 def _commentlines(raw):
562 '''Surround lineswith a comment char and a new line'''
562 '''Surround lineswith a comment char and a new line'''
563 lines = raw.splitlines()
563 lines = raw.splitlines()
564 commentedlines = ['# %s' % line for line in lines]
564 commentedlines = ['# %s' % line for line in lines]
565 return '\n'.join(commentedlines) + '\n'
565 return '\n'.join(commentedlines) + '\n'
566
566
567 def _conflictsmsg(repo):
567 def _conflictsmsg(repo):
568 # avoid merge cycle
568 # avoid merge cycle
569 from . import merge as mergemod
569 from . import merge as mergemod
570 mergestate = mergemod.mergestate.read(repo)
570 mergestate = mergemod.mergestate.read(repo)
571 if not mergestate.active():
571 if not mergestate.active():
572 return
572 return
573
573
574 m = scmutil.match(repo[None])
574 m = scmutil.match(repo[None])
575 unresolvedlist = [f for f in mergestate.unresolved() if m(f)]
575 unresolvedlist = [f for f in mergestate.unresolved() if m(f)]
576 if unresolvedlist:
576 if unresolvedlist:
577 mergeliststr = '\n'.join(
577 mergeliststr = '\n'.join(
578 [' %s' % os.path.relpath(
578 [' %s' % os.path.relpath(
579 os.path.join(repo.root, path),
579 os.path.join(repo.root, path),
580 pycompat.getcwd()) for path in unresolvedlist])
580 pycompat.getcwd()) for path in unresolvedlist])
581 msg = _('''Unresolved merge conflicts:
581 msg = _('''Unresolved merge conflicts:
582
582
583 %s
583 %s
584
584
585 To mark files as resolved: hg resolve --mark FILE''') % mergeliststr
585 To mark files as resolved: hg resolve --mark FILE''') % mergeliststr
586 else:
586 else:
587 msg = _('No unresolved merge conflicts.')
587 msg = _('No unresolved merge conflicts.')
588
588
589 return _commentlines(msg)
589 return _commentlines(msg)
590
590
591 def _helpmessage(continuecmd, abortcmd):
591 def _helpmessage(continuecmd, abortcmd):
592 msg = _('To continue: %s\n'
592 msg = _('To continue: %s\n'
593 'To abort: %s') % (continuecmd, abortcmd)
593 'To abort: %s') % (continuecmd, abortcmd)
594 return _commentlines(msg)
594 return _commentlines(msg)
595
595
596 def _rebasemsg():
596 def _rebasemsg():
597 return _helpmessage('hg rebase --continue', 'hg rebase --abort')
597 return _helpmessage('hg rebase --continue', 'hg rebase --abort')
598
598
599 def _histeditmsg():
599 def _histeditmsg():
600 return _helpmessage('hg histedit --continue', 'hg histedit --abort')
600 return _helpmessage('hg histedit --continue', 'hg histedit --abort')
601
601
602 def _unshelvemsg():
602 def _unshelvemsg():
603 return _helpmessage('hg unshelve --continue', 'hg unshelve --abort')
603 return _helpmessage('hg unshelve --continue', 'hg unshelve --abort')
604
604
605 def _updatecleanmsg(dest=None):
605 def _updatecleanmsg(dest=None):
606 warning = _('warning: this will discard uncommitted changes')
606 warning = _('warning: this will discard uncommitted changes')
607 return 'hg update --clean %s (%s)' % (dest or '.', warning)
607 return 'hg update --clean %s (%s)' % (dest or '.', warning)
608
608
609 def _graftmsg():
609 def _graftmsg():
610 # tweakdefaults requires `update` to have a rev hence the `.`
610 # tweakdefaults requires `update` to have a rev hence the `.`
611 return _helpmessage('hg graft --continue', _updatecleanmsg())
611 return _helpmessage('hg graft --continue', _updatecleanmsg())
612
612
613 def _mergemsg():
613 def _mergemsg():
614 # tweakdefaults requires `update` to have a rev hence the `.`
614 # tweakdefaults requires `update` to have a rev hence the `.`
615 return _helpmessage('hg commit', _updatecleanmsg())
615 return _helpmessage('hg commit', _updatecleanmsg())
616
616
617 def _bisectmsg():
617 def _bisectmsg():
618 msg = _('To mark the changeset good: hg bisect --good\n'
618 msg = _('To mark the changeset good: hg bisect --good\n'
619 'To mark the changeset bad: hg bisect --bad\n'
619 'To mark the changeset bad: hg bisect --bad\n'
620 'To abort: hg bisect --reset\n')
620 'To abort: hg bisect --reset\n')
621 return _commentlines(msg)
621 return _commentlines(msg)
622
622
623 def fileexistspredicate(filename):
623 def fileexistspredicate(filename):
624 return lambda repo: repo.vfs.exists(filename)
624 return lambda repo: repo.vfs.exists(filename)
625
625
626 def _mergepredicate(repo):
626 def _mergepredicate(repo):
627 return len(repo[None].parents()) > 1
627 return len(repo[None].parents()) > 1
628
628
629 STATES = (
629 STATES = (
630 # (state, predicate to detect states, helpful message function)
630 # (state, predicate to detect states, helpful message function)
631 ('histedit', fileexistspredicate('histedit-state'), _histeditmsg),
631 ('histedit', fileexistspredicate('histedit-state'), _histeditmsg),
632 ('bisect', fileexistspredicate('bisect.state'), _bisectmsg),
632 ('bisect', fileexistspredicate('bisect.state'), _bisectmsg),
633 ('graft', fileexistspredicate('graftstate'), _graftmsg),
633 ('graft', fileexistspredicate('graftstate'), _graftmsg),
634 ('unshelve', fileexistspredicate('unshelverebasestate'), _unshelvemsg),
634 ('unshelve', fileexistspredicate('unshelverebasestate'), _unshelvemsg),
635 ('rebase', fileexistspredicate('rebasestate'), _rebasemsg),
635 ('rebase', fileexistspredicate('rebasestate'), _rebasemsg),
636 # The merge state is part of a list that will be iterated over.
636 # The merge state is part of a list that will be iterated over.
637 # They need to be last because some of the other unfinished states may also
637 # They need to be last because some of the other unfinished states may also
638 # be in a merge or update state (eg. rebase, histedit, graft, etc).
638 # be in a merge or update state (eg. rebase, histedit, graft, etc).
639 # We want those to have priority.
639 # We want those to have priority.
640 ('merge', _mergepredicate, _mergemsg),
640 ('merge', _mergepredicate, _mergemsg),
641 )
641 )
642
642
643 def _getrepostate(repo):
643 def _getrepostate(repo):
644 # experimental config: commands.status.skipstates
644 # experimental config: commands.status.skipstates
645 skip = set(repo.ui.configlist('commands', 'status.skipstates'))
645 skip = set(repo.ui.configlist('commands', 'status.skipstates'))
646 for state, statedetectionpredicate, msgfn in STATES:
646 for state, statedetectionpredicate, msgfn in STATES:
647 if state in skip:
647 if state in skip:
648 continue
648 continue
649 if statedetectionpredicate(repo):
649 if statedetectionpredicate(repo):
650 return (state, statedetectionpredicate, msgfn)
650 return (state, statedetectionpredicate, msgfn)
651
651
652 def morestatus(repo, fm):
652 def morestatus(repo, fm):
653 statetuple = _getrepostate(repo)
653 statetuple = _getrepostate(repo)
654 label = 'status.morestatus'
654 label = 'status.morestatus'
655 if statetuple:
655 if statetuple:
656 fm.startitem()
656 fm.startitem()
657 state, statedetectionpredicate, helpfulmsg = statetuple
657 state, statedetectionpredicate, helpfulmsg = statetuple
658 statemsg = _('The repository is in an unfinished *%s* state.') % state
658 statemsg = _('The repository is in an unfinished *%s* state.') % state
659 fm.write('statemsg', '%s\n', _commentlines(statemsg), label=label)
659 fm.write('statemsg', '%s\n', _commentlines(statemsg), label=label)
660 conmsg = _conflictsmsg(repo)
660 conmsg = _conflictsmsg(repo)
661 if conmsg:
661 if conmsg:
662 fm.write('conflictsmsg', '%s\n', conmsg, label=label)
662 fm.write('conflictsmsg', '%s\n', conmsg, label=label)
663 if helpfulmsg:
663 if helpfulmsg:
664 helpmsg = helpfulmsg()
664 helpmsg = helpfulmsg()
665 fm.write('helpmsg', '%s\n', helpmsg, label=label)
665 fm.write('helpmsg', '%s\n', helpmsg, label=label)
666
666
667 def findpossible(cmd, table, strict=False):
667 def findpossible(cmd, table, strict=False):
668 """
668 """
669 Return cmd -> (aliases, command table entry)
669 Return cmd -> (aliases, command table entry)
670 for each matching command.
670 for each matching command.
671 Return debug commands (or their aliases) only if no normal command matches.
671 Return debug commands (or their aliases) only if no normal command matches.
672 """
672 """
673 choice = {}
673 choice = {}
674 debugchoice = {}
674 debugchoice = {}
675
675
676 if cmd in table:
676 if cmd in table:
677 # short-circuit exact matches, "log" alias beats "^log|history"
677 # short-circuit exact matches, "log" alias beats "^log|history"
678 keys = [cmd]
678 keys = [cmd]
679 else:
679 else:
680 keys = table.keys()
680 keys = table.keys()
681
681
682 allcmds = []
682 allcmds = []
683 for e in keys:
683 for e in keys:
684 aliases = parsealiases(e)
684 aliases = parsealiases(e)
685 allcmds.extend(aliases)
685 allcmds.extend(aliases)
686 found = None
686 found = None
687 if cmd in aliases:
687 if cmd in aliases:
688 found = cmd
688 found = cmd
689 elif not strict:
689 elif not strict:
690 for a in aliases:
690 for a in aliases:
691 if a.startswith(cmd):
691 if a.startswith(cmd):
692 found = a
692 found = a
693 break
693 break
694 if found is not None:
694 if found is not None:
695 if aliases[0].startswith("debug") or found.startswith("debug"):
695 if aliases[0].startswith("debug") or found.startswith("debug"):
696 debugchoice[found] = (aliases, table[e])
696 debugchoice[found] = (aliases, table[e])
697 else:
697 else:
698 choice[found] = (aliases, table[e])
698 choice[found] = (aliases, table[e])
699
699
700 if not choice and debugchoice:
700 if not choice and debugchoice:
701 choice = debugchoice
701 choice = debugchoice
702
702
703 return choice, allcmds
703 return choice, allcmds
704
704
705 def findcmd(cmd, table, strict=True):
705 def findcmd(cmd, table, strict=True):
706 """Return (aliases, command table entry) for command string."""
706 """Return (aliases, command table entry) for command string."""
707 choice, allcmds = findpossible(cmd, table, strict)
707 choice, allcmds = findpossible(cmd, table, strict)
708
708
709 if cmd in choice:
709 if cmd in choice:
710 return choice[cmd]
710 return choice[cmd]
711
711
712 if len(choice) > 1:
712 if len(choice) > 1:
713 clist = sorted(choice)
713 clist = sorted(choice)
714 raise error.AmbiguousCommand(cmd, clist)
714 raise error.AmbiguousCommand(cmd, clist)
715
715
716 if choice:
716 if choice:
717 return list(choice.values())[0]
717 return list(choice.values())[0]
718
718
719 raise error.UnknownCommand(cmd, allcmds)
719 raise error.UnknownCommand(cmd, allcmds)
720
720
721 def findrepo(p):
721 def findrepo(p):
722 while not os.path.isdir(os.path.join(p, ".hg")):
722 while not os.path.isdir(os.path.join(p, ".hg")):
723 oldp, p = p, os.path.dirname(p)
723 oldp, p = p, os.path.dirname(p)
724 if p == oldp:
724 if p == oldp:
725 return None
725 return None
726
726
727 return p
727 return p
728
728
729 def bailifchanged(repo, merge=True, hint=None):
729 def bailifchanged(repo, merge=True, hint=None):
730 """ enforce the precondition that working directory must be clean.
730 """ enforce the precondition that working directory must be clean.
731
731
732 'merge' can be set to false if a pending uncommitted merge should be
732 'merge' can be set to false if a pending uncommitted merge should be
733 ignored (such as when 'update --check' runs).
733 ignored (such as when 'update --check' runs).
734
734
735 'hint' is the usual hint given to Abort exception.
735 'hint' is the usual hint given to Abort exception.
736 """
736 """
737
737
738 if merge and repo.dirstate.p2() != nullid:
738 if merge and repo.dirstate.p2() != nullid:
739 raise error.Abort(_('outstanding uncommitted merge'), hint=hint)
739 raise error.Abort(_('outstanding uncommitted merge'), hint=hint)
740 modified, added, removed, deleted = repo.status()[:4]
740 modified, added, removed, deleted = repo.status()[:4]
741 if modified or added or removed or deleted:
741 if modified or added or removed or deleted:
742 raise error.Abort(_('uncommitted changes'), hint=hint)
742 raise error.Abort(_('uncommitted changes'), hint=hint)
743 ctx = repo[None]
743 ctx = repo[None]
744 for s in sorted(ctx.substate):
744 for s in sorted(ctx.substate):
745 ctx.sub(s).bailifchanged(hint=hint)
745 ctx.sub(s).bailifchanged(hint=hint)
746
746
747 def logmessage(ui, opts):
747 def logmessage(ui, opts):
748 """ get the log message according to -m and -l option """
748 """ get the log message according to -m and -l option """
749 message = opts.get('message')
749 message = opts.get('message')
750 logfile = opts.get('logfile')
750 logfile = opts.get('logfile')
751
751
752 if message and logfile:
752 if message and logfile:
753 raise error.Abort(_('options --message and --logfile are mutually '
753 raise error.Abort(_('options --message and --logfile are mutually '
754 'exclusive'))
754 'exclusive'))
755 if not message and logfile:
755 if not message and logfile:
756 try:
756 try:
757 if isstdiofilename(logfile):
757 if isstdiofilename(logfile):
758 message = ui.fin.read()
758 message = ui.fin.read()
759 else:
759 else:
760 message = '\n'.join(util.readfile(logfile).splitlines())
760 message = '\n'.join(util.readfile(logfile).splitlines())
761 except IOError as inst:
761 except IOError as inst:
762 raise error.Abort(_("can't read commit message '%s': %s") %
762 raise error.Abort(_("can't read commit message '%s': %s") %
763 (logfile, encoding.strtolocal(inst.strerror)))
763 (logfile, encoding.strtolocal(inst.strerror)))
764 return message
764 return message
765
765
766 def mergeeditform(ctxorbool, baseformname):
766 def mergeeditform(ctxorbool, baseformname):
767 """return appropriate editform name (referencing a committemplate)
767 """return appropriate editform name (referencing a committemplate)
768
768
769 'ctxorbool' is either a ctx to be committed, or a bool indicating whether
769 'ctxorbool' is either a ctx to be committed, or a bool indicating whether
770 merging is committed.
770 merging is committed.
771
771
772 This returns baseformname with '.merge' appended if it is a merge,
772 This returns baseformname with '.merge' appended if it is a merge,
773 otherwise '.normal' is appended.
773 otherwise '.normal' is appended.
774 """
774 """
775 if isinstance(ctxorbool, bool):
775 if isinstance(ctxorbool, bool):
776 if ctxorbool:
776 if ctxorbool:
777 return baseformname + ".merge"
777 return baseformname + ".merge"
778 elif 1 < len(ctxorbool.parents()):
778 elif 1 < len(ctxorbool.parents()):
779 return baseformname + ".merge"
779 return baseformname + ".merge"
780
780
781 return baseformname + ".normal"
781 return baseformname + ".normal"
782
782
783 def getcommiteditor(edit=False, finishdesc=None, extramsg=None,
783 def getcommiteditor(edit=False, finishdesc=None, extramsg=None,
784 editform='', **opts):
784 editform='', **opts):
785 """get appropriate commit message editor according to '--edit' option
785 """get appropriate commit message editor according to '--edit' option
786
786
787 'finishdesc' is a function to be called with edited commit message
787 'finishdesc' is a function to be called with edited commit message
788 (= 'description' of the new changeset) just after editing, but
788 (= 'description' of the new changeset) just after editing, but
789 before checking empty-ness. It should return actual text to be
789 before checking empty-ness. It should return actual text to be
790 stored into history. This allows to change description before
790 stored into history. This allows to change description before
791 storing.
791 storing.
792
792
793 'extramsg' is a extra message to be shown in the editor instead of
793 'extramsg' is a extra message to be shown in the editor instead of
794 'Leave message empty to abort commit' line. 'HG: ' prefix and EOL
794 'Leave message empty to abort commit' line. 'HG: ' prefix and EOL
795 is automatically added.
795 is automatically added.
796
796
797 'editform' is a dot-separated list of names, to distinguish
797 'editform' is a dot-separated list of names, to distinguish
798 the purpose of commit text editing.
798 the purpose of commit text editing.
799
799
800 'getcommiteditor' returns 'commitforceeditor' regardless of
800 'getcommiteditor' returns 'commitforceeditor' regardless of
801 'edit', if one of 'finishdesc' or 'extramsg' is specified, because
801 'edit', if one of 'finishdesc' or 'extramsg' is specified, because
802 they are specific for usage in MQ.
802 they are specific for usage in MQ.
803 """
803 """
804 if edit or finishdesc or extramsg:
804 if edit or finishdesc or extramsg:
805 return lambda r, c, s: commitforceeditor(r, c, s,
805 return lambda r, c, s: commitforceeditor(r, c, s,
806 finishdesc=finishdesc,
806 finishdesc=finishdesc,
807 extramsg=extramsg,
807 extramsg=extramsg,
808 editform=editform)
808 editform=editform)
809 elif editform:
809 elif editform:
810 return lambda r, c, s: commiteditor(r, c, s, editform=editform)
810 return lambda r, c, s: commiteditor(r, c, s, editform=editform)
811 else:
811 else:
812 return commiteditor
812 return commiteditor
813
813
814 def loglimit(opts):
814 def loglimit(opts):
815 """get the log limit according to option -l/--limit"""
815 """get the log limit according to option -l/--limit"""
816 limit = opts.get('limit')
816 limit = opts.get('limit')
817 if limit:
817 if limit:
818 try:
818 try:
819 limit = int(limit)
819 limit = int(limit)
820 except ValueError:
820 except ValueError:
821 raise error.Abort(_('limit must be a positive integer'))
821 raise error.Abort(_('limit must be a positive integer'))
822 if limit <= 0:
822 if limit <= 0:
823 raise error.Abort(_('limit must be positive'))
823 raise error.Abort(_('limit must be positive'))
824 else:
824 else:
825 limit = None
825 limit = None
826 return limit
826 return limit
827
827
828 def makefilename(repo, pat, node, desc=None,
828 def makefilename(repo, pat, node, desc=None,
829 total=None, seqno=None, revwidth=None, pathname=None):
829 total=None, seqno=None, revwidth=None, pathname=None):
830 node_expander = {
830 node_expander = {
831 'H': lambda: hex(node),
831 'H': lambda: hex(node),
832 'R': lambda: str(repo.changelog.rev(node)),
832 'R': lambda: str(repo.changelog.rev(node)),
833 'h': lambda: short(node),
833 'h': lambda: short(node),
834 'm': lambda: re.sub('[^\w]', '_', str(desc))
834 'm': lambda: re.sub('[^\w]', '_', str(desc))
835 }
835 }
836 expander = {
836 expander = {
837 '%': lambda: '%',
837 '%': lambda: '%',
838 'b': lambda: os.path.basename(repo.root),
838 'b': lambda: os.path.basename(repo.root),
839 }
839 }
840
840
841 try:
841 try:
842 if node:
842 if node:
843 expander.update(node_expander)
843 expander.update(node_expander)
844 if node:
844 if node:
845 expander['r'] = (lambda:
845 expander['r'] = (lambda:
846 str(repo.changelog.rev(node)).zfill(revwidth or 0))
846 str(repo.changelog.rev(node)).zfill(revwidth or 0))
847 if total is not None:
847 if total is not None:
848 expander['N'] = lambda: str(total)
848 expander['N'] = lambda: str(total)
849 if seqno is not None:
849 if seqno is not None:
850 expander['n'] = lambda: str(seqno)
850 expander['n'] = lambda: str(seqno)
851 if total is not None and seqno is not None:
851 if total is not None and seqno is not None:
852 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
852 expander['n'] = lambda: str(seqno).zfill(len(str(total)))
853 if pathname is not None:
853 if pathname is not None:
854 expander['s'] = lambda: os.path.basename(pathname)
854 expander['s'] = lambda: os.path.basename(pathname)
855 expander['d'] = lambda: os.path.dirname(pathname) or '.'
855 expander['d'] = lambda: os.path.dirname(pathname) or '.'
856 expander['p'] = lambda: pathname
856 expander['p'] = lambda: pathname
857
857
858 newname = []
858 newname = []
859 patlen = len(pat)
859 patlen = len(pat)
860 i = 0
860 i = 0
861 while i < patlen:
861 while i < patlen:
862 c = pat[i:i + 1]
862 c = pat[i:i + 1]
863 if c == '%':
863 if c == '%':
864 i += 1
864 i += 1
865 c = pat[i:i + 1]
865 c = pat[i:i + 1]
866 c = expander[c]()
866 c = expander[c]()
867 newname.append(c)
867 newname.append(c)
868 i += 1
868 i += 1
869 return ''.join(newname)
869 return ''.join(newname)
870 except KeyError as inst:
870 except KeyError as inst:
871 raise error.Abort(_("invalid format spec '%%%s' in output filename") %
871 raise error.Abort(_("invalid format spec '%%%s' in output filename") %
872 inst.args[0])
872 inst.args[0])
873
873
874 def isstdiofilename(pat):
874 def isstdiofilename(pat):
875 """True if the given pat looks like a filename denoting stdin/stdout"""
875 """True if the given pat looks like a filename denoting stdin/stdout"""
876 return not pat or pat == '-'
876 return not pat or pat == '-'
877
877
878 class _unclosablefile(object):
878 class _unclosablefile(object):
879 def __init__(self, fp):
879 def __init__(self, fp):
880 self._fp = fp
880 self._fp = fp
881
881
882 def close(self):
882 def close(self):
883 pass
883 pass
884
884
885 def __iter__(self):
885 def __iter__(self):
886 return iter(self._fp)
886 return iter(self._fp)
887
887
888 def __getattr__(self, attr):
888 def __getattr__(self, attr):
889 return getattr(self._fp, attr)
889 return getattr(self._fp, attr)
890
890
891 def __enter__(self):
891 def __enter__(self):
892 return self
892 return self
893
893
894 def __exit__(self, exc_type, exc_value, exc_tb):
894 def __exit__(self, exc_type, exc_value, exc_tb):
895 pass
895 pass
896
896
897 def makefileobj(repo, pat, node=None, desc=None, total=None,
897 def makefileobj(repo, pat, node=None, desc=None, total=None,
898 seqno=None, revwidth=None, mode='wb', modemap=None,
898 seqno=None, revwidth=None, mode='wb', modemap=None,
899 pathname=None):
899 pathname=None):
900
900
901 writable = mode not in ('r', 'rb')
901 writable = mode not in ('r', 'rb')
902
902
903 if isstdiofilename(pat):
903 if isstdiofilename(pat):
904 if writable:
904 if writable:
905 fp = repo.ui.fout
905 fp = repo.ui.fout
906 else:
906 else:
907 fp = repo.ui.fin
907 fp = repo.ui.fin
908 return _unclosablefile(fp)
908 return _unclosablefile(fp)
909 fn = makefilename(repo, pat, node, desc, total, seqno, revwidth, pathname)
909 fn = makefilename(repo, pat, node, desc, total, seqno, revwidth, pathname)
910 if modemap is not None:
910 if modemap is not None:
911 mode = modemap.get(fn, mode)
911 mode = modemap.get(fn, mode)
912 if mode == 'wb':
912 if mode == 'wb':
913 modemap[fn] = 'ab'
913 modemap[fn] = 'ab'
914 return open(fn, mode)
914 return open(fn, mode)
915
915
916 def openrevlog(repo, cmd, file_, opts):
916 def openrevlog(repo, cmd, file_, opts):
917 """opens the changelog, manifest, a filelog or a given revlog"""
917 """opens the changelog, manifest, a filelog or a given revlog"""
918 cl = opts['changelog']
918 cl = opts['changelog']
919 mf = opts['manifest']
919 mf = opts['manifest']
920 dir = opts['dir']
920 dir = opts['dir']
921 msg = None
921 msg = None
922 if cl and mf:
922 if cl and mf:
923 msg = _('cannot specify --changelog and --manifest at the same time')
923 msg = _('cannot specify --changelog and --manifest at the same time')
924 elif cl and dir:
924 elif cl and dir:
925 msg = _('cannot specify --changelog and --dir at the same time')
925 msg = _('cannot specify --changelog and --dir at the same time')
926 elif cl or mf or dir:
926 elif cl or mf or dir:
927 if file_:
927 if file_:
928 msg = _('cannot specify filename with --changelog or --manifest')
928 msg = _('cannot specify filename with --changelog or --manifest')
929 elif not repo:
929 elif not repo:
930 msg = _('cannot specify --changelog or --manifest or --dir '
930 msg = _('cannot specify --changelog or --manifest or --dir '
931 'without a repository')
931 'without a repository')
932 if msg:
932 if msg:
933 raise error.Abort(msg)
933 raise error.Abort(msg)
934
934
935 r = None
935 r = None
936 if repo:
936 if repo:
937 if cl:
937 if cl:
938 r = repo.unfiltered().changelog
938 r = repo.unfiltered().changelog
939 elif dir:
939 elif dir:
940 if 'treemanifest' not in repo.requirements:
940 if 'treemanifest' not in repo.requirements:
941 raise error.Abort(_("--dir can only be used on repos with "
941 raise error.Abort(_("--dir can only be used on repos with "
942 "treemanifest enabled"))
942 "treemanifest enabled"))
943 dirlog = repo.manifestlog._revlog.dirlog(dir)
943 dirlog = repo.manifestlog._revlog.dirlog(dir)
944 if len(dirlog):
944 if len(dirlog):
945 r = dirlog
945 r = dirlog
946 elif mf:
946 elif mf:
947 r = repo.manifestlog._revlog
947 r = repo.manifestlog._revlog
948 elif file_:
948 elif file_:
949 filelog = repo.file(file_)
949 filelog = repo.file(file_)
950 if len(filelog):
950 if len(filelog):
951 r = filelog
951 r = filelog
952 if not r:
952 if not r:
953 if not file_:
953 if not file_:
954 raise error.CommandError(cmd, _('invalid arguments'))
954 raise error.CommandError(cmd, _('invalid arguments'))
955 if not os.path.isfile(file_):
955 if not os.path.isfile(file_):
956 raise error.Abort(_("revlog '%s' not found") % file_)
956 raise error.Abort(_("revlog '%s' not found") % file_)
957 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
957 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
958 file_[:-2] + ".i")
958 file_[:-2] + ".i")
959 return r
959 return r
960
960
961 def copy(ui, repo, pats, opts, rename=False):
961 def copy(ui, repo, pats, opts, rename=False):
962 # called with the repo lock held
962 # called with the repo lock held
963 #
963 #
964 # hgsep => pathname that uses "/" to separate directories
964 # hgsep => pathname that uses "/" to separate directories
965 # ossep => pathname that uses os.sep to separate directories
965 # ossep => pathname that uses os.sep to separate directories
966 cwd = repo.getcwd()
966 cwd = repo.getcwd()
967 targets = {}
967 targets = {}
968 after = opts.get("after")
968 after = opts.get("after")
969 dryrun = opts.get("dry_run")
969 dryrun = opts.get("dry_run")
970 wctx = repo[None]
970 wctx = repo[None]
971
971
972 def walkpat(pat):
972 def walkpat(pat):
973 srcs = []
973 srcs = []
974 if after:
974 if after:
975 badstates = '?'
975 badstates = '?'
976 else:
976 else:
977 badstates = '?r'
977 badstates = '?r'
978 m = scmutil.match(wctx, [pat], opts, globbed=True)
978 m = scmutil.match(wctx, [pat], opts, globbed=True)
979 for abs in wctx.walk(m):
979 for abs in wctx.walk(m):
980 state = repo.dirstate[abs]
980 state = repo.dirstate[abs]
981 rel = m.rel(abs)
981 rel = m.rel(abs)
982 exact = m.exact(abs)
982 exact = m.exact(abs)
983 if state in badstates:
983 if state in badstates:
984 if exact and state == '?':
984 if exact and state == '?':
985 ui.warn(_('%s: not copying - file is not managed\n') % rel)
985 ui.warn(_('%s: not copying - file is not managed\n') % rel)
986 if exact and state == 'r':
986 if exact and state == 'r':
987 ui.warn(_('%s: not copying - file has been marked for'
987 ui.warn(_('%s: not copying - file has been marked for'
988 ' remove\n') % rel)
988 ' remove\n') % rel)
989 continue
989 continue
990 # abs: hgsep
990 # abs: hgsep
991 # rel: ossep
991 # rel: ossep
992 srcs.append((abs, rel, exact))
992 srcs.append((abs, rel, exact))
993 return srcs
993 return srcs
994
994
995 # abssrc: hgsep
995 # abssrc: hgsep
996 # relsrc: ossep
996 # relsrc: ossep
997 # otarget: ossep
997 # otarget: ossep
998 def copyfile(abssrc, relsrc, otarget, exact):
998 def copyfile(abssrc, relsrc, otarget, exact):
999 abstarget = pathutil.canonpath(repo.root, cwd, otarget)
999 abstarget = pathutil.canonpath(repo.root, cwd, otarget)
1000 if '/' in abstarget:
1000 if '/' in abstarget:
1001 # We cannot normalize abstarget itself, this would prevent
1001 # We cannot normalize abstarget itself, this would prevent
1002 # case only renames, like a => A.
1002 # case only renames, like a => A.
1003 abspath, absname = abstarget.rsplit('/', 1)
1003 abspath, absname = abstarget.rsplit('/', 1)
1004 abstarget = repo.dirstate.normalize(abspath) + '/' + absname
1004 abstarget = repo.dirstate.normalize(abspath) + '/' + absname
1005 reltarget = repo.pathto(abstarget, cwd)
1005 reltarget = repo.pathto(abstarget, cwd)
1006 target = repo.wjoin(abstarget)
1006 target = repo.wjoin(abstarget)
1007 src = repo.wjoin(abssrc)
1007 src = repo.wjoin(abssrc)
1008 state = repo.dirstate[abstarget]
1008 state = repo.dirstate[abstarget]
1009
1009
1010 scmutil.checkportable(ui, abstarget)
1010 scmutil.checkportable(ui, abstarget)
1011
1011
1012 # check for collisions
1012 # check for collisions
1013 prevsrc = targets.get(abstarget)
1013 prevsrc = targets.get(abstarget)
1014 if prevsrc is not None:
1014 if prevsrc is not None:
1015 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
1015 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
1016 (reltarget, repo.pathto(abssrc, cwd),
1016 (reltarget, repo.pathto(abssrc, cwd),
1017 repo.pathto(prevsrc, cwd)))
1017 repo.pathto(prevsrc, cwd)))
1018 return
1018 return
1019
1019
1020 # check for overwrites
1020 # check for overwrites
1021 exists = os.path.lexists(target)
1021 exists = os.path.lexists(target)
1022 samefile = False
1022 samefile = False
1023 if exists and abssrc != abstarget:
1023 if exists and abssrc != abstarget:
1024 if (repo.dirstate.normalize(abssrc) ==
1024 if (repo.dirstate.normalize(abssrc) ==
1025 repo.dirstate.normalize(abstarget)):
1025 repo.dirstate.normalize(abstarget)):
1026 if not rename:
1026 if not rename:
1027 ui.warn(_("%s: can't copy - same file\n") % reltarget)
1027 ui.warn(_("%s: can't copy - same file\n") % reltarget)
1028 return
1028 return
1029 exists = False
1029 exists = False
1030 samefile = True
1030 samefile = True
1031
1031
1032 if not after and exists or after and state in 'mn':
1032 if not after and exists or after and state in 'mn':
1033 if not opts['force']:
1033 if not opts['force']:
1034 if state in 'mn':
1034 if state in 'mn':
1035 msg = _('%s: not overwriting - file already committed\n')
1035 msg = _('%s: not overwriting - file already committed\n')
1036 if after:
1036 if after:
1037 flags = '--after --force'
1037 flags = '--after --force'
1038 else:
1038 else:
1039 flags = '--force'
1039 flags = '--force'
1040 if rename:
1040 if rename:
1041 hint = _('(hg rename %s to replace the file by '
1041 hint = _('(hg rename %s to replace the file by '
1042 'recording a rename)\n') % flags
1042 'recording a rename)\n') % flags
1043 else:
1043 else:
1044 hint = _('(hg copy %s to replace the file by '
1044 hint = _('(hg copy %s to replace the file by '
1045 'recording a copy)\n') % flags
1045 'recording a copy)\n') % flags
1046 else:
1046 else:
1047 msg = _('%s: not overwriting - file exists\n')
1047 msg = _('%s: not overwriting - file exists\n')
1048 if rename:
1048 if rename:
1049 hint = _('(hg rename --after to record the rename)\n')
1049 hint = _('(hg rename --after to record the rename)\n')
1050 else:
1050 else:
1051 hint = _('(hg copy --after to record the copy)\n')
1051 hint = _('(hg copy --after to record the copy)\n')
1052 ui.warn(msg % reltarget)
1052 ui.warn(msg % reltarget)
1053 ui.warn(hint)
1053 ui.warn(hint)
1054 return
1054 return
1055
1055
1056 if after:
1056 if after:
1057 if not exists:
1057 if not exists:
1058 if rename:
1058 if rename:
1059 ui.warn(_('%s: not recording move - %s does not exist\n') %
1059 ui.warn(_('%s: not recording move - %s does not exist\n') %
1060 (relsrc, reltarget))
1060 (relsrc, reltarget))
1061 else:
1061 else:
1062 ui.warn(_('%s: not recording copy - %s does not exist\n') %
1062 ui.warn(_('%s: not recording copy - %s does not exist\n') %
1063 (relsrc, reltarget))
1063 (relsrc, reltarget))
1064 return
1064 return
1065 elif not dryrun:
1065 elif not dryrun:
1066 try:
1066 try:
1067 if exists:
1067 if exists:
1068 os.unlink(target)
1068 os.unlink(target)
1069 targetdir = os.path.dirname(target) or '.'
1069 targetdir = os.path.dirname(target) or '.'
1070 if not os.path.isdir(targetdir):
1070 if not os.path.isdir(targetdir):
1071 os.makedirs(targetdir)
1071 os.makedirs(targetdir)
1072 if samefile:
1072 if samefile:
1073 tmp = target + "~hgrename"
1073 tmp = target + "~hgrename"
1074 os.rename(src, tmp)
1074 os.rename(src, tmp)
1075 os.rename(tmp, target)
1075 os.rename(tmp, target)
1076 else:
1076 else:
1077 util.copyfile(src, target)
1077 util.copyfile(src, target)
1078 srcexists = True
1078 srcexists = True
1079 except IOError as inst:
1079 except IOError as inst:
1080 if inst.errno == errno.ENOENT:
1080 if inst.errno == errno.ENOENT:
1081 ui.warn(_('%s: deleted in working directory\n') % relsrc)
1081 ui.warn(_('%s: deleted in working directory\n') % relsrc)
1082 srcexists = False
1082 srcexists = False
1083 else:
1083 else:
1084 ui.warn(_('%s: cannot copy - %s\n') %
1084 ui.warn(_('%s: cannot copy - %s\n') %
1085 (relsrc, encoding.strtolocal(inst.strerror)))
1085 (relsrc, encoding.strtolocal(inst.strerror)))
1086 return True # report a failure
1086 return True # report a failure
1087
1087
1088 if ui.verbose or not exact:
1088 if ui.verbose or not exact:
1089 if rename:
1089 if rename:
1090 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
1090 ui.status(_('moving %s to %s\n') % (relsrc, reltarget))
1091 else:
1091 else:
1092 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
1092 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
1093
1093
1094 targets[abstarget] = abssrc
1094 targets[abstarget] = abssrc
1095
1095
1096 # fix up dirstate
1096 # fix up dirstate
1097 scmutil.dirstatecopy(ui, repo, wctx, abssrc, abstarget,
1097 scmutil.dirstatecopy(ui, repo, wctx, abssrc, abstarget,
1098 dryrun=dryrun, cwd=cwd)
1098 dryrun=dryrun, cwd=cwd)
1099 if rename and not dryrun:
1099 if rename and not dryrun:
1100 if not after and srcexists and not samefile:
1100 if not after and srcexists and not samefile:
1101 repo.wvfs.unlinkpath(abssrc)
1101 repo.wvfs.unlinkpath(abssrc)
1102 wctx.forget([abssrc])
1102 wctx.forget([abssrc])
1103
1103
1104 # pat: ossep
1104 # pat: ossep
1105 # dest ossep
1105 # dest ossep
1106 # srcs: list of (hgsep, hgsep, ossep, bool)
1106 # srcs: list of (hgsep, hgsep, ossep, bool)
1107 # return: function that takes hgsep and returns ossep
1107 # return: function that takes hgsep and returns ossep
1108 def targetpathfn(pat, dest, srcs):
1108 def targetpathfn(pat, dest, srcs):
1109 if os.path.isdir(pat):
1109 if os.path.isdir(pat):
1110 abspfx = pathutil.canonpath(repo.root, cwd, pat)
1110 abspfx = pathutil.canonpath(repo.root, cwd, pat)
1111 abspfx = util.localpath(abspfx)
1111 abspfx = util.localpath(abspfx)
1112 if destdirexists:
1112 if destdirexists:
1113 striplen = len(os.path.split(abspfx)[0])
1113 striplen = len(os.path.split(abspfx)[0])
1114 else:
1114 else:
1115 striplen = len(abspfx)
1115 striplen = len(abspfx)
1116 if striplen:
1116 if striplen:
1117 striplen += len(pycompat.ossep)
1117 striplen += len(pycompat.ossep)
1118 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
1118 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:])
1119 elif destdirexists:
1119 elif destdirexists:
1120 res = lambda p: os.path.join(dest,
1120 res = lambda p: os.path.join(dest,
1121 os.path.basename(util.localpath(p)))
1121 os.path.basename(util.localpath(p)))
1122 else:
1122 else:
1123 res = lambda p: dest
1123 res = lambda p: dest
1124 return res
1124 return res
1125
1125
1126 # pat: ossep
1126 # pat: ossep
1127 # dest ossep
1127 # dest ossep
1128 # srcs: list of (hgsep, hgsep, ossep, bool)
1128 # srcs: list of (hgsep, hgsep, ossep, bool)
1129 # return: function that takes hgsep and returns ossep
1129 # return: function that takes hgsep and returns ossep
1130 def targetpathafterfn(pat, dest, srcs):
1130 def targetpathafterfn(pat, dest, srcs):
1131 if matchmod.patkind(pat):
1131 if matchmod.patkind(pat):
1132 # a mercurial pattern
1132 # a mercurial pattern
1133 res = lambda p: os.path.join(dest,
1133 res = lambda p: os.path.join(dest,
1134 os.path.basename(util.localpath(p)))
1134 os.path.basename(util.localpath(p)))
1135 else:
1135 else:
1136 abspfx = pathutil.canonpath(repo.root, cwd, pat)
1136 abspfx = pathutil.canonpath(repo.root, cwd, pat)
1137 if len(abspfx) < len(srcs[0][0]):
1137 if len(abspfx) < len(srcs[0][0]):
1138 # A directory. Either the target path contains the last
1138 # A directory. Either the target path contains the last
1139 # component of the source path or it does not.
1139 # component of the source path or it does not.
1140 def evalpath(striplen):
1140 def evalpath(striplen):
1141 score = 0
1141 score = 0
1142 for s in srcs:
1142 for s in srcs:
1143 t = os.path.join(dest, util.localpath(s[0])[striplen:])
1143 t = os.path.join(dest, util.localpath(s[0])[striplen:])
1144 if os.path.lexists(t):
1144 if os.path.lexists(t):
1145 score += 1
1145 score += 1
1146 return score
1146 return score
1147
1147
1148 abspfx = util.localpath(abspfx)
1148 abspfx = util.localpath(abspfx)
1149 striplen = len(abspfx)
1149 striplen = len(abspfx)
1150 if striplen:
1150 if striplen:
1151 striplen += len(pycompat.ossep)
1151 striplen += len(pycompat.ossep)
1152 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
1152 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
1153 score = evalpath(striplen)
1153 score = evalpath(striplen)
1154 striplen1 = len(os.path.split(abspfx)[0])
1154 striplen1 = len(os.path.split(abspfx)[0])
1155 if striplen1:
1155 if striplen1:
1156 striplen1 += len(pycompat.ossep)
1156 striplen1 += len(pycompat.ossep)
1157 if evalpath(striplen1) > score:
1157 if evalpath(striplen1) > score:
1158 striplen = striplen1
1158 striplen = striplen1
1159 res = lambda p: os.path.join(dest,
1159 res = lambda p: os.path.join(dest,
1160 util.localpath(p)[striplen:])
1160 util.localpath(p)[striplen:])
1161 else:
1161 else:
1162 # a file
1162 # a file
1163 if destdirexists:
1163 if destdirexists:
1164 res = lambda p: os.path.join(dest,
1164 res = lambda p: os.path.join(dest,
1165 os.path.basename(util.localpath(p)))
1165 os.path.basename(util.localpath(p)))
1166 else:
1166 else:
1167 res = lambda p: dest
1167 res = lambda p: dest
1168 return res
1168 return res
1169
1169
1170 pats = scmutil.expandpats(pats)
1170 pats = scmutil.expandpats(pats)
1171 if not pats:
1171 if not pats:
1172 raise error.Abort(_('no source or destination specified'))
1172 raise error.Abort(_('no source or destination specified'))
1173 if len(pats) == 1:
1173 if len(pats) == 1:
1174 raise error.Abort(_('no destination specified'))
1174 raise error.Abort(_('no destination specified'))
1175 dest = pats.pop()
1175 dest = pats.pop()
1176 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
1176 destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
1177 if not destdirexists:
1177 if not destdirexists:
1178 if len(pats) > 1 or matchmod.patkind(pats[0]):
1178 if len(pats) > 1 or matchmod.patkind(pats[0]):
1179 raise error.Abort(_('with multiple sources, destination must be an '
1179 raise error.Abort(_('with multiple sources, destination must be an '
1180 'existing directory'))
1180 'existing directory'))
1181 if util.endswithsep(dest):
1181 if util.endswithsep(dest):
1182 raise error.Abort(_('destination %s is not a directory') % dest)
1182 raise error.Abort(_('destination %s is not a directory') % dest)
1183
1183
1184 tfn = targetpathfn
1184 tfn = targetpathfn
1185 if after:
1185 if after:
1186 tfn = targetpathafterfn
1186 tfn = targetpathafterfn
1187 copylist = []
1187 copylist = []
1188 for pat in pats:
1188 for pat in pats:
1189 srcs = walkpat(pat)
1189 srcs = walkpat(pat)
1190 if not srcs:
1190 if not srcs:
1191 continue
1191 continue
1192 copylist.append((tfn(pat, dest, srcs), srcs))
1192 copylist.append((tfn(pat, dest, srcs), srcs))
1193 if not copylist:
1193 if not copylist:
1194 raise error.Abort(_('no files to copy'))
1194 raise error.Abort(_('no files to copy'))
1195
1195
1196 errors = 0
1196 errors = 0
1197 for targetpath, srcs in copylist:
1197 for targetpath, srcs in copylist:
1198 for abssrc, relsrc, exact in srcs:
1198 for abssrc, relsrc, exact in srcs:
1199 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
1199 if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
1200 errors += 1
1200 errors += 1
1201
1201
1202 if errors:
1202 if errors:
1203 ui.warn(_('(consider using --after)\n'))
1203 ui.warn(_('(consider using --after)\n'))
1204
1204
1205 return errors != 0
1205 return errors != 0
1206
1206
1207 ## facility to let extension process additional data into an import patch
1207 ## facility to let extension process additional data into an import patch
1208 # list of identifier to be executed in order
1208 # list of identifier to be executed in order
1209 extrapreimport = [] # run before commit
1209 extrapreimport = [] # run before commit
1210 extrapostimport = [] # run after commit
1210 extrapostimport = [] # run after commit
1211 # mapping from identifier to actual import function
1211 # mapping from identifier to actual import function
1212 #
1212 #
1213 # 'preimport' are run before the commit is made and are provided the following
1213 # 'preimport' are run before the commit is made and are provided the following
1214 # arguments:
1214 # arguments:
1215 # - repo: the localrepository instance,
1215 # - repo: the localrepository instance,
1216 # - patchdata: data extracted from patch header (cf m.patch.patchheadermap),
1216 # - patchdata: data extracted from patch header (cf m.patch.patchheadermap),
1217 # - extra: the future extra dictionary of the changeset, please mutate it,
1217 # - extra: the future extra dictionary of the changeset, please mutate it,
1218 # - opts: the import options.
1218 # - opts: the import options.
1219 # XXX ideally, we would just pass an ctx ready to be computed, that would allow
1219 # XXX ideally, we would just pass an ctx ready to be computed, that would allow
1220 # mutation of in memory commit and more. Feel free to rework the code to get
1220 # mutation of in memory commit and more. Feel free to rework the code to get
1221 # there.
1221 # there.
1222 extrapreimportmap = {}
1222 extrapreimportmap = {}
1223 # 'postimport' are run after the commit is made and are provided the following
1223 # 'postimport' are run after the commit is made and are provided the following
1224 # argument:
1224 # argument:
1225 # - ctx: the changectx created by import.
1225 # - ctx: the changectx created by import.
1226 extrapostimportmap = {}
1226 extrapostimportmap = {}
1227
1227
1228 def tryimportone(ui, repo, hunk, parents, opts, msgs, updatefunc):
1228 def tryimportone(ui, repo, hunk, parents, opts, msgs, updatefunc):
1229 """Utility function used by commands.import to import a single patch
1229 """Utility function used by commands.import to import a single patch
1230
1230
1231 This function is explicitly defined here to help the evolve extension to
1231 This function is explicitly defined here to help the evolve extension to
1232 wrap this part of the import logic.
1232 wrap this part of the import logic.
1233
1233
1234 The API is currently a bit ugly because it a simple code translation from
1234 The API is currently a bit ugly because it a simple code translation from
1235 the import command. Feel free to make it better.
1235 the import command. Feel free to make it better.
1236
1236
1237 :hunk: a patch (as a binary string)
1237 :hunk: a patch (as a binary string)
1238 :parents: nodes that will be parent of the created commit
1238 :parents: nodes that will be parent of the created commit
1239 :opts: the full dict of option passed to the import command
1239 :opts: the full dict of option passed to the import command
1240 :msgs: list to save commit message to.
1240 :msgs: list to save commit message to.
1241 (used in case we need to save it when failing)
1241 (used in case we need to save it when failing)
1242 :updatefunc: a function that update a repo to a given node
1242 :updatefunc: a function that update a repo to a given node
1243 updatefunc(<repo>, <node>)
1243 updatefunc(<repo>, <node>)
1244 """
1244 """
1245 # avoid cycle context -> subrepo -> cmdutil
1245 # avoid cycle context -> subrepo -> cmdutil
1246 from . import context
1246 from . import context
1247 extractdata = patch.extract(ui, hunk)
1247 extractdata = patch.extract(ui, hunk)
1248 tmpname = extractdata.get('filename')
1248 tmpname = extractdata.get('filename')
1249 message = extractdata.get('message')
1249 message = extractdata.get('message')
1250 user = opts.get('user') or extractdata.get('user')
1250 user = opts.get('user') or extractdata.get('user')
1251 date = opts.get('date') or extractdata.get('date')
1251 date = opts.get('date') or extractdata.get('date')
1252 branch = extractdata.get('branch')
1252 branch = extractdata.get('branch')
1253 nodeid = extractdata.get('nodeid')
1253 nodeid = extractdata.get('nodeid')
1254 p1 = extractdata.get('p1')
1254 p1 = extractdata.get('p1')
1255 p2 = extractdata.get('p2')
1255 p2 = extractdata.get('p2')
1256
1256
1257 nocommit = opts.get('no_commit')
1257 nocommit = opts.get('no_commit')
1258 importbranch = opts.get('import_branch')
1258 importbranch = opts.get('import_branch')
1259 update = not opts.get('bypass')
1259 update = not opts.get('bypass')
1260 strip = opts["strip"]
1260 strip = opts["strip"]
1261 prefix = opts["prefix"]
1261 prefix = opts["prefix"]
1262 sim = float(opts.get('similarity') or 0)
1262 sim = float(opts.get('similarity') or 0)
1263 if not tmpname:
1263 if not tmpname:
1264 return (None, None, False)
1264 return (None, None, False)
1265
1265
1266 rejects = False
1266 rejects = False
1267
1267
1268 try:
1268 try:
1269 cmdline_message = logmessage(ui, opts)
1269 cmdline_message = logmessage(ui, opts)
1270 if cmdline_message:
1270 if cmdline_message:
1271 # pickup the cmdline msg
1271 # pickup the cmdline msg
1272 message = cmdline_message
1272 message = cmdline_message
1273 elif message:
1273 elif message:
1274 # pickup the patch msg
1274 # pickup the patch msg
1275 message = message.strip()
1275 message = message.strip()
1276 else:
1276 else:
1277 # launch the editor
1277 # launch the editor
1278 message = None
1278 message = None
1279 ui.debug('message:\n%s\n' % message)
1279 ui.debug('message:\n%s\n' % message)
1280
1280
1281 if len(parents) == 1:
1281 if len(parents) == 1:
1282 parents.append(repo[nullid])
1282 parents.append(repo[nullid])
1283 if opts.get('exact'):
1283 if opts.get('exact'):
1284 if not nodeid or not p1:
1284 if not nodeid or not p1:
1285 raise error.Abort(_('not a Mercurial patch'))
1285 raise error.Abort(_('not a Mercurial patch'))
1286 p1 = repo[p1]
1286 p1 = repo[p1]
1287 p2 = repo[p2 or nullid]
1287 p2 = repo[p2 or nullid]
1288 elif p2:
1288 elif p2:
1289 try:
1289 try:
1290 p1 = repo[p1]
1290 p1 = repo[p1]
1291 p2 = repo[p2]
1291 p2 = repo[p2]
1292 # Without any options, consider p2 only if the
1292 # Without any options, consider p2 only if the
1293 # patch is being applied on top of the recorded
1293 # patch is being applied on top of the recorded
1294 # first parent.
1294 # first parent.
1295 if p1 != parents[0]:
1295 if p1 != parents[0]:
1296 p1 = parents[0]
1296 p1 = parents[0]
1297 p2 = repo[nullid]
1297 p2 = repo[nullid]
1298 except error.RepoError:
1298 except error.RepoError:
1299 p1, p2 = parents
1299 p1, p2 = parents
1300 if p2.node() == nullid:
1300 if p2.node() == nullid:
1301 ui.warn(_("warning: import the patch as a normal revision\n"
1301 ui.warn(_("warning: import the patch as a normal revision\n"
1302 "(use --exact to import the patch as a merge)\n"))
1302 "(use --exact to import the patch as a merge)\n"))
1303 else:
1303 else:
1304 p1, p2 = parents
1304 p1, p2 = parents
1305
1305
1306 n = None
1306 n = None
1307 if update:
1307 if update:
1308 if p1 != parents[0]:
1308 if p1 != parents[0]:
1309 updatefunc(repo, p1.node())
1309 updatefunc(repo, p1.node())
1310 if p2 != parents[1]:
1310 if p2 != parents[1]:
1311 repo.setparents(p1.node(), p2.node())
1311 repo.setparents(p1.node(), p2.node())
1312
1312
1313 if opts.get('exact') or importbranch:
1313 if opts.get('exact') or importbranch:
1314 repo.dirstate.setbranch(branch or 'default')
1314 repo.dirstate.setbranch(branch or 'default')
1315
1315
1316 partial = opts.get('partial', False)
1316 partial = opts.get('partial', False)
1317 files = set()
1317 files = set()
1318 try:
1318 try:
1319 patch.patch(ui, repo, tmpname, strip=strip, prefix=prefix,
1319 patch.patch(ui, repo, tmpname, strip=strip, prefix=prefix,
1320 files=files, eolmode=None, similarity=sim / 100.0)
1320 files=files, eolmode=None, similarity=sim / 100.0)
1321 except error.PatchError as e:
1321 except error.PatchError as e:
1322 if not partial:
1322 if not partial:
1323 raise error.Abort(str(e))
1323 raise error.Abort(str(e))
1324 if partial:
1324 if partial:
1325 rejects = True
1325 rejects = True
1326
1326
1327 files = list(files)
1327 files = list(files)
1328 if nocommit:
1328 if nocommit:
1329 if message:
1329 if message:
1330 msgs.append(message)
1330 msgs.append(message)
1331 else:
1331 else:
1332 if opts.get('exact') or p2:
1332 if opts.get('exact') or p2:
1333 # If you got here, you either use --force and know what
1333 # If you got here, you either use --force and know what
1334 # you are doing or used --exact or a merge patch while
1334 # you are doing or used --exact or a merge patch while
1335 # being updated to its first parent.
1335 # being updated to its first parent.
1336 m = None
1336 m = None
1337 else:
1337 else:
1338 m = scmutil.matchfiles(repo, files or [])
1338 m = scmutil.matchfiles(repo, files or [])
1339 editform = mergeeditform(repo[None], 'import.normal')
1339 editform = mergeeditform(repo[None], 'import.normal')
1340 if opts.get('exact'):
1340 if opts.get('exact'):
1341 editor = None
1341 editor = None
1342 else:
1342 else:
1343 editor = getcommiteditor(editform=editform, **opts)
1343 editor = getcommiteditor(editform=editform, **opts)
1344 extra = {}
1344 extra = {}
1345 for idfunc in extrapreimport:
1345 for idfunc in extrapreimport:
1346 extrapreimportmap[idfunc](repo, extractdata, extra, opts)
1346 extrapreimportmap[idfunc](repo, extractdata, extra, opts)
1347 overrides = {}
1347 overrides = {}
1348 if partial:
1348 if partial:
1349 overrides[('ui', 'allowemptycommit')] = True
1349 overrides[('ui', 'allowemptycommit')] = True
1350 with repo.ui.configoverride(overrides, 'import'):
1350 with repo.ui.configoverride(overrides, 'import'):
1351 n = repo.commit(message, user,
1351 n = repo.commit(message, user,
1352 date, match=m,
1352 date, match=m,
1353 editor=editor, extra=extra)
1353 editor=editor, extra=extra)
1354 for idfunc in extrapostimport:
1354 for idfunc in extrapostimport:
1355 extrapostimportmap[idfunc](repo[n])
1355 extrapostimportmap[idfunc](repo[n])
1356 else:
1356 else:
1357 if opts.get('exact') or importbranch:
1357 if opts.get('exact') or importbranch:
1358 branch = branch or 'default'
1358 branch = branch or 'default'
1359 else:
1359 else:
1360 branch = p1.branch()
1360 branch = p1.branch()
1361 store = patch.filestore()
1361 store = patch.filestore()
1362 try:
1362 try:
1363 files = set()
1363 files = set()
1364 try:
1364 try:
1365 patch.patchrepo(ui, repo, p1, store, tmpname, strip, prefix,
1365 patch.patchrepo(ui, repo, p1, store, tmpname, strip, prefix,
1366 files, eolmode=None)
1366 files, eolmode=None)
1367 except error.PatchError as e:
1367 except error.PatchError as e:
1368 raise error.Abort(str(e))
1368 raise error.Abort(str(e))
1369 if opts.get('exact'):
1369 if opts.get('exact'):
1370 editor = None
1370 editor = None
1371 else:
1371 else:
1372 editor = getcommiteditor(editform='import.bypass')
1372 editor = getcommiteditor(editform='import.bypass')
1373 memctx = context.memctx(repo, (p1.node(), p2.node()),
1373 memctx = context.memctx(repo, (p1.node(), p2.node()),
1374 message,
1374 message,
1375 files=files,
1375 files=files,
1376 filectxfn=store,
1376 filectxfn=store,
1377 user=user,
1377 user=user,
1378 date=date,
1378 date=date,
1379 branch=branch,
1379 branch=branch,
1380 editor=editor)
1380 editor=editor)
1381 n = memctx.commit()
1381 n = memctx.commit()
1382 finally:
1382 finally:
1383 store.close()
1383 store.close()
1384 if opts.get('exact') and nocommit:
1384 if opts.get('exact') and nocommit:
1385 # --exact with --no-commit is still useful in that it does merge
1385 # --exact with --no-commit is still useful in that it does merge
1386 # and branch bits
1386 # and branch bits
1387 ui.warn(_("warning: can't check exact import with --no-commit\n"))
1387 ui.warn(_("warning: can't check exact import with --no-commit\n"))
1388 elif opts.get('exact') and hex(n) != nodeid:
1388 elif opts.get('exact') and hex(n) != nodeid:
1389 raise error.Abort(_('patch is damaged or loses information'))
1389 raise error.Abort(_('patch is damaged or loses information'))
1390 msg = _('applied to working directory')
1390 msg = _('applied to working directory')
1391 if n:
1391 if n:
1392 # i18n: refers to a short changeset id
1392 # i18n: refers to a short changeset id
1393 msg = _('created %s') % short(n)
1393 msg = _('created %s') % short(n)
1394 return (msg, n, rejects)
1394 return (msg, n, rejects)
1395 finally:
1395 finally:
1396 os.unlink(tmpname)
1396 os.unlink(tmpname)
1397
1397
1398 # facility to let extensions include additional data in an exported patch
1398 # facility to let extensions include additional data in an exported patch
1399 # list of identifiers to be executed in order
1399 # list of identifiers to be executed in order
1400 extraexport = []
1400 extraexport = []
1401 # mapping from identifier to actual export function
1401 # mapping from identifier to actual export function
1402 # function as to return a string to be added to the header or None
1402 # function as to return a string to be added to the header or None
1403 # it is given two arguments (sequencenumber, changectx)
1403 # it is given two arguments (sequencenumber, changectx)
1404 extraexportmap = {}
1404 extraexportmap = {}
1405
1405
1406 def _exportsingle(repo, ctx, match, switch_parent, rev, seqno, write, diffopts):
1406 def _exportsingle(repo, ctx, match, switch_parent, rev, seqno, write, diffopts):
1407 node = scmutil.binnode(ctx)
1407 node = scmutil.binnode(ctx)
1408 parents = [p.node() for p in ctx.parents() if p]
1408 parents = [p.node() for p in ctx.parents() if p]
1409 branch = ctx.branch()
1409 branch = ctx.branch()
1410 if switch_parent:
1410 if switch_parent:
1411 parents.reverse()
1411 parents.reverse()
1412
1412
1413 if parents:
1413 if parents:
1414 prev = parents[0]
1414 prev = parents[0]
1415 else:
1415 else:
1416 prev = nullid
1416 prev = nullid
1417
1417
1418 write("# HG changeset patch\n")
1418 write("# HG changeset patch\n")
1419 write("# User %s\n" % ctx.user())
1419 write("# User %s\n" % ctx.user())
1420 write("# Date %d %d\n" % ctx.date())
1420 write("# Date %d %d\n" % ctx.date())
1421 write("# %s\n" % util.datestr(ctx.date()))
1421 write("# %s\n" % util.datestr(ctx.date()))
1422 if branch and branch != 'default':
1422 if branch and branch != 'default':
1423 write("# Branch %s\n" % branch)
1423 write("# Branch %s\n" % branch)
1424 write("# Node ID %s\n" % hex(node))
1424 write("# Node ID %s\n" % hex(node))
1425 write("# Parent %s\n" % hex(prev))
1425 write("# Parent %s\n" % hex(prev))
1426 if len(parents) > 1:
1426 if len(parents) > 1:
1427 write("# Parent %s\n" % hex(parents[1]))
1427 write("# Parent %s\n" % hex(parents[1]))
1428
1428
1429 for headerid in extraexport:
1429 for headerid in extraexport:
1430 header = extraexportmap[headerid](seqno, ctx)
1430 header = extraexportmap[headerid](seqno, ctx)
1431 if header is not None:
1431 if header is not None:
1432 write('# %s\n' % header)
1432 write('# %s\n' % header)
1433 write(ctx.description().rstrip())
1433 write(ctx.description().rstrip())
1434 write("\n\n")
1434 write("\n\n")
1435
1435
1436 for chunk, label in patch.diffui(repo, prev, node, match, opts=diffopts):
1436 for chunk, label in patch.diffui(repo, prev, node, match, opts=diffopts):
1437 write(chunk, label=label)
1437 write(chunk, label=label)
1438
1438
1439 def export(repo, revs, fntemplate='hg-%h.patch', fp=None, switch_parent=False,
1439 def export(repo, revs, fntemplate='hg-%h.patch', fp=None, switch_parent=False,
1440 opts=None, match=None):
1440 opts=None, match=None):
1441 '''export changesets as hg patches
1441 '''export changesets as hg patches
1442
1442
1443 Args:
1443 Args:
1444 repo: The repository from which we're exporting revisions.
1444 repo: The repository from which we're exporting revisions.
1445 revs: A list of revisions to export as revision numbers.
1445 revs: A list of revisions to export as revision numbers.
1446 fntemplate: An optional string to use for generating patch file names.
1446 fntemplate: An optional string to use for generating patch file names.
1447 fp: An optional file-like object to which patches should be written.
1447 fp: An optional file-like object to which patches should be written.
1448 switch_parent: If True, show diffs against second parent when not nullid.
1448 switch_parent: If True, show diffs against second parent when not nullid.
1449 Default is false, which always shows diff against p1.
1449 Default is false, which always shows diff against p1.
1450 opts: diff options to use for generating the patch.
1450 opts: diff options to use for generating the patch.
1451 match: If specified, only export changes to files matching this matcher.
1451 match: If specified, only export changes to files matching this matcher.
1452
1452
1453 Returns:
1453 Returns:
1454 Nothing.
1454 Nothing.
1455
1455
1456 Side Effect:
1456 Side Effect:
1457 "HG Changeset Patch" data is emitted to one of the following
1457 "HG Changeset Patch" data is emitted to one of the following
1458 destinations:
1458 destinations:
1459 fp is specified: All revs are written to the specified
1459 fp is specified: All revs are written to the specified
1460 file-like object.
1460 file-like object.
1461 fntemplate specified: Each rev is written to a unique file named using
1461 fntemplate specified: Each rev is written to a unique file named using
1462 the given template.
1462 the given template.
1463 Neither fp nor template specified: All revs written to repo.ui.write()
1463 Neither fp nor template specified: All revs written to repo.ui.write()
1464 '''
1464 '''
1465
1465
1466 total = len(revs)
1466 total = len(revs)
1467 revwidth = max(len(str(rev)) for rev in revs)
1467 revwidth = max(len(str(rev)) for rev in revs)
1468 filemode = {}
1468 filemode = {}
1469
1469
1470 write = None
1470 write = None
1471 dest = '<unnamed>'
1471 dest = '<unnamed>'
1472 if fp:
1472 if fp:
1473 dest = getattr(fp, 'name', dest)
1473 dest = getattr(fp, 'name', dest)
1474 def write(s, **kw):
1474 def write(s, **kw):
1475 fp.write(s)
1475 fp.write(s)
1476 elif not fntemplate:
1476 elif not fntemplate:
1477 write = repo.ui.write
1477 write = repo.ui.write
1478
1478
1479 for seqno, rev in enumerate(revs, 1):
1479 for seqno, rev in enumerate(revs, 1):
1480 ctx = repo[rev]
1480 ctx = repo[rev]
1481 fo = None
1481 fo = None
1482 if not fp and fntemplate:
1482 if not fp and fntemplate:
1483 desc_lines = ctx.description().rstrip().split('\n')
1483 desc_lines = ctx.description().rstrip().split('\n')
1484 desc = desc_lines[0] #Commit always has a first line.
1484 desc = desc_lines[0] #Commit always has a first line.
1485 fo = makefileobj(repo, fntemplate, ctx.node(), desc=desc,
1485 fo = makefileobj(repo, fntemplate, ctx.node(), desc=desc,
1486 total=total, seqno=seqno, revwidth=revwidth,
1486 total=total, seqno=seqno, revwidth=revwidth,
1487 mode='wb', modemap=filemode)
1487 mode='wb', modemap=filemode)
1488 dest = fo.name
1488 dest = fo.name
1489 def write(s, **kw):
1489 def write(s, **kw):
1490 fo.write(s)
1490 fo.write(s)
1491 if not dest.startswith('<'):
1491 if not dest.startswith('<'):
1492 repo.ui.note("%s\n" % dest)
1492 repo.ui.note("%s\n" % dest)
1493 _exportsingle(
1493 _exportsingle(
1494 repo, ctx, match, switch_parent, rev, seqno, write, opts)
1494 repo, ctx, match, switch_parent, rev, seqno, write, opts)
1495 if fo is not None:
1495 if fo is not None:
1496 fo.close()
1496 fo.close()
1497
1497
1498 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
1498 def diffordiffstat(ui, repo, diffopts, node1, node2, match,
1499 changes=None, stat=False, fp=None, prefix='',
1499 changes=None, stat=False, fp=None, prefix='',
1500 root='', listsubrepos=False, hunksfilterfn=None):
1500 root='', listsubrepos=False, hunksfilterfn=None):
1501 '''show diff or diffstat.'''
1501 '''show diff or diffstat.'''
1502 if fp is None:
1502 if fp is None:
1503 write = ui.write
1503 write = ui.write
1504 else:
1504 else:
1505 def write(s, **kw):
1505 def write(s, **kw):
1506 fp.write(s)
1506 fp.write(s)
1507
1507
1508 if root:
1508 if root:
1509 relroot = pathutil.canonpath(repo.root, repo.getcwd(), root)
1509 relroot = pathutil.canonpath(repo.root, repo.getcwd(), root)
1510 else:
1510 else:
1511 relroot = ''
1511 relroot = ''
1512 if relroot != '':
1512 if relroot != '':
1513 # XXX relative roots currently don't work if the root is within a
1513 # XXX relative roots currently don't work if the root is within a
1514 # subrepo
1514 # subrepo
1515 uirelroot = match.uipath(relroot)
1515 uirelroot = match.uipath(relroot)
1516 relroot += '/'
1516 relroot += '/'
1517 for matchroot in match.files():
1517 for matchroot in match.files():
1518 if not matchroot.startswith(relroot):
1518 if not matchroot.startswith(relroot):
1519 ui.warn(_('warning: %s not inside relative root %s\n') % (
1519 ui.warn(_('warning: %s not inside relative root %s\n') % (
1520 match.uipath(matchroot), uirelroot))
1520 match.uipath(matchroot), uirelroot))
1521
1521
1522 if stat:
1522 if stat:
1523 diffopts = diffopts.copy(context=0)
1523 diffopts = diffopts.copy(context=0)
1524 width = 80
1524 width = 80
1525 if not ui.plain():
1525 if not ui.plain():
1526 width = ui.termwidth()
1526 width = ui.termwidth()
1527 chunks = patch.diff(repo, node1, node2, match, changes, diffopts,
1527 chunks = patch.diff(repo, node1, node2, match, changes, diffopts,
1528 prefix=prefix, relroot=relroot,
1528 prefix=prefix, relroot=relroot,
1529 hunksfilterfn=hunksfilterfn)
1529 hunksfilterfn=hunksfilterfn)
1530 for chunk, label in patch.diffstatui(util.iterlines(chunks),
1530 for chunk, label in patch.diffstatui(util.iterlines(chunks),
1531 width=width):
1531 width=width):
1532 write(chunk, label=label)
1532 write(chunk, label=label)
1533 else:
1533 else:
1534 for chunk, label in patch.diffui(repo, node1, node2, match,
1534 for chunk, label in patch.diffui(repo, node1, node2, match,
1535 changes, diffopts, prefix=prefix,
1535 changes, diffopts, prefix=prefix,
1536 relroot=relroot,
1536 relroot=relroot,
1537 hunksfilterfn=hunksfilterfn):
1537 hunksfilterfn=hunksfilterfn):
1538 write(chunk, label=label)
1538 write(chunk, label=label)
1539
1539
1540 if listsubrepos:
1540 if listsubrepos:
1541 ctx1 = repo[node1]
1541 ctx1 = repo[node1]
1542 ctx2 = repo[node2]
1542 ctx2 = repo[node2]
1543 for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
1543 for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
1544 tempnode2 = node2
1544 tempnode2 = node2
1545 try:
1545 try:
1546 if node2 is not None:
1546 if node2 is not None:
1547 tempnode2 = ctx2.substate[subpath][1]
1547 tempnode2 = ctx2.substate[subpath][1]
1548 except KeyError:
1548 except KeyError:
1549 # A subrepo that existed in node1 was deleted between node1 and
1549 # A subrepo that existed in node1 was deleted between node1 and
1550 # node2 (inclusive). Thus, ctx2's substate won't contain that
1550 # node2 (inclusive). Thus, ctx2's substate won't contain that
1551 # subpath. The best we can do is to ignore it.
1551 # subpath. The best we can do is to ignore it.
1552 tempnode2 = None
1552 tempnode2 = None
1553 submatch = matchmod.subdirmatcher(subpath, match)
1553 submatch = matchmod.subdirmatcher(subpath, match)
1554 sub.diff(ui, diffopts, tempnode2, submatch, changes=changes,
1554 sub.diff(ui, diffopts, tempnode2, submatch, changes=changes,
1555 stat=stat, fp=fp, prefix=prefix)
1555 stat=stat, fp=fp, prefix=prefix)
1556
1556
1557 def _changesetlabels(ctx):
1557 def _changesetlabels(ctx):
1558 labels = ['log.changeset', 'changeset.%s' % ctx.phasestr()]
1558 labels = ['log.changeset', 'changeset.%s' % ctx.phasestr()]
1559 if ctx.obsolete():
1559 if ctx.obsolete():
1560 labels.append('changeset.obsolete')
1560 labels.append('changeset.obsolete')
1561 if ctx.isunstable():
1561 if ctx.isunstable():
1562 labels.append('changeset.unstable')
1562 labels.append('changeset.unstable')
1563 for instability in ctx.instabilities():
1563 for instability in ctx.instabilities():
1564 labels.append('instability.%s' % instability)
1564 labels.append('instability.%s' % instability)
1565 return ' '.join(labels)
1565 return ' '.join(labels)
1566
1566
1567 class changeset_printer(object):
1567 class changeset_printer(object):
1568 '''show changeset information when templating not requested.'''
1568 '''show changeset information when templating not requested.'''
1569
1569
1570 def __init__(self, ui, repo, matchfn, diffopts, buffered):
1570 def __init__(self, ui, repo, matchfn, diffopts, buffered):
1571 self.ui = ui
1571 self.ui = ui
1572 self.repo = repo
1572 self.repo = repo
1573 self.buffered = buffered
1573 self.buffered = buffered
1574 self.matchfn = matchfn
1574 self.matchfn = matchfn
1575 self.diffopts = diffopts
1575 self.diffopts = diffopts
1576 self.header = {}
1576 self.header = {}
1577 self.hunk = {}
1577 self.hunk = {}
1578 self.lastheader = None
1578 self.lastheader = None
1579 self.footer = None
1579 self.footer = None
1580
1580
1581 def flush(self, ctx):
1581 def flush(self, ctx):
1582 rev = ctx.rev()
1582 rev = ctx.rev()
1583 if rev in self.header:
1583 if rev in self.header:
1584 h = self.header[rev]
1584 h = self.header[rev]
1585 if h != self.lastheader:
1585 if h != self.lastheader:
1586 self.lastheader = h
1586 self.lastheader = h
1587 self.ui.write(h)
1587 self.ui.write(h)
1588 del self.header[rev]
1588 del self.header[rev]
1589 if rev in self.hunk:
1589 if rev in self.hunk:
1590 self.ui.write(self.hunk[rev])
1590 self.ui.write(self.hunk[rev])
1591 del self.hunk[rev]
1591 del self.hunk[rev]
1592 return 1
1592 return 1
1593 return 0
1593 return 0
1594
1594
1595 def close(self):
1595 def close(self):
1596 if self.footer:
1596 if self.footer:
1597 self.ui.write(self.footer)
1597 self.ui.write(self.footer)
1598
1598
1599 def show(self, ctx, copies=None, matchfn=None, hunksfilterfn=None,
1599 def show(self, ctx, copies=None, matchfn=None, hunksfilterfn=None,
1600 **props):
1600 **props):
1601 props = pycompat.byteskwargs(props)
1601 props = pycompat.byteskwargs(props)
1602 if self.buffered:
1602 if self.buffered:
1603 self.ui.pushbuffer(labeled=True)
1603 self.ui.pushbuffer(labeled=True)
1604 self._show(ctx, copies, matchfn, hunksfilterfn, props)
1604 self._show(ctx, copies, matchfn, hunksfilterfn, props)
1605 self.hunk[ctx.rev()] = self.ui.popbuffer()
1605 self.hunk[ctx.rev()] = self.ui.popbuffer()
1606 else:
1606 else:
1607 self._show(ctx, copies, matchfn, hunksfilterfn, props)
1607 self._show(ctx, copies, matchfn, hunksfilterfn, props)
1608
1608
1609 def _show(self, ctx, copies, matchfn, hunksfilterfn, props):
1609 def _show(self, ctx, copies, matchfn, hunksfilterfn, props):
1610 '''show a single changeset or file revision'''
1610 '''show a single changeset or file revision'''
1611 changenode = ctx.node()
1611 changenode = ctx.node()
1612 rev = ctx.rev()
1612 rev = ctx.rev()
1613
1613
1614 if self.ui.quiet:
1614 if self.ui.quiet:
1615 self.ui.write("%s\n" % scmutil.formatchangeid(ctx),
1615 self.ui.write("%s\n" % scmutil.formatchangeid(ctx),
1616 label='log.node')
1616 label='log.node')
1617 return
1617 return
1618
1618
1619 date = util.datestr(ctx.date())
1619 date = util.datestr(ctx.date())
1620
1620
1621 # i18n: column positioning for "hg log"
1621 # i18n: column positioning for "hg log"
1622 self.ui.write(_("changeset: %s\n") % scmutil.formatchangeid(ctx),
1622 self.ui.write(_("changeset: %s\n") % scmutil.formatchangeid(ctx),
1623 label=_changesetlabels(ctx))
1623 label=_changesetlabels(ctx))
1624
1624
1625 # branches are shown first before any other names due to backwards
1625 # branches are shown first before any other names due to backwards
1626 # compatibility
1626 # compatibility
1627 branch = ctx.branch()
1627 branch = ctx.branch()
1628 # don't show the default branch name
1628 # don't show the default branch name
1629 if branch != 'default':
1629 if branch != 'default':
1630 # i18n: column positioning for "hg log"
1630 # i18n: column positioning for "hg log"
1631 self.ui.write(_("branch: %s\n") % branch,
1631 self.ui.write(_("branch: %s\n") % branch,
1632 label='log.branch')
1632 label='log.branch')
1633
1633
1634 for nsname, ns in self.repo.names.iteritems():
1634 for nsname, ns in self.repo.names.iteritems():
1635 # branches has special logic already handled above, so here we just
1635 # branches has special logic already handled above, so here we just
1636 # skip it
1636 # skip it
1637 if nsname == 'branches':
1637 if nsname == 'branches':
1638 continue
1638 continue
1639 # we will use the templatename as the color name since those two
1639 # we will use the templatename as the color name since those two
1640 # should be the same
1640 # should be the same
1641 for name in ns.names(self.repo, changenode):
1641 for name in ns.names(self.repo, changenode):
1642 self.ui.write(ns.logfmt % name,
1642 self.ui.write(ns.logfmt % name,
1643 label='log.%s' % ns.colorname)
1643 label='log.%s' % ns.colorname)
1644 if self.ui.debugflag:
1644 if self.ui.debugflag:
1645 # i18n: column positioning for "hg log"
1645 # i18n: column positioning for "hg log"
1646 self.ui.write(_("phase: %s\n") % ctx.phasestr(),
1646 self.ui.write(_("phase: %s\n") % ctx.phasestr(),
1647 label='log.phase')
1647 label='log.phase')
1648 for pctx in scmutil.meaningfulparents(self.repo, ctx):
1648 for pctx in scmutil.meaningfulparents(self.repo, ctx):
1649 label = 'log.parent changeset.%s' % pctx.phasestr()
1649 label = 'log.parent changeset.%s' % pctx.phasestr()
1650 # i18n: column positioning for "hg log"
1650 # i18n: column positioning for "hg log"
1651 self.ui.write(_("parent: %s\n") % scmutil.formatchangeid(pctx),
1651 self.ui.write(_("parent: %s\n") % scmutil.formatchangeid(pctx),
1652 label=label)
1652 label=label)
1653
1653
1654 if self.ui.debugflag and rev is not None:
1654 if self.ui.debugflag and rev is not None:
1655 mnode = ctx.manifestnode()
1655 mnode = ctx.manifestnode()
1656 mrev = self.repo.manifestlog._revlog.rev(mnode)
1656 mrev = self.repo.manifestlog._revlog.rev(mnode)
1657 # i18n: column positioning for "hg log"
1657 # i18n: column positioning for "hg log"
1658 self.ui.write(_("manifest: %s\n")
1658 self.ui.write(_("manifest: %s\n")
1659 % scmutil.formatrevnode(self.ui, mrev, mnode),
1659 % scmutil.formatrevnode(self.ui, mrev, mnode),
1660 label='ui.debug log.manifest')
1660 label='ui.debug log.manifest')
1661 # i18n: column positioning for "hg log"
1661 # i18n: column positioning for "hg log"
1662 self.ui.write(_("user: %s\n") % ctx.user(),
1662 self.ui.write(_("user: %s\n") % ctx.user(),
1663 label='log.user')
1663 label='log.user')
1664 # i18n: column positioning for "hg log"
1664 # i18n: column positioning for "hg log"
1665 self.ui.write(_("date: %s\n") % date,
1665 self.ui.write(_("date: %s\n") % date,
1666 label='log.date')
1666 label='log.date')
1667
1667
1668 if ctx.isunstable():
1668 if ctx.isunstable():
1669 # i18n: column positioning for "hg log"
1669 # i18n: column positioning for "hg log"
1670 instabilities = ctx.instabilities()
1670 instabilities = ctx.instabilities()
1671 self.ui.write(_("instability: %s\n") % ', '.join(instabilities),
1671 self.ui.write(_("instability: %s\n") % ', '.join(instabilities),
1672 label='log.instability')
1672 label='log.instability')
1673
1673
1674 elif ctx.obsolete():
1674 elif ctx.obsolete():
1675 self._showobsfate(ctx)
1675 self._showobsfate(ctx)
1676
1676
1677 self._exthook(ctx)
1677 self._exthook(ctx)
1678
1678
1679 if self.ui.debugflag:
1679 if self.ui.debugflag:
1680 files = ctx.p1().status(ctx)[:3]
1680 files = ctx.p1().status(ctx)[:3]
1681 for key, value in zip([# i18n: column positioning for "hg log"
1681 for key, value in zip([# i18n: column positioning for "hg log"
1682 _("files:"),
1682 _("files:"),
1683 # i18n: column positioning for "hg log"
1683 # i18n: column positioning for "hg log"
1684 _("files+:"),
1684 _("files+:"),
1685 # i18n: column positioning for "hg log"
1685 # i18n: column positioning for "hg log"
1686 _("files-:")], files):
1686 _("files-:")], files):
1687 if value:
1687 if value:
1688 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
1688 self.ui.write("%-12s %s\n" % (key, " ".join(value)),
1689 label='ui.debug log.files')
1689 label='ui.debug log.files')
1690 elif ctx.files() and self.ui.verbose:
1690 elif ctx.files() and self.ui.verbose:
1691 # i18n: column positioning for "hg log"
1691 # i18n: column positioning for "hg log"
1692 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
1692 self.ui.write(_("files: %s\n") % " ".join(ctx.files()),
1693 label='ui.note log.files')
1693 label='ui.note log.files')
1694 if copies and self.ui.verbose:
1694 if copies and self.ui.verbose:
1695 copies = ['%s (%s)' % c for c in copies]
1695 copies = ['%s (%s)' % c for c in copies]
1696 # i18n: column positioning for "hg log"
1696 # i18n: column positioning for "hg log"
1697 self.ui.write(_("copies: %s\n") % ' '.join(copies),
1697 self.ui.write(_("copies: %s\n") % ' '.join(copies),
1698 label='ui.note log.copies')
1698 label='ui.note log.copies')
1699
1699
1700 extra = ctx.extra()
1700 extra = ctx.extra()
1701 if extra and self.ui.debugflag:
1701 if extra and self.ui.debugflag:
1702 for key, value in sorted(extra.items()):
1702 for key, value in sorted(extra.items()):
1703 # i18n: column positioning for "hg log"
1703 # i18n: column positioning for "hg log"
1704 self.ui.write(_("extra: %s=%s\n")
1704 self.ui.write(_("extra: %s=%s\n")
1705 % (key, util.escapestr(value)),
1705 % (key, util.escapestr(value)),
1706 label='ui.debug log.extra')
1706 label='ui.debug log.extra')
1707
1707
1708 description = ctx.description().strip()
1708 description = ctx.description().strip()
1709 if description:
1709 if description:
1710 if self.ui.verbose:
1710 if self.ui.verbose:
1711 self.ui.write(_("description:\n"),
1711 self.ui.write(_("description:\n"),
1712 label='ui.note log.description')
1712 label='ui.note log.description')
1713 self.ui.write(description,
1713 self.ui.write(description,
1714 label='ui.note log.description')
1714 label='ui.note log.description')
1715 self.ui.write("\n\n")
1715 self.ui.write("\n\n")
1716 else:
1716 else:
1717 # i18n: column positioning for "hg log"
1717 # i18n: column positioning for "hg log"
1718 self.ui.write(_("summary: %s\n") %
1718 self.ui.write(_("summary: %s\n") %
1719 description.splitlines()[0],
1719 description.splitlines()[0],
1720 label='log.summary')
1720 label='log.summary')
1721 self.ui.write("\n")
1721 self.ui.write("\n")
1722
1722
1723 self.showpatch(ctx, matchfn, hunksfilterfn=hunksfilterfn)
1723 self.showpatch(ctx, matchfn, hunksfilterfn=hunksfilterfn)
1724
1724
1725 def _showobsfate(self, ctx):
1725 def _showobsfate(self, ctx):
1726 obsfate = templatekw.showobsfate(repo=self.repo, ctx=ctx, ui=self.ui)
1726 obsfate = templatekw.showobsfate(repo=self.repo, ctx=ctx, ui=self.ui)
1727
1727
1728 if obsfate:
1728 if obsfate:
1729 for obsfateline in obsfate:
1729 for obsfateline in obsfate:
1730 # i18n: column positioning for "hg log"
1730 # i18n: column positioning for "hg log"
1731 self.ui.write(_("obsfate: %s\n") % obsfateline,
1731 self.ui.write(_("obsolete: %s\n") % obsfateline,
1732 label='log.obsfate')
1732 label='log.obsfate')
1733
1733
1734 def _exthook(self, ctx):
1734 def _exthook(self, ctx):
1735 '''empty method used by extension as a hook point
1735 '''empty method used by extension as a hook point
1736 '''
1736 '''
1737
1737
1738 def showpatch(self, ctx, matchfn, hunksfilterfn=None):
1738 def showpatch(self, ctx, matchfn, hunksfilterfn=None):
1739 if not matchfn:
1739 if not matchfn:
1740 matchfn = self.matchfn
1740 matchfn = self.matchfn
1741 if matchfn:
1741 if matchfn:
1742 stat = self.diffopts.get('stat')
1742 stat = self.diffopts.get('stat')
1743 diff = self.diffopts.get('patch')
1743 diff = self.diffopts.get('patch')
1744 diffopts = patch.diffallopts(self.ui, self.diffopts)
1744 diffopts = patch.diffallopts(self.ui, self.diffopts)
1745 node = ctx.node()
1745 node = ctx.node()
1746 prev = ctx.p1().node()
1746 prev = ctx.p1().node()
1747 if stat:
1747 if stat:
1748 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
1748 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
1749 match=matchfn, stat=True,
1749 match=matchfn, stat=True,
1750 hunksfilterfn=hunksfilterfn)
1750 hunksfilterfn=hunksfilterfn)
1751 if diff:
1751 if diff:
1752 if stat:
1752 if stat:
1753 self.ui.write("\n")
1753 self.ui.write("\n")
1754 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
1754 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
1755 match=matchfn, stat=False,
1755 match=matchfn, stat=False,
1756 hunksfilterfn=hunksfilterfn)
1756 hunksfilterfn=hunksfilterfn)
1757 self.ui.write("\n")
1757 self.ui.write("\n")
1758
1758
1759 class jsonchangeset(changeset_printer):
1759 class jsonchangeset(changeset_printer):
1760 '''format changeset information.'''
1760 '''format changeset information.'''
1761
1761
1762 def __init__(self, ui, repo, matchfn, diffopts, buffered):
1762 def __init__(self, ui, repo, matchfn, diffopts, buffered):
1763 changeset_printer.__init__(self, ui, repo, matchfn, diffopts, buffered)
1763 changeset_printer.__init__(self, ui, repo, matchfn, diffopts, buffered)
1764 self.cache = {}
1764 self.cache = {}
1765 self._first = True
1765 self._first = True
1766
1766
1767 def close(self):
1767 def close(self):
1768 if not self._first:
1768 if not self._first:
1769 self.ui.write("\n]\n")
1769 self.ui.write("\n]\n")
1770 else:
1770 else:
1771 self.ui.write("[]\n")
1771 self.ui.write("[]\n")
1772
1772
1773 def _show(self, ctx, copies, matchfn, hunksfilterfn, props):
1773 def _show(self, ctx, copies, matchfn, hunksfilterfn, props):
1774 '''show a single changeset or file revision'''
1774 '''show a single changeset or file revision'''
1775 rev = ctx.rev()
1775 rev = ctx.rev()
1776 if rev is None:
1776 if rev is None:
1777 jrev = jnode = 'null'
1777 jrev = jnode = 'null'
1778 else:
1778 else:
1779 jrev = '%d' % rev
1779 jrev = '%d' % rev
1780 jnode = '"%s"' % hex(ctx.node())
1780 jnode = '"%s"' % hex(ctx.node())
1781 j = encoding.jsonescape
1781 j = encoding.jsonescape
1782
1782
1783 if self._first:
1783 if self._first:
1784 self.ui.write("[\n {")
1784 self.ui.write("[\n {")
1785 self._first = False
1785 self._first = False
1786 else:
1786 else:
1787 self.ui.write(",\n {")
1787 self.ui.write(",\n {")
1788
1788
1789 if self.ui.quiet:
1789 if self.ui.quiet:
1790 self.ui.write(('\n "rev": %s') % jrev)
1790 self.ui.write(('\n "rev": %s') % jrev)
1791 self.ui.write((',\n "node": %s') % jnode)
1791 self.ui.write((',\n "node": %s') % jnode)
1792 self.ui.write('\n }')
1792 self.ui.write('\n }')
1793 return
1793 return
1794
1794
1795 self.ui.write(('\n "rev": %s') % jrev)
1795 self.ui.write(('\n "rev": %s') % jrev)
1796 self.ui.write((',\n "node": %s') % jnode)
1796 self.ui.write((',\n "node": %s') % jnode)
1797 self.ui.write((',\n "branch": "%s"') % j(ctx.branch()))
1797 self.ui.write((',\n "branch": "%s"') % j(ctx.branch()))
1798 self.ui.write((',\n "phase": "%s"') % ctx.phasestr())
1798 self.ui.write((',\n "phase": "%s"') % ctx.phasestr())
1799 self.ui.write((',\n "user": "%s"') % j(ctx.user()))
1799 self.ui.write((',\n "user": "%s"') % j(ctx.user()))
1800 self.ui.write((',\n "date": [%d, %d]') % ctx.date())
1800 self.ui.write((',\n "date": [%d, %d]') % ctx.date())
1801 self.ui.write((',\n "desc": "%s"') % j(ctx.description()))
1801 self.ui.write((',\n "desc": "%s"') % j(ctx.description()))
1802
1802
1803 self.ui.write((',\n "bookmarks": [%s]') %
1803 self.ui.write((',\n "bookmarks": [%s]') %
1804 ", ".join('"%s"' % j(b) for b in ctx.bookmarks()))
1804 ", ".join('"%s"' % j(b) for b in ctx.bookmarks()))
1805 self.ui.write((',\n "tags": [%s]') %
1805 self.ui.write((',\n "tags": [%s]') %
1806 ", ".join('"%s"' % j(t) for t in ctx.tags()))
1806 ", ".join('"%s"' % j(t) for t in ctx.tags()))
1807 self.ui.write((',\n "parents": [%s]') %
1807 self.ui.write((',\n "parents": [%s]') %
1808 ", ".join('"%s"' % c.hex() for c in ctx.parents()))
1808 ", ".join('"%s"' % c.hex() for c in ctx.parents()))
1809
1809
1810 if self.ui.debugflag:
1810 if self.ui.debugflag:
1811 if rev is None:
1811 if rev is None:
1812 jmanifestnode = 'null'
1812 jmanifestnode = 'null'
1813 else:
1813 else:
1814 jmanifestnode = '"%s"' % hex(ctx.manifestnode())
1814 jmanifestnode = '"%s"' % hex(ctx.manifestnode())
1815 self.ui.write((',\n "manifest": %s') % jmanifestnode)
1815 self.ui.write((',\n "manifest": %s') % jmanifestnode)
1816
1816
1817 self.ui.write((',\n "extra": {%s}') %
1817 self.ui.write((',\n "extra": {%s}') %
1818 ", ".join('"%s": "%s"' % (j(k), j(v))
1818 ", ".join('"%s": "%s"' % (j(k), j(v))
1819 for k, v in ctx.extra().items()))
1819 for k, v in ctx.extra().items()))
1820
1820
1821 files = ctx.p1().status(ctx)
1821 files = ctx.p1().status(ctx)
1822 self.ui.write((',\n "modified": [%s]') %
1822 self.ui.write((',\n "modified": [%s]') %
1823 ", ".join('"%s"' % j(f) for f in files[0]))
1823 ", ".join('"%s"' % j(f) for f in files[0]))
1824 self.ui.write((',\n "added": [%s]') %
1824 self.ui.write((',\n "added": [%s]') %
1825 ", ".join('"%s"' % j(f) for f in files[1]))
1825 ", ".join('"%s"' % j(f) for f in files[1]))
1826 self.ui.write((',\n "removed": [%s]') %
1826 self.ui.write((',\n "removed": [%s]') %
1827 ", ".join('"%s"' % j(f) for f in files[2]))
1827 ", ".join('"%s"' % j(f) for f in files[2]))
1828
1828
1829 elif self.ui.verbose:
1829 elif self.ui.verbose:
1830 self.ui.write((',\n "files": [%s]') %
1830 self.ui.write((',\n "files": [%s]') %
1831 ", ".join('"%s"' % j(f) for f in ctx.files()))
1831 ", ".join('"%s"' % j(f) for f in ctx.files()))
1832
1832
1833 if copies:
1833 if copies:
1834 self.ui.write((',\n "copies": {%s}') %
1834 self.ui.write((',\n "copies": {%s}') %
1835 ", ".join('"%s": "%s"' % (j(k), j(v))
1835 ", ".join('"%s": "%s"' % (j(k), j(v))
1836 for k, v in copies))
1836 for k, v in copies))
1837
1837
1838 matchfn = self.matchfn
1838 matchfn = self.matchfn
1839 if matchfn:
1839 if matchfn:
1840 stat = self.diffopts.get('stat')
1840 stat = self.diffopts.get('stat')
1841 diff = self.diffopts.get('patch')
1841 diff = self.diffopts.get('patch')
1842 diffopts = patch.difffeatureopts(self.ui, self.diffopts, git=True)
1842 diffopts = patch.difffeatureopts(self.ui, self.diffopts, git=True)
1843 node, prev = ctx.node(), ctx.p1().node()
1843 node, prev = ctx.node(), ctx.p1().node()
1844 if stat:
1844 if stat:
1845 self.ui.pushbuffer()
1845 self.ui.pushbuffer()
1846 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
1846 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
1847 match=matchfn, stat=True)
1847 match=matchfn, stat=True)
1848 self.ui.write((',\n "diffstat": "%s"')
1848 self.ui.write((',\n "diffstat": "%s"')
1849 % j(self.ui.popbuffer()))
1849 % j(self.ui.popbuffer()))
1850 if diff:
1850 if diff:
1851 self.ui.pushbuffer()
1851 self.ui.pushbuffer()
1852 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
1852 diffordiffstat(self.ui, self.repo, diffopts, prev, node,
1853 match=matchfn, stat=False)
1853 match=matchfn, stat=False)
1854 self.ui.write((',\n "diff": "%s"') % j(self.ui.popbuffer()))
1854 self.ui.write((',\n "diff": "%s"') % j(self.ui.popbuffer()))
1855
1855
1856 self.ui.write("\n }")
1856 self.ui.write("\n }")
1857
1857
1858 class changeset_templater(changeset_printer):
1858 class changeset_templater(changeset_printer):
1859 '''format changeset information.'''
1859 '''format changeset information.'''
1860
1860
1861 # Arguments before "buffered" used to be positional. Consider not
1861 # Arguments before "buffered" used to be positional. Consider not
1862 # adding/removing arguments before "buffered" to not break callers.
1862 # adding/removing arguments before "buffered" to not break callers.
1863 def __init__(self, ui, repo, tmplspec, matchfn=None, diffopts=None,
1863 def __init__(self, ui, repo, tmplspec, matchfn=None, diffopts=None,
1864 buffered=False):
1864 buffered=False):
1865 diffopts = diffopts or {}
1865 diffopts = diffopts or {}
1866
1866
1867 changeset_printer.__init__(self, ui, repo, matchfn, diffopts, buffered)
1867 changeset_printer.__init__(self, ui, repo, matchfn, diffopts, buffered)
1868 self.t = formatter.loadtemplater(ui, tmplspec,
1868 self.t = formatter.loadtemplater(ui, tmplspec,
1869 cache=templatekw.defaulttempl)
1869 cache=templatekw.defaulttempl)
1870 self._counter = itertools.count()
1870 self._counter = itertools.count()
1871 self.cache = {}
1871 self.cache = {}
1872
1872
1873 self._tref = tmplspec.ref
1873 self._tref = tmplspec.ref
1874 self._parts = {'header': '', 'footer': '',
1874 self._parts = {'header': '', 'footer': '',
1875 tmplspec.ref: tmplspec.ref,
1875 tmplspec.ref: tmplspec.ref,
1876 'docheader': '', 'docfooter': '',
1876 'docheader': '', 'docfooter': '',
1877 'separator': ''}
1877 'separator': ''}
1878 if tmplspec.mapfile:
1878 if tmplspec.mapfile:
1879 # find correct templates for current mode, for backward
1879 # find correct templates for current mode, for backward
1880 # compatibility with 'log -v/-q/--debug' using a mapfile
1880 # compatibility with 'log -v/-q/--debug' using a mapfile
1881 tmplmodes = [
1881 tmplmodes = [
1882 (True, ''),
1882 (True, ''),
1883 (self.ui.verbose, '_verbose'),
1883 (self.ui.verbose, '_verbose'),
1884 (self.ui.quiet, '_quiet'),
1884 (self.ui.quiet, '_quiet'),
1885 (self.ui.debugflag, '_debug'),
1885 (self.ui.debugflag, '_debug'),
1886 ]
1886 ]
1887 for mode, postfix in tmplmodes:
1887 for mode, postfix in tmplmodes:
1888 for t in self._parts:
1888 for t in self._parts:
1889 cur = t + postfix
1889 cur = t + postfix
1890 if mode and cur in self.t:
1890 if mode and cur in self.t:
1891 self._parts[t] = cur
1891 self._parts[t] = cur
1892 else:
1892 else:
1893 partnames = [p for p in self._parts.keys() if p != tmplspec.ref]
1893 partnames = [p for p in self._parts.keys() if p != tmplspec.ref]
1894 m = formatter.templatepartsmap(tmplspec, self.t, partnames)
1894 m = formatter.templatepartsmap(tmplspec, self.t, partnames)
1895 self._parts.update(m)
1895 self._parts.update(m)
1896
1896
1897 if self._parts['docheader']:
1897 if self._parts['docheader']:
1898 self.ui.write(templater.stringify(self.t(self._parts['docheader'])))
1898 self.ui.write(templater.stringify(self.t(self._parts['docheader'])))
1899
1899
1900 def close(self):
1900 def close(self):
1901 if self._parts['docfooter']:
1901 if self._parts['docfooter']:
1902 if not self.footer:
1902 if not self.footer:
1903 self.footer = ""
1903 self.footer = ""
1904 self.footer += templater.stringify(self.t(self._parts['docfooter']))
1904 self.footer += templater.stringify(self.t(self._parts['docfooter']))
1905 return super(changeset_templater, self).close()
1905 return super(changeset_templater, self).close()
1906
1906
1907 def _show(self, ctx, copies, matchfn, hunksfilterfn, props):
1907 def _show(self, ctx, copies, matchfn, hunksfilterfn, props):
1908 '''show a single changeset or file revision'''
1908 '''show a single changeset or file revision'''
1909 props = props.copy()
1909 props = props.copy()
1910 props.update(templatekw.keywords)
1910 props.update(templatekw.keywords)
1911 props['templ'] = self.t
1911 props['templ'] = self.t
1912 props['ctx'] = ctx
1912 props['ctx'] = ctx
1913 props['repo'] = self.repo
1913 props['repo'] = self.repo
1914 props['ui'] = self.repo.ui
1914 props['ui'] = self.repo.ui
1915 props['index'] = index = next(self._counter)
1915 props['index'] = index = next(self._counter)
1916 props['revcache'] = {'copies': copies}
1916 props['revcache'] = {'copies': copies}
1917 props['cache'] = self.cache
1917 props['cache'] = self.cache
1918 props = pycompat.strkwargs(props)
1918 props = pycompat.strkwargs(props)
1919
1919
1920 # write separator, which wouldn't work well with the header part below
1920 # write separator, which wouldn't work well with the header part below
1921 # since there's inherently a conflict between header (across items) and
1921 # since there's inherently a conflict between header (across items) and
1922 # separator (per item)
1922 # separator (per item)
1923 if self._parts['separator'] and index > 0:
1923 if self._parts['separator'] and index > 0:
1924 self.ui.write(templater.stringify(self.t(self._parts['separator'])))
1924 self.ui.write(templater.stringify(self.t(self._parts['separator'])))
1925
1925
1926 # write header
1926 # write header
1927 if self._parts['header']:
1927 if self._parts['header']:
1928 h = templater.stringify(self.t(self._parts['header'], **props))
1928 h = templater.stringify(self.t(self._parts['header'], **props))
1929 if self.buffered:
1929 if self.buffered:
1930 self.header[ctx.rev()] = h
1930 self.header[ctx.rev()] = h
1931 else:
1931 else:
1932 if self.lastheader != h:
1932 if self.lastheader != h:
1933 self.lastheader = h
1933 self.lastheader = h
1934 self.ui.write(h)
1934 self.ui.write(h)
1935
1935
1936 # write changeset metadata, then patch if requested
1936 # write changeset metadata, then patch if requested
1937 key = self._parts[self._tref]
1937 key = self._parts[self._tref]
1938 self.ui.write(templater.stringify(self.t(key, **props)))
1938 self.ui.write(templater.stringify(self.t(key, **props)))
1939 self.showpatch(ctx, matchfn, hunksfilterfn=hunksfilterfn)
1939 self.showpatch(ctx, matchfn, hunksfilterfn=hunksfilterfn)
1940
1940
1941 if self._parts['footer']:
1941 if self._parts['footer']:
1942 if not self.footer:
1942 if not self.footer:
1943 self.footer = templater.stringify(
1943 self.footer = templater.stringify(
1944 self.t(self._parts['footer'], **props))
1944 self.t(self._parts['footer'], **props))
1945
1945
1946 def logtemplatespec(tmpl, mapfile):
1946 def logtemplatespec(tmpl, mapfile):
1947 if mapfile:
1947 if mapfile:
1948 return formatter.templatespec('changeset', tmpl, mapfile)
1948 return formatter.templatespec('changeset', tmpl, mapfile)
1949 else:
1949 else:
1950 return formatter.templatespec('', tmpl, None)
1950 return formatter.templatespec('', tmpl, None)
1951
1951
1952 def _lookuplogtemplate(ui, tmpl, style):
1952 def _lookuplogtemplate(ui, tmpl, style):
1953 """Find the template matching the given template spec or style
1953 """Find the template matching the given template spec or style
1954
1954
1955 See formatter.lookuptemplate() for details.
1955 See formatter.lookuptemplate() for details.
1956 """
1956 """
1957
1957
1958 # ui settings
1958 # ui settings
1959 if not tmpl and not style: # template are stronger than style
1959 if not tmpl and not style: # template are stronger than style
1960 tmpl = ui.config('ui', 'logtemplate')
1960 tmpl = ui.config('ui', 'logtemplate')
1961 if tmpl:
1961 if tmpl:
1962 return logtemplatespec(templater.unquotestring(tmpl), None)
1962 return logtemplatespec(templater.unquotestring(tmpl), None)
1963 else:
1963 else:
1964 style = util.expandpath(ui.config('ui', 'style'))
1964 style = util.expandpath(ui.config('ui', 'style'))
1965
1965
1966 if not tmpl and style:
1966 if not tmpl and style:
1967 mapfile = style
1967 mapfile = style
1968 if not os.path.split(mapfile)[0]:
1968 if not os.path.split(mapfile)[0]:
1969 mapname = (templater.templatepath('map-cmdline.' + mapfile)
1969 mapname = (templater.templatepath('map-cmdline.' + mapfile)
1970 or templater.templatepath(mapfile))
1970 or templater.templatepath(mapfile))
1971 if mapname:
1971 if mapname:
1972 mapfile = mapname
1972 mapfile = mapname
1973 return logtemplatespec(None, mapfile)
1973 return logtemplatespec(None, mapfile)
1974
1974
1975 if not tmpl:
1975 if not tmpl:
1976 return logtemplatespec(None, None)
1976 return logtemplatespec(None, None)
1977
1977
1978 return formatter.lookuptemplate(ui, 'changeset', tmpl)
1978 return formatter.lookuptemplate(ui, 'changeset', tmpl)
1979
1979
1980 def makelogtemplater(ui, repo, tmpl, buffered=False):
1980 def makelogtemplater(ui, repo, tmpl, buffered=False):
1981 """Create a changeset_templater from a literal template 'tmpl'"""
1981 """Create a changeset_templater from a literal template 'tmpl'"""
1982 spec = logtemplatespec(tmpl, None)
1982 spec = logtemplatespec(tmpl, None)
1983 return changeset_templater(ui, repo, spec, buffered=buffered)
1983 return changeset_templater(ui, repo, spec, buffered=buffered)
1984
1984
1985 def show_changeset(ui, repo, opts, buffered=False):
1985 def show_changeset(ui, repo, opts, buffered=False):
1986 """show one changeset using template or regular display.
1986 """show one changeset using template or regular display.
1987
1987
1988 Display format will be the first non-empty hit of:
1988 Display format will be the first non-empty hit of:
1989 1. option 'template'
1989 1. option 'template'
1990 2. option 'style'
1990 2. option 'style'
1991 3. [ui] setting 'logtemplate'
1991 3. [ui] setting 'logtemplate'
1992 4. [ui] setting 'style'
1992 4. [ui] setting 'style'
1993 If all of these values are either the unset or the empty string,
1993 If all of these values are either the unset or the empty string,
1994 regular display via changeset_printer() is done.
1994 regular display via changeset_printer() is done.
1995 """
1995 """
1996 # options
1996 # options
1997 match = None
1997 match = None
1998 if opts.get('patch') or opts.get('stat'):
1998 if opts.get('patch') or opts.get('stat'):
1999 match = scmutil.matchall(repo)
1999 match = scmutil.matchall(repo)
2000
2000
2001 if opts.get('template') == 'json':
2001 if opts.get('template') == 'json':
2002 return jsonchangeset(ui, repo, match, opts, buffered)
2002 return jsonchangeset(ui, repo, match, opts, buffered)
2003
2003
2004 spec = _lookuplogtemplate(ui, opts.get('template'), opts.get('style'))
2004 spec = _lookuplogtemplate(ui, opts.get('template'), opts.get('style'))
2005
2005
2006 if not spec.ref and not spec.tmpl and not spec.mapfile:
2006 if not spec.ref and not spec.tmpl and not spec.mapfile:
2007 return changeset_printer(ui, repo, match, opts, buffered)
2007 return changeset_printer(ui, repo, match, opts, buffered)
2008
2008
2009 return changeset_templater(ui, repo, spec, match, opts, buffered)
2009 return changeset_templater(ui, repo, spec, match, opts, buffered)
2010
2010
2011 def showmarker(fm, marker, index=None):
2011 def showmarker(fm, marker, index=None):
2012 """utility function to display obsolescence marker in a readable way
2012 """utility function to display obsolescence marker in a readable way
2013
2013
2014 To be used by debug function."""
2014 To be used by debug function."""
2015 if index is not None:
2015 if index is not None:
2016 fm.write('index', '%i ', index)
2016 fm.write('index', '%i ', index)
2017 fm.write('prednode', '%s ', hex(marker.prednode()))
2017 fm.write('prednode', '%s ', hex(marker.prednode()))
2018 succs = marker.succnodes()
2018 succs = marker.succnodes()
2019 fm.condwrite(succs, 'succnodes', '%s ',
2019 fm.condwrite(succs, 'succnodes', '%s ',
2020 fm.formatlist(map(hex, succs), name='node'))
2020 fm.formatlist(map(hex, succs), name='node'))
2021 fm.write('flag', '%X ', marker.flags())
2021 fm.write('flag', '%X ', marker.flags())
2022 parents = marker.parentnodes()
2022 parents = marker.parentnodes()
2023 if parents is not None:
2023 if parents is not None:
2024 fm.write('parentnodes', '{%s} ',
2024 fm.write('parentnodes', '{%s} ',
2025 fm.formatlist(map(hex, parents), name='node', sep=', '))
2025 fm.formatlist(map(hex, parents), name='node', sep=', '))
2026 fm.write('date', '(%s) ', fm.formatdate(marker.date()))
2026 fm.write('date', '(%s) ', fm.formatdate(marker.date()))
2027 meta = marker.metadata().copy()
2027 meta = marker.metadata().copy()
2028 meta.pop('date', None)
2028 meta.pop('date', None)
2029 fm.write('metadata', '{%s}', fm.formatdict(meta, fmt='%r: %r', sep=', '))
2029 fm.write('metadata', '{%s}', fm.formatdict(meta, fmt='%r: %r', sep=', '))
2030 fm.plain('\n')
2030 fm.plain('\n')
2031
2031
2032 def finddate(ui, repo, date):
2032 def finddate(ui, repo, date):
2033 """Find the tipmost changeset that matches the given date spec"""
2033 """Find the tipmost changeset that matches the given date spec"""
2034
2034
2035 df = util.matchdate(date)
2035 df = util.matchdate(date)
2036 m = scmutil.matchall(repo)
2036 m = scmutil.matchall(repo)
2037 results = {}
2037 results = {}
2038
2038
2039 def prep(ctx, fns):
2039 def prep(ctx, fns):
2040 d = ctx.date()
2040 d = ctx.date()
2041 if df(d[0]):
2041 if df(d[0]):
2042 results[ctx.rev()] = d
2042 results[ctx.rev()] = d
2043
2043
2044 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
2044 for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
2045 rev = ctx.rev()
2045 rev = ctx.rev()
2046 if rev in results:
2046 if rev in results:
2047 ui.status(_("found revision %s from %s\n") %
2047 ui.status(_("found revision %s from %s\n") %
2048 (rev, util.datestr(results[rev])))
2048 (rev, util.datestr(results[rev])))
2049 return '%d' % rev
2049 return '%d' % rev
2050
2050
2051 raise error.Abort(_("revision matching date not found"))
2051 raise error.Abort(_("revision matching date not found"))
2052
2052
2053 def increasingwindows(windowsize=8, sizelimit=512):
2053 def increasingwindows(windowsize=8, sizelimit=512):
2054 while True:
2054 while True:
2055 yield windowsize
2055 yield windowsize
2056 if windowsize < sizelimit:
2056 if windowsize < sizelimit:
2057 windowsize *= 2
2057 windowsize *= 2
2058
2058
2059 class FileWalkError(Exception):
2059 class FileWalkError(Exception):
2060 pass
2060 pass
2061
2061
2062 def walkfilerevs(repo, match, follow, revs, fncache):
2062 def walkfilerevs(repo, match, follow, revs, fncache):
2063 '''Walks the file history for the matched files.
2063 '''Walks the file history for the matched files.
2064
2064
2065 Returns the changeset revs that are involved in the file history.
2065 Returns the changeset revs that are involved in the file history.
2066
2066
2067 Throws FileWalkError if the file history can't be walked using
2067 Throws FileWalkError if the file history can't be walked using
2068 filelogs alone.
2068 filelogs alone.
2069 '''
2069 '''
2070 wanted = set()
2070 wanted = set()
2071 copies = []
2071 copies = []
2072 minrev, maxrev = min(revs), max(revs)
2072 minrev, maxrev = min(revs), max(revs)
2073 def filerevgen(filelog, last):
2073 def filerevgen(filelog, last):
2074 """
2074 """
2075 Only files, no patterns. Check the history of each file.
2075 Only files, no patterns. Check the history of each file.
2076
2076
2077 Examines filelog entries within minrev, maxrev linkrev range
2077 Examines filelog entries within minrev, maxrev linkrev range
2078 Returns an iterator yielding (linkrev, parentlinkrevs, copied)
2078 Returns an iterator yielding (linkrev, parentlinkrevs, copied)
2079 tuples in backwards order
2079 tuples in backwards order
2080 """
2080 """
2081 cl_count = len(repo)
2081 cl_count = len(repo)
2082 revs = []
2082 revs = []
2083 for j in xrange(0, last + 1):
2083 for j in xrange(0, last + 1):
2084 linkrev = filelog.linkrev(j)
2084 linkrev = filelog.linkrev(j)
2085 if linkrev < minrev:
2085 if linkrev < minrev:
2086 continue
2086 continue
2087 # only yield rev for which we have the changelog, it can
2087 # only yield rev for which we have the changelog, it can
2088 # happen while doing "hg log" during a pull or commit
2088 # happen while doing "hg log" during a pull or commit
2089 if linkrev >= cl_count:
2089 if linkrev >= cl_count:
2090 break
2090 break
2091
2091
2092 parentlinkrevs = []
2092 parentlinkrevs = []
2093 for p in filelog.parentrevs(j):
2093 for p in filelog.parentrevs(j):
2094 if p != nullrev:
2094 if p != nullrev:
2095 parentlinkrevs.append(filelog.linkrev(p))
2095 parentlinkrevs.append(filelog.linkrev(p))
2096 n = filelog.node(j)
2096 n = filelog.node(j)
2097 revs.append((linkrev, parentlinkrevs,
2097 revs.append((linkrev, parentlinkrevs,
2098 follow and filelog.renamed(n)))
2098 follow and filelog.renamed(n)))
2099
2099
2100 return reversed(revs)
2100 return reversed(revs)
2101 def iterfiles():
2101 def iterfiles():
2102 pctx = repo['.']
2102 pctx = repo['.']
2103 for filename in match.files():
2103 for filename in match.files():
2104 if follow:
2104 if follow:
2105 if filename not in pctx:
2105 if filename not in pctx:
2106 raise error.Abort(_('cannot follow file not in parent '
2106 raise error.Abort(_('cannot follow file not in parent '
2107 'revision: "%s"') % filename)
2107 'revision: "%s"') % filename)
2108 yield filename, pctx[filename].filenode()
2108 yield filename, pctx[filename].filenode()
2109 else:
2109 else:
2110 yield filename, None
2110 yield filename, None
2111 for filename_node in copies:
2111 for filename_node in copies:
2112 yield filename_node
2112 yield filename_node
2113
2113
2114 for file_, node in iterfiles():
2114 for file_, node in iterfiles():
2115 filelog = repo.file(file_)
2115 filelog = repo.file(file_)
2116 if not len(filelog):
2116 if not len(filelog):
2117 if node is None:
2117 if node is None:
2118 # A zero count may be a directory or deleted file, so
2118 # A zero count may be a directory or deleted file, so
2119 # try to find matching entries on the slow path.
2119 # try to find matching entries on the slow path.
2120 if follow:
2120 if follow:
2121 raise error.Abort(
2121 raise error.Abort(
2122 _('cannot follow nonexistent file: "%s"') % file_)
2122 _('cannot follow nonexistent file: "%s"') % file_)
2123 raise FileWalkError("Cannot walk via filelog")
2123 raise FileWalkError("Cannot walk via filelog")
2124 else:
2124 else:
2125 continue
2125 continue
2126
2126
2127 if node is None:
2127 if node is None:
2128 last = len(filelog) - 1
2128 last = len(filelog) - 1
2129 else:
2129 else:
2130 last = filelog.rev(node)
2130 last = filelog.rev(node)
2131
2131
2132 # keep track of all ancestors of the file
2132 # keep track of all ancestors of the file
2133 ancestors = {filelog.linkrev(last)}
2133 ancestors = {filelog.linkrev(last)}
2134
2134
2135 # iterate from latest to oldest revision
2135 # iterate from latest to oldest revision
2136 for rev, flparentlinkrevs, copied in filerevgen(filelog, last):
2136 for rev, flparentlinkrevs, copied in filerevgen(filelog, last):
2137 if not follow:
2137 if not follow:
2138 if rev > maxrev:
2138 if rev > maxrev:
2139 continue
2139 continue
2140 else:
2140 else:
2141 # Note that last might not be the first interesting
2141 # Note that last might not be the first interesting
2142 # rev to us:
2142 # rev to us:
2143 # if the file has been changed after maxrev, we'll
2143 # if the file has been changed after maxrev, we'll
2144 # have linkrev(last) > maxrev, and we still need
2144 # have linkrev(last) > maxrev, and we still need
2145 # to explore the file graph
2145 # to explore the file graph
2146 if rev not in ancestors:
2146 if rev not in ancestors:
2147 continue
2147 continue
2148 # XXX insert 1327 fix here
2148 # XXX insert 1327 fix here
2149 if flparentlinkrevs:
2149 if flparentlinkrevs:
2150 ancestors.update(flparentlinkrevs)
2150 ancestors.update(flparentlinkrevs)
2151
2151
2152 fncache.setdefault(rev, []).append(file_)
2152 fncache.setdefault(rev, []).append(file_)
2153 wanted.add(rev)
2153 wanted.add(rev)
2154 if copied:
2154 if copied:
2155 copies.append(copied)
2155 copies.append(copied)
2156
2156
2157 return wanted
2157 return wanted
2158
2158
2159 class _followfilter(object):
2159 class _followfilter(object):
2160 def __init__(self, repo, onlyfirst=False):
2160 def __init__(self, repo, onlyfirst=False):
2161 self.repo = repo
2161 self.repo = repo
2162 self.startrev = nullrev
2162 self.startrev = nullrev
2163 self.roots = set()
2163 self.roots = set()
2164 self.onlyfirst = onlyfirst
2164 self.onlyfirst = onlyfirst
2165
2165
2166 def match(self, rev):
2166 def match(self, rev):
2167 def realparents(rev):
2167 def realparents(rev):
2168 if self.onlyfirst:
2168 if self.onlyfirst:
2169 return self.repo.changelog.parentrevs(rev)[0:1]
2169 return self.repo.changelog.parentrevs(rev)[0:1]
2170 else:
2170 else:
2171 return filter(lambda x: x != nullrev,
2171 return filter(lambda x: x != nullrev,
2172 self.repo.changelog.parentrevs(rev))
2172 self.repo.changelog.parentrevs(rev))
2173
2173
2174 if self.startrev == nullrev:
2174 if self.startrev == nullrev:
2175 self.startrev = rev
2175 self.startrev = rev
2176 return True
2176 return True
2177
2177
2178 if rev > self.startrev:
2178 if rev > self.startrev:
2179 # forward: all descendants
2179 # forward: all descendants
2180 if not self.roots:
2180 if not self.roots:
2181 self.roots.add(self.startrev)
2181 self.roots.add(self.startrev)
2182 for parent in realparents(rev):
2182 for parent in realparents(rev):
2183 if parent in self.roots:
2183 if parent in self.roots:
2184 self.roots.add(rev)
2184 self.roots.add(rev)
2185 return True
2185 return True
2186 else:
2186 else:
2187 # backwards: all parents
2187 # backwards: all parents
2188 if not self.roots:
2188 if not self.roots:
2189 self.roots.update(realparents(self.startrev))
2189 self.roots.update(realparents(self.startrev))
2190 if rev in self.roots:
2190 if rev in self.roots:
2191 self.roots.remove(rev)
2191 self.roots.remove(rev)
2192 self.roots.update(realparents(rev))
2192 self.roots.update(realparents(rev))
2193 return True
2193 return True
2194
2194
2195 return False
2195 return False
2196
2196
2197 def walkchangerevs(repo, match, opts, prepare):
2197 def walkchangerevs(repo, match, opts, prepare):
2198 '''Iterate over files and the revs in which they changed.
2198 '''Iterate over files and the revs in which they changed.
2199
2199
2200 Callers most commonly need to iterate backwards over the history
2200 Callers most commonly need to iterate backwards over the history
2201 in which they are interested. Doing so has awful (quadratic-looking)
2201 in which they are interested. Doing so has awful (quadratic-looking)
2202 performance, so we use iterators in a "windowed" way.
2202 performance, so we use iterators in a "windowed" way.
2203
2203
2204 We walk a window of revisions in the desired order. Within the
2204 We walk a window of revisions in the desired order. Within the
2205 window, we first walk forwards to gather data, then in the desired
2205 window, we first walk forwards to gather data, then in the desired
2206 order (usually backwards) to display it.
2206 order (usually backwards) to display it.
2207
2207
2208 This function returns an iterator yielding contexts. Before
2208 This function returns an iterator yielding contexts. Before
2209 yielding each context, the iterator will first call the prepare
2209 yielding each context, the iterator will first call the prepare
2210 function on each context in the window in forward order.'''
2210 function on each context in the window in forward order.'''
2211
2211
2212 follow = opts.get('follow') or opts.get('follow_first')
2212 follow = opts.get('follow') or opts.get('follow_first')
2213 revs = _logrevs(repo, opts)
2213 revs = _logrevs(repo, opts)
2214 if not revs:
2214 if not revs:
2215 return []
2215 return []
2216 wanted = set()
2216 wanted = set()
2217 slowpath = match.anypats() or ((match.isexact() or match.prefix()) and
2217 slowpath = match.anypats() or ((match.isexact() or match.prefix()) and
2218 opts.get('removed'))
2218 opts.get('removed'))
2219 fncache = {}
2219 fncache = {}
2220 change = repo.changectx
2220 change = repo.changectx
2221
2221
2222 # First step is to fill wanted, the set of revisions that we want to yield.
2222 # First step is to fill wanted, the set of revisions that we want to yield.
2223 # When it does not induce extra cost, we also fill fncache for revisions in
2223 # When it does not induce extra cost, we also fill fncache for revisions in
2224 # wanted: a cache of filenames that were changed (ctx.files()) and that
2224 # wanted: a cache of filenames that were changed (ctx.files()) and that
2225 # match the file filtering conditions.
2225 # match the file filtering conditions.
2226
2226
2227 if match.always():
2227 if match.always():
2228 # No files, no patterns. Display all revs.
2228 # No files, no patterns. Display all revs.
2229 wanted = revs
2229 wanted = revs
2230 elif not slowpath:
2230 elif not slowpath:
2231 # We only have to read through the filelog to find wanted revisions
2231 # We only have to read through the filelog to find wanted revisions
2232
2232
2233 try:
2233 try:
2234 wanted = walkfilerevs(repo, match, follow, revs, fncache)
2234 wanted = walkfilerevs(repo, match, follow, revs, fncache)
2235 except FileWalkError:
2235 except FileWalkError:
2236 slowpath = True
2236 slowpath = True
2237
2237
2238 # We decided to fall back to the slowpath because at least one
2238 # We decided to fall back to the slowpath because at least one
2239 # of the paths was not a file. Check to see if at least one of them
2239 # of the paths was not a file. Check to see if at least one of them
2240 # existed in history, otherwise simply return
2240 # existed in history, otherwise simply return
2241 for path in match.files():
2241 for path in match.files():
2242 if path == '.' or path in repo.store:
2242 if path == '.' or path in repo.store:
2243 break
2243 break
2244 else:
2244 else:
2245 return []
2245 return []
2246
2246
2247 if slowpath:
2247 if slowpath:
2248 # We have to read the changelog to match filenames against
2248 # We have to read the changelog to match filenames against
2249 # changed files
2249 # changed files
2250
2250
2251 if follow:
2251 if follow:
2252 raise error.Abort(_('can only follow copies/renames for explicit '
2252 raise error.Abort(_('can only follow copies/renames for explicit '
2253 'filenames'))
2253 'filenames'))
2254
2254
2255 # The slow path checks files modified in every changeset.
2255 # The slow path checks files modified in every changeset.
2256 # This is really slow on large repos, so compute the set lazily.
2256 # This is really slow on large repos, so compute the set lazily.
2257 class lazywantedset(object):
2257 class lazywantedset(object):
2258 def __init__(self):
2258 def __init__(self):
2259 self.set = set()
2259 self.set = set()
2260 self.revs = set(revs)
2260 self.revs = set(revs)
2261
2261
2262 # No need to worry about locality here because it will be accessed
2262 # No need to worry about locality here because it will be accessed
2263 # in the same order as the increasing window below.
2263 # in the same order as the increasing window below.
2264 def __contains__(self, value):
2264 def __contains__(self, value):
2265 if value in self.set:
2265 if value in self.set:
2266 return True
2266 return True
2267 elif not value in self.revs:
2267 elif not value in self.revs:
2268 return False
2268 return False
2269 else:
2269 else:
2270 self.revs.discard(value)
2270 self.revs.discard(value)
2271 ctx = change(value)
2271 ctx = change(value)
2272 matches = filter(match, ctx.files())
2272 matches = filter(match, ctx.files())
2273 if matches:
2273 if matches:
2274 fncache[value] = matches
2274 fncache[value] = matches
2275 self.set.add(value)
2275 self.set.add(value)
2276 return True
2276 return True
2277 return False
2277 return False
2278
2278
2279 def discard(self, value):
2279 def discard(self, value):
2280 self.revs.discard(value)
2280 self.revs.discard(value)
2281 self.set.discard(value)
2281 self.set.discard(value)
2282
2282
2283 wanted = lazywantedset()
2283 wanted = lazywantedset()
2284
2284
2285 # it might be worthwhile to do this in the iterator if the rev range
2285 # it might be worthwhile to do this in the iterator if the rev range
2286 # is descending and the prune args are all within that range
2286 # is descending and the prune args are all within that range
2287 for rev in opts.get('prune', ()):
2287 for rev in opts.get('prune', ()):
2288 rev = repo[rev].rev()
2288 rev = repo[rev].rev()
2289 ff = _followfilter(repo)
2289 ff = _followfilter(repo)
2290 stop = min(revs[0], revs[-1])
2290 stop = min(revs[0], revs[-1])
2291 for x in xrange(rev, stop - 1, -1):
2291 for x in xrange(rev, stop - 1, -1):
2292 if ff.match(x):
2292 if ff.match(x):
2293 wanted = wanted - [x]
2293 wanted = wanted - [x]
2294
2294
2295 # Now that wanted is correctly initialized, we can iterate over the
2295 # Now that wanted is correctly initialized, we can iterate over the
2296 # revision range, yielding only revisions in wanted.
2296 # revision range, yielding only revisions in wanted.
2297 def iterate():
2297 def iterate():
2298 if follow and match.always():
2298 if follow and match.always():
2299 ff = _followfilter(repo, onlyfirst=opts.get('follow_first'))
2299 ff = _followfilter(repo, onlyfirst=opts.get('follow_first'))
2300 def want(rev):
2300 def want(rev):
2301 return ff.match(rev) and rev in wanted
2301 return ff.match(rev) and rev in wanted
2302 else:
2302 else:
2303 def want(rev):
2303 def want(rev):
2304 return rev in wanted
2304 return rev in wanted
2305
2305
2306 it = iter(revs)
2306 it = iter(revs)
2307 stopiteration = False
2307 stopiteration = False
2308 for windowsize in increasingwindows():
2308 for windowsize in increasingwindows():
2309 nrevs = []
2309 nrevs = []
2310 for i in xrange(windowsize):
2310 for i in xrange(windowsize):
2311 rev = next(it, None)
2311 rev = next(it, None)
2312 if rev is None:
2312 if rev is None:
2313 stopiteration = True
2313 stopiteration = True
2314 break
2314 break
2315 elif want(rev):
2315 elif want(rev):
2316 nrevs.append(rev)
2316 nrevs.append(rev)
2317 for rev in sorted(nrevs):
2317 for rev in sorted(nrevs):
2318 fns = fncache.get(rev)
2318 fns = fncache.get(rev)
2319 ctx = change(rev)
2319 ctx = change(rev)
2320 if not fns:
2320 if not fns:
2321 def fns_generator():
2321 def fns_generator():
2322 for f in ctx.files():
2322 for f in ctx.files():
2323 if match(f):
2323 if match(f):
2324 yield f
2324 yield f
2325 fns = fns_generator()
2325 fns = fns_generator()
2326 prepare(ctx, fns)
2326 prepare(ctx, fns)
2327 for rev in nrevs:
2327 for rev in nrevs:
2328 yield change(rev)
2328 yield change(rev)
2329
2329
2330 if stopiteration:
2330 if stopiteration:
2331 break
2331 break
2332
2332
2333 return iterate()
2333 return iterate()
2334
2334
2335 def _makefollowlogfilematcher(repo, files, followfirst):
2335 def _makefollowlogfilematcher(repo, files, followfirst):
2336 # When displaying a revision with --patch --follow FILE, we have
2336 # When displaying a revision with --patch --follow FILE, we have
2337 # to know which file of the revision must be diffed. With
2337 # to know which file of the revision must be diffed. With
2338 # --follow, we want the names of the ancestors of FILE in the
2338 # --follow, we want the names of the ancestors of FILE in the
2339 # revision, stored in "fcache". "fcache" is populated by
2339 # revision, stored in "fcache". "fcache" is populated by
2340 # reproducing the graph traversal already done by --follow revset
2340 # reproducing the graph traversal already done by --follow revset
2341 # and relating revs to file names (which is not "correct" but
2341 # and relating revs to file names (which is not "correct" but
2342 # good enough).
2342 # good enough).
2343 fcache = {}
2343 fcache = {}
2344 fcacheready = [False]
2344 fcacheready = [False]
2345 pctx = repo['.']
2345 pctx = repo['.']
2346
2346
2347 def populate():
2347 def populate():
2348 for fn in files:
2348 for fn in files:
2349 fctx = pctx[fn]
2349 fctx = pctx[fn]
2350 fcache.setdefault(fctx.introrev(), set()).add(fctx.path())
2350 fcache.setdefault(fctx.introrev(), set()).add(fctx.path())
2351 for c in fctx.ancestors(followfirst=followfirst):
2351 for c in fctx.ancestors(followfirst=followfirst):
2352 fcache.setdefault(c.rev(), set()).add(c.path())
2352 fcache.setdefault(c.rev(), set()).add(c.path())
2353
2353
2354 def filematcher(rev):
2354 def filematcher(rev):
2355 if not fcacheready[0]:
2355 if not fcacheready[0]:
2356 # Lazy initialization
2356 # Lazy initialization
2357 fcacheready[0] = True
2357 fcacheready[0] = True
2358 populate()
2358 populate()
2359 return scmutil.matchfiles(repo, fcache.get(rev, []))
2359 return scmutil.matchfiles(repo, fcache.get(rev, []))
2360
2360
2361 return filematcher
2361 return filematcher
2362
2362
2363 def _makenofollowlogfilematcher(repo, pats, opts):
2363 def _makenofollowlogfilematcher(repo, pats, opts):
2364 '''hook for extensions to override the filematcher for non-follow cases'''
2364 '''hook for extensions to override the filematcher for non-follow cases'''
2365 return None
2365 return None
2366
2366
2367 def _makelogrevset(repo, pats, opts, revs):
2367 def _makelogrevset(repo, pats, opts, revs):
2368 """Return (expr, filematcher) where expr is a revset string built
2368 """Return (expr, filematcher) where expr is a revset string built
2369 from log options and file patterns or None. If --stat or --patch
2369 from log options and file patterns or None. If --stat or --patch
2370 are not passed filematcher is None. Otherwise it is a callable
2370 are not passed filematcher is None. Otherwise it is a callable
2371 taking a revision number and returning a match objects filtering
2371 taking a revision number and returning a match objects filtering
2372 the files to be detailed when displaying the revision.
2372 the files to be detailed when displaying the revision.
2373 """
2373 """
2374 opt2revset = {
2374 opt2revset = {
2375 'no_merges': ('not merge()', None),
2375 'no_merges': ('not merge()', None),
2376 'only_merges': ('merge()', None),
2376 'only_merges': ('merge()', None),
2377 '_ancestors': ('ancestors(%(val)s)', None),
2377 '_ancestors': ('ancestors(%(val)s)', None),
2378 '_fancestors': ('_firstancestors(%(val)s)', None),
2378 '_fancestors': ('_firstancestors(%(val)s)', None),
2379 '_descendants': ('descendants(%(val)s)', None),
2379 '_descendants': ('descendants(%(val)s)', None),
2380 '_fdescendants': ('_firstdescendants(%(val)s)', None),
2380 '_fdescendants': ('_firstdescendants(%(val)s)', None),
2381 '_matchfiles': ('_matchfiles(%(val)s)', None),
2381 '_matchfiles': ('_matchfiles(%(val)s)', None),
2382 'date': ('date(%(val)r)', None),
2382 'date': ('date(%(val)r)', None),
2383 'branch': ('branch(%(val)r)', ' or '),
2383 'branch': ('branch(%(val)r)', ' or '),
2384 '_patslog': ('filelog(%(val)r)', ' or '),
2384 '_patslog': ('filelog(%(val)r)', ' or '),
2385 '_patsfollow': ('follow(%(val)r)', ' or '),
2385 '_patsfollow': ('follow(%(val)r)', ' or '),
2386 '_patsfollowfirst': ('_followfirst(%(val)r)', ' or '),
2386 '_patsfollowfirst': ('_followfirst(%(val)r)', ' or '),
2387 'keyword': ('keyword(%(val)r)', ' or '),
2387 'keyword': ('keyword(%(val)r)', ' or '),
2388 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '),
2388 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '),
2389 'user': ('user(%(val)r)', ' or '),
2389 'user': ('user(%(val)r)', ' or '),
2390 }
2390 }
2391
2391
2392 opts = dict(opts)
2392 opts = dict(opts)
2393 # follow or not follow?
2393 # follow or not follow?
2394 follow = opts.get('follow') or opts.get('follow_first')
2394 follow = opts.get('follow') or opts.get('follow_first')
2395 if opts.get('follow_first'):
2395 if opts.get('follow_first'):
2396 followfirst = 1
2396 followfirst = 1
2397 else:
2397 else:
2398 followfirst = 0
2398 followfirst = 0
2399 # --follow with FILE behavior depends on revs...
2399 # --follow with FILE behavior depends on revs...
2400 it = iter(revs)
2400 it = iter(revs)
2401 startrev = next(it)
2401 startrev = next(it)
2402 followdescendants = startrev < next(it, startrev)
2402 followdescendants = startrev < next(it, startrev)
2403
2403
2404 # branch and only_branch are really aliases and must be handled at
2404 # branch and only_branch are really aliases and must be handled at
2405 # the same time
2405 # the same time
2406 opts['branch'] = opts.get('branch', []) + opts.get('only_branch', [])
2406 opts['branch'] = opts.get('branch', []) + opts.get('only_branch', [])
2407 opts['branch'] = [repo.lookupbranch(b) for b in opts['branch']]
2407 opts['branch'] = [repo.lookupbranch(b) for b in opts['branch']]
2408 # pats/include/exclude are passed to match.match() directly in
2408 # pats/include/exclude are passed to match.match() directly in
2409 # _matchfiles() revset but walkchangerevs() builds its matcher with
2409 # _matchfiles() revset but walkchangerevs() builds its matcher with
2410 # scmutil.match(). The difference is input pats are globbed on
2410 # scmutil.match(). The difference is input pats are globbed on
2411 # platforms without shell expansion (windows).
2411 # platforms without shell expansion (windows).
2412 wctx = repo[None]
2412 wctx = repo[None]
2413 match, pats = scmutil.matchandpats(wctx, pats, opts)
2413 match, pats = scmutil.matchandpats(wctx, pats, opts)
2414 slowpath = match.anypats() or ((match.isexact() or match.prefix()) and
2414 slowpath = match.anypats() or ((match.isexact() or match.prefix()) and
2415 opts.get('removed'))
2415 opts.get('removed'))
2416 if not slowpath:
2416 if not slowpath:
2417 for f in match.files():
2417 for f in match.files():
2418 if follow and f not in wctx:
2418 if follow and f not in wctx:
2419 # If the file exists, it may be a directory, so let it
2419 # If the file exists, it may be a directory, so let it
2420 # take the slow path.
2420 # take the slow path.
2421 if os.path.exists(repo.wjoin(f)):
2421 if os.path.exists(repo.wjoin(f)):
2422 slowpath = True
2422 slowpath = True
2423 continue
2423 continue
2424 else:
2424 else:
2425 raise error.Abort(_('cannot follow file not in parent '
2425 raise error.Abort(_('cannot follow file not in parent '
2426 'revision: "%s"') % f)
2426 'revision: "%s"') % f)
2427 filelog = repo.file(f)
2427 filelog = repo.file(f)
2428 if not filelog:
2428 if not filelog:
2429 # A zero count may be a directory or deleted file, so
2429 # A zero count may be a directory or deleted file, so
2430 # try to find matching entries on the slow path.
2430 # try to find matching entries on the slow path.
2431 if follow:
2431 if follow:
2432 raise error.Abort(
2432 raise error.Abort(
2433 _('cannot follow nonexistent file: "%s"') % f)
2433 _('cannot follow nonexistent file: "%s"') % f)
2434 slowpath = True
2434 slowpath = True
2435
2435
2436 # We decided to fall back to the slowpath because at least one
2436 # We decided to fall back to the slowpath because at least one
2437 # of the paths was not a file. Check to see if at least one of them
2437 # of the paths was not a file. Check to see if at least one of them
2438 # existed in history - in that case, we'll continue down the
2438 # existed in history - in that case, we'll continue down the
2439 # slowpath; otherwise, we can turn off the slowpath
2439 # slowpath; otherwise, we can turn off the slowpath
2440 if slowpath:
2440 if slowpath:
2441 for path in match.files():
2441 for path in match.files():
2442 if path == '.' or path in repo.store:
2442 if path == '.' or path in repo.store:
2443 break
2443 break
2444 else:
2444 else:
2445 slowpath = False
2445 slowpath = False
2446
2446
2447 fpats = ('_patsfollow', '_patsfollowfirst')
2447 fpats = ('_patsfollow', '_patsfollowfirst')
2448 fnopats = (('_ancestors', '_fancestors'),
2448 fnopats = (('_ancestors', '_fancestors'),
2449 ('_descendants', '_fdescendants'))
2449 ('_descendants', '_fdescendants'))
2450 if slowpath:
2450 if slowpath:
2451 # See walkchangerevs() slow path.
2451 # See walkchangerevs() slow path.
2452 #
2452 #
2453 # pats/include/exclude cannot be represented as separate
2453 # pats/include/exclude cannot be represented as separate
2454 # revset expressions as their filtering logic applies at file
2454 # revset expressions as their filtering logic applies at file
2455 # level. For instance "-I a -X a" matches a revision touching
2455 # level. For instance "-I a -X a" matches a revision touching
2456 # "a" and "b" while "file(a) and not file(b)" does
2456 # "a" and "b" while "file(a) and not file(b)" does
2457 # not. Besides, filesets are evaluated against the working
2457 # not. Besides, filesets are evaluated against the working
2458 # directory.
2458 # directory.
2459 matchargs = ['r:', 'd:relpath']
2459 matchargs = ['r:', 'd:relpath']
2460 for p in pats:
2460 for p in pats:
2461 matchargs.append('p:' + p)
2461 matchargs.append('p:' + p)
2462 for p in opts.get('include', []):
2462 for p in opts.get('include', []):
2463 matchargs.append('i:' + p)
2463 matchargs.append('i:' + p)
2464 for p in opts.get('exclude', []):
2464 for p in opts.get('exclude', []):
2465 matchargs.append('x:' + p)
2465 matchargs.append('x:' + p)
2466 matchargs = ','.join(('%r' % p) for p in matchargs)
2466 matchargs = ','.join(('%r' % p) for p in matchargs)
2467 opts['_matchfiles'] = matchargs
2467 opts['_matchfiles'] = matchargs
2468 if follow:
2468 if follow:
2469 opts[fnopats[0][followfirst]] = '.'
2469 opts[fnopats[0][followfirst]] = '.'
2470 else:
2470 else:
2471 if follow:
2471 if follow:
2472 if pats:
2472 if pats:
2473 # follow() revset interprets its file argument as a
2473 # follow() revset interprets its file argument as a
2474 # manifest entry, so use match.files(), not pats.
2474 # manifest entry, so use match.files(), not pats.
2475 opts[fpats[followfirst]] = list(match.files())
2475 opts[fpats[followfirst]] = list(match.files())
2476 else:
2476 else:
2477 op = fnopats[followdescendants][followfirst]
2477 op = fnopats[followdescendants][followfirst]
2478 opts[op] = 'rev(%d)' % startrev
2478 opts[op] = 'rev(%d)' % startrev
2479 else:
2479 else:
2480 opts['_patslog'] = list(pats)
2480 opts['_patslog'] = list(pats)
2481
2481
2482 filematcher = None
2482 filematcher = None
2483 if opts.get('patch') or opts.get('stat'):
2483 if opts.get('patch') or opts.get('stat'):
2484 # When following files, track renames via a special matcher.
2484 # When following files, track renames via a special matcher.
2485 # If we're forced to take the slowpath it means we're following
2485 # If we're forced to take the slowpath it means we're following
2486 # at least one pattern/directory, so don't bother with rename tracking.
2486 # at least one pattern/directory, so don't bother with rename tracking.
2487 if follow and not match.always() and not slowpath:
2487 if follow and not match.always() and not slowpath:
2488 # _makefollowlogfilematcher expects its files argument to be
2488 # _makefollowlogfilematcher expects its files argument to be
2489 # relative to the repo root, so use match.files(), not pats.
2489 # relative to the repo root, so use match.files(), not pats.
2490 filematcher = _makefollowlogfilematcher(repo, match.files(),
2490 filematcher = _makefollowlogfilematcher(repo, match.files(),
2491 followfirst)
2491 followfirst)
2492 else:
2492 else:
2493 filematcher = _makenofollowlogfilematcher(repo, pats, opts)
2493 filematcher = _makenofollowlogfilematcher(repo, pats, opts)
2494 if filematcher is None:
2494 if filematcher is None:
2495 filematcher = lambda rev: match
2495 filematcher = lambda rev: match
2496
2496
2497 expr = []
2497 expr = []
2498 for op, val in sorted(opts.iteritems()):
2498 for op, val in sorted(opts.iteritems()):
2499 if not val:
2499 if not val:
2500 continue
2500 continue
2501 if op not in opt2revset:
2501 if op not in opt2revset:
2502 continue
2502 continue
2503 revop, andor = opt2revset[op]
2503 revop, andor = opt2revset[op]
2504 if '%(val)' not in revop:
2504 if '%(val)' not in revop:
2505 expr.append(revop)
2505 expr.append(revop)
2506 else:
2506 else:
2507 if not isinstance(val, list):
2507 if not isinstance(val, list):
2508 e = revop % {'val': val}
2508 e = revop % {'val': val}
2509 else:
2509 else:
2510 e = '(' + andor.join((revop % {'val': v}) for v in val) + ')'
2510 e = '(' + andor.join((revop % {'val': v}) for v in val) + ')'
2511 expr.append(e)
2511 expr.append(e)
2512
2512
2513 if expr:
2513 if expr:
2514 expr = '(' + ' and '.join(expr) + ')'
2514 expr = '(' + ' and '.join(expr) + ')'
2515 else:
2515 else:
2516 expr = None
2516 expr = None
2517 return expr, filematcher
2517 return expr, filematcher
2518
2518
2519 def _logrevs(repo, opts):
2519 def _logrevs(repo, opts):
2520 # Default --rev value depends on --follow but --follow behavior
2520 # Default --rev value depends on --follow but --follow behavior
2521 # depends on revisions resolved from --rev...
2521 # depends on revisions resolved from --rev...
2522 follow = opts.get('follow') or opts.get('follow_first')
2522 follow = opts.get('follow') or opts.get('follow_first')
2523 if opts.get('rev'):
2523 if opts.get('rev'):
2524 revs = scmutil.revrange(repo, opts['rev'])
2524 revs = scmutil.revrange(repo, opts['rev'])
2525 elif follow and repo.dirstate.p1() == nullid:
2525 elif follow and repo.dirstate.p1() == nullid:
2526 revs = smartset.baseset()
2526 revs = smartset.baseset()
2527 elif follow:
2527 elif follow:
2528 revs = repo.revs('reverse(:.)')
2528 revs = repo.revs('reverse(:.)')
2529 else:
2529 else:
2530 revs = smartset.spanset(repo)
2530 revs = smartset.spanset(repo)
2531 revs.reverse()
2531 revs.reverse()
2532 return revs
2532 return revs
2533
2533
2534 def getgraphlogrevs(repo, pats, opts):
2534 def getgraphlogrevs(repo, pats, opts):
2535 """Return (revs, expr, filematcher) where revs is an iterable of
2535 """Return (revs, expr, filematcher) where revs is an iterable of
2536 revision numbers, expr is a revset string built from log options
2536 revision numbers, expr is a revset string built from log options
2537 and file patterns or None, and used to filter 'revs'. If --stat or
2537 and file patterns or None, and used to filter 'revs'. If --stat or
2538 --patch are not passed filematcher is None. Otherwise it is a
2538 --patch are not passed filematcher is None. Otherwise it is a
2539 callable taking a revision number and returning a match objects
2539 callable taking a revision number and returning a match objects
2540 filtering the files to be detailed when displaying the revision.
2540 filtering the files to be detailed when displaying the revision.
2541 """
2541 """
2542 limit = loglimit(opts)
2542 limit = loglimit(opts)
2543 revs = _logrevs(repo, opts)
2543 revs = _logrevs(repo, opts)
2544 if not revs:
2544 if not revs:
2545 return smartset.baseset(), None, None
2545 return smartset.baseset(), None, None
2546 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
2546 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
2547 if opts.get('rev'):
2547 if opts.get('rev'):
2548 # User-specified revs might be unsorted, but don't sort before
2548 # User-specified revs might be unsorted, but don't sort before
2549 # _makelogrevset because it might depend on the order of revs
2549 # _makelogrevset because it might depend on the order of revs
2550 if not (revs.isdescending() or revs.istopo()):
2550 if not (revs.isdescending() or revs.istopo()):
2551 revs.sort(reverse=True)
2551 revs.sort(reverse=True)
2552 if expr:
2552 if expr:
2553 matcher = revset.match(repo.ui, expr)
2553 matcher = revset.match(repo.ui, expr)
2554 revs = matcher(repo, revs)
2554 revs = matcher(repo, revs)
2555 if limit is not None:
2555 if limit is not None:
2556 limitedrevs = []
2556 limitedrevs = []
2557 for idx, rev in enumerate(revs):
2557 for idx, rev in enumerate(revs):
2558 if idx >= limit:
2558 if idx >= limit:
2559 break
2559 break
2560 limitedrevs.append(rev)
2560 limitedrevs.append(rev)
2561 revs = smartset.baseset(limitedrevs)
2561 revs = smartset.baseset(limitedrevs)
2562
2562
2563 return revs, expr, filematcher
2563 return revs, expr, filematcher
2564
2564
2565 def getlogrevs(repo, pats, opts):
2565 def getlogrevs(repo, pats, opts):
2566 """Return (revs, expr, filematcher) where revs is an iterable of
2566 """Return (revs, expr, filematcher) where revs is an iterable of
2567 revision numbers, expr is a revset string built from log options
2567 revision numbers, expr is a revset string built from log options
2568 and file patterns or None, and used to filter 'revs'. If --stat or
2568 and file patterns or None, and used to filter 'revs'. If --stat or
2569 --patch are not passed filematcher is None. Otherwise it is a
2569 --patch are not passed filematcher is None. Otherwise it is a
2570 callable taking a revision number and returning a match objects
2570 callable taking a revision number and returning a match objects
2571 filtering the files to be detailed when displaying the revision.
2571 filtering the files to be detailed when displaying the revision.
2572 """
2572 """
2573 limit = loglimit(opts)
2573 limit = loglimit(opts)
2574 revs = _logrevs(repo, opts)
2574 revs = _logrevs(repo, opts)
2575 if not revs:
2575 if not revs:
2576 return smartset.baseset([]), None, None
2576 return smartset.baseset([]), None, None
2577 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
2577 expr, filematcher = _makelogrevset(repo, pats, opts, revs)
2578 if expr:
2578 if expr:
2579 matcher = revset.match(repo.ui, expr)
2579 matcher = revset.match(repo.ui, expr)
2580 revs = matcher(repo, revs)
2580 revs = matcher(repo, revs)
2581 if limit is not None:
2581 if limit is not None:
2582 limitedrevs = []
2582 limitedrevs = []
2583 for idx, r in enumerate(revs):
2583 for idx, r in enumerate(revs):
2584 if limit <= idx:
2584 if limit <= idx:
2585 break
2585 break
2586 limitedrevs.append(r)
2586 limitedrevs.append(r)
2587 revs = smartset.baseset(limitedrevs)
2587 revs = smartset.baseset(limitedrevs)
2588
2588
2589 return revs, expr, filematcher
2589 return revs, expr, filematcher
2590
2590
2591 def _parselinerangelogopt(repo, opts):
2591 def _parselinerangelogopt(repo, opts):
2592 """Parse --line-range log option and return a list of tuples (filename,
2592 """Parse --line-range log option and return a list of tuples (filename,
2593 (fromline, toline)).
2593 (fromline, toline)).
2594 """
2594 """
2595 linerangebyfname = []
2595 linerangebyfname = []
2596 for pat in opts.get('line_range', []):
2596 for pat in opts.get('line_range', []):
2597 try:
2597 try:
2598 pat, linerange = pat.rsplit(',', 1)
2598 pat, linerange = pat.rsplit(',', 1)
2599 except ValueError:
2599 except ValueError:
2600 raise error.Abort(_('malformatted line-range pattern %s') % pat)
2600 raise error.Abort(_('malformatted line-range pattern %s') % pat)
2601 try:
2601 try:
2602 fromline, toline = map(int, linerange.split('-'))
2602 fromline, toline = map(int, linerange.split('-'))
2603 except ValueError:
2603 except ValueError:
2604 raise error.Abort(_("invalid line range for %s") % pat)
2604 raise error.Abort(_("invalid line range for %s") % pat)
2605 msg = _("line range pattern '%s' must match exactly one file") % pat
2605 msg = _("line range pattern '%s' must match exactly one file") % pat
2606 fname = scmutil.parsefollowlinespattern(repo, None, pat, msg)
2606 fname = scmutil.parsefollowlinespattern(repo, None, pat, msg)
2607 linerangebyfname.append(
2607 linerangebyfname.append(
2608 (fname, util.processlinerange(fromline, toline)))
2608 (fname, util.processlinerange(fromline, toline)))
2609 return linerangebyfname
2609 return linerangebyfname
2610
2610
2611 def getloglinerangerevs(repo, userrevs, opts):
2611 def getloglinerangerevs(repo, userrevs, opts):
2612 """Return (revs, filematcher, hunksfilter).
2612 """Return (revs, filematcher, hunksfilter).
2613
2613
2614 "revs" are revisions obtained by processing "line-range" log options and
2614 "revs" are revisions obtained by processing "line-range" log options and
2615 walking block ancestors of each specified file/line-range.
2615 walking block ancestors of each specified file/line-range.
2616
2616
2617 "filematcher(rev) -> match" is a factory function returning a match object
2617 "filematcher(rev) -> match" is a factory function returning a match object
2618 for a given revision for file patterns specified in --line-range option.
2618 for a given revision for file patterns specified in --line-range option.
2619 If neither --stat nor --patch options are passed, "filematcher" is None.
2619 If neither --stat nor --patch options are passed, "filematcher" is None.
2620
2620
2621 "hunksfilter(rev) -> filterfn(fctx, hunks)" is a factory function
2621 "hunksfilter(rev) -> filterfn(fctx, hunks)" is a factory function
2622 returning a hunks filtering function.
2622 returning a hunks filtering function.
2623 If neither --stat nor --patch options are passed, "filterhunks" is None.
2623 If neither --stat nor --patch options are passed, "filterhunks" is None.
2624 """
2624 """
2625 wctx = repo[None]
2625 wctx = repo[None]
2626
2626
2627 # Two-levels map of "rev -> file ctx -> [line range]".
2627 # Two-levels map of "rev -> file ctx -> [line range]".
2628 linerangesbyrev = {}
2628 linerangesbyrev = {}
2629 for fname, (fromline, toline) in _parselinerangelogopt(repo, opts):
2629 for fname, (fromline, toline) in _parselinerangelogopt(repo, opts):
2630 fctx = wctx.filectx(fname)
2630 fctx = wctx.filectx(fname)
2631 for fctx, linerange in dagop.blockancestors(fctx, fromline, toline):
2631 for fctx, linerange in dagop.blockancestors(fctx, fromline, toline):
2632 rev = fctx.introrev()
2632 rev = fctx.introrev()
2633 if rev not in userrevs:
2633 if rev not in userrevs:
2634 continue
2634 continue
2635 linerangesbyrev.setdefault(
2635 linerangesbyrev.setdefault(
2636 rev, {}).setdefault(
2636 rev, {}).setdefault(
2637 fctx.path(), []).append(linerange)
2637 fctx.path(), []).append(linerange)
2638
2638
2639 filematcher = None
2639 filematcher = None
2640 hunksfilter = None
2640 hunksfilter = None
2641 if opts.get('patch') or opts.get('stat'):
2641 if opts.get('patch') or opts.get('stat'):
2642
2642
2643 def nofilterhunksfn(fctx, hunks):
2643 def nofilterhunksfn(fctx, hunks):
2644 return hunks
2644 return hunks
2645
2645
2646 def hunksfilter(rev):
2646 def hunksfilter(rev):
2647 fctxlineranges = linerangesbyrev.get(rev)
2647 fctxlineranges = linerangesbyrev.get(rev)
2648 if fctxlineranges is None:
2648 if fctxlineranges is None:
2649 return nofilterhunksfn
2649 return nofilterhunksfn
2650
2650
2651 def filterfn(fctx, hunks):
2651 def filterfn(fctx, hunks):
2652 lineranges = fctxlineranges.get(fctx.path())
2652 lineranges = fctxlineranges.get(fctx.path())
2653 if lineranges is not None:
2653 if lineranges is not None:
2654 for hr, lines in hunks:
2654 for hr, lines in hunks:
2655 if any(mdiff.hunkinrange(hr[2:], lr)
2655 if any(mdiff.hunkinrange(hr[2:], lr)
2656 for lr in lineranges):
2656 for lr in lineranges):
2657 yield hr, lines
2657 yield hr, lines
2658 else:
2658 else:
2659 for hunk in hunks:
2659 for hunk in hunks:
2660 yield hunk
2660 yield hunk
2661
2661
2662 return filterfn
2662 return filterfn
2663
2663
2664 def filematcher(rev):
2664 def filematcher(rev):
2665 files = list(linerangesbyrev.get(rev, []))
2665 files = list(linerangesbyrev.get(rev, []))
2666 return scmutil.matchfiles(repo, files)
2666 return scmutil.matchfiles(repo, files)
2667
2667
2668 revs = sorted(linerangesbyrev, reverse=True)
2668 revs = sorted(linerangesbyrev, reverse=True)
2669
2669
2670 return revs, filematcher, hunksfilter
2670 return revs, filematcher, hunksfilter
2671
2671
2672 def _graphnodeformatter(ui, displayer):
2672 def _graphnodeformatter(ui, displayer):
2673 spec = ui.config('ui', 'graphnodetemplate')
2673 spec = ui.config('ui', 'graphnodetemplate')
2674 if not spec:
2674 if not spec:
2675 return templatekw.showgraphnode # fast path for "{graphnode}"
2675 return templatekw.showgraphnode # fast path for "{graphnode}"
2676
2676
2677 spec = templater.unquotestring(spec)
2677 spec = templater.unquotestring(spec)
2678 templ = formatter.maketemplater(ui, spec)
2678 templ = formatter.maketemplater(ui, spec)
2679 cache = {}
2679 cache = {}
2680 if isinstance(displayer, changeset_templater):
2680 if isinstance(displayer, changeset_templater):
2681 cache = displayer.cache # reuse cache of slow templates
2681 cache = displayer.cache # reuse cache of slow templates
2682 props = templatekw.keywords.copy()
2682 props = templatekw.keywords.copy()
2683 props['templ'] = templ
2683 props['templ'] = templ
2684 props['cache'] = cache
2684 props['cache'] = cache
2685 def formatnode(repo, ctx):
2685 def formatnode(repo, ctx):
2686 props['ctx'] = ctx
2686 props['ctx'] = ctx
2687 props['repo'] = repo
2687 props['repo'] = repo
2688 props['ui'] = repo.ui
2688 props['ui'] = repo.ui
2689 props['revcache'] = {}
2689 props['revcache'] = {}
2690 return templ.render(props)
2690 return templ.render(props)
2691 return formatnode
2691 return formatnode
2692
2692
2693 def displaygraph(ui, repo, dag, displayer, edgefn, getrenamed=None,
2693 def displaygraph(ui, repo, dag, displayer, edgefn, getrenamed=None,
2694 filematcher=None, props=None):
2694 filematcher=None, props=None):
2695 props = props or {}
2695 props = props or {}
2696 formatnode = _graphnodeformatter(ui, displayer)
2696 formatnode = _graphnodeformatter(ui, displayer)
2697 state = graphmod.asciistate()
2697 state = graphmod.asciistate()
2698 styles = state['styles']
2698 styles = state['styles']
2699
2699
2700 # only set graph styling if HGPLAIN is not set.
2700 # only set graph styling if HGPLAIN is not set.
2701 if ui.plain('graph'):
2701 if ui.plain('graph'):
2702 # set all edge styles to |, the default pre-3.8 behaviour
2702 # set all edge styles to |, the default pre-3.8 behaviour
2703 styles.update(dict.fromkeys(styles, '|'))
2703 styles.update(dict.fromkeys(styles, '|'))
2704 else:
2704 else:
2705 edgetypes = {
2705 edgetypes = {
2706 'parent': graphmod.PARENT,
2706 'parent': graphmod.PARENT,
2707 'grandparent': graphmod.GRANDPARENT,
2707 'grandparent': graphmod.GRANDPARENT,
2708 'missing': graphmod.MISSINGPARENT
2708 'missing': graphmod.MISSINGPARENT
2709 }
2709 }
2710 for name, key in edgetypes.items():
2710 for name, key in edgetypes.items():
2711 # experimental config: experimental.graphstyle.*
2711 # experimental config: experimental.graphstyle.*
2712 styles[key] = ui.config('experimental', 'graphstyle.%s' % name,
2712 styles[key] = ui.config('experimental', 'graphstyle.%s' % name,
2713 styles[key])
2713 styles[key])
2714 if not styles[key]:
2714 if not styles[key]:
2715 styles[key] = None
2715 styles[key] = None
2716
2716
2717 # experimental config: experimental.graphshorten
2717 # experimental config: experimental.graphshorten
2718 state['graphshorten'] = ui.configbool('experimental', 'graphshorten')
2718 state['graphshorten'] = ui.configbool('experimental', 'graphshorten')
2719
2719
2720 for rev, type, ctx, parents in dag:
2720 for rev, type, ctx, parents in dag:
2721 char = formatnode(repo, ctx)
2721 char = formatnode(repo, ctx)
2722 copies = None
2722 copies = None
2723 if getrenamed and ctx.rev():
2723 if getrenamed and ctx.rev():
2724 copies = []
2724 copies = []
2725 for fn in ctx.files():
2725 for fn in ctx.files():
2726 rename = getrenamed(fn, ctx.rev())
2726 rename = getrenamed(fn, ctx.rev())
2727 if rename:
2727 if rename:
2728 copies.append((fn, rename[0]))
2728 copies.append((fn, rename[0]))
2729 revmatchfn = None
2729 revmatchfn = None
2730 if filematcher is not None:
2730 if filematcher is not None:
2731 revmatchfn = filematcher(ctx.rev())
2731 revmatchfn = filematcher(ctx.rev())
2732 edges = edgefn(type, char, state, rev, parents)
2732 edges = edgefn(type, char, state, rev, parents)
2733 firstedge = next(edges)
2733 firstedge = next(edges)
2734 width = firstedge[2]
2734 width = firstedge[2]
2735 displayer.show(ctx, copies=copies, matchfn=revmatchfn,
2735 displayer.show(ctx, copies=copies, matchfn=revmatchfn,
2736 _graphwidth=width, **props)
2736 _graphwidth=width, **props)
2737 lines = displayer.hunk.pop(rev).split('\n')
2737 lines = displayer.hunk.pop(rev).split('\n')
2738 if not lines[-1]:
2738 if not lines[-1]:
2739 del lines[-1]
2739 del lines[-1]
2740 displayer.flush(ctx)
2740 displayer.flush(ctx)
2741 for type, char, width, coldata in itertools.chain([firstedge], edges):
2741 for type, char, width, coldata in itertools.chain([firstedge], edges):
2742 graphmod.ascii(ui, state, type, char, lines, coldata)
2742 graphmod.ascii(ui, state, type, char, lines, coldata)
2743 lines = []
2743 lines = []
2744 displayer.close()
2744 displayer.close()
2745
2745
2746 def graphlog(ui, repo, pats, opts):
2746 def graphlog(ui, repo, pats, opts):
2747 # Parameters are identical to log command ones
2747 # Parameters are identical to log command ones
2748 revs, expr, filematcher = getgraphlogrevs(repo, pats, opts)
2748 revs, expr, filematcher = getgraphlogrevs(repo, pats, opts)
2749 revdag = graphmod.dagwalker(repo, revs)
2749 revdag = graphmod.dagwalker(repo, revs)
2750
2750
2751 getrenamed = None
2751 getrenamed = None
2752 if opts.get('copies'):
2752 if opts.get('copies'):
2753 endrev = None
2753 endrev = None
2754 if opts.get('rev'):
2754 if opts.get('rev'):
2755 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
2755 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
2756 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2756 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2757
2757
2758 ui.pager('log')
2758 ui.pager('log')
2759 displayer = show_changeset(ui, repo, opts, buffered=True)
2759 displayer = show_changeset(ui, repo, opts, buffered=True)
2760 displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges, getrenamed,
2760 displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges, getrenamed,
2761 filematcher)
2761 filematcher)
2762
2762
2763 def checkunsupportedgraphflags(pats, opts):
2763 def checkunsupportedgraphflags(pats, opts):
2764 for op in ["newest_first"]:
2764 for op in ["newest_first"]:
2765 if op in opts and opts[op]:
2765 if op in opts and opts[op]:
2766 raise error.Abort(_("-G/--graph option is incompatible with --%s")
2766 raise error.Abort(_("-G/--graph option is incompatible with --%s")
2767 % op.replace("_", "-"))
2767 % op.replace("_", "-"))
2768
2768
2769 def graphrevs(repo, nodes, opts):
2769 def graphrevs(repo, nodes, opts):
2770 limit = loglimit(opts)
2770 limit = loglimit(opts)
2771 nodes.reverse()
2771 nodes.reverse()
2772 if limit is not None:
2772 if limit is not None:
2773 nodes = nodes[:limit]
2773 nodes = nodes[:limit]
2774 return graphmod.nodes(repo, nodes)
2774 return graphmod.nodes(repo, nodes)
2775
2775
2776 def add(ui, repo, match, prefix, explicitonly, **opts):
2776 def add(ui, repo, match, prefix, explicitonly, **opts):
2777 join = lambda f: os.path.join(prefix, f)
2777 join = lambda f: os.path.join(prefix, f)
2778 bad = []
2778 bad = []
2779
2779
2780 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
2780 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
2781 names = []
2781 names = []
2782 wctx = repo[None]
2782 wctx = repo[None]
2783 cca = None
2783 cca = None
2784 abort, warn = scmutil.checkportabilityalert(ui)
2784 abort, warn = scmutil.checkportabilityalert(ui)
2785 if abort or warn:
2785 if abort or warn:
2786 cca = scmutil.casecollisionauditor(ui, abort, repo.dirstate)
2786 cca = scmutil.casecollisionauditor(ui, abort, repo.dirstate)
2787
2787
2788 badmatch = matchmod.badmatch(match, badfn)
2788 badmatch = matchmod.badmatch(match, badfn)
2789 dirstate = repo.dirstate
2789 dirstate = repo.dirstate
2790 # We don't want to just call wctx.walk here, since it would return a lot of
2790 # We don't want to just call wctx.walk here, since it would return a lot of
2791 # clean files, which we aren't interested in and takes time.
2791 # clean files, which we aren't interested in and takes time.
2792 for f in sorted(dirstate.walk(badmatch, subrepos=sorted(wctx.substate),
2792 for f in sorted(dirstate.walk(badmatch, subrepos=sorted(wctx.substate),
2793 unknown=True, ignored=False, full=False)):
2793 unknown=True, ignored=False, full=False)):
2794 exact = match.exact(f)
2794 exact = match.exact(f)
2795 if exact or not explicitonly and f not in wctx and repo.wvfs.lexists(f):
2795 if exact or not explicitonly and f not in wctx and repo.wvfs.lexists(f):
2796 if cca:
2796 if cca:
2797 cca(f)
2797 cca(f)
2798 names.append(f)
2798 names.append(f)
2799 if ui.verbose or not exact:
2799 if ui.verbose or not exact:
2800 ui.status(_('adding %s\n') % match.rel(f))
2800 ui.status(_('adding %s\n') % match.rel(f))
2801
2801
2802 for subpath in sorted(wctx.substate):
2802 for subpath in sorted(wctx.substate):
2803 sub = wctx.sub(subpath)
2803 sub = wctx.sub(subpath)
2804 try:
2804 try:
2805 submatch = matchmod.subdirmatcher(subpath, match)
2805 submatch = matchmod.subdirmatcher(subpath, match)
2806 if opts.get(r'subrepos'):
2806 if opts.get(r'subrepos'):
2807 bad.extend(sub.add(ui, submatch, prefix, False, **opts))
2807 bad.extend(sub.add(ui, submatch, prefix, False, **opts))
2808 else:
2808 else:
2809 bad.extend(sub.add(ui, submatch, prefix, True, **opts))
2809 bad.extend(sub.add(ui, submatch, prefix, True, **opts))
2810 except error.LookupError:
2810 except error.LookupError:
2811 ui.status(_("skipping missing subrepository: %s\n")
2811 ui.status(_("skipping missing subrepository: %s\n")
2812 % join(subpath))
2812 % join(subpath))
2813
2813
2814 if not opts.get(r'dry_run'):
2814 if not opts.get(r'dry_run'):
2815 rejected = wctx.add(names, prefix)
2815 rejected = wctx.add(names, prefix)
2816 bad.extend(f for f in rejected if f in match.files())
2816 bad.extend(f for f in rejected if f in match.files())
2817 return bad
2817 return bad
2818
2818
2819 def addwebdirpath(repo, serverpath, webconf):
2819 def addwebdirpath(repo, serverpath, webconf):
2820 webconf[serverpath] = repo.root
2820 webconf[serverpath] = repo.root
2821 repo.ui.debug('adding %s = %s\n' % (serverpath, repo.root))
2821 repo.ui.debug('adding %s = %s\n' % (serverpath, repo.root))
2822
2822
2823 for r in repo.revs('filelog("path:.hgsub")'):
2823 for r in repo.revs('filelog("path:.hgsub")'):
2824 ctx = repo[r]
2824 ctx = repo[r]
2825 for subpath in ctx.substate:
2825 for subpath in ctx.substate:
2826 ctx.sub(subpath).addwebdirpath(serverpath, webconf)
2826 ctx.sub(subpath).addwebdirpath(serverpath, webconf)
2827
2827
2828 def forget(ui, repo, match, prefix, explicitonly):
2828 def forget(ui, repo, match, prefix, explicitonly):
2829 join = lambda f: os.path.join(prefix, f)
2829 join = lambda f: os.path.join(prefix, f)
2830 bad = []
2830 bad = []
2831 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
2831 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
2832 wctx = repo[None]
2832 wctx = repo[None]
2833 forgot = []
2833 forgot = []
2834
2834
2835 s = repo.status(match=matchmod.badmatch(match, badfn), clean=True)
2835 s = repo.status(match=matchmod.badmatch(match, badfn), clean=True)
2836 forget = sorted(s.modified + s.added + s.deleted + s.clean)
2836 forget = sorted(s.modified + s.added + s.deleted + s.clean)
2837 if explicitonly:
2837 if explicitonly:
2838 forget = [f for f in forget if match.exact(f)]
2838 forget = [f for f in forget if match.exact(f)]
2839
2839
2840 for subpath in sorted(wctx.substate):
2840 for subpath in sorted(wctx.substate):
2841 sub = wctx.sub(subpath)
2841 sub = wctx.sub(subpath)
2842 try:
2842 try:
2843 submatch = matchmod.subdirmatcher(subpath, match)
2843 submatch = matchmod.subdirmatcher(subpath, match)
2844 subbad, subforgot = sub.forget(submatch, prefix)
2844 subbad, subforgot = sub.forget(submatch, prefix)
2845 bad.extend([subpath + '/' + f for f in subbad])
2845 bad.extend([subpath + '/' + f for f in subbad])
2846 forgot.extend([subpath + '/' + f for f in subforgot])
2846 forgot.extend([subpath + '/' + f for f in subforgot])
2847 except error.LookupError:
2847 except error.LookupError:
2848 ui.status(_("skipping missing subrepository: %s\n")
2848 ui.status(_("skipping missing subrepository: %s\n")
2849 % join(subpath))
2849 % join(subpath))
2850
2850
2851 if not explicitonly:
2851 if not explicitonly:
2852 for f in match.files():
2852 for f in match.files():
2853 if f not in repo.dirstate and not repo.wvfs.isdir(f):
2853 if f not in repo.dirstate and not repo.wvfs.isdir(f):
2854 if f not in forgot:
2854 if f not in forgot:
2855 if repo.wvfs.exists(f):
2855 if repo.wvfs.exists(f):
2856 # Don't complain if the exact case match wasn't given.
2856 # Don't complain if the exact case match wasn't given.
2857 # But don't do this until after checking 'forgot', so
2857 # But don't do this until after checking 'forgot', so
2858 # that subrepo files aren't normalized, and this op is
2858 # that subrepo files aren't normalized, and this op is
2859 # purely from data cached by the status walk above.
2859 # purely from data cached by the status walk above.
2860 if repo.dirstate.normalize(f) in repo.dirstate:
2860 if repo.dirstate.normalize(f) in repo.dirstate:
2861 continue
2861 continue
2862 ui.warn(_('not removing %s: '
2862 ui.warn(_('not removing %s: '
2863 'file is already untracked\n')
2863 'file is already untracked\n')
2864 % match.rel(f))
2864 % match.rel(f))
2865 bad.append(f)
2865 bad.append(f)
2866
2866
2867 for f in forget:
2867 for f in forget:
2868 if ui.verbose or not match.exact(f):
2868 if ui.verbose or not match.exact(f):
2869 ui.status(_('removing %s\n') % match.rel(f))
2869 ui.status(_('removing %s\n') % match.rel(f))
2870
2870
2871 rejected = wctx.forget(forget, prefix)
2871 rejected = wctx.forget(forget, prefix)
2872 bad.extend(f for f in rejected if f in match.files())
2872 bad.extend(f for f in rejected if f in match.files())
2873 forgot.extend(f for f in forget if f not in rejected)
2873 forgot.extend(f for f in forget if f not in rejected)
2874 return bad, forgot
2874 return bad, forgot
2875
2875
2876 def files(ui, ctx, m, fm, fmt, subrepos):
2876 def files(ui, ctx, m, fm, fmt, subrepos):
2877 rev = ctx.rev()
2877 rev = ctx.rev()
2878 ret = 1
2878 ret = 1
2879 ds = ctx.repo().dirstate
2879 ds = ctx.repo().dirstate
2880
2880
2881 for f in ctx.matches(m):
2881 for f in ctx.matches(m):
2882 if rev is None and ds[f] == 'r':
2882 if rev is None and ds[f] == 'r':
2883 continue
2883 continue
2884 fm.startitem()
2884 fm.startitem()
2885 if ui.verbose:
2885 if ui.verbose:
2886 fc = ctx[f]
2886 fc = ctx[f]
2887 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
2887 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
2888 fm.data(abspath=f)
2888 fm.data(abspath=f)
2889 fm.write('path', fmt, m.rel(f))
2889 fm.write('path', fmt, m.rel(f))
2890 ret = 0
2890 ret = 0
2891
2891
2892 for subpath in sorted(ctx.substate):
2892 for subpath in sorted(ctx.substate):
2893 submatch = matchmod.subdirmatcher(subpath, m)
2893 submatch = matchmod.subdirmatcher(subpath, m)
2894 if (subrepos or m.exact(subpath) or any(submatch.files())):
2894 if (subrepos or m.exact(subpath) or any(submatch.files())):
2895 sub = ctx.sub(subpath)
2895 sub = ctx.sub(subpath)
2896 try:
2896 try:
2897 recurse = m.exact(subpath) or subrepos
2897 recurse = m.exact(subpath) or subrepos
2898 if sub.printfiles(ui, submatch, fm, fmt, recurse) == 0:
2898 if sub.printfiles(ui, submatch, fm, fmt, recurse) == 0:
2899 ret = 0
2899 ret = 0
2900 except error.LookupError:
2900 except error.LookupError:
2901 ui.status(_("skipping missing subrepository: %s\n")
2901 ui.status(_("skipping missing subrepository: %s\n")
2902 % m.abs(subpath))
2902 % m.abs(subpath))
2903
2903
2904 return ret
2904 return ret
2905
2905
2906 def remove(ui, repo, m, prefix, after, force, subrepos, warnings=None):
2906 def remove(ui, repo, m, prefix, after, force, subrepos, warnings=None):
2907 join = lambda f: os.path.join(prefix, f)
2907 join = lambda f: os.path.join(prefix, f)
2908 ret = 0
2908 ret = 0
2909 s = repo.status(match=m, clean=True)
2909 s = repo.status(match=m, clean=True)
2910 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2910 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2911
2911
2912 wctx = repo[None]
2912 wctx = repo[None]
2913
2913
2914 if warnings is None:
2914 if warnings is None:
2915 warnings = []
2915 warnings = []
2916 warn = True
2916 warn = True
2917 else:
2917 else:
2918 warn = False
2918 warn = False
2919
2919
2920 subs = sorted(wctx.substate)
2920 subs = sorted(wctx.substate)
2921 total = len(subs)
2921 total = len(subs)
2922 count = 0
2922 count = 0
2923 for subpath in subs:
2923 for subpath in subs:
2924 count += 1
2924 count += 1
2925 submatch = matchmod.subdirmatcher(subpath, m)
2925 submatch = matchmod.subdirmatcher(subpath, m)
2926 if subrepos or m.exact(subpath) or any(submatch.files()):
2926 if subrepos or m.exact(subpath) or any(submatch.files()):
2927 ui.progress(_('searching'), count, total=total, unit=_('subrepos'))
2927 ui.progress(_('searching'), count, total=total, unit=_('subrepos'))
2928 sub = wctx.sub(subpath)
2928 sub = wctx.sub(subpath)
2929 try:
2929 try:
2930 if sub.removefiles(submatch, prefix, after, force, subrepos,
2930 if sub.removefiles(submatch, prefix, after, force, subrepos,
2931 warnings):
2931 warnings):
2932 ret = 1
2932 ret = 1
2933 except error.LookupError:
2933 except error.LookupError:
2934 warnings.append(_("skipping missing subrepository: %s\n")
2934 warnings.append(_("skipping missing subrepository: %s\n")
2935 % join(subpath))
2935 % join(subpath))
2936 ui.progress(_('searching'), None)
2936 ui.progress(_('searching'), None)
2937
2937
2938 # warn about failure to delete explicit files/dirs
2938 # warn about failure to delete explicit files/dirs
2939 deleteddirs = util.dirs(deleted)
2939 deleteddirs = util.dirs(deleted)
2940 files = m.files()
2940 files = m.files()
2941 total = len(files)
2941 total = len(files)
2942 count = 0
2942 count = 0
2943 for f in files:
2943 for f in files:
2944 def insubrepo():
2944 def insubrepo():
2945 for subpath in wctx.substate:
2945 for subpath in wctx.substate:
2946 if f.startswith(subpath + '/'):
2946 if f.startswith(subpath + '/'):
2947 return True
2947 return True
2948 return False
2948 return False
2949
2949
2950 count += 1
2950 count += 1
2951 ui.progress(_('deleting'), count, total=total, unit=_('files'))
2951 ui.progress(_('deleting'), count, total=total, unit=_('files'))
2952 isdir = f in deleteddirs or wctx.hasdir(f)
2952 isdir = f in deleteddirs or wctx.hasdir(f)
2953 if (f in repo.dirstate or isdir or f == '.'
2953 if (f in repo.dirstate or isdir or f == '.'
2954 or insubrepo() or f in subs):
2954 or insubrepo() or f in subs):
2955 continue
2955 continue
2956
2956
2957 if repo.wvfs.exists(f):
2957 if repo.wvfs.exists(f):
2958 if repo.wvfs.isdir(f):
2958 if repo.wvfs.isdir(f):
2959 warnings.append(_('not removing %s: no tracked files\n')
2959 warnings.append(_('not removing %s: no tracked files\n')
2960 % m.rel(f))
2960 % m.rel(f))
2961 else:
2961 else:
2962 warnings.append(_('not removing %s: file is untracked\n')
2962 warnings.append(_('not removing %s: file is untracked\n')
2963 % m.rel(f))
2963 % m.rel(f))
2964 # missing files will generate a warning elsewhere
2964 # missing files will generate a warning elsewhere
2965 ret = 1
2965 ret = 1
2966 ui.progress(_('deleting'), None)
2966 ui.progress(_('deleting'), None)
2967
2967
2968 if force:
2968 if force:
2969 list = modified + deleted + clean + added
2969 list = modified + deleted + clean + added
2970 elif after:
2970 elif after:
2971 list = deleted
2971 list = deleted
2972 remaining = modified + added + clean
2972 remaining = modified + added + clean
2973 total = len(remaining)
2973 total = len(remaining)
2974 count = 0
2974 count = 0
2975 for f in remaining:
2975 for f in remaining:
2976 count += 1
2976 count += 1
2977 ui.progress(_('skipping'), count, total=total, unit=_('files'))
2977 ui.progress(_('skipping'), count, total=total, unit=_('files'))
2978 warnings.append(_('not removing %s: file still exists\n')
2978 warnings.append(_('not removing %s: file still exists\n')
2979 % m.rel(f))
2979 % m.rel(f))
2980 ret = 1
2980 ret = 1
2981 ui.progress(_('skipping'), None)
2981 ui.progress(_('skipping'), None)
2982 else:
2982 else:
2983 list = deleted + clean
2983 list = deleted + clean
2984 total = len(modified) + len(added)
2984 total = len(modified) + len(added)
2985 count = 0
2985 count = 0
2986 for f in modified:
2986 for f in modified:
2987 count += 1
2987 count += 1
2988 ui.progress(_('skipping'), count, total=total, unit=_('files'))
2988 ui.progress(_('skipping'), count, total=total, unit=_('files'))
2989 warnings.append(_('not removing %s: file is modified (use -f'
2989 warnings.append(_('not removing %s: file is modified (use -f'
2990 ' to force removal)\n') % m.rel(f))
2990 ' to force removal)\n') % m.rel(f))
2991 ret = 1
2991 ret = 1
2992 for f in added:
2992 for f in added:
2993 count += 1
2993 count += 1
2994 ui.progress(_('skipping'), count, total=total, unit=_('files'))
2994 ui.progress(_('skipping'), count, total=total, unit=_('files'))
2995 warnings.append(_("not removing %s: file has been marked for add"
2995 warnings.append(_("not removing %s: file has been marked for add"
2996 " (use 'hg forget' to undo add)\n") % m.rel(f))
2996 " (use 'hg forget' to undo add)\n") % m.rel(f))
2997 ret = 1
2997 ret = 1
2998 ui.progress(_('skipping'), None)
2998 ui.progress(_('skipping'), None)
2999
2999
3000 list = sorted(list)
3000 list = sorted(list)
3001 total = len(list)
3001 total = len(list)
3002 count = 0
3002 count = 0
3003 for f in list:
3003 for f in list:
3004 count += 1
3004 count += 1
3005 if ui.verbose or not m.exact(f):
3005 if ui.verbose or not m.exact(f):
3006 ui.progress(_('deleting'), count, total=total, unit=_('files'))
3006 ui.progress(_('deleting'), count, total=total, unit=_('files'))
3007 ui.status(_('removing %s\n') % m.rel(f))
3007 ui.status(_('removing %s\n') % m.rel(f))
3008 ui.progress(_('deleting'), None)
3008 ui.progress(_('deleting'), None)
3009
3009
3010 with repo.wlock():
3010 with repo.wlock():
3011 if not after:
3011 if not after:
3012 for f in list:
3012 for f in list:
3013 if f in added:
3013 if f in added:
3014 continue # we never unlink added files on remove
3014 continue # we never unlink added files on remove
3015 repo.wvfs.unlinkpath(f, ignoremissing=True)
3015 repo.wvfs.unlinkpath(f, ignoremissing=True)
3016 repo[None].forget(list)
3016 repo[None].forget(list)
3017
3017
3018 if warn:
3018 if warn:
3019 for warning in warnings:
3019 for warning in warnings:
3020 ui.warn(warning)
3020 ui.warn(warning)
3021
3021
3022 return ret
3022 return ret
3023
3023
3024 def cat(ui, repo, ctx, matcher, basefm, fntemplate, prefix, **opts):
3024 def cat(ui, repo, ctx, matcher, basefm, fntemplate, prefix, **opts):
3025 err = 1
3025 err = 1
3026
3026
3027 def write(path):
3027 def write(path):
3028 filename = None
3028 filename = None
3029 if fntemplate:
3029 if fntemplate:
3030 filename = makefilename(repo, fntemplate, ctx.node(),
3030 filename = makefilename(repo, fntemplate, ctx.node(),
3031 pathname=os.path.join(prefix, path))
3031 pathname=os.path.join(prefix, path))
3032 with formatter.maybereopen(basefm, filename, opts) as fm:
3032 with formatter.maybereopen(basefm, filename, opts) as fm:
3033 data = ctx[path].data()
3033 data = ctx[path].data()
3034 if opts.get('decode'):
3034 if opts.get('decode'):
3035 data = repo.wwritedata(path, data)
3035 data = repo.wwritedata(path, data)
3036 fm.startitem()
3036 fm.startitem()
3037 fm.write('data', '%s', data)
3037 fm.write('data', '%s', data)
3038 fm.data(abspath=path, path=matcher.rel(path))
3038 fm.data(abspath=path, path=matcher.rel(path))
3039
3039
3040 # Automation often uses hg cat on single files, so special case it
3040 # Automation often uses hg cat on single files, so special case it
3041 # for performance to avoid the cost of parsing the manifest.
3041 # for performance to avoid the cost of parsing the manifest.
3042 if len(matcher.files()) == 1 and not matcher.anypats():
3042 if len(matcher.files()) == 1 and not matcher.anypats():
3043 file = matcher.files()[0]
3043 file = matcher.files()[0]
3044 mfl = repo.manifestlog
3044 mfl = repo.manifestlog
3045 mfnode = ctx.manifestnode()
3045 mfnode = ctx.manifestnode()
3046 try:
3046 try:
3047 if mfnode and mfl[mfnode].find(file)[0]:
3047 if mfnode and mfl[mfnode].find(file)[0]:
3048 write(file)
3048 write(file)
3049 return 0
3049 return 0
3050 except KeyError:
3050 except KeyError:
3051 pass
3051 pass
3052
3052
3053 for abs in ctx.walk(matcher):
3053 for abs in ctx.walk(matcher):
3054 write(abs)
3054 write(abs)
3055 err = 0
3055 err = 0
3056
3056
3057 for subpath in sorted(ctx.substate):
3057 for subpath in sorted(ctx.substate):
3058 sub = ctx.sub(subpath)
3058 sub = ctx.sub(subpath)
3059 try:
3059 try:
3060 submatch = matchmod.subdirmatcher(subpath, matcher)
3060 submatch = matchmod.subdirmatcher(subpath, matcher)
3061
3061
3062 if not sub.cat(submatch, basefm, fntemplate,
3062 if not sub.cat(submatch, basefm, fntemplate,
3063 os.path.join(prefix, sub._path), **opts):
3063 os.path.join(prefix, sub._path), **opts):
3064 err = 0
3064 err = 0
3065 except error.RepoLookupError:
3065 except error.RepoLookupError:
3066 ui.status(_("skipping missing subrepository: %s\n")
3066 ui.status(_("skipping missing subrepository: %s\n")
3067 % os.path.join(prefix, subpath))
3067 % os.path.join(prefix, subpath))
3068
3068
3069 return err
3069 return err
3070
3070
3071 def commit(ui, repo, commitfunc, pats, opts):
3071 def commit(ui, repo, commitfunc, pats, opts):
3072 '''commit the specified files or all outstanding changes'''
3072 '''commit the specified files or all outstanding changes'''
3073 date = opts.get('date')
3073 date = opts.get('date')
3074 if date:
3074 if date:
3075 opts['date'] = util.parsedate(date)
3075 opts['date'] = util.parsedate(date)
3076 message = logmessage(ui, opts)
3076 message = logmessage(ui, opts)
3077 matcher = scmutil.match(repo[None], pats, opts)
3077 matcher = scmutil.match(repo[None], pats, opts)
3078
3078
3079 dsguard = None
3079 dsguard = None
3080 # extract addremove carefully -- this function can be called from a command
3080 # extract addremove carefully -- this function can be called from a command
3081 # that doesn't support addremove
3081 # that doesn't support addremove
3082 if opts.get('addremove'):
3082 if opts.get('addremove'):
3083 dsguard = dirstateguard.dirstateguard(repo, 'commit')
3083 dsguard = dirstateguard.dirstateguard(repo, 'commit')
3084 with dsguard or util.nullcontextmanager():
3084 with dsguard or util.nullcontextmanager():
3085 if dsguard:
3085 if dsguard:
3086 if scmutil.addremove(repo, matcher, "", opts) != 0:
3086 if scmutil.addremove(repo, matcher, "", opts) != 0:
3087 raise error.Abort(
3087 raise error.Abort(
3088 _("failed to mark all new/missing files as added/removed"))
3088 _("failed to mark all new/missing files as added/removed"))
3089
3089
3090 return commitfunc(ui, repo, message, matcher, opts)
3090 return commitfunc(ui, repo, message, matcher, opts)
3091
3091
3092 def samefile(f, ctx1, ctx2):
3092 def samefile(f, ctx1, ctx2):
3093 if f in ctx1.manifest():
3093 if f in ctx1.manifest():
3094 a = ctx1.filectx(f)
3094 a = ctx1.filectx(f)
3095 if f in ctx2.manifest():
3095 if f in ctx2.manifest():
3096 b = ctx2.filectx(f)
3096 b = ctx2.filectx(f)
3097 return (not a.cmp(b)
3097 return (not a.cmp(b)
3098 and a.flags() == b.flags())
3098 and a.flags() == b.flags())
3099 else:
3099 else:
3100 return False
3100 return False
3101 else:
3101 else:
3102 return f not in ctx2.manifest()
3102 return f not in ctx2.manifest()
3103
3103
3104 def amend(ui, repo, old, extra, pats, opts):
3104 def amend(ui, repo, old, extra, pats, opts):
3105 # avoid cycle context -> subrepo -> cmdutil
3105 # avoid cycle context -> subrepo -> cmdutil
3106 from . import context
3106 from . import context
3107
3107
3108 # amend will reuse the existing user if not specified, but the obsolete
3108 # amend will reuse the existing user if not specified, but the obsolete
3109 # marker creation requires that the current user's name is specified.
3109 # marker creation requires that the current user's name is specified.
3110 if obsolete.isenabled(repo, obsolete.createmarkersopt):
3110 if obsolete.isenabled(repo, obsolete.createmarkersopt):
3111 ui.username() # raise exception if username not set
3111 ui.username() # raise exception if username not set
3112
3112
3113 ui.note(_('amending changeset %s\n') % old)
3113 ui.note(_('amending changeset %s\n') % old)
3114 base = old.p1()
3114 base = old.p1()
3115
3115
3116 with repo.wlock(), repo.lock(), repo.transaction('amend'):
3116 with repo.wlock(), repo.lock(), repo.transaction('amend'):
3117 # Participating changesets:
3117 # Participating changesets:
3118 #
3118 #
3119 # wctx o - workingctx that contains changes from working copy
3119 # wctx o - workingctx that contains changes from working copy
3120 # | to go into amending commit
3120 # | to go into amending commit
3121 # |
3121 # |
3122 # old o - changeset to amend
3122 # old o - changeset to amend
3123 # |
3123 # |
3124 # base o - first parent of the changeset to amend
3124 # base o - first parent of the changeset to amend
3125 wctx = repo[None]
3125 wctx = repo[None]
3126
3126
3127 # Update extra dict from amended commit (e.g. to preserve graft
3127 # Update extra dict from amended commit (e.g. to preserve graft
3128 # source)
3128 # source)
3129 extra.update(old.extra())
3129 extra.update(old.extra())
3130
3130
3131 # Also update it from the from the wctx
3131 # Also update it from the from the wctx
3132 extra.update(wctx.extra())
3132 extra.update(wctx.extra())
3133
3133
3134 user = opts.get('user') or old.user()
3134 user = opts.get('user') or old.user()
3135 date = opts.get('date') or old.date()
3135 date = opts.get('date') or old.date()
3136
3136
3137 # Parse the date to allow comparison between date and old.date()
3137 # Parse the date to allow comparison between date and old.date()
3138 date = util.parsedate(date)
3138 date = util.parsedate(date)
3139
3139
3140 if len(old.parents()) > 1:
3140 if len(old.parents()) > 1:
3141 # ctx.files() isn't reliable for merges, so fall back to the
3141 # ctx.files() isn't reliable for merges, so fall back to the
3142 # slower repo.status() method
3142 # slower repo.status() method
3143 files = set([fn for st in repo.status(base, old)[:3]
3143 files = set([fn for st in repo.status(base, old)[:3]
3144 for fn in st])
3144 for fn in st])
3145 else:
3145 else:
3146 files = set(old.files())
3146 files = set(old.files())
3147
3147
3148 # add/remove the files to the working copy if the "addremove" option
3148 # add/remove the files to the working copy if the "addremove" option
3149 # was specified.
3149 # was specified.
3150 matcher = scmutil.match(wctx, pats, opts)
3150 matcher = scmutil.match(wctx, pats, opts)
3151 if (opts.get('addremove')
3151 if (opts.get('addremove')
3152 and scmutil.addremove(repo, matcher, "", opts)):
3152 and scmutil.addremove(repo, matcher, "", opts)):
3153 raise error.Abort(
3153 raise error.Abort(
3154 _("failed to mark all new/missing files as added/removed"))
3154 _("failed to mark all new/missing files as added/removed"))
3155
3155
3156 filestoamend = set(f for f in wctx.files() if matcher(f))
3156 filestoamend = set(f for f in wctx.files() if matcher(f))
3157
3157
3158 changes = (len(filestoamend) > 0)
3158 changes = (len(filestoamend) > 0)
3159 if changes:
3159 if changes:
3160 # Recompute copies (avoid recording a -> b -> a)
3160 # Recompute copies (avoid recording a -> b -> a)
3161 copied = copies.pathcopies(base, wctx, matcher)
3161 copied = copies.pathcopies(base, wctx, matcher)
3162 if old.p2:
3162 if old.p2:
3163 copied.update(copies.pathcopies(old.p2(), wctx, matcher))
3163 copied.update(copies.pathcopies(old.p2(), wctx, matcher))
3164
3164
3165 # Prune files which were reverted by the updates: if old
3165 # Prune files which were reverted by the updates: if old
3166 # introduced file X and the file was renamed in the working
3166 # introduced file X and the file was renamed in the working
3167 # copy, then those two files are the same and
3167 # copy, then those two files are the same and
3168 # we can discard X from our list of files. Likewise if X
3168 # we can discard X from our list of files. Likewise if X
3169 # was deleted, it's no longer relevant
3169 # was deleted, it's no longer relevant
3170 files.update(filestoamend)
3170 files.update(filestoamend)
3171 files = [f for f in files if not samefile(f, wctx, base)]
3171 files = [f for f in files if not samefile(f, wctx, base)]
3172
3172
3173 def filectxfn(repo, ctx_, path):
3173 def filectxfn(repo, ctx_, path):
3174 try:
3174 try:
3175 # If the file being considered is not amongst the files
3175 # If the file being considered is not amongst the files
3176 # to be amended, we should return the file context from the
3176 # to be amended, we should return the file context from the
3177 # old changeset. This avoids issues when only some files in
3177 # old changeset. This avoids issues when only some files in
3178 # the working copy are being amended but there are also
3178 # the working copy are being amended but there are also
3179 # changes to other files from the old changeset.
3179 # changes to other files from the old changeset.
3180 if path not in filestoamend:
3180 if path not in filestoamend:
3181 return old.filectx(path)
3181 return old.filectx(path)
3182
3182
3183 fctx = wctx[path]
3183 fctx = wctx[path]
3184
3184
3185 # Return None for removed files.
3185 # Return None for removed files.
3186 if not fctx.exists():
3186 if not fctx.exists():
3187 return None
3187 return None
3188
3188
3189 flags = fctx.flags()
3189 flags = fctx.flags()
3190 mctx = context.memfilectx(repo,
3190 mctx = context.memfilectx(repo,
3191 fctx.path(), fctx.data(),
3191 fctx.path(), fctx.data(),
3192 islink='l' in flags,
3192 islink='l' in flags,
3193 isexec='x' in flags,
3193 isexec='x' in flags,
3194 copied=copied.get(path))
3194 copied=copied.get(path))
3195 return mctx
3195 return mctx
3196 except KeyError:
3196 except KeyError:
3197 return None
3197 return None
3198 else:
3198 else:
3199 ui.note(_('copying changeset %s to %s\n') % (old, base))
3199 ui.note(_('copying changeset %s to %s\n') % (old, base))
3200
3200
3201 # Use version of files as in the old cset
3201 # Use version of files as in the old cset
3202 def filectxfn(repo, ctx_, path):
3202 def filectxfn(repo, ctx_, path):
3203 try:
3203 try:
3204 return old.filectx(path)
3204 return old.filectx(path)
3205 except KeyError:
3205 except KeyError:
3206 return None
3206 return None
3207
3207
3208 # See if we got a message from -m or -l, if not, open the editor with
3208 # See if we got a message from -m or -l, if not, open the editor with
3209 # the message of the changeset to amend.
3209 # the message of the changeset to amend.
3210 message = logmessage(ui, opts)
3210 message = logmessage(ui, opts)
3211
3211
3212 editform = mergeeditform(old, 'commit.amend')
3212 editform = mergeeditform(old, 'commit.amend')
3213 editor = getcommiteditor(editform=editform,
3213 editor = getcommiteditor(editform=editform,
3214 **pycompat.strkwargs(opts))
3214 **pycompat.strkwargs(opts))
3215
3215
3216 if not message:
3216 if not message:
3217 editor = getcommiteditor(edit=True, editform=editform)
3217 editor = getcommiteditor(edit=True, editform=editform)
3218 message = old.description()
3218 message = old.description()
3219
3219
3220 pureextra = extra.copy()
3220 pureextra = extra.copy()
3221 extra['amend_source'] = old.hex()
3221 extra['amend_source'] = old.hex()
3222
3222
3223 new = context.memctx(repo,
3223 new = context.memctx(repo,
3224 parents=[base.node(), old.p2().node()],
3224 parents=[base.node(), old.p2().node()],
3225 text=message,
3225 text=message,
3226 files=files,
3226 files=files,
3227 filectxfn=filectxfn,
3227 filectxfn=filectxfn,
3228 user=user,
3228 user=user,
3229 date=date,
3229 date=date,
3230 extra=extra,
3230 extra=extra,
3231 editor=editor)
3231 editor=editor)
3232
3232
3233 newdesc = changelog.stripdesc(new.description())
3233 newdesc = changelog.stripdesc(new.description())
3234 if ((not changes)
3234 if ((not changes)
3235 and newdesc == old.description()
3235 and newdesc == old.description()
3236 and user == old.user()
3236 and user == old.user()
3237 and date == old.date()
3237 and date == old.date()
3238 and pureextra == old.extra()):
3238 and pureextra == old.extra()):
3239 # nothing changed. continuing here would create a new node
3239 # nothing changed. continuing here would create a new node
3240 # anyway because of the amend_source noise.
3240 # anyway because of the amend_source noise.
3241 #
3241 #
3242 # This not what we expect from amend.
3242 # This not what we expect from amend.
3243 return old.node()
3243 return old.node()
3244
3244
3245 if opts.get('secret'):
3245 if opts.get('secret'):
3246 commitphase = 'secret'
3246 commitphase = 'secret'
3247 else:
3247 else:
3248 commitphase = old.phase()
3248 commitphase = old.phase()
3249 overrides = {('phases', 'new-commit'): commitphase}
3249 overrides = {('phases', 'new-commit'): commitphase}
3250 with ui.configoverride(overrides, 'amend'):
3250 with ui.configoverride(overrides, 'amend'):
3251 newid = repo.commitctx(new)
3251 newid = repo.commitctx(new)
3252
3252
3253 # Reroute the working copy parent to the new changeset
3253 # Reroute the working copy parent to the new changeset
3254 repo.setparents(newid, nullid)
3254 repo.setparents(newid, nullid)
3255 mapping = {old.node(): (newid,)}
3255 mapping = {old.node(): (newid,)}
3256 obsmetadata = None
3256 obsmetadata = None
3257 if opts.get('note'):
3257 if opts.get('note'):
3258 obsmetadata = {'note': opts['note']}
3258 obsmetadata = {'note': opts['note']}
3259 scmutil.cleanupnodes(repo, mapping, 'amend', metadata=obsmetadata)
3259 scmutil.cleanupnodes(repo, mapping, 'amend', metadata=obsmetadata)
3260
3260
3261 # Fixing the dirstate because localrepo.commitctx does not update
3261 # Fixing the dirstate because localrepo.commitctx does not update
3262 # it. This is rather convenient because we did not need to update
3262 # it. This is rather convenient because we did not need to update
3263 # the dirstate for all the files in the new commit which commitctx
3263 # the dirstate for all the files in the new commit which commitctx
3264 # could have done if it updated the dirstate. Now, we can
3264 # could have done if it updated the dirstate. Now, we can
3265 # selectively update the dirstate only for the amended files.
3265 # selectively update the dirstate only for the amended files.
3266 dirstate = repo.dirstate
3266 dirstate = repo.dirstate
3267
3267
3268 # Update the state of the files which were added and
3268 # Update the state of the files which were added and
3269 # and modified in the amend to "normal" in the dirstate.
3269 # and modified in the amend to "normal" in the dirstate.
3270 normalfiles = set(wctx.modified() + wctx.added()) & filestoamend
3270 normalfiles = set(wctx.modified() + wctx.added()) & filestoamend
3271 for f in normalfiles:
3271 for f in normalfiles:
3272 dirstate.normal(f)
3272 dirstate.normal(f)
3273
3273
3274 # Update the state of files which were removed in the amend
3274 # Update the state of files which were removed in the amend
3275 # to "removed" in the dirstate.
3275 # to "removed" in the dirstate.
3276 removedfiles = set(wctx.removed()) & filestoamend
3276 removedfiles = set(wctx.removed()) & filestoamend
3277 for f in removedfiles:
3277 for f in removedfiles:
3278 dirstate.drop(f)
3278 dirstate.drop(f)
3279
3279
3280 return newid
3280 return newid
3281
3281
3282 def commiteditor(repo, ctx, subs, editform=''):
3282 def commiteditor(repo, ctx, subs, editform=''):
3283 if ctx.description():
3283 if ctx.description():
3284 return ctx.description()
3284 return ctx.description()
3285 return commitforceeditor(repo, ctx, subs, editform=editform,
3285 return commitforceeditor(repo, ctx, subs, editform=editform,
3286 unchangedmessagedetection=True)
3286 unchangedmessagedetection=True)
3287
3287
3288 def commitforceeditor(repo, ctx, subs, finishdesc=None, extramsg=None,
3288 def commitforceeditor(repo, ctx, subs, finishdesc=None, extramsg=None,
3289 editform='', unchangedmessagedetection=False):
3289 editform='', unchangedmessagedetection=False):
3290 if not extramsg:
3290 if not extramsg:
3291 extramsg = _("Leave message empty to abort commit.")
3291 extramsg = _("Leave message empty to abort commit.")
3292
3292
3293 forms = [e for e in editform.split('.') if e]
3293 forms = [e for e in editform.split('.') if e]
3294 forms.insert(0, 'changeset')
3294 forms.insert(0, 'changeset')
3295 templatetext = None
3295 templatetext = None
3296 while forms:
3296 while forms:
3297 ref = '.'.join(forms)
3297 ref = '.'.join(forms)
3298 if repo.ui.config('committemplate', ref):
3298 if repo.ui.config('committemplate', ref):
3299 templatetext = committext = buildcommittemplate(
3299 templatetext = committext = buildcommittemplate(
3300 repo, ctx, subs, extramsg, ref)
3300 repo, ctx, subs, extramsg, ref)
3301 break
3301 break
3302 forms.pop()
3302 forms.pop()
3303 else:
3303 else:
3304 committext = buildcommittext(repo, ctx, subs, extramsg)
3304 committext = buildcommittext(repo, ctx, subs, extramsg)
3305
3305
3306 # run editor in the repository root
3306 # run editor in the repository root
3307 olddir = pycompat.getcwd()
3307 olddir = pycompat.getcwd()
3308 os.chdir(repo.root)
3308 os.chdir(repo.root)
3309
3309
3310 # make in-memory changes visible to external process
3310 # make in-memory changes visible to external process
3311 tr = repo.currenttransaction()
3311 tr = repo.currenttransaction()
3312 repo.dirstate.write(tr)
3312 repo.dirstate.write(tr)
3313 pending = tr and tr.writepending() and repo.root
3313 pending = tr and tr.writepending() and repo.root
3314
3314
3315 editortext = repo.ui.edit(committext, ctx.user(), ctx.extra(),
3315 editortext = repo.ui.edit(committext, ctx.user(), ctx.extra(),
3316 editform=editform, pending=pending,
3316 editform=editform, pending=pending,
3317 repopath=repo.path, action='commit')
3317 repopath=repo.path, action='commit')
3318 text = editortext
3318 text = editortext
3319
3319
3320 # strip away anything below this special string (used for editors that want
3320 # strip away anything below this special string (used for editors that want
3321 # to display the diff)
3321 # to display the diff)
3322 stripbelow = re.search(_linebelow, text, flags=re.MULTILINE)
3322 stripbelow = re.search(_linebelow, text, flags=re.MULTILINE)
3323 if stripbelow:
3323 if stripbelow:
3324 text = text[:stripbelow.start()]
3324 text = text[:stripbelow.start()]
3325
3325
3326 text = re.sub("(?m)^HG:.*(\n|$)", "", text)
3326 text = re.sub("(?m)^HG:.*(\n|$)", "", text)
3327 os.chdir(olddir)
3327 os.chdir(olddir)
3328
3328
3329 if finishdesc:
3329 if finishdesc:
3330 text = finishdesc(text)
3330 text = finishdesc(text)
3331 if not text.strip():
3331 if not text.strip():
3332 raise error.Abort(_("empty commit message"))
3332 raise error.Abort(_("empty commit message"))
3333 if unchangedmessagedetection and editortext == templatetext:
3333 if unchangedmessagedetection and editortext == templatetext:
3334 raise error.Abort(_("commit message unchanged"))
3334 raise error.Abort(_("commit message unchanged"))
3335
3335
3336 return text
3336 return text
3337
3337
3338 def buildcommittemplate(repo, ctx, subs, extramsg, ref):
3338 def buildcommittemplate(repo, ctx, subs, extramsg, ref):
3339 ui = repo.ui
3339 ui = repo.ui
3340 spec = formatter.templatespec(ref, None, None)
3340 spec = formatter.templatespec(ref, None, None)
3341 t = changeset_templater(ui, repo, spec, None, {}, False)
3341 t = changeset_templater(ui, repo, spec, None, {}, False)
3342 t.t.cache.update((k, templater.unquotestring(v))
3342 t.t.cache.update((k, templater.unquotestring(v))
3343 for k, v in repo.ui.configitems('committemplate'))
3343 for k, v in repo.ui.configitems('committemplate'))
3344
3344
3345 if not extramsg:
3345 if not extramsg:
3346 extramsg = '' # ensure that extramsg is string
3346 extramsg = '' # ensure that extramsg is string
3347
3347
3348 ui.pushbuffer()
3348 ui.pushbuffer()
3349 t.show(ctx, extramsg=extramsg)
3349 t.show(ctx, extramsg=extramsg)
3350 return ui.popbuffer()
3350 return ui.popbuffer()
3351
3351
3352 def hgprefix(msg):
3352 def hgprefix(msg):
3353 return "\n".join(["HG: %s" % a for a in msg.split("\n") if a])
3353 return "\n".join(["HG: %s" % a for a in msg.split("\n") if a])
3354
3354
3355 def buildcommittext(repo, ctx, subs, extramsg):
3355 def buildcommittext(repo, ctx, subs, extramsg):
3356 edittext = []
3356 edittext = []
3357 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
3357 modified, added, removed = ctx.modified(), ctx.added(), ctx.removed()
3358 if ctx.description():
3358 if ctx.description():
3359 edittext.append(ctx.description())
3359 edittext.append(ctx.description())
3360 edittext.append("")
3360 edittext.append("")
3361 edittext.append("") # Empty line between message and comments.
3361 edittext.append("") # Empty line between message and comments.
3362 edittext.append(hgprefix(_("Enter commit message."
3362 edittext.append(hgprefix(_("Enter commit message."
3363 " Lines beginning with 'HG:' are removed.")))
3363 " Lines beginning with 'HG:' are removed.")))
3364 edittext.append(hgprefix(extramsg))
3364 edittext.append(hgprefix(extramsg))
3365 edittext.append("HG: --")
3365 edittext.append("HG: --")
3366 edittext.append(hgprefix(_("user: %s") % ctx.user()))
3366 edittext.append(hgprefix(_("user: %s") % ctx.user()))
3367 if ctx.p2():
3367 if ctx.p2():
3368 edittext.append(hgprefix(_("branch merge")))
3368 edittext.append(hgprefix(_("branch merge")))
3369 if ctx.branch():
3369 if ctx.branch():
3370 edittext.append(hgprefix(_("branch '%s'") % ctx.branch()))
3370 edittext.append(hgprefix(_("branch '%s'") % ctx.branch()))
3371 if bookmarks.isactivewdirparent(repo):
3371 if bookmarks.isactivewdirparent(repo):
3372 edittext.append(hgprefix(_("bookmark '%s'") % repo._activebookmark))
3372 edittext.append(hgprefix(_("bookmark '%s'") % repo._activebookmark))
3373 edittext.extend([hgprefix(_("subrepo %s") % s) for s in subs])
3373 edittext.extend([hgprefix(_("subrepo %s") % s) for s in subs])
3374 edittext.extend([hgprefix(_("added %s") % f) for f in added])
3374 edittext.extend([hgprefix(_("added %s") % f) for f in added])
3375 edittext.extend([hgprefix(_("changed %s") % f) for f in modified])
3375 edittext.extend([hgprefix(_("changed %s") % f) for f in modified])
3376 edittext.extend([hgprefix(_("removed %s") % f) for f in removed])
3376 edittext.extend([hgprefix(_("removed %s") % f) for f in removed])
3377 if not added and not modified and not removed:
3377 if not added and not modified and not removed:
3378 edittext.append(hgprefix(_("no files changed")))
3378 edittext.append(hgprefix(_("no files changed")))
3379 edittext.append("")
3379 edittext.append("")
3380
3380
3381 return "\n".join(edittext)
3381 return "\n".join(edittext)
3382
3382
3383 def commitstatus(repo, node, branch, bheads=None, opts=None):
3383 def commitstatus(repo, node, branch, bheads=None, opts=None):
3384 if opts is None:
3384 if opts is None:
3385 opts = {}
3385 opts = {}
3386 ctx = repo[node]
3386 ctx = repo[node]
3387 parents = ctx.parents()
3387 parents = ctx.parents()
3388
3388
3389 if (not opts.get('amend') and bheads and node not in bheads and not
3389 if (not opts.get('amend') and bheads and node not in bheads and not
3390 [x for x in parents if x.node() in bheads and x.branch() == branch]):
3390 [x for x in parents if x.node() in bheads and x.branch() == branch]):
3391 repo.ui.status(_('created new head\n'))
3391 repo.ui.status(_('created new head\n'))
3392 # The message is not printed for initial roots. For the other
3392 # The message is not printed for initial roots. For the other
3393 # changesets, it is printed in the following situations:
3393 # changesets, it is printed in the following situations:
3394 #
3394 #
3395 # Par column: for the 2 parents with ...
3395 # Par column: for the 2 parents with ...
3396 # N: null or no parent
3396 # N: null or no parent
3397 # B: parent is on another named branch
3397 # B: parent is on another named branch
3398 # C: parent is a regular non head changeset
3398 # C: parent is a regular non head changeset
3399 # H: parent was a branch head of the current branch
3399 # H: parent was a branch head of the current branch
3400 # Msg column: whether we print "created new head" message
3400 # Msg column: whether we print "created new head" message
3401 # In the following, it is assumed that there already exists some
3401 # In the following, it is assumed that there already exists some
3402 # initial branch heads of the current branch, otherwise nothing is
3402 # initial branch heads of the current branch, otherwise nothing is
3403 # printed anyway.
3403 # printed anyway.
3404 #
3404 #
3405 # Par Msg Comment
3405 # Par Msg Comment
3406 # N N y additional topo root
3406 # N N y additional topo root
3407 #
3407 #
3408 # B N y additional branch root
3408 # B N y additional branch root
3409 # C N y additional topo head
3409 # C N y additional topo head
3410 # H N n usual case
3410 # H N n usual case
3411 #
3411 #
3412 # B B y weird additional branch root
3412 # B B y weird additional branch root
3413 # C B y branch merge
3413 # C B y branch merge
3414 # H B n merge with named branch
3414 # H B n merge with named branch
3415 #
3415 #
3416 # C C y additional head from merge
3416 # C C y additional head from merge
3417 # C H n merge with a head
3417 # C H n merge with a head
3418 #
3418 #
3419 # H H n head merge: head count decreases
3419 # H H n head merge: head count decreases
3420
3420
3421 if not opts.get('close_branch'):
3421 if not opts.get('close_branch'):
3422 for r in parents:
3422 for r in parents:
3423 if r.closesbranch() and r.branch() == branch:
3423 if r.closesbranch() and r.branch() == branch:
3424 repo.ui.status(_('reopening closed branch head %d\n') % r)
3424 repo.ui.status(_('reopening closed branch head %d\n') % r)
3425
3425
3426 if repo.ui.debugflag:
3426 if repo.ui.debugflag:
3427 repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
3427 repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
3428 elif repo.ui.verbose:
3428 elif repo.ui.verbose:
3429 repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
3429 repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
3430
3430
3431 def postcommitstatus(repo, pats, opts):
3431 def postcommitstatus(repo, pats, opts):
3432 return repo.status(match=scmutil.match(repo[None], pats, opts))
3432 return repo.status(match=scmutil.match(repo[None], pats, opts))
3433
3433
3434 def revert(ui, repo, ctx, parents, *pats, **opts):
3434 def revert(ui, repo, ctx, parents, *pats, **opts):
3435 parent, p2 = parents
3435 parent, p2 = parents
3436 node = ctx.node()
3436 node = ctx.node()
3437
3437
3438 mf = ctx.manifest()
3438 mf = ctx.manifest()
3439 if node == p2:
3439 if node == p2:
3440 parent = p2
3440 parent = p2
3441
3441
3442 # need all matching names in dirstate and manifest of target rev,
3442 # need all matching names in dirstate and manifest of target rev,
3443 # so have to walk both. do not print errors if files exist in one
3443 # so have to walk both. do not print errors if files exist in one
3444 # but not other. in both cases, filesets should be evaluated against
3444 # but not other. in both cases, filesets should be evaluated against
3445 # workingctx to get consistent result (issue4497). this means 'set:**'
3445 # workingctx to get consistent result (issue4497). this means 'set:**'
3446 # cannot be used to select missing files from target rev.
3446 # cannot be used to select missing files from target rev.
3447
3447
3448 # `names` is a mapping for all elements in working copy and target revision
3448 # `names` is a mapping for all elements in working copy and target revision
3449 # The mapping is in the form:
3449 # The mapping is in the form:
3450 # <asb path in repo> -> (<path from CWD>, <exactly specified by matcher?>)
3450 # <asb path in repo> -> (<path from CWD>, <exactly specified by matcher?>)
3451 names = {}
3451 names = {}
3452
3452
3453 with repo.wlock():
3453 with repo.wlock():
3454 ## filling of the `names` mapping
3454 ## filling of the `names` mapping
3455 # walk dirstate to fill `names`
3455 # walk dirstate to fill `names`
3456
3456
3457 interactive = opts.get('interactive', False)
3457 interactive = opts.get('interactive', False)
3458 wctx = repo[None]
3458 wctx = repo[None]
3459 m = scmutil.match(wctx, pats, opts)
3459 m = scmutil.match(wctx, pats, opts)
3460
3460
3461 # we'll need this later
3461 # we'll need this later
3462 targetsubs = sorted(s for s in wctx.substate if m(s))
3462 targetsubs = sorted(s for s in wctx.substate if m(s))
3463
3463
3464 if not m.always():
3464 if not m.always():
3465 matcher = matchmod.badmatch(m, lambda x, y: False)
3465 matcher = matchmod.badmatch(m, lambda x, y: False)
3466 for abs in wctx.walk(matcher):
3466 for abs in wctx.walk(matcher):
3467 names[abs] = m.rel(abs), m.exact(abs)
3467 names[abs] = m.rel(abs), m.exact(abs)
3468
3468
3469 # walk target manifest to fill `names`
3469 # walk target manifest to fill `names`
3470
3470
3471 def badfn(path, msg):
3471 def badfn(path, msg):
3472 if path in names:
3472 if path in names:
3473 return
3473 return
3474 if path in ctx.substate:
3474 if path in ctx.substate:
3475 return
3475 return
3476 path_ = path + '/'
3476 path_ = path + '/'
3477 for f in names:
3477 for f in names:
3478 if f.startswith(path_):
3478 if f.startswith(path_):
3479 return
3479 return
3480 ui.warn("%s: %s\n" % (m.rel(path), msg))
3480 ui.warn("%s: %s\n" % (m.rel(path), msg))
3481
3481
3482 for abs in ctx.walk(matchmod.badmatch(m, badfn)):
3482 for abs in ctx.walk(matchmod.badmatch(m, badfn)):
3483 if abs not in names:
3483 if abs not in names:
3484 names[abs] = m.rel(abs), m.exact(abs)
3484 names[abs] = m.rel(abs), m.exact(abs)
3485
3485
3486 # Find status of all file in `names`.
3486 # Find status of all file in `names`.
3487 m = scmutil.matchfiles(repo, names)
3487 m = scmutil.matchfiles(repo, names)
3488
3488
3489 changes = repo.status(node1=node, match=m,
3489 changes = repo.status(node1=node, match=m,
3490 unknown=True, ignored=True, clean=True)
3490 unknown=True, ignored=True, clean=True)
3491 else:
3491 else:
3492 changes = repo.status(node1=node, match=m)
3492 changes = repo.status(node1=node, match=m)
3493 for kind in changes:
3493 for kind in changes:
3494 for abs in kind:
3494 for abs in kind:
3495 names[abs] = m.rel(abs), m.exact(abs)
3495 names[abs] = m.rel(abs), m.exact(abs)
3496
3496
3497 m = scmutil.matchfiles(repo, names)
3497 m = scmutil.matchfiles(repo, names)
3498
3498
3499 modified = set(changes.modified)
3499 modified = set(changes.modified)
3500 added = set(changes.added)
3500 added = set(changes.added)
3501 removed = set(changes.removed)
3501 removed = set(changes.removed)
3502 _deleted = set(changes.deleted)
3502 _deleted = set(changes.deleted)
3503 unknown = set(changes.unknown)
3503 unknown = set(changes.unknown)
3504 unknown.update(changes.ignored)
3504 unknown.update(changes.ignored)
3505 clean = set(changes.clean)
3505 clean = set(changes.clean)
3506 modadded = set()
3506 modadded = set()
3507
3507
3508 # We need to account for the state of the file in the dirstate,
3508 # We need to account for the state of the file in the dirstate,
3509 # even when we revert against something else than parent. This will
3509 # even when we revert against something else than parent. This will
3510 # slightly alter the behavior of revert (doing back up or not, delete
3510 # slightly alter the behavior of revert (doing back up or not, delete
3511 # or just forget etc).
3511 # or just forget etc).
3512 if parent == node:
3512 if parent == node:
3513 dsmodified = modified
3513 dsmodified = modified
3514 dsadded = added
3514 dsadded = added
3515 dsremoved = removed
3515 dsremoved = removed
3516 # store all local modifications, useful later for rename detection
3516 # store all local modifications, useful later for rename detection
3517 localchanges = dsmodified | dsadded
3517 localchanges = dsmodified | dsadded
3518 modified, added, removed = set(), set(), set()
3518 modified, added, removed = set(), set(), set()
3519 else:
3519 else:
3520 changes = repo.status(node1=parent, match=m)
3520 changes = repo.status(node1=parent, match=m)
3521 dsmodified = set(changes.modified)
3521 dsmodified = set(changes.modified)
3522 dsadded = set(changes.added)
3522 dsadded = set(changes.added)
3523 dsremoved = set(changes.removed)
3523 dsremoved = set(changes.removed)
3524 # store all local modifications, useful later for rename detection
3524 # store all local modifications, useful later for rename detection
3525 localchanges = dsmodified | dsadded
3525 localchanges = dsmodified | dsadded
3526
3526
3527 # only take into account for removes between wc and target
3527 # only take into account for removes between wc and target
3528 clean |= dsremoved - removed
3528 clean |= dsremoved - removed
3529 dsremoved &= removed
3529 dsremoved &= removed
3530 # distinct between dirstate remove and other
3530 # distinct between dirstate remove and other
3531 removed -= dsremoved
3531 removed -= dsremoved
3532
3532
3533 modadded = added & dsmodified
3533 modadded = added & dsmodified
3534 added -= modadded
3534 added -= modadded
3535
3535
3536 # tell newly modified apart.
3536 # tell newly modified apart.
3537 dsmodified &= modified
3537 dsmodified &= modified
3538 dsmodified |= modified & dsadded # dirstate added may need backup
3538 dsmodified |= modified & dsadded # dirstate added may need backup
3539 modified -= dsmodified
3539 modified -= dsmodified
3540
3540
3541 # We need to wait for some post-processing to update this set
3541 # We need to wait for some post-processing to update this set
3542 # before making the distinction. The dirstate will be used for
3542 # before making the distinction. The dirstate will be used for
3543 # that purpose.
3543 # that purpose.
3544 dsadded = added
3544 dsadded = added
3545
3545
3546 # in case of merge, files that are actually added can be reported as
3546 # in case of merge, files that are actually added can be reported as
3547 # modified, we need to post process the result
3547 # modified, we need to post process the result
3548 if p2 != nullid:
3548 if p2 != nullid:
3549 mergeadd = set(dsmodified)
3549 mergeadd = set(dsmodified)
3550 for path in dsmodified:
3550 for path in dsmodified:
3551 if path in mf:
3551 if path in mf:
3552 mergeadd.remove(path)
3552 mergeadd.remove(path)
3553 dsadded |= mergeadd
3553 dsadded |= mergeadd
3554 dsmodified -= mergeadd
3554 dsmodified -= mergeadd
3555
3555
3556 # if f is a rename, update `names` to also revert the source
3556 # if f is a rename, update `names` to also revert the source
3557 cwd = repo.getcwd()
3557 cwd = repo.getcwd()
3558 for f in localchanges:
3558 for f in localchanges:
3559 src = repo.dirstate.copied(f)
3559 src = repo.dirstate.copied(f)
3560 # XXX should we check for rename down to target node?
3560 # XXX should we check for rename down to target node?
3561 if src and src not in names and repo.dirstate[src] == 'r':
3561 if src and src not in names and repo.dirstate[src] == 'r':
3562 dsremoved.add(src)
3562 dsremoved.add(src)
3563 names[src] = (repo.pathto(src, cwd), True)
3563 names[src] = (repo.pathto(src, cwd), True)
3564
3564
3565 # determine the exact nature of the deleted changesets
3565 # determine the exact nature of the deleted changesets
3566 deladded = set(_deleted)
3566 deladded = set(_deleted)
3567 for path in _deleted:
3567 for path in _deleted:
3568 if path in mf:
3568 if path in mf:
3569 deladded.remove(path)
3569 deladded.remove(path)
3570 deleted = _deleted - deladded
3570 deleted = _deleted - deladded
3571
3571
3572 # distinguish between file to forget and the other
3572 # distinguish between file to forget and the other
3573 added = set()
3573 added = set()
3574 for abs in dsadded:
3574 for abs in dsadded:
3575 if repo.dirstate[abs] != 'a':
3575 if repo.dirstate[abs] != 'a':
3576 added.add(abs)
3576 added.add(abs)
3577 dsadded -= added
3577 dsadded -= added
3578
3578
3579 for abs in deladded:
3579 for abs in deladded:
3580 if repo.dirstate[abs] == 'a':
3580 if repo.dirstate[abs] == 'a':
3581 dsadded.add(abs)
3581 dsadded.add(abs)
3582 deladded -= dsadded
3582 deladded -= dsadded
3583
3583
3584 # For files marked as removed, we check if an unknown file is present at
3584 # For files marked as removed, we check if an unknown file is present at
3585 # the same path. If a such file exists it may need to be backed up.
3585 # the same path. If a such file exists it may need to be backed up.
3586 # Making the distinction at this stage helps have simpler backup
3586 # Making the distinction at this stage helps have simpler backup
3587 # logic.
3587 # logic.
3588 removunk = set()
3588 removunk = set()
3589 for abs in removed:
3589 for abs in removed:
3590 target = repo.wjoin(abs)
3590 target = repo.wjoin(abs)
3591 if os.path.lexists(target):
3591 if os.path.lexists(target):
3592 removunk.add(abs)
3592 removunk.add(abs)
3593 removed -= removunk
3593 removed -= removunk
3594
3594
3595 dsremovunk = set()
3595 dsremovunk = set()
3596 for abs in dsremoved:
3596 for abs in dsremoved:
3597 target = repo.wjoin(abs)
3597 target = repo.wjoin(abs)
3598 if os.path.lexists(target):
3598 if os.path.lexists(target):
3599 dsremovunk.add(abs)
3599 dsremovunk.add(abs)
3600 dsremoved -= dsremovunk
3600 dsremoved -= dsremovunk
3601
3601
3602 # action to be actually performed by revert
3602 # action to be actually performed by revert
3603 # (<list of file>, message>) tuple
3603 # (<list of file>, message>) tuple
3604 actions = {'revert': ([], _('reverting %s\n')),
3604 actions = {'revert': ([], _('reverting %s\n')),
3605 'add': ([], _('adding %s\n')),
3605 'add': ([], _('adding %s\n')),
3606 'remove': ([], _('removing %s\n')),
3606 'remove': ([], _('removing %s\n')),
3607 'drop': ([], _('removing %s\n')),
3607 'drop': ([], _('removing %s\n')),
3608 'forget': ([], _('forgetting %s\n')),
3608 'forget': ([], _('forgetting %s\n')),
3609 'undelete': ([], _('undeleting %s\n')),
3609 'undelete': ([], _('undeleting %s\n')),
3610 'noop': (None, _('no changes needed to %s\n')),
3610 'noop': (None, _('no changes needed to %s\n')),
3611 'unknown': (None, _('file not managed: %s\n')),
3611 'unknown': (None, _('file not managed: %s\n')),
3612 }
3612 }
3613
3613
3614 # "constant" that convey the backup strategy.
3614 # "constant" that convey the backup strategy.
3615 # All set to `discard` if `no-backup` is set do avoid checking
3615 # All set to `discard` if `no-backup` is set do avoid checking
3616 # no_backup lower in the code.
3616 # no_backup lower in the code.
3617 # These values are ordered for comparison purposes
3617 # These values are ordered for comparison purposes
3618 backupinteractive = 3 # do backup if interactively modified
3618 backupinteractive = 3 # do backup if interactively modified
3619 backup = 2 # unconditionally do backup
3619 backup = 2 # unconditionally do backup
3620 check = 1 # check if the existing file differs from target
3620 check = 1 # check if the existing file differs from target
3621 discard = 0 # never do backup
3621 discard = 0 # never do backup
3622 if opts.get('no_backup'):
3622 if opts.get('no_backup'):
3623 backupinteractive = backup = check = discard
3623 backupinteractive = backup = check = discard
3624 if interactive:
3624 if interactive:
3625 dsmodifiedbackup = backupinteractive
3625 dsmodifiedbackup = backupinteractive
3626 else:
3626 else:
3627 dsmodifiedbackup = backup
3627 dsmodifiedbackup = backup
3628 tobackup = set()
3628 tobackup = set()
3629
3629
3630 backupanddel = actions['remove']
3630 backupanddel = actions['remove']
3631 if not opts.get('no_backup'):
3631 if not opts.get('no_backup'):
3632 backupanddel = actions['drop']
3632 backupanddel = actions['drop']
3633
3633
3634 disptable = (
3634 disptable = (
3635 # dispatch table:
3635 # dispatch table:
3636 # file state
3636 # file state
3637 # action
3637 # action
3638 # make backup
3638 # make backup
3639
3639
3640 ## Sets that results that will change file on disk
3640 ## Sets that results that will change file on disk
3641 # Modified compared to target, no local change
3641 # Modified compared to target, no local change
3642 (modified, actions['revert'], discard),
3642 (modified, actions['revert'], discard),
3643 # Modified compared to target, but local file is deleted
3643 # Modified compared to target, but local file is deleted
3644 (deleted, actions['revert'], discard),
3644 (deleted, actions['revert'], discard),
3645 # Modified compared to target, local change
3645 # Modified compared to target, local change
3646 (dsmodified, actions['revert'], dsmodifiedbackup),
3646 (dsmodified, actions['revert'], dsmodifiedbackup),
3647 # Added since target
3647 # Added since target
3648 (added, actions['remove'], discard),
3648 (added, actions['remove'], discard),
3649 # Added in working directory
3649 # Added in working directory
3650 (dsadded, actions['forget'], discard),
3650 (dsadded, actions['forget'], discard),
3651 # Added since target, have local modification
3651 # Added since target, have local modification
3652 (modadded, backupanddel, backup),
3652 (modadded, backupanddel, backup),
3653 # Added since target but file is missing in working directory
3653 # Added since target but file is missing in working directory
3654 (deladded, actions['drop'], discard),
3654 (deladded, actions['drop'], discard),
3655 # Removed since target, before working copy parent
3655 # Removed since target, before working copy parent
3656 (removed, actions['add'], discard),
3656 (removed, actions['add'], discard),
3657 # Same as `removed` but an unknown file exists at the same path
3657 # Same as `removed` but an unknown file exists at the same path
3658 (removunk, actions['add'], check),
3658 (removunk, actions['add'], check),
3659 # Removed since targe, marked as such in working copy parent
3659 # Removed since targe, marked as such in working copy parent
3660 (dsremoved, actions['undelete'], discard),
3660 (dsremoved, actions['undelete'], discard),
3661 # Same as `dsremoved` but an unknown file exists at the same path
3661 # Same as `dsremoved` but an unknown file exists at the same path
3662 (dsremovunk, actions['undelete'], check),
3662 (dsremovunk, actions['undelete'], check),
3663 ## the following sets does not result in any file changes
3663 ## the following sets does not result in any file changes
3664 # File with no modification
3664 # File with no modification
3665 (clean, actions['noop'], discard),
3665 (clean, actions['noop'], discard),
3666 # Existing file, not tracked anywhere
3666 # Existing file, not tracked anywhere
3667 (unknown, actions['unknown'], discard),
3667 (unknown, actions['unknown'], discard),
3668 )
3668 )
3669
3669
3670 for abs, (rel, exact) in sorted(names.items()):
3670 for abs, (rel, exact) in sorted(names.items()):
3671 # target file to be touch on disk (relative to cwd)
3671 # target file to be touch on disk (relative to cwd)
3672 target = repo.wjoin(abs)
3672 target = repo.wjoin(abs)
3673 # search the entry in the dispatch table.
3673 # search the entry in the dispatch table.
3674 # if the file is in any of these sets, it was touched in the working
3674 # if the file is in any of these sets, it was touched in the working
3675 # directory parent and we are sure it needs to be reverted.
3675 # directory parent and we are sure it needs to be reverted.
3676 for table, (xlist, msg), dobackup in disptable:
3676 for table, (xlist, msg), dobackup in disptable:
3677 if abs not in table:
3677 if abs not in table:
3678 continue
3678 continue
3679 if xlist is not None:
3679 if xlist is not None:
3680 xlist.append(abs)
3680 xlist.append(abs)
3681 if dobackup:
3681 if dobackup:
3682 # If in interactive mode, don't automatically create
3682 # If in interactive mode, don't automatically create
3683 # .orig files (issue4793)
3683 # .orig files (issue4793)
3684 if dobackup == backupinteractive:
3684 if dobackup == backupinteractive:
3685 tobackup.add(abs)
3685 tobackup.add(abs)
3686 elif (backup <= dobackup or wctx[abs].cmp(ctx[abs])):
3686 elif (backup <= dobackup or wctx[abs].cmp(ctx[abs])):
3687 bakname = scmutil.origpath(ui, repo, rel)
3687 bakname = scmutil.origpath(ui, repo, rel)
3688 ui.note(_('saving current version of %s as %s\n') %
3688 ui.note(_('saving current version of %s as %s\n') %
3689 (rel, bakname))
3689 (rel, bakname))
3690 if not opts.get('dry_run'):
3690 if not opts.get('dry_run'):
3691 if interactive:
3691 if interactive:
3692 util.copyfile(target, bakname)
3692 util.copyfile(target, bakname)
3693 else:
3693 else:
3694 util.rename(target, bakname)
3694 util.rename(target, bakname)
3695 if ui.verbose or not exact:
3695 if ui.verbose or not exact:
3696 if not isinstance(msg, basestring):
3696 if not isinstance(msg, basestring):
3697 msg = msg(abs)
3697 msg = msg(abs)
3698 ui.status(msg % rel)
3698 ui.status(msg % rel)
3699 elif exact:
3699 elif exact:
3700 ui.warn(msg % rel)
3700 ui.warn(msg % rel)
3701 break
3701 break
3702
3702
3703 if not opts.get('dry_run'):
3703 if not opts.get('dry_run'):
3704 needdata = ('revert', 'add', 'undelete')
3704 needdata = ('revert', 'add', 'undelete')
3705 _revertprefetch(repo, ctx, *[actions[name][0] for name in needdata])
3705 _revertprefetch(repo, ctx, *[actions[name][0] for name in needdata])
3706 _performrevert(repo, parents, ctx, actions, interactive, tobackup)
3706 _performrevert(repo, parents, ctx, actions, interactive, tobackup)
3707
3707
3708 if targetsubs:
3708 if targetsubs:
3709 # Revert the subrepos on the revert list
3709 # Revert the subrepos on the revert list
3710 for sub in targetsubs:
3710 for sub in targetsubs:
3711 try:
3711 try:
3712 wctx.sub(sub).revert(ctx.substate[sub], *pats, **opts)
3712 wctx.sub(sub).revert(ctx.substate[sub], *pats, **opts)
3713 except KeyError:
3713 except KeyError:
3714 raise error.Abort("subrepository '%s' does not exist in %s!"
3714 raise error.Abort("subrepository '%s' does not exist in %s!"
3715 % (sub, short(ctx.node())))
3715 % (sub, short(ctx.node())))
3716
3716
3717 def _revertprefetch(repo, ctx, *files):
3717 def _revertprefetch(repo, ctx, *files):
3718 """Let extension changing the storage layer prefetch content"""
3718 """Let extension changing the storage layer prefetch content"""
3719
3719
3720 def _performrevert(repo, parents, ctx, actions, interactive=False,
3720 def _performrevert(repo, parents, ctx, actions, interactive=False,
3721 tobackup=None):
3721 tobackup=None):
3722 """function that actually perform all the actions computed for revert
3722 """function that actually perform all the actions computed for revert
3723
3723
3724 This is an independent function to let extension to plug in and react to
3724 This is an independent function to let extension to plug in and react to
3725 the imminent revert.
3725 the imminent revert.
3726
3726
3727 Make sure you have the working directory locked when calling this function.
3727 Make sure you have the working directory locked when calling this function.
3728 """
3728 """
3729 parent, p2 = parents
3729 parent, p2 = parents
3730 node = ctx.node()
3730 node = ctx.node()
3731 excluded_files = []
3731 excluded_files = []
3732 matcher_opts = {"exclude": excluded_files}
3732 matcher_opts = {"exclude": excluded_files}
3733
3733
3734 def checkout(f):
3734 def checkout(f):
3735 fc = ctx[f]
3735 fc = ctx[f]
3736 repo.wwrite(f, fc.data(), fc.flags())
3736 repo.wwrite(f, fc.data(), fc.flags())
3737
3737
3738 def doremove(f):
3738 def doremove(f):
3739 try:
3739 try:
3740 repo.wvfs.unlinkpath(f)
3740 repo.wvfs.unlinkpath(f)
3741 except OSError:
3741 except OSError:
3742 pass
3742 pass
3743 repo.dirstate.remove(f)
3743 repo.dirstate.remove(f)
3744
3744
3745 audit_path = pathutil.pathauditor(repo.root, cached=True)
3745 audit_path = pathutil.pathauditor(repo.root, cached=True)
3746 for f in actions['forget'][0]:
3746 for f in actions['forget'][0]:
3747 if interactive:
3747 if interactive:
3748 choice = repo.ui.promptchoice(
3748 choice = repo.ui.promptchoice(
3749 _("forget added file %s (Yn)?$$ &Yes $$ &No") % f)
3749 _("forget added file %s (Yn)?$$ &Yes $$ &No") % f)
3750 if choice == 0:
3750 if choice == 0:
3751 repo.dirstate.drop(f)
3751 repo.dirstate.drop(f)
3752 else:
3752 else:
3753 excluded_files.append(repo.wjoin(f))
3753 excluded_files.append(repo.wjoin(f))
3754 else:
3754 else:
3755 repo.dirstate.drop(f)
3755 repo.dirstate.drop(f)
3756 for f in actions['remove'][0]:
3756 for f in actions['remove'][0]:
3757 audit_path(f)
3757 audit_path(f)
3758 if interactive:
3758 if interactive:
3759 choice = repo.ui.promptchoice(
3759 choice = repo.ui.promptchoice(
3760 _("remove added file %s (Yn)?$$ &Yes $$ &No") % f)
3760 _("remove added file %s (Yn)?$$ &Yes $$ &No") % f)
3761 if choice == 0:
3761 if choice == 0:
3762 doremove(f)
3762 doremove(f)
3763 else:
3763 else:
3764 excluded_files.append(repo.wjoin(f))
3764 excluded_files.append(repo.wjoin(f))
3765 else:
3765 else:
3766 doremove(f)
3766 doremove(f)
3767 for f in actions['drop'][0]:
3767 for f in actions['drop'][0]:
3768 audit_path(f)
3768 audit_path(f)
3769 repo.dirstate.remove(f)
3769 repo.dirstate.remove(f)
3770
3770
3771 normal = None
3771 normal = None
3772 if node == parent:
3772 if node == parent:
3773 # We're reverting to our parent. If possible, we'd like status
3773 # We're reverting to our parent. If possible, we'd like status
3774 # to report the file as clean. We have to use normallookup for
3774 # to report the file as clean. We have to use normallookup for
3775 # merges to avoid losing information about merged/dirty files.
3775 # merges to avoid losing information about merged/dirty files.
3776 if p2 != nullid:
3776 if p2 != nullid:
3777 normal = repo.dirstate.normallookup
3777 normal = repo.dirstate.normallookup
3778 else:
3778 else:
3779 normal = repo.dirstate.normal
3779 normal = repo.dirstate.normal
3780
3780
3781 newlyaddedandmodifiedfiles = set()
3781 newlyaddedandmodifiedfiles = set()
3782 if interactive:
3782 if interactive:
3783 # Prompt the user for changes to revert
3783 # Prompt the user for changes to revert
3784 torevert = [repo.wjoin(f) for f in actions['revert'][0]]
3784 torevert = [repo.wjoin(f) for f in actions['revert'][0]]
3785 m = scmutil.match(ctx, torevert, matcher_opts)
3785 m = scmutil.match(ctx, torevert, matcher_opts)
3786 diffopts = patch.difffeatureopts(repo.ui, whitespace=True)
3786 diffopts = patch.difffeatureopts(repo.ui, whitespace=True)
3787 diffopts.nodates = True
3787 diffopts.nodates = True
3788 diffopts.git = True
3788 diffopts.git = True
3789 operation = 'discard'
3789 operation = 'discard'
3790 reversehunks = True
3790 reversehunks = True
3791 if node != parent:
3791 if node != parent:
3792 operation = 'revert'
3792 operation = 'revert'
3793 reversehunks = repo.ui.configbool('experimental',
3793 reversehunks = repo.ui.configbool('experimental',
3794 'revertalternateinteractivemode')
3794 'revertalternateinteractivemode')
3795 if reversehunks:
3795 if reversehunks:
3796 diff = patch.diff(repo, ctx.node(), None, m, opts=diffopts)
3796 diff = patch.diff(repo, ctx.node(), None, m, opts=diffopts)
3797 else:
3797 else:
3798 diff = patch.diff(repo, None, ctx.node(), m, opts=diffopts)
3798 diff = patch.diff(repo, None, ctx.node(), m, opts=diffopts)
3799 originalchunks = patch.parsepatch(diff)
3799 originalchunks = patch.parsepatch(diff)
3800
3800
3801 try:
3801 try:
3802
3802
3803 chunks, opts = recordfilter(repo.ui, originalchunks,
3803 chunks, opts = recordfilter(repo.ui, originalchunks,
3804 operation=operation)
3804 operation=operation)
3805 if reversehunks:
3805 if reversehunks:
3806 chunks = patch.reversehunks(chunks)
3806 chunks = patch.reversehunks(chunks)
3807
3807
3808 except error.PatchError as err:
3808 except error.PatchError as err:
3809 raise error.Abort(_('error parsing patch: %s') % err)
3809 raise error.Abort(_('error parsing patch: %s') % err)
3810
3810
3811 newlyaddedandmodifiedfiles = newandmodified(chunks, originalchunks)
3811 newlyaddedandmodifiedfiles = newandmodified(chunks, originalchunks)
3812 if tobackup is None:
3812 if tobackup is None:
3813 tobackup = set()
3813 tobackup = set()
3814 # Apply changes
3814 # Apply changes
3815 fp = stringio()
3815 fp = stringio()
3816 for c in chunks:
3816 for c in chunks:
3817 # Create a backup file only if this hunk should be backed up
3817 # Create a backup file only if this hunk should be backed up
3818 if ishunk(c) and c.header.filename() in tobackup:
3818 if ishunk(c) and c.header.filename() in tobackup:
3819 abs = c.header.filename()
3819 abs = c.header.filename()
3820 target = repo.wjoin(abs)
3820 target = repo.wjoin(abs)
3821 bakname = scmutil.origpath(repo.ui, repo, m.rel(abs))
3821 bakname = scmutil.origpath(repo.ui, repo, m.rel(abs))
3822 util.copyfile(target, bakname)
3822 util.copyfile(target, bakname)
3823 tobackup.remove(abs)
3823 tobackup.remove(abs)
3824 c.write(fp)
3824 c.write(fp)
3825 dopatch = fp.tell()
3825 dopatch = fp.tell()
3826 fp.seek(0)
3826 fp.seek(0)
3827 if dopatch:
3827 if dopatch:
3828 try:
3828 try:
3829 patch.internalpatch(repo.ui, repo, fp, 1, eolmode=None)
3829 patch.internalpatch(repo.ui, repo, fp, 1, eolmode=None)
3830 except error.PatchError as err:
3830 except error.PatchError as err:
3831 raise error.Abort(str(err))
3831 raise error.Abort(str(err))
3832 del fp
3832 del fp
3833 else:
3833 else:
3834 for f in actions['revert'][0]:
3834 for f in actions['revert'][0]:
3835 checkout(f)
3835 checkout(f)
3836 if normal:
3836 if normal:
3837 normal(f)
3837 normal(f)
3838
3838
3839 for f in actions['add'][0]:
3839 for f in actions['add'][0]:
3840 # Don't checkout modified files, they are already created by the diff
3840 # Don't checkout modified files, they are already created by the diff
3841 if f not in newlyaddedandmodifiedfiles:
3841 if f not in newlyaddedandmodifiedfiles:
3842 checkout(f)
3842 checkout(f)
3843 repo.dirstate.add(f)
3843 repo.dirstate.add(f)
3844
3844
3845 normal = repo.dirstate.normallookup
3845 normal = repo.dirstate.normallookup
3846 if node == parent and p2 == nullid:
3846 if node == parent and p2 == nullid:
3847 normal = repo.dirstate.normal
3847 normal = repo.dirstate.normal
3848 for f in actions['undelete'][0]:
3848 for f in actions['undelete'][0]:
3849 checkout(f)
3849 checkout(f)
3850 normal(f)
3850 normal(f)
3851
3851
3852 copied = copies.pathcopies(repo[parent], ctx)
3852 copied = copies.pathcopies(repo[parent], ctx)
3853
3853
3854 for f in actions['add'][0] + actions['undelete'][0] + actions['revert'][0]:
3854 for f in actions['add'][0] + actions['undelete'][0] + actions['revert'][0]:
3855 if f in copied:
3855 if f in copied:
3856 repo.dirstate.copy(copied[f], f)
3856 repo.dirstate.copy(copied[f], f)
3857
3857
3858 class command(registrar.command):
3858 class command(registrar.command):
3859 def _doregister(self, func, name, *args, **kwargs):
3859 def _doregister(self, func, name, *args, **kwargs):
3860 func._deprecatedregistrar = True # flag for deprecwarn in extensions.py
3860 func._deprecatedregistrar = True # flag for deprecwarn in extensions.py
3861 return super(command, self)._doregister(func, name, *args, **kwargs)
3861 return super(command, self)._doregister(func, name, *args, **kwargs)
3862
3862
3863 # a list of (ui, repo, otherpeer, opts, missing) functions called by
3863 # a list of (ui, repo, otherpeer, opts, missing) functions called by
3864 # commands.outgoing. "missing" is "missing" of the result of
3864 # commands.outgoing. "missing" is "missing" of the result of
3865 # "findcommonoutgoing()"
3865 # "findcommonoutgoing()"
3866 outgoinghooks = util.hooks()
3866 outgoinghooks = util.hooks()
3867
3867
3868 # a list of (ui, repo) functions called by commands.summary
3868 # a list of (ui, repo) functions called by commands.summary
3869 summaryhooks = util.hooks()
3869 summaryhooks = util.hooks()
3870
3870
3871 # a list of (ui, repo, opts, changes) functions called by commands.summary.
3871 # a list of (ui, repo, opts, changes) functions called by commands.summary.
3872 #
3872 #
3873 # functions should return tuple of booleans below, if 'changes' is None:
3873 # functions should return tuple of booleans below, if 'changes' is None:
3874 # (whether-incomings-are-needed, whether-outgoings-are-needed)
3874 # (whether-incomings-are-needed, whether-outgoings-are-needed)
3875 #
3875 #
3876 # otherwise, 'changes' is a tuple of tuples below:
3876 # otherwise, 'changes' is a tuple of tuples below:
3877 # - (sourceurl, sourcebranch, sourcepeer, incoming)
3877 # - (sourceurl, sourcebranch, sourcepeer, incoming)
3878 # - (desturl, destbranch, destpeer, outgoing)
3878 # - (desturl, destbranch, destpeer, outgoing)
3879 summaryremotehooks = util.hooks()
3879 summaryremotehooks = util.hooks()
3880
3880
3881 # A list of state files kept by multistep operations like graft.
3881 # A list of state files kept by multistep operations like graft.
3882 # Since graft cannot be aborted, it is considered 'clearable' by update.
3882 # Since graft cannot be aborted, it is considered 'clearable' by update.
3883 # note: bisect is intentionally excluded
3883 # note: bisect is intentionally excluded
3884 # (state file, clearable, allowcommit, error, hint)
3884 # (state file, clearable, allowcommit, error, hint)
3885 unfinishedstates = [
3885 unfinishedstates = [
3886 ('graftstate', True, False, _('graft in progress'),
3886 ('graftstate', True, False, _('graft in progress'),
3887 _("use 'hg graft --continue' or 'hg update' to abort")),
3887 _("use 'hg graft --continue' or 'hg update' to abort")),
3888 ('updatestate', True, False, _('last update was interrupted'),
3888 ('updatestate', True, False, _('last update was interrupted'),
3889 _("use 'hg update' to get a consistent checkout"))
3889 _("use 'hg update' to get a consistent checkout"))
3890 ]
3890 ]
3891
3891
3892 def checkunfinished(repo, commit=False):
3892 def checkunfinished(repo, commit=False):
3893 '''Look for an unfinished multistep operation, like graft, and abort
3893 '''Look for an unfinished multistep operation, like graft, and abort
3894 if found. It's probably good to check this right before
3894 if found. It's probably good to check this right before
3895 bailifchanged().
3895 bailifchanged().
3896 '''
3896 '''
3897 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3897 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3898 if commit and allowcommit:
3898 if commit and allowcommit:
3899 continue
3899 continue
3900 if repo.vfs.exists(f):
3900 if repo.vfs.exists(f):
3901 raise error.Abort(msg, hint=hint)
3901 raise error.Abort(msg, hint=hint)
3902
3902
3903 def clearunfinished(repo):
3903 def clearunfinished(repo):
3904 '''Check for unfinished operations (as above), and clear the ones
3904 '''Check for unfinished operations (as above), and clear the ones
3905 that are clearable.
3905 that are clearable.
3906 '''
3906 '''
3907 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3907 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3908 if not clearable and repo.vfs.exists(f):
3908 if not clearable and repo.vfs.exists(f):
3909 raise error.Abort(msg, hint=hint)
3909 raise error.Abort(msg, hint=hint)
3910 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3910 for f, clearable, allowcommit, msg, hint in unfinishedstates:
3911 if clearable and repo.vfs.exists(f):
3911 if clearable and repo.vfs.exists(f):
3912 util.unlink(repo.vfs.join(f))
3912 util.unlink(repo.vfs.join(f))
3913
3913
3914 afterresolvedstates = [
3914 afterresolvedstates = [
3915 ('graftstate',
3915 ('graftstate',
3916 _('hg graft --continue')),
3916 _('hg graft --continue')),
3917 ]
3917 ]
3918
3918
3919 def howtocontinue(repo):
3919 def howtocontinue(repo):
3920 '''Check for an unfinished operation and return the command to finish
3920 '''Check for an unfinished operation and return the command to finish
3921 it.
3921 it.
3922
3922
3923 afterresolvedstates tuples define a .hg/{file} and the corresponding
3923 afterresolvedstates tuples define a .hg/{file} and the corresponding
3924 command needed to finish it.
3924 command needed to finish it.
3925
3925
3926 Returns a (msg, warning) tuple. 'msg' is a string and 'warning' is
3926 Returns a (msg, warning) tuple. 'msg' is a string and 'warning' is
3927 a boolean.
3927 a boolean.
3928 '''
3928 '''
3929 contmsg = _("continue: %s")
3929 contmsg = _("continue: %s")
3930 for f, msg in afterresolvedstates:
3930 for f, msg in afterresolvedstates:
3931 if repo.vfs.exists(f):
3931 if repo.vfs.exists(f):
3932 return contmsg % msg, True
3932 return contmsg % msg, True
3933 if repo[None].dirty(missing=True, merge=False, branch=False):
3933 if repo[None].dirty(missing=True, merge=False, branch=False):
3934 return contmsg % _("hg commit"), False
3934 return contmsg % _("hg commit"), False
3935 return None, None
3935 return None, None
3936
3936
3937 def checkafterresolved(repo):
3937 def checkafterresolved(repo):
3938 '''Inform the user about the next action after completing hg resolve
3938 '''Inform the user about the next action after completing hg resolve
3939
3939
3940 If there's a matching afterresolvedstates, howtocontinue will yield
3940 If there's a matching afterresolvedstates, howtocontinue will yield
3941 repo.ui.warn as the reporter.
3941 repo.ui.warn as the reporter.
3942
3942
3943 Otherwise, it will yield repo.ui.note.
3943 Otherwise, it will yield repo.ui.note.
3944 '''
3944 '''
3945 msg, warning = howtocontinue(repo)
3945 msg, warning = howtocontinue(repo)
3946 if msg is not None:
3946 if msg is not None:
3947 if warning:
3947 if warning:
3948 repo.ui.warn("%s\n" % msg)
3948 repo.ui.warn("%s\n" % msg)
3949 else:
3949 else:
3950 repo.ui.note("%s\n" % msg)
3950 repo.ui.note("%s\n" % msg)
3951
3951
3952 def wrongtooltocontinue(repo, task):
3952 def wrongtooltocontinue(repo, task):
3953 '''Raise an abort suggesting how to properly continue if there is an
3953 '''Raise an abort suggesting how to properly continue if there is an
3954 active task.
3954 active task.
3955
3955
3956 Uses howtocontinue() to find the active task.
3956 Uses howtocontinue() to find the active task.
3957
3957
3958 If there's no task (repo.ui.note for 'hg commit'), it does not offer
3958 If there's no task (repo.ui.note for 'hg commit'), it does not offer
3959 a hint.
3959 a hint.
3960 '''
3960 '''
3961 after = howtocontinue(repo)
3961 after = howtocontinue(repo)
3962 hint = None
3962 hint = None
3963 if after[1]:
3963 if after[1]:
3964 hint = after[0]
3964 hint = after[0]
3965 raise error.Abort(_('no %s in progress') % task, hint=hint)
3965 raise error.Abort(_('no %s in progress') % task, hint=hint)
@@ -1,1013 +1,1013 b''
1 #if windows
1 #if windows
2 $ PYTHONPATH="$TESTDIR/../contrib;$PYTHONPATH"
2 $ PYTHONPATH="$TESTDIR/../contrib;$PYTHONPATH"
3 #else
3 #else
4 $ PYTHONPATH="$TESTDIR/../contrib:$PYTHONPATH"
4 $ PYTHONPATH="$TESTDIR/../contrib:$PYTHONPATH"
5 #endif
5 #endif
6 $ export PYTHONPATH
6 $ export PYTHONPATH
7
7
8 typical client does not want echo-back messages, so test without it:
8 typical client does not want echo-back messages, so test without it:
9
9
10 $ grep -v '^promptecho ' < $HGRCPATH >> $HGRCPATH.new
10 $ grep -v '^promptecho ' < $HGRCPATH >> $HGRCPATH.new
11 $ mv $HGRCPATH.new $HGRCPATH
11 $ mv $HGRCPATH.new $HGRCPATH
12
12
13 $ hg init repo
13 $ hg init repo
14 $ cd repo
14 $ cd repo
15
15
16 >>> from __future__ import absolute_import, print_function
16 >>> from __future__ import absolute_import, print_function
17 >>> import os
17 >>> import os
18 >>> import sys
18 >>> import sys
19 >>> from hgclient import check, readchannel, runcommand
19 >>> from hgclient import check, readchannel, runcommand
20 >>> @check
20 >>> @check
21 ... def hellomessage(server):
21 ... def hellomessage(server):
22 ... ch, data = readchannel(server)
22 ... ch, data = readchannel(server)
23 ... print('%c, %r' % (ch, data))
23 ... print('%c, %r' % (ch, data))
24 ... # run an arbitrary command to make sure the next thing the server
24 ... # run an arbitrary command to make sure the next thing the server
25 ... # sends isn't part of the hello message
25 ... # sends isn't part of the hello message
26 ... runcommand(server, ['id'])
26 ... runcommand(server, ['id'])
27 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
27 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
28 *** runcommand id
28 *** runcommand id
29 000000000000 tip
29 000000000000 tip
30
30
31 >>> from hgclient import check
31 >>> from hgclient import check
32 >>> @check
32 >>> @check
33 ... def unknowncommand(server):
33 ... def unknowncommand(server):
34 ... server.stdin.write('unknowncommand\n')
34 ... server.stdin.write('unknowncommand\n')
35 abort: unknown command unknowncommand
35 abort: unknown command unknowncommand
36
36
37 >>> from hgclient import check, readchannel, runcommand
37 >>> from hgclient import check, readchannel, runcommand
38 >>> @check
38 >>> @check
39 ... def checkruncommand(server):
39 ... def checkruncommand(server):
40 ... # hello block
40 ... # hello block
41 ... readchannel(server)
41 ... readchannel(server)
42 ...
42 ...
43 ... # no args
43 ... # no args
44 ... runcommand(server, [])
44 ... runcommand(server, [])
45 ...
45 ...
46 ... # global options
46 ... # global options
47 ... runcommand(server, ['id', '--quiet'])
47 ... runcommand(server, ['id', '--quiet'])
48 ...
48 ...
49 ... # make sure global options don't stick through requests
49 ... # make sure global options don't stick through requests
50 ... runcommand(server, ['id'])
50 ... runcommand(server, ['id'])
51 ...
51 ...
52 ... # --config
52 ... # --config
53 ... runcommand(server, ['id', '--config', 'ui.quiet=True'])
53 ... runcommand(server, ['id', '--config', 'ui.quiet=True'])
54 ...
54 ...
55 ... # make sure --config doesn't stick
55 ... # make sure --config doesn't stick
56 ... runcommand(server, ['id'])
56 ... runcommand(server, ['id'])
57 ...
57 ...
58 ... # negative return code should be masked
58 ... # negative return code should be masked
59 ... runcommand(server, ['id', '-runknown'])
59 ... runcommand(server, ['id', '-runknown'])
60 *** runcommand
60 *** runcommand
61 Mercurial Distributed SCM
61 Mercurial Distributed SCM
62
62
63 basic commands:
63 basic commands:
64
64
65 add add the specified files on the next commit
65 add add the specified files on the next commit
66 annotate show changeset information by line for each file
66 annotate show changeset information by line for each file
67 clone make a copy of an existing repository
67 clone make a copy of an existing repository
68 commit commit the specified files or all outstanding changes
68 commit commit the specified files or all outstanding changes
69 diff diff repository (or selected files)
69 diff diff repository (or selected files)
70 export dump the header and diffs for one or more changesets
70 export dump the header and diffs for one or more changesets
71 forget forget the specified files on the next commit
71 forget forget the specified files on the next commit
72 init create a new repository in the given directory
72 init create a new repository in the given directory
73 log show revision history of entire repository or files
73 log show revision history of entire repository or files
74 merge merge another revision into working directory
74 merge merge another revision into working directory
75 pull pull changes from the specified source
75 pull pull changes from the specified source
76 push push changes to the specified destination
76 push push changes to the specified destination
77 remove remove the specified files on the next commit
77 remove remove the specified files on the next commit
78 serve start stand-alone webserver
78 serve start stand-alone webserver
79 status show changed files in the working directory
79 status show changed files in the working directory
80 summary summarize working directory state
80 summary summarize working directory state
81 update update working directory (or switch revisions)
81 update update working directory (or switch revisions)
82
82
83 (use 'hg help' for the full list of commands or 'hg -v' for details)
83 (use 'hg help' for the full list of commands or 'hg -v' for details)
84 *** runcommand id --quiet
84 *** runcommand id --quiet
85 000000000000
85 000000000000
86 *** runcommand id
86 *** runcommand id
87 000000000000 tip
87 000000000000 tip
88 *** runcommand id --config ui.quiet=True
88 *** runcommand id --config ui.quiet=True
89 000000000000
89 000000000000
90 *** runcommand id
90 *** runcommand id
91 000000000000 tip
91 000000000000 tip
92 *** runcommand id -runknown
92 *** runcommand id -runknown
93 abort: unknown revision 'unknown'!
93 abort: unknown revision 'unknown'!
94 [255]
94 [255]
95
95
96 >>> from hgclient import check, readchannel
96 >>> from hgclient import check, readchannel
97 >>> @check
97 >>> @check
98 ... def inputeof(server):
98 ... def inputeof(server):
99 ... readchannel(server)
99 ... readchannel(server)
100 ... server.stdin.write('runcommand\n')
100 ... server.stdin.write('runcommand\n')
101 ... # close stdin while server is waiting for input
101 ... # close stdin while server is waiting for input
102 ... server.stdin.close()
102 ... server.stdin.close()
103 ...
103 ...
104 ... # server exits with 1 if the pipe closed while reading the command
104 ... # server exits with 1 if the pipe closed while reading the command
105 ... print('server exit code =', server.wait())
105 ... print('server exit code =', server.wait())
106 server exit code = 1
106 server exit code = 1
107
107
108 >>> from hgclient import check, readchannel, runcommand, stringio
108 >>> from hgclient import check, readchannel, runcommand, stringio
109 >>> @check
109 >>> @check
110 ... def serverinput(server):
110 ... def serverinput(server):
111 ... readchannel(server)
111 ... readchannel(server)
112 ...
112 ...
113 ... patch = """
113 ... patch = """
114 ... # HG changeset patch
114 ... # HG changeset patch
115 ... # User test
115 ... # User test
116 ... # Date 0 0
116 ... # Date 0 0
117 ... # Node ID c103a3dec114d882c98382d684d8af798d09d857
117 ... # Node ID c103a3dec114d882c98382d684d8af798d09d857
118 ... # Parent 0000000000000000000000000000000000000000
118 ... # Parent 0000000000000000000000000000000000000000
119 ... 1
119 ... 1
120 ...
120 ...
121 ... diff -r 000000000000 -r c103a3dec114 a
121 ... diff -r 000000000000 -r c103a3dec114 a
122 ... --- /dev/null Thu Jan 01 00:00:00 1970 +0000
122 ... --- /dev/null Thu Jan 01 00:00:00 1970 +0000
123 ... +++ b/a Thu Jan 01 00:00:00 1970 +0000
123 ... +++ b/a Thu Jan 01 00:00:00 1970 +0000
124 ... @@ -0,0 +1,1 @@
124 ... @@ -0,0 +1,1 @@
125 ... +1
125 ... +1
126 ... """
126 ... """
127 ...
127 ...
128 ... runcommand(server, ['import', '-'], input=stringio(patch))
128 ... runcommand(server, ['import', '-'], input=stringio(patch))
129 ... runcommand(server, ['log'])
129 ... runcommand(server, ['log'])
130 *** runcommand import -
130 *** runcommand import -
131 applying patch from stdin
131 applying patch from stdin
132 *** runcommand log
132 *** runcommand log
133 changeset: 0:eff892de26ec
133 changeset: 0:eff892de26ec
134 tag: tip
134 tag: tip
135 user: test
135 user: test
136 date: Thu Jan 01 00:00:00 1970 +0000
136 date: Thu Jan 01 00:00:00 1970 +0000
137 summary: 1
137 summary: 1
138
138
139
139
140 check that "histedit --commands=-" can read rules from the input channel:
140 check that "histedit --commands=-" can read rules from the input channel:
141
141
142 >>> import cStringIO
142 >>> import cStringIO
143 >>> from hgclient import check, readchannel, runcommand
143 >>> from hgclient import check, readchannel, runcommand
144 >>> @check
144 >>> @check
145 ... def serverinput(server):
145 ... def serverinput(server):
146 ... readchannel(server)
146 ... readchannel(server)
147 ... rules = 'pick eff892de26ec\n'
147 ... rules = 'pick eff892de26ec\n'
148 ... runcommand(server, ['histedit', '0', '--commands=-',
148 ... runcommand(server, ['histedit', '0', '--commands=-',
149 ... '--config', 'extensions.histedit='],
149 ... '--config', 'extensions.histedit='],
150 ... input=cStringIO.StringIO(rules))
150 ... input=cStringIO.StringIO(rules))
151 *** runcommand histedit 0 --commands=- --config extensions.histedit=
151 *** runcommand histedit 0 --commands=- --config extensions.histedit=
152
152
153 check that --cwd doesn't persist between requests:
153 check that --cwd doesn't persist between requests:
154
154
155 $ mkdir foo
155 $ mkdir foo
156 $ touch foo/bar
156 $ touch foo/bar
157 >>> from hgclient import check, readchannel, runcommand
157 >>> from hgclient import check, readchannel, runcommand
158 >>> @check
158 >>> @check
159 ... def cwd(server):
159 ... def cwd(server):
160 ... readchannel(server)
160 ... readchannel(server)
161 ... runcommand(server, ['--cwd', 'foo', 'st', 'bar'])
161 ... runcommand(server, ['--cwd', 'foo', 'st', 'bar'])
162 ... runcommand(server, ['st', 'foo/bar'])
162 ... runcommand(server, ['st', 'foo/bar'])
163 *** runcommand --cwd foo st bar
163 *** runcommand --cwd foo st bar
164 ? bar
164 ? bar
165 *** runcommand st foo/bar
165 *** runcommand st foo/bar
166 ? foo/bar
166 ? foo/bar
167
167
168 $ rm foo/bar
168 $ rm foo/bar
169
169
170
170
171 check that local configs for the cached repo aren't inherited when -R is used:
171 check that local configs for the cached repo aren't inherited when -R is used:
172
172
173 $ cat <<EOF >> .hg/hgrc
173 $ cat <<EOF >> .hg/hgrc
174 > [ui]
174 > [ui]
175 > foo = bar
175 > foo = bar
176 > EOF
176 > EOF
177
177
178 >>> from hgclient import check, readchannel, runcommand, sep
178 >>> from hgclient import check, readchannel, runcommand, sep
179 >>> @check
179 >>> @check
180 ... def localhgrc(server):
180 ... def localhgrc(server):
181 ... readchannel(server)
181 ... readchannel(server)
182 ...
182 ...
183 ... # the cached repo local hgrc contains ui.foo=bar, so showconfig should
183 ... # the cached repo local hgrc contains ui.foo=bar, so showconfig should
184 ... # show it
184 ... # show it
185 ... runcommand(server, ['showconfig'], outfilter=sep)
185 ... runcommand(server, ['showconfig'], outfilter=sep)
186 ...
186 ...
187 ... # but not for this repo
187 ... # but not for this repo
188 ... runcommand(server, ['init', 'foo'])
188 ... runcommand(server, ['init', 'foo'])
189 ... runcommand(server, ['-R', 'foo', 'showconfig', 'ui', 'defaults'])
189 ... runcommand(server, ['-R', 'foo', 'showconfig', 'ui', 'defaults'])
190 *** runcommand showconfig
190 *** runcommand showconfig
191 bundle.mainreporoot=$TESTTMP/repo
191 bundle.mainreporoot=$TESTTMP/repo
192 devel.all-warnings=true
192 devel.all-warnings=true
193 devel.default-date=0 0
193 devel.default-date=0 0
194 extensions.fsmonitor= (fsmonitor !)
194 extensions.fsmonitor= (fsmonitor !)
195 largefiles.usercache=$TESTTMP/.cache/largefiles
195 largefiles.usercache=$TESTTMP/.cache/largefiles
196 ui.slash=True
196 ui.slash=True
197 ui.interactive=False
197 ui.interactive=False
198 ui.mergemarkers=detailed
198 ui.mergemarkers=detailed
199 ui.usehttp2=true (?)
199 ui.usehttp2=true (?)
200 ui.foo=bar
200 ui.foo=bar
201 ui.nontty=true
201 ui.nontty=true
202 web.address=localhost
202 web.address=localhost
203 web\.ipv6=(?:True|False) (re)
203 web\.ipv6=(?:True|False) (re)
204 *** runcommand init foo
204 *** runcommand init foo
205 *** runcommand -R foo showconfig ui defaults
205 *** runcommand -R foo showconfig ui defaults
206 ui.slash=True
206 ui.slash=True
207 ui.interactive=False
207 ui.interactive=False
208 ui.mergemarkers=detailed
208 ui.mergemarkers=detailed
209 ui.usehttp2=true (?)
209 ui.usehttp2=true (?)
210 ui.nontty=true
210 ui.nontty=true
211
211
212 $ rm -R foo
212 $ rm -R foo
213
213
214 #if windows
214 #if windows
215 $ PYTHONPATH="$TESTTMP/repo;$PYTHONPATH"
215 $ PYTHONPATH="$TESTTMP/repo;$PYTHONPATH"
216 #else
216 #else
217 $ PYTHONPATH="$TESTTMP/repo:$PYTHONPATH"
217 $ PYTHONPATH="$TESTTMP/repo:$PYTHONPATH"
218 #endif
218 #endif
219
219
220 $ cat <<EOF > hook.py
220 $ cat <<EOF > hook.py
221 > from __future__ import print_function
221 > from __future__ import print_function
222 > import sys
222 > import sys
223 > def hook(**args):
223 > def hook(**args):
224 > print('hook talking')
224 > print('hook talking')
225 > print('now try to read something: %r' % sys.stdin.read())
225 > print('now try to read something: %r' % sys.stdin.read())
226 > EOF
226 > EOF
227
227
228 >>> from hgclient import check, readchannel, runcommand, stringio
228 >>> from hgclient import check, readchannel, runcommand, stringio
229 >>> @check
229 >>> @check
230 ... def hookoutput(server):
230 ... def hookoutput(server):
231 ... readchannel(server)
231 ... readchannel(server)
232 ... runcommand(server, ['--config',
232 ... runcommand(server, ['--config',
233 ... 'hooks.pre-identify=python:hook.hook',
233 ... 'hooks.pre-identify=python:hook.hook',
234 ... 'id'],
234 ... 'id'],
235 ... input=stringio('some input'))
235 ... input=stringio('some input'))
236 *** runcommand --config hooks.pre-identify=python:hook.hook id
236 *** runcommand --config hooks.pre-identify=python:hook.hook id
237 eff892de26ec tip
237 eff892de26ec tip
238
238
239 Clean hook cached version
239 Clean hook cached version
240 $ rm hook.py*
240 $ rm hook.py*
241 $ rm -Rf __pycache__
241 $ rm -Rf __pycache__
242
242
243 $ echo a >> a
243 $ echo a >> a
244 >>> import os
244 >>> import os
245 >>> from hgclient import check, readchannel, runcommand
245 >>> from hgclient import check, readchannel, runcommand
246 >>> @check
246 >>> @check
247 ... def outsidechanges(server):
247 ... def outsidechanges(server):
248 ... readchannel(server)
248 ... readchannel(server)
249 ... runcommand(server, ['status'])
249 ... runcommand(server, ['status'])
250 ... os.system('hg ci -Am2')
250 ... os.system('hg ci -Am2')
251 ... runcommand(server, ['tip'])
251 ... runcommand(server, ['tip'])
252 ... runcommand(server, ['status'])
252 ... runcommand(server, ['status'])
253 *** runcommand status
253 *** runcommand status
254 M a
254 M a
255 *** runcommand tip
255 *** runcommand tip
256 changeset: 1:d3a0a68be6de
256 changeset: 1:d3a0a68be6de
257 tag: tip
257 tag: tip
258 user: test
258 user: test
259 date: Thu Jan 01 00:00:00 1970 +0000
259 date: Thu Jan 01 00:00:00 1970 +0000
260 summary: 2
260 summary: 2
261
261
262 *** runcommand status
262 *** runcommand status
263
263
264 >>> import os
264 >>> import os
265 >>> from hgclient import check, readchannel, runcommand
265 >>> from hgclient import check, readchannel, runcommand
266 >>> @check
266 >>> @check
267 ... def bookmarks(server):
267 ... def bookmarks(server):
268 ... readchannel(server)
268 ... readchannel(server)
269 ... runcommand(server, ['bookmarks'])
269 ... runcommand(server, ['bookmarks'])
270 ...
270 ...
271 ... # changes .hg/bookmarks
271 ... # changes .hg/bookmarks
272 ... os.system('hg bookmark -i bm1')
272 ... os.system('hg bookmark -i bm1')
273 ... os.system('hg bookmark -i bm2')
273 ... os.system('hg bookmark -i bm2')
274 ... runcommand(server, ['bookmarks'])
274 ... runcommand(server, ['bookmarks'])
275 ...
275 ...
276 ... # changes .hg/bookmarks.current
276 ... # changes .hg/bookmarks.current
277 ... os.system('hg upd bm1 -q')
277 ... os.system('hg upd bm1 -q')
278 ... runcommand(server, ['bookmarks'])
278 ... runcommand(server, ['bookmarks'])
279 ...
279 ...
280 ... runcommand(server, ['bookmarks', 'bm3'])
280 ... runcommand(server, ['bookmarks', 'bm3'])
281 ... f = open('a', 'ab')
281 ... f = open('a', 'ab')
282 ... f.write('a\n')
282 ... f.write('a\n')
283 ... f.close()
283 ... f.close()
284 ... runcommand(server, ['commit', '-Amm'])
284 ... runcommand(server, ['commit', '-Amm'])
285 ... runcommand(server, ['bookmarks'])
285 ... runcommand(server, ['bookmarks'])
286 ... print('')
286 ... print('')
287 *** runcommand bookmarks
287 *** runcommand bookmarks
288 no bookmarks set
288 no bookmarks set
289 *** runcommand bookmarks
289 *** runcommand bookmarks
290 bm1 1:d3a0a68be6de
290 bm1 1:d3a0a68be6de
291 bm2 1:d3a0a68be6de
291 bm2 1:d3a0a68be6de
292 *** runcommand bookmarks
292 *** runcommand bookmarks
293 * bm1 1:d3a0a68be6de
293 * bm1 1:d3a0a68be6de
294 bm2 1:d3a0a68be6de
294 bm2 1:d3a0a68be6de
295 *** runcommand bookmarks bm3
295 *** runcommand bookmarks bm3
296 *** runcommand commit -Amm
296 *** runcommand commit -Amm
297 *** runcommand bookmarks
297 *** runcommand bookmarks
298 bm1 1:d3a0a68be6de
298 bm1 1:d3a0a68be6de
299 bm2 1:d3a0a68be6de
299 bm2 1:d3a0a68be6de
300 * bm3 2:aef17e88f5f0
300 * bm3 2:aef17e88f5f0
301
301
302
302
303 >>> import os
303 >>> import os
304 >>> from hgclient import check, readchannel, runcommand
304 >>> from hgclient import check, readchannel, runcommand
305 >>> @check
305 >>> @check
306 ... def tagscache(server):
306 ... def tagscache(server):
307 ... readchannel(server)
307 ... readchannel(server)
308 ... runcommand(server, ['id', '-t', '-r', '0'])
308 ... runcommand(server, ['id', '-t', '-r', '0'])
309 ... os.system('hg tag -r 0 foo')
309 ... os.system('hg tag -r 0 foo')
310 ... runcommand(server, ['id', '-t', '-r', '0'])
310 ... runcommand(server, ['id', '-t', '-r', '0'])
311 *** runcommand id -t -r 0
311 *** runcommand id -t -r 0
312
312
313 *** runcommand id -t -r 0
313 *** runcommand id -t -r 0
314 foo
314 foo
315
315
316 >>> import os
316 >>> import os
317 >>> from hgclient import check, readchannel, runcommand
317 >>> from hgclient import check, readchannel, runcommand
318 >>> @check
318 >>> @check
319 ... def setphase(server):
319 ... def setphase(server):
320 ... readchannel(server)
320 ... readchannel(server)
321 ... runcommand(server, ['phase', '-r', '.'])
321 ... runcommand(server, ['phase', '-r', '.'])
322 ... os.system('hg phase -r . -p')
322 ... os.system('hg phase -r . -p')
323 ... runcommand(server, ['phase', '-r', '.'])
323 ... runcommand(server, ['phase', '-r', '.'])
324 *** runcommand phase -r .
324 *** runcommand phase -r .
325 3: draft
325 3: draft
326 *** runcommand phase -r .
326 *** runcommand phase -r .
327 3: public
327 3: public
328
328
329 $ echo a >> a
329 $ echo a >> a
330 >>> from hgclient import check, readchannel, runcommand
330 >>> from hgclient import check, readchannel, runcommand
331 >>> @check
331 >>> @check
332 ... def rollback(server):
332 ... def rollback(server):
333 ... readchannel(server)
333 ... readchannel(server)
334 ... runcommand(server, ['phase', '-r', '.', '-p'])
334 ... runcommand(server, ['phase', '-r', '.', '-p'])
335 ... runcommand(server, ['commit', '-Am.'])
335 ... runcommand(server, ['commit', '-Am.'])
336 ... runcommand(server, ['rollback'])
336 ... runcommand(server, ['rollback'])
337 ... runcommand(server, ['phase', '-r', '.'])
337 ... runcommand(server, ['phase', '-r', '.'])
338 ... print('')
338 ... print('')
339 *** runcommand phase -r . -p
339 *** runcommand phase -r . -p
340 no phases changed
340 no phases changed
341 *** runcommand commit -Am.
341 *** runcommand commit -Am.
342 *** runcommand rollback
342 *** runcommand rollback
343 repository tip rolled back to revision 3 (undo commit)
343 repository tip rolled back to revision 3 (undo commit)
344 working directory now based on revision 3
344 working directory now based on revision 3
345 *** runcommand phase -r .
345 *** runcommand phase -r .
346 3: public
346 3: public
347
347
348
348
349 >>> import os
349 >>> import os
350 >>> from hgclient import check, readchannel, runcommand
350 >>> from hgclient import check, readchannel, runcommand
351 >>> @check
351 >>> @check
352 ... def branch(server):
352 ... def branch(server):
353 ... readchannel(server)
353 ... readchannel(server)
354 ... runcommand(server, ['branch'])
354 ... runcommand(server, ['branch'])
355 ... os.system('hg branch foo')
355 ... os.system('hg branch foo')
356 ... runcommand(server, ['branch'])
356 ... runcommand(server, ['branch'])
357 ... os.system('hg branch default')
357 ... os.system('hg branch default')
358 *** runcommand branch
358 *** runcommand branch
359 default
359 default
360 marked working directory as branch foo
360 marked working directory as branch foo
361 (branches are permanent and global, did you want a bookmark?)
361 (branches are permanent and global, did you want a bookmark?)
362 *** runcommand branch
362 *** runcommand branch
363 foo
363 foo
364 marked working directory as branch default
364 marked working directory as branch default
365 (branches are permanent and global, did you want a bookmark?)
365 (branches are permanent and global, did you want a bookmark?)
366
366
367 $ touch .hgignore
367 $ touch .hgignore
368 >>> import os
368 >>> import os
369 >>> from hgclient import check, readchannel, runcommand
369 >>> from hgclient import check, readchannel, runcommand
370 >>> @check
370 >>> @check
371 ... def hgignore(server):
371 ... def hgignore(server):
372 ... readchannel(server)
372 ... readchannel(server)
373 ... runcommand(server, ['commit', '-Am.'])
373 ... runcommand(server, ['commit', '-Am.'])
374 ... f = open('ignored-file', 'ab')
374 ... f = open('ignored-file', 'ab')
375 ... f.write('')
375 ... f.write('')
376 ... f.close()
376 ... f.close()
377 ... f = open('.hgignore', 'ab')
377 ... f = open('.hgignore', 'ab')
378 ... f.write('ignored-file')
378 ... f.write('ignored-file')
379 ... f.close()
379 ... f.close()
380 ... runcommand(server, ['status', '-i', '-u'])
380 ... runcommand(server, ['status', '-i', '-u'])
381 ... print('')
381 ... print('')
382 *** runcommand commit -Am.
382 *** runcommand commit -Am.
383 adding .hgignore
383 adding .hgignore
384 *** runcommand status -i -u
384 *** runcommand status -i -u
385 I ignored-file
385 I ignored-file
386
386
387
387
388 cache of non-public revisions should be invalidated on repository change
388 cache of non-public revisions should be invalidated on repository change
389 (issue4855):
389 (issue4855):
390
390
391 >>> import os
391 >>> import os
392 >>> from hgclient import check, readchannel, runcommand
392 >>> from hgclient import check, readchannel, runcommand
393 >>> @check
393 >>> @check
394 ... def phasesetscacheaftercommit(server):
394 ... def phasesetscacheaftercommit(server):
395 ... readchannel(server)
395 ... readchannel(server)
396 ... # load _phasecache._phaserevs and _phasesets
396 ... # load _phasecache._phaserevs and _phasesets
397 ... runcommand(server, ['log', '-qr', 'draft()'])
397 ... runcommand(server, ['log', '-qr', 'draft()'])
398 ... # create draft commits by another process
398 ... # create draft commits by another process
399 ... for i in xrange(5, 7):
399 ... for i in xrange(5, 7):
400 ... f = open('a', 'ab')
400 ... f = open('a', 'ab')
401 ... f.seek(0, os.SEEK_END)
401 ... f.seek(0, os.SEEK_END)
402 ... f.write('a\n')
402 ... f.write('a\n')
403 ... f.close()
403 ... f.close()
404 ... os.system('hg commit -Aqm%d' % i)
404 ... os.system('hg commit -Aqm%d' % i)
405 ... # new commits should be listed as draft revisions
405 ... # new commits should be listed as draft revisions
406 ... runcommand(server, ['log', '-qr', 'draft()'])
406 ... runcommand(server, ['log', '-qr', 'draft()'])
407 ... print('')
407 ... print('')
408 *** runcommand log -qr draft()
408 *** runcommand log -qr draft()
409 4:7966c8e3734d
409 4:7966c8e3734d
410 *** runcommand log -qr draft()
410 *** runcommand log -qr draft()
411 4:7966c8e3734d
411 4:7966c8e3734d
412 5:41f6602d1c4f
412 5:41f6602d1c4f
413 6:10501e202c35
413 6:10501e202c35
414
414
415
415
416 >>> import os
416 >>> import os
417 >>> from hgclient import check, readchannel, runcommand
417 >>> from hgclient import check, readchannel, runcommand
418 >>> @check
418 >>> @check
419 ... def phasesetscacheafterstrip(server):
419 ... def phasesetscacheafterstrip(server):
420 ... readchannel(server)
420 ... readchannel(server)
421 ... # load _phasecache._phaserevs and _phasesets
421 ... # load _phasecache._phaserevs and _phasesets
422 ... runcommand(server, ['log', '-qr', 'draft()'])
422 ... runcommand(server, ['log', '-qr', 'draft()'])
423 ... # strip cached revisions by another process
423 ... # strip cached revisions by another process
424 ... os.system('hg --config extensions.strip= strip -q 5')
424 ... os.system('hg --config extensions.strip= strip -q 5')
425 ... # shouldn't abort by "unknown revision '6'"
425 ... # shouldn't abort by "unknown revision '6'"
426 ... runcommand(server, ['log', '-qr', 'draft()'])
426 ... runcommand(server, ['log', '-qr', 'draft()'])
427 ... print('')
427 ... print('')
428 *** runcommand log -qr draft()
428 *** runcommand log -qr draft()
429 4:7966c8e3734d
429 4:7966c8e3734d
430 5:41f6602d1c4f
430 5:41f6602d1c4f
431 6:10501e202c35
431 6:10501e202c35
432 *** runcommand log -qr draft()
432 *** runcommand log -qr draft()
433 4:7966c8e3734d
433 4:7966c8e3734d
434
434
435
435
436 cache of phase roots should be invalidated on strip (issue3827):
436 cache of phase roots should be invalidated on strip (issue3827):
437
437
438 >>> import os
438 >>> import os
439 >>> from hgclient import check, readchannel, runcommand, sep
439 >>> from hgclient import check, readchannel, runcommand, sep
440 >>> @check
440 >>> @check
441 ... def phasecacheafterstrip(server):
441 ... def phasecacheafterstrip(server):
442 ... readchannel(server)
442 ... readchannel(server)
443 ...
443 ...
444 ... # create new head, 5:731265503d86
444 ... # create new head, 5:731265503d86
445 ... runcommand(server, ['update', '-C', '0'])
445 ... runcommand(server, ['update', '-C', '0'])
446 ... f = open('a', 'ab')
446 ... f = open('a', 'ab')
447 ... f.write('a\n')
447 ... f.write('a\n')
448 ... f.close()
448 ... f.close()
449 ... runcommand(server, ['commit', '-Am.', 'a'])
449 ... runcommand(server, ['commit', '-Am.', 'a'])
450 ... runcommand(server, ['log', '-Gq'])
450 ... runcommand(server, ['log', '-Gq'])
451 ...
451 ...
452 ... # make it public; draft marker moves to 4:7966c8e3734d
452 ... # make it public; draft marker moves to 4:7966c8e3734d
453 ... runcommand(server, ['phase', '-p', '.'])
453 ... runcommand(server, ['phase', '-p', '.'])
454 ... # load _phasecache.phaseroots
454 ... # load _phasecache.phaseroots
455 ... runcommand(server, ['phase', '.'], outfilter=sep)
455 ... runcommand(server, ['phase', '.'], outfilter=sep)
456 ...
456 ...
457 ... # strip 1::4 outside server
457 ... # strip 1::4 outside server
458 ... os.system('hg -q --config extensions.mq= strip 1')
458 ... os.system('hg -q --config extensions.mq= strip 1')
459 ...
459 ...
460 ... # shouldn't raise "7966c8e3734d: no node!"
460 ... # shouldn't raise "7966c8e3734d: no node!"
461 ... runcommand(server, ['branches'])
461 ... runcommand(server, ['branches'])
462 *** runcommand update -C 0
462 *** runcommand update -C 0
463 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
463 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
464 (leaving bookmark bm3)
464 (leaving bookmark bm3)
465 *** runcommand commit -Am. a
465 *** runcommand commit -Am. a
466 created new head
466 created new head
467 *** runcommand log -Gq
467 *** runcommand log -Gq
468 @ 5:731265503d86
468 @ 5:731265503d86
469 |
469 |
470 | o 4:7966c8e3734d
470 | o 4:7966c8e3734d
471 | |
471 | |
472 | o 3:b9b85890c400
472 | o 3:b9b85890c400
473 | |
473 | |
474 | o 2:aef17e88f5f0
474 | o 2:aef17e88f5f0
475 | |
475 | |
476 | o 1:d3a0a68be6de
476 | o 1:d3a0a68be6de
477 |/
477 |/
478 o 0:eff892de26ec
478 o 0:eff892de26ec
479
479
480 *** runcommand phase -p .
480 *** runcommand phase -p .
481 *** runcommand phase .
481 *** runcommand phase .
482 5: public
482 5: public
483 *** runcommand branches
483 *** runcommand branches
484 default 1:731265503d86
484 default 1:731265503d86
485
485
486 in-memory cache must be reloaded if transaction is aborted. otherwise
486 in-memory cache must be reloaded if transaction is aborted. otherwise
487 changelog and manifest would have invalid node:
487 changelog and manifest would have invalid node:
488
488
489 $ echo a >> a
489 $ echo a >> a
490 >>> from hgclient import check, readchannel, runcommand
490 >>> from hgclient import check, readchannel, runcommand
491 >>> @check
491 >>> @check
492 ... def txabort(server):
492 ... def txabort(server):
493 ... readchannel(server)
493 ... readchannel(server)
494 ... runcommand(server, ['commit', '--config', 'hooks.pretxncommit=false',
494 ... runcommand(server, ['commit', '--config', 'hooks.pretxncommit=false',
495 ... '-mfoo'])
495 ... '-mfoo'])
496 ... runcommand(server, ['verify'])
496 ... runcommand(server, ['verify'])
497 *** runcommand commit --config hooks.pretxncommit=false -mfoo
497 *** runcommand commit --config hooks.pretxncommit=false -mfoo
498 transaction abort!
498 transaction abort!
499 rollback completed
499 rollback completed
500 abort: pretxncommit hook exited with status 1
500 abort: pretxncommit hook exited with status 1
501 [255]
501 [255]
502 *** runcommand verify
502 *** runcommand verify
503 checking changesets
503 checking changesets
504 checking manifests
504 checking manifests
505 crosschecking files in changesets and manifests
505 crosschecking files in changesets and manifests
506 checking files
506 checking files
507 1 files, 2 changesets, 2 total revisions
507 1 files, 2 changesets, 2 total revisions
508 $ hg revert --no-backup -aq
508 $ hg revert --no-backup -aq
509
509
510 $ cat >> .hg/hgrc << EOF
510 $ cat >> .hg/hgrc << EOF
511 > [experimental]
511 > [experimental]
512 > evolution.createmarkers=True
512 > evolution.createmarkers=True
513 > EOF
513 > EOF
514
514
515 >>> import os
515 >>> import os
516 >>> from hgclient import check, readchannel, runcommand
516 >>> from hgclient import check, readchannel, runcommand
517 >>> @check
517 >>> @check
518 ... def obsolete(server):
518 ... def obsolete(server):
519 ... readchannel(server)
519 ... readchannel(server)
520 ...
520 ...
521 ... runcommand(server, ['up', 'null'])
521 ... runcommand(server, ['up', 'null'])
522 ... runcommand(server, ['phase', '-df', 'tip'])
522 ... runcommand(server, ['phase', '-df', 'tip'])
523 ... cmd = 'hg debugobsolete `hg log -r tip --template {node}`'
523 ... cmd = 'hg debugobsolete `hg log -r tip --template {node}`'
524 ... if os.name == 'nt':
524 ... if os.name == 'nt':
525 ... cmd = 'sh -c "%s"' % cmd # run in sh, not cmd.exe
525 ... cmd = 'sh -c "%s"' % cmd # run in sh, not cmd.exe
526 ... os.system(cmd)
526 ... os.system(cmd)
527 ... runcommand(server, ['log', '--hidden'])
527 ... runcommand(server, ['log', '--hidden'])
528 ... runcommand(server, ['log'])
528 ... runcommand(server, ['log'])
529 *** runcommand up null
529 *** runcommand up null
530 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
530 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
531 *** runcommand phase -df tip
531 *** runcommand phase -df tip
532 obsoleted 1 changesets
532 obsoleted 1 changesets
533 *** runcommand log --hidden
533 *** runcommand log --hidden
534 changeset: 1:731265503d86
534 changeset: 1:731265503d86
535 tag: tip
535 tag: tip
536 user: test
536 user: test
537 date: Thu Jan 01 00:00:00 1970 +0000
537 date: Thu Jan 01 00:00:00 1970 +0000
538 obsfate: pruned
538 obsolete: pruned
539 summary: .
539 summary: .
540
540
541 changeset: 0:eff892de26ec
541 changeset: 0:eff892de26ec
542 bookmark: bm1
542 bookmark: bm1
543 bookmark: bm2
543 bookmark: bm2
544 bookmark: bm3
544 bookmark: bm3
545 user: test
545 user: test
546 date: Thu Jan 01 00:00:00 1970 +0000
546 date: Thu Jan 01 00:00:00 1970 +0000
547 summary: 1
547 summary: 1
548
548
549 *** runcommand log
549 *** runcommand log
550 changeset: 0:eff892de26ec
550 changeset: 0:eff892de26ec
551 bookmark: bm1
551 bookmark: bm1
552 bookmark: bm2
552 bookmark: bm2
553 bookmark: bm3
553 bookmark: bm3
554 tag: tip
554 tag: tip
555 user: test
555 user: test
556 date: Thu Jan 01 00:00:00 1970 +0000
556 date: Thu Jan 01 00:00:00 1970 +0000
557 summary: 1
557 summary: 1
558
558
559
559
560 $ cat <<EOF >> .hg/hgrc
560 $ cat <<EOF >> .hg/hgrc
561 > [extensions]
561 > [extensions]
562 > mq =
562 > mq =
563 > EOF
563 > EOF
564
564
565 >>> import os
565 >>> import os
566 >>> from hgclient import check, readchannel, runcommand
566 >>> from hgclient import check, readchannel, runcommand
567 >>> @check
567 >>> @check
568 ... def mqoutsidechanges(server):
568 ... def mqoutsidechanges(server):
569 ... readchannel(server)
569 ... readchannel(server)
570 ...
570 ...
571 ... # load repo.mq
571 ... # load repo.mq
572 ... runcommand(server, ['qapplied'])
572 ... runcommand(server, ['qapplied'])
573 ... os.system('hg qnew 0.diff')
573 ... os.system('hg qnew 0.diff')
574 ... # repo.mq should be invalidated
574 ... # repo.mq should be invalidated
575 ... runcommand(server, ['qapplied'])
575 ... runcommand(server, ['qapplied'])
576 ...
576 ...
577 ... runcommand(server, ['qpop', '--all'])
577 ... runcommand(server, ['qpop', '--all'])
578 ... os.system('hg qqueue --create foo')
578 ... os.system('hg qqueue --create foo')
579 ... # repo.mq should be recreated to point to new queue
579 ... # repo.mq should be recreated to point to new queue
580 ... runcommand(server, ['qqueue', '--active'])
580 ... runcommand(server, ['qqueue', '--active'])
581 *** runcommand qapplied
581 *** runcommand qapplied
582 *** runcommand qapplied
582 *** runcommand qapplied
583 0.diff
583 0.diff
584 *** runcommand qpop --all
584 *** runcommand qpop --all
585 popping 0.diff
585 popping 0.diff
586 patch queue now empty
586 patch queue now empty
587 *** runcommand qqueue --active
587 *** runcommand qqueue --active
588 foo
588 foo
589
589
590 $ cat <<EOF > dbgui.py
590 $ cat <<EOF > dbgui.py
591 > import os
591 > import os
592 > import sys
592 > import sys
593 > from mercurial import commands, registrar
593 > from mercurial import commands, registrar
594 > cmdtable = {}
594 > cmdtable = {}
595 > command = registrar.command(cmdtable)
595 > command = registrar.command(cmdtable)
596 > @command(b"debuggetpass", norepo=True)
596 > @command(b"debuggetpass", norepo=True)
597 > def debuggetpass(ui):
597 > def debuggetpass(ui):
598 > ui.write("%s\\n" % ui.getpass())
598 > ui.write("%s\\n" % ui.getpass())
599 > @command(b"debugprompt", norepo=True)
599 > @command(b"debugprompt", norepo=True)
600 > def debugprompt(ui):
600 > def debugprompt(ui):
601 > ui.write("%s\\n" % ui.prompt("prompt:"))
601 > ui.write("%s\\n" % ui.prompt("prompt:"))
602 > @command(b"debugreadstdin", norepo=True)
602 > @command(b"debugreadstdin", norepo=True)
603 > def debugreadstdin(ui):
603 > def debugreadstdin(ui):
604 > ui.write("read: %r\n" % sys.stdin.read(1))
604 > ui.write("read: %r\n" % sys.stdin.read(1))
605 > @command(b"debugwritestdout", norepo=True)
605 > @command(b"debugwritestdout", norepo=True)
606 > def debugwritestdout(ui):
606 > def debugwritestdout(ui):
607 > os.write(1, "low-level stdout fd and\n")
607 > os.write(1, "low-level stdout fd and\n")
608 > sys.stdout.write("stdout should be redirected to /dev/null\n")
608 > sys.stdout.write("stdout should be redirected to /dev/null\n")
609 > sys.stdout.flush()
609 > sys.stdout.flush()
610 > EOF
610 > EOF
611 $ cat <<EOF >> .hg/hgrc
611 $ cat <<EOF >> .hg/hgrc
612 > [extensions]
612 > [extensions]
613 > dbgui = dbgui.py
613 > dbgui = dbgui.py
614 > EOF
614 > EOF
615
615
616 >>> from hgclient import check, readchannel, runcommand, stringio
616 >>> from hgclient import check, readchannel, runcommand, stringio
617 >>> @check
617 >>> @check
618 ... def getpass(server):
618 ... def getpass(server):
619 ... readchannel(server)
619 ... readchannel(server)
620 ... runcommand(server, ['debuggetpass', '--config',
620 ... runcommand(server, ['debuggetpass', '--config',
621 ... 'ui.interactive=True'],
621 ... 'ui.interactive=True'],
622 ... input=stringio('1234\n'))
622 ... input=stringio('1234\n'))
623 ... runcommand(server, ['debuggetpass', '--config',
623 ... runcommand(server, ['debuggetpass', '--config',
624 ... 'ui.interactive=True'],
624 ... 'ui.interactive=True'],
625 ... input=stringio('\n'))
625 ... input=stringio('\n'))
626 ... runcommand(server, ['debuggetpass', '--config',
626 ... runcommand(server, ['debuggetpass', '--config',
627 ... 'ui.interactive=True'],
627 ... 'ui.interactive=True'],
628 ... input=stringio(''))
628 ... input=stringio(''))
629 ... runcommand(server, ['debugprompt', '--config',
629 ... runcommand(server, ['debugprompt', '--config',
630 ... 'ui.interactive=True'],
630 ... 'ui.interactive=True'],
631 ... input=stringio('5678\n'))
631 ... input=stringio('5678\n'))
632 ... runcommand(server, ['debugreadstdin'])
632 ... runcommand(server, ['debugreadstdin'])
633 ... runcommand(server, ['debugwritestdout'])
633 ... runcommand(server, ['debugwritestdout'])
634 *** runcommand debuggetpass --config ui.interactive=True
634 *** runcommand debuggetpass --config ui.interactive=True
635 password: 1234
635 password: 1234
636 *** runcommand debuggetpass --config ui.interactive=True
636 *** runcommand debuggetpass --config ui.interactive=True
637 password:
637 password:
638 *** runcommand debuggetpass --config ui.interactive=True
638 *** runcommand debuggetpass --config ui.interactive=True
639 password: abort: response expected
639 password: abort: response expected
640 [255]
640 [255]
641 *** runcommand debugprompt --config ui.interactive=True
641 *** runcommand debugprompt --config ui.interactive=True
642 prompt: 5678
642 prompt: 5678
643 *** runcommand debugreadstdin
643 *** runcommand debugreadstdin
644 read: ''
644 read: ''
645 *** runcommand debugwritestdout
645 *** runcommand debugwritestdout
646
646
647
647
648 run commandserver in commandserver, which is silly but should work:
648 run commandserver in commandserver, which is silly but should work:
649
649
650 >>> from __future__ import print_function
650 >>> from __future__ import print_function
651 >>> from hgclient import check, readchannel, runcommand, stringio
651 >>> from hgclient import check, readchannel, runcommand, stringio
652 >>> @check
652 >>> @check
653 ... def nested(server):
653 ... def nested(server):
654 ... print('%c, %r' % readchannel(server))
654 ... print('%c, %r' % readchannel(server))
655 ... class nestedserver(object):
655 ... class nestedserver(object):
656 ... stdin = stringio('getencoding\n')
656 ... stdin = stringio('getencoding\n')
657 ... stdout = stringio()
657 ... stdout = stringio()
658 ... runcommand(server, ['serve', '--cmdserver', 'pipe'],
658 ... runcommand(server, ['serve', '--cmdserver', 'pipe'],
659 ... output=nestedserver.stdout, input=nestedserver.stdin)
659 ... output=nestedserver.stdout, input=nestedserver.stdin)
660 ... nestedserver.stdout.seek(0)
660 ... nestedserver.stdout.seek(0)
661 ... print('%c, %r' % readchannel(nestedserver)) # hello
661 ... print('%c, %r' % readchannel(nestedserver)) # hello
662 ... print('%c, %r' % readchannel(nestedserver)) # getencoding
662 ... print('%c, %r' % readchannel(nestedserver)) # getencoding
663 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
663 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
664 *** runcommand serve --cmdserver pipe
664 *** runcommand serve --cmdserver pipe
665 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
665 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
666 r, '*' (glob)
666 r, '*' (glob)
667
667
668
668
669 start without repository:
669 start without repository:
670
670
671 $ cd ..
671 $ cd ..
672
672
673 >>> from __future__ import print_function
673 >>> from __future__ import print_function
674 >>> from hgclient import check, readchannel, runcommand
674 >>> from hgclient import check, readchannel, runcommand
675 >>> @check
675 >>> @check
676 ... def hellomessage(server):
676 ... def hellomessage(server):
677 ... ch, data = readchannel(server)
677 ... ch, data = readchannel(server)
678 ... print('%c, %r' % (ch, data))
678 ... print('%c, %r' % (ch, data))
679 ... # run an arbitrary command to make sure the next thing the server
679 ... # run an arbitrary command to make sure the next thing the server
680 ... # sends isn't part of the hello message
680 ... # sends isn't part of the hello message
681 ... runcommand(server, ['id'])
681 ... runcommand(server, ['id'])
682 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
682 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
683 *** runcommand id
683 *** runcommand id
684 abort: there is no Mercurial repository here (.hg not found)
684 abort: there is no Mercurial repository here (.hg not found)
685 [255]
685 [255]
686
686
687 >>> from hgclient import check, readchannel, runcommand
687 >>> from hgclient import check, readchannel, runcommand
688 >>> @check
688 >>> @check
689 ... def startwithoutrepo(server):
689 ... def startwithoutrepo(server):
690 ... readchannel(server)
690 ... readchannel(server)
691 ... runcommand(server, ['init', 'repo2'])
691 ... runcommand(server, ['init', 'repo2'])
692 ... runcommand(server, ['id', '-R', 'repo2'])
692 ... runcommand(server, ['id', '-R', 'repo2'])
693 *** runcommand init repo2
693 *** runcommand init repo2
694 *** runcommand id -R repo2
694 *** runcommand id -R repo2
695 000000000000 tip
695 000000000000 tip
696
696
697
697
698 don't fall back to cwd if invalid -R path is specified (issue4805):
698 don't fall back to cwd if invalid -R path is specified (issue4805):
699
699
700 $ cd repo
700 $ cd repo
701 $ hg serve --cmdserver pipe -R ../nonexistent
701 $ hg serve --cmdserver pipe -R ../nonexistent
702 abort: repository ../nonexistent not found!
702 abort: repository ../nonexistent not found!
703 [255]
703 [255]
704 $ cd ..
704 $ cd ..
705
705
706
706
707 unix domain socket:
707 unix domain socket:
708
708
709 $ cd repo
709 $ cd repo
710 $ hg update -q
710 $ hg update -q
711
711
712 #if unix-socket unix-permissions
712 #if unix-socket unix-permissions
713
713
714 >>> from __future__ import print_function
714 >>> from __future__ import print_function
715 >>> from hgclient import check, readchannel, runcommand, stringio, unixserver
715 >>> from hgclient import check, readchannel, runcommand, stringio, unixserver
716 >>> server = unixserver('.hg/server.sock', '.hg/server.log')
716 >>> server = unixserver('.hg/server.sock', '.hg/server.log')
717 >>> def hellomessage(conn):
717 >>> def hellomessage(conn):
718 ... ch, data = readchannel(conn)
718 ... ch, data = readchannel(conn)
719 ... print('%c, %r' % (ch, data))
719 ... print('%c, %r' % (ch, data))
720 ... runcommand(conn, ['id'])
720 ... runcommand(conn, ['id'])
721 >>> check(hellomessage, server.connect)
721 >>> check(hellomessage, server.connect)
722 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
722 o, 'capabilities: getencoding runcommand\nencoding: *\npid: *' (glob)
723 *** runcommand id
723 *** runcommand id
724 eff892de26ec tip bm1/bm2/bm3
724 eff892de26ec tip bm1/bm2/bm3
725 >>> def unknowncommand(conn):
725 >>> def unknowncommand(conn):
726 ... readchannel(conn)
726 ... readchannel(conn)
727 ... conn.stdin.write('unknowncommand\n')
727 ... conn.stdin.write('unknowncommand\n')
728 >>> check(unknowncommand, server.connect) # error sent to server.log
728 >>> check(unknowncommand, server.connect) # error sent to server.log
729 >>> def serverinput(conn):
729 >>> def serverinput(conn):
730 ... readchannel(conn)
730 ... readchannel(conn)
731 ... patch = """
731 ... patch = """
732 ... # HG changeset patch
732 ... # HG changeset patch
733 ... # User test
733 ... # User test
734 ... # Date 0 0
734 ... # Date 0 0
735 ... 2
735 ... 2
736 ...
736 ...
737 ... diff -r eff892de26ec -r 1ed24be7e7a0 a
737 ... diff -r eff892de26ec -r 1ed24be7e7a0 a
738 ... --- a/a
738 ... --- a/a
739 ... +++ b/a
739 ... +++ b/a
740 ... @@ -1,1 +1,2 @@
740 ... @@ -1,1 +1,2 @@
741 ... 1
741 ... 1
742 ... +2
742 ... +2
743 ... """
743 ... """
744 ... runcommand(conn, ['import', '-'], input=stringio(patch))
744 ... runcommand(conn, ['import', '-'], input=stringio(patch))
745 ... runcommand(conn, ['log', '-rtip', '-q'])
745 ... runcommand(conn, ['log', '-rtip', '-q'])
746 >>> check(serverinput, server.connect)
746 >>> check(serverinput, server.connect)
747 *** runcommand import -
747 *** runcommand import -
748 applying patch from stdin
748 applying patch from stdin
749 *** runcommand log -rtip -q
749 *** runcommand log -rtip -q
750 2:1ed24be7e7a0
750 2:1ed24be7e7a0
751 >>> server.shutdown()
751 >>> server.shutdown()
752
752
753 $ cat .hg/server.log
753 $ cat .hg/server.log
754 listening at .hg/server.sock
754 listening at .hg/server.sock
755 abort: unknown command unknowncommand
755 abort: unknown command unknowncommand
756 killed!
756 killed!
757 $ rm .hg/server.log
757 $ rm .hg/server.log
758
758
759 if server crashed before hello, traceback will be sent to 'e' channel as
759 if server crashed before hello, traceback will be sent to 'e' channel as
760 last ditch:
760 last ditch:
761
761
762 $ cat <<EOF >> .hg/hgrc
762 $ cat <<EOF >> .hg/hgrc
763 > [cmdserver]
763 > [cmdserver]
764 > log = inexistent/path.log
764 > log = inexistent/path.log
765 > EOF
765 > EOF
766 >>> from __future__ import print_function
766 >>> from __future__ import print_function
767 >>> from hgclient import check, readchannel, unixserver
767 >>> from hgclient import check, readchannel, unixserver
768 >>> server = unixserver('.hg/server.sock', '.hg/server.log')
768 >>> server = unixserver('.hg/server.sock', '.hg/server.log')
769 >>> def earlycrash(conn):
769 >>> def earlycrash(conn):
770 ... while True:
770 ... while True:
771 ... try:
771 ... try:
772 ... ch, data = readchannel(conn)
772 ... ch, data = readchannel(conn)
773 ... if not data.startswith(' '):
773 ... if not data.startswith(' '):
774 ... print('%c, %r' % (ch, data))
774 ... print('%c, %r' % (ch, data))
775 ... except EOFError:
775 ... except EOFError:
776 ... break
776 ... break
777 >>> check(earlycrash, server.connect)
777 >>> check(earlycrash, server.connect)
778 e, 'Traceback (most recent call last):\n'
778 e, 'Traceback (most recent call last):\n'
779 e, "IOError: *" (glob)
779 e, "IOError: *" (glob)
780 >>> server.shutdown()
780 >>> server.shutdown()
781
781
782 $ cat .hg/server.log | grep -v '^ '
782 $ cat .hg/server.log | grep -v '^ '
783 listening at .hg/server.sock
783 listening at .hg/server.sock
784 Traceback (most recent call last):
784 Traceback (most recent call last):
785 IOError: * (glob)
785 IOError: * (glob)
786 killed!
786 killed!
787 #endif
787 #endif
788 #if no-unix-socket
788 #if no-unix-socket
789
789
790 $ hg serve --cmdserver unix -a .hg/server.sock
790 $ hg serve --cmdserver unix -a .hg/server.sock
791 abort: unsupported platform
791 abort: unsupported platform
792 [255]
792 [255]
793
793
794 #endif
794 #endif
795
795
796 $ cd ..
796 $ cd ..
797
797
798 Test that accessing to invalid changelog cache is avoided at
798 Test that accessing to invalid changelog cache is avoided at
799 subsequent operations even if repo object is reused even after failure
799 subsequent operations even if repo object is reused even after failure
800 of transaction (see 0a7610758c42 also)
800 of transaction (see 0a7610758c42 also)
801
801
802 "hg log" after failure of transaction is needed to detect invalid
802 "hg log" after failure of transaction is needed to detect invalid
803 cache in repoview: this can't detect by "hg verify" only.
803 cache in repoview: this can't detect by "hg verify" only.
804
804
805 Combination of "finalization" and "empty-ness of changelog" (2 x 2 =
805 Combination of "finalization" and "empty-ness of changelog" (2 x 2 =
806 4) are tested, because '00changelog.i' are differently changed in each
806 4) are tested, because '00changelog.i' are differently changed in each
807 cases.
807 cases.
808
808
809 $ cat > $TESTTMP/failafterfinalize.py <<EOF
809 $ cat > $TESTTMP/failafterfinalize.py <<EOF
810 > # extension to abort transaction after finalization forcibly
810 > # extension to abort transaction after finalization forcibly
811 > from mercurial import commands, error, extensions, lock as lockmod
811 > from mercurial import commands, error, extensions, lock as lockmod
812 > from mercurial import registrar
812 > from mercurial import registrar
813 > cmdtable = {}
813 > cmdtable = {}
814 > command = registrar.command(cmdtable)
814 > command = registrar.command(cmdtable)
815 > configtable = {}
815 > configtable = {}
816 > configitem = registrar.configitem(configtable)
816 > configitem = registrar.configitem(configtable)
817 > configitem('failafterfinalize', 'fail',
817 > configitem('failafterfinalize', 'fail',
818 > default=None,
818 > default=None,
819 > )
819 > )
820 > def fail(tr):
820 > def fail(tr):
821 > raise error.Abort('fail after finalization')
821 > raise error.Abort('fail after finalization')
822 > def reposetup(ui, repo):
822 > def reposetup(ui, repo):
823 > class failrepo(repo.__class__):
823 > class failrepo(repo.__class__):
824 > def commitctx(self, ctx, error=False):
824 > def commitctx(self, ctx, error=False):
825 > if self.ui.configbool('failafterfinalize', 'fail'):
825 > if self.ui.configbool('failafterfinalize', 'fail'):
826 > # 'sorted()' by ASCII code on category names causes
826 > # 'sorted()' by ASCII code on category names causes
827 > # invoking 'fail' after finalization of changelog
827 > # invoking 'fail' after finalization of changelog
828 > # using "'cl-%i' % id(self)" as category name
828 > # using "'cl-%i' % id(self)" as category name
829 > self.currenttransaction().addfinalize('zzzzzzzz', fail)
829 > self.currenttransaction().addfinalize('zzzzzzzz', fail)
830 > return super(failrepo, self).commitctx(ctx, error)
830 > return super(failrepo, self).commitctx(ctx, error)
831 > repo.__class__ = failrepo
831 > repo.__class__ = failrepo
832 > EOF
832 > EOF
833
833
834 $ hg init repo3
834 $ hg init repo3
835 $ cd repo3
835 $ cd repo3
836
836
837 $ cat <<EOF >> $HGRCPATH
837 $ cat <<EOF >> $HGRCPATH
838 > [ui]
838 > [ui]
839 > logtemplate = {rev} {desc|firstline} ({files})\n
839 > logtemplate = {rev} {desc|firstline} ({files})\n
840 >
840 >
841 > [extensions]
841 > [extensions]
842 > failafterfinalize = $TESTTMP/failafterfinalize.py
842 > failafterfinalize = $TESTTMP/failafterfinalize.py
843 > EOF
843 > EOF
844
844
845 - test failure with "empty changelog"
845 - test failure with "empty changelog"
846
846
847 $ echo foo > foo
847 $ echo foo > foo
848 $ hg add foo
848 $ hg add foo
849
849
850 (failure before finalization)
850 (failure before finalization)
851
851
852 >>> from hgclient import check, readchannel, runcommand
852 >>> from hgclient import check, readchannel, runcommand
853 >>> @check
853 >>> @check
854 ... def abort(server):
854 ... def abort(server):
855 ... readchannel(server)
855 ... readchannel(server)
856 ... runcommand(server, ['commit',
856 ... runcommand(server, ['commit',
857 ... '--config', 'hooks.pretxncommit=false',
857 ... '--config', 'hooks.pretxncommit=false',
858 ... '-mfoo'])
858 ... '-mfoo'])
859 ... runcommand(server, ['log'])
859 ... runcommand(server, ['log'])
860 ... runcommand(server, ['verify', '-q'])
860 ... runcommand(server, ['verify', '-q'])
861 *** runcommand commit --config hooks.pretxncommit=false -mfoo
861 *** runcommand commit --config hooks.pretxncommit=false -mfoo
862 transaction abort!
862 transaction abort!
863 rollback completed
863 rollback completed
864 abort: pretxncommit hook exited with status 1
864 abort: pretxncommit hook exited with status 1
865 [255]
865 [255]
866 *** runcommand log
866 *** runcommand log
867 *** runcommand verify -q
867 *** runcommand verify -q
868
868
869 (failure after finalization)
869 (failure after finalization)
870
870
871 >>> from hgclient import check, readchannel, runcommand
871 >>> from hgclient import check, readchannel, runcommand
872 >>> @check
872 >>> @check
873 ... def abort(server):
873 ... def abort(server):
874 ... readchannel(server)
874 ... readchannel(server)
875 ... runcommand(server, ['commit',
875 ... runcommand(server, ['commit',
876 ... '--config', 'failafterfinalize.fail=true',
876 ... '--config', 'failafterfinalize.fail=true',
877 ... '-mfoo'])
877 ... '-mfoo'])
878 ... runcommand(server, ['log'])
878 ... runcommand(server, ['log'])
879 ... runcommand(server, ['verify', '-q'])
879 ... runcommand(server, ['verify', '-q'])
880 *** runcommand commit --config failafterfinalize.fail=true -mfoo
880 *** runcommand commit --config failafterfinalize.fail=true -mfoo
881 transaction abort!
881 transaction abort!
882 rollback completed
882 rollback completed
883 abort: fail after finalization
883 abort: fail after finalization
884 [255]
884 [255]
885 *** runcommand log
885 *** runcommand log
886 *** runcommand verify -q
886 *** runcommand verify -q
887
887
888 - test failure with "not-empty changelog"
888 - test failure with "not-empty changelog"
889
889
890 $ echo bar > bar
890 $ echo bar > bar
891 $ hg add bar
891 $ hg add bar
892 $ hg commit -mbar bar
892 $ hg commit -mbar bar
893
893
894 (failure before finalization)
894 (failure before finalization)
895
895
896 >>> from hgclient import check, readchannel, runcommand
896 >>> from hgclient import check, readchannel, runcommand
897 >>> @check
897 >>> @check
898 ... def abort(server):
898 ... def abort(server):
899 ... readchannel(server)
899 ... readchannel(server)
900 ... runcommand(server, ['commit',
900 ... runcommand(server, ['commit',
901 ... '--config', 'hooks.pretxncommit=false',
901 ... '--config', 'hooks.pretxncommit=false',
902 ... '-mfoo', 'foo'])
902 ... '-mfoo', 'foo'])
903 ... runcommand(server, ['log'])
903 ... runcommand(server, ['log'])
904 ... runcommand(server, ['verify', '-q'])
904 ... runcommand(server, ['verify', '-q'])
905 *** runcommand commit --config hooks.pretxncommit=false -mfoo foo
905 *** runcommand commit --config hooks.pretxncommit=false -mfoo foo
906 transaction abort!
906 transaction abort!
907 rollback completed
907 rollback completed
908 abort: pretxncommit hook exited with status 1
908 abort: pretxncommit hook exited with status 1
909 [255]
909 [255]
910 *** runcommand log
910 *** runcommand log
911 0 bar (bar)
911 0 bar (bar)
912 *** runcommand verify -q
912 *** runcommand verify -q
913
913
914 (failure after finalization)
914 (failure after finalization)
915
915
916 >>> from hgclient import check, readchannel, runcommand
916 >>> from hgclient import check, readchannel, runcommand
917 >>> @check
917 >>> @check
918 ... def abort(server):
918 ... def abort(server):
919 ... readchannel(server)
919 ... readchannel(server)
920 ... runcommand(server, ['commit',
920 ... runcommand(server, ['commit',
921 ... '--config', 'failafterfinalize.fail=true',
921 ... '--config', 'failafterfinalize.fail=true',
922 ... '-mfoo', 'foo'])
922 ... '-mfoo', 'foo'])
923 ... runcommand(server, ['log'])
923 ... runcommand(server, ['log'])
924 ... runcommand(server, ['verify', '-q'])
924 ... runcommand(server, ['verify', '-q'])
925 *** runcommand commit --config failafterfinalize.fail=true -mfoo foo
925 *** runcommand commit --config failafterfinalize.fail=true -mfoo foo
926 transaction abort!
926 transaction abort!
927 rollback completed
927 rollback completed
928 abort: fail after finalization
928 abort: fail after finalization
929 [255]
929 [255]
930 *** runcommand log
930 *** runcommand log
931 0 bar (bar)
931 0 bar (bar)
932 *** runcommand verify -q
932 *** runcommand verify -q
933
933
934 $ cd ..
934 $ cd ..
935
935
936 Test symlink traversal over cached audited paths:
936 Test symlink traversal over cached audited paths:
937 -------------------------------------------------
937 -------------------------------------------------
938
938
939 #if symlink
939 #if symlink
940
940
941 set up symlink hell
941 set up symlink hell
942
942
943 $ mkdir merge-symlink-out
943 $ mkdir merge-symlink-out
944 $ hg init merge-symlink
944 $ hg init merge-symlink
945 $ cd merge-symlink
945 $ cd merge-symlink
946 $ touch base
946 $ touch base
947 $ hg commit -qAm base
947 $ hg commit -qAm base
948 $ ln -s ../merge-symlink-out a
948 $ ln -s ../merge-symlink-out a
949 $ hg commit -qAm 'symlink a -> ../merge-symlink-out'
949 $ hg commit -qAm 'symlink a -> ../merge-symlink-out'
950 $ hg up -q 0
950 $ hg up -q 0
951 $ mkdir a
951 $ mkdir a
952 $ touch a/poisoned
952 $ touch a/poisoned
953 $ hg commit -qAm 'file a/poisoned'
953 $ hg commit -qAm 'file a/poisoned'
954 $ hg log -G -T '{rev}: {desc}\n'
954 $ hg log -G -T '{rev}: {desc}\n'
955 @ 2: file a/poisoned
955 @ 2: file a/poisoned
956 |
956 |
957 | o 1: symlink a -> ../merge-symlink-out
957 | o 1: symlink a -> ../merge-symlink-out
958 |/
958 |/
959 o 0: base
959 o 0: base
960
960
961
961
962 try trivial merge after update: cache of audited paths should be discarded,
962 try trivial merge after update: cache of audited paths should be discarded,
963 and the merge should fail (issue5628)
963 and the merge should fail (issue5628)
964
964
965 $ hg up -q null
965 $ hg up -q null
966 >>> from hgclient import check, readchannel, runcommand
966 >>> from hgclient import check, readchannel, runcommand
967 >>> @check
967 >>> @check
968 ... def merge(server):
968 ... def merge(server):
969 ... readchannel(server)
969 ... readchannel(server)
970 ... # audit a/poisoned as a good path
970 ... # audit a/poisoned as a good path
971 ... runcommand(server, ['up', '-qC', '2'])
971 ... runcommand(server, ['up', '-qC', '2'])
972 ... runcommand(server, ['up', '-qC', '1'])
972 ... runcommand(server, ['up', '-qC', '1'])
973 ... # here a is a symlink, so a/poisoned is bad
973 ... # here a is a symlink, so a/poisoned is bad
974 ... runcommand(server, ['merge', '2'])
974 ... runcommand(server, ['merge', '2'])
975 *** runcommand up -qC 2
975 *** runcommand up -qC 2
976 *** runcommand up -qC 1
976 *** runcommand up -qC 1
977 *** runcommand merge 2
977 *** runcommand merge 2
978 a: path conflict - a file or link has the same name as a directory
978 a: path conflict - a file or link has the same name as a directory
979 the local file has been renamed to a~aa04623eb0c3
979 the local file has been renamed to a~aa04623eb0c3
980 resolve manually then use 'hg resolve --mark a'
980 resolve manually then use 'hg resolve --mark a'
981 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
981 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
982 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
982 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
983 [1]
983 [1]
984 $ ls ../merge-symlink-out
984 $ ls ../merge-symlink-out
985
985
986 cache of repo.auditor should be discarded, so matcher would never traverse
986 cache of repo.auditor should be discarded, so matcher would never traverse
987 symlinks:
987 symlinks:
988
988
989 $ hg up -qC 0
989 $ hg up -qC 0
990 $ touch ../merge-symlink-out/poisoned
990 $ touch ../merge-symlink-out/poisoned
991 >>> from hgclient import check, readchannel, runcommand
991 >>> from hgclient import check, readchannel, runcommand
992 >>> @check
992 >>> @check
993 ... def files(server):
993 ... def files(server):
994 ... readchannel(server)
994 ... readchannel(server)
995 ... runcommand(server, ['up', '-qC', '2'])
995 ... runcommand(server, ['up', '-qC', '2'])
996 ... # audit a/poisoned as a good path
996 ... # audit a/poisoned as a good path
997 ... runcommand(server, ['files', 'a/poisoned'])
997 ... runcommand(server, ['files', 'a/poisoned'])
998 ... runcommand(server, ['up', '-qC', '0'])
998 ... runcommand(server, ['up', '-qC', '0'])
999 ... runcommand(server, ['up', '-qC', '1'])
999 ... runcommand(server, ['up', '-qC', '1'])
1000 ... # here 'a' is a symlink, so a/poisoned should be warned
1000 ... # here 'a' is a symlink, so a/poisoned should be warned
1001 ... runcommand(server, ['files', 'a/poisoned'])
1001 ... runcommand(server, ['files', 'a/poisoned'])
1002 *** runcommand up -qC 2
1002 *** runcommand up -qC 2
1003 *** runcommand files a/poisoned
1003 *** runcommand files a/poisoned
1004 a/poisoned
1004 a/poisoned
1005 *** runcommand up -qC 0
1005 *** runcommand up -qC 0
1006 *** runcommand up -qC 1
1006 *** runcommand up -qC 1
1007 *** runcommand files a/poisoned
1007 *** runcommand files a/poisoned
1008 abort: path 'a/poisoned' traverses symbolic link 'a'
1008 abort: path 'a/poisoned' traverses symbolic link 'a'
1009 [255]
1009 [255]
1010
1010
1011 $ cd ..
1011 $ cd ..
1012
1012
1013 #endif
1013 #endif
@@ -1,2545 +1,2545 b''
1 This test file test the various templates related to obsmarkers.
1 This test file test the various templates related to obsmarkers.
2
2
3 Global setup
3 Global setup
4 ============
4 ============
5
5
6 $ . $TESTDIR/testlib/obsmarker-common.sh
6 $ . $TESTDIR/testlib/obsmarker-common.sh
7 $ cat >> $HGRCPATH <<EOF
7 $ cat >> $HGRCPATH <<EOF
8 > [ui]
8 > [ui]
9 > interactive = true
9 > interactive = true
10 > [phases]
10 > [phases]
11 > publish=False
11 > publish=False
12 > [experimental]
12 > [experimental]
13 > evolution=true
13 > evolution=true
14 > [templates]
14 > [templates]
15 > obsfatesuccessors = "{if(successors, " as ")}{join(successors, ", ")}"
15 > obsfatesuccessors = "{if(successors, " as ")}{join(successors, ", ")}"
16 > obsfateverb = "{obsfateverb(successors)}"
16 > obsfateverb = "{obsfateverb(successors)}"
17 > obsfateoperations = "{if(obsfateoperations(markers), " using {join(obsfateoperations(markers), ", ")}")}"
17 > obsfateoperations = "{if(obsfateoperations(markers), " using {join(obsfateoperations(markers), ", ")}")}"
18 > obsfateusers = "{if(obsfateusers(markers), " by {join(obsfateusers(markers), ", ")}")}"
18 > obsfateusers = "{if(obsfateusers(markers), " by {join(obsfateusers(markers), ", ")}")}"
19 > obsfatedate = "{if(obsfatedate(markers), "{ifeq(min(obsfatedate(markers)), max(obsfatedate(markers)), " (at {min(obsfatedate(markers))|isodate})", " (between {min(obsfatedate(markers))|isodate} and {max(obsfatedate(markers))|isodate})")}")}"
19 > obsfatedate = "{if(obsfatedate(markers), "{ifeq(min(obsfatedate(markers)), max(obsfatedate(markers)), " (at {min(obsfatedate(markers))|isodate})", " (between {min(obsfatedate(markers))|isodate} and {max(obsfatedate(markers))|isodate})")}")}"
20 > obsfatetempl = "{obsfateverb}{obsfateoperations}{obsfatesuccessors}{obsfateusers}{obsfatedate}; "
20 > obsfatetempl = "{obsfateverb}{obsfateoperations}{obsfatesuccessors}{obsfateusers}{obsfatedate}; "
21 > [alias]
21 > [alias]
22 > tlog = log -G -T '{node|short}\
22 > tlog = log -G -T '{node|short}\
23 > {if(predecessors, "\n Predecessors: {predecessors}")}\
23 > {if(predecessors, "\n Predecessors: {predecessors}")}\
24 > {if(predecessors, "\n semi-colon: {join(predecessors, "; ")}")}\
24 > {if(predecessors, "\n semi-colon: {join(predecessors, "; ")}")}\
25 > {if(predecessors, "\n json: {predecessors|json}")}\
25 > {if(predecessors, "\n json: {predecessors|json}")}\
26 > {if(predecessors, "\n map: {join(predecessors % "{rev}:{node}", " ")}")}\
26 > {if(predecessors, "\n map: {join(predecessors % "{rev}:{node}", " ")}")}\
27 > {if(successorssets, "\n Successors: {successorssets}")}\
27 > {if(successorssets, "\n Successors: {successorssets}")}\
28 > {if(successorssets, "\n multi-line: {join(successorssets, "\n multi-line: ")}")}\
28 > {if(successorssets, "\n multi-line: {join(successorssets, "\n multi-line: ")}")}\
29 > {if(successorssets, "\n json: {successorssets|json}")}\n'
29 > {if(successorssets, "\n json: {successorssets|json}")}\n'
30 > fatelog = log -G -T '{node|short}\n{if(succsandmarkers, " Obsfate: {succsandmarkers % "{obsfatetempl}"} \n" )}'
30 > fatelog = log -G -T '{node|short}\n{if(succsandmarkers, " Obsfate: {succsandmarkers % "{obsfatetempl}"} \n" )}'
31 > fatelogjson = log -G -T '{node|short}\n{if(succsandmarkers, " Obsfate: {succsandmarkers|json}\n")}'
31 > fatelogjson = log -G -T '{node|short}\n{if(succsandmarkers, " Obsfate: {succsandmarkers|json}\n")}'
32 > fatelogkw = log -G -T '{node|short}\n{if(obsfate, "{obsfate % " Obsfate: {fate}\n"}")}'
32 > fatelogkw = log -G -T '{node|short}\n{if(obsfate, "{obsfate % " Obsfate: {fate}\n"}")}'
33 > EOF
33 > EOF
34
34
35 Test templates on amended commit
35 Test templates on amended commit
36 ================================
36 ================================
37
37
38 Test setup
38 Test setup
39 ----------
39 ----------
40
40
41 $ hg init $TESTTMP/templates-local-amend
41 $ hg init $TESTTMP/templates-local-amend
42 $ cd $TESTTMP/templates-local-amend
42 $ cd $TESTTMP/templates-local-amend
43 $ mkcommit ROOT
43 $ mkcommit ROOT
44 $ mkcommit A0
44 $ mkcommit A0
45 $ echo 42 >> A0
45 $ echo 42 >> A0
46 $ hg commit --amend -m "A1" --config devel.default-date="1234567890 0"
46 $ hg commit --amend -m "A1" --config devel.default-date="1234567890 0"
47 $ hg commit --amend -m "A2" --config devel.default-date="987654321 0" --config devel.user.obsmarker=test2
47 $ hg commit --amend -m "A2" --config devel.default-date="987654321 0" --config devel.user.obsmarker=test2
48
48
49 $ hg log --hidden -G
49 $ hg log --hidden -G
50 @ changeset: 3:d004c8f274b9
50 @ changeset: 3:d004c8f274b9
51 | tag: tip
51 | tag: tip
52 | parent: 0:ea207398892e
52 | parent: 0:ea207398892e
53 | user: test
53 | user: test
54 | date: Thu Jan 01 00:00:00 1970 +0000
54 | date: Thu Jan 01 00:00:00 1970 +0000
55 | summary: A2
55 | summary: A2
56 |
56 |
57 | x changeset: 2:a468dc9b3633
57 | x changeset: 2:a468dc9b3633
58 |/ parent: 0:ea207398892e
58 |/ parent: 0:ea207398892e
59 | user: test
59 | user: test
60 | date: Thu Jan 01 00:00:00 1970 +0000
60 | date: Thu Jan 01 00:00:00 1970 +0000
61 | obsfate: rewritten using amend as 3:d004c8f274b9 by test2
61 | obsolete: rewritten using amend as 3:d004c8f274b9 by test2
62 | summary: A1
62 | summary: A1
63 |
63 |
64 | x changeset: 1:471f378eab4c
64 | x changeset: 1:471f378eab4c
65 |/ user: test
65 |/ user: test
66 | date: Thu Jan 01 00:00:00 1970 +0000
66 | date: Thu Jan 01 00:00:00 1970 +0000
67 | obsfate: rewritten using amend as 2:a468dc9b3633
67 | obsolete: rewritten using amend as 2:a468dc9b3633
68 | summary: A0
68 | summary: A0
69 |
69 |
70 o changeset: 0:ea207398892e
70 o changeset: 0:ea207398892e
71 user: test
71 user: test
72 date: Thu Jan 01 00:00:00 1970 +0000
72 date: Thu Jan 01 00:00:00 1970 +0000
73 summary: ROOT
73 summary: ROOT
74
74
75 Check templates
75 Check templates
76 ---------------
76 ---------------
77 $ hg up 'desc(A0)' --hidden
77 $ hg up 'desc(A0)' --hidden
78 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
78 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
79
79
80 Predecessors template should show current revision as it is the working copy
80 Predecessors template should show current revision as it is the working copy
81 $ hg tlog
81 $ hg tlog
82 o d004c8f274b9
82 o d004c8f274b9
83 | Predecessors: 1:471f378eab4c
83 | Predecessors: 1:471f378eab4c
84 | semi-colon: 1:471f378eab4c
84 | semi-colon: 1:471f378eab4c
85 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
85 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
86 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
86 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
87 | @ 471f378eab4c
87 | @ 471f378eab4c
88 |/ Successors: 3:d004c8f274b9
88 |/ Successors: 3:d004c8f274b9
89 | multi-line: 3:d004c8f274b9
89 | multi-line: 3:d004c8f274b9
90 | json: [["d004c8f274b9ec480a47a93c10dac5eee63adb78"]]
90 | json: [["d004c8f274b9ec480a47a93c10dac5eee63adb78"]]
91 o ea207398892e
91 o ea207398892e
92
92
93 $ hg fatelog
93 $ hg fatelog
94 o d004c8f274b9
94 o d004c8f274b9
95 |
95 |
96 | @ 471f378eab4c
96 | @ 471f378eab4c
97 |/ Obsfate: rewritten using amend as 3:d004c8f274b9 by test, test2 (between 2001-04-19 04:25 +0000 and 2009-02-13 23:31 +0000);
97 |/ Obsfate: rewritten using amend as 3:d004c8f274b9 by test, test2 (between 2001-04-19 04:25 +0000 and 2009-02-13 23:31 +0000);
98 o ea207398892e
98 o ea207398892e
99
99
100
100
101 $ hg fatelogkw
101 $ hg fatelogkw
102 o d004c8f274b9
102 o d004c8f274b9
103 |
103 |
104 | @ 471f378eab4c
104 | @ 471f378eab4c
105 |/ Obsfate: rewritten using amend as 3:d004c8f274b9 by test, test2
105 |/ Obsfate: rewritten using amend as 3:d004c8f274b9 by test, test2
106 o ea207398892e
106 o ea207398892e
107
107
108
108
109 $ hg log -G --config ui.logtemplate=
109 $ hg log -G --config ui.logtemplate=
110 o changeset: 3:d004c8f274b9
110 o changeset: 3:d004c8f274b9
111 | tag: tip
111 | tag: tip
112 | parent: 0:ea207398892e
112 | parent: 0:ea207398892e
113 | user: test
113 | user: test
114 | date: Thu Jan 01 00:00:00 1970 +0000
114 | date: Thu Jan 01 00:00:00 1970 +0000
115 | summary: A2
115 | summary: A2
116 |
116 |
117 | @ changeset: 1:471f378eab4c
117 | @ changeset: 1:471f378eab4c
118 |/ user: test
118 |/ user: test
119 | date: Thu Jan 01 00:00:00 1970 +0000
119 | date: Thu Jan 01 00:00:00 1970 +0000
120 | obsfate: rewritten using amend as 3:d004c8f274b9 by test, test2
120 | obsolete: rewritten using amend as 3:d004c8f274b9 by test, test2
121 | summary: A0
121 | summary: A0
122 |
122 |
123 o changeset: 0:ea207398892e
123 o changeset: 0:ea207398892e
124 user: test
124 user: test
125 date: Thu Jan 01 00:00:00 1970 +0000
125 date: Thu Jan 01 00:00:00 1970 +0000
126 summary: ROOT
126 summary: ROOT
127
127
128
128
129 $ hg log -G -T "default"
129 $ hg log -G -T "default"
130 o changeset: 3:d004c8f274b9
130 o changeset: 3:d004c8f274b9
131 | tag: tip
131 | tag: tip
132 | parent: 0:ea207398892e
132 | parent: 0:ea207398892e
133 | user: test
133 | user: test
134 | date: Thu Jan 01 00:00:00 1970 +0000
134 | date: Thu Jan 01 00:00:00 1970 +0000
135 | summary: A2
135 | summary: A2
136 |
136 |
137 | @ changeset: 1:471f378eab4c
137 | @ changeset: 1:471f378eab4c
138 |/ user: test
138 |/ user: test
139 | date: Thu Jan 01 00:00:00 1970 +0000
139 | date: Thu Jan 01 00:00:00 1970 +0000
140 | obsfate: rewritten using amend as 3:d004c8f274b9 by test, test2
140 | obsfate: rewritten using amend as 3:d004c8f274b9 by test, test2
141 | summary: A0
141 | summary: A0
142 |
142 |
143 o changeset: 0:ea207398892e
143 o changeset: 0:ea207398892e
144 user: test
144 user: test
145 date: Thu Jan 01 00:00:00 1970 +0000
145 date: Thu Jan 01 00:00:00 1970 +0000
146 summary: ROOT
146 summary: ROOT
147
147
148 $ hg up 'desc(A1)' --hidden
148 $ hg up 'desc(A1)' --hidden
149 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
149 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
150
150
151 Predecessors template should show current revision as it is the working copy
151 Predecessors template should show current revision as it is the working copy
152 $ hg tlog
152 $ hg tlog
153 o d004c8f274b9
153 o d004c8f274b9
154 | Predecessors: 2:a468dc9b3633
154 | Predecessors: 2:a468dc9b3633
155 | semi-colon: 2:a468dc9b3633
155 | semi-colon: 2:a468dc9b3633
156 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
156 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
157 | map: 2:a468dc9b36338b14fdb7825f55ce3df4e71517ad
157 | map: 2:a468dc9b36338b14fdb7825f55ce3df4e71517ad
158 | @ a468dc9b3633
158 | @ a468dc9b3633
159 |/ Successors: 3:d004c8f274b9
159 |/ Successors: 3:d004c8f274b9
160 | multi-line: 3:d004c8f274b9
160 | multi-line: 3:d004c8f274b9
161 | json: [["d004c8f274b9ec480a47a93c10dac5eee63adb78"]]
161 | json: [["d004c8f274b9ec480a47a93c10dac5eee63adb78"]]
162 o ea207398892e
162 o ea207398892e
163
163
164 $ hg fatelog
164 $ hg fatelog
165 o d004c8f274b9
165 o d004c8f274b9
166 |
166 |
167 | @ a468dc9b3633
167 | @ a468dc9b3633
168 |/ Obsfate: rewritten using amend as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000);
168 |/ Obsfate: rewritten using amend as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000);
169 o ea207398892e
169 o ea207398892e
170
170
171 Predecessors template should show all the predecessors as we force their display
171 Predecessors template should show all the predecessors as we force their display
172 with --hidden
172 with --hidden
173 $ hg tlog --hidden
173 $ hg tlog --hidden
174 o d004c8f274b9
174 o d004c8f274b9
175 | Predecessors: 2:a468dc9b3633
175 | Predecessors: 2:a468dc9b3633
176 | semi-colon: 2:a468dc9b3633
176 | semi-colon: 2:a468dc9b3633
177 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
177 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
178 | map: 2:a468dc9b36338b14fdb7825f55ce3df4e71517ad
178 | map: 2:a468dc9b36338b14fdb7825f55ce3df4e71517ad
179 | @ a468dc9b3633
179 | @ a468dc9b3633
180 |/ Predecessors: 1:471f378eab4c
180 |/ Predecessors: 1:471f378eab4c
181 | semi-colon: 1:471f378eab4c
181 | semi-colon: 1:471f378eab4c
182 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
182 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
183 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
183 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
184 | Successors: 3:d004c8f274b9
184 | Successors: 3:d004c8f274b9
185 | multi-line: 3:d004c8f274b9
185 | multi-line: 3:d004c8f274b9
186 | json: [["d004c8f274b9ec480a47a93c10dac5eee63adb78"]]
186 | json: [["d004c8f274b9ec480a47a93c10dac5eee63adb78"]]
187 | x 471f378eab4c
187 | x 471f378eab4c
188 |/ Successors: 2:a468dc9b3633
188 |/ Successors: 2:a468dc9b3633
189 | multi-line: 2:a468dc9b3633
189 | multi-line: 2:a468dc9b3633
190 | json: [["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]]
190 | json: [["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]]
191 o ea207398892e
191 o ea207398892e
192
192
193 $ hg fatelog --hidden
193 $ hg fatelog --hidden
194 o d004c8f274b9
194 o d004c8f274b9
195 |
195 |
196 | @ a468dc9b3633
196 | @ a468dc9b3633
197 |/ Obsfate: rewritten using amend as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000);
197 |/ Obsfate: rewritten using amend as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000);
198 | x 471f378eab4c
198 | x 471f378eab4c
199 |/ Obsfate: rewritten using amend as 2:a468dc9b3633 by test (at 2009-02-13 23:31 +0000);
199 |/ Obsfate: rewritten using amend as 2:a468dc9b3633 by test (at 2009-02-13 23:31 +0000);
200 o ea207398892e
200 o ea207398892e
201
201
202
202
203 Predecessors template shouldn't show anything as all obsolete commit are not
203 Predecessors template shouldn't show anything as all obsolete commit are not
204 visible.
204 visible.
205 $ hg up 'desc(A2)'
205 $ hg up 'desc(A2)'
206 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
207 $ hg tlog
207 $ hg tlog
208 @ d004c8f274b9
208 @ d004c8f274b9
209 |
209 |
210 o ea207398892e
210 o ea207398892e
211
211
212 $ hg tlog --hidden
212 $ hg tlog --hidden
213 @ d004c8f274b9
213 @ d004c8f274b9
214 | Predecessors: 2:a468dc9b3633
214 | Predecessors: 2:a468dc9b3633
215 | semi-colon: 2:a468dc9b3633
215 | semi-colon: 2:a468dc9b3633
216 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
216 | json: ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]
217 | map: 2:a468dc9b36338b14fdb7825f55ce3df4e71517ad
217 | map: 2:a468dc9b36338b14fdb7825f55ce3df4e71517ad
218 | x a468dc9b3633
218 | x a468dc9b3633
219 |/ Predecessors: 1:471f378eab4c
219 |/ Predecessors: 1:471f378eab4c
220 | semi-colon: 1:471f378eab4c
220 | semi-colon: 1:471f378eab4c
221 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
221 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
222 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
222 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
223 | Successors: 3:d004c8f274b9
223 | Successors: 3:d004c8f274b9
224 | multi-line: 3:d004c8f274b9
224 | multi-line: 3:d004c8f274b9
225 | json: [["d004c8f274b9ec480a47a93c10dac5eee63adb78"]]
225 | json: [["d004c8f274b9ec480a47a93c10dac5eee63adb78"]]
226 | x 471f378eab4c
226 | x 471f378eab4c
227 |/ Successors: 2:a468dc9b3633
227 |/ Successors: 2:a468dc9b3633
228 | multi-line: 2:a468dc9b3633
228 | multi-line: 2:a468dc9b3633
229 | json: [["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]]
229 | json: [["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]]
230 o ea207398892e
230 o ea207398892e
231
231
232 $ hg fatelog
232 $ hg fatelog
233 @ d004c8f274b9
233 @ d004c8f274b9
234 |
234 |
235 o ea207398892e
235 o ea207398892e
236
236
237
237
238 $ hg fatelog --hidden
238 $ hg fatelog --hidden
239 @ d004c8f274b9
239 @ d004c8f274b9
240 |
240 |
241 | x a468dc9b3633
241 | x a468dc9b3633
242 |/ Obsfate: rewritten using amend as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000);
242 |/ Obsfate: rewritten using amend as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000);
243 | x 471f378eab4c
243 | x 471f378eab4c
244 |/ Obsfate: rewritten using amend as 2:a468dc9b3633 by test (at 2009-02-13 23:31 +0000);
244 |/ Obsfate: rewritten using amend as 2:a468dc9b3633 by test (at 2009-02-13 23:31 +0000);
245 o ea207398892e
245 o ea207398892e
246
246
247 $ hg fatelogjson --hidden
247 $ hg fatelogjson --hidden
248 @ d004c8f274b9
248 @ d004c8f274b9
249 |
249 |
250 | x a468dc9b3633
250 | x a468dc9b3633
251 |/ Obsfate: [{"markers": [["a468dc9b36338b14fdb7825f55ce3df4e71517ad", ["d004c8f274b9ec480a47a93c10dac5eee63adb78"], 0, [["operation", "amend"], ["user", "test2"]], [987654321.0, 0], null]], "successors": ["d004c8f274b9ec480a47a93c10dac5eee63adb78"]}]
251 |/ Obsfate: [{"markers": [["a468dc9b36338b14fdb7825f55ce3df4e71517ad", ["d004c8f274b9ec480a47a93c10dac5eee63adb78"], 0, [["operation", "amend"], ["user", "test2"]], [987654321.0, 0], null]], "successors": ["d004c8f274b9ec480a47a93c10dac5eee63adb78"]}]
252 | x 471f378eab4c
252 | x 471f378eab4c
253 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"], 0, [["operation", "amend"], ["user", "test"]], [1234567890.0, 0], null]], "successors": ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]}]
253 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"], 0, [["operation", "amend"], ["user", "test"]], [1234567890.0, 0], null]], "successors": ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"]}]
254 o ea207398892e
254 o ea207398892e
255
255
256
256
257 Check other fatelog implementations
257 Check other fatelog implementations
258 -----------------------------------
258 -----------------------------------
259
259
260 $ hg fatelogkw --hidden -q
260 $ hg fatelogkw --hidden -q
261 @ d004c8f274b9
261 @ d004c8f274b9
262 |
262 |
263 | x a468dc9b3633
263 | x a468dc9b3633
264 |/ Obsfate: rewritten using amend as 3:d004c8f274b9
264 |/ Obsfate: rewritten using amend as 3:d004c8f274b9
265 | x 471f378eab4c
265 | x 471f378eab4c
266 |/ Obsfate: rewritten using amend as 2:a468dc9b3633
266 |/ Obsfate: rewritten using amend as 2:a468dc9b3633
267 o ea207398892e
267 o ea207398892e
268
268
269 $ hg fatelogkw --hidden
269 $ hg fatelogkw --hidden
270 @ d004c8f274b9
270 @ d004c8f274b9
271 |
271 |
272 | x a468dc9b3633
272 | x a468dc9b3633
273 |/ Obsfate: rewritten using amend as 3:d004c8f274b9 by test2
273 |/ Obsfate: rewritten using amend as 3:d004c8f274b9 by test2
274 | x 471f378eab4c
274 | x 471f378eab4c
275 |/ Obsfate: rewritten using amend as 2:a468dc9b3633
275 |/ Obsfate: rewritten using amend as 2:a468dc9b3633
276 o ea207398892e
276 o ea207398892e
277
277
278 $ hg fatelogkw --hidden -v
278 $ hg fatelogkw --hidden -v
279 @ d004c8f274b9
279 @ d004c8f274b9
280 |
280 |
281 | x a468dc9b3633
281 | x a468dc9b3633
282 |/ Obsfate: rewritten using amend as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000)
282 |/ Obsfate: rewritten using amend as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000)
283 | x 471f378eab4c
283 | x 471f378eab4c
284 |/ Obsfate: rewritten using amend as 2:a468dc9b3633 by test (at 2009-02-13 23:31 +0000)
284 |/ Obsfate: rewritten using amend as 2:a468dc9b3633 by test (at 2009-02-13 23:31 +0000)
285 o ea207398892e
285 o ea207398892e
286
286
287
287
288 $ hg log -G -T "default" --hidden
288 $ hg log -G -T "default" --hidden
289 @ changeset: 3:d004c8f274b9
289 @ changeset: 3:d004c8f274b9
290 | tag: tip
290 | tag: tip
291 | parent: 0:ea207398892e
291 | parent: 0:ea207398892e
292 | user: test
292 | user: test
293 | date: Thu Jan 01 00:00:00 1970 +0000
293 | date: Thu Jan 01 00:00:00 1970 +0000
294 | summary: A2
294 | summary: A2
295 |
295 |
296 | x changeset: 2:a468dc9b3633
296 | x changeset: 2:a468dc9b3633
297 |/ parent: 0:ea207398892e
297 |/ parent: 0:ea207398892e
298 | user: test
298 | user: test
299 | date: Thu Jan 01 00:00:00 1970 +0000
299 | date: Thu Jan 01 00:00:00 1970 +0000
300 | obsfate: rewritten using amend as 3:d004c8f274b9 by test2
300 | obsfate: rewritten using amend as 3:d004c8f274b9 by test2
301 | summary: A1
301 | summary: A1
302 |
302 |
303 | x changeset: 1:471f378eab4c
303 | x changeset: 1:471f378eab4c
304 |/ user: test
304 |/ user: test
305 | date: Thu Jan 01 00:00:00 1970 +0000
305 | date: Thu Jan 01 00:00:00 1970 +0000
306 | obsfate: rewritten using amend as 2:a468dc9b3633
306 | obsfate: rewritten using amend as 2:a468dc9b3633
307 | summary: A0
307 | summary: A0
308 |
308 |
309 o changeset: 0:ea207398892e
309 o changeset: 0:ea207398892e
310 user: test
310 user: test
311 date: Thu Jan 01 00:00:00 1970 +0000
311 date: Thu Jan 01 00:00:00 1970 +0000
312 summary: ROOT
312 summary: ROOT
313
313
314 $ hg log -G -T "default" --hidden -v
314 $ hg log -G -T "default" --hidden -v
315 @ changeset: 3:d004c8f274b9
315 @ changeset: 3:d004c8f274b9
316 | tag: tip
316 | tag: tip
317 | parent: 0:ea207398892e
317 | parent: 0:ea207398892e
318 | user: test
318 | user: test
319 | date: Thu Jan 01 00:00:00 1970 +0000
319 | date: Thu Jan 01 00:00:00 1970 +0000
320 | files: A0
320 | files: A0
321 | description:
321 | description:
322 | A2
322 | A2
323 |
323 |
324 |
324 |
325 | x changeset: 2:a468dc9b3633
325 | x changeset: 2:a468dc9b3633
326 |/ parent: 0:ea207398892e
326 |/ parent: 0:ea207398892e
327 | user: test
327 | user: test
328 | date: Thu Jan 01 00:00:00 1970 +0000
328 | date: Thu Jan 01 00:00:00 1970 +0000
329 | obsfate: rewritten using amend as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000)
329 | obsfate: rewritten using amend as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000)
330 | files: A0
330 | files: A0
331 | description:
331 | description:
332 | A1
332 | A1
333 |
333 |
334 |
334 |
335 | x changeset: 1:471f378eab4c
335 | x changeset: 1:471f378eab4c
336 |/ user: test
336 |/ user: test
337 | date: Thu Jan 01 00:00:00 1970 +0000
337 | date: Thu Jan 01 00:00:00 1970 +0000
338 | obsfate: rewritten using amend as 2:a468dc9b3633 by test (at 2009-02-13 23:31 +0000)
338 | obsfate: rewritten using amend as 2:a468dc9b3633 by test (at 2009-02-13 23:31 +0000)
339 | files: A0
339 | files: A0
340 | description:
340 | description:
341 | A0
341 | A0
342 |
342 |
343 |
343 |
344 o changeset: 0:ea207398892e
344 o changeset: 0:ea207398892e
345 user: test
345 user: test
346 date: Thu Jan 01 00:00:00 1970 +0000
346 date: Thu Jan 01 00:00:00 1970 +0000
347 files: ROOT
347 files: ROOT
348 description:
348 description:
349 ROOT
349 ROOT
350
350
351
351
352 Test templates with splitted commit
352 Test templates with splitted commit
353 ===================================
353 ===================================
354
354
355 $ hg init $TESTTMP/templates-local-split
355 $ hg init $TESTTMP/templates-local-split
356 $ cd $TESTTMP/templates-local-split
356 $ cd $TESTTMP/templates-local-split
357 $ mkcommit ROOT
357 $ mkcommit ROOT
358 $ echo 42 >> a
358 $ echo 42 >> a
359 $ echo 43 >> b
359 $ echo 43 >> b
360 $ hg commit -A -m "A0"
360 $ hg commit -A -m "A0"
361 adding a
361 adding a
362 adding b
362 adding b
363 $ hg log --hidden -G
363 $ hg log --hidden -G
364 @ changeset: 1:471597cad322
364 @ changeset: 1:471597cad322
365 | tag: tip
365 | tag: tip
366 | user: test
366 | user: test
367 | date: Thu Jan 01 00:00:00 1970 +0000
367 | date: Thu Jan 01 00:00:00 1970 +0000
368 | summary: A0
368 | summary: A0
369 |
369 |
370 o changeset: 0:ea207398892e
370 o changeset: 0:ea207398892e
371 user: test
371 user: test
372 date: Thu Jan 01 00:00:00 1970 +0000
372 date: Thu Jan 01 00:00:00 1970 +0000
373 summary: ROOT
373 summary: ROOT
374
374
375 # Simulate split
375 # Simulate split
376 $ hg up -r "desc(ROOT)"
376 $ hg up -r "desc(ROOT)"
377 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
377 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
378 $ echo 42 >> a
378 $ echo 42 >> a
379 $ hg commit -A -m "A0"
379 $ hg commit -A -m "A0"
380 adding a
380 adding a
381 created new head
381 created new head
382 $ echo 43 >> b
382 $ echo 43 >> b
383 $ hg commit -A -m "A0"
383 $ hg commit -A -m "A0"
384 adding b
384 adding b
385 $ hg debugobsolete `getid "1"` `getid "2"` `getid "3"`
385 $ hg debugobsolete `getid "1"` `getid "2"` `getid "3"`
386 obsoleted 1 changesets
386 obsoleted 1 changesets
387
387
388 $ hg log --hidden -G
388 $ hg log --hidden -G
389 @ changeset: 3:f257fde29c7a
389 @ changeset: 3:f257fde29c7a
390 | tag: tip
390 | tag: tip
391 | user: test
391 | user: test
392 | date: Thu Jan 01 00:00:00 1970 +0000
392 | date: Thu Jan 01 00:00:00 1970 +0000
393 | summary: A0
393 | summary: A0
394 |
394 |
395 o changeset: 2:337fec4d2edc
395 o changeset: 2:337fec4d2edc
396 | parent: 0:ea207398892e
396 | parent: 0:ea207398892e
397 | user: test
397 | user: test
398 | date: Thu Jan 01 00:00:00 1970 +0000
398 | date: Thu Jan 01 00:00:00 1970 +0000
399 | summary: A0
399 | summary: A0
400 |
400 |
401 | x changeset: 1:471597cad322
401 | x changeset: 1:471597cad322
402 |/ user: test
402 |/ user: test
403 | date: Thu Jan 01 00:00:00 1970 +0000
403 | date: Thu Jan 01 00:00:00 1970 +0000
404 | obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a
404 | obsolete: split as 2:337fec4d2edc, 3:f257fde29c7a
405 | summary: A0
405 | summary: A0
406 |
406 |
407 o changeset: 0:ea207398892e
407 o changeset: 0:ea207398892e
408 user: test
408 user: test
409 date: Thu Jan 01 00:00:00 1970 +0000
409 date: Thu Jan 01 00:00:00 1970 +0000
410 summary: ROOT
410 summary: ROOT
411
411
412 Check templates
412 Check templates
413 ---------------
413 ---------------
414
414
415 $ hg up 'obsolete()' --hidden
415 $ hg up 'obsolete()' --hidden
416 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
416 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
417
417
418 Predecessors template should show current revision as it is the working copy
418 Predecessors template should show current revision as it is the working copy
419 $ hg tlog
419 $ hg tlog
420 o f257fde29c7a
420 o f257fde29c7a
421 | Predecessors: 1:471597cad322
421 | Predecessors: 1:471597cad322
422 | semi-colon: 1:471597cad322
422 | semi-colon: 1:471597cad322
423 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
423 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
424 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
424 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
425 o 337fec4d2edc
425 o 337fec4d2edc
426 | Predecessors: 1:471597cad322
426 | Predecessors: 1:471597cad322
427 | semi-colon: 1:471597cad322
427 | semi-colon: 1:471597cad322
428 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
428 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
429 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
429 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
430 | @ 471597cad322
430 | @ 471597cad322
431 |/ Successors: 2:337fec4d2edc 3:f257fde29c7a
431 |/ Successors: 2:337fec4d2edc 3:f257fde29c7a
432 | multi-line: 2:337fec4d2edc 3:f257fde29c7a
432 | multi-line: 2:337fec4d2edc 3:f257fde29c7a
433 | json: [["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"]]
433 | json: [["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"]]
434 o ea207398892e
434 o ea207398892e
435
435
436
436
437 $ hg fatelog
437 $ hg fatelog
438 o f257fde29c7a
438 o f257fde29c7a
439 |
439 |
440 o 337fec4d2edc
440 o 337fec4d2edc
441 |
441 |
442 | @ 471597cad322
442 | @ 471597cad322
443 |/ Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a by test (at 1970-01-01 00:00 +0000);
443 |/ Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a by test (at 1970-01-01 00:00 +0000);
444 o ea207398892e
444 o ea207398892e
445
445
446 $ hg up f257fde29c7a
446 $ hg up f257fde29c7a
447 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
447 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
448
448
449 Predecessors template should not show a predecessor as it's not displayed in
449 Predecessors template should not show a predecessor as it's not displayed in
450 the log
450 the log
451 $ hg tlog
451 $ hg tlog
452 @ f257fde29c7a
452 @ f257fde29c7a
453 |
453 |
454 o 337fec4d2edc
454 o 337fec4d2edc
455 |
455 |
456 o ea207398892e
456 o ea207398892e
457
457
458 Predecessors template should show both predecessors as we force their display
458 Predecessors template should show both predecessors as we force their display
459 with --hidden
459 with --hidden
460 $ hg tlog --hidden
460 $ hg tlog --hidden
461 @ f257fde29c7a
461 @ f257fde29c7a
462 | Predecessors: 1:471597cad322
462 | Predecessors: 1:471597cad322
463 | semi-colon: 1:471597cad322
463 | semi-colon: 1:471597cad322
464 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
464 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
465 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
465 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
466 o 337fec4d2edc
466 o 337fec4d2edc
467 | Predecessors: 1:471597cad322
467 | Predecessors: 1:471597cad322
468 | semi-colon: 1:471597cad322
468 | semi-colon: 1:471597cad322
469 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
469 | json: ["471597cad322d1f659bb169751be9133dad92ef3"]
470 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
470 | map: 1:471597cad322d1f659bb169751be9133dad92ef3
471 | x 471597cad322
471 | x 471597cad322
472 |/ Successors: 2:337fec4d2edc 3:f257fde29c7a
472 |/ Successors: 2:337fec4d2edc 3:f257fde29c7a
473 | multi-line: 2:337fec4d2edc 3:f257fde29c7a
473 | multi-line: 2:337fec4d2edc 3:f257fde29c7a
474 | json: [["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"]]
474 | json: [["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"]]
475 o ea207398892e
475 o ea207398892e
476
476
477
477
478 $ hg fatelog --hidden
478 $ hg fatelog --hidden
479 @ f257fde29c7a
479 @ f257fde29c7a
480 |
480 |
481 o 337fec4d2edc
481 o 337fec4d2edc
482 |
482 |
483 | x 471597cad322
483 | x 471597cad322
484 |/ Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a by test (at 1970-01-01 00:00 +0000);
484 |/ Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a by test (at 1970-01-01 00:00 +0000);
485 o ea207398892e
485 o ea207398892e
486
486
487 $ hg fatelogjson --hidden
487 $ hg fatelogjson --hidden
488 @ f257fde29c7a
488 @ f257fde29c7a
489 |
489 |
490 o 337fec4d2edc
490 o 337fec4d2edc
491 |
491 |
492 | x 471597cad322
492 | x 471597cad322
493 |/ Obsfate: [{"markers": [["471597cad322d1f659bb169751be9133dad92ef3", ["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"]}]
493 |/ Obsfate: [{"markers": [["471597cad322d1f659bb169751be9133dad92ef3", ["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"]}]
494 o ea207398892e
494 o ea207398892e
495
495
496 Check other fatelog implementations
496 Check other fatelog implementations
497 -----------------------------------
497 -----------------------------------
498
498
499 $ hg fatelogkw --hidden -q
499 $ hg fatelogkw --hidden -q
500 @ f257fde29c7a
500 @ f257fde29c7a
501 |
501 |
502 o 337fec4d2edc
502 o 337fec4d2edc
503 |
503 |
504 | x 471597cad322
504 | x 471597cad322
505 |/ Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a
505 |/ Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a
506 o ea207398892e
506 o ea207398892e
507
507
508 $ hg fatelogkw --hidden
508 $ hg fatelogkw --hidden
509 @ f257fde29c7a
509 @ f257fde29c7a
510 |
510 |
511 o 337fec4d2edc
511 o 337fec4d2edc
512 |
512 |
513 | x 471597cad322
513 | x 471597cad322
514 |/ Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a
514 |/ Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a
515 o ea207398892e
515 o ea207398892e
516
516
517 $ hg fatelogkw --hidden -v
517 $ hg fatelogkw --hidden -v
518 @ f257fde29c7a
518 @ f257fde29c7a
519 |
519 |
520 o 337fec4d2edc
520 o 337fec4d2edc
521 |
521 |
522 | x 471597cad322
522 | x 471597cad322
523 |/ Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a by test (at 1970-01-01 00:00 +0000)
523 |/ Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a by test (at 1970-01-01 00:00 +0000)
524 o ea207398892e
524 o ea207398892e
525
525
526
526
527 $ hg log -G -T "default" --hidden
527 $ hg log -G -T "default" --hidden
528 @ changeset: 3:f257fde29c7a
528 @ changeset: 3:f257fde29c7a
529 | tag: tip
529 | tag: tip
530 | user: test
530 | user: test
531 | date: Thu Jan 01 00:00:00 1970 +0000
531 | date: Thu Jan 01 00:00:00 1970 +0000
532 | summary: A0
532 | summary: A0
533 |
533 |
534 o changeset: 2:337fec4d2edc
534 o changeset: 2:337fec4d2edc
535 | parent: 0:ea207398892e
535 | parent: 0:ea207398892e
536 | user: test
536 | user: test
537 | date: Thu Jan 01 00:00:00 1970 +0000
537 | date: Thu Jan 01 00:00:00 1970 +0000
538 | summary: A0
538 | summary: A0
539 |
539 |
540 | x changeset: 1:471597cad322
540 | x changeset: 1:471597cad322
541 |/ user: test
541 |/ user: test
542 | date: Thu Jan 01 00:00:00 1970 +0000
542 | date: Thu Jan 01 00:00:00 1970 +0000
543 | obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a
543 | obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a
544 | summary: A0
544 | summary: A0
545 |
545 |
546 o changeset: 0:ea207398892e
546 o changeset: 0:ea207398892e
547 user: test
547 user: test
548 date: Thu Jan 01 00:00:00 1970 +0000
548 date: Thu Jan 01 00:00:00 1970 +0000
549 summary: ROOT
549 summary: ROOT
550
550
551
551
552 Test templates with folded commit
552 Test templates with folded commit
553 =================================
553 =================================
554
554
555 Test setup
555 Test setup
556 ----------
556 ----------
557
557
558 $ hg init $TESTTMP/templates-local-fold
558 $ hg init $TESTTMP/templates-local-fold
559 $ cd $TESTTMP/templates-local-fold
559 $ cd $TESTTMP/templates-local-fold
560 $ mkcommit ROOT
560 $ mkcommit ROOT
561 $ mkcommit A0
561 $ mkcommit A0
562 $ mkcommit B0
562 $ mkcommit B0
563 $ hg log --hidden -G
563 $ hg log --hidden -G
564 @ changeset: 2:0dec01379d3b
564 @ changeset: 2:0dec01379d3b
565 | tag: tip
565 | tag: tip
566 | user: test
566 | user: test
567 | date: Thu Jan 01 00:00:00 1970 +0000
567 | date: Thu Jan 01 00:00:00 1970 +0000
568 | summary: B0
568 | summary: B0
569 |
569 |
570 o changeset: 1:471f378eab4c
570 o changeset: 1:471f378eab4c
571 | user: test
571 | user: test
572 | date: Thu Jan 01 00:00:00 1970 +0000
572 | date: Thu Jan 01 00:00:00 1970 +0000
573 | summary: A0
573 | summary: A0
574 |
574 |
575 o changeset: 0:ea207398892e
575 o changeset: 0:ea207398892e
576 user: test
576 user: test
577 date: Thu Jan 01 00:00:00 1970 +0000
577 date: Thu Jan 01 00:00:00 1970 +0000
578 summary: ROOT
578 summary: ROOT
579
579
580 Simulate a fold
580 Simulate a fold
581 $ hg up -r "desc(ROOT)"
581 $ hg up -r "desc(ROOT)"
582 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
582 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
583 $ echo "A0" > A0
583 $ echo "A0" > A0
584 $ echo "B0" > B0
584 $ echo "B0" > B0
585 $ hg commit -A -m "C0"
585 $ hg commit -A -m "C0"
586 adding A0
586 adding A0
587 adding B0
587 adding B0
588 created new head
588 created new head
589 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(C0)"`
589 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(C0)"`
590 obsoleted 1 changesets
590 obsoleted 1 changesets
591 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(C0)"`
591 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(C0)"`
592 obsoleted 1 changesets
592 obsoleted 1 changesets
593
593
594 $ hg log --hidden -G
594 $ hg log --hidden -G
595 @ changeset: 3:eb5a0daa2192
595 @ changeset: 3:eb5a0daa2192
596 | tag: tip
596 | tag: tip
597 | parent: 0:ea207398892e
597 | parent: 0:ea207398892e
598 | user: test
598 | user: test
599 | date: Thu Jan 01 00:00:00 1970 +0000
599 | date: Thu Jan 01 00:00:00 1970 +0000
600 | summary: C0
600 | summary: C0
601 |
601 |
602 | x changeset: 2:0dec01379d3b
602 | x changeset: 2:0dec01379d3b
603 | | user: test
603 | | user: test
604 | | date: Thu Jan 01 00:00:00 1970 +0000
604 | | date: Thu Jan 01 00:00:00 1970 +0000
605 | | obsfate: rewritten as 3:eb5a0daa2192
605 | | obsolete: rewritten as 3:eb5a0daa2192
606 | | summary: B0
606 | | summary: B0
607 | |
607 | |
608 | x changeset: 1:471f378eab4c
608 | x changeset: 1:471f378eab4c
609 |/ user: test
609 |/ user: test
610 | date: Thu Jan 01 00:00:00 1970 +0000
610 | date: Thu Jan 01 00:00:00 1970 +0000
611 | obsfate: rewritten as 3:eb5a0daa2192
611 | obsolete: rewritten as 3:eb5a0daa2192
612 | summary: A0
612 | summary: A0
613 |
613 |
614 o changeset: 0:ea207398892e
614 o changeset: 0:ea207398892e
615 user: test
615 user: test
616 date: Thu Jan 01 00:00:00 1970 +0000
616 date: Thu Jan 01 00:00:00 1970 +0000
617 summary: ROOT
617 summary: ROOT
618
618
619 Check templates
619 Check templates
620 ---------------
620 ---------------
621
621
622 $ hg up 'desc(A0)' --hidden
622 $ hg up 'desc(A0)' --hidden
623 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
623 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
624
624
625 Predecessors template should show current revision as it is the working copy
625 Predecessors template should show current revision as it is the working copy
626 $ hg tlog
626 $ hg tlog
627 o eb5a0daa2192
627 o eb5a0daa2192
628 | Predecessors: 1:471f378eab4c
628 | Predecessors: 1:471f378eab4c
629 | semi-colon: 1:471f378eab4c
629 | semi-colon: 1:471f378eab4c
630 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
630 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
631 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
631 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
632 | @ 471f378eab4c
632 | @ 471f378eab4c
633 |/ Successors: 3:eb5a0daa2192
633 |/ Successors: 3:eb5a0daa2192
634 | multi-line: 3:eb5a0daa2192
634 | multi-line: 3:eb5a0daa2192
635 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
635 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
636 o ea207398892e
636 o ea207398892e
637
637
638
638
639 $ hg fatelog
639 $ hg fatelog
640 o eb5a0daa2192
640 o eb5a0daa2192
641 |
641 |
642 | @ 471f378eab4c
642 | @ 471f378eab4c
643 |/ Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
643 |/ Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
644 o ea207398892e
644 o ea207398892e
645
645
646 $ hg up 'desc(B0)' --hidden
646 $ hg up 'desc(B0)' --hidden
647 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
647 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
648
648
649 Predecessors template should show both predecessors as they should be both
649 Predecessors template should show both predecessors as they should be both
650 displayed
650 displayed
651 $ hg tlog
651 $ hg tlog
652 o eb5a0daa2192
652 o eb5a0daa2192
653 | Predecessors: 2:0dec01379d3b 1:471f378eab4c
653 | Predecessors: 2:0dec01379d3b 1:471f378eab4c
654 | semi-colon: 2:0dec01379d3b; 1:471f378eab4c
654 | semi-colon: 2:0dec01379d3b; 1:471f378eab4c
655 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
655 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
656 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5 1:471f378eab4c5e25f6c77f785b27c936efb22874
656 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5 1:471f378eab4c5e25f6c77f785b27c936efb22874
657 | @ 0dec01379d3b
657 | @ 0dec01379d3b
658 | | Successors: 3:eb5a0daa2192
658 | | Successors: 3:eb5a0daa2192
659 | | multi-line: 3:eb5a0daa2192
659 | | multi-line: 3:eb5a0daa2192
660 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
660 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
661 | x 471f378eab4c
661 | x 471f378eab4c
662 |/ Successors: 3:eb5a0daa2192
662 |/ Successors: 3:eb5a0daa2192
663 | multi-line: 3:eb5a0daa2192
663 | multi-line: 3:eb5a0daa2192
664 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
664 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
665 o ea207398892e
665 o ea207398892e
666
666
667
667
668 $ hg fatelog
668 $ hg fatelog
669 o eb5a0daa2192
669 o eb5a0daa2192
670 |
670 |
671 | @ 0dec01379d3b
671 | @ 0dec01379d3b
672 | | Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
672 | | Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
673 | x 471f378eab4c
673 | x 471f378eab4c
674 |/ Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
674 |/ Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
675 o ea207398892e
675 o ea207398892e
676
676
677 $ hg up 'desc(C0)'
677 $ hg up 'desc(C0)'
678 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
678 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
679
679
680 Predecessors template should not show predecessors as they are not displayed in
680 Predecessors template should not show predecessors as they are not displayed in
681 the log
681 the log
682 $ hg tlog
682 $ hg tlog
683 @ eb5a0daa2192
683 @ eb5a0daa2192
684 |
684 |
685 o ea207398892e
685 o ea207398892e
686
686
687 Predecessors template should show both predecessors as we force their display
687 Predecessors template should show both predecessors as we force their display
688 with --hidden
688 with --hidden
689 $ hg tlog --hidden
689 $ hg tlog --hidden
690 @ eb5a0daa2192
690 @ eb5a0daa2192
691 | Predecessors: 2:0dec01379d3b 1:471f378eab4c
691 | Predecessors: 2:0dec01379d3b 1:471f378eab4c
692 | semi-colon: 2:0dec01379d3b; 1:471f378eab4c
692 | semi-colon: 2:0dec01379d3b; 1:471f378eab4c
693 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
693 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
694 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5 1:471f378eab4c5e25f6c77f785b27c936efb22874
694 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5 1:471f378eab4c5e25f6c77f785b27c936efb22874
695 | x 0dec01379d3b
695 | x 0dec01379d3b
696 | | Successors: 3:eb5a0daa2192
696 | | Successors: 3:eb5a0daa2192
697 | | multi-line: 3:eb5a0daa2192
697 | | multi-line: 3:eb5a0daa2192
698 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
698 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
699 | x 471f378eab4c
699 | x 471f378eab4c
700 |/ Successors: 3:eb5a0daa2192
700 |/ Successors: 3:eb5a0daa2192
701 | multi-line: 3:eb5a0daa2192
701 | multi-line: 3:eb5a0daa2192
702 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
702 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
703 o ea207398892e
703 o ea207398892e
704
704
705
705
706 $ hg fatelog --hidden
706 $ hg fatelog --hidden
707 @ eb5a0daa2192
707 @ eb5a0daa2192
708 |
708 |
709 | x 0dec01379d3b
709 | x 0dec01379d3b
710 | | Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
710 | | Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
711 | x 471f378eab4c
711 | x 471f378eab4c
712 |/ Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
712 |/ Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
713 o ea207398892e
713 o ea207398892e
714
714
715
715
716 $ hg fatelogjson --hidden
716 $ hg fatelogjson --hidden
717 @ eb5a0daa2192
717 @ eb5a0daa2192
718 |
718 |
719 | x 0dec01379d3b
719 | x 0dec01379d3b
720 | | Obsfate: [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]}]
720 | | Obsfate: [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]}]
721 | x 471f378eab4c
721 | x 471f378eab4c
722 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]}]
722 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]}]
723 o ea207398892e
723 o ea207398892e
724
724
725 Check other fatelog implementations
725 Check other fatelog implementations
726 -----------------------------------
726 -----------------------------------
727
727
728 $ hg fatelogkw --hidden -q
728 $ hg fatelogkw --hidden -q
729 @ eb5a0daa2192
729 @ eb5a0daa2192
730 |
730 |
731 | x 0dec01379d3b
731 | x 0dec01379d3b
732 | | Obsfate: rewritten as 3:eb5a0daa2192
732 | | Obsfate: rewritten as 3:eb5a0daa2192
733 | x 471f378eab4c
733 | x 471f378eab4c
734 |/ Obsfate: rewritten as 3:eb5a0daa2192
734 |/ Obsfate: rewritten as 3:eb5a0daa2192
735 o ea207398892e
735 o ea207398892e
736
736
737 $ hg fatelogkw --hidden
737 $ hg fatelogkw --hidden
738 @ eb5a0daa2192
738 @ eb5a0daa2192
739 |
739 |
740 | x 0dec01379d3b
740 | x 0dec01379d3b
741 | | Obsfate: rewritten as 3:eb5a0daa2192
741 | | Obsfate: rewritten as 3:eb5a0daa2192
742 | x 471f378eab4c
742 | x 471f378eab4c
743 |/ Obsfate: rewritten as 3:eb5a0daa2192
743 |/ Obsfate: rewritten as 3:eb5a0daa2192
744 o ea207398892e
744 o ea207398892e
745
745
746 $ hg fatelogkw --hidden -v
746 $ hg fatelogkw --hidden -v
747 @ eb5a0daa2192
747 @ eb5a0daa2192
748 |
748 |
749 | x 0dec01379d3b
749 | x 0dec01379d3b
750 | | Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000)
750 | | Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000)
751 | x 471f378eab4c
751 | x 471f378eab4c
752 |/ Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000)
752 |/ Obsfate: rewritten as 3:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000)
753 o ea207398892e
753 o ea207398892e
754
754
755 $ hg log -G -T "default" --hidden
755 $ hg log -G -T "default" --hidden
756 @ changeset: 3:eb5a0daa2192
756 @ changeset: 3:eb5a0daa2192
757 | tag: tip
757 | tag: tip
758 | parent: 0:ea207398892e
758 | parent: 0:ea207398892e
759 | user: test
759 | user: test
760 | date: Thu Jan 01 00:00:00 1970 +0000
760 | date: Thu Jan 01 00:00:00 1970 +0000
761 | summary: C0
761 | summary: C0
762 |
762 |
763 | x changeset: 2:0dec01379d3b
763 | x changeset: 2:0dec01379d3b
764 | | user: test
764 | | user: test
765 | | date: Thu Jan 01 00:00:00 1970 +0000
765 | | date: Thu Jan 01 00:00:00 1970 +0000
766 | | obsfate: rewritten as 3:eb5a0daa2192
766 | | obsfate: rewritten as 3:eb5a0daa2192
767 | | summary: B0
767 | | summary: B0
768 | |
768 | |
769 | x changeset: 1:471f378eab4c
769 | x changeset: 1:471f378eab4c
770 |/ user: test
770 |/ user: test
771 | date: Thu Jan 01 00:00:00 1970 +0000
771 | date: Thu Jan 01 00:00:00 1970 +0000
772 | obsfate: rewritten as 3:eb5a0daa2192
772 | obsfate: rewritten as 3:eb5a0daa2192
773 | summary: A0
773 | summary: A0
774 |
774 |
775 o changeset: 0:ea207398892e
775 o changeset: 0:ea207398892e
776 user: test
776 user: test
777 date: Thu Jan 01 00:00:00 1970 +0000
777 date: Thu Jan 01 00:00:00 1970 +0000
778 summary: ROOT
778 summary: ROOT
779
779
780
780
781 Test templates with divergence
781 Test templates with divergence
782 ==============================
782 ==============================
783
783
784 Test setup
784 Test setup
785 ----------
785 ----------
786
786
787 $ hg init $TESTTMP/templates-local-divergence
787 $ hg init $TESTTMP/templates-local-divergence
788 $ cd $TESTTMP/templates-local-divergence
788 $ cd $TESTTMP/templates-local-divergence
789 $ mkcommit ROOT
789 $ mkcommit ROOT
790 $ mkcommit A0
790 $ mkcommit A0
791 $ hg commit --amend -m "A1"
791 $ hg commit --amend -m "A1"
792 $ hg log --hidden -G
792 $ hg log --hidden -G
793 @ changeset: 2:fdf9bde5129a
793 @ changeset: 2:fdf9bde5129a
794 | tag: tip
794 | tag: tip
795 | parent: 0:ea207398892e
795 | parent: 0:ea207398892e
796 | user: test
796 | user: test
797 | date: Thu Jan 01 00:00:00 1970 +0000
797 | date: Thu Jan 01 00:00:00 1970 +0000
798 | summary: A1
798 | summary: A1
799 |
799 |
800 | x changeset: 1:471f378eab4c
800 | x changeset: 1:471f378eab4c
801 |/ user: test
801 |/ user: test
802 | date: Thu Jan 01 00:00:00 1970 +0000
802 | date: Thu Jan 01 00:00:00 1970 +0000
803 | obsfate: rewritten using amend as 2:fdf9bde5129a
803 | obsolete: rewritten using amend as 2:fdf9bde5129a
804 | summary: A0
804 | summary: A0
805 |
805 |
806 o changeset: 0:ea207398892e
806 o changeset: 0:ea207398892e
807 user: test
807 user: test
808 date: Thu Jan 01 00:00:00 1970 +0000
808 date: Thu Jan 01 00:00:00 1970 +0000
809 summary: ROOT
809 summary: ROOT
810
810
811 $ hg update --hidden 'desc(A0)'
811 $ hg update --hidden 'desc(A0)'
812 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
812 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
813 $ hg commit --amend -m "A2"
813 $ hg commit --amend -m "A2"
814 $ hg log --hidden -G
814 $ hg log --hidden -G
815 @ changeset: 3:65b757b745b9
815 @ changeset: 3:65b757b745b9
816 | tag: tip
816 | tag: tip
817 | parent: 0:ea207398892e
817 | parent: 0:ea207398892e
818 | user: test
818 | user: test
819 | date: Thu Jan 01 00:00:00 1970 +0000
819 | date: Thu Jan 01 00:00:00 1970 +0000
820 | instability: content-divergent
820 | instability: content-divergent
821 | summary: A2
821 | summary: A2
822 |
822 |
823 | o changeset: 2:fdf9bde5129a
823 | o changeset: 2:fdf9bde5129a
824 |/ parent: 0:ea207398892e
824 |/ parent: 0:ea207398892e
825 | user: test
825 | user: test
826 | date: Thu Jan 01 00:00:00 1970 +0000
826 | date: Thu Jan 01 00:00:00 1970 +0000
827 | instability: content-divergent
827 | instability: content-divergent
828 | summary: A1
828 | summary: A1
829 |
829 |
830 | x changeset: 1:471f378eab4c
830 | x changeset: 1:471f378eab4c
831 |/ user: test
831 |/ user: test
832 | date: Thu Jan 01 00:00:00 1970 +0000
832 | date: Thu Jan 01 00:00:00 1970 +0000
833 | obsfate: rewritten using amend as 2:fdf9bde5129a
833 | obsolete: rewritten using amend as 2:fdf9bde5129a
834 | obsfate: rewritten using amend as 3:65b757b745b9
834 | obsolete: rewritten using amend as 3:65b757b745b9
835 | summary: A0
835 | summary: A0
836 |
836 |
837 o changeset: 0:ea207398892e
837 o changeset: 0:ea207398892e
838 user: test
838 user: test
839 date: Thu Jan 01 00:00:00 1970 +0000
839 date: Thu Jan 01 00:00:00 1970 +0000
840 summary: ROOT
840 summary: ROOT
841
841
842 $ hg commit --amend -m 'A3'
842 $ hg commit --amend -m 'A3'
843 $ hg log --hidden -G
843 $ hg log --hidden -G
844 @ changeset: 4:019fadeab383
844 @ changeset: 4:019fadeab383
845 | tag: tip
845 | tag: tip
846 | parent: 0:ea207398892e
846 | parent: 0:ea207398892e
847 | user: test
847 | user: test
848 | date: Thu Jan 01 00:00:00 1970 +0000
848 | date: Thu Jan 01 00:00:00 1970 +0000
849 | instability: content-divergent
849 | instability: content-divergent
850 | summary: A3
850 | summary: A3
851 |
851 |
852 | x changeset: 3:65b757b745b9
852 | x changeset: 3:65b757b745b9
853 |/ parent: 0:ea207398892e
853 |/ parent: 0:ea207398892e
854 | user: test
854 | user: test
855 | date: Thu Jan 01 00:00:00 1970 +0000
855 | date: Thu Jan 01 00:00:00 1970 +0000
856 | obsfate: rewritten using amend as 4:019fadeab383
856 | obsolete: rewritten using amend as 4:019fadeab383
857 | summary: A2
857 | summary: A2
858 |
858 |
859 | o changeset: 2:fdf9bde5129a
859 | o changeset: 2:fdf9bde5129a
860 |/ parent: 0:ea207398892e
860 |/ parent: 0:ea207398892e
861 | user: test
861 | user: test
862 | date: Thu Jan 01 00:00:00 1970 +0000
862 | date: Thu Jan 01 00:00:00 1970 +0000
863 | instability: content-divergent
863 | instability: content-divergent
864 | summary: A1
864 | summary: A1
865 |
865 |
866 | x changeset: 1:471f378eab4c
866 | x changeset: 1:471f378eab4c
867 |/ user: test
867 |/ user: test
868 | date: Thu Jan 01 00:00:00 1970 +0000
868 | date: Thu Jan 01 00:00:00 1970 +0000
869 | obsfate: rewritten using amend as 2:fdf9bde5129a
869 | obsolete: rewritten using amend as 2:fdf9bde5129a
870 | obsfate: rewritten using amend as 3:65b757b745b9
870 | obsolete: rewritten using amend as 3:65b757b745b9
871 | summary: A0
871 | summary: A0
872 |
872 |
873 o changeset: 0:ea207398892e
873 o changeset: 0:ea207398892e
874 user: test
874 user: test
875 date: Thu Jan 01 00:00:00 1970 +0000
875 date: Thu Jan 01 00:00:00 1970 +0000
876 summary: ROOT
876 summary: ROOT
877
877
878
878
879 Check templates
879 Check templates
880 ---------------
880 ---------------
881
881
882 $ hg up 'desc(A0)' --hidden
882 $ hg up 'desc(A0)' --hidden
883 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
883 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
884
884
885 Predecessors template should show current revision as it is the working copy
885 Predecessors template should show current revision as it is the working copy
886 $ hg tlog
886 $ hg tlog
887 o 019fadeab383
887 o 019fadeab383
888 | Predecessors: 1:471f378eab4c
888 | Predecessors: 1:471f378eab4c
889 | semi-colon: 1:471f378eab4c
889 | semi-colon: 1:471f378eab4c
890 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
890 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
891 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
891 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
892 | o fdf9bde5129a
892 | o fdf9bde5129a
893 |/ Predecessors: 1:471f378eab4c
893 |/ Predecessors: 1:471f378eab4c
894 | semi-colon: 1:471f378eab4c
894 | semi-colon: 1:471f378eab4c
895 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
895 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
896 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
896 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
897 | @ 471f378eab4c
897 | @ 471f378eab4c
898 |/ Successors: 2:fdf9bde5129a; 4:019fadeab383
898 |/ Successors: 2:fdf9bde5129a; 4:019fadeab383
899 | multi-line: 2:fdf9bde5129a
899 | multi-line: 2:fdf9bde5129a
900 | multi-line: 4:019fadeab383
900 | multi-line: 4:019fadeab383
901 | json: [["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"]]
901 | json: [["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"]]
902 o ea207398892e
902 o ea207398892e
903
903
904 $ hg fatelog
904 $ hg fatelog
905 o 019fadeab383
905 o 019fadeab383
906 |
906 |
907 | o fdf9bde5129a
907 | o fdf9bde5129a
908 |/
908 |/
909 | @ 471f378eab4c
909 | @ 471f378eab4c
910 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a by test (at 1970-01-01 00:00 +0000); rewritten using amend as 4:019fadeab383 by test (at 1970-01-01 00:00 +0000);
910 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a by test (at 1970-01-01 00:00 +0000); rewritten using amend as 4:019fadeab383 by test (at 1970-01-01 00:00 +0000);
911 o ea207398892e
911 o ea207398892e
912
912
913 $ hg up 'desc(A1)'
913 $ hg up 'desc(A1)'
914 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
914 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
915
915
916 Predecessors template should not show predecessors as they are not displayed in
916 Predecessors template should not show predecessors as they are not displayed in
917 the log
917 the log
918 $ hg tlog
918 $ hg tlog
919 o 019fadeab383
919 o 019fadeab383
920 |
920 |
921 | @ fdf9bde5129a
921 | @ fdf9bde5129a
922 |/
922 |/
923 o ea207398892e
923 o ea207398892e
924
924
925
925
926 $ hg fatelog
926 $ hg fatelog
927 o 019fadeab383
927 o 019fadeab383
928 |
928 |
929 | @ fdf9bde5129a
929 | @ fdf9bde5129a
930 |/
930 |/
931 o ea207398892e
931 o ea207398892e
932
932
933 Predecessors template should the predecessors as we force their display with
933 Predecessors template should the predecessors as we force their display with
934 --hidden
934 --hidden
935 $ hg tlog --hidden
935 $ hg tlog --hidden
936 o 019fadeab383
936 o 019fadeab383
937 | Predecessors: 3:65b757b745b9
937 | Predecessors: 3:65b757b745b9
938 | semi-colon: 3:65b757b745b9
938 | semi-colon: 3:65b757b745b9
939 | json: ["65b757b745b935093c87a2bccd877521cccffcbd"]
939 | json: ["65b757b745b935093c87a2bccd877521cccffcbd"]
940 | map: 3:65b757b745b935093c87a2bccd877521cccffcbd
940 | map: 3:65b757b745b935093c87a2bccd877521cccffcbd
941 | x 65b757b745b9
941 | x 65b757b745b9
942 |/ Predecessors: 1:471f378eab4c
942 |/ Predecessors: 1:471f378eab4c
943 | semi-colon: 1:471f378eab4c
943 | semi-colon: 1:471f378eab4c
944 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
944 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
945 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
945 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
946 | Successors: 4:019fadeab383
946 | Successors: 4:019fadeab383
947 | multi-line: 4:019fadeab383
947 | multi-line: 4:019fadeab383
948 | json: [["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"]]
948 | json: [["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"]]
949 | @ fdf9bde5129a
949 | @ fdf9bde5129a
950 |/ Predecessors: 1:471f378eab4c
950 |/ Predecessors: 1:471f378eab4c
951 | semi-colon: 1:471f378eab4c
951 | semi-colon: 1:471f378eab4c
952 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
952 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
953 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
953 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
954 | x 471f378eab4c
954 | x 471f378eab4c
955 |/ Successors: 2:fdf9bde5129a; 3:65b757b745b9
955 |/ Successors: 2:fdf9bde5129a; 3:65b757b745b9
956 | multi-line: 2:fdf9bde5129a
956 | multi-line: 2:fdf9bde5129a
957 | multi-line: 3:65b757b745b9
957 | multi-line: 3:65b757b745b9
958 | json: [["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], ["65b757b745b935093c87a2bccd877521cccffcbd"]]
958 | json: [["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], ["65b757b745b935093c87a2bccd877521cccffcbd"]]
959 o ea207398892e
959 o ea207398892e
960
960
961
961
962 $ hg fatelog --hidden
962 $ hg fatelog --hidden
963 o 019fadeab383
963 o 019fadeab383
964 |
964 |
965 | x 65b757b745b9
965 | x 65b757b745b9
966 |/ Obsfate: rewritten using amend as 4:019fadeab383 by test (at 1970-01-01 00:00 +0000);
966 |/ Obsfate: rewritten using amend as 4:019fadeab383 by test (at 1970-01-01 00:00 +0000);
967 | @ fdf9bde5129a
967 | @ fdf9bde5129a
968 |/
968 |/
969 | x 471f378eab4c
969 | x 471f378eab4c
970 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a by test (at 1970-01-01 00:00 +0000); rewritten using amend as 3:65b757b745b9 by test (at 1970-01-01 00:00 +0000);
970 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a by test (at 1970-01-01 00:00 +0000); rewritten using amend as 3:65b757b745b9 by test (at 1970-01-01 00:00 +0000);
971 o ea207398892e
971 o ea207398892e
972
972
973
973
974 $ hg fatelogjson --hidden
974 $ hg fatelogjson --hidden
975 o 019fadeab383
975 o 019fadeab383
976 |
976 |
977 | x 65b757b745b9
977 | x 65b757b745b9
978 |/ Obsfate: [{"markers": [["65b757b745b935093c87a2bccd877521cccffcbd", ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"], 0, [["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "successors": ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"]}]
978 |/ Obsfate: [{"markers": [["65b757b745b935093c87a2bccd877521cccffcbd", ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"], 0, [["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "successors": ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"]}]
979 | @ fdf9bde5129a
979 | @ fdf9bde5129a
980 |/
980 |/
981 | x 471f378eab4c
981 | x 471f378eab4c
982 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], 0, [["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "successors": ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"]}, {"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["65b757b745b935093c87a2bccd877521cccffcbd"], 0, [["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "successors": ["65b757b745b935093c87a2bccd877521cccffcbd"]}]
982 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], 0, [["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "successors": ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"]}, {"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["65b757b745b935093c87a2bccd877521cccffcbd"], 0, [["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "successors": ["65b757b745b935093c87a2bccd877521cccffcbd"]}]
983 o ea207398892e
983 o ea207398892e
984
984
985
985
986 Check other fatelog implementations
986 Check other fatelog implementations
987 -----------------------------------
987 -----------------------------------
988
988
989 $ hg fatelogkw --hidden -q
989 $ hg fatelogkw --hidden -q
990 o 019fadeab383
990 o 019fadeab383
991 |
991 |
992 | x 65b757b745b9
992 | x 65b757b745b9
993 |/ Obsfate: rewritten using amend as 4:019fadeab383
993 |/ Obsfate: rewritten using amend as 4:019fadeab383
994 | @ fdf9bde5129a
994 | @ fdf9bde5129a
995 |/
995 |/
996 | x 471f378eab4c
996 | x 471f378eab4c
997 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a
997 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a
998 | Obsfate: rewritten using amend as 3:65b757b745b9
998 | Obsfate: rewritten using amend as 3:65b757b745b9
999 o ea207398892e
999 o ea207398892e
1000
1000
1001 $ hg fatelogkw --hidden
1001 $ hg fatelogkw --hidden
1002 o 019fadeab383
1002 o 019fadeab383
1003 |
1003 |
1004 | x 65b757b745b9
1004 | x 65b757b745b9
1005 |/ Obsfate: rewritten using amend as 4:019fadeab383
1005 |/ Obsfate: rewritten using amend as 4:019fadeab383
1006 | @ fdf9bde5129a
1006 | @ fdf9bde5129a
1007 |/
1007 |/
1008 | x 471f378eab4c
1008 | x 471f378eab4c
1009 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a
1009 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a
1010 | Obsfate: rewritten using amend as 3:65b757b745b9
1010 | Obsfate: rewritten using amend as 3:65b757b745b9
1011 o ea207398892e
1011 o ea207398892e
1012
1012
1013 $ hg fatelogkw --hidden -v
1013 $ hg fatelogkw --hidden -v
1014 o 019fadeab383
1014 o 019fadeab383
1015 |
1015 |
1016 | x 65b757b745b9
1016 | x 65b757b745b9
1017 |/ Obsfate: rewritten using amend as 4:019fadeab383 by test (at 1970-01-01 00:00 +0000)
1017 |/ Obsfate: rewritten using amend as 4:019fadeab383 by test (at 1970-01-01 00:00 +0000)
1018 | @ fdf9bde5129a
1018 | @ fdf9bde5129a
1019 |/
1019 |/
1020 | x 471f378eab4c
1020 | x 471f378eab4c
1021 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a by test (at 1970-01-01 00:00 +0000)
1021 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a by test (at 1970-01-01 00:00 +0000)
1022 | Obsfate: rewritten using amend as 3:65b757b745b9 by test (at 1970-01-01 00:00 +0000)
1022 | Obsfate: rewritten using amend as 3:65b757b745b9 by test (at 1970-01-01 00:00 +0000)
1023 o ea207398892e
1023 o ea207398892e
1024
1024
1025 $ hg log -G -T "default" --hidden
1025 $ hg log -G -T "default" --hidden
1026 o changeset: 4:019fadeab383
1026 o changeset: 4:019fadeab383
1027 | tag: tip
1027 | tag: tip
1028 | parent: 0:ea207398892e
1028 | parent: 0:ea207398892e
1029 | user: test
1029 | user: test
1030 | date: Thu Jan 01 00:00:00 1970 +0000
1030 | date: Thu Jan 01 00:00:00 1970 +0000
1031 | instability: content-divergent
1031 | instability: content-divergent
1032 | summary: A3
1032 | summary: A3
1033 |
1033 |
1034 | x changeset: 3:65b757b745b9
1034 | x changeset: 3:65b757b745b9
1035 |/ parent: 0:ea207398892e
1035 |/ parent: 0:ea207398892e
1036 | user: test
1036 | user: test
1037 | date: Thu Jan 01 00:00:00 1970 +0000
1037 | date: Thu Jan 01 00:00:00 1970 +0000
1038 | obsfate: rewritten using amend as 4:019fadeab383
1038 | obsfate: rewritten using amend as 4:019fadeab383
1039 | summary: A2
1039 | summary: A2
1040 |
1040 |
1041 | @ changeset: 2:fdf9bde5129a
1041 | @ changeset: 2:fdf9bde5129a
1042 |/ parent: 0:ea207398892e
1042 |/ parent: 0:ea207398892e
1043 | user: test
1043 | user: test
1044 | date: Thu Jan 01 00:00:00 1970 +0000
1044 | date: Thu Jan 01 00:00:00 1970 +0000
1045 | instability: content-divergent
1045 | instability: content-divergent
1046 | summary: A1
1046 | summary: A1
1047 |
1047 |
1048 | x changeset: 1:471f378eab4c
1048 | x changeset: 1:471f378eab4c
1049 |/ user: test
1049 |/ user: test
1050 | date: Thu Jan 01 00:00:00 1970 +0000
1050 | date: Thu Jan 01 00:00:00 1970 +0000
1051 | obsfate: rewritten using amend as 2:fdf9bde5129a
1051 | obsfate: rewritten using amend as 2:fdf9bde5129a
1052 | obsfate: rewritten using amend as 3:65b757b745b9
1052 | obsfate: rewritten using amend as 3:65b757b745b9
1053 | summary: A0
1053 | summary: A0
1054 |
1054 |
1055 o changeset: 0:ea207398892e
1055 o changeset: 0:ea207398892e
1056 user: test
1056 user: test
1057 date: Thu Jan 01 00:00:00 1970 +0000
1057 date: Thu Jan 01 00:00:00 1970 +0000
1058 summary: ROOT
1058 summary: ROOT
1059
1059
1060
1060
1061 Test templates with amended + folded commit
1061 Test templates with amended + folded commit
1062 ===========================================
1062 ===========================================
1063
1063
1064 Test setup
1064 Test setup
1065 ----------
1065 ----------
1066
1066
1067 $ hg init $TESTTMP/templates-local-amend-fold
1067 $ hg init $TESTTMP/templates-local-amend-fold
1068 $ cd $TESTTMP/templates-local-amend-fold
1068 $ cd $TESTTMP/templates-local-amend-fold
1069 $ mkcommit ROOT
1069 $ mkcommit ROOT
1070 $ mkcommit A0
1070 $ mkcommit A0
1071 $ mkcommit B0
1071 $ mkcommit B0
1072 $ hg commit --amend -m "B1"
1072 $ hg commit --amend -m "B1"
1073 $ hg log --hidden -G
1073 $ hg log --hidden -G
1074 @ changeset: 3:b7ea6d14e664
1074 @ changeset: 3:b7ea6d14e664
1075 | tag: tip
1075 | tag: tip
1076 | parent: 1:471f378eab4c
1076 | parent: 1:471f378eab4c
1077 | user: test
1077 | user: test
1078 | date: Thu Jan 01 00:00:00 1970 +0000
1078 | date: Thu Jan 01 00:00:00 1970 +0000
1079 | summary: B1
1079 | summary: B1
1080 |
1080 |
1081 | x changeset: 2:0dec01379d3b
1081 | x changeset: 2:0dec01379d3b
1082 |/ user: test
1082 |/ user: test
1083 | date: Thu Jan 01 00:00:00 1970 +0000
1083 | date: Thu Jan 01 00:00:00 1970 +0000
1084 | obsfate: rewritten using amend as 3:b7ea6d14e664
1084 | obsolete: rewritten using amend as 3:b7ea6d14e664
1085 | summary: B0
1085 | summary: B0
1086 |
1086 |
1087 o changeset: 1:471f378eab4c
1087 o changeset: 1:471f378eab4c
1088 | user: test
1088 | user: test
1089 | date: Thu Jan 01 00:00:00 1970 +0000
1089 | date: Thu Jan 01 00:00:00 1970 +0000
1090 | summary: A0
1090 | summary: A0
1091 |
1091 |
1092 o changeset: 0:ea207398892e
1092 o changeset: 0:ea207398892e
1093 user: test
1093 user: test
1094 date: Thu Jan 01 00:00:00 1970 +0000
1094 date: Thu Jan 01 00:00:00 1970 +0000
1095 summary: ROOT
1095 summary: ROOT
1096
1096
1097 # Simulate a fold
1097 # Simulate a fold
1098 $ hg up -r "desc(ROOT)"
1098 $ hg up -r "desc(ROOT)"
1099 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1099 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1100 $ echo "A0" > A0
1100 $ echo "A0" > A0
1101 $ echo "B0" > B0
1101 $ echo "B0" > B0
1102 $ hg commit -A -m "C0"
1102 $ hg commit -A -m "C0"
1103 adding A0
1103 adding A0
1104 adding B0
1104 adding B0
1105 created new head
1105 created new head
1106 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(C0)"`
1106 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(C0)"`
1107 obsoleted 1 changesets
1107 obsoleted 1 changesets
1108 $ hg debugobsolete `getid "desc(B1)"` `getid "desc(C0)"`
1108 $ hg debugobsolete `getid "desc(B1)"` `getid "desc(C0)"`
1109 obsoleted 1 changesets
1109 obsoleted 1 changesets
1110
1110
1111 $ hg log --hidden -G
1111 $ hg log --hidden -G
1112 @ changeset: 4:eb5a0daa2192
1112 @ changeset: 4:eb5a0daa2192
1113 | tag: tip
1113 | tag: tip
1114 | parent: 0:ea207398892e
1114 | parent: 0:ea207398892e
1115 | user: test
1115 | user: test
1116 | date: Thu Jan 01 00:00:00 1970 +0000
1116 | date: Thu Jan 01 00:00:00 1970 +0000
1117 | summary: C0
1117 | summary: C0
1118 |
1118 |
1119 | x changeset: 3:b7ea6d14e664
1119 | x changeset: 3:b7ea6d14e664
1120 | | parent: 1:471f378eab4c
1120 | | parent: 1:471f378eab4c
1121 | | user: test
1121 | | user: test
1122 | | date: Thu Jan 01 00:00:00 1970 +0000
1122 | | date: Thu Jan 01 00:00:00 1970 +0000
1123 | | obsfate: rewritten as 4:eb5a0daa2192
1123 | | obsolete: rewritten as 4:eb5a0daa2192
1124 | | summary: B1
1124 | | summary: B1
1125 | |
1125 | |
1126 | | x changeset: 2:0dec01379d3b
1126 | | x changeset: 2:0dec01379d3b
1127 | |/ user: test
1127 | |/ user: test
1128 | | date: Thu Jan 01 00:00:00 1970 +0000
1128 | | date: Thu Jan 01 00:00:00 1970 +0000
1129 | | obsfate: rewritten using amend as 3:b7ea6d14e664
1129 | | obsolete: rewritten using amend as 3:b7ea6d14e664
1130 | | summary: B0
1130 | | summary: B0
1131 | |
1131 | |
1132 | x changeset: 1:471f378eab4c
1132 | x changeset: 1:471f378eab4c
1133 |/ user: test
1133 |/ user: test
1134 | date: Thu Jan 01 00:00:00 1970 +0000
1134 | date: Thu Jan 01 00:00:00 1970 +0000
1135 | obsfate: rewritten as 4:eb5a0daa2192
1135 | obsolete: rewritten as 4:eb5a0daa2192
1136 | summary: A0
1136 | summary: A0
1137 |
1137 |
1138 o changeset: 0:ea207398892e
1138 o changeset: 0:ea207398892e
1139 user: test
1139 user: test
1140 date: Thu Jan 01 00:00:00 1970 +0000
1140 date: Thu Jan 01 00:00:00 1970 +0000
1141 summary: ROOT
1141 summary: ROOT
1142
1142
1143 Check templates
1143 Check templates
1144 ---------------
1144 ---------------
1145
1145
1146 $ hg up 'desc(A0)' --hidden
1146 $ hg up 'desc(A0)' --hidden
1147 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1147 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1148
1148
1149 Predecessors template should show current revision as it is the working copy
1149 Predecessors template should show current revision as it is the working copy
1150 $ hg tlog
1150 $ hg tlog
1151 o eb5a0daa2192
1151 o eb5a0daa2192
1152 | Predecessors: 1:471f378eab4c
1152 | Predecessors: 1:471f378eab4c
1153 | semi-colon: 1:471f378eab4c
1153 | semi-colon: 1:471f378eab4c
1154 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1154 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1155 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1155 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1156 | @ 471f378eab4c
1156 | @ 471f378eab4c
1157 |/ Successors: 4:eb5a0daa2192
1157 |/ Successors: 4:eb5a0daa2192
1158 | multi-line: 4:eb5a0daa2192
1158 | multi-line: 4:eb5a0daa2192
1159 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
1159 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
1160 o ea207398892e
1160 o ea207398892e
1161
1161
1162
1162
1163 $ hg fatelog
1163 $ hg fatelog
1164 o eb5a0daa2192
1164 o eb5a0daa2192
1165 |
1165 |
1166 | @ 471f378eab4c
1166 | @ 471f378eab4c
1167 |/ Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
1167 |/ Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
1168 o ea207398892e
1168 o ea207398892e
1169
1169
1170 $ hg up 'desc(B0)' --hidden
1170 $ hg up 'desc(B0)' --hidden
1171 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1171 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1172
1172
1173 Predecessors template should both predecessors as they are visible
1173 Predecessors template should both predecessors as they are visible
1174 $ hg tlog
1174 $ hg tlog
1175 o eb5a0daa2192
1175 o eb5a0daa2192
1176 | Predecessors: 2:0dec01379d3b 1:471f378eab4c
1176 | Predecessors: 2:0dec01379d3b 1:471f378eab4c
1177 | semi-colon: 2:0dec01379d3b; 1:471f378eab4c
1177 | semi-colon: 2:0dec01379d3b; 1:471f378eab4c
1178 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
1178 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", "471f378eab4c5e25f6c77f785b27c936efb22874"]
1179 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5 1:471f378eab4c5e25f6c77f785b27c936efb22874
1179 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5 1:471f378eab4c5e25f6c77f785b27c936efb22874
1180 | @ 0dec01379d3b
1180 | @ 0dec01379d3b
1181 | | Successors: 4:eb5a0daa2192
1181 | | Successors: 4:eb5a0daa2192
1182 | | multi-line: 4:eb5a0daa2192
1182 | | multi-line: 4:eb5a0daa2192
1183 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
1183 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
1184 | x 471f378eab4c
1184 | x 471f378eab4c
1185 |/ Successors: 4:eb5a0daa2192
1185 |/ Successors: 4:eb5a0daa2192
1186 | multi-line: 4:eb5a0daa2192
1186 | multi-line: 4:eb5a0daa2192
1187 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
1187 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
1188 o ea207398892e
1188 o ea207398892e
1189
1189
1190
1190
1191 $ hg fatelog
1191 $ hg fatelog
1192 o eb5a0daa2192
1192 o eb5a0daa2192
1193 |
1193 |
1194 | @ 0dec01379d3b
1194 | @ 0dec01379d3b
1195 | | Obsfate: rewritten using amend as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
1195 | | Obsfate: rewritten using amend as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
1196 | x 471f378eab4c
1196 | x 471f378eab4c
1197 |/ Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
1197 |/ Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
1198 o ea207398892e
1198 o ea207398892e
1199
1199
1200 $ hg up 'desc(B1)' --hidden
1200 $ hg up 'desc(B1)' --hidden
1201 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1201 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1202
1202
1203 Predecessors template should both predecessors as they are visible
1203 Predecessors template should both predecessors as they are visible
1204 $ hg tlog
1204 $ hg tlog
1205 o eb5a0daa2192
1205 o eb5a0daa2192
1206 | Predecessors: 1:471f378eab4c 3:b7ea6d14e664
1206 | Predecessors: 1:471f378eab4c 3:b7ea6d14e664
1207 | semi-colon: 1:471f378eab4c; 3:b7ea6d14e664
1207 | semi-colon: 1:471f378eab4c; 3:b7ea6d14e664
1208 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874", "b7ea6d14e664bdc8922221f7992631b50da3fb07"]
1208 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874", "b7ea6d14e664bdc8922221f7992631b50da3fb07"]
1209 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874 3:b7ea6d14e664bdc8922221f7992631b50da3fb07
1209 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874 3:b7ea6d14e664bdc8922221f7992631b50da3fb07
1210 | @ b7ea6d14e664
1210 | @ b7ea6d14e664
1211 | | Successors: 4:eb5a0daa2192
1211 | | Successors: 4:eb5a0daa2192
1212 | | multi-line: 4:eb5a0daa2192
1212 | | multi-line: 4:eb5a0daa2192
1213 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
1213 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
1214 | x 471f378eab4c
1214 | x 471f378eab4c
1215 |/ Successors: 4:eb5a0daa2192
1215 |/ Successors: 4:eb5a0daa2192
1216 | multi-line: 4:eb5a0daa2192
1216 | multi-line: 4:eb5a0daa2192
1217 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
1217 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
1218 o ea207398892e
1218 o ea207398892e
1219
1219
1220
1220
1221 $ hg fatelog
1221 $ hg fatelog
1222 o eb5a0daa2192
1222 o eb5a0daa2192
1223 |
1223 |
1224 | @ b7ea6d14e664
1224 | @ b7ea6d14e664
1225 | | Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
1225 | | Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
1226 | x 471f378eab4c
1226 | x 471f378eab4c
1227 |/ Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
1227 |/ Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
1228 o ea207398892e
1228 o ea207398892e
1229
1229
1230 $ hg up 'desc(C0)'
1230 $ hg up 'desc(C0)'
1231 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1231 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1232
1232
1233 Predecessors template should show no predecessors as they are both non visible
1233 Predecessors template should show no predecessors as they are both non visible
1234 $ hg tlog
1234 $ hg tlog
1235 @ eb5a0daa2192
1235 @ eb5a0daa2192
1236 |
1236 |
1237 o ea207398892e
1237 o ea207398892e
1238
1238
1239
1239
1240 $ hg fatelog
1240 $ hg fatelog
1241 @ eb5a0daa2192
1241 @ eb5a0daa2192
1242 |
1242 |
1243 o ea207398892e
1243 o ea207398892e
1244
1244
1245 Predecessors template should show all predecessors as we force their display
1245 Predecessors template should show all predecessors as we force their display
1246 with --hidden
1246 with --hidden
1247 $ hg tlog --hidden
1247 $ hg tlog --hidden
1248 @ eb5a0daa2192
1248 @ eb5a0daa2192
1249 | Predecessors: 1:471f378eab4c 3:b7ea6d14e664
1249 | Predecessors: 1:471f378eab4c 3:b7ea6d14e664
1250 | semi-colon: 1:471f378eab4c; 3:b7ea6d14e664
1250 | semi-colon: 1:471f378eab4c; 3:b7ea6d14e664
1251 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874", "b7ea6d14e664bdc8922221f7992631b50da3fb07"]
1251 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874", "b7ea6d14e664bdc8922221f7992631b50da3fb07"]
1252 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874 3:b7ea6d14e664bdc8922221f7992631b50da3fb07
1252 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874 3:b7ea6d14e664bdc8922221f7992631b50da3fb07
1253 | x b7ea6d14e664
1253 | x b7ea6d14e664
1254 | | Predecessors: 2:0dec01379d3b
1254 | | Predecessors: 2:0dec01379d3b
1255 | | semi-colon: 2:0dec01379d3b
1255 | | semi-colon: 2:0dec01379d3b
1256 | | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1256 | | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1257 | | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1257 | | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1258 | | Successors: 4:eb5a0daa2192
1258 | | Successors: 4:eb5a0daa2192
1259 | | multi-line: 4:eb5a0daa2192
1259 | | multi-line: 4:eb5a0daa2192
1260 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
1260 | | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
1261 | | x 0dec01379d3b
1261 | | x 0dec01379d3b
1262 | |/ Successors: 3:b7ea6d14e664
1262 | |/ Successors: 3:b7ea6d14e664
1263 | | multi-line: 3:b7ea6d14e664
1263 | | multi-line: 3:b7ea6d14e664
1264 | | json: [["b7ea6d14e664bdc8922221f7992631b50da3fb07"]]
1264 | | json: [["b7ea6d14e664bdc8922221f7992631b50da3fb07"]]
1265 | x 471f378eab4c
1265 | x 471f378eab4c
1266 |/ Successors: 4:eb5a0daa2192
1266 |/ Successors: 4:eb5a0daa2192
1267 | multi-line: 4:eb5a0daa2192
1267 | multi-line: 4:eb5a0daa2192
1268 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
1268 | json: [["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]]
1269 o ea207398892e
1269 o ea207398892e
1270
1270
1271
1271
1272 $ hg fatelog --hidden
1272 $ hg fatelog --hidden
1273 @ eb5a0daa2192
1273 @ eb5a0daa2192
1274 |
1274 |
1275 | x b7ea6d14e664
1275 | x b7ea6d14e664
1276 | | Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
1276 | | Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
1277 | | x 0dec01379d3b
1277 | | x 0dec01379d3b
1278 | |/ Obsfate: rewritten using amend as 3:b7ea6d14e664 by test (at 1970-01-01 00:00 +0000);
1278 | |/ Obsfate: rewritten using amend as 3:b7ea6d14e664 by test (at 1970-01-01 00:00 +0000);
1279 | x 471f378eab4c
1279 | x 471f378eab4c
1280 |/ Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
1280 |/ Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000);
1281 o ea207398892e
1281 o ea207398892e
1282
1282
1283
1283
1284 $ hg fatelogjson --hidden
1284 $ hg fatelogjson --hidden
1285 @ eb5a0daa2192
1285 @ eb5a0daa2192
1286 |
1286 |
1287 | x b7ea6d14e664
1287 | x b7ea6d14e664
1288 | | Obsfate: [{"markers": [["b7ea6d14e664bdc8922221f7992631b50da3fb07", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]}]
1288 | | Obsfate: [{"markers": [["b7ea6d14e664bdc8922221f7992631b50da3fb07", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]}]
1289 | | x 0dec01379d3b
1289 | | x 0dec01379d3b
1290 | |/ Obsfate: [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["b7ea6d14e664bdc8922221f7992631b50da3fb07"], 0, [["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "successors": ["b7ea6d14e664bdc8922221f7992631b50da3fb07"]}]
1290 | |/ Obsfate: [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["b7ea6d14e664bdc8922221f7992631b50da3fb07"], 0, [["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "successors": ["b7ea6d14e664bdc8922221f7992631b50da3fb07"]}]
1291 | x 471f378eab4c
1291 | x 471f378eab4c
1292 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]}]
1292 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"]}]
1293 o ea207398892e
1293 o ea207398892e
1294
1294
1295
1295
1296 Check other fatelog implementations
1296 Check other fatelog implementations
1297 -----------------------------------
1297 -----------------------------------
1298
1298
1299 $ hg fatelogkw --hidden -q
1299 $ hg fatelogkw --hidden -q
1300 @ eb5a0daa2192
1300 @ eb5a0daa2192
1301 |
1301 |
1302 | x b7ea6d14e664
1302 | x b7ea6d14e664
1303 | | Obsfate: rewritten as 4:eb5a0daa2192
1303 | | Obsfate: rewritten as 4:eb5a0daa2192
1304 | | x 0dec01379d3b
1304 | | x 0dec01379d3b
1305 | |/ Obsfate: rewritten using amend as 3:b7ea6d14e664
1305 | |/ Obsfate: rewritten using amend as 3:b7ea6d14e664
1306 | x 471f378eab4c
1306 | x 471f378eab4c
1307 |/ Obsfate: rewritten as 4:eb5a0daa2192
1307 |/ Obsfate: rewritten as 4:eb5a0daa2192
1308 o ea207398892e
1308 o ea207398892e
1309
1309
1310 $ hg fatelogkw --hidden
1310 $ hg fatelogkw --hidden
1311 @ eb5a0daa2192
1311 @ eb5a0daa2192
1312 |
1312 |
1313 | x b7ea6d14e664
1313 | x b7ea6d14e664
1314 | | Obsfate: rewritten as 4:eb5a0daa2192
1314 | | Obsfate: rewritten as 4:eb5a0daa2192
1315 | | x 0dec01379d3b
1315 | | x 0dec01379d3b
1316 | |/ Obsfate: rewritten using amend as 3:b7ea6d14e664
1316 | |/ Obsfate: rewritten using amend as 3:b7ea6d14e664
1317 | x 471f378eab4c
1317 | x 471f378eab4c
1318 |/ Obsfate: rewritten as 4:eb5a0daa2192
1318 |/ Obsfate: rewritten as 4:eb5a0daa2192
1319 o ea207398892e
1319 o ea207398892e
1320
1320
1321 $ hg fatelogkw --hidden -v
1321 $ hg fatelogkw --hidden -v
1322 @ eb5a0daa2192
1322 @ eb5a0daa2192
1323 |
1323 |
1324 | x b7ea6d14e664
1324 | x b7ea6d14e664
1325 | | Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000)
1325 | | Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000)
1326 | | x 0dec01379d3b
1326 | | x 0dec01379d3b
1327 | |/ Obsfate: rewritten using amend as 3:b7ea6d14e664 by test (at 1970-01-01 00:00 +0000)
1327 | |/ Obsfate: rewritten using amend as 3:b7ea6d14e664 by test (at 1970-01-01 00:00 +0000)
1328 | x 471f378eab4c
1328 | x 471f378eab4c
1329 |/ Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000)
1329 |/ Obsfate: rewritten as 4:eb5a0daa2192 by test (at 1970-01-01 00:00 +0000)
1330 o ea207398892e
1330 o ea207398892e
1331
1331
1332 $ hg log -G -T "default" --hidden
1332 $ hg log -G -T "default" --hidden
1333 @ changeset: 4:eb5a0daa2192
1333 @ changeset: 4:eb5a0daa2192
1334 | tag: tip
1334 | tag: tip
1335 | parent: 0:ea207398892e
1335 | parent: 0:ea207398892e
1336 | user: test
1336 | user: test
1337 | date: Thu Jan 01 00:00:00 1970 +0000
1337 | date: Thu Jan 01 00:00:00 1970 +0000
1338 | summary: C0
1338 | summary: C0
1339 |
1339 |
1340 | x changeset: 3:b7ea6d14e664
1340 | x changeset: 3:b7ea6d14e664
1341 | | parent: 1:471f378eab4c
1341 | | parent: 1:471f378eab4c
1342 | | user: test
1342 | | user: test
1343 | | date: Thu Jan 01 00:00:00 1970 +0000
1343 | | date: Thu Jan 01 00:00:00 1970 +0000
1344 | | obsfate: rewritten as 4:eb5a0daa2192
1344 | | obsfate: rewritten as 4:eb5a0daa2192
1345 | | summary: B1
1345 | | summary: B1
1346 | |
1346 | |
1347 | | x changeset: 2:0dec01379d3b
1347 | | x changeset: 2:0dec01379d3b
1348 | |/ user: test
1348 | |/ user: test
1349 | | date: Thu Jan 01 00:00:00 1970 +0000
1349 | | date: Thu Jan 01 00:00:00 1970 +0000
1350 | | obsfate: rewritten using amend as 3:b7ea6d14e664
1350 | | obsfate: rewritten using amend as 3:b7ea6d14e664
1351 | | summary: B0
1351 | | summary: B0
1352 | |
1352 | |
1353 | x changeset: 1:471f378eab4c
1353 | x changeset: 1:471f378eab4c
1354 |/ user: test
1354 |/ user: test
1355 | date: Thu Jan 01 00:00:00 1970 +0000
1355 | date: Thu Jan 01 00:00:00 1970 +0000
1356 | obsfate: rewritten as 4:eb5a0daa2192
1356 | obsfate: rewritten as 4:eb5a0daa2192
1357 | summary: A0
1357 | summary: A0
1358 |
1358 |
1359 o changeset: 0:ea207398892e
1359 o changeset: 0:ea207398892e
1360 user: test
1360 user: test
1361 date: Thu Jan 01 00:00:00 1970 +0000
1361 date: Thu Jan 01 00:00:00 1970 +0000
1362 summary: ROOT
1362 summary: ROOT
1363
1363
1364
1364
1365 Test template with pushed and pulled obs markers
1365 Test template with pushed and pulled obs markers
1366 ================================================
1366 ================================================
1367
1367
1368 Test setup
1368 Test setup
1369 ----------
1369 ----------
1370
1370
1371 $ hg init $TESTTMP/templates-local-remote-markers-1
1371 $ hg init $TESTTMP/templates-local-remote-markers-1
1372 $ cd $TESTTMP/templates-local-remote-markers-1
1372 $ cd $TESTTMP/templates-local-remote-markers-1
1373 $ mkcommit ROOT
1373 $ mkcommit ROOT
1374 $ mkcommit A0
1374 $ mkcommit A0
1375 $ hg clone $TESTTMP/templates-local-remote-markers-1 $TESTTMP/templates-local-remote-markers-2
1375 $ hg clone $TESTTMP/templates-local-remote-markers-1 $TESTTMP/templates-local-remote-markers-2
1376 updating to branch default
1376 updating to branch default
1377 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1377 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1378 $ cd $TESTTMP/templates-local-remote-markers-2
1378 $ cd $TESTTMP/templates-local-remote-markers-2
1379 $ hg log --hidden -G
1379 $ hg log --hidden -G
1380 @ changeset: 1:471f378eab4c
1380 @ changeset: 1:471f378eab4c
1381 | tag: tip
1381 | tag: tip
1382 | user: test
1382 | user: test
1383 | date: Thu Jan 01 00:00:00 1970 +0000
1383 | date: Thu Jan 01 00:00:00 1970 +0000
1384 | summary: A0
1384 | summary: A0
1385 |
1385 |
1386 o changeset: 0:ea207398892e
1386 o changeset: 0:ea207398892e
1387 user: test
1387 user: test
1388 date: Thu Jan 01 00:00:00 1970 +0000
1388 date: Thu Jan 01 00:00:00 1970 +0000
1389 summary: ROOT
1389 summary: ROOT
1390
1390
1391 $ cd $TESTTMP/templates-local-remote-markers-1
1391 $ cd $TESTTMP/templates-local-remote-markers-1
1392 $ hg commit --amend -m "A1"
1392 $ hg commit --amend -m "A1"
1393 $ hg commit --amend -m "A2"
1393 $ hg commit --amend -m "A2"
1394 $ hg log --hidden -G
1394 $ hg log --hidden -G
1395 @ changeset: 3:7a230b46bf61
1395 @ changeset: 3:7a230b46bf61
1396 | tag: tip
1396 | tag: tip
1397 | parent: 0:ea207398892e
1397 | parent: 0:ea207398892e
1398 | user: test
1398 | user: test
1399 | date: Thu Jan 01 00:00:00 1970 +0000
1399 | date: Thu Jan 01 00:00:00 1970 +0000
1400 | summary: A2
1400 | summary: A2
1401 |
1401 |
1402 | x changeset: 2:fdf9bde5129a
1402 | x changeset: 2:fdf9bde5129a
1403 |/ parent: 0:ea207398892e
1403 |/ parent: 0:ea207398892e
1404 | user: test
1404 | user: test
1405 | date: Thu Jan 01 00:00:00 1970 +0000
1405 | date: Thu Jan 01 00:00:00 1970 +0000
1406 | obsfate: rewritten using amend as 3:7a230b46bf61
1406 | obsolete: rewritten using amend as 3:7a230b46bf61
1407 | summary: A1
1407 | summary: A1
1408 |
1408 |
1409 | x changeset: 1:471f378eab4c
1409 | x changeset: 1:471f378eab4c
1410 |/ user: test
1410 |/ user: test
1411 | date: Thu Jan 01 00:00:00 1970 +0000
1411 | date: Thu Jan 01 00:00:00 1970 +0000
1412 | obsfate: rewritten using amend as 2:fdf9bde5129a
1412 | obsolete: rewritten using amend as 2:fdf9bde5129a
1413 | summary: A0
1413 | summary: A0
1414 |
1414 |
1415 o changeset: 0:ea207398892e
1415 o changeset: 0:ea207398892e
1416 user: test
1416 user: test
1417 date: Thu Jan 01 00:00:00 1970 +0000
1417 date: Thu Jan 01 00:00:00 1970 +0000
1418 summary: ROOT
1418 summary: ROOT
1419
1419
1420 $ cd $TESTTMP/templates-local-remote-markers-2
1420 $ cd $TESTTMP/templates-local-remote-markers-2
1421 $ hg pull
1421 $ hg pull
1422 pulling from $TESTTMP/templates-local-remote-markers-1 (glob)
1422 pulling from $TESTTMP/templates-local-remote-markers-1 (glob)
1423 searching for changes
1423 searching for changes
1424 adding changesets
1424 adding changesets
1425 adding manifests
1425 adding manifests
1426 adding file changes
1426 adding file changes
1427 added 1 changesets with 0 changes to 1 files (+1 heads)
1427 added 1 changesets with 0 changes to 1 files (+1 heads)
1428 2 new obsolescence markers
1428 2 new obsolescence markers
1429 obsoleted 1 changesets
1429 obsoleted 1 changesets
1430 new changesets 7a230b46bf61
1430 new changesets 7a230b46bf61
1431 (run 'hg heads' to see heads, 'hg merge' to merge)
1431 (run 'hg heads' to see heads, 'hg merge' to merge)
1432 $ hg log --hidden -G
1432 $ hg log --hidden -G
1433 o changeset: 2:7a230b46bf61
1433 o changeset: 2:7a230b46bf61
1434 | tag: tip
1434 | tag: tip
1435 | parent: 0:ea207398892e
1435 | parent: 0:ea207398892e
1436 | user: test
1436 | user: test
1437 | date: Thu Jan 01 00:00:00 1970 +0000
1437 | date: Thu Jan 01 00:00:00 1970 +0000
1438 | summary: A2
1438 | summary: A2
1439 |
1439 |
1440 | @ changeset: 1:471f378eab4c
1440 | @ changeset: 1:471f378eab4c
1441 |/ user: test
1441 |/ user: test
1442 | date: Thu Jan 01 00:00:00 1970 +0000
1442 | date: Thu Jan 01 00:00:00 1970 +0000
1443 | obsfate: rewritten using amend as 2:7a230b46bf61
1443 | obsolete: rewritten using amend as 2:7a230b46bf61
1444 | summary: A0
1444 | summary: A0
1445 |
1445 |
1446 o changeset: 0:ea207398892e
1446 o changeset: 0:ea207398892e
1447 user: test
1447 user: test
1448 date: Thu Jan 01 00:00:00 1970 +0000
1448 date: Thu Jan 01 00:00:00 1970 +0000
1449 summary: ROOT
1449 summary: ROOT
1450
1450
1451
1451
1452 $ hg debugobsolete
1452 $ hg debugobsolete
1453 471f378eab4c5e25f6c77f785b27c936efb22874 fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1453 471f378eab4c5e25f6c77f785b27c936efb22874 fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1454 fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e 7a230b46bf61e50b30308c6cfd7bd1269ef54702 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1454 fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e 7a230b46bf61e50b30308c6cfd7bd1269ef54702 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1455
1455
1456 Check templates
1456 Check templates
1457 ---------------
1457 ---------------
1458
1458
1459 Predecessors template should show current revision as it is the working copy
1459 Predecessors template should show current revision as it is the working copy
1460 $ hg tlog
1460 $ hg tlog
1461 o 7a230b46bf61
1461 o 7a230b46bf61
1462 | Predecessors: 1:471f378eab4c
1462 | Predecessors: 1:471f378eab4c
1463 | semi-colon: 1:471f378eab4c
1463 | semi-colon: 1:471f378eab4c
1464 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1464 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1465 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1465 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1466 | @ 471f378eab4c
1466 | @ 471f378eab4c
1467 |/ Successors: 2:7a230b46bf61
1467 |/ Successors: 2:7a230b46bf61
1468 | multi-line: 2:7a230b46bf61
1468 | multi-line: 2:7a230b46bf61
1469 | json: [["7a230b46bf61e50b30308c6cfd7bd1269ef54702"]]
1469 | json: [["7a230b46bf61e50b30308c6cfd7bd1269ef54702"]]
1470 o ea207398892e
1470 o ea207398892e
1471
1471
1472
1472
1473 $ hg fatelog
1473 $ hg fatelog
1474 o 7a230b46bf61
1474 o 7a230b46bf61
1475 |
1475 |
1476 | @ 471f378eab4c
1476 | @ 471f378eab4c
1477 |/ Obsfate: rewritten using amend as 2:7a230b46bf61 by test (at 1970-01-01 00:00 +0000);
1477 |/ Obsfate: rewritten using amend as 2:7a230b46bf61 by test (at 1970-01-01 00:00 +0000);
1478 o ea207398892e
1478 o ea207398892e
1479
1479
1480 $ hg up 'desc(A2)'
1480 $ hg up 'desc(A2)'
1481 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1481 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1482
1482
1483 Predecessors template should show no predecessors as they are non visible
1483 Predecessors template should show no predecessors as they are non visible
1484 $ hg tlog
1484 $ hg tlog
1485 @ 7a230b46bf61
1485 @ 7a230b46bf61
1486 |
1486 |
1487 o ea207398892e
1487 o ea207398892e
1488
1488
1489
1489
1490 $ hg fatelog
1490 $ hg fatelog
1491 @ 7a230b46bf61
1491 @ 7a230b46bf61
1492 |
1492 |
1493 o ea207398892e
1493 o ea207398892e
1494
1494
1495 Predecessors template should show all predecessors as we force their display
1495 Predecessors template should show all predecessors as we force their display
1496 with --hidden
1496 with --hidden
1497 $ hg tlog --hidden
1497 $ hg tlog --hidden
1498 @ 7a230b46bf61
1498 @ 7a230b46bf61
1499 | Predecessors: 1:471f378eab4c
1499 | Predecessors: 1:471f378eab4c
1500 | semi-colon: 1:471f378eab4c
1500 | semi-colon: 1:471f378eab4c
1501 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1501 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1502 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1502 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1503 | x 471f378eab4c
1503 | x 471f378eab4c
1504 |/ Successors: 2:7a230b46bf61
1504 |/ Successors: 2:7a230b46bf61
1505 | multi-line: 2:7a230b46bf61
1505 | multi-line: 2:7a230b46bf61
1506 | json: [["7a230b46bf61e50b30308c6cfd7bd1269ef54702"]]
1506 | json: [["7a230b46bf61e50b30308c6cfd7bd1269ef54702"]]
1507 o ea207398892e
1507 o ea207398892e
1508
1508
1509
1509
1510 $ hg fatelog --hidden
1510 $ hg fatelog --hidden
1511 @ 7a230b46bf61
1511 @ 7a230b46bf61
1512 |
1512 |
1513 | x 471f378eab4c
1513 | x 471f378eab4c
1514 |/ Obsfate: rewritten using amend as 2:7a230b46bf61 by test (at 1970-01-01 00:00 +0000);
1514 |/ Obsfate: rewritten using amend as 2:7a230b46bf61 by test (at 1970-01-01 00:00 +0000);
1515 o ea207398892e
1515 o ea207398892e
1516
1516
1517
1517
1518 Check other fatelog implementations
1518 Check other fatelog implementations
1519 -----------------------------------
1519 -----------------------------------
1520
1520
1521 $ hg fatelogkw --hidden -q
1521 $ hg fatelogkw --hidden -q
1522 @ 7a230b46bf61
1522 @ 7a230b46bf61
1523 |
1523 |
1524 | x 471f378eab4c
1524 | x 471f378eab4c
1525 |/ Obsfate: rewritten using amend as 2:7a230b46bf61
1525 |/ Obsfate: rewritten using amend as 2:7a230b46bf61
1526 o ea207398892e
1526 o ea207398892e
1527
1527
1528 $ hg fatelogkw --hidden
1528 $ hg fatelogkw --hidden
1529 @ 7a230b46bf61
1529 @ 7a230b46bf61
1530 |
1530 |
1531 | x 471f378eab4c
1531 | x 471f378eab4c
1532 |/ Obsfate: rewritten using amend as 2:7a230b46bf61
1532 |/ Obsfate: rewritten using amend as 2:7a230b46bf61
1533 o ea207398892e
1533 o ea207398892e
1534
1534
1535 $ hg fatelogkw --hidden -v
1535 $ hg fatelogkw --hidden -v
1536 @ 7a230b46bf61
1536 @ 7a230b46bf61
1537 |
1537 |
1538 | x 471f378eab4c
1538 | x 471f378eab4c
1539 |/ Obsfate: rewritten using amend as 2:7a230b46bf61 by test (at 1970-01-01 00:00 +0000)
1539 |/ Obsfate: rewritten using amend as 2:7a230b46bf61 by test (at 1970-01-01 00:00 +0000)
1540 o ea207398892e
1540 o ea207398892e
1541
1541
1542 $ hg log -G -T "default" --hidden
1542 $ hg log -G -T "default" --hidden
1543 @ changeset: 2:7a230b46bf61
1543 @ changeset: 2:7a230b46bf61
1544 | tag: tip
1544 | tag: tip
1545 | parent: 0:ea207398892e
1545 | parent: 0:ea207398892e
1546 | user: test
1546 | user: test
1547 | date: Thu Jan 01 00:00:00 1970 +0000
1547 | date: Thu Jan 01 00:00:00 1970 +0000
1548 | summary: A2
1548 | summary: A2
1549 |
1549 |
1550 | x changeset: 1:471f378eab4c
1550 | x changeset: 1:471f378eab4c
1551 |/ user: test
1551 |/ user: test
1552 | date: Thu Jan 01 00:00:00 1970 +0000
1552 | date: Thu Jan 01 00:00:00 1970 +0000
1553 | obsfate: rewritten using amend as 2:7a230b46bf61
1553 | obsfate: rewritten using amend as 2:7a230b46bf61
1554 | summary: A0
1554 | summary: A0
1555 |
1555 |
1556 o changeset: 0:ea207398892e
1556 o changeset: 0:ea207398892e
1557 user: test
1557 user: test
1558 date: Thu Jan 01 00:00:00 1970 +0000
1558 date: Thu Jan 01 00:00:00 1970 +0000
1559 summary: ROOT
1559 summary: ROOT
1560
1560
1561
1561
1562 Test template with obsmarkers cycle
1562 Test template with obsmarkers cycle
1563 ===================================
1563 ===================================
1564
1564
1565 Test setup
1565 Test setup
1566 ----------
1566 ----------
1567
1567
1568 $ hg init $TESTTMP/templates-local-cycle
1568 $ hg init $TESTTMP/templates-local-cycle
1569 $ cd $TESTTMP/templates-local-cycle
1569 $ cd $TESTTMP/templates-local-cycle
1570 $ mkcommit ROOT
1570 $ mkcommit ROOT
1571 $ mkcommit A0
1571 $ mkcommit A0
1572 $ mkcommit B0
1572 $ mkcommit B0
1573 $ hg up -r 0
1573 $ hg up -r 0
1574 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1574 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1575 $ mkcommit C0
1575 $ mkcommit C0
1576 created new head
1576 created new head
1577
1577
1578 Create the cycle
1578 Create the cycle
1579
1579
1580 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(B0)"`
1580 $ hg debugobsolete `getid "desc(A0)"` `getid "desc(B0)"`
1581 obsoleted 1 changesets
1581 obsoleted 1 changesets
1582 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(C0)"`
1582 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(C0)"`
1583 obsoleted 1 changesets
1583 obsoleted 1 changesets
1584 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(A0)"`
1584 $ hg debugobsolete `getid "desc(B0)"` `getid "desc(A0)"`
1585
1585
1586 Check templates
1586 Check templates
1587 ---------------
1587 ---------------
1588
1588
1589 $ hg tlog
1589 $ hg tlog
1590 @ f897c6137566
1590 @ f897c6137566
1591 |
1591 |
1592 o ea207398892e
1592 o ea207398892e
1593
1593
1594
1594
1595 $ hg fatelog
1595 $ hg fatelog
1596 @ f897c6137566
1596 @ f897c6137566
1597 |
1597 |
1598 o ea207398892e
1598 o ea207398892e
1599
1599
1600
1600
1601 $ hg up -r "desc(B0)" --hidden
1601 $ hg up -r "desc(B0)" --hidden
1602 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1602 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
1603 $ hg tlog
1603 $ hg tlog
1604 o f897c6137566
1604 o f897c6137566
1605 | Predecessors: 2:0dec01379d3b
1605 | Predecessors: 2:0dec01379d3b
1606 | semi-colon: 2:0dec01379d3b
1606 | semi-colon: 2:0dec01379d3b
1607 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1607 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1608 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1608 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1609 | @ 0dec01379d3b
1609 | @ 0dec01379d3b
1610 | | Predecessors: 1:471f378eab4c
1610 | | Predecessors: 1:471f378eab4c
1611 | | semi-colon: 1:471f378eab4c
1611 | | semi-colon: 1:471f378eab4c
1612 | | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1612 | | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1613 | | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1613 | | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1614 | | Successors: 3:f897c6137566; 1:471f378eab4c
1614 | | Successors: 3:f897c6137566; 1:471f378eab4c
1615 | | multi-line: 3:f897c6137566
1615 | | multi-line: 3:f897c6137566
1616 | | multi-line: 1:471f378eab4c
1616 | | multi-line: 1:471f378eab4c
1617 | | json: [["f897c6137566320b081514b4c7227ecc3d384b39"], ["471f378eab4c5e25f6c77f785b27c936efb22874"]]
1617 | | json: [["f897c6137566320b081514b4c7227ecc3d384b39"], ["471f378eab4c5e25f6c77f785b27c936efb22874"]]
1618 | x 471f378eab4c
1618 | x 471f378eab4c
1619 |/ Predecessors: 2:0dec01379d3b
1619 |/ Predecessors: 2:0dec01379d3b
1620 | semi-colon: 2:0dec01379d3b
1620 | semi-colon: 2:0dec01379d3b
1621 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1621 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1622 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1622 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1623 | Successors: 2:0dec01379d3b
1623 | Successors: 2:0dec01379d3b
1624 | multi-line: 2:0dec01379d3b
1624 | multi-line: 2:0dec01379d3b
1625 | json: [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]]
1625 | json: [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]]
1626 o ea207398892e
1626 o ea207398892e
1627
1627
1628
1628
1629 $ hg fatelog
1629 $ hg fatelog
1630 o f897c6137566
1630 o f897c6137566
1631 |
1631 |
1632 | @ 0dec01379d3b
1632 | @ 0dec01379d3b
1633 | | Obsfate: rewritten as 3:f897c6137566 by test (at 1970-01-01 00:00 +0000); rewritten as 1:471f378eab4c by test (at 1970-01-01 00:00 +0000);
1633 | | Obsfate: rewritten as 3:f897c6137566 by test (at 1970-01-01 00:00 +0000); rewritten as 1:471f378eab4c by test (at 1970-01-01 00:00 +0000);
1634 | x 471f378eab4c
1634 | x 471f378eab4c
1635 |/ Obsfate: rewritten as 2:0dec01379d3b by test (at 1970-01-01 00:00 +0000);
1635 |/ Obsfate: rewritten as 2:0dec01379d3b by test (at 1970-01-01 00:00 +0000);
1636 o ea207398892e
1636 o ea207398892e
1637
1637
1638
1638
1639 $ hg up -r "desc(A0)" --hidden
1639 $ hg up -r "desc(A0)" --hidden
1640 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1640 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1641 $ hg tlog
1641 $ hg tlog
1642 o f897c6137566
1642 o f897c6137566
1643 | Predecessors: 1:471f378eab4c
1643 | Predecessors: 1:471f378eab4c
1644 | semi-colon: 1:471f378eab4c
1644 | semi-colon: 1:471f378eab4c
1645 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1645 | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1646 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1646 | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1647 | @ 471f378eab4c
1647 | @ 471f378eab4c
1648 |/
1648 |/
1649 o ea207398892e
1649 o ea207398892e
1650
1650
1651
1651
1652 $ hg fatelog
1652 $ hg fatelog
1653 o f897c6137566
1653 o f897c6137566
1654 |
1654 |
1655 | @ 471f378eab4c
1655 | @ 471f378eab4c
1656 |/ Obsfate: pruned;
1656 |/ Obsfate: pruned;
1657 o ea207398892e
1657 o ea207398892e
1658
1658
1659
1659
1660 $ hg up -r "desc(ROOT)" --hidden
1660 $ hg up -r "desc(ROOT)" --hidden
1661 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1661 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1662 $ hg tlog
1662 $ hg tlog
1663 o f897c6137566
1663 o f897c6137566
1664 |
1664 |
1665 @ ea207398892e
1665 @ ea207398892e
1666
1666
1667
1667
1668 $ hg fatelog
1668 $ hg fatelog
1669 o f897c6137566
1669 o f897c6137566
1670 |
1670 |
1671 @ ea207398892e
1671 @ ea207398892e
1672
1672
1673
1673
1674 $ hg tlog --hidden
1674 $ hg tlog --hidden
1675 o f897c6137566
1675 o f897c6137566
1676 | Predecessors: 2:0dec01379d3b
1676 | Predecessors: 2:0dec01379d3b
1677 | semi-colon: 2:0dec01379d3b
1677 | semi-colon: 2:0dec01379d3b
1678 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1678 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1679 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1679 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1680 | x 0dec01379d3b
1680 | x 0dec01379d3b
1681 | | Predecessors: 1:471f378eab4c
1681 | | Predecessors: 1:471f378eab4c
1682 | | semi-colon: 1:471f378eab4c
1682 | | semi-colon: 1:471f378eab4c
1683 | | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1683 | | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
1684 | | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1684 | | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
1685 | | Successors: 3:f897c6137566; 1:471f378eab4c
1685 | | Successors: 3:f897c6137566; 1:471f378eab4c
1686 | | multi-line: 3:f897c6137566
1686 | | multi-line: 3:f897c6137566
1687 | | multi-line: 1:471f378eab4c
1687 | | multi-line: 1:471f378eab4c
1688 | | json: [["f897c6137566320b081514b4c7227ecc3d384b39"], ["471f378eab4c5e25f6c77f785b27c936efb22874"]]
1688 | | json: [["f897c6137566320b081514b4c7227ecc3d384b39"], ["471f378eab4c5e25f6c77f785b27c936efb22874"]]
1689 | x 471f378eab4c
1689 | x 471f378eab4c
1690 |/ Predecessors: 2:0dec01379d3b
1690 |/ Predecessors: 2:0dec01379d3b
1691 | semi-colon: 2:0dec01379d3b
1691 | semi-colon: 2:0dec01379d3b
1692 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1692 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1693 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1693 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1694 | Successors: 2:0dec01379d3b
1694 | Successors: 2:0dec01379d3b
1695 | multi-line: 2:0dec01379d3b
1695 | multi-line: 2:0dec01379d3b
1696 | json: [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]]
1696 | json: [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]]
1697 @ ea207398892e
1697 @ ea207398892e
1698
1698
1699
1699
1700 Check other fatelog implementations
1700 Check other fatelog implementations
1701 -----------------------------------
1701 -----------------------------------
1702
1702
1703 $ hg fatelogkw --hidden -q
1703 $ hg fatelogkw --hidden -q
1704 o f897c6137566
1704 o f897c6137566
1705 |
1705 |
1706 | x 0dec01379d3b
1706 | x 0dec01379d3b
1707 | | Obsfate: rewritten as 3:f897c6137566
1707 | | Obsfate: rewritten as 3:f897c6137566
1708 | | Obsfate: rewritten as 1:471f378eab4c
1708 | | Obsfate: rewritten as 1:471f378eab4c
1709 | x 471f378eab4c
1709 | x 471f378eab4c
1710 |/ Obsfate: rewritten as 2:0dec01379d3b
1710 |/ Obsfate: rewritten as 2:0dec01379d3b
1711 @ ea207398892e
1711 @ ea207398892e
1712
1712
1713 $ hg fatelogkw --hidden
1713 $ hg fatelogkw --hidden
1714 o f897c6137566
1714 o f897c6137566
1715 |
1715 |
1716 | x 0dec01379d3b
1716 | x 0dec01379d3b
1717 | | Obsfate: rewritten as 3:f897c6137566
1717 | | Obsfate: rewritten as 3:f897c6137566
1718 | | Obsfate: rewritten as 1:471f378eab4c
1718 | | Obsfate: rewritten as 1:471f378eab4c
1719 | x 471f378eab4c
1719 | x 471f378eab4c
1720 |/ Obsfate: rewritten as 2:0dec01379d3b
1720 |/ Obsfate: rewritten as 2:0dec01379d3b
1721 @ ea207398892e
1721 @ ea207398892e
1722
1722
1723 $ hg fatelogkw --hidden -v
1723 $ hg fatelogkw --hidden -v
1724 o f897c6137566
1724 o f897c6137566
1725 |
1725 |
1726 | x 0dec01379d3b
1726 | x 0dec01379d3b
1727 | | Obsfate: rewritten as 3:f897c6137566 by test (at 1970-01-01 00:00 +0000)
1727 | | Obsfate: rewritten as 3:f897c6137566 by test (at 1970-01-01 00:00 +0000)
1728 | | Obsfate: rewritten as 1:471f378eab4c by test (at 1970-01-01 00:00 +0000)
1728 | | Obsfate: rewritten as 1:471f378eab4c by test (at 1970-01-01 00:00 +0000)
1729 | x 471f378eab4c
1729 | x 471f378eab4c
1730 |/ Obsfate: rewritten as 2:0dec01379d3b by test (at 1970-01-01 00:00 +0000)
1730 |/ Obsfate: rewritten as 2:0dec01379d3b by test (at 1970-01-01 00:00 +0000)
1731 @ ea207398892e
1731 @ ea207398892e
1732
1732
1733 $ hg log -G -T "default" --hidden
1733 $ hg log -G -T "default" --hidden
1734 o changeset: 3:f897c6137566
1734 o changeset: 3:f897c6137566
1735 | tag: tip
1735 | tag: tip
1736 | parent: 0:ea207398892e
1736 | parent: 0:ea207398892e
1737 | user: test
1737 | user: test
1738 | date: Thu Jan 01 00:00:00 1970 +0000
1738 | date: Thu Jan 01 00:00:00 1970 +0000
1739 | summary: C0
1739 | summary: C0
1740 |
1740 |
1741 | x changeset: 2:0dec01379d3b
1741 | x changeset: 2:0dec01379d3b
1742 | | user: test
1742 | | user: test
1743 | | date: Thu Jan 01 00:00:00 1970 +0000
1743 | | date: Thu Jan 01 00:00:00 1970 +0000
1744 | | obsfate: rewritten as 3:f897c6137566
1744 | | obsfate: rewritten as 3:f897c6137566
1745 | | obsfate: rewritten as 1:471f378eab4c
1745 | | obsfate: rewritten as 1:471f378eab4c
1746 | | summary: B0
1746 | | summary: B0
1747 | |
1747 | |
1748 | x changeset: 1:471f378eab4c
1748 | x changeset: 1:471f378eab4c
1749 |/ user: test
1749 |/ user: test
1750 | date: Thu Jan 01 00:00:00 1970 +0000
1750 | date: Thu Jan 01 00:00:00 1970 +0000
1751 | obsfate: rewritten as 2:0dec01379d3b
1751 | obsfate: rewritten as 2:0dec01379d3b
1752 | summary: A0
1752 | summary: A0
1753 |
1753 |
1754 @ changeset: 0:ea207398892e
1754 @ changeset: 0:ea207398892e
1755 user: test
1755 user: test
1756 date: Thu Jan 01 00:00:00 1970 +0000
1756 date: Thu Jan 01 00:00:00 1970 +0000
1757 summary: ROOT
1757 summary: ROOT
1758
1758
1759
1759
1760 Test template with split + divergence with cycles
1760 Test template with split + divergence with cycles
1761 =================================================
1761 =================================================
1762
1762
1763 $ hg log -G
1763 $ hg log -G
1764 o changeset: 3:f897c6137566
1764 o changeset: 3:f897c6137566
1765 | tag: tip
1765 | tag: tip
1766 | parent: 0:ea207398892e
1766 | parent: 0:ea207398892e
1767 | user: test
1767 | user: test
1768 | date: Thu Jan 01 00:00:00 1970 +0000
1768 | date: Thu Jan 01 00:00:00 1970 +0000
1769 | summary: C0
1769 | summary: C0
1770 |
1770 |
1771 @ changeset: 0:ea207398892e
1771 @ changeset: 0:ea207398892e
1772 user: test
1772 user: test
1773 date: Thu Jan 01 00:00:00 1970 +0000
1773 date: Thu Jan 01 00:00:00 1970 +0000
1774 summary: ROOT
1774 summary: ROOT
1775
1775
1776 $ hg up
1776 $ hg up
1777 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1777 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1778
1778
1779 Create a commit with three files
1779 Create a commit with three files
1780 $ touch A B C
1780 $ touch A B C
1781 $ hg commit -A -m "Add A,B,C" A B C
1781 $ hg commit -A -m "Add A,B,C" A B C
1782
1782
1783 Split it
1783 Split it
1784 $ hg up 3
1784 $ hg up 3
1785 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
1785 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
1786 $ touch A
1786 $ touch A
1787 $ hg commit -A -m "Add A,B,C" A
1787 $ hg commit -A -m "Add A,B,C" A
1788 created new head
1788 created new head
1789
1789
1790 $ touch B
1790 $ touch B
1791 $ hg commit -A -m "Add A,B,C" B
1791 $ hg commit -A -m "Add A,B,C" B
1792
1792
1793 $ touch C
1793 $ touch C
1794 $ hg commit -A -m "Add A,B,C" C
1794 $ hg commit -A -m "Add A,B,C" C
1795
1795
1796 $ hg log -G
1796 $ hg log -G
1797 @ changeset: 7:ba2ed02b0c9a
1797 @ changeset: 7:ba2ed02b0c9a
1798 | tag: tip
1798 | tag: tip
1799 | user: test
1799 | user: test
1800 | date: Thu Jan 01 00:00:00 1970 +0000
1800 | date: Thu Jan 01 00:00:00 1970 +0000
1801 | summary: Add A,B,C
1801 | summary: Add A,B,C
1802 |
1802 |
1803 o changeset: 6:4a004186e638
1803 o changeset: 6:4a004186e638
1804 | user: test
1804 | user: test
1805 | date: Thu Jan 01 00:00:00 1970 +0000
1805 | date: Thu Jan 01 00:00:00 1970 +0000
1806 | summary: Add A,B,C
1806 | summary: Add A,B,C
1807 |
1807 |
1808 o changeset: 5:dd800401bd8c
1808 o changeset: 5:dd800401bd8c
1809 | parent: 3:f897c6137566
1809 | parent: 3:f897c6137566
1810 | user: test
1810 | user: test
1811 | date: Thu Jan 01 00:00:00 1970 +0000
1811 | date: Thu Jan 01 00:00:00 1970 +0000
1812 | summary: Add A,B,C
1812 | summary: Add A,B,C
1813 |
1813 |
1814 | o changeset: 4:9bd10a0775e4
1814 | o changeset: 4:9bd10a0775e4
1815 |/ user: test
1815 |/ user: test
1816 | date: Thu Jan 01 00:00:00 1970 +0000
1816 | date: Thu Jan 01 00:00:00 1970 +0000
1817 | summary: Add A,B,C
1817 | summary: Add A,B,C
1818 |
1818 |
1819 o changeset: 3:f897c6137566
1819 o changeset: 3:f897c6137566
1820 | parent: 0:ea207398892e
1820 | parent: 0:ea207398892e
1821 | user: test
1821 | user: test
1822 | date: Thu Jan 01 00:00:00 1970 +0000
1822 | date: Thu Jan 01 00:00:00 1970 +0000
1823 | summary: C0
1823 | summary: C0
1824 |
1824 |
1825 o changeset: 0:ea207398892e
1825 o changeset: 0:ea207398892e
1826 user: test
1826 user: test
1827 date: Thu Jan 01 00:00:00 1970 +0000
1827 date: Thu Jan 01 00:00:00 1970 +0000
1828 summary: ROOT
1828 summary: ROOT
1829
1829
1830 $ hg debugobsolete `getid "4"` `getid "5"` `getid "6"` `getid "7"`
1830 $ hg debugobsolete `getid "4"` `getid "5"` `getid "6"` `getid "7"`
1831 obsoleted 1 changesets
1831 obsoleted 1 changesets
1832 $ hg log -G
1832 $ hg log -G
1833 @ changeset: 7:ba2ed02b0c9a
1833 @ changeset: 7:ba2ed02b0c9a
1834 | tag: tip
1834 | tag: tip
1835 | user: test
1835 | user: test
1836 | date: Thu Jan 01 00:00:00 1970 +0000
1836 | date: Thu Jan 01 00:00:00 1970 +0000
1837 | summary: Add A,B,C
1837 | summary: Add A,B,C
1838 |
1838 |
1839 o changeset: 6:4a004186e638
1839 o changeset: 6:4a004186e638
1840 | user: test
1840 | user: test
1841 | date: Thu Jan 01 00:00:00 1970 +0000
1841 | date: Thu Jan 01 00:00:00 1970 +0000
1842 | summary: Add A,B,C
1842 | summary: Add A,B,C
1843 |
1843 |
1844 o changeset: 5:dd800401bd8c
1844 o changeset: 5:dd800401bd8c
1845 | parent: 3:f897c6137566
1845 | parent: 3:f897c6137566
1846 | user: test
1846 | user: test
1847 | date: Thu Jan 01 00:00:00 1970 +0000
1847 | date: Thu Jan 01 00:00:00 1970 +0000
1848 | summary: Add A,B,C
1848 | summary: Add A,B,C
1849 |
1849 |
1850 o changeset: 3:f897c6137566
1850 o changeset: 3:f897c6137566
1851 | parent: 0:ea207398892e
1851 | parent: 0:ea207398892e
1852 | user: test
1852 | user: test
1853 | date: Thu Jan 01 00:00:00 1970 +0000
1853 | date: Thu Jan 01 00:00:00 1970 +0000
1854 | summary: C0
1854 | summary: C0
1855 |
1855 |
1856 o changeset: 0:ea207398892e
1856 o changeset: 0:ea207398892e
1857 user: test
1857 user: test
1858 date: Thu Jan 01 00:00:00 1970 +0000
1858 date: Thu Jan 01 00:00:00 1970 +0000
1859 summary: ROOT
1859 summary: ROOT
1860
1860
1861 Diverge one of the splitted commit
1861 Diverge one of the splitted commit
1862
1862
1863 $ hg up 6
1863 $ hg up 6
1864 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1864 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1865 $ hg commit --amend -m "Add only B"
1865 $ hg commit --amend -m "Add only B"
1866
1866
1867 $ hg up 6 --hidden
1867 $ hg up 6 --hidden
1868 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1868 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1869 $ hg commit --amend -m "Add B only"
1869 $ hg commit --amend -m "Add B only"
1870
1870
1871 $ hg log -G
1871 $ hg log -G
1872 @ changeset: 9:0b997eb7ceee
1872 @ changeset: 9:0b997eb7ceee
1873 | tag: tip
1873 | tag: tip
1874 | parent: 5:dd800401bd8c
1874 | parent: 5:dd800401bd8c
1875 | user: test
1875 | user: test
1876 | date: Thu Jan 01 00:00:00 1970 +0000
1876 | date: Thu Jan 01 00:00:00 1970 +0000
1877 | instability: content-divergent
1877 | instability: content-divergent
1878 | summary: Add B only
1878 | summary: Add B only
1879 |
1879 |
1880 | o changeset: 8:b18bc8331526
1880 | o changeset: 8:b18bc8331526
1881 |/ parent: 5:dd800401bd8c
1881 |/ parent: 5:dd800401bd8c
1882 | user: test
1882 | user: test
1883 | date: Thu Jan 01 00:00:00 1970 +0000
1883 | date: Thu Jan 01 00:00:00 1970 +0000
1884 | instability: content-divergent
1884 | instability: content-divergent
1885 | summary: Add only B
1885 | summary: Add only B
1886 |
1886 |
1887 | o changeset: 7:ba2ed02b0c9a
1887 | o changeset: 7:ba2ed02b0c9a
1888 | | user: test
1888 | | user: test
1889 | | date: Thu Jan 01 00:00:00 1970 +0000
1889 | | date: Thu Jan 01 00:00:00 1970 +0000
1890 | | instability: orphan, content-divergent
1890 | | instability: orphan, content-divergent
1891 | | summary: Add A,B,C
1891 | | summary: Add A,B,C
1892 | |
1892 | |
1893 | x changeset: 6:4a004186e638
1893 | x changeset: 6:4a004186e638
1894 |/ user: test
1894 |/ user: test
1895 | date: Thu Jan 01 00:00:00 1970 +0000
1895 | date: Thu Jan 01 00:00:00 1970 +0000
1896 | obsfate: rewritten using amend as 8:b18bc8331526
1896 | obsolete: rewritten using amend as 8:b18bc8331526
1897 | obsfate: rewritten using amend as 9:0b997eb7ceee
1897 | obsolete: rewritten using amend as 9:0b997eb7ceee
1898 | summary: Add A,B,C
1898 | summary: Add A,B,C
1899 |
1899 |
1900 o changeset: 5:dd800401bd8c
1900 o changeset: 5:dd800401bd8c
1901 | parent: 3:f897c6137566
1901 | parent: 3:f897c6137566
1902 | user: test
1902 | user: test
1903 | date: Thu Jan 01 00:00:00 1970 +0000
1903 | date: Thu Jan 01 00:00:00 1970 +0000
1904 | instability: content-divergent
1904 | instability: content-divergent
1905 | summary: Add A,B,C
1905 | summary: Add A,B,C
1906 |
1906 |
1907 o changeset: 3:f897c6137566
1907 o changeset: 3:f897c6137566
1908 | parent: 0:ea207398892e
1908 | parent: 0:ea207398892e
1909 | user: test
1909 | user: test
1910 | date: Thu Jan 01 00:00:00 1970 +0000
1910 | date: Thu Jan 01 00:00:00 1970 +0000
1911 | summary: C0
1911 | summary: C0
1912 |
1912 |
1913 o changeset: 0:ea207398892e
1913 o changeset: 0:ea207398892e
1914 user: test
1914 user: test
1915 date: Thu Jan 01 00:00:00 1970 +0000
1915 date: Thu Jan 01 00:00:00 1970 +0000
1916 summary: ROOT
1916 summary: ROOT
1917
1917
1918
1918
1919 Check templates
1919 Check templates
1920 ---------------
1920 ---------------
1921
1921
1922 $ hg tlog
1922 $ hg tlog
1923 @ 0b997eb7ceee
1923 @ 0b997eb7ceee
1924 | Predecessors: 6:4a004186e638
1924 | Predecessors: 6:4a004186e638
1925 | semi-colon: 6:4a004186e638
1925 | semi-colon: 6:4a004186e638
1926 | json: ["4a004186e63889f20cb16434fcbd72220bd1eace"]
1926 | json: ["4a004186e63889f20cb16434fcbd72220bd1eace"]
1927 | map: 6:4a004186e63889f20cb16434fcbd72220bd1eace
1927 | map: 6:4a004186e63889f20cb16434fcbd72220bd1eace
1928 | o b18bc8331526
1928 | o b18bc8331526
1929 |/ Predecessors: 6:4a004186e638
1929 |/ Predecessors: 6:4a004186e638
1930 | semi-colon: 6:4a004186e638
1930 | semi-colon: 6:4a004186e638
1931 | json: ["4a004186e63889f20cb16434fcbd72220bd1eace"]
1931 | json: ["4a004186e63889f20cb16434fcbd72220bd1eace"]
1932 | map: 6:4a004186e63889f20cb16434fcbd72220bd1eace
1932 | map: 6:4a004186e63889f20cb16434fcbd72220bd1eace
1933 | o ba2ed02b0c9a
1933 | o ba2ed02b0c9a
1934 | |
1934 | |
1935 | x 4a004186e638
1935 | x 4a004186e638
1936 |/ Successors: 8:b18bc8331526; 9:0b997eb7ceee
1936 |/ Successors: 8:b18bc8331526; 9:0b997eb7ceee
1937 | multi-line: 8:b18bc8331526
1937 | multi-line: 8:b18bc8331526
1938 | multi-line: 9:0b997eb7ceee
1938 | multi-line: 9:0b997eb7ceee
1939 | json: [["b18bc8331526a22cbb1801022bd1555bf291c48b"], ["0b997eb7ceeee06200a02f8aab185979092d514e"]]
1939 | json: [["b18bc8331526a22cbb1801022bd1555bf291c48b"], ["0b997eb7ceeee06200a02f8aab185979092d514e"]]
1940 o dd800401bd8c
1940 o dd800401bd8c
1941 |
1941 |
1942 o f897c6137566
1942 o f897c6137566
1943 |
1943 |
1944 o ea207398892e
1944 o ea207398892e
1945
1945
1946 $ hg fatelog
1946 $ hg fatelog
1947 @ 0b997eb7ceee
1947 @ 0b997eb7ceee
1948 |
1948 |
1949 | o b18bc8331526
1949 | o b18bc8331526
1950 |/
1950 |/
1951 | o ba2ed02b0c9a
1951 | o ba2ed02b0c9a
1952 | |
1952 | |
1953 | x 4a004186e638
1953 | x 4a004186e638
1954 |/ Obsfate: rewritten using amend as 8:b18bc8331526 by test (at 1970-01-01 00:00 +0000); rewritten using amend as 9:0b997eb7ceee by test (at 1970-01-01 00:00 +0000);
1954 |/ Obsfate: rewritten using amend as 8:b18bc8331526 by test (at 1970-01-01 00:00 +0000); rewritten using amend as 9:0b997eb7ceee by test (at 1970-01-01 00:00 +0000);
1955 o dd800401bd8c
1955 o dd800401bd8c
1956 |
1956 |
1957 o f897c6137566
1957 o f897c6137566
1958 |
1958 |
1959 o ea207398892e
1959 o ea207398892e
1960
1960
1961 $ hg tlog --hidden
1961 $ hg tlog --hidden
1962 @ 0b997eb7ceee
1962 @ 0b997eb7ceee
1963 | Predecessors: 6:4a004186e638
1963 | Predecessors: 6:4a004186e638
1964 | semi-colon: 6:4a004186e638
1964 | semi-colon: 6:4a004186e638
1965 | json: ["4a004186e63889f20cb16434fcbd72220bd1eace"]
1965 | json: ["4a004186e63889f20cb16434fcbd72220bd1eace"]
1966 | map: 6:4a004186e63889f20cb16434fcbd72220bd1eace
1966 | map: 6:4a004186e63889f20cb16434fcbd72220bd1eace
1967 | o b18bc8331526
1967 | o b18bc8331526
1968 |/ Predecessors: 6:4a004186e638
1968 |/ Predecessors: 6:4a004186e638
1969 | semi-colon: 6:4a004186e638
1969 | semi-colon: 6:4a004186e638
1970 | json: ["4a004186e63889f20cb16434fcbd72220bd1eace"]
1970 | json: ["4a004186e63889f20cb16434fcbd72220bd1eace"]
1971 | map: 6:4a004186e63889f20cb16434fcbd72220bd1eace
1971 | map: 6:4a004186e63889f20cb16434fcbd72220bd1eace
1972 | o ba2ed02b0c9a
1972 | o ba2ed02b0c9a
1973 | | Predecessors: 4:9bd10a0775e4
1973 | | Predecessors: 4:9bd10a0775e4
1974 | | semi-colon: 4:9bd10a0775e4
1974 | | semi-colon: 4:9bd10a0775e4
1975 | | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
1975 | | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
1976 | | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
1976 | | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
1977 | x 4a004186e638
1977 | x 4a004186e638
1978 |/ Predecessors: 4:9bd10a0775e4
1978 |/ Predecessors: 4:9bd10a0775e4
1979 | semi-colon: 4:9bd10a0775e4
1979 | semi-colon: 4:9bd10a0775e4
1980 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
1980 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
1981 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
1981 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
1982 | Successors: 8:b18bc8331526; 9:0b997eb7ceee
1982 | Successors: 8:b18bc8331526; 9:0b997eb7ceee
1983 | multi-line: 8:b18bc8331526
1983 | multi-line: 8:b18bc8331526
1984 | multi-line: 9:0b997eb7ceee
1984 | multi-line: 9:0b997eb7ceee
1985 | json: [["b18bc8331526a22cbb1801022bd1555bf291c48b"], ["0b997eb7ceeee06200a02f8aab185979092d514e"]]
1985 | json: [["b18bc8331526a22cbb1801022bd1555bf291c48b"], ["0b997eb7ceeee06200a02f8aab185979092d514e"]]
1986 o dd800401bd8c
1986 o dd800401bd8c
1987 | Predecessors: 4:9bd10a0775e4
1987 | Predecessors: 4:9bd10a0775e4
1988 | semi-colon: 4:9bd10a0775e4
1988 | semi-colon: 4:9bd10a0775e4
1989 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
1989 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
1990 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
1990 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
1991 | x 9bd10a0775e4
1991 | x 9bd10a0775e4
1992 |/ Successors: 5:dd800401bd8c 6:4a004186e638 7:ba2ed02b0c9a
1992 |/ Successors: 5:dd800401bd8c 6:4a004186e638 7:ba2ed02b0c9a
1993 | multi-line: 5:dd800401bd8c 6:4a004186e638 7:ba2ed02b0c9a
1993 | multi-line: 5:dd800401bd8c 6:4a004186e638 7:ba2ed02b0c9a
1994 | json: [["dd800401bd8c79d815329277739e433e883f784e", "4a004186e63889f20cb16434fcbd72220bd1eace", "ba2ed02b0c9a56b9fdbc4e79c7e57866984d8a1f"]]
1994 | json: [["dd800401bd8c79d815329277739e433e883f784e", "4a004186e63889f20cb16434fcbd72220bd1eace", "ba2ed02b0c9a56b9fdbc4e79c7e57866984d8a1f"]]
1995 o f897c6137566
1995 o f897c6137566
1996 | Predecessors: 2:0dec01379d3b
1996 | Predecessors: 2:0dec01379d3b
1997 | semi-colon: 2:0dec01379d3b
1997 | semi-colon: 2:0dec01379d3b
1998 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1998 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
1999 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
1999 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
2000 | x 0dec01379d3b
2000 | x 0dec01379d3b
2001 | | Predecessors: 1:471f378eab4c
2001 | | Predecessors: 1:471f378eab4c
2002 | | semi-colon: 1:471f378eab4c
2002 | | semi-colon: 1:471f378eab4c
2003 | | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
2003 | | json: ["471f378eab4c5e25f6c77f785b27c936efb22874"]
2004 | | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
2004 | | map: 1:471f378eab4c5e25f6c77f785b27c936efb22874
2005 | | Successors: 3:f897c6137566; 1:471f378eab4c
2005 | | Successors: 3:f897c6137566; 1:471f378eab4c
2006 | | multi-line: 3:f897c6137566
2006 | | multi-line: 3:f897c6137566
2007 | | multi-line: 1:471f378eab4c
2007 | | multi-line: 1:471f378eab4c
2008 | | json: [["f897c6137566320b081514b4c7227ecc3d384b39"], ["471f378eab4c5e25f6c77f785b27c936efb22874"]]
2008 | | json: [["f897c6137566320b081514b4c7227ecc3d384b39"], ["471f378eab4c5e25f6c77f785b27c936efb22874"]]
2009 | x 471f378eab4c
2009 | x 471f378eab4c
2010 |/ Predecessors: 2:0dec01379d3b
2010 |/ Predecessors: 2:0dec01379d3b
2011 | semi-colon: 2:0dec01379d3b
2011 | semi-colon: 2:0dec01379d3b
2012 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
2012 | json: ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]
2013 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
2013 | map: 2:0dec01379d3be6318c470ead31b1fe7ae7cb53d5
2014 | Successors: 2:0dec01379d3b
2014 | Successors: 2:0dec01379d3b
2015 | multi-line: 2:0dec01379d3b
2015 | multi-line: 2:0dec01379d3b
2016 | json: [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]]
2016 | json: [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]]
2017 o ea207398892e
2017 o ea207398892e
2018
2018
2019 $ hg fatelog --hidden
2019 $ hg fatelog --hidden
2020 @ 0b997eb7ceee
2020 @ 0b997eb7ceee
2021 |
2021 |
2022 | o b18bc8331526
2022 | o b18bc8331526
2023 |/
2023 |/
2024 | o ba2ed02b0c9a
2024 | o ba2ed02b0c9a
2025 | |
2025 | |
2026 | x 4a004186e638
2026 | x 4a004186e638
2027 |/ Obsfate: rewritten using amend as 8:b18bc8331526 by test (at 1970-01-01 00:00 +0000); rewritten using amend as 9:0b997eb7ceee by test (at 1970-01-01 00:00 +0000);
2027 |/ Obsfate: rewritten using amend as 8:b18bc8331526 by test (at 1970-01-01 00:00 +0000); rewritten using amend as 9:0b997eb7ceee by test (at 1970-01-01 00:00 +0000);
2028 o dd800401bd8c
2028 o dd800401bd8c
2029 |
2029 |
2030 | x 9bd10a0775e4
2030 | x 9bd10a0775e4
2031 |/ Obsfate: split as 5:dd800401bd8c, 6:4a004186e638, 7:ba2ed02b0c9a by test (at 1970-01-01 00:00 +0000);
2031 |/ Obsfate: split as 5:dd800401bd8c, 6:4a004186e638, 7:ba2ed02b0c9a by test (at 1970-01-01 00:00 +0000);
2032 o f897c6137566
2032 o f897c6137566
2033 |
2033 |
2034 | x 0dec01379d3b
2034 | x 0dec01379d3b
2035 | | Obsfate: rewritten as 3:f897c6137566 by test (at 1970-01-01 00:00 +0000); rewritten as 1:471f378eab4c by test (at 1970-01-01 00:00 +0000);
2035 | | Obsfate: rewritten as 3:f897c6137566 by test (at 1970-01-01 00:00 +0000); rewritten as 1:471f378eab4c by test (at 1970-01-01 00:00 +0000);
2036 | x 471f378eab4c
2036 | x 471f378eab4c
2037 |/ Obsfate: rewritten as 2:0dec01379d3b by test (at 1970-01-01 00:00 +0000);
2037 |/ Obsfate: rewritten as 2:0dec01379d3b by test (at 1970-01-01 00:00 +0000);
2038 o ea207398892e
2038 o ea207398892e
2039
2039
2040 $ hg fatelogjson --hidden
2040 $ hg fatelogjson --hidden
2041 @ 0b997eb7ceee
2041 @ 0b997eb7ceee
2042 |
2042 |
2043 | o b18bc8331526
2043 | o b18bc8331526
2044 |/
2044 |/
2045 | o ba2ed02b0c9a
2045 | o ba2ed02b0c9a
2046 | |
2046 | |
2047 | x 4a004186e638
2047 | x 4a004186e638
2048 |/ Obsfate: [{"markers": [["4a004186e63889f20cb16434fcbd72220bd1eace", ["b18bc8331526a22cbb1801022bd1555bf291c48b"], 0, [["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "successors": ["b18bc8331526a22cbb1801022bd1555bf291c48b"]}, {"markers": [["4a004186e63889f20cb16434fcbd72220bd1eace", ["0b997eb7ceeee06200a02f8aab185979092d514e"], 0, [["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "successors": ["0b997eb7ceeee06200a02f8aab185979092d514e"]}]
2048 |/ Obsfate: [{"markers": [["4a004186e63889f20cb16434fcbd72220bd1eace", ["b18bc8331526a22cbb1801022bd1555bf291c48b"], 0, [["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "successors": ["b18bc8331526a22cbb1801022bd1555bf291c48b"]}, {"markers": [["4a004186e63889f20cb16434fcbd72220bd1eace", ["0b997eb7ceeee06200a02f8aab185979092d514e"], 0, [["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "successors": ["0b997eb7ceeee06200a02f8aab185979092d514e"]}]
2049 o dd800401bd8c
2049 o dd800401bd8c
2050 |
2050 |
2051 | x 9bd10a0775e4
2051 | x 9bd10a0775e4
2052 |/ Obsfate: [{"markers": [["9bd10a0775e478708cada5f176ec6de654359ce7", ["dd800401bd8c79d815329277739e433e883f784e", "4a004186e63889f20cb16434fcbd72220bd1eace", "ba2ed02b0c9a56b9fdbc4e79c7e57866984d8a1f"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["dd800401bd8c79d815329277739e433e883f784e", "4a004186e63889f20cb16434fcbd72220bd1eace", "ba2ed02b0c9a56b9fdbc4e79c7e57866984d8a1f"]}]
2052 |/ Obsfate: [{"markers": [["9bd10a0775e478708cada5f176ec6de654359ce7", ["dd800401bd8c79d815329277739e433e883f784e", "4a004186e63889f20cb16434fcbd72220bd1eace", "ba2ed02b0c9a56b9fdbc4e79c7e57866984d8a1f"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["dd800401bd8c79d815329277739e433e883f784e", "4a004186e63889f20cb16434fcbd72220bd1eace", "ba2ed02b0c9a56b9fdbc4e79c7e57866984d8a1f"]}]
2053 o f897c6137566
2053 o f897c6137566
2054 |
2054 |
2055 | x 0dec01379d3b
2055 | x 0dec01379d3b
2056 | | Obsfate: [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["f897c6137566320b081514b4c7227ecc3d384b39"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["f897c6137566320b081514b4c7227ecc3d384b39"]}, {"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["471f378eab4c5e25f6c77f785b27c936efb22874"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["471f378eab4c5e25f6c77f785b27c936efb22874"]}]
2056 | | Obsfate: [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["f897c6137566320b081514b4c7227ecc3d384b39"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["f897c6137566320b081514b4c7227ecc3d384b39"]}, {"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["471f378eab4c5e25f6c77f785b27c936efb22874"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["471f378eab4c5e25f6c77f785b27c936efb22874"]}]
2057 | x 471f378eab4c
2057 | x 471f378eab4c
2058 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]}]
2058 |/ Obsfate: [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"], 0, [["user", "test"]], [0.0, 0], null]], "successors": ["0dec01379d3be6318c470ead31b1fe7ae7cb53d5"]}]
2059 o ea207398892e
2059 o ea207398892e
2060
2060
2061 $ hg up --hidden 4
2061 $ hg up --hidden 4
2062 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2062 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2063 $ hg rebase -r 7 -d 8 --config extensions.rebase=
2063 $ hg rebase -r 7 -d 8 --config extensions.rebase=
2064 rebasing 7:ba2ed02b0c9a "Add A,B,C"
2064 rebasing 7:ba2ed02b0c9a "Add A,B,C"
2065 $ hg tlog
2065 $ hg tlog
2066 o eceed8f98ffc
2066 o eceed8f98ffc
2067 | Predecessors: 4:9bd10a0775e4
2067 | Predecessors: 4:9bd10a0775e4
2068 | semi-colon: 4:9bd10a0775e4
2068 | semi-colon: 4:9bd10a0775e4
2069 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
2069 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
2070 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
2070 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
2071 | o 0b997eb7ceee
2071 | o 0b997eb7ceee
2072 | | Predecessors: 4:9bd10a0775e4
2072 | | Predecessors: 4:9bd10a0775e4
2073 | | semi-colon: 4:9bd10a0775e4
2073 | | semi-colon: 4:9bd10a0775e4
2074 | | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
2074 | | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
2075 | | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
2075 | | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
2076 o | b18bc8331526
2076 o | b18bc8331526
2077 |/ Predecessors: 4:9bd10a0775e4
2077 |/ Predecessors: 4:9bd10a0775e4
2078 | semi-colon: 4:9bd10a0775e4
2078 | semi-colon: 4:9bd10a0775e4
2079 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
2079 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
2080 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
2080 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
2081 o dd800401bd8c
2081 o dd800401bd8c
2082 | Predecessors: 4:9bd10a0775e4
2082 | Predecessors: 4:9bd10a0775e4
2083 | semi-colon: 4:9bd10a0775e4
2083 | semi-colon: 4:9bd10a0775e4
2084 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
2084 | json: ["9bd10a0775e478708cada5f176ec6de654359ce7"]
2085 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
2085 | map: 4:9bd10a0775e478708cada5f176ec6de654359ce7
2086 | @ 9bd10a0775e4
2086 | @ 9bd10a0775e4
2087 |/ Successors: 5:dd800401bd8c 9:0b997eb7ceee 10:eceed8f98ffc; 5:dd800401bd8c 8:b18bc8331526 10:eceed8f98ffc
2087 |/ Successors: 5:dd800401bd8c 9:0b997eb7ceee 10:eceed8f98ffc; 5:dd800401bd8c 8:b18bc8331526 10:eceed8f98ffc
2088 | multi-line: 5:dd800401bd8c 9:0b997eb7ceee 10:eceed8f98ffc
2088 | multi-line: 5:dd800401bd8c 9:0b997eb7ceee 10:eceed8f98ffc
2089 | multi-line: 5:dd800401bd8c 8:b18bc8331526 10:eceed8f98ffc
2089 | multi-line: 5:dd800401bd8c 8:b18bc8331526 10:eceed8f98ffc
2090 | json: [["dd800401bd8c79d815329277739e433e883f784e", "0b997eb7ceeee06200a02f8aab185979092d514e", "eceed8f98ffc4186032e29a6542ab98888ebf68d"], ["dd800401bd8c79d815329277739e433e883f784e", "b18bc8331526a22cbb1801022bd1555bf291c48b", "eceed8f98ffc4186032e29a6542ab98888ebf68d"]]
2090 | json: [["dd800401bd8c79d815329277739e433e883f784e", "0b997eb7ceeee06200a02f8aab185979092d514e", "eceed8f98ffc4186032e29a6542ab98888ebf68d"], ["dd800401bd8c79d815329277739e433e883f784e", "b18bc8331526a22cbb1801022bd1555bf291c48b", "eceed8f98ffc4186032e29a6542ab98888ebf68d"]]
2091 o f897c6137566
2091 o f897c6137566
2092 |
2092 |
2093 o ea207398892e
2093 o ea207398892e
2094
2094
2095
2095
2096 $ hg fatelog
2096 $ hg fatelog
2097 o eceed8f98ffc
2097 o eceed8f98ffc
2098 |
2098 |
2099 | o 0b997eb7ceee
2099 | o 0b997eb7ceee
2100 | |
2100 | |
2101 o | b18bc8331526
2101 o | b18bc8331526
2102 |/
2102 |/
2103 o dd800401bd8c
2103 o dd800401bd8c
2104 |
2104 |
2105 | @ 9bd10a0775e4
2105 | @ 9bd10a0775e4
2106 |/ Obsfate: split using amend, rebase as 5:dd800401bd8c, 9:0b997eb7ceee, 10:eceed8f98ffc by test (at 1970-01-01 00:00 +0000); split using amend, rebase as 5:dd800401bd8c, 8:b18bc8331526, 10:eceed8f98ffc by test (at 1970-01-01 00:00 +0000);
2106 |/ Obsfate: split using amend, rebase as 5:dd800401bd8c, 9:0b997eb7ceee, 10:eceed8f98ffc by test (at 1970-01-01 00:00 +0000); split using amend, rebase as 5:dd800401bd8c, 8:b18bc8331526, 10:eceed8f98ffc by test (at 1970-01-01 00:00 +0000);
2107 o f897c6137566
2107 o f897c6137566
2108 |
2108 |
2109 o ea207398892e
2109 o ea207398892e
2110
2110
2111 Check other fatelog implementations
2111 Check other fatelog implementations
2112 -----------------------------------
2112 -----------------------------------
2113
2113
2114 $ hg fatelogkw --hidden -q
2114 $ hg fatelogkw --hidden -q
2115 o eceed8f98ffc
2115 o eceed8f98ffc
2116 |
2116 |
2117 | o 0b997eb7ceee
2117 | o 0b997eb7ceee
2118 | |
2118 | |
2119 o | b18bc8331526
2119 o | b18bc8331526
2120 |/
2120 |/
2121 | x ba2ed02b0c9a
2121 | x ba2ed02b0c9a
2122 | | Obsfate: rewritten using rebase as 10:eceed8f98ffc
2122 | | Obsfate: rewritten using rebase as 10:eceed8f98ffc
2123 | x 4a004186e638
2123 | x 4a004186e638
2124 |/ Obsfate: rewritten using amend as 8:b18bc8331526
2124 |/ Obsfate: rewritten using amend as 8:b18bc8331526
2125 | Obsfate: rewritten using amend as 9:0b997eb7ceee
2125 | Obsfate: rewritten using amend as 9:0b997eb7ceee
2126 o dd800401bd8c
2126 o dd800401bd8c
2127 |
2127 |
2128 | @ 9bd10a0775e4
2128 | @ 9bd10a0775e4
2129 |/ Obsfate: split as 5:dd800401bd8c, 6:4a004186e638, 7:ba2ed02b0c9a
2129 |/ Obsfate: split as 5:dd800401bd8c, 6:4a004186e638, 7:ba2ed02b0c9a
2130 o f897c6137566
2130 o f897c6137566
2131 |
2131 |
2132 | x 0dec01379d3b
2132 | x 0dec01379d3b
2133 | | Obsfate: rewritten as 3:f897c6137566
2133 | | Obsfate: rewritten as 3:f897c6137566
2134 | | Obsfate: rewritten as 1:471f378eab4c
2134 | | Obsfate: rewritten as 1:471f378eab4c
2135 | x 471f378eab4c
2135 | x 471f378eab4c
2136 |/ Obsfate: rewritten as 2:0dec01379d3b
2136 |/ Obsfate: rewritten as 2:0dec01379d3b
2137 o ea207398892e
2137 o ea207398892e
2138
2138
2139 $ hg fatelogkw --hidden
2139 $ hg fatelogkw --hidden
2140 o eceed8f98ffc
2140 o eceed8f98ffc
2141 |
2141 |
2142 | o 0b997eb7ceee
2142 | o 0b997eb7ceee
2143 | |
2143 | |
2144 o | b18bc8331526
2144 o | b18bc8331526
2145 |/
2145 |/
2146 | x ba2ed02b0c9a
2146 | x ba2ed02b0c9a
2147 | | Obsfate: rewritten using rebase as 10:eceed8f98ffc
2147 | | Obsfate: rewritten using rebase as 10:eceed8f98ffc
2148 | x 4a004186e638
2148 | x 4a004186e638
2149 |/ Obsfate: rewritten using amend as 8:b18bc8331526
2149 |/ Obsfate: rewritten using amend as 8:b18bc8331526
2150 | Obsfate: rewritten using amend as 9:0b997eb7ceee
2150 | Obsfate: rewritten using amend as 9:0b997eb7ceee
2151 o dd800401bd8c
2151 o dd800401bd8c
2152 |
2152 |
2153 | @ 9bd10a0775e4
2153 | @ 9bd10a0775e4
2154 |/ Obsfate: split as 5:dd800401bd8c, 6:4a004186e638, 7:ba2ed02b0c9a
2154 |/ Obsfate: split as 5:dd800401bd8c, 6:4a004186e638, 7:ba2ed02b0c9a
2155 o f897c6137566
2155 o f897c6137566
2156 |
2156 |
2157 | x 0dec01379d3b
2157 | x 0dec01379d3b
2158 | | Obsfate: rewritten as 3:f897c6137566
2158 | | Obsfate: rewritten as 3:f897c6137566
2159 | | Obsfate: rewritten as 1:471f378eab4c
2159 | | Obsfate: rewritten as 1:471f378eab4c
2160 | x 471f378eab4c
2160 | x 471f378eab4c
2161 |/ Obsfate: rewritten as 2:0dec01379d3b
2161 |/ Obsfate: rewritten as 2:0dec01379d3b
2162 o ea207398892e
2162 o ea207398892e
2163
2163
2164 $ hg fatelogkw --hidden -v
2164 $ hg fatelogkw --hidden -v
2165 o eceed8f98ffc
2165 o eceed8f98ffc
2166 |
2166 |
2167 | o 0b997eb7ceee
2167 | o 0b997eb7ceee
2168 | |
2168 | |
2169 o | b18bc8331526
2169 o | b18bc8331526
2170 |/
2170 |/
2171 | x ba2ed02b0c9a
2171 | x ba2ed02b0c9a
2172 | | Obsfate: rewritten using rebase as 10:eceed8f98ffc by test (at 1970-01-01 00:00 +0000)
2172 | | Obsfate: rewritten using rebase as 10:eceed8f98ffc by test (at 1970-01-01 00:00 +0000)
2173 | x 4a004186e638
2173 | x 4a004186e638
2174 |/ Obsfate: rewritten using amend as 8:b18bc8331526 by test (at 1970-01-01 00:00 +0000)
2174 |/ Obsfate: rewritten using amend as 8:b18bc8331526 by test (at 1970-01-01 00:00 +0000)
2175 | Obsfate: rewritten using amend as 9:0b997eb7ceee by test (at 1970-01-01 00:00 +0000)
2175 | Obsfate: rewritten using amend as 9:0b997eb7ceee by test (at 1970-01-01 00:00 +0000)
2176 o dd800401bd8c
2176 o dd800401bd8c
2177 |
2177 |
2178 | @ 9bd10a0775e4
2178 | @ 9bd10a0775e4
2179 |/ Obsfate: split as 5:dd800401bd8c, 6:4a004186e638, 7:ba2ed02b0c9a by test (at 1970-01-01 00:00 +0000)
2179 |/ Obsfate: split as 5:dd800401bd8c, 6:4a004186e638, 7:ba2ed02b0c9a by test (at 1970-01-01 00:00 +0000)
2180 o f897c6137566
2180 o f897c6137566
2181 |
2181 |
2182 | x 0dec01379d3b
2182 | x 0dec01379d3b
2183 | | Obsfate: rewritten as 3:f897c6137566 by test (at 1970-01-01 00:00 +0000)
2183 | | Obsfate: rewritten as 3:f897c6137566 by test (at 1970-01-01 00:00 +0000)
2184 | | Obsfate: rewritten as 1:471f378eab4c by test (at 1970-01-01 00:00 +0000)
2184 | | Obsfate: rewritten as 1:471f378eab4c by test (at 1970-01-01 00:00 +0000)
2185 | x 471f378eab4c
2185 | x 471f378eab4c
2186 |/ Obsfate: rewritten as 2:0dec01379d3b by test (at 1970-01-01 00:00 +0000)
2186 |/ Obsfate: rewritten as 2:0dec01379d3b by test (at 1970-01-01 00:00 +0000)
2187 o ea207398892e
2187 o ea207398892e
2188
2188
2189 $ hg log -G -T "default" --hidden
2189 $ hg log -G -T "default" --hidden
2190 o changeset: 10:eceed8f98ffc
2190 o changeset: 10:eceed8f98ffc
2191 | tag: tip
2191 | tag: tip
2192 | parent: 8:b18bc8331526
2192 | parent: 8:b18bc8331526
2193 | user: test
2193 | user: test
2194 | date: Thu Jan 01 00:00:00 1970 +0000
2194 | date: Thu Jan 01 00:00:00 1970 +0000
2195 | instability: content-divergent
2195 | instability: content-divergent
2196 | summary: Add A,B,C
2196 | summary: Add A,B,C
2197 |
2197 |
2198 | o changeset: 9:0b997eb7ceee
2198 | o changeset: 9:0b997eb7ceee
2199 | | parent: 5:dd800401bd8c
2199 | | parent: 5:dd800401bd8c
2200 | | user: test
2200 | | user: test
2201 | | date: Thu Jan 01 00:00:00 1970 +0000
2201 | | date: Thu Jan 01 00:00:00 1970 +0000
2202 | | instability: content-divergent
2202 | | instability: content-divergent
2203 | | summary: Add B only
2203 | | summary: Add B only
2204 | |
2204 | |
2205 o | changeset: 8:b18bc8331526
2205 o | changeset: 8:b18bc8331526
2206 |/ parent: 5:dd800401bd8c
2206 |/ parent: 5:dd800401bd8c
2207 | user: test
2207 | user: test
2208 | date: Thu Jan 01 00:00:00 1970 +0000
2208 | date: Thu Jan 01 00:00:00 1970 +0000
2209 | instability: content-divergent
2209 | instability: content-divergent
2210 | summary: Add only B
2210 | summary: Add only B
2211 |
2211 |
2212 | x changeset: 7:ba2ed02b0c9a
2212 | x changeset: 7:ba2ed02b0c9a
2213 | | user: test
2213 | | user: test
2214 | | date: Thu Jan 01 00:00:00 1970 +0000
2214 | | date: Thu Jan 01 00:00:00 1970 +0000
2215 | | obsfate: rewritten using rebase as 10:eceed8f98ffc
2215 | | obsfate: rewritten using rebase as 10:eceed8f98ffc
2216 | | summary: Add A,B,C
2216 | | summary: Add A,B,C
2217 | |
2217 | |
2218 | x changeset: 6:4a004186e638
2218 | x changeset: 6:4a004186e638
2219 |/ user: test
2219 |/ user: test
2220 | date: Thu Jan 01 00:00:00 1970 +0000
2220 | date: Thu Jan 01 00:00:00 1970 +0000
2221 | obsfate: rewritten using amend as 8:b18bc8331526
2221 | obsfate: rewritten using amend as 8:b18bc8331526
2222 | obsfate: rewritten using amend as 9:0b997eb7ceee
2222 | obsfate: rewritten using amend as 9:0b997eb7ceee
2223 | summary: Add A,B,C
2223 | summary: Add A,B,C
2224 |
2224 |
2225 o changeset: 5:dd800401bd8c
2225 o changeset: 5:dd800401bd8c
2226 | parent: 3:f897c6137566
2226 | parent: 3:f897c6137566
2227 | user: test
2227 | user: test
2228 | date: Thu Jan 01 00:00:00 1970 +0000
2228 | date: Thu Jan 01 00:00:00 1970 +0000
2229 | instability: content-divergent
2229 | instability: content-divergent
2230 | summary: Add A,B,C
2230 | summary: Add A,B,C
2231 |
2231 |
2232 | @ changeset: 4:9bd10a0775e4
2232 | @ changeset: 4:9bd10a0775e4
2233 |/ user: test
2233 |/ user: test
2234 | date: Thu Jan 01 00:00:00 1970 +0000
2234 | date: Thu Jan 01 00:00:00 1970 +0000
2235 | obsfate: split as 5:dd800401bd8c, 6:4a004186e638, 7:ba2ed02b0c9a
2235 | obsfate: split as 5:dd800401bd8c, 6:4a004186e638, 7:ba2ed02b0c9a
2236 | summary: Add A,B,C
2236 | summary: Add A,B,C
2237 |
2237 |
2238 o changeset: 3:f897c6137566
2238 o changeset: 3:f897c6137566
2239 | parent: 0:ea207398892e
2239 | parent: 0:ea207398892e
2240 | user: test
2240 | user: test
2241 | date: Thu Jan 01 00:00:00 1970 +0000
2241 | date: Thu Jan 01 00:00:00 1970 +0000
2242 | summary: C0
2242 | summary: C0
2243 |
2243 |
2244 | x changeset: 2:0dec01379d3b
2244 | x changeset: 2:0dec01379d3b
2245 | | user: test
2245 | | user: test
2246 | | date: Thu Jan 01 00:00:00 1970 +0000
2246 | | date: Thu Jan 01 00:00:00 1970 +0000
2247 | | obsfate: rewritten as 3:f897c6137566
2247 | | obsfate: rewritten as 3:f897c6137566
2248 | | obsfate: rewritten as 1:471f378eab4c
2248 | | obsfate: rewritten as 1:471f378eab4c
2249 | | summary: B0
2249 | | summary: B0
2250 | |
2250 | |
2251 | x changeset: 1:471f378eab4c
2251 | x changeset: 1:471f378eab4c
2252 |/ user: test
2252 |/ user: test
2253 | date: Thu Jan 01 00:00:00 1970 +0000
2253 | date: Thu Jan 01 00:00:00 1970 +0000
2254 | obsfate: rewritten as 2:0dec01379d3b
2254 | obsfate: rewritten as 2:0dec01379d3b
2255 | summary: A0
2255 | summary: A0
2256 |
2256 |
2257 o changeset: 0:ea207398892e
2257 o changeset: 0:ea207398892e
2258 user: test
2258 user: test
2259 date: Thu Jan 01 00:00:00 1970 +0000
2259 date: Thu Jan 01 00:00:00 1970 +0000
2260 summary: ROOT
2260 summary: ROOT
2261
2261
2262
2262
2263 Test templates with pruned commits
2263 Test templates with pruned commits
2264 ==================================
2264 ==================================
2265
2265
2266 Test setup
2266 Test setup
2267 ----------
2267 ----------
2268
2268
2269 $ hg init $TESTTMP/templates-local-prune
2269 $ hg init $TESTTMP/templates-local-prune
2270 $ cd $TESTTMP/templates-local-prune
2270 $ cd $TESTTMP/templates-local-prune
2271 $ mkcommit ROOT
2271 $ mkcommit ROOT
2272 $ mkcommit A0
2272 $ mkcommit A0
2273 $ hg debugobsolete --record-parent `getid "."`
2273 $ hg debugobsolete --record-parent `getid "."`
2274 obsoleted 1 changesets
2274 obsoleted 1 changesets
2275
2275
2276 Check output
2276 Check output
2277 ------------
2277 ------------
2278
2278
2279 $ hg up "desc(A0)" --hidden
2279 $ hg up "desc(A0)" --hidden
2280 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2280 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2281 $ hg tlog
2281 $ hg tlog
2282 @ 471f378eab4c
2282 @ 471f378eab4c
2283 |
2283 |
2284 o ea207398892e
2284 o ea207398892e
2285
2285
2286 $ hg fatelog
2286 $ hg fatelog
2287 @ 471f378eab4c
2287 @ 471f378eab4c
2288 | Obsfate: pruned by test (at 1970-01-01 00:00 +0000);
2288 | Obsfate: pruned by test (at 1970-01-01 00:00 +0000);
2289 o ea207398892e
2289 o ea207398892e
2290
2290
2291 Test templates with multiple pruned commits
2291 Test templates with multiple pruned commits
2292 ===========================================
2292 ===========================================
2293
2293
2294 Test setup
2294 Test setup
2295 ----------
2295 ----------
2296
2296
2297 $ hg init $TESTTMP/multiple-local-prune
2297 $ hg init $TESTTMP/multiple-local-prune
2298 $ cd $TESTTMP/multiple-local-prune
2298 $ cd $TESTTMP/multiple-local-prune
2299 $ mkcommit ROOT
2299 $ mkcommit ROOT
2300 $ mkcommit A0
2300 $ mkcommit A0
2301 $ hg commit --amend -m "A1"
2301 $ hg commit --amend -m "A1"
2302 $ hg debugobsolete --record-parent `getid "."`
2302 $ hg debugobsolete --record-parent `getid "."`
2303 obsoleted 1 changesets
2303 obsoleted 1 changesets
2304
2304
2305 $ hg up -r "desc(A0)" --hidden
2305 $ hg up -r "desc(A0)" --hidden
2306 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2306 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2307 $ hg commit --amend -m "A2"
2307 $ hg commit --amend -m "A2"
2308 $ hg debugobsolete --record-parent `getid "."`
2308 $ hg debugobsolete --record-parent `getid "."`
2309 obsoleted 1 changesets
2309 obsoleted 1 changesets
2310
2310
2311 Check output
2311 Check output
2312 ------------
2312 ------------
2313
2313
2314 $ hg up "desc(A0)" --hidden
2314 $ hg up "desc(A0)" --hidden
2315 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2315 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2316 $ hg tlog
2316 $ hg tlog
2317 @ 471f378eab4c
2317 @ 471f378eab4c
2318 |
2318 |
2319 o ea207398892e
2319 o ea207398892e
2320
2320
2321 # todo: the obsfate output is not ideal
2321 # todo: the obsfate output is not ideal
2322 $ hg fatelog
2322 $ hg fatelog
2323 @ 471f378eab4c
2323 @ 471f378eab4c
2324 | Obsfate: pruned;
2324 | Obsfate: pruned;
2325 o ea207398892e
2325 o ea207398892e
2326
2326
2327 $ hg fatelog --hidden
2327 $ hg fatelog --hidden
2328 x 65b757b745b9
2328 x 65b757b745b9
2329 | Obsfate: pruned by test (at 1970-01-01 00:00 +0000);
2329 | Obsfate: pruned by test (at 1970-01-01 00:00 +0000);
2330 | x fdf9bde5129a
2330 | x fdf9bde5129a
2331 |/ Obsfate: pruned by test (at 1970-01-01 00:00 +0000);
2331 |/ Obsfate: pruned by test (at 1970-01-01 00:00 +0000);
2332 | @ 471f378eab4c
2332 | @ 471f378eab4c
2333 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a by test (at 1970-01-01 00:00 +0000); rewritten using amend as 3:65b757b745b9 by test (at 1970-01-01 00:00 +0000);
2333 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a by test (at 1970-01-01 00:00 +0000); rewritten using amend as 3:65b757b745b9 by test (at 1970-01-01 00:00 +0000);
2334 o ea207398892e
2334 o ea207398892e
2335
2335
2336 Check other fatelog implementations
2336 Check other fatelog implementations
2337 -----------------------------------
2337 -----------------------------------
2338
2338
2339 $ hg fatelogkw --hidden -q
2339 $ hg fatelogkw --hidden -q
2340 x 65b757b745b9
2340 x 65b757b745b9
2341 | Obsfate: pruned
2341 | Obsfate: pruned
2342 | x fdf9bde5129a
2342 | x fdf9bde5129a
2343 |/ Obsfate: pruned
2343 |/ Obsfate: pruned
2344 | @ 471f378eab4c
2344 | @ 471f378eab4c
2345 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a
2345 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a
2346 | Obsfate: rewritten using amend as 3:65b757b745b9
2346 | Obsfate: rewritten using amend as 3:65b757b745b9
2347 o ea207398892e
2347 o ea207398892e
2348
2348
2349 $ hg fatelogkw --hidden
2349 $ hg fatelogkw --hidden
2350 x 65b757b745b9
2350 x 65b757b745b9
2351 | Obsfate: pruned
2351 | Obsfate: pruned
2352 | x fdf9bde5129a
2352 | x fdf9bde5129a
2353 |/ Obsfate: pruned
2353 |/ Obsfate: pruned
2354 | @ 471f378eab4c
2354 | @ 471f378eab4c
2355 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a
2355 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a
2356 | Obsfate: rewritten using amend as 3:65b757b745b9
2356 | Obsfate: rewritten using amend as 3:65b757b745b9
2357 o ea207398892e
2357 o ea207398892e
2358
2358
2359 $ hg fatelogkw --hidden -v
2359 $ hg fatelogkw --hidden -v
2360 x 65b757b745b9
2360 x 65b757b745b9
2361 | Obsfate: pruned by test (at 1970-01-01 00:00 +0000)
2361 | Obsfate: pruned by test (at 1970-01-01 00:00 +0000)
2362 | x fdf9bde5129a
2362 | x fdf9bde5129a
2363 |/ Obsfate: pruned by test (at 1970-01-01 00:00 +0000)
2363 |/ Obsfate: pruned by test (at 1970-01-01 00:00 +0000)
2364 | @ 471f378eab4c
2364 | @ 471f378eab4c
2365 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a by test (at 1970-01-01 00:00 +0000)
2365 |/ Obsfate: rewritten using amend as 2:fdf9bde5129a by test (at 1970-01-01 00:00 +0000)
2366 | Obsfate: rewritten using amend as 3:65b757b745b9 by test (at 1970-01-01 00:00 +0000)
2366 | Obsfate: rewritten using amend as 3:65b757b745b9 by test (at 1970-01-01 00:00 +0000)
2367 o ea207398892e
2367 o ea207398892e
2368
2368
2369
2369
2370 $ hg log -G -T "default" --hidden
2370 $ hg log -G -T "default" --hidden
2371 x changeset: 3:65b757b745b9
2371 x changeset: 3:65b757b745b9
2372 | tag: tip
2372 | tag: tip
2373 | parent: 0:ea207398892e
2373 | parent: 0:ea207398892e
2374 | user: test
2374 | user: test
2375 | date: Thu Jan 01 00:00:00 1970 +0000
2375 | date: Thu Jan 01 00:00:00 1970 +0000
2376 | obsfate: pruned
2376 | obsfate: pruned
2377 | summary: A2
2377 | summary: A2
2378 |
2378 |
2379 | x changeset: 2:fdf9bde5129a
2379 | x changeset: 2:fdf9bde5129a
2380 |/ parent: 0:ea207398892e
2380 |/ parent: 0:ea207398892e
2381 | user: test
2381 | user: test
2382 | date: Thu Jan 01 00:00:00 1970 +0000
2382 | date: Thu Jan 01 00:00:00 1970 +0000
2383 | obsfate: pruned
2383 | obsfate: pruned
2384 | summary: A1
2384 | summary: A1
2385 |
2385 |
2386 | @ changeset: 1:471f378eab4c
2386 | @ changeset: 1:471f378eab4c
2387 |/ user: test
2387 |/ user: test
2388 | date: Thu Jan 01 00:00:00 1970 +0000
2388 | date: Thu Jan 01 00:00:00 1970 +0000
2389 | obsfate: rewritten using amend as 2:fdf9bde5129a
2389 | obsfate: rewritten using amend as 2:fdf9bde5129a
2390 | obsfate: rewritten using amend as 3:65b757b745b9
2390 | obsfate: rewritten using amend as 3:65b757b745b9
2391 | summary: A0
2391 | summary: A0
2392 |
2392 |
2393 o changeset: 0:ea207398892e
2393 o changeset: 0:ea207398892e
2394 user: test
2394 user: test
2395 date: Thu Jan 01 00:00:00 1970 +0000
2395 date: Thu Jan 01 00:00:00 1970 +0000
2396 summary: ROOT
2396 summary: ROOT
2397
2397
2398
2398
2399 Test templates with splitted and pruned commit
2399 Test templates with splitted and pruned commit
2400 ==============================================
2400 ==============================================
2401
2401
2402 $ hg init $TESTTMP/templates-local-split-prune
2402 $ hg init $TESTTMP/templates-local-split-prune
2403 $ cd $TESTTMP/templates-local-split-prune
2403 $ cd $TESTTMP/templates-local-split-prune
2404 $ mkcommit ROOT
2404 $ mkcommit ROOT
2405 $ echo 42 >> a
2405 $ echo 42 >> a
2406 $ echo 43 >> b
2406 $ echo 43 >> b
2407 $ hg commit -A -m "A0"
2407 $ hg commit -A -m "A0"
2408 adding a
2408 adding a
2409 adding b
2409 adding b
2410 $ hg log --hidden -G
2410 $ hg log --hidden -G
2411 @ changeset: 1:471597cad322
2411 @ changeset: 1:471597cad322
2412 | tag: tip
2412 | tag: tip
2413 | user: test
2413 | user: test
2414 | date: Thu Jan 01 00:00:00 1970 +0000
2414 | date: Thu Jan 01 00:00:00 1970 +0000
2415 | summary: A0
2415 | summary: A0
2416 |
2416 |
2417 o changeset: 0:ea207398892e
2417 o changeset: 0:ea207398892e
2418 user: test
2418 user: test
2419 date: Thu Jan 01 00:00:00 1970 +0000
2419 date: Thu Jan 01 00:00:00 1970 +0000
2420 summary: ROOT
2420 summary: ROOT
2421
2421
2422 # Simulate split
2422 # Simulate split
2423 $ hg up -r "desc(ROOT)"
2423 $ hg up -r "desc(ROOT)"
2424 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
2424 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
2425 $ echo 42 >> a
2425 $ echo 42 >> a
2426 $ hg commit -A -m "A1"
2426 $ hg commit -A -m "A1"
2427 adding a
2427 adding a
2428 created new head
2428 created new head
2429 $ echo 43 >> b
2429 $ echo 43 >> b
2430 $ hg commit -A -m "A2"
2430 $ hg commit -A -m "A2"
2431 adding b
2431 adding b
2432 $ hg debugobsolete `getid "1"` `getid "2"` `getid "3"`
2432 $ hg debugobsolete `getid "1"` `getid "2"` `getid "3"`
2433 obsoleted 1 changesets
2433 obsoleted 1 changesets
2434
2434
2435 # Simulate prune
2435 # Simulate prune
2436 $ hg debugobsolete --record-parent `getid "."`
2436 $ hg debugobsolete --record-parent `getid "."`
2437 obsoleted 1 changesets
2437 obsoleted 1 changesets
2438
2438
2439 $ hg log --hidden -G
2439 $ hg log --hidden -G
2440 @ changeset: 3:0d0ef4bdf70e
2440 @ changeset: 3:0d0ef4bdf70e
2441 | tag: tip
2441 | tag: tip
2442 | user: test
2442 | user: test
2443 | date: Thu Jan 01 00:00:00 1970 +0000
2443 | date: Thu Jan 01 00:00:00 1970 +0000
2444 | obsfate: pruned
2444 | obsolete: pruned
2445 | summary: A2
2445 | summary: A2
2446 |
2446 |
2447 o changeset: 2:617adc3a144c
2447 o changeset: 2:617adc3a144c
2448 | parent: 0:ea207398892e
2448 | parent: 0:ea207398892e
2449 | user: test
2449 | user: test
2450 | date: Thu Jan 01 00:00:00 1970 +0000
2450 | date: Thu Jan 01 00:00:00 1970 +0000
2451 | summary: A1
2451 | summary: A1
2452 |
2452 |
2453 | x changeset: 1:471597cad322
2453 | x changeset: 1:471597cad322
2454 |/ user: test
2454 |/ user: test
2455 | date: Thu Jan 01 00:00:00 1970 +0000
2455 | date: Thu Jan 01 00:00:00 1970 +0000
2456 | obsfate: split as 2:617adc3a144c, 3:0d0ef4bdf70e
2456 | obsolete: split as 2:617adc3a144c, 3:0d0ef4bdf70e
2457 | summary: A0
2457 | summary: A0
2458 |
2458 |
2459 o changeset: 0:ea207398892e
2459 o changeset: 0:ea207398892e
2460 user: test
2460 user: test
2461 date: Thu Jan 01 00:00:00 1970 +0000
2461 date: Thu Jan 01 00:00:00 1970 +0000
2462 summary: ROOT
2462 summary: ROOT
2463
2463
2464 Check templates
2464 Check templates
2465 ---------------
2465 ---------------
2466
2466
2467 $ hg up 'desc("A0")' --hidden
2467 $ hg up 'desc("A0")' --hidden
2468 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2468 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2469
2469
2470 # todo: the obsfate output is not ideal
2470 # todo: the obsfate output is not ideal
2471 $ hg fatelog
2471 $ hg fatelog
2472 o 617adc3a144c
2472 o 617adc3a144c
2473 |
2473 |
2474 | @ 471597cad322
2474 | @ 471597cad322
2475 |/ Obsfate: pruned;
2475 |/ Obsfate: pruned;
2476 o ea207398892e
2476 o ea207398892e
2477
2477
2478 $ hg up -r 'desc("A2")' --hidden
2478 $ hg up -r 'desc("A2")' --hidden
2479 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2479 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2480
2480
2481 $ hg fatelog --hidden
2481 $ hg fatelog --hidden
2482 @ 0d0ef4bdf70e
2482 @ 0d0ef4bdf70e
2483 | Obsfate: pruned by test (at 1970-01-01 00:00 +0000);
2483 | Obsfate: pruned by test (at 1970-01-01 00:00 +0000);
2484 o 617adc3a144c
2484 o 617adc3a144c
2485 |
2485 |
2486 | x 471597cad322
2486 | x 471597cad322
2487 |/ Obsfate: split as 2:617adc3a144c, 3:0d0ef4bdf70e by test (at 1970-01-01 00:00 +0000);
2487 |/ Obsfate: split as 2:617adc3a144c, 3:0d0ef4bdf70e by test (at 1970-01-01 00:00 +0000);
2488 o ea207398892e
2488 o ea207398892e
2489
2489
2490
2490
2491 Check other fatelog implementations
2491 Check other fatelog implementations
2492 -----------------------------------
2492 -----------------------------------
2493
2493
2494 $ hg fatelogkw --hidden -q
2494 $ hg fatelogkw --hidden -q
2495 @ 0d0ef4bdf70e
2495 @ 0d0ef4bdf70e
2496 | Obsfate: pruned
2496 | Obsfate: pruned
2497 o 617adc3a144c
2497 o 617adc3a144c
2498 |
2498 |
2499 | x 471597cad322
2499 | x 471597cad322
2500 |/ Obsfate: split as 2:617adc3a144c, 3:0d0ef4bdf70e
2500 |/ Obsfate: split as 2:617adc3a144c, 3:0d0ef4bdf70e
2501 o ea207398892e
2501 o ea207398892e
2502
2502
2503 $ hg fatelogkw --hidden
2503 $ hg fatelogkw --hidden
2504 @ 0d0ef4bdf70e
2504 @ 0d0ef4bdf70e
2505 | Obsfate: pruned
2505 | Obsfate: pruned
2506 o 617adc3a144c
2506 o 617adc3a144c
2507 |
2507 |
2508 | x 471597cad322
2508 | x 471597cad322
2509 |/ Obsfate: split as 2:617adc3a144c, 3:0d0ef4bdf70e
2509 |/ Obsfate: split as 2:617adc3a144c, 3:0d0ef4bdf70e
2510 o ea207398892e
2510 o ea207398892e
2511
2511
2512 $ hg fatelogkw --hidden -v
2512 $ hg fatelogkw --hidden -v
2513 @ 0d0ef4bdf70e
2513 @ 0d0ef4bdf70e
2514 | Obsfate: pruned by test (at 1970-01-01 00:00 +0000)
2514 | Obsfate: pruned by test (at 1970-01-01 00:00 +0000)
2515 o 617adc3a144c
2515 o 617adc3a144c
2516 |
2516 |
2517 | x 471597cad322
2517 | x 471597cad322
2518 |/ Obsfate: split as 2:617adc3a144c, 3:0d0ef4bdf70e by test (at 1970-01-01 00:00 +0000)
2518 |/ Obsfate: split as 2:617adc3a144c, 3:0d0ef4bdf70e by test (at 1970-01-01 00:00 +0000)
2519 o ea207398892e
2519 o ea207398892e
2520
2520
2521 $ hg log -G -T "default" --hidden
2521 $ hg log -G -T "default" --hidden
2522 @ changeset: 3:0d0ef4bdf70e
2522 @ changeset: 3:0d0ef4bdf70e
2523 | tag: tip
2523 | tag: tip
2524 | user: test
2524 | user: test
2525 | date: Thu Jan 01 00:00:00 1970 +0000
2525 | date: Thu Jan 01 00:00:00 1970 +0000
2526 | obsfate: pruned
2526 | obsfate: pruned
2527 | summary: A2
2527 | summary: A2
2528 |
2528 |
2529 o changeset: 2:617adc3a144c
2529 o changeset: 2:617adc3a144c
2530 | parent: 0:ea207398892e
2530 | parent: 0:ea207398892e
2531 | user: test
2531 | user: test
2532 | date: Thu Jan 01 00:00:00 1970 +0000
2532 | date: Thu Jan 01 00:00:00 1970 +0000
2533 | summary: A1
2533 | summary: A1
2534 |
2534 |
2535 | x changeset: 1:471597cad322
2535 | x changeset: 1:471597cad322
2536 |/ user: test
2536 |/ user: test
2537 | date: Thu Jan 01 00:00:00 1970 +0000
2537 | date: Thu Jan 01 00:00:00 1970 +0000
2538 | obsfate: split as 2:617adc3a144c, 3:0d0ef4bdf70e
2538 | obsfate: split as 2:617adc3a144c, 3:0d0ef4bdf70e
2539 | summary: A0
2539 | summary: A0
2540 |
2540 |
2541 o changeset: 0:ea207398892e
2541 o changeset: 0:ea207398892e
2542 user: test
2542 user: test
2543 date: Thu Jan 01 00:00:00 1970 +0000
2543 date: Thu Jan 01 00:00:00 1970 +0000
2544 summary: ROOT
2544 summary: ROOT
2545
2545
@@ -1,1512 +1,1512 b''
1 $ cat >> $HGRCPATH << EOF
1 $ cat >> $HGRCPATH << EOF
2 > [phases]
2 > [phases]
3 > # public changeset are not obsolete
3 > # public changeset are not obsolete
4 > publish=false
4 > publish=false
5 > [ui]
5 > [ui]
6 > logtemplate="{rev}:{node|short} ({phase}{if(obsolete, ' *{obsolete}*')}{if(instabilities, ' {instabilities}')}) [{tags} {bookmarks}] {desc|firstline}{if(obsfate, " [{join(obsfate, "; ")}]")}\n"
6 > logtemplate="{rev}:{node|short} ({phase}{if(obsolete, ' *{obsolete}*')}{if(instabilities, ' {instabilities}')}) [{tags} {bookmarks}] {desc|firstline}{if(obsfate, " [{join(obsfate, "; ")}]")}\n"
7 > EOF
7 > EOF
8 $ mkcommit() {
8 $ mkcommit() {
9 > echo "$1" > "$1"
9 > echo "$1" > "$1"
10 > hg add "$1"
10 > hg add "$1"
11 > hg ci -m "add $1"
11 > hg ci -m "add $1"
12 > }
12 > }
13 $ getid() {
13 $ getid() {
14 > hg log -T "{node}\n" --hidden -r "desc('$1')"
14 > hg log -T "{node}\n" --hidden -r "desc('$1')"
15 > }
15 > }
16
16
17 $ cat > debugkeys.py <<EOF
17 $ cat > debugkeys.py <<EOF
18 > def reposetup(ui, repo):
18 > def reposetup(ui, repo):
19 > class debugkeysrepo(repo.__class__):
19 > class debugkeysrepo(repo.__class__):
20 > def listkeys(self, namespace):
20 > def listkeys(self, namespace):
21 > ui.write('listkeys %s\n' % (namespace,))
21 > ui.write('listkeys %s\n' % (namespace,))
22 > return super(debugkeysrepo, self).listkeys(namespace)
22 > return super(debugkeysrepo, self).listkeys(namespace)
23 >
23 >
24 > if repo.local():
24 > if repo.local():
25 > repo.__class__ = debugkeysrepo
25 > repo.__class__ = debugkeysrepo
26 > EOF
26 > EOF
27
27
28 $ hg init tmpa
28 $ hg init tmpa
29 $ cd tmpa
29 $ cd tmpa
30 $ mkcommit kill_me
30 $ mkcommit kill_me
31
31
32 Checking that the feature is properly disabled
32 Checking that the feature is properly disabled
33
33
34 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
34 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
35 abort: creating obsolete markers is not enabled on this repo
35 abort: creating obsolete markers is not enabled on this repo
36 [255]
36 [255]
37
37
38 Enabling it
38 Enabling it
39
39
40 $ cat >> $HGRCPATH << EOF
40 $ cat >> $HGRCPATH << EOF
41 > [experimental]
41 > [experimental]
42 > evolution=exchange
42 > evolution=exchange
43 > evolution.createmarkers=True
43 > evolution.createmarkers=True
44 > EOF
44 > EOF
45
45
46 Killing a single changeset without replacement
46 Killing a single changeset without replacement
47
47
48 $ hg debugobsolete 0
48 $ hg debugobsolete 0
49 abort: changeset references must be full hexadecimal node identifiers
49 abort: changeset references must be full hexadecimal node identifiers
50 [255]
50 [255]
51 $ hg debugobsolete '00'
51 $ hg debugobsolete '00'
52 abort: changeset references must be full hexadecimal node identifiers
52 abort: changeset references must be full hexadecimal node identifiers
53 [255]
53 [255]
54 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
54 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
55 obsoleted 1 changesets
55 obsoleted 1 changesets
56 $ hg debugobsolete
56 $ hg debugobsolete
57 97b7c2d76b1845ed3eb988cd612611e72406cef0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'babar'}
57 97b7c2d76b1845ed3eb988cd612611e72406cef0 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'babar'}
58
58
59 (test that mercurial is not confused)
59 (test that mercurial is not confused)
60
60
61 $ hg up null --quiet # having 0 as parent prevents it to be hidden
61 $ hg up null --quiet # having 0 as parent prevents it to be hidden
62 $ hg tip
62 $ hg tip
63 -1:000000000000 (public) [tip ]
63 -1:000000000000 (public) [tip ]
64 $ hg up --hidden tip --quiet
64 $ hg up --hidden tip --quiet
65
65
66 Killing a single changeset with itself should fail
66 Killing a single changeset with itself should fail
67 (simple local safeguard)
67 (simple local safeguard)
68
68
69 $ hg debugobsolete `getid kill_me` `getid kill_me`
69 $ hg debugobsolete `getid kill_me` `getid kill_me`
70 abort: bad obsmarker input: in-marker cycle with 97b7c2d76b1845ed3eb988cd612611e72406cef0
70 abort: bad obsmarker input: in-marker cycle with 97b7c2d76b1845ed3eb988cd612611e72406cef0
71 [255]
71 [255]
72
72
73 $ cd ..
73 $ cd ..
74
74
75 Killing a single changeset with replacement
75 Killing a single changeset with replacement
76 (and testing the format option)
76 (and testing the format option)
77
77
78 $ hg init tmpb
78 $ hg init tmpb
79 $ cd tmpb
79 $ cd tmpb
80 $ mkcommit a
80 $ mkcommit a
81 $ mkcommit b
81 $ mkcommit b
82 $ mkcommit original_c
82 $ mkcommit original_c
83 $ hg up "desc('b')"
83 $ hg up "desc('b')"
84 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
84 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
85 $ mkcommit new_c
85 $ mkcommit new_c
86 created new head
86 created new head
87 $ hg log -r 'hidden()' --template '{rev}:{node|short} {desc}\n' --hidden
87 $ hg log -r 'hidden()' --template '{rev}:{node|short} {desc}\n' --hidden
88 $ hg debugobsolete --config format.obsstore-version=0 --flag 12 `getid original_c` `getid new_c` -d '121 120'
88 $ hg debugobsolete --config format.obsstore-version=0 --flag 12 `getid original_c` `getid new_c` -d '121 120'
89 obsoleted 1 changesets
89 obsoleted 1 changesets
90 $ hg log -r 'hidden()' --template '{rev}:{node|short} {desc}\n' --hidden
90 $ hg log -r 'hidden()' --template '{rev}:{node|short} {desc}\n' --hidden
91 2:245bde4270cd add original_c
91 2:245bde4270cd add original_c
92 $ hg debugrevlog -cd
92 $ hg debugrevlog -cd
93 # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads chainlen
93 # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads chainlen
94 0 -1 -1 0 59 0 0 0 0 58 58 0 1 0
94 0 -1 -1 0 59 0 0 0 0 58 58 0 1 0
95 1 0 -1 59 118 59 59 0 0 58 116 0 1 0
95 1 0 -1 59 118 59 59 0 0 58 116 0 1 0
96 2 1 -1 118 193 118 118 59 0 76 192 0 1 0
96 2 1 -1 118 193 118 118 59 0 76 192 0 1 0
97 3 1 -1 193 260 193 193 59 0 66 258 0 2 0
97 3 1 -1 193 260 193 193 59 0 66 258 0 2 0
98 $ hg debugobsolete
98 $ hg debugobsolete
99 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
99 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
100
100
101 (check for version number of the obsstore)
101 (check for version number of the obsstore)
102
102
103 $ dd bs=1 count=1 if=.hg/store/obsstore 2>/dev/null
103 $ dd bs=1 count=1 if=.hg/store/obsstore 2>/dev/null
104 \x00 (no-eol) (esc)
104 \x00 (no-eol) (esc)
105
105
106 do it again (it read the obsstore before adding new changeset)
106 do it again (it read the obsstore before adding new changeset)
107
107
108 $ hg up '.^'
108 $ hg up '.^'
109 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
109 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
110 $ mkcommit new_2_c
110 $ mkcommit new_2_c
111 created new head
111 created new head
112 $ hg debugobsolete -d '1337 0' `getid new_c` `getid new_2_c`
112 $ hg debugobsolete -d '1337 0' `getid new_c` `getid new_2_c`
113 obsoleted 1 changesets
113 obsoleted 1 changesets
114 $ hg debugobsolete
114 $ hg debugobsolete
115 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
115 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
116 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
116 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
117
117
118 Register two markers with a missing node
118 Register two markers with a missing node
119
119
120 $ hg up '.^'
120 $ hg up '.^'
121 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
121 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
122 $ mkcommit new_3_c
122 $ mkcommit new_3_c
123 created new head
123 created new head
124 $ hg debugobsolete -d '1338 0' `getid new_2_c` 1337133713371337133713371337133713371337
124 $ hg debugobsolete -d '1338 0' `getid new_2_c` 1337133713371337133713371337133713371337
125 obsoleted 1 changesets
125 obsoleted 1 changesets
126 $ hg debugobsolete -d '1339 0' 1337133713371337133713371337133713371337 `getid new_3_c`
126 $ hg debugobsolete -d '1339 0' 1337133713371337133713371337133713371337 `getid new_3_c`
127 $ hg debugobsolete
127 $ hg debugobsolete
128 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
128 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
129 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
129 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
130 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
130 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
131 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
131 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
132
132
133 Test the --index option of debugobsolete command
133 Test the --index option of debugobsolete command
134 $ hg debugobsolete --index
134 $ hg debugobsolete --index
135 0 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
135 0 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
136 1 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
136 1 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
137 2 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
137 2 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
138 3 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
138 3 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
139
139
140 Refuse pathological nullid successors
140 Refuse pathological nullid successors
141 $ hg debugobsolete -d '9001 0' 1337133713371337133713371337133713371337 0000000000000000000000000000000000000000
141 $ hg debugobsolete -d '9001 0' 1337133713371337133713371337133713371337 0000000000000000000000000000000000000000
142 transaction abort!
142 transaction abort!
143 rollback completed
143 rollback completed
144 abort: bad obsolescence marker detected: invalid successors nullid
144 abort: bad obsolescence marker detected: invalid successors nullid
145 [255]
145 [255]
146
146
147 Check that graphlog detect that a changeset is obsolete:
147 Check that graphlog detect that a changeset is obsolete:
148
148
149 $ hg log -G
149 $ hg log -G
150 @ 5:5601fb93a350 (draft) [tip ] add new_3_c
150 @ 5:5601fb93a350 (draft) [tip ] add new_3_c
151 |
151 |
152 o 1:7c3bad9141dc (draft) [ ] add b
152 o 1:7c3bad9141dc (draft) [ ] add b
153 |
153 |
154 o 0:1f0dee641bb7 (draft) [ ] add a
154 o 0:1f0dee641bb7 (draft) [ ] add a
155
155
156
156
157 check that heads does not report them
157 check that heads does not report them
158
158
159 $ hg heads
159 $ hg heads
160 5:5601fb93a350 (draft) [tip ] add new_3_c
160 5:5601fb93a350 (draft) [tip ] add new_3_c
161 $ hg heads --hidden
161 $ hg heads --hidden
162 5:5601fb93a350 (draft) [tip ] add new_3_c
162 5:5601fb93a350 (draft) [tip ] add new_3_c
163 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c [rewritten as 5:5601fb93a350]
163 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c [rewritten as 5:5601fb93a350]
164 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c [rewritten as 4:ca819180edb9]
164 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c [rewritten as 4:ca819180edb9]
165 2:245bde4270cd (draft *obsolete*) [ ] add original_c [rewritten as 3:cdbce2fbb163]
165 2:245bde4270cd (draft *obsolete*) [ ] add original_c [rewritten as 3:cdbce2fbb163]
166
166
167
167
168 check that summary does not report them
168 check that summary does not report them
169
169
170 $ hg init ../sink
170 $ hg init ../sink
171 $ echo '[paths]' >> .hg/hgrc
171 $ echo '[paths]' >> .hg/hgrc
172 $ echo 'default=../sink' >> .hg/hgrc
172 $ echo 'default=../sink' >> .hg/hgrc
173 $ hg summary --remote
173 $ hg summary --remote
174 parent: 5:5601fb93a350 tip
174 parent: 5:5601fb93a350 tip
175 add new_3_c
175 add new_3_c
176 branch: default
176 branch: default
177 commit: (clean)
177 commit: (clean)
178 update: (current)
178 update: (current)
179 phases: 3 draft
179 phases: 3 draft
180 remote: 3 outgoing
180 remote: 3 outgoing
181
181
182 $ hg summary --remote --hidden
182 $ hg summary --remote --hidden
183 parent: 5:5601fb93a350 tip
183 parent: 5:5601fb93a350 tip
184 add new_3_c
184 add new_3_c
185 branch: default
185 branch: default
186 commit: (clean)
186 commit: (clean)
187 update: 3 new changesets, 4 branch heads (merge)
187 update: 3 new changesets, 4 branch heads (merge)
188 phases: 6 draft
188 phases: 6 draft
189 remote: 3 outgoing
189 remote: 3 outgoing
190
190
191 check that various commands work well with filtering
191 check that various commands work well with filtering
192
192
193 $ hg tip
193 $ hg tip
194 5:5601fb93a350 (draft) [tip ] add new_3_c
194 5:5601fb93a350 (draft) [tip ] add new_3_c
195 $ hg log -r 6
195 $ hg log -r 6
196 abort: unknown revision '6'!
196 abort: unknown revision '6'!
197 [255]
197 [255]
198 $ hg log -r 4
198 $ hg log -r 4
199 abort: hidden revision '4'!
199 abort: hidden revision '4'!
200 (use --hidden to access hidden revisions)
200 (use --hidden to access hidden revisions)
201 [255]
201 [255]
202 $ hg debugrevspec 'rev(6)'
202 $ hg debugrevspec 'rev(6)'
203 $ hg debugrevspec 'rev(4)'
203 $ hg debugrevspec 'rev(4)'
204 $ hg debugrevspec 'null'
204 $ hg debugrevspec 'null'
205 -1
205 -1
206
206
207 Check that public changeset are not accounted as obsolete:
207 Check that public changeset are not accounted as obsolete:
208
208
209 $ hg --hidden phase --public 2
209 $ hg --hidden phase --public 2
210 $ hg log -G
210 $ hg log -G
211 @ 5:5601fb93a350 (draft phase-divergent) [tip ] add new_3_c
211 @ 5:5601fb93a350 (draft phase-divergent) [tip ] add new_3_c
212 |
212 |
213 | o 2:245bde4270cd (public) [ ] add original_c
213 | o 2:245bde4270cd (public) [ ] add original_c
214 |/
214 |/
215 o 1:7c3bad9141dc (public) [ ] add b
215 o 1:7c3bad9141dc (public) [ ] add b
216 |
216 |
217 o 0:1f0dee641bb7 (public) [ ] add a
217 o 0:1f0dee641bb7 (public) [ ] add a
218
218
219
219
220 And that bumped changeset are detected
220 And that bumped changeset are detected
221 --------------------------------------
221 --------------------------------------
222
222
223 If we didn't filtered obsolete changesets out, 3 and 4 would show up too. Also
223 If we didn't filtered obsolete changesets out, 3 and 4 would show up too. Also
224 note that the bumped changeset (5:5601fb93a350) is not a direct successor of
224 note that the bumped changeset (5:5601fb93a350) is not a direct successor of
225 the public changeset
225 the public changeset
226
226
227 $ hg log --hidden -r 'phasedivergent()'
227 $ hg log --hidden -r 'phasedivergent()'
228 5:5601fb93a350 (draft phase-divergent) [tip ] add new_3_c
228 5:5601fb93a350 (draft phase-divergent) [tip ] add new_3_c
229
229
230 And that we can't push bumped changeset
230 And that we can't push bumped changeset
231
231
232 $ hg push ../tmpa -r 0 --force #(make repo related)
232 $ hg push ../tmpa -r 0 --force #(make repo related)
233 pushing to ../tmpa
233 pushing to ../tmpa
234 searching for changes
234 searching for changes
235 warning: repository is unrelated
235 warning: repository is unrelated
236 adding changesets
236 adding changesets
237 adding manifests
237 adding manifests
238 adding file changes
238 adding file changes
239 added 1 changesets with 1 changes to 1 files (+1 heads)
239 added 1 changesets with 1 changes to 1 files (+1 heads)
240 $ hg push ../tmpa
240 $ hg push ../tmpa
241 pushing to ../tmpa
241 pushing to ../tmpa
242 searching for changes
242 searching for changes
243 abort: push includes phase-divergent changeset: 5601fb93a350!
243 abort: push includes phase-divergent changeset: 5601fb93a350!
244 [255]
244 [255]
245
245
246 Fixing "bumped" situation
246 Fixing "bumped" situation
247 We need to create a clone of 5 and add a special marker with a flag
247 We need to create a clone of 5 and add a special marker with a flag
248
248
249 $ hg summary
249 $ hg summary
250 parent: 5:5601fb93a350 tip (phase-divergent)
250 parent: 5:5601fb93a350 tip (phase-divergent)
251 add new_3_c
251 add new_3_c
252 branch: default
252 branch: default
253 commit: (clean)
253 commit: (clean)
254 update: 1 new changesets, 2 branch heads (merge)
254 update: 1 new changesets, 2 branch heads (merge)
255 phases: 1 draft
255 phases: 1 draft
256 phase-divergent: 1 changesets
256 phase-divergent: 1 changesets
257 $ hg up '5^'
257 $ hg up '5^'
258 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
258 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
259 $ hg revert -ar 5
259 $ hg revert -ar 5
260 adding new_3_c
260 adding new_3_c
261 $ hg ci -m 'add n3w_3_c'
261 $ hg ci -m 'add n3w_3_c'
262 created new head
262 created new head
263 $ hg debugobsolete -d '1338 0' --flags 1 `getid new_3_c` `getid n3w_3_c`
263 $ hg debugobsolete -d '1338 0' --flags 1 `getid new_3_c` `getid n3w_3_c`
264 obsoleted 1 changesets
264 obsoleted 1 changesets
265 $ hg log -r 'phasedivergent()'
265 $ hg log -r 'phasedivergent()'
266 $ hg log -G
266 $ hg log -G
267 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
267 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
268 |
268 |
269 | o 2:245bde4270cd (public) [ ] add original_c
269 | o 2:245bde4270cd (public) [ ] add original_c
270 |/
270 |/
271 o 1:7c3bad9141dc (public) [ ] add b
271 o 1:7c3bad9141dc (public) [ ] add b
272 |
272 |
273 o 0:1f0dee641bb7 (public) [ ] add a
273 o 0:1f0dee641bb7 (public) [ ] add a
274
274
275
275
276 Basic exclusive testing
276 Basic exclusive testing
277
277
278 $ hg log -G --hidden
278 $ hg log -G --hidden
279 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
279 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
280 |
280 |
281 | x 5:5601fb93a350 (draft *obsolete*) [ ] add new_3_c [rewritten as 6:6f9641995072]
281 | x 5:5601fb93a350 (draft *obsolete*) [ ] add new_3_c [rewritten as 6:6f9641995072]
282 |/
282 |/
283 | x 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c [rewritten as 5:5601fb93a350]
283 | x 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c [rewritten as 5:5601fb93a350]
284 |/
284 |/
285 | x 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c [rewritten as 4:ca819180edb9]
285 | x 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c [rewritten as 4:ca819180edb9]
286 |/
286 |/
287 | o 2:245bde4270cd (public) [ ] add original_c
287 | o 2:245bde4270cd (public) [ ] add original_c
288 |/
288 |/
289 o 1:7c3bad9141dc (public) [ ] add b
289 o 1:7c3bad9141dc (public) [ ] add b
290 |
290 |
291 o 0:1f0dee641bb7 (public) [ ] add a
291 o 0:1f0dee641bb7 (public) [ ] add a
292
292
293 $ hg debugobsolete --rev 6f9641995072
293 $ hg debugobsolete --rev 6f9641995072
294 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
294 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
295 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
295 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
296 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
296 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
297 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
297 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
298 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
298 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
299 $ hg debugobsolete --rev 6f9641995072 --exclusive
299 $ hg debugobsolete --rev 6f9641995072 --exclusive
300 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
300 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
301 $ hg debugobsolete --rev 5601fb93a350 --hidden
301 $ hg debugobsolete --rev 5601fb93a350 --hidden
302 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
302 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
303 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
303 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
304 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
304 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
305 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
305 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
306 $ hg debugobsolete --rev 5601fb93a350 --hidden --exclusive
306 $ hg debugobsolete --rev 5601fb93a350 --hidden --exclusive
307 $ hg debugobsolete --rev 5601fb93a350+6f9641995072 --hidden --exclusive
307 $ hg debugobsolete --rev 5601fb93a350+6f9641995072 --hidden --exclusive
308 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
308 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
309 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
309 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
310 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
310 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
311
311
312 $ cd ..
312 $ cd ..
313
313
314 Revision 0 is hidden
314 Revision 0 is hidden
315 --------------------
315 --------------------
316
316
317 $ hg init rev0hidden
317 $ hg init rev0hidden
318 $ cd rev0hidden
318 $ cd rev0hidden
319
319
320 $ mkcommit kill0
320 $ mkcommit kill0
321 $ hg up -q null
321 $ hg up -q null
322 $ hg debugobsolete `getid kill0`
322 $ hg debugobsolete `getid kill0`
323 obsoleted 1 changesets
323 obsoleted 1 changesets
324 $ mkcommit a
324 $ mkcommit a
325 $ mkcommit b
325 $ mkcommit b
326
326
327 Should pick the first visible revision as "repo" node
327 Should pick the first visible revision as "repo" node
328
328
329 $ hg archive ../archive-null
329 $ hg archive ../archive-null
330 $ cat ../archive-null/.hg_archival.txt
330 $ cat ../archive-null/.hg_archival.txt
331 repo: 1f0dee641bb7258c56bd60e93edfa2405381c41e
331 repo: 1f0dee641bb7258c56bd60e93edfa2405381c41e
332 node: 7c3bad9141dcb46ff89abf5f61856facd56e476c
332 node: 7c3bad9141dcb46ff89abf5f61856facd56e476c
333 branch: default
333 branch: default
334 latesttag: null
334 latesttag: null
335 latesttagdistance: 2
335 latesttagdistance: 2
336 changessincelatesttag: 2
336 changessincelatesttag: 2
337
337
338
338
339 $ cd ..
339 $ cd ..
340
340
341 Exchange Test
341 Exchange Test
342 ============================
342 ============================
343
343
344 Destination repo does not have any data
344 Destination repo does not have any data
345 ---------------------------------------
345 ---------------------------------------
346
346
347 Simple incoming test
347 Simple incoming test
348
348
349 $ hg init tmpc
349 $ hg init tmpc
350 $ cd tmpc
350 $ cd tmpc
351 $ hg incoming ../tmpb
351 $ hg incoming ../tmpb
352 comparing with ../tmpb
352 comparing with ../tmpb
353 0:1f0dee641bb7 (public) [ ] add a
353 0:1f0dee641bb7 (public) [ ] add a
354 1:7c3bad9141dc (public) [ ] add b
354 1:7c3bad9141dc (public) [ ] add b
355 2:245bde4270cd (public) [ ] add original_c
355 2:245bde4270cd (public) [ ] add original_c
356 6:6f9641995072 (draft) [tip ] add n3w_3_c
356 6:6f9641995072 (draft) [tip ] add n3w_3_c
357
357
358 Try to pull markers
358 Try to pull markers
359 (extinct changeset are excluded but marker are pushed)
359 (extinct changeset are excluded but marker are pushed)
360
360
361 $ hg pull ../tmpb
361 $ hg pull ../tmpb
362 pulling from ../tmpb
362 pulling from ../tmpb
363 requesting all changes
363 requesting all changes
364 adding changesets
364 adding changesets
365 adding manifests
365 adding manifests
366 adding file changes
366 adding file changes
367 added 4 changesets with 4 changes to 4 files (+1 heads)
367 added 4 changesets with 4 changes to 4 files (+1 heads)
368 5 new obsolescence markers
368 5 new obsolescence markers
369 new changesets 1f0dee641bb7:6f9641995072
369 new changesets 1f0dee641bb7:6f9641995072
370 (run 'hg heads' to see heads, 'hg merge' to merge)
370 (run 'hg heads' to see heads, 'hg merge' to merge)
371 $ hg debugobsolete
371 $ hg debugobsolete
372 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
372 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
373 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
373 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
374 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
374 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
375 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
375 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
376 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
376 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
377
377
378 Rollback//Transaction support
378 Rollback//Transaction support
379
379
380 $ hg debugobsolete -d '1340 0' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
380 $ hg debugobsolete -d '1340 0' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
381 $ hg debugobsolete
381 $ hg debugobsolete
382 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
382 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
383 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
383 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
384 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
384 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
385 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
385 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
386 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
386 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
387 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 (Thu Jan 01 00:22:20 1970 +0000) {'user': 'test'}
387 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0 (Thu Jan 01 00:22:20 1970 +0000) {'user': 'test'}
388 $ hg rollback -n
388 $ hg rollback -n
389 repository tip rolled back to revision 3 (undo debugobsolete)
389 repository tip rolled back to revision 3 (undo debugobsolete)
390 $ hg rollback
390 $ hg rollback
391 repository tip rolled back to revision 3 (undo debugobsolete)
391 repository tip rolled back to revision 3 (undo debugobsolete)
392 $ hg debugobsolete
392 $ hg debugobsolete
393 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
393 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
394 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
394 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
395 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
395 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
396 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
396 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
397 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
397 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
398
398
399 $ cd ..
399 $ cd ..
400
400
401 Try to push markers
401 Try to push markers
402
402
403 $ hg init tmpd
403 $ hg init tmpd
404 $ hg -R tmpb push tmpd
404 $ hg -R tmpb push tmpd
405 pushing to tmpd
405 pushing to tmpd
406 searching for changes
406 searching for changes
407 adding changesets
407 adding changesets
408 adding manifests
408 adding manifests
409 adding file changes
409 adding file changes
410 added 4 changesets with 4 changes to 4 files (+1 heads)
410 added 4 changesets with 4 changes to 4 files (+1 heads)
411 5 new obsolescence markers
411 5 new obsolescence markers
412 $ hg -R tmpd debugobsolete | sort
412 $ hg -R tmpd debugobsolete | sort
413 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
413 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
414 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
414 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
415 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
415 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
416 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
416 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
417 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
417 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
418
418
419 Check obsolete keys are exchanged only if source has an obsolete store
419 Check obsolete keys are exchanged only if source has an obsolete store
420
420
421 $ hg init empty
421 $ hg init empty
422 $ hg --config extensions.debugkeys=debugkeys.py -R empty push tmpd
422 $ hg --config extensions.debugkeys=debugkeys.py -R empty push tmpd
423 pushing to tmpd
423 pushing to tmpd
424 listkeys phases
424 listkeys phases
425 listkeys bookmarks
425 listkeys bookmarks
426 no changes found
426 no changes found
427 listkeys phases
427 listkeys phases
428 [1]
428 [1]
429
429
430 clone support
430 clone support
431 (markers are copied and extinct changesets are included to allow hardlinks)
431 (markers are copied and extinct changesets are included to allow hardlinks)
432
432
433 $ hg clone tmpb clone-dest
433 $ hg clone tmpb clone-dest
434 updating to branch default
434 updating to branch default
435 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
435 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
436 $ hg -R clone-dest log -G --hidden
436 $ hg -R clone-dest log -G --hidden
437 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
437 @ 6:6f9641995072 (draft) [tip ] add n3w_3_c
438 |
438 |
439 | x 5:5601fb93a350 (draft *obsolete*) [ ] add new_3_c [rewritten as 6:6f9641995072]
439 | x 5:5601fb93a350 (draft *obsolete*) [ ] add new_3_c [rewritten as 6:6f9641995072]
440 |/
440 |/
441 | x 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c [rewritten as 5:5601fb93a350]
441 | x 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c [rewritten as 5:5601fb93a350]
442 |/
442 |/
443 | x 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c [rewritten as 4:ca819180edb9]
443 | x 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c [rewritten as 4:ca819180edb9]
444 |/
444 |/
445 | o 2:245bde4270cd (public) [ ] add original_c
445 | o 2:245bde4270cd (public) [ ] add original_c
446 |/
446 |/
447 o 1:7c3bad9141dc (public) [ ] add b
447 o 1:7c3bad9141dc (public) [ ] add b
448 |
448 |
449 o 0:1f0dee641bb7 (public) [ ] add a
449 o 0:1f0dee641bb7 (public) [ ] add a
450
450
451 $ hg -R clone-dest debugobsolete
451 $ hg -R clone-dest debugobsolete
452 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
452 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
453 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
453 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
454 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
454 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
455 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
455 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
456 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
456 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
457
457
458
458
459 Destination repo have existing data
459 Destination repo have existing data
460 ---------------------------------------
460 ---------------------------------------
461
461
462 On pull
462 On pull
463
463
464 $ hg init tmpe
464 $ hg init tmpe
465 $ cd tmpe
465 $ cd tmpe
466 $ hg debugobsolete -d '1339 0' 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00
466 $ hg debugobsolete -d '1339 0' 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00
467 $ hg pull ../tmpb
467 $ hg pull ../tmpb
468 pulling from ../tmpb
468 pulling from ../tmpb
469 requesting all changes
469 requesting all changes
470 adding changesets
470 adding changesets
471 adding manifests
471 adding manifests
472 adding file changes
472 adding file changes
473 added 4 changesets with 4 changes to 4 files (+1 heads)
473 added 4 changesets with 4 changes to 4 files (+1 heads)
474 5 new obsolescence markers
474 5 new obsolescence markers
475 new changesets 1f0dee641bb7:6f9641995072
475 new changesets 1f0dee641bb7:6f9641995072
476 (run 'hg heads' to see heads, 'hg merge' to merge)
476 (run 'hg heads' to see heads, 'hg merge' to merge)
477 $ hg debugobsolete
477 $ hg debugobsolete
478 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
478 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
479 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
479 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
480 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
480 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
481 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
481 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
482 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
482 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
483 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
483 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
484
484
485
485
486 On push
486 On push
487
487
488 $ hg push ../tmpc
488 $ hg push ../tmpc
489 pushing to ../tmpc
489 pushing to ../tmpc
490 searching for changes
490 searching for changes
491 no changes found
491 no changes found
492 1 new obsolescence markers
492 1 new obsolescence markers
493 [1]
493 [1]
494 $ hg -R ../tmpc debugobsolete
494 $ hg -R ../tmpc debugobsolete
495 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
495 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
496 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
496 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
497 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
497 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
498 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
498 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
499 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
499 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
500 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
500 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
501
501
502 detect outgoing obsolete and unstable
502 detect outgoing obsolete and unstable
503 ---------------------------------------
503 ---------------------------------------
504
504
505
505
506 $ hg log -G
506 $ hg log -G
507 o 3:6f9641995072 (draft) [tip ] add n3w_3_c
507 o 3:6f9641995072 (draft) [tip ] add n3w_3_c
508 |
508 |
509 | o 2:245bde4270cd (public) [ ] add original_c
509 | o 2:245bde4270cd (public) [ ] add original_c
510 |/
510 |/
511 o 1:7c3bad9141dc (public) [ ] add b
511 o 1:7c3bad9141dc (public) [ ] add b
512 |
512 |
513 o 0:1f0dee641bb7 (public) [ ] add a
513 o 0:1f0dee641bb7 (public) [ ] add a
514
514
515 $ hg up 'desc("n3w_3_c")'
515 $ hg up 'desc("n3w_3_c")'
516 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
516 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
517 $ mkcommit original_d
517 $ mkcommit original_d
518 $ mkcommit original_e
518 $ mkcommit original_e
519 $ hg debugobsolete --record-parents `getid original_d` -d '0 0'
519 $ hg debugobsolete --record-parents `getid original_d` -d '0 0'
520 obsoleted 1 changesets
520 obsoleted 1 changesets
521 $ hg debugobsolete | grep `getid original_d`
521 $ hg debugobsolete | grep `getid original_d`
522 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
522 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
523 $ hg log -r 'obsolete()'
523 $ hg log -r 'obsolete()'
524 4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned]
524 4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned]
525 $ hg summary
525 $ hg summary
526 parent: 5:cda648ca50f5 tip (orphan)
526 parent: 5:cda648ca50f5 tip (orphan)
527 add original_e
527 add original_e
528 branch: default
528 branch: default
529 commit: (clean)
529 commit: (clean)
530 update: 1 new changesets, 2 branch heads (merge)
530 update: 1 new changesets, 2 branch heads (merge)
531 phases: 3 draft
531 phases: 3 draft
532 orphan: 1 changesets
532 orphan: 1 changesets
533 $ hg log -G -r '::orphan()'
533 $ hg log -G -r '::orphan()'
534 @ 5:cda648ca50f5 (draft orphan) [tip ] add original_e
534 @ 5:cda648ca50f5 (draft orphan) [tip ] add original_e
535 |
535 |
536 x 4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned]
536 x 4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned]
537 |
537 |
538 o 3:6f9641995072 (draft) [ ] add n3w_3_c
538 o 3:6f9641995072 (draft) [ ] add n3w_3_c
539 |
539 |
540 o 1:7c3bad9141dc (public) [ ] add b
540 o 1:7c3bad9141dc (public) [ ] add b
541 |
541 |
542 o 0:1f0dee641bb7 (public) [ ] add a
542 o 0:1f0dee641bb7 (public) [ ] add a
543
543
544
544
545 refuse to push obsolete changeset
545 refuse to push obsolete changeset
546
546
547 $ hg push ../tmpc/ -r 'desc("original_d")'
547 $ hg push ../tmpc/ -r 'desc("original_d")'
548 pushing to ../tmpc/
548 pushing to ../tmpc/
549 searching for changes
549 searching for changes
550 abort: push includes obsolete changeset: 94b33453f93b!
550 abort: push includes obsolete changeset: 94b33453f93b!
551 [255]
551 [255]
552
552
553 refuse to push unstable changeset
553 refuse to push unstable changeset
554
554
555 $ hg push ../tmpc/
555 $ hg push ../tmpc/
556 pushing to ../tmpc/
556 pushing to ../tmpc/
557 searching for changes
557 searching for changes
558 abort: push includes orphan changeset: cda648ca50f5!
558 abort: push includes orphan changeset: cda648ca50f5!
559 [255]
559 [255]
560
560
561 Test that extinct changeset are properly detected
561 Test that extinct changeset are properly detected
562
562
563 $ hg log -r 'extinct()'
563 $ hg log -r 'extinct()'
564
564
565 Don't try to push extinct changeset
565 Don't try to push extinct changeset
566
566
567 $ hg init ../tmpf
567 $ hg init ../tmpf
568 $ hg out ../tmpf
568 $ hg out ../tmpf
569 comparing with ../tmpf
569 comparing with ../tmpf
570 searching for changes
570 searching for changes
571 0:1f0dee641bb7 (public) [ ] add a
571 0:1f0dee641bb7 (public) [ ] add a
572 1:7c3bad9141dc (public) [ ] add b
572 1:7c3bad9141dc (public) [ ] add b
573 2:245bde4270cd (public) [ ] add original_c
573 2:245bde4270cd (public) [ ] add original_c
574 3:6f9641995072 (draft) [ ] add n3w_3_c
574 3:6f9641995072 (draft) [ ] add n3w_3_c
575 4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned]
575 4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned]
576 5:cda648ca50f5 (draft orphan) [tip ] add original_e
576 5:cda648ca50f5 (draft orphan) [tip ] add original_e
577 $ hg push ../tmpf -f # -f because be push unstable too
577 $ hg push ../tmpf -f # -f because be push unstable too
578 pushing to ../tmpf
578 pushing to ../tmpf
579 searching for changes
579 searching for changes
580 adding changesets
580 adding changesets
581 adding manifests
581 adding manifests
582 adding file changes
582 adding file changes
583 added 6 changesets with 6 changes to 6 files (+1 heads)
583 added 6 changesets with 6 changes to 6 files (+1 heads)
584 7 new obsolescence markers
584 7 new obsolescence markers
585
585
586 no warning displayed
586 no warning displayed
587
587
588 $ hg push ../tmpf
588 $ hg push ../tmpf
589 pushing to ../tmpf
589 pushing to ../tmpf
590 searching for changes
590 searching for changes
591 no changes found
591 no changes found
592 [1]
592 [1]
593
593
594 Do not warn about new head when the new head is a successors of a remote one
594 Do not warn about new head when the new head is a successors of a remote one
595
595
596 $ hg log -G
596 $ hg log -G
597 @ 5:cda648ca50f5 (draft orphan) [tip ] add original_e
597 @ 5:cda648ca50f5 (draft orphan) [tip ] add original_e
598 |
598 |
599 x 4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned]
599 x 4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned]
600 |
600 |
601 o 3:6f9641995072 (draft) [ ] add n3w_3_c
601 o 3:6f9641995072 (draft) [ ] add n3w_3_c
602 |
602 |
603 | o 2:245bde4270cd (public) [ ] add original_c
603 | o 2:245bde4270cd (public) [ ] add original_c
604 |/
604 |/
605 o 1:7c3bad9141dc (public) [ ] add b
605 o 1:7c3bad9141dc (public) [ ] add b
606 |
606 |
607 o 0:1f0dee641bb7 (public) [ ] add a
607 o 0:1f0dee641bb7 (public) [ ] add a
608
608
609 $ hg up -q 'desc(n3w_3_c)'
609 $ hg up -q 'desc(n3w_3_c)'
610 $ mkcommit obsolete_e
610 $ mkcommit obsolete_e
611 created new head
611 created new head
612 $ hg debugobsolete `getid 'original_e'` `getid 'obsolete_e'` \
612 $ hg debugobsolete `getid 'original_e'` `getid 'obsolete_e'` \
613 > -u 'test <test@example.net>'
613 > -u 'test <test@example.net>'
614 obsoleted 1 changesets
614 obsoleted 1 changesets
615 $ hg outgoing ../tmpf # parasite hg outgoing testin
615 $ hg outgoing ../tmpf # parasite hg outgoing testin
616 comparing with ../tmpf
616 comparing with ../tmpf
617 searching for changes
617 searching for changes
618 6:3de5eca88c00 (draft) [tip ] add obsolete_e
618 6:3de5eca88c00 (draft) [tip ] add obsolete_e
619 $ hg push ../tmpf
619 $ hg push ../tmpf
620 pushing to ../tmpf
620 pushing to ../tmpf
621 searching for changes
621 searching for changes
622 adding changesets
622 adding changesets
623 adding manifests
623 adding manifests
624 adding file changes
624 adding file changes
625 added 1 changesets with 1 changes to 1 files (+1 heads)
625 added 1 changesets with 1 changes to 1 files (+1 heads)
626 1 new obsolescence markers
626 1 new obsolescence markers
627 obsoleted 1 changesets
627 obsoleted 1 changesets
628
628
629 test relevance computation
629 test relevance computation
630 ---------------------------------------
630 ---------------------------------------
631
631
632 Checking simple case of "marker relevance".
632 Checking simple case of "marker relevance".
633
633
634
634
635 Reminder of the repo situation
635 Reminder of the repo situation
636
636
637 $ hg log --hidden --graph
637 $ hg log --hidden --graph
638 @ 6:3de5eca88c00 (draft) [tip ] add obsolete_e
638 @ 6:3de5eca88c00 (draft) [tip ] add obsolete_e
639 |
639 |
640 | x 5:cda648ca50f5 (draft *obsolete*) [ ] add original_e [rewritten as 6:3de5eca88c00 by test <test@example.net>]
640 | x 5:cda648ca50f5 (draft *obsolete*) [ ] add original_e [rewritten as 6:3de5eca88c00 by test <test@example.net>]
641 | |
641 | |
642 | x 4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned]
642 | x 4:94b33453f93b (draft *obsolete*) [ ] add original_d [pruned]
643 |/
643 |/
644 o 3:6f9641995072 (draft) [ ] add n3w_3_c
644 o 3:6f9641995072 (draft) [ ] add n3w_3_c
645 |
645 |
646 | o 2:245bde4270cd (public) [ ] add original_c
646 | o 2:245bde4270cd (public) [ ] add original_c
647 |/
647 |/
648 o 1:7c3bad9141dc (public) [ ] add b
648 o 1:7c3bad9141dc (public) [ ] add b
649 |
649 |
650 o 0:1f0dee641bb7 (public) [ ] add a
650 o 0:1f0dee641bb7 (public) [ ] add a
651
651
652
652
653 List of all markers
653 List of all markers
654
654
655 $ hg debugobsolete
655 $ hg debugobsolete
656 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
656 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
657 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
657 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
658 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
658 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
659 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
659 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
660 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
660 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
661 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
661 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
662 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
662 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
663 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test <test@example.net>'} (glob)
663 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test <test@example.net>'} (glob)
664
664
665 List of changesets with no chain
665 List of changesets with no chain
666
666
667 $ hg debugobsolete --hidden --rev ::2
667 $ hg debugobsolete --hidden --rev ::2
668
668
669 List of changesets that are included on marker chain
669 List of changesets that are included on marker chain
670
670
671 $ hg debugobsolete --hidden --rev 6
671 $ hg debugobsolete --hidden --rev 6
672 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test <test@example.net>'} (glob)
672 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test <test@example.net>'} (glob)
673
673
674 List of changesets with a longer chain, (including a pruned children)
674 List of changesets with a longer chain, (including a pruned children)
675
675
676 $ hg debugobsolete --hidden --rev 3
676 $ hg debugobsolete --hidden --rev 3
677 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
677 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
678 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
678 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
679 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
679 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
680 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
680 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
681 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
681 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
682 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
682 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
683 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
683 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
684
684
685 List of both
685 List of both
686
686
687 $ hg debugobsolete --hidden --rev 3::6
687 $ hg debugobsolete --hidden --rev 3::6
688 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
688 1337133713371337133713371337133713371337 5601fb93a350734d935195fee37f4054c529ff39 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
689 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
689 1339133913391339133913391339133913391339 ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:19 1970 +0000) {'user': 'test'}
690 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
690 245bde4270cd1072a27757984f9cda8ba26f08ca cdbce2fbb16313928851e97e0d85413f3f7eb77f C (Thu Jan 01 00:00:01 1970 -0002) {'user': 'test'}
691 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
691 5601fb93a350734d935195fee37f4054c529ff39 6f96419950729f3671185b847352890f074f7557 1 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
692 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
692 94b33453f93bdb8d457ef9b770851a618bf413e1 0 {6f96419950729f3671185b847352890f074f7557} (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
693 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
693 ca819180edb99ed25ceafb3e9584ac287e240b00 1337133713371337133713371337133713371337 0 (Thu Jan 01 00:22:18 1970 +0000) {'user': 'test'}
694 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test <test@example.net>'} (glob)
694 cda648ca50f50482b7055c0b0c4c117bba6733d9 3de5eca88c00aa039da7399a220f4a5221faa585 0 (*) {'user': 'test <test@example.net>'} (glob)
695 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
695 cdbce2fbb16313928851e97e0d85413f3f7eb77f ca819180edb99ed25ceafb3e9584ac287e240b00 0 (Thu Jan 01 00:22:17 1970 +0000) {'user': 'test'}
696
696
697 List of all markers in JSON
697 List of all markers in JSON
698
698
699 $ hg debugobsolete -Tjson
699 $ hg debugobsolete -Tjson
700 [
700 [
701 {
701 {
702 "date": [1339.0, 0],
702 "date": [1339.0, 0],
703 "flag": 0,
703 "flag": 0,
704 "metadata": {"user": "test"},
704 "metadata": {"user": "test"},
705 "prednode": "1339133913391339133913391339133913391339",
705 "prednode": "1339133913391339133913391339133913391339",
706 "succnodes": ["ca819180edb99ed25ceafb3e9584ac287e240b00"]
706 "succnodes": ["ca819180edb99ed25ceafb3e9584ac287e240b00"]
707 },
707 },
708 {
708 {
709 "date": [1339.0, 0],
709 "date": [1339.0, 0],
710 "flag": 0,
710 "flag": 0,
711 "metadata": {"user": "test"},
711 "metadata": {"user": "test"},
712 "prednode": "1337133713371337133713371337133713371337",
712 "prednode": "1337133713371337133713371337133713371337",
713 "succnodes": ["5601fb93a350734d935195fee37f4054c529ff39"]
713 "succnodes": ["5601fb93a350734d935195fee37f4054c529ff39"]
714 },
714 },
715 {
715 {
716 "date": [121.0, 120],
716 "date": [121.0, 120],
717 "flag": 12,
717 "flag": 12,
718 "metadata": {"user": "test"},
718 "metadata": {"user": "test"},
719 "prednode": "245bde4270cd1072a27757984f9cda8ba26f08ca",
719 "prednode": "245bde4270cd1072a27757984f9cda8ba26f08ca",
720 "succnodes": ["cdbce2fbb16313928851e97e0d85413f3f7eb77f"]
720 "succnodes": ["cdbce2fbb16313928851e97e0d85413f3f7eb77f"]
721 },
721 },
722 {
722 {
723 "date": [1338.0, 0],
723 "date": [1338.0, 0],
724 "flag": 1,
724 "flag": 1,
725 "metadata": {"user": "test"},
725 "metadata": {"user": "test"},
726 "prednode": "5601fb93a350734d935195fee37f4054c529ff39",
726 "prednode": "5601fb93a350734d935195fee37f4054c529ff39",
727 "succnodes": ["6f96419950729f3671185b847352890f074f7557"]
727 "succnodes": ["6f96419950729f3671185b847352890f074f7557"]
728 },
728 },
729 {
729 {
730 "date": [1338.0, 0],
730 "date": [1338.0, 0],
731 "flag": 0,
731 "flag": 0,
732 "metadata": {"user": "test"},
732 "metadata": {"user": "test"},
733 "prednode": "ca819180edb99ed25ceafb3e9584ac287e240b00",
733 "prednode": "ca819180edb99ed25ceafb3e9584ac287e240b00",
734 "succnodes": ["1337133713371337133713371337133713371337"]
734 "succnodes": ["1337133713371337133713371337133713371337"]
735 },
735 },
736 {
736 {
737 "date": [1337.0, 0],
737 "date": [1337.0, 0],
738 "flag": 0,
738 "flag": 0,
739 "metadata": {"user": "test"},
739 "metadata": {"user": "test"},
740 "prednode": "cdbce2fbb16313928851e97e0d85413f3f7eb77f",
740 "prednode": "cdbce2fbb16313928851e97e0d85413f3f7eb77f",
741 "succnodes": ["ca819180edb99ed25ceafb3e9584ac287e240b00"]
741 "succnodes": ["ca819180edb99ed25ceafb3e9584ac287e240b00"]
742 },
742 },
743 {
743 {
744 "date": [0.0, 0],
744 "date": [0.0, 0],
745 "flag": 0,
745 "flag": 0,
746 "metadata": {"user": "test"},
746 "metadata": {"user": "test"},
747 "parentnodes": ["6f96419950729f3671185b847352890f074f7557"],
747 "parentnodes": ["6f96419950729f3671185b847352890f074f7557"],
748 "prednode": "94b33453f93bdb8d457ef9b770851a618bf413e1",
748 "prednode": "94b33453f93bdb8d457ef9b770851a618bf413e1",
749 "succnodes": []
749 "succnodes": []
750 },
750 },
751 {
751 {
752 "date": *, (glob)
752 "date": *, (glob)
753 "flag": 0,
753 "flag": 0,
754 "metadata": {"user": "test <test@example.net>"},
754 "metadata": {"user": "test <test@example.net>"},
755 "prednode": "cda648ca50f50482b7055c0b0c4c117bba6733d9",
755 "prednode": "cda648ca50f50482b7055c0b0c4c117bba6733d9",
756 "succnodes": ["3de5eca88c00aa039da7399a220f4a5221faa585"]
756 "succnodes": ["3de5eca88c00aa039da7399a220f4a5221faa585"]
757 }
757 }
758 ]
758 ]
759
759
760 Template keywords
760 Template keywords
761
761
762 $ hg debugobsolete -r6 -T '{succnodes % "{node|short}"} {date|shortdate}\n'
762 $ hg debugobsolete -r6 -T '{succnodes % "{node|short}"} {date|shortdate}\n'
763 3de5eca88c00 ????-??-?? (glob)
763 3de5eca88c00 ????-??-?? (glob)
764 $ hg debugobsolete -r6 -T '{join(metadata % "{key}={value}", " ")}\n'
764 $ hg debugobsolete -r6 -T '{join(metadata % "{key}={value}", " ")}\n'
765 user=test <test@example.net>
765 user=test <test@example.net>
766 $ hg debugobsolete -r6 -T '{metadata}\n{metadata}\n'
766 $ hg debugobsolete -r6 -T '{metadata}\n{metadata}\n'
767 'user': 'test <test@example.net>'
767 'user': 'test <test@example.net>'
768 'user': 'test <test@example.net>'
768 'user': 'test <test@example.net>'
769 $ hg debugobsolete -r6 -T '{succnodes}\n{succnodes}\n'
769 $ hg debugobsolete -r6 -T '{succnodes}\n{succnodes}\n'
770 3de5eca88c00aa039da7399a220f4a5221faa585
770 3de5eca88c00aa039da7399a220f4a5221faa585
771 3de5eca88c00aa039da7399a220f4a5221faa585
771 3de5eca88c00aa039da7399a220f4a5221faa585
772 $ hg debugobsolete -r6 -T '{flag} {get(metadata, "user")}\n'
772 $ hg debugobsolete -r6 -T '{flag} {get(metadata, "user")}\n'
773 0 test <test@example.net>
773 0 test <test@example.net>
774
774
775 Test the debug output for exchange
775 Test the debug output for exchange
776 ----------------------------------
776 ----------------------------------
777
777
778 $ hg pull ../tmpb --config 'experimental.obsmarkers-exchange-debug=True' # bundle2
778 $ hg pull ../tmpb --config 'experimental.obsmarkers-exchange-debug=True' # bundle2
779 pulling from ../tmpb
779 pulling from ../tmpb
780 searching for changes
780 searching for changes
781 no changes found
781 no changes found
782 obsmarker-exchange: 346 bytes received
782 obsmarker-exchange: 346 bytes received
783
783
784 check hgweb does not explode
784 check hgweb does not explode
785 ====================================
785 ====================================
786
786
787 $ hg unbundle $TESTDIR/bundles/hgweb+obs.hg
787 $ hg unbundle $TESTDIR/bundles/hgweb+obs.hg
788 adding changesets
788 adding changesets
789 adding manifests
789 adding manifests
790 adding file changes
790 adding file changes
791 added 62 changesets with 63 changes to 9 files (+60 heads)
791 added 62 changesets with 63 changes to 9 files (+60 heads)
792 new changesets 50c51b361e60:c15e9edfca13
792 new changesets 50c51b361e60:c15e9edfca13
793 (run 'hg heads .' to see heads, 'hg merge' to merge)
793 (run 'hg heads .' to see heads, 'hg merge' to merge)
794 $ for node in `hg log -r 'desc(babar_)' --template '{node}\n'`;
794 $ for node in `hg log -r 'desc(babar_)' --template '{node}\n'`;
795 > do
795 > do
796 > hg debugobsolete $node
796 > hg debugobsolete $node
797 > done
797 > done
798 obsoleted 1 changesets
798 obsoleted 1 changesets
799 obsoleted 1 changesets
799 obsoleted 1 changesets
800 obsoleted 1 changesets
800 obsoleted 1 changesets
801 obsoleted 1 changesets
801 obsoleted 1 changesets
802 obsoleted 1 changesets
802 obsoleted 1 changesets
803 obsoleted 1 changesets
803 obsoleted 1 changesets
804 obsoleted 1 changesets
804 obsoleted 1 changesets
805 obsoleted 1 changesets
805 obsoleted 1 changesets
806 obsoleted 1 changesets
806 obsoleted 1 changesets
807 obsoleted 1 changesets
807 obsoleted 1 changesets
808 obsoleted 1 changesets
808 obsoleted 1 changesets
809 obsoleted 1 changesets
809 obsoleted 1 changesets
810 obsoleted 1 changesets
810 obsoleted 1 changesets
811 obsoleted 1 changesets
811 obsoleted 1 changesets
812 obsoleted 1 changesets
812 obsoleted 1 changesets
813 obsoleted 1 changesets
813 obsoleted 1 changesets
814 obsoleted 1 changesets
814 obsoleted 1 changesets
815 obsoleted 1 changesets
815 obsoleted 1 changesets
816 obsoleted 1 changesets
816 obsoleted 1 changesets
817 obsoleted 1 changesets
817 obsoleted 1 changesets
818 obsoleted 1 changesets
818 obsoleted 1 changesets
819 obsoleted 1 changesets
819 obsoleted 1 changesets
820 obsoleted 1 changesets
820 obsoleted 1 changesets
821 obsoleted 1 changesets
821 obsoleted 1 changesets
822 obsoleted 1 changesets
822 obsoleted 1 changesets
823 obsoleted 1 changesets
823 obsoleted 1 changesets
824 obsoleted 1 changesets
824 obsoleted 1 changesets
825 obsoleted 1 changesets
825 obsoleted 1 changesets
826 obsoleted 1 changesets
826 obsoleted 1 changesets
827 obsoleted 1 changesets
827 obsoleted 1 changesets
828 obsoleted 1 changesets
828 obsoleted 1 changesets
829 obsoleted 1 changesets
829 obsoleted 1 changesets
830 obsoleted 1 changesets
830 obsoleted 1 changesets
831 obsoleted 1 changesets
831 obsoleted 1 changesets
832 obsoleted 1 changesets
832 obsoleted 1 changesets
833 obsoleted 1 changesets
833 obsoleted 1 changesets
834 obsoleted 1 changesets
834 obsoleted 1 changesets
835 obsoleted 1 changesets
835 obsoleted 1 changesets
836 obsoleted 1 changesets
836 obsoleted 1 changesets
837 obsoleted 1 changesets
837 obsoleted 1 changesets
838 obsoleted 1 changesets
838 obsoleted 1 changesets
839 obsoleted 1 changesets
839 obsoleted 1 changesets
840 obsoleted 1 changesets
840 obsoleted 1 changesets
841 obsoleted 1 changesets
841 obsoleted 1 changesets
842 obsoleted 1 changesets
842 obsoleted 1 changesets
843 obsoleted 1 changesets
843 obsoleted 1 changesets
844 obsoleted 1 changesets
844 obsoleted 1 changesets
845 obsoleted 1 changesets
845 obsoleted 1 changesets
846 obsoleted 1 changesets
846 obsoleted 1 changesets
847 obsoleted 1 changesets
847 obsoleted 1 changesets
848 obsoleted 1 changesets
848 obsoleted 1 changesets
849 obsoleted 1 changesets
849 obsoleted 1 changesets
850 obsoleted 1 changesets
850 obsoleted 1 changesets
851 obsoleted 1 changesets
851 obsoleted 1 changesets
852 obsoleted 1 changesets
852 obsoleted 1 changesets
853 obsoleted 1 changesets
853 obsoleted 1 changesets
854 obsoleted 1 changesets
854 obsoleted 1 changesets
855 obsoleted 1 changesets
855 obsoleted 1 changesets
856 obsoleted 1 changesets
856 obsoleted 1 changesets
857 obsoleted 1 changesets
857 obsoleted 1 changesets
858 $ hg up tip
858 $ hg up tip
859 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
859 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
860
860
861 #if serve
861 #if serve
862
862
863 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
863 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
864 $ cat hg.pid >> $DAEMON_PIDS
864 $ cat hg.pid >> $DAEMON_PIDS
865
865
866 check changelog view
866 check changelog view
867
867
868 $ get-with-headers.py --headeronly localhost:$HGPORT 'shortlog/'
868 $ get-with-headers.py --headeronly localhost:$HGPORT 'shortlog/'
869 200 Script output follows
869 200 Script output follows
870
870
871 check graph view
871 check graph view
872
872
873 $ get-with-headers.py --headeronly localhost:$HGPORT 'graph'
873 $ get-with-headers.py --headeronly localhost:$HGPORT 'graph'
874 200 Script output follows
874 200 Script output follows
875
875
876 check filelog view
876 check filelog view
877
877
878 $ get-with-headers.py --headeronly localhost:$HGPORT 'log/'`hg log -r . -T "{node}"`/'babar'
878 $ get-with-headers.py --headeronly localhost:$HGPORT 'log/'`hg log -r . -T "{node}"`/'babar'
879 200 Script output follows
879 200 Script output follows
880
880
881 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/68'
881 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/68'
882 200 Script output follows
882 200 Script output follows
883 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/67'
883 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/67'
884 404 Not Found
884 404 Not Found
885 [1]
885 [1]
886
886
887 check that web.view config option:
887 check that web.view config option:
888
888
889 $ killdaemons.py hg.pid
889 $ killdaemons.py hg.pid
890 $ cat >> .hg/hgrc << EOF
890 $ cat >> .hg/hgrc << EOF
891 > [web]
891 > [web]
892 > view=all
892 > view=all
893 > EOF
893 > EOF
894 $ wait
894 $ wait
895 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
895 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
896 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/67'
896 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/67'
897 200 Script output follows
897 200 Script output follows
898 $ killdaemons.py hg.pid
898 $ killdaemons.py hg.pid
899
899
900 Checking _enable=False warning if obsolete marker exists
900 Checking _enable=False warning if obsolete marker exists
901
901
902 $ echo '[experimental]' >> $HGRCPATH
902 $ echo '[experimental]' >> $HGRCPATH
903 $ echo "evolution=" >> $HGRCPATH
903 $ echo "evolution=" >> $HGRCPATH
904 $ hg log -r tip
904 $ hg log -r tip
905 68:c15e9edfca13 (draft) [tip ] add celestine
905 68:c15e9edfca13 (draft) [tip ] add celestine
906
906
907 reenable for later test
907 reenable for later test
908
908
909 $ echo '[experimental]' >> $HGRCPATH
909 $ echo '[experimental]' >> $HGRCPATH
910 $ echo "evolution.exchange=True" >> $HGRCPATH
910 $ echo "evolution.exchange=True" >> $HGRCPATH
911 $ echo "evolution.createmarkers=True" >> $HGRCPATH
911 $ echo "evolution.createmarkers=True" >> $HGRCPATH
912
912
913 $ rm hg.pid access.log errors.log
913 $ rm hg.pid access.log errors.log
914 #endif
914 #endif
915
915
916 Several troubles on the same changeset (create an unstable and bumped changeset)
916 Several troubles on the same changeset (create an unstable and bumped changeset)
917
917
918 $ hg debugobsolete `getid obsolete_e`
918 $ hg debugobsolete `getid obsolete_e`
919 obsoleted 1 changesets
919 obsoleted 1 changesets
920 $ hg debugobsolete `getid original_c` `getid babar`
920 $ hg debugobsolete `getid original_c` `getid babar`
921 $ hg log --config ui.logtemplate= -r 'phasedivergent() and orphan()'
921 $ hg log --config ui.logtemplate= -r 'phasedivergent() and orphan()'
922 changeset: 7:50c51b361e60
922 changeset: 7:50c51b361e60
923 user: test
923 user: test
924 date: Thu Jan 01 00:00:00 1970 +0000
924 date: Thu Jan 01 00:00:00 1970 +0000
925 instability: orphan, phase-divergent
925 instability: orphan, phase-divergent
926 summary: add babar
926 summary: add babar
927
927
928
928
929 test the "obsolete" templatekw
929 test the "obsolete" templatekw
930
930
931 $ hg log -r 'obsolete()'
931 $ hg log -r 'obsolete()'
932 6:3de5eca88c00 (draft *obsolete*) [ ] add obsolete_e [pruned]
932 6:3de5eca88c00 (draft *obsolete*) [ ] add obsolete_e [pruned]
933
933
934 test the "troubles" templatekw
934 test the "troubles" templatekw
935
935
936 $ hg log -r 'phasedivergent() and orphan()'
936 $ hg log -r 'phasedivergent() and orphan()'
937 7:50c51b361e60 (draft orphan phase-divergent) [ ] add babar
937 7:50c51b361e60 (draft orphan phase-divergent) [ ] add babar
938
938
939 test the default cmdline template
939 test the default cmdline template
940
940
941 $ hg log -T default -r 'phasedivergent()'
941 $ hg log -T default -r 'phasedivergent()'
942 changeset: 7:50c51b361e60
942 changeset: 7:50c51b361e60
943 user: test
943 user: test
944 date: Thu Jan 01 00:00:00 1970 +0000
944 date: Thu Jan 01 00:00:00 1970 +0000
945 instability: orphan, phase-divergent
945 instability: orphan, phase-divergent
946 summary: add babar
946 summary: add babar
947
947
948 $ hg log -T default -r 'obsolete()'
948 $ hg log -T default -r 'obsolete()'
949 changeset: 6:3de5eca88c00
949 changeset: 6:3de5eca88c00
950 parent: 3:6f9641995072
950 parent: 3:6f9641995072
951 user: test
951 user: test
952 date: Thu Jan 01 00:00:00 1970 +0000
952 date: Thu Jan 01 00:00:00 1970 +0000
953 obsfate: pruned
953 obsfate: pruned
954 summary: add obsolete_e
954 summary: add obsolete_e
955
955
956
956
957 test the obsolete labels
957 test the obsolete labels
958
958
959 $ hg log --config ui.logtemplate= --color=debug -r 'phasedivergent()'
959 $ hg log --config ui.logtemplate= --color=debug -r 'phasedivergent()'
960 [log.changeset changeset.draft changeset.unstable instability.orphan instability.phase-divergent|changeset: 7:50c51b361e60]
960 [log.changeset changeset.draft changeset.unstable instability.orphan instability.phase-divergent|changeset: 7:50c51b361e60]
961 [log.user|user: test]
961 [log.user|user: test]
962 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
962 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
963 [log.instability|instability: orphan, phase-divergent]
963 [log.instability|instability: orphan, phase-divergent]
964 [log.summary|summary: add babar]
964 [log.summary|summary: add babar]
965
965
966
966
967 $ hg log -T default -r 'phasedivergent()' --color=debug
967 $ hg log -T default -r 'phasedivergent()' --color=debug
968 [log.changeset changeset.draft changeset.unstable instability.orphan instability.phase-divergent|changeset: 7:50c51b361e60]
968 [log.changeset changeset.draft changeset.unstable instability.orphan instability.phase-divergent|changeset: 7:50c51b361e60]
969 [log.user|user: test]
969 [log.user|user: test]
970 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
970 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
971 [log.instability|instability: orphan, phase-divergent]
971 [log.instability|instability: orphan, phase-divergent]
972 [log.summary|summary: add babar]
972 [log.summary|summary: add babar]
973
973
974
974
975 $ hg log --config ui.logtemplate= --color=debug -r "obsolete()"
975 $ hg log --config ui.logtemplate= --color=debug -r "obsolete()"
976 [log.changeset changeset.draft changeset.obsolete|changeset: 6:3de5eca88c00]
976 [log.changeset changeset.draft changeset.obsolete|changeset: 6:3de5eca88c00]
977 [log.parent changeset.draft|parent: 3:6f9641995072]
977 [log.parent changeset.draft|parent: 3:6f9641995072]
978 [log.user|user: test]
978 [log.user|user: test]
979 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
979 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
980 [log.obsfate|obsfate: pruned]
980 [log.obsfate|obsolete: pruned]
981 [log.summary|summary: add obsolete_e]
981 [log.summary|summary: add obsolete_e]
982
982
983
983
984 $ hg log -T default -r 'obsolete()' --color=debug
984 $ hg log -T default -r 'obsolete()' --color=debug
985 [log.changeset changeset.draft changeset.obsolete|changeset: 6:3de5eca88c00]
985 [log.changeset changeset.draft changeset.obsolete|changeset: 6:3de5eca88c00]
986 [log.parent changeset.draft|parent: 3:6f9641995072]
986 [log.parent changeset.draft|parent: 3:6f9641995072]
987 [log.user|user: test]
987 [log.user|user: test]
988 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
988 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
989 [log.obsfate|obsfate: pruned]
989 [log.obsfate|obsfate: pruned]
990 [log.summary|summary: add obsolete_e]
990 [log.summary|summary: add obsolete_e]
991
991
992
992
993 test summary output
993 test summary output
994
994
995 $ hg up -r 'phasedivergent() and orphan()'
995 $ hg up -r 'phasedivergent() and orphan()'
996 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
996 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
997 $ hg summary
997 $ hg summary
998 parent: 7:50c51b361e60 (orphan, phase-divergent)
998 parent: 7:50c51b361e60 (orphan, phase-divergent)
999 add babar
999 add babar
1000 branch: default
1000 branch: default
1001 commit: (clean)
1001 commit: (clean)
1002 update: 2 new changesets (update)
1002 update: 2 new changesets (update)
1003 phases: 4 draft
1003 phases: 4 draft
1004 orphan: 2 changesets
1004 orphan: 2 changesets
1005 phase-divergent: 1 changesets
1005 phase-divergent: 1 changesets
1006 $ hg up -r 'obsolete()'
1006 $ hg up -r 'obsolete()'
1007 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1007 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1008 $ hg summary
1008 $ hg summary
1009 parent: 6:3de5eca88c00 (obsolete)
1009 parent: 6:3de5eca88c00 (obsolete)
1010 add obsolete_e
1010 add obsolete_e
1011 branch: default
1011 branch: default
1012 commit: (clean)
1012 commit: (clean)
1013 update: 3 new changesets (update)
1013 update: 3 new changesets (update)
1014 phases: 4 draft
1014 phases: 4 draft
1015 orphan: 2 changesets
1015 orphan: 2 changesets
1016 phase-divergent: 1 changesets
1016 phase-divergent: 1 changesets
1017
1017
1018 Test incoming/outcoming with changesets obsoleted remotely, known locally
1018 Test incoming/outcoming with changesets obsoleted remotely, known locally
1019 ===============================================================================
1019 ===============================================================================
1020
1020
1021 This test issue 3805
1021 This test issue 3805
1022
1022
1023 $ hg init repo-issue3805
1023 $ hg init repo-issue3805
1024 $ cd repo-issue3805
1024 $ cd repo-issue3805
1025 $ echo "base" > base
1025 $ echo "base" > base
1026 $ hg ci -Am "base"
1026 $ hg ci -Am "base"
1027 adding base
1027 adding base
1028 $ echo "foo" > foo
1028 $ echo "foo" > foo
1029 $ hg ci -Am "A"
1029 $ hg ci -Am "A"
1030 adding foo
1030 adding foo
1031 $ hg clone . ../other-issue3805
1031 $ hg clone . ../other-issue3805
1032 updating to branch default
1032 updating to branch default
1033 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1033 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1034 $ echo "bar" >> foo
1034 $ echo "bar" >> foo
1035 $ hg ci --amend
1035 $ hg ci --amend
1036 $ cd ../other-issue3805
1036 $ cd ../other-issue3805
1037 $ hg log -G
1037 $ hg log -G
1038 @ 1:29f0c6921ddd (draft) [tip ] A
1038 @ 1:29f0c6921ddd (draft) [tip ] A
1039 |
1039 |
1040 o 0:d20a80d4def3 (draft) [ ] base
1040 o 0:d20a80d4def3 (draft) [ ] base
1041
1041
1042 $ hg log -G -R ../repo-issue3805
1042 $ hg log -G -R ../repo-issue3805
1043 @ 2:323a9c3ddd91 (draft) [tip ] A
1043 @ 2:323a9c3ddd91 (draft) [tip ] A
1044 |
1044 |
1045 o 0:d20a80d4def3 (draft) [ ] base
1045 o 0:d20a80d4def3 (draft) [ ] base
1046
1046
1047 $ hg incoming
1047 $ hg incoming
1048 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
1048 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
1049 searching for changes
1049 searching for changes
1050 2:323a9c3ddd91 (draft) [tip ] A
1050 2:323a9c3ddd91 (draft) [tip ] A
1051 $ hg incoming --bundle ../issue3805.hg
1051 $ hg incoming --bundle ../issue3805.hg
1052 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
1052 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
1053 searching for changes
1053 searching for changes
1054 2:323a9c3ddd91 (draft) [tip ] A
1054 2:323a9c3ddd91 (draft) [tip ] A
1055 $ hg outgoing
1055 $ hg outgoing
1056 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
1056 comparing with $TESTTMP/tmpe/repo-issue3805 (glob)
1057 searching for changes
1057 searching for changes
1058 1:29f0c6921ddd (draft) [tip ] A
1058 1:29f0c6921ddd (draft) [tip ] A
1059
1059
1060 #if serve
1060 #if serve
1061
1061
1062 $ hg serve -R ../repo-issue3805 -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1062 $ hg serve -R ../repo-issue3805 -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1063 $ cat hg.pid >> $DAEMON_PIDS
1063 $ cat hg.pid >> $DAEMON_PIDS
1064
1064
1065 $ hg incoming http://localhost:$HGPORT
1065 $ hg incoming http://localhost:$HGPORT
1066 comparing with http://localhost:$HGPORT/
1066 comparing with http://localhost:$HGPORT/
1067 searching for changes
1067 searching for changes
1068 2:323a9c3ddd91 (draft) [tip ] A
1068 2:323a9c3ddd91 (draft) [tip ] A
1069 $ hg outgoing http://localhost:$HGPORT
1069 $ hg outgoing http://localhost:$HGPORT
1070 comparing with http://localhost:$HGPORT/
1070 comparing with http://localhost:$HGPORT/
1071 searching for changes
1071 searching for changes
1072 1:29f0c6921ddd (draft) [tip ] A
1072 1:29f0c6921ddd (draft) [tip ] A
1073
1073
1074 $ killdaemons.py
1074 $ killdaemons.py
1075
1075
1076 #endif
1076 #endif
1077
1077
1078 This test issue 3814
1078 This test issue 3814
1079
1079
1080 (nothing to push but locally hidden changeset)
1080 (nothing to push but locally hidden changeset)
1081
1081
1082 $ cd ..
1082 $ cd ..
1083 $ hg init repo-issue3814
1083 $ hg init repo-issue3814
1084 $ cd repo-issue3805
1084 $ cd repo-issue3805
1085 $ hg push -r 323a9c3ddd91 ../repo-issue3814
1085 $ hg push -r 323a9c3ddd91 ../repo-issue3814
1086 pushing to ../repo-issue3814
1086 pushing to ../repo-issue3814
1087 searching for changes
1087 searching for changes
1088 adding changesets
1088 adding changesets
1089 adding manifests
1089 adding manifests
1090 adding file changes
1090 adding file changes
1091 added 2 changesets with 2 changes to 2 files
1091 added 2 changesets with 2 changes to 2 files
1092 1 new obsolescence markers
1092 1 new obsolescence markers
1093 $ hg out ../repo-issue3814
1093 $ hg out ../repo-issue3814
1094 comparing with ../repo-issue3814
1094 comparing with ../repo-issue3814
1095 searching for changes
1095 searching for changes
1096 no changes found
1096 no changes found
1097 [1]
1097 [1]
1098
1098
1099 Test that a local tag blocks a changeset from being hidden
1099 Test that a local tag blocks a changeset from being hidden
1100
1100
1101 $ hg tag -l visible -r 1 --hidden
1101 $ hg tag -l visible -r 1 --hidden
1102 $ hg log -G
1102 $ hg log -G
1103 @ 2:323a9c3ddd91 (draft) [tip ] A
1103 @ 2:323a9c3ddd91 (draft) [tip ] A
1104 |
1104 |
1105 | x 1:29f0c6921ddd (draft *obsolete*) [visible ] A [rewritten using amend as 2:323a9c3ddd91]
1105 | x 1:29f0c6921ddd (draft *obsolete*) [visible ] A [rewritten using amend as 2:323a9c3ddd91]
1106 |/
1106 |/
1107 o 0:d20a80d4def3 (draft) [ ] base
1107 o 0:d20a80d4def3 (draft) [ ] base
1108
1108
1109 Test that removing a local tag does not cause some commands to fail
1109 Test that removing a local tag does not cause some commands to fail
1110
1110
1111 $ hg tag -l -r tip tiptag
1111 $ hg tag -l -r tip tiptag
1112 $ hg tags
1112 $ hg tags
1113 tiptag 2:323a9c3ddd91
1113 tiptag 2:323a9c3ddd91
1114 tip 2:323a9c3ddd91
1114 tip 2:323a9c3ddd91
1115 visible 1:29f0c6921ddd
1115 visible 1:29f0c6921ddd
1116 $ hg --config extensions.strip= strip -r tip --no-backup
1116 $ hg --config extensions.strip= strip -r tip --no-backup
1117 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1117 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1118 $ hg tags
1118 $ hg tags
1119 visible 1:29f0c6921ddd
1119 visible 1:29f0c6921ddd
1120 tip 1:29f0c6921ddd
1120 tip 1:29f0c6921ddd
1121
1121
1122 Test bundle overlay onto hidden revision
1122 Test bundle overlay onto hidden revision
1123
1123
1124 $ cd ..
1124 $ cd ..
1125 $ hg init repo-bundleoverlay
1125 $ hg init repo-bundleoverlay
1126 $ cd repo-bundleoverlay
1126 $ cd repo-bundleoverlay
1127 $ echo "A" > foo
1127 $ echo "A" > foo
1128 $ hg ci -Am "A"
1128 $ hg ci -Am "A"
1129 adding foo
1129 adding foo
1130 $ echo "B" >> foo
1130 $ echo "B" >> foo
1131 $ hg ci -m "B"
1131 $ hg ci -m "B"
1132 $ hg up 0
1132 $ hg up 0
1133 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1133 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1134 $ echo "C" >> foo
1134 $ echo "C" >> foo
1135 $ hg ci -m "C"
1135 $ hg ci -m "C"
1136 created new head
1136 created new head
1137 $ hg log -G
1137 $ hg log -G
1138 @ 2:c186d7714947 (draft) [tip ] C
1138 @ 2:c186d7714947 (draft) [tip ] C
1139 |
1139 |
1140 | o 1:44526ebb0f98 (draft) [ ] B
1140 | o 1:44526ebb0f98 (draft) [ ] B
1141 |/
1141 |/
1142 o 0:4b34ecfb0d56 (draft) [ ] A
1142 o 0:4b34ecfb0d56 (draft) [ ] A
1143
1143
1144
1144
1145 $ hg clone -r1 . ../other-bundleoverlay
1145 $ hg clone -r1 . ../other-bundleoverlay
1146 adding changesets
1146 adding changesets
1147 adding manifests
1147 adding manifests
1148 adding file changes
1148 adding file changes
1149 added 2 changesets with 2 changes to 1 files
1149 added 2 changesets with 2 changes to 1 files
1150 new changesets 4b34ecfb0d56:44526ebb0f98
1150 new changesets 4b34ecfb0d56:44526ebb0f98
1151 updating to branch default
1151 updating to branch default
1152 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1152 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1153 $ cd ../other-bundleoverlay
1153 $ cd ../other-bundleoverlay
1154 $ echo "B+" >> foo
1154 $ echo "B+" >> foo
1155 $ hg ci --amend -m "B+"
1155 $ hg ci --amend -m "B+"
1156 $ hg log -G --hidden
1156 $ hg log -G --hidden
1157 @ 2:b7d587542d40 (draft) [tip ] B+
1157 @ 2:b7d587542d40 (draft) [tip ] B+
1158 |
1158 |
1159 | x 1:44526ebb0f98 (draft *obsolete*) [ ] B [rewritten using amend as 2:b7d587542d40]
1159 | x 1:44526ebb0f98 (draft *obsolete*) [ ] B [rewritten using amend as 2:b7d587542d40]
1160 |/
1160 |/
1161 o 0:4b34ecfb0d56 (draft) [ ] A
1161 o 0:4b34ecfb0d56 (draft) [ ] A
1162
1162
1163
1163
1164 $ hg incoming ../repo-bundleoverlay --bundle ../bundleoverlay.hg
1164 $ hg incoming ../repo-bundleoverlay --bundle ../bundleoverlay.hg
1165 comparing with ../repo-bundleoverlay
1165 comparing with ../repo-bundleoverlay
1166 searching for changes
1166 searching for changes
1167 1:44526ebb0f98 (draft) [ ] B
1167 1:44526ebb0f98 (draft) [ ] B
1168 2:c186d7714947 (draft) [tip ] C
1168 2:c186d7714947 (draft) [tip ] C
1169 $ hg log -G -R ../bundleoverlay.hg
1169 $ hg log -G -R ../bundleoverlay.hg
1170 o 3:c186d7714947 (draft) [tip ] C
1170 o 3:c186d7714947 (draft) [tip ] C
1171 |
1171 |
1172 | @ 2:b7d587542d40 (draft) [ ] B+
1172 | @ 2:b7d587542d40 (draft) [ ] B+
1173 |/
1173 |/
1174 o 0:4b34ecfb0d56 (draft) [ ] A
1174 o 0:4b34ecfb0d56 (draft) [ ] A
1175
1175
1176
1176
1177 #if serve
1177 #if serve
1178
1178
1179 Test issue 4506
1179 Test issue 4506
1180
1180
1181 $ cd ..
1181 $ cd ..
1182 $ hg init repo-issue4506
1182 $ hg init repo-issue4506
1183 $ cd repo-issue4506
1183 $ cd repo-issue4506
1184 $ echo "0" > foo
1184 $ echo "0" > foo
1185 $ hg add foo
1185 $ hg add foo
1186 $ hg ci -m "content-0"
1186 $ hg ci -m "content-0"
1187
1187
1188 $ hg up null
1188 $ hg up null
1189 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1189 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1190 $ echo "1" > bar
1190 $ echo "1" > bar
1191 $ hg add bar
1191 $ hg add bar
1192 $ hg ci -m "content-1"
1192 $ hg ci -m "content-1"
1193 created new head
1193 created new head
1194 $ hg up 0
1194 $ hg up 0
1195 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1195 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1196 $ hg graft 1
1196 $ hg graft 1
1197 grafting 1:1c9eddb02162 "content-1" (tip)
1197 grafting 1:1c9eddb02162 "content-1" (tip)
1198
1198
1199 $ hg debugobsolete `hg log -r1 -T'{node}'` `hg log -r2 -T'{node}'`
1199 $ hg debugobsolete `hg log -r1 -T'{node}'` `hg log -r2 -T'{node}'`
1200 obsoleted 1 changesets
1200 obsoleted 1 changesets
1201
1201
1202 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1202 $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
1203 $ cat hg.pid >> $DAEMON_PIDS
1203 $ cat hg.pid >> $DAEMON_PIDS
1204
1204
1205 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/1'
1205 $ get-with-headers.py --headeronly localhost:$HGPORT 'rev/1'
1206 404 Not Found
1206 404 Not Found
1207 [1]
1207 [1]
1208 $ get-with-headers.py --headeronly localhost:$HGPORT 'file/tip/bar'
1208 $ get-with-headers.py --headeronly localhost:$HGPORT 'file/tip/bar'
1209 200 Script output follows
1209 200 Script output follows
1210 $ get-with-headers.py --headeronly localhost:$HGPORT 'annotate/tip/bar'
1210 $ get-with-headers.py --headeronly localhost:$HGPORT 'annotate/tip/bar'
1211 200 Script output follows
1211 200 Script output follows
1212
1212
1213 $ killdaemons.py
1213 $ killdaemons.py
1214
1214
1215 #endif
1215 #endif
1216
1216
1217 Test heads computation on pending index changes with obsolescence markers
1217 Test heads computation on pending index changes with obsolescence markers
1218 $ cd ..
1218 $ cd ..
1219 $ cat >$TESTTMP/test_extension.py << EOF
1219 $ cat >$TESTTMP/test_extension.py << EOF
1220 > from __future__ import absolute_import
1220 > from __future__ import absolute_import
1221 > from mercurial.i18n import _
1221 > from mercurial.i18n import _
1222 > from mercurial import cmdutil, registrar
1222 > from mercurial import cmdutil, registrar
1223 >
1223 >
1224 > cmdtable = {}
1224 > cmdtable = {}
1225 > command = registrar.command(cmdtable)
1225 > command = registrar.command(cmdtable)
1226 > @command(b"amendtransient",[], _('hg amendtransient [rev]'))
1226 > @command(b"amendtransient",[], _('hg amendtransient [rev]'))
1227 > def amend(ui, repo, *pats, **opts):
1227 > def amend(ui, repo, *pats, **opts):
1228 > opts['message'] = 'Test'
1228 > opts['message'] = 'Test'
1229 > opts['logfile'] = None
1229 > opts['logfile'] = None
1230 > cmdutil.amend(ui, repo, repo['.'], {}, pats, opts)
1230 > cmdutil.amend(ui, repo, repo['.'], {}, pats, opts)
1231 > ui.write('%s\n' % repo.changelog.headrevs())
1231 > ui.write('%s\n' % repo.changelog.headrevs())
1232 > EOF
1232 > EOF
1233 $ cat >> $HGRCPATH << EOF
1233 $ cat >> $HGRCPATH << EOF
1234 > [extensions]
1234 > [extensions]
1235 > testextension=$TESTTMP/test_extension.py
1235 > testextension=$TESTTMP/test_extension.py
1236 > EOF
1236 > EOF
1237 $ hg init repo-issue-nativerevs-pending-changes
1237 $ hg init repo-issue-nativerevs-pending-changes
1238 $ cd repo-issue-nativerevs-pending-changes
1238 $ cd repo-issue-nativerevs-pending-changes
1239 $ mkcommit a
1239 $ mkcommit a
1240 $ mkcommit b
1240 $ mkcommit b
1241 $ hg up ".^"
1241 $ hg up ".^"
1242 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1242 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1243 $ echo aa > a
1243 $ echo aa > a
1244 $ hg amendtransient
1244 $ hg amendtransient
1245 [1, 2]
1245 [1, 2]
1246
1246
1247 Test cache consistency for the visible filter
1247 Test cache consistency for the visible filter
1248 1) We want to make sure that the cached filtered revs are invalidated when
1248 1) We want to make sure that the cached filtered revs are invalidated when
1249 bookmarks change
1249 bookmarks change
1250 $ cd ..
1250 $ cd ..
1251 $ cat >$TESTTMP/test_extension.py << EOF
1251 $ cat >$TESTTMP/test_extension.py << EOF
1252 > from __future__ import absolute_import, print_function
1252 > from __future__ import absolute_import, print_function
1253 > import weakref
1253 > import weakref
1254 > from mercurial import (
1254 > from mercurial import (
1255 > bookmarks,
1255 > bookmarks,
1256 > cmdutil,
1256 > cmdutil,
1257 > extensions,
1257 > extensions,
1258 > repoview,
1258 > repoview,
1259 > )
1259 > )
1260 > def _bookmarkchanged(orig, bkmstoreinst, *args, **kwargs):
1260 > def _bookmarkchanged(orig, bkmstoreinst, *args, **kwargs):
1261 > reporef = weakref.ref(bkmstoreinst._repo)
1261 > reporef = weakref.ref(bkmstoreinst._repo)
1262 > def trhook(tr):
1262 > def trhook(tr):
1263 > repo = reporef()
1263 > repo = reporef()
1264 > hidden1 = repoview.computehidden(repo)
1264 > hidden1 = repoview.computehidden(repo)
1265 > hidden = repoview.filterrevs(repo, 'visible')
1265 > hidden = repoview.filterrevs(repo, 'visible')
1266 > if sorted(hidden1) != sorted(hidden):
1266 > if sorted(hidden1) != sorted(hidden):
1267 > print("cache inconsistency")
1267 > print("cache inconsistency")
1268 > bkmstoreinst._repo.currenttransaction().addpostclose('test_extension', trhook)
1268 > bkmstoreinst._repo.currenttransaction().addpostclose('test_extension', trhook)
1269 > orig(bkmstoreinst, *args, **kwargs)
1269 > orig(bkmstoreinst, *args, **kwargs)
1270 > def extsetup(ui):
1270 > def extsetup(ui):
1271 > extensions.wrapfunction(bookmarks.bmstore, '_recordchange',
1271 > extensions.wrapfunction(bookmarks.bmstore, '_recordchange',
1272 > _bookmarkchanged)
1272 > _bookmarkchanged)
1273 > EOF
1273 > EOF
1274
1274
1275 $ hg init repo-cache-inconsistency
1275 $ hg init repo-cache-inconsistency
1276 $ cd repo-issue-nativerevs-pending-changes
1276 $ cd repo-issue-nativerevs-pending-changes
1277 $ mkcommit a
1277 $ mkcommit a
1278 a already tracked!
1278 a already tracked!
1279 $ mkcommit b
1279 $ mkcommit b
1280 $ hg id
1280 $ hg id
1281 13bedc178fce tip
1281 13bedc178fce tip
1282 $ echo "hello" > b
1282 $ echo "hello" > b
1283 $ hg commit --amend -m "message"
1283 $ hg commit --amend -m "message"
1284 $ hg book bookb -r 13bedc178fce --hidden
1284 $ hg book bookb -r 13bedc178fce --hidden
1285 $ hg log -r 13bedc178fce
1285 $ hg log -r 13bedc178fce
1286 4:13bedc178fce (draft *obsolete*) [ bookb] add b [rewritten using amend as 5:a9b1f8652753]
1286 4:13bedc178fce (draft *obsolete*) [ bookb] add b [rewritten using amend as 5:a9b1f8652753]
1287 $ hg book -d bookb
1287 $ hg book -d bookb
1288 $ hg log -r 13bedc178fce
1288 $ hg log -r 13bedc178fce
1289 abort: hidden revision '13bedc178fce'!
1289 abort: hidden revision '13bedc178fce'!
1290 (use --hidden to access hidden revisions)
1290 (use --hidden to access hidden revisions)
1291 [255]
1291 [255]
1292
1292
1293 Empty out the test extension, as it isn't compatible with later parts
1293 Empty out the test extension, as it isn't compatible with later parts
1294 of the test.
1294 of the test.
1295 $ echo > $TESTTMP/test_extension.py
1295 $ echo > $TESTTMP/test_extension.py
1296
1296
1297 Test ability to pull changeset with locally applying obsolescence markers
1297 Test ability to pull changeset with locally applying obsolescence markers
1298 (issue4945)
1298 (issue4945)
1299
1299
1300 $ cd ..
1300 $ cd ..
1301 $ hg init issue4845
1301 $ hg init issue4845
1302 $ cd issue4845
1302 $ cd issue4845
1303
1303
1304 $ echo foo > f0
1304 $ echo foo > f0
1305 $ hg add f0
1305 $ hg add f0
1306 $ hg ci -m '0'
1306 $ hg ci -m '0'
1307 $ echo foo > f1
1307 $ echo foo > f1
1308 $ hg add f1
1308 $ hg add f1
1309 $ hg ci -m '1'
1309 $ hg ci -m '1'
1310 $ echo foo > f2
1310 $ echo foo > f2
1311 $ hg add f2
1311 $ hg add f2
1312 $ hg ci -m '2'
1312 $ hg ci -m '2'
1313
1313
1314 $ echo bar > f2
1314 $ echo bar > f2
1315 $ hg commit --amend --config experimental.evolution.createmarkers=True
1315 $ hg commit --amend --config experimental.evolution.createmarkers=True
1316 $ hg log -G
1316 $ hg log -G
1317 @ 3:b0551702f918 (draft) [tip ] 2
1317 @ 3:b0551702f918 (draft) [tip ] 2
1318 |
1318 |
1319 o 1:e016b03fd86f (draft) [ ] 1
1319 o 1:e016b03fd86f (draft) [ ] 1
1320 |
1320 |
1321 o 0:a78f55e5508c (draft) [ ] 0
1321 o 0:a78f55e5508c (draft) [ ] 0
1322
1322
1323 $ hg log -G --hidden
1323 $ hg log -G --hidden
1324 @ 3:b0551702f918 (draft) [tip ] 2
1324 @ 3:b0551702f918 (draft) [tip ] 2
1325 |
1325 |
1326 | x 2:e008cf283490 (draft *obsolete*) [ ] 2 [rewritten using amend as 3:b0551702f918]
1326 | x 2:e008cf283490 (draft *obsolete*) [ ] 2 [rewritten using amend as 3:b0551702f918]
1327 |/
1327 |/
1328 o 1:e016b03fd86f (draft) [ ] 1
1328 o 1:e016b03fd86f (draft) [ ] 1
1329 |
1329 |
1330 o 0:a78f55e5508c (draft) [ ] 0
1330 o 0:a78f55e5508c (draft) [ ] 0
1331
1331
1332
1332
1333 $ hg strip --hidden -r 2 --config extensions.strip= --config devel.strip-obsmarkers=no
1333 $ hg strip --hidden -r 2 --config extensions.strip= --config devel.strip-obsmarkers=no
1334 saved backup bundle to $TESTTMP/tmpe/issue4845/.hg/strip-backup/e008cf283490-ede36964-backup.hg (glob)
1334 saved backup bundle to $TESTTMP/tmpe/issue4845/.hg/strip-backup/e008cf283490-ede36964-backup.hg (glob)
1335 $ hg debugobsolete
1335 $ hg debugobsolete
1336 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1336 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1337 $ hg log -G
1337 $ hg log -G
1338 @ 2:b0551702f918 (draft) [tip ] 2
1338 @ 2:b0551702f918 (draft) [tip ] 2
1339 |
1339 |
1340 o 1:e016b03fd86f (draft) [ ] 1
1340 o 1:e016b03fd86f (draft) [ ] 1
1341 |
1341 |
1342 o 0:a78f55e5508c (draft) [ ] 0
1342 o 0:a78f55e5508c (draft) [ ] 0
1343
1343
1344 $ hg log -G --hidden
1344 $ hg log -G --hidden
1345 @ 2:b0551702f918 (draft) [tip ] 2
1345 @ 2:b0551702f918 (draft) [tip ] 2
1346 |
1346 |
1347 o 1:e016b03fd86f (draft) [ ] 1
1347 o 1:e016b03fd86f (draft) [ ] 1
1348 |
1348 |
1349 o 0:a78f55e5508c (draft) [ ] 0
1349 o 0:a78f55e5508c (draft) [ ] 0
1350
1350
1351 $ hg debugbundle .hg/strip-backup/e008cf283490-*-backup.hg
1351 $ hg debugbundle .hg/strip-backup/e008cf283490-*-backup.hg
1352 Stream params: {Compression: BZ}
1352 Stream params: {Compression: BZ}
1353 changegroup -- {nbchanges: 1, version: 02}
1353 changegroup -- {nbchanges: 1, version: 02}
1354 e008cf2834908e5d6b0f792a9d4b0e2272260fb8
1354 e008cf2834908e5d6b0f792a9d4b0e2272260fb8
1355 phase-heads -- {}
1355 phase-heads -- {}
1356 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 draft
1356 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 draft
1357
1357
1358 $ hg pull .hg/strip-backup/e008cf283490-*-backup.hg
1358 $ hg pull .hg/strip-backup/e008cf283490-*-backup.hg
1359 pulling from .hg/strip-backup/e008cf283490-ede36964-backup.hg
1359 pulling from .hg/strip-backup/e008cf283490-ede36964-backup.hg
1360 searching for changes
1360 searching for changes
1361 no changes found
1361 no changes found
1362 $ hg debugobsolete
1362 $ hg debugobsolete
1363 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1363 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1364 $ hg log -G
1364 $ hg log -G
1365 @ 2:b0551702f918 (draft) [tip ] 2
1365 @ 2:b0551702f918 (draft) [tip ] 2
1366 |
1366 |
1367 o 1:e016b03fd86f (draft) [ ] 1
1367 o 1:e016b03fd86f (draft) [ ] 1
1368 |
1368 |
1369 o 0:a78f55e5508c (draft) [ ] 0
1369 o 0:a78f55e5508c (draft) [ ] 0
1370
1370
1371 $ hg log -G --hidden
1371 $ hg log -G --hidden
1372 @ 2:b0551702f918 (draft) [tip ] 2
1372 @ 2:b0551702f918 (draft) [tip ] 2
1373 |
1373 |
1374 o 1:e016b03fd86f (draft) [ ] 1
1374 o 1:e016b03fd86f (draft) [ ] 1
1375 |
1375 |
1376 o 0:a78f55e5508c (draft) [ ] 0
1376 o 0:a78f55e5508c (draft) [ ] 0
1377
1377
1378
1378
1379 Testing that strip remove markers:
1379 Testing that strip remove markers:
1380
1380
1381 $ hg strip -r 1 --config extensions.strip=
1381 $ hg strip -r 1 --config extensions.strip=
1382 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1382 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1383 saved backup bundle to $TESTTMP/tmpe/issue4845/.hg/strip-backup/e016b03fd86f-65ede734-backup.hg (glob)
1383 saved backup bundle to $TESTTMP/tmpe/issue4845/.hg/strip-backup/e016b03fd86f-65ede734-backup.hg (glob)
1384 $ hg debugobsolete
1384 $ hg debugobsolete
1385 $ hg log -G
1385 $ hg log -G
1386 @ 0:a78f55e5508c (draft) [tip ] 0
1386 @ 0:a78f55e5508c (draft) [tip ] 0
1387
1387
1388 $ hg log -G --hidden
1388 $ hg log -G --hidden
1389 @ 0:a78f55e5508c (draft) [tip ] 0
1389 @ 0:a78f55e5508c (draft) [tip ] 0
1390
1390
1391 $ hg debugbundle .hg/strip-backup/e016b03fd86f-*-backup.hg
1391 $ hg debugbundle .hg/strip-backup/e016b03fd86f-*-backup.hg
1392 Stream params: {Compression: BZ}
1392 Stream params: {Compression: BZ}
1393 changegroup -- {nbchanges: 2, version: 02}
1393 changegroup -- {nbchanges: 2, version: 02}
1394 e016b03fd86fcccc54817d120b90b751aaf367d6
1394 e016b03fd86fcccc54817d120b90b751aaf367d6
1395 b0551702f918510f01ae838ab03a463054c67b46
1395 b0551702f918510f01ae838ab03a463054c67b46
1396 obsmarkers -- {}
1396 obsmarkers -- {}
1397 version: 1 (86 bytes)
1397 version: 1 (86 bytes)
1398 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1398 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1399 phase-heads -- {}
1399 phase-heads -- {}
1400 b0551702f918510f01ae838ab03a463054c67b46 draft
1400 b0551702f918510f01ae838ab03a463054c67b46 draft
1401
1401
1402 $ hg unbundle .hg/strip-backup/e016b03fd86f-*-backup.hg
1402 $ hg unbundle .hg/strip-backup/e016b03fd86f-*-backup.hg
1403 adding changesets
1403 adding changesets
1404 adding manifests
1404 adding manifests
1405 adding file changes
1405 adding file changes
1406 added 2 changesets with 2 changes to 2 files
1406 added 2 changesets with 2 changes to 2 files
1407 1 new obsolescence markers
1407 1 new obsolescence markers
1408 new changesets e016b03fd86f:b0551702f918
1408 new changesets e016b03fd86f:b0551702f918
1409 (run 'hg update' to get a working copy)
1409 (run 'hg update' to get a working copy)
1410 $ hg debugobsolete | sort
1410 $ hg debugobsolete | sort
1411 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1411 e008cf2834908e5d6b0f792a9d4b0e2272260fb8 b0551702f918510f01ae838ab03a463054c67b46 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1412 $ hg log -G
1412 $ hg log -G
1413 o 2:b0551702f918 (draft) [tip ] 2
1413 o 2:b0551702f918 (draft) [tip ] 2
1414 |
1414 |
1415 o 1:e016b03fd86f (draft) [ ] 1
1415 o 1:e016b03fd86f (draft) [ ] 1
1416 |
1416 |
1417 @ 0:a78f55e5508c (draft) [ ] 0
1417 @ 0:a78f55e5508c (draft) [ ] 0
1418
1418
1419 $ hg log -G --hidden
1419 $ hg log -G --hidden
1420 o 2:b0551702f918 (draft) [tip ] 2
1420 o 2:b0551702f918 (draft) [tip ] 2
1421 |
1421 |
1422 o 1:e016b03fd86f (draft) [ ] 1
1422 o 1:e016b03fd86f (draft) [ ] 1
1423 |
1423 |
1424 @ 0:a78f55e5508c (draft) [ ] 0
1424 @ 0:a78f55e5508c (draft) [ ] 0
1425
1425
1426 Test that 'hg debugobsolete --index --rev' can show indices of obsmarkers when
1426 Test that 'hg debugobsolete --index --rev' can show indices of obsmarkers when
1427 only a subset of those are displayed (because of --rev option)
1427 only a subset of those are displayed (because of --rev option)
1428 $ hg init doindexrev
1428 $ hg init doindexrev
1429 $ cd doindexrev
1429 $ cd doindexrev
1430 $ echo a > a
1430 $ echo a > a
1431 $ hg ci -Am a
1431 $ hg ci -Am a
1432 adding a
1432 adding a
1433 $ hg ci --amend -m aa
1433 $ hg ci --amend -m aa
1434 $ echo b > b
1434 $ echo b > b
1435 $ hg ci -Am b
1435 $ hg ci -Am b
1436 adding b
1436 adding b
1437 $ hg ci --amend -m bb
1437 $ hg ci --amend -m bb
1438 $ echo c > c
1438 $ echo c > c
1439 $ hg ci -Am c
1439 $ hg ci -Am c
1440 adding c
1440 adding c
1441 $ hg ci --amend -m cc
1441 $ hg ci --amend -m cc
1442 $ echo d > d
1442 $ echo d > d
1443 $ hg ci -Am d
1443 $ hg ci -Am d
1444 adding d
1444 adding d
1445 $ hg ci --amend -m dd --config experimental.evolution.track-operation=1
1445 $ hg ci --amend -m dd --config experimental.evolution.track-operation=1
1446 $ hg debugobsolete --index --rev "3+7"
1446 $ hg debugobsolete --index --rev "3+7"
1447 1 6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1 d27fb9b066076fd921277a4b9e8b9cb48c95bc6a 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1447 1 6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1 d27fb9b066076fd921277a4b9e8b9cb48c95bc6a 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1448 3 4715cf767440ed891755448016c2b8cf70760c30 7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d 0 \(.*\) {'operation': 'amend', 'user': 'test'} (re)
1448 3 4715cf767440ed891755448016c2b8cf70760c30 7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d 0 \(.*\) {'operation': 'amend', 'user': 'test'} (re)
1449 $ hg debugobsolete --index --rev "3+7" -Tjson
1449 $ hg debugobsolete --index --rev "3+7" -Tjson
1450 [
1450 [
1451 {
1451 {
1452 "date": [0.0, 0],
1452 "date": [0.0, 0],
1453 "flag": 0,
1453 "flag": 0,
1454 "index": 1,
1454 "index": 1,
1455 "metadata": {"operation": "amend", "user": "test"},
1455 "metadata": {"operation": "amend", "user": "test"},
1456 "prednode": "6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1",
1456 "prednode": "6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1",
1457 "succnodes": ["d27fb9b066076fd921277a4b9e8b9cb48c95bc6a"]
1457 "succnodes": ["d27fb9b066076fd921277a4b9e8b9cb48c95bc6a"]
1458 },
1458 },
1459 {
1459 {
1460 "date": [0.0, 0],
1460 "date": [0.0, 0],
1461 "flag": 0,
1461 "flag": 0,
1462 "index": 3,
1462 "index": 3,
1463 "metadata": {"operation": "amend", "user": "test"},
1463 "metadata": {"operation": "amend", "user": "test"},
1464 "prednode": "4715cf767440ed891755448016c2b8cf70760c30",
1464 "prednode": "4715cf767440ed891755448016c2b8cf70760c30",
1465 "succnodes": ["7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d"]
1465 "succnodes": ["7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d"]
1466 }
1466 }
1467 ]
1467 ]
1468
1468
1469 Test the --delete option of debugobsolete command
1469 Test the --delete option of debugobsolete command
1470 $ hg debugobsolete --index
1470 $ hg debugobsolete --index
1471 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b f9bd49731b0b175e42992a3c8fa6c678b2bc11f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1471 0 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b f9bd49731b0b175e42992a3c8fa6c678b2bc11f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1472 1 6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1 d27fb9b066076fd921277a4b9e8b9cb48c95bc6a 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1472 1 6fdef60fcbabbd3d50e9b9cbc2a240724b91a5e1 d27fb9b066076fd921277a4b9e8b9cb48c95bc6a 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1473 2 1ab51af8f9b41ef8c7f6f3312d4706d870b1fb74 29346082e4a9e27042b62d2da0e2de211c027621 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1473 2 1ab51af8f9b41ef8c7f6f3312d4706d870b1fb74 29346082e4a9e27042b62d2da0e2de211c027621 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1474 3 4715cf767440ed891755448016c2b8cf70760c30 7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1474 3 4715cf767440ed891755448016c2b8cf70760c30 7ae79c5d60f049c7b0dd02f5f25b9d60aaf7b36d 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1475 $ hg debugobsolete --delete 1 --delete 3
1475 $ hg debugobsolete --delete 1 --delete 3
1476 deleted 2 obsolescence markers
1476 deleted 2 obsolescence markers
1477 $ hg debugobsolete
1477 $ hg debugobsolete
1478 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b f9bd49731b0b175e42992a3c8fa6c678b2bc11f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1478 cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b f9bd49731b0b175e42992a3c8fa6c678b2bc11f1 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1479 1ab51af8f9b41ef8c7f6f3312d4706d870b1fb74 29346082e4a9e27042b62d2da0e2de211c027621 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1479 1ab51af8f9b41ef8c7f6f3312d4706d870b1fb74 29346082e4a9e27042b62d2da0e2de211c027621 0 (Thu Jan 01 00:00:00 1970 +0000) {'operation': 'amend', 'user': 'test'}
1480
1480
1481 Test adding changeset after obsmarkers affecting it
1481 Test adding changeset after obsmarkers affecting it
1482 (eg: during pull, or unbundle)
1482 (eg: during pull, or unbundle)
1483
1483
1484 $ mkcommit e
1484 $ mkcommit e
1485 $ hg bundle -r . --base .~1 ../bundle-2.hg
1485 $ hg bundle -r . --base .~1 ../bundle-2.hg
1486 1 changesets found
1486 1 changesets found
1487 $ getid .
1487 $ getid .
1488 $ hg --config extensions.strip= strip -r .
1488 $ hg --config extensions.strip= strip -r .
1489 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1489 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1490 saved backup bundle to $TESTTMP/tmpe/issue4845/doindexrev/.hg/strip-backup/9bc153528424-ee80edd4-backup.hg (glob)
1490 saved backup bundle to $TESTTMP/tmpe/issue4845/doindexrev/.hg/strip-backup/9bc153528424-ee80edd4-backup.hg (glob)
1491 $ hg debugobsolete 9bc153528424ea266d13e57f9ff0d799dfe61e4b
1491 $ hg debugobsolete 9bc153528424ea266d13e57f9ff0d799dfe61e4b
1492 $ hg unbundle ../bundle-2.hg
1492 $ hg unbundle ../bundle-2.hg
1493 adding changesets
1493 adding changesets
1494 adding manifests
1494 adding manifests
1495 adding file changes
1495 adding file changes
1496 added 1 changesets with 1 changes to 1 files
1496 added 1 changesets with 1 changes to 1 files
1497 (run 'hg update' to get a working copy)
1497 (run 'hg update' to get a working copy)
1498 $ hg log -G
1498 $ hg log -G
1499 @ 7:7ae79c5d60f0 (draft) [tip ] dd
1499 @ 7:7ae79c5d60f0 (draft) [tip ] dd
1500 |
1500 |
1501 | o 6:4715cf767440 (draft) [ ] d
1501 | o 6:4715cf767440 (draft) [ ] d
1502 |/
1502 |/
1503 o 5:29346082e4a9 (draft) [ ] cc
1503 o 5:29346082e4a9 (draft) [ ] cc
1504 |
1504 |
1505 o 3:d27fb9b06607 (draft) [ ] bb
1505 o 3:d27fb9b06607 (draft) [ ] bb
1506 |
1506 |
1507 | o 2:6fdef60fcbab (draft) [ ] b
1507 | o 2:6fdef60fcbab (draft) [ ] b
1508 |/
1508 |/
1509 o 1:f9bd49731b0b (draft) [ ] aa
1509 o 1:f9bd49731b0b (draft) [ ] aa
1510
1510
1511
1511
1512 $ cd ..
1512 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now