##// END OF EJS Templates
merge with stable
Matt Mackall -
r15623:fc8c7a5c merge default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,101 +1,119 b''
1 1 ====
2 2 hg
3 3 ====
4 4
5 5 ---------------------------------------
6 6 Mercurial source code management system
7 7 ---------------------------------------
8 8
9 9 :Author: Matt Mackall <mpm@selenic.com>
10 10 :Organization: Mercurial
11 11 :Manual section: 1
12 12 :Manual group: Mercurial Manual
13 13
14 14 .. contents::
15 15 :backlinks: top
16 16 :class: htmlonly
17 17 :depth: 1
18 18
19 19
20 20 Synopsis
21 21 --------
22 22 **hg** *command* [*option*]... [*argument*]...
23 23
24 24 Description
25 25 -----------
26 26 The **hg** command provides a command line interface to the Mercurial
27 27 system.
28 28
29 29 Command Elements
30 30 ----------------
31 31
32 32 files...
33 33 indicates one or more filename or relative path filenames; see
34 34 `File Name Patterns`_ for information on pattern matching
35 35
36 36 path
37 37 indicates a path on the local machine
38 38
39 39 revision
40 40 indicates a changeset which can be specified as a changeset
41 41 revision number, a tag, or a unique substring of the changeset
42 42 hash value
43 43
44 44 repository path
45 45 either the pathname of a local repository or the URI of a remote
46 46 repository.
47 47
48 48 .. include:: hg.1.gendoc.txt
49 49
50 50 Files
51 51 -----
52 52
53 ``.hgignore``
54 This file contains regular expressions (one per line) that
55 describe file names that should be ignored by **hg**. For details,
56 see |hgignore(5)|_.
57
58 ``.hgtags``
59 This file contains changeset hash values and text tag names (one
60 of each separated by spaces) that correspond to tagged versions of
61 the repository contents.
62
63 53 ``/etc/mercurial/hgrc``, ``$HOME/.hgrc``, ``.hg/hgrc``
64 54 This file contains defaults and configuration. Values in
65 55 ``.hg/hgrc`` override those in ``$HOME/.hgrc``, and these override
66 56 settings made in the global ``/etc/mercurial/hgrc`` configuration.
67 57 See |hgrc(5)|_ for details of the contents and format of these
68 58 files.
69 59
60 ``.hgignore``
61 This file contains regular expressions (one per line) that
62 describe file names that should be ignored by **hg**. For details,
63 see |hgignore(5)|_.
64
65 ``.hgsub``
66 This file defines the locations of all subrepositories, and
67 tells where the subrepository checkouts came from. For details, see
68 :hg:`help subrepos`.
69
70 ``.hgsubstate``
71 This file is where Mercurial stores all nested repository states. *NB: This
72 file should not be edited manually.*
73
74 ``.hgtags``
75 This file contains changeset hash values and text tag names (one
76 of each separated by spaces) that correspond to tagged versions of
77 the repository contents. The file content is encoded using UTF-8.
78
79 ``.hg/last-message.txt``
80 This file is used by :hg:`commit` to store a backup of the commit message
81 in case the commit fails.
82
83 ``.hg/localtags``
84 This file can be used to define local tags which are not shared among
85 repositories. The file format is the same as for ``.hgtags``, but it is
86 encoded using the local system encoding.
87
70 88 Some commands (e.g. revert) produce backup files ending in ``.orig``,
71 89 if the ``.orig`` file already exists and is not tracked by Mercurial,
72 90 it will be overwritten.
73 91
74 92 Bugs
75 93 ----
76 94 Probably lots, please post them to the mailing list (see Resources_
77 95 below) when you find them.
78 96
79 97 See Also
80 98 --------
81 99 |hgignore(5)|_, |hgrc(5)|_
82 100
83 101 Author
84 102 ------
85 103 Written by Matt Mackall <mpm@selenic.com>
86 104
87 105 Resources
88 106 ---------
89 107 Main Web Site: http://mercurial.selenic.com/
90 108
91 109 Source code repository: http://selenic.com/hg
92 110
93 111 Mailing list: http://selenic.com/mailman/listinfo/mercurial
94 112
95 113 Copying
96 114 -------
97 115 Copyright (C) 2005-2010 Matt Mackall.
98 116 Free use of this software is granted under the terms of the GNU General
99 117 Public License version 2 or any later version.
100 118
101 119 .. include:: common.txt
@@ -1,5701 +1,5703 b''
1 1 # commands.py - command processing for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from node import hex, bin, nullid, nullrev, short
9 9 from lock import release
10 10 from i18n import _, gettext
11 11 import os, re, difflib, time, tempfile, errno
12 12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 13 import patch, help, url, encoding, templatekw, discovery
14 14 import archival, changegroup, cmdutil, hbisect
15 15 import sshserver, hgweb, hgweb.server, commandserver
16 16 import match as matchmod
17 17 import merge as mergemod
18 18 import minirst, revset, fileset
19 19 import dagparser, context, simplemerge
20 20 import random, setdiscovery, treediscovery, dagutil
21 21
22 22 table = {}
23 23
24 24 command = cmdutil.command(table)
25 25
26 26 # common command options
27 27
28 28 globalopts = [
29 29 ('R', 'repository', '',
30 30 _('repository root directory or name of overlay bundle file'),
31 31 _('REPO')),
32 32 ('', 'cwd', '',
33 33 _('change working directory'), _('DIR')),
34 34 ('y', 'noninteractive', None,
35 35 _('do not prompt, automatically pick the first choice for all prompts')),
36 36 ('q', 'quiet', None, _('suppress output')),
37 37 ('v', 'verbose', None, _('enable additional output')),
38 38 ('', 'config', [],
39 39 _('set/override config option (use \'section.name=value\')'),
40 40 _('CONFIG')),
41 41 ('', 'debug', None, _('enable debugging output')),
42 42 ('', 'debugger', None, _('start debugger')),
43 43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 44 _('ENCODE')),
45 45 ('', 'encodingmode', encoding.encodingmode,
46 46 _('set the charset encoding mode'), _('MODE')),
47 47 ('', 'traceback', None, _('always print a traceback on exception')),
48 48 ('', 'time', None, _('time how long the command takes')),
49 49 ('', 'profile', None, _('print command execution profile')),
50 50 ('', 'version', None, _('output version information and exit')),
51 51 ('h', 'help', None, _('display help and exit')),
52 52 ]
53 53
54 54 dryrunopts = [('n', 'dry-run', None,
55 55 _('do not perform actions, just print output'))]
56 56
57 57 remoteopts = [
58 58 ('e', 'ssh', '',
59 59 _('specify ssh command to use'), _('CMD')),
60 60 ('', 'remotecmd', '',
61 61 _('specify hg command to run on the remote side'), _('CMD')),
62 62 ('', 'insecure', None,
63 63 _('do not verify server certificate (ignoring web.cacerts config)')),
64 64 ]
65 65
66 66 walkopts = [
67 67 ('I', 'include', [],
68 68 _('include names matching the given patterns'), _('PATTERN')),
69 69 ('X', 'exclude', [],
70 70 _('exclude names matching the given patterns'), _('PATTERN')),
71 71 ]
72 72
73 73 commitopts = [
74 74 ('m', 'message', '',
75 75 _('use text as commit message'), _('TEXT')),
76 76 ('l', 'logfile', '',
77 77 _('read commit message from file'), _('FILE')),
78 78 ]
79 79
80 80 commitopts2 = [
81 81 ('d', 'date', '',
82 82 _('record the specified date as commit date'), _('DATE')),
83 83 ('u', 'user', '',
84 84 _('record the specified user as committer'), _('USER')),
85 85 ]
86 86
87 87 templateopts = [
88 88 ('', 'style', '',
89 89 _('display using template map file'), _('STYLE')),
90 90 ('', 'template', '',
91 91 _('display with template'), _('TEMPLATE')),
92 92 ]
93 93
94 94 logopts = [
95 95 ('p', 'patch', None, _('show patch')),
96 96 ('g', 'git', None, _('use git extended diff format')),
97 97 ('l', 'limit', '',
98 98 _('limit number of changes displayed'), _('NUM')),
99 99 ('M', 'no-merges', None, _('do not show merges')),
100 100 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 101 ] + templateopts
102 102
103 103 diffopts = [
104 104 ('a', 'text', None, _('treat all files as text')),
105 105 ('g', 'git', None, _('use git extended diff format')),
106 106 ('', 'nodates', None, _('omit dates from diff headers'))
107 107 ]
108 108
109 109 diffwsopts = [
110 110 ('w', 'ignore-all-space', None,
111 111 _('ignore white space when comparing lines')),
112 112 ('b', 'ignore-space-change', None,
113 113 _('ignore changes in the amount of white space')),
114 114 ('B', 'ignore-blank-lines', None,
115 115 _('ignore changes whose lines are all blank')),
116 116 ]
117 117
118 118 diffopts2 = [
119 119 ('p', 'show-function', None, _('show which function each change is in')),
120 120 ('', 'reverse', None, _('produce a diff that undoes the changes')),
121 121 ] + diffwsopts + [
122 122 ('U', 'unified', '',
123 123 _('number of lines of context to show'), _('NUM')),
124 124 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 125 ]
126 126
127 127 mergetoolopts = [
128 128 ('t', 'tool', '', _('specify merge tool')),
129 129 ]
130 130
131 131 similarityopts = [
132 132 ('s', 'similarity', '',
133 133 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
134 134 ]
135 135
136 136 subrepoopts = [
137 137 ('S', 'subrepos', None,
138 138 _('recurse into subrepositories'))
139 139 ]
140 140
141 141 # Commands start here, listed alphabetically
142 142
143 143 @command('^add',
144 144 walkopts + subrepoopts + dryrunopts,
145 145 _('[OPTION]... [FILE]...'))
146 146 def add(ui, repo, *pats, **opts):
147 147 """add the specified files on the next commit
148 148
149 149 Schedule files to be version controlled and added to the
150 150 repository.
151 151
152 152 The files will be added to the repository at the next commit. To
153 153 undo an add before that, see :hg:`forget`.
154 154
155 155 If no names are given, add all files to the repository.
156 156
157 157 .. container:: verbose
158 158
159 159 An example showing how new (unknown) files are added
160 160 automatically by :hg:`add`::
161 161
162 162 $ ls
163 163 foo.c
164 164 $ hg status
165 165 ? foo.c
166 166 $ hg add
167 167 adding foo.c
168 168 $ hg status
169 169 A foo.c
170 170
171 171 Returns 0 if all files are successfully added.
172 172 """
173 173
174 174 m = scmutil.match(repo[None], pats, opts)
175 175 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
176 176 opts.get('subrepos'), prefix="")
177 177 return rejected and 1 or 0
178 178
179 179 @command('addremove',
180 180 similarityopts + walkopts + dryrunopts,
181 181 _('[OPTION]... [FILE]...'))
182 182 def addremove(ui, repo, *pats, **opts):
183 183 """add all new files, delete all missing files
184 184
185 185 Add all new files and remove all missing files from the
186 186 repository.
187 187
188 188 New files are ignored if they match any of the patterns in
189 189 ``.hgignore``. As with add, these changes take effect at the next
190 190 commit.
191 191
192 192 Use the -s/--similarity option to detect renamed files. With a
193 193 parameter greater than 0, this compares every removed file with
194 194 every added file and records those similar enough as renames. This
195 195 option takes a percentage between 0 (disabled) and 100 (files must
196 196 be identical) as its parameter. Detecting renamed files this way
197 197 can be expensive. After using this option, :hg:`status -C` can be
198 198 used to check which files were identified as moved or renamed.
199 199
200 200 Returns 0 if all files are successfully added.
201 201 """
202 202 try:
203 203 sim = float(opts.get('similarity') or 100)
204 204 except ValueError:
205 205 raise util.Abort(_('similarity must be a number'))
206 206 if sim < 0 or sim > 100:
207 207 raise util.Abort(_('similarity must be between 0 and 100'))
208 208 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
209 209
210 210 @command('^annotate|blame',
211 211 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
212 212 ('', 'follow', None,
213 213 _('follow copies/renames and list the filename (DEPRECATED)')),
214 214 ('', 'no-follow', None, _("don't follow copies and renames")),
215 215 ('a', 'text', None, _('treat all files as text')),
216 216 ('u', 'user', None, _('list the author (long with -v)')),
217 217 ('f', 'file', None, _('list the filename')),
218 218 ('d', 'date', None, _('list the date (short with -q)')),
219 219 ('n', 'number', None, _('list the revision number (default)')),
220 220 ('c', 'changeset', None, _('list the changeset')),
221 221 ('l', 'line-number', None, _('show line number at the first appearance'))
222 222 ] + diffwsopts + walkopts,
223 223 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
224 224 def annotate(ui, repo, *pats, **opts):
225 225 """show changeset information by line for each file
226 226
227 227 List changes in files, showing the revision id responsible for
228 228 each line
229 229
230 230 This command is useful for discovering when a change was made and
231 231 by whom.
232 232
233 233 Without the -a/--text option, annotate will avoid processing files
234 234 it detects as binary. With -a, annotate will annotate the file
235 235 anyway, although the results will probably be neither useful
236 236 nor desirable.
237 237
238 238 Returns 0 on success.
239 239 """
240 240 if opts.get('follow'):
241 241 # --follow is deprecated and now just an alias for -f/--file
242 242 # to mimic the behavior of Mercurial before version 1.5
243 243 opts['file'] = True
244 244
245 245 datefunc = ui.quiet and util.shortdate or util.datestr
246 246 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
247 247
248 248 if not pats:
249 249 raise util.Abort(_('at least one filename or pattern is required'))
250 250
251 251 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
252 252 ('number', ' ', lambda x: str(x[0].rev())),
253 253 ('changeset', ' ', lambda x: short(x[0].node())),
254 254 ('date', ' ', getdate),
255 255 ('file', ' ', lambda x: x[0].path()),
256 256 ('line_number', ':', lambda x: str(x[1])),
257 257 ]
258 258
259 259 if (not opts.get('user') and not opts.get('changeset')
260 260 and not opts.get('date') and not opts.get('file')):
261 261 opts['number'] = True
262 262
263 263 linenumber = opts.get('line_number') is not None
264 264 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
265 265 raise util.Abort(_('at least one of -n/-c is required for -l'))
266 266
267 267 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
268 268 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
269 269
270 270 def bad(x, y):
271 271 raise util.Abort("%s: %s" % (x, y))
272 272
273 273 ctx = scmutil.revsingle(repo, opts.get('rev'))
274 274 m = scmutil.match(ctx, pats, opts)
275 275 m.bad = bad
276 276 follow = not opts.get('no_follow')
277 277 diffopts = patch.diffopts(ui, opts, section='annotate')
278 278 for abs in ctx.walk(m):
279 279 fctx = ctx[abs]
280 280 if not opts.get('text') and util.binary(fctx.data()):
281 281 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
282 282 continue
283 283
284 284 lines = fctx.annotate(follow=follow, linenumber=linenumber,
285 285 diffopts=diffopts)
286 286 pieces = []
287 287
288 288 for f, sep in funcmap:
289 289 l = [f(n) for n, dummy in lines]
290 290 if l:
291 291 sized = [(x, encoding.colwidth(x)) for x in l]
292 292 ml = max([w for x, w in sized])
293 293 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
294 294 for x, w in sized])
295 295
296 296 if pieces:
297 297 for p, l in zip(zip(*pieces), lines):
298 298 ui.write("%s: %s" % ("".join(p), l[1]))
299 299
300 300 @command('archive',
301 301 [('', 'no-decode', None, _('do not pass files through decoders')),
302 302 ('p', 'prefix', '', _('directory prefix for files in archive'),
303 303 _('PREFIX')),
304 304 ('r', 'rev', '', _('revision to distribute'), _('REV')),
305 305 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
306 306 ] + subrepoopts + walkopts,
307 307 _('[OPTION]... DEST'))
308 308 def archive(ui, repo, dest, **opts):
309 309 '''create an unversioned archive of a repository revision
310 310
311 311 By default, the revision used is the parent of the working
312 312 directory; use -r/--rev to specify a different revision.
313 313
314 314 The archive type is automatically detected based on file
315 315 extension (or override using -t/--type).
316 316
317 317 .. container:: verbose
318 318
319 319 Examples:
320 320
321 321 - create a zip file containing the 1.0 release::
322 322
323 323 hg archive -r 1.0 project-1.0.zip
324 324
325 325 - create a tarball excluding .hg files::
326 326
327 327 hg archive project.tar.gz -X ".hg*"
328 328
329 329 Valid types are:
330 330
331 331 :``files``: a directory full of files (default)
332 332 :``tar``: tar archive, uncompressed
333 333 :``tbz2``: tar archive, compressed using bzip2
334 334 :``tgz``: tar archive, compressed using gzip
335 335 :``uzip``: zip archive, uncompressed
336 336 :``zip``: zip archive, compressed using deflate
337 337
338 338 The exact name of the destination archive or directory is given
339 339 using a format string; see :hg:`help export` for details.
340 340
341 341 Each member added to an archive file has a directory prefix
342 342 prepended. Use -p/--prefix to specify a format string for the
343 343 prefix. The default is the basename of the archive, with suffixes
344 344 removed.
345 345
346 346 Returns 0 on success.
347 347 '''
348 348
349 349 ctx = scmutil.revsingle(repo, opts.get('rev'))
350 350 if not ctx:
351 351 raise util.Abort(_('no working directory: please specify a revision'))
352 352 node = ctx.node()
353 353 dest = cmdutil.makefilename(repo, dest, node)
354 354 if os.path.realpath(dest) == repo.root:
355 355 raise util.Abort(_('repository root cannot be destination'))
356 356
357 357 kind = opts.get('type') or archival.guesskind(dest) or 'files'
358 358 prefix = opts.get('prefix')
359 359
360 360 if dest == '-':
361 361 if kind == 'files':
362 362 raise util.Abort(_('cannot archive plain files to stdout'))
363 363 dest = cmdutil.makefileobj(repo, dest)
364 364 if not prefix:
365 365 prefix = os.path.basename(repo.root) + '-%h'
366 366
367 367 prefix = cmdutil.makefilename(repo, prefix, node)
368 368 matchfn = scmutil.match(ctx, [], opts)
369 369 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
370 370 matchfn, prefix, subrepos=opts.get('subrepos'))
371 371
372 372 @command('backout',
373 373 [('', 'merge', None, _('merge with old dirstate parent after backout')),
374 374 ('', 'parent', '',
375 375 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
376 376 ('r', 'rev', '', _('revision to backout'), _('REV')),
377 377 ] + mergetoolopts + walkopts + commitopts + commitopts2,
378 378 _('[OPTION]... [-r] REV'))
379 379 def backout(ui, repo, node=None, rev=None, **opts):
380 380 '''reverse effect of earlier changeset
381 381
382 382 Prepare a new changeset with the effect of REV undone in the
383 383 current working directory.
384 384
385 385 If REV is the parent of the working directory, then this new changeset
386 386 is committed automatically. Otherwise, hg needs to merge the
387 387 changes and the merged result is left uncommitted.
388 388
389 389 .. note::
390 390 backout cannot be used to fix either an unwanted or
391 391 incorrect merge.
392 392
393 393 .. container:: verbose
394 394
395 395 By default, the pending changeset will have one parent,
396 396 maintaining a linear history. With --merge, the pending
397 397 changeset will instead have two parents: the old parent of the
398 398 working directory and a new child of REV that simply undoes REV.
399 399
400 400 Before version 1.7, the behavior without --merge was equivalent
401 401 to specifying --merge followed by :hg:`update --clean .` to
402 402 cancel the merge and leave the child of REV as a head to be
403 403 merged separately.
404 404
405 405 See :hg:`help dates` for a list of formats valid for -d/--date.
406 406
407 407 Returns 0 on success.
408 408 '''
409 409 if rev and node:
410 410 raise util.Abort(_("please specify just one revision"))
411 411
412 412 if not rev:
413 413 rev = node
414 414
415 415 if not rev:
416 416 raise util.Abort(_("please specify a revision to backout"))
417 417
418 418 date = opts.get('date')
419 419 if date:
420 420 opts['date'] = util.parsedate(date)
421 421
422 422 cmdutil.bailifchanged(repo)
423 423 node = scmutil.revsingle(repo, rev).node()
424 424
425 425 op1, op2 = repo.dirstate.parents()
426 426 a = repo.changelog.ancestor(op1, node)
427 427 if a != node:
428 428 raise util.Abort(_('cannot backout change on a different branch'))
429 429
430 430 p1, p2 = repo.changelog.parents(node)
431 431 if p1 == nullid:
432 432 raise util.Abort(_('cannot backout a change with no parents'))
433 433 if p2 != nullid:
434 434 if not opts.get('parent'):
435 435 raise util.Abort(_('cannot backout a merge changeset'))
436 436 p = repo.lookup(opts['parent'])
437 437 if p not in (p1, p2):
438 438 raise util.Abort(_('%s is not a parent of %s') %
439 439 (short(p), short(node)))
440 440 parent = p
441 441 else:
442 442 if opts.get('parent'):
443 443 raise util.Abort(_('cannot use --parent on non-merge changeset'))
444 444 parent = p1
445 445
446 446 # the backout should appear on the same branch
447 447 branch = repo.dirstate.branch()
448 448 hg.clean(repo, node, show_stats=False)
449 449 repo.dirstate.setbranch(branch)
450 450 revert_opts = opts.copy()
451 451 revert_opts['date'] = None
452 452 revert_opts['all'] = True
453 453 revert_opts['rev'] = hex(parent)
454 454 revert_opts['no_backup'] = None
455 455 revert(ui, repo, **revert_opts)
456 456 if not opts.get('merge') and op1 != node:
457 457 try:
458 458 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
459 459 return hg.update(repo, op1)
460 460 finally:
461 461 ui.setconfig('ui', 'forcemerge', '')
462 462
463 463 commit_opts = opts.copy()
464 464 commit_opts['addremove'] = False
465 465 if not commit_opts['message'] and not commit_opts['logfile']:
466 466 # we don't translate commit messages
467 467 commit_opts['message'] = "Backed out changeset %s" % short(node)
468 468 commit_opts['force_editor'] = True
469 469 commit(ui, repo, **commit_opts)
470 470 def nice(node):
471 471 return '%d:%s' % (repo.changelog.rev(node), short(node))
472 472 ui.status(_('changeset %s backs out changeset %s\n') %
473 473 (nice(repo.changelog.tip()), nice(node)))
474 474 if opts.get('merge') and op1 != node:
475 475 hg.clean(repo, op1, show_stats=False)
476 476 ui.status(_('merging with changeset %s\n')
477 477 % nice(repo.changelog.tip()))
478 478 try:
479 479 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
480 480 return hg.merge(repo, hex(repo.changelog.tip()))
481 481 finally:
482 482 ui.setconfig('ui', 'forcemerge', '')
483 483 return 0
484 484
485 485 @command('bisect',
486 486 [('r', 'reset', False, _('reset bisect state')),
487 487 ('g', 'good', False, _('mark changeset good')),
488 488 ('b', 'bad', False, _('mark changeset bad')),
489 489 ('s', 'skip', False, _('skip testing changeset')),
490 490 ('e', 'extend', False, _('extend the bisect range')),
491 491 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
492 492 ('U', 'noupdate', False, _('do not update to target'))],
493 493 _("[-gbsr] [-U] [-c CMD] [REV]"))
494 494 def bisect(ui, repo, rev=None, extra=None, command=None,
495 495 reset=None, good=None, bad=None, skip=None, extend=None,
496 496 noupdate=None):
497 497 """subdivision search of changesets
498 498
499 499 This command helps to find changesets which introduce problems. To
500 500 use, mark the earliest changeset you know exhibits the problem as
501 501 bad, then mark the latest changeset which is free from the problem
502 502 as good. Bisect will update your working directory to a revision
503 503 for testing (unless the -U/--noupdate option is specified). Once
504 504 you have performed tests, mark the working directory as good or
505 505 bad, and bisect will either update to another candidate changeset
506 506 or announce that it has found the bad revision.
507 507
508 508 As a shortcut, you can also use the revision argument to mark a
509 509 revision as good or bad without checking it out first.
510 510
511 511 If you supply a command, it will be used for automatic bisection.
512 512 Its exit status will be used to mark revisions as good or bad:
513 513 status 0 means good, 125 means to skip the revision, 127
514 514 (command not found) will abort the bisection, and any other
515 515 non-zero exit status means the revision is bad.
516 516
517 517 .. container:: verbose
518 518
519 519 Some examples:
520 520
521 521 - start a bisection with known bad revision 12, and good revision 34::
522 522
523 523 hg bisect --bad 34
524 524 hg bisect --good 12
525 525
526 526 - advance the current bisection by marking current revision as good or
527 527 bad::
528 528
529 529 hg bisect --good
530 530 hg bisect --bad
531 531
532 532 - mark the current revision, or a known revision, to be skipped (eg. if
533 533 that revision is not usable because of another issue)::
534 534
535 535 hg bisect --skip
536 536 hg bisect --skip 23
537 537
538 538 - forget the current bisection::
539 539
540 540 hg bisect --reset
541 541
542 542 - use 'make && make tests' to automatically find the first broken
543 543 revision::
544 544
545 545 hg bisect --reset
546 546 hg bisect --bad 34
547 547 hg bisect --good 12
548 548 hg bisect --command 'make && make tests'
549 549
550 550 - see all changesets whose states are already known in the current
551 551 bisection::
552 552
553 553 hg log -r "bisect(pruned)"
554 554
555 555 - see all changesets that took part in the current bisection::
556 556
557 557 hg log -r "bisect(range)"
558 558
559 559 - with the graphlog extension, you can even get a nice graph::
560 560
561 561 hg log --graph -r "bisect(range)"
562 562
563 563 See :hg:`help revsets` for more about the `bisect()` keyword.
564 564
565 565 Returns 0 on success.
566 566 """
567 567 def extendbisectrange(nodes, good):
568 568 # bisect is incomplete when it ends on a merge node and
569 569 # one of the parent was not checked.
570 570 parents = repo[nodes[0]].parents()
571 571 if len(parents) > 1:
572 572 side = good and state['bad'] or state['good']
573 573 num = len(set(i.node() for i in parents) & set(side))
574 574 if num == 1:
575 575 return parents[0].ancestor(parents[1])
576 576 return None
577 577
578 578 def print_result(nodes, good):
579 579 displayer = cmdutil.show_changeset(ui, repo, {})
580 580 if len(nodes) == 1:
581 581 # narrowed it down to a single revision
582 582 if good:
583 583 ui.write(_("The first good revision is:\n"))
584 584 else:
585 585 ui.write(_("The first bad revision is:\n"))
586 586 displayer.show(repo[nodes[0]])
587 587 extendnode = extendbisectrange(nodes, good)
588 588 if extendnode is not None:
589 589 ui.write(_('Not all ancestors of this changeset have been'
590 590 ' checked.\nUse bisect --extend to continue the '
591 591 'bisection from\nthe common ancestor, %s.\n')
592 592 % extendnode)
593 593 else:
594 594 # multiple possible revisions
595 595 if good:
596 596 ui.write(_("Due to skipped revisions, the first "
597 597 "good revision could be any of:\n"))
598 598 else:
599 599 ui.write(_("Due to skipped revisions, the first "
600 600 "bad revision could be any of:\n"))
601 601 for n in nodes:
602 602 displayer.show(repo[n])
603 603 displayer.close()
604 604
605 605 def check_state(state, interactive=True):
606 606 if not state['good'] or not state['bad']:
607 607 if (good or bad or skip or reset) and interactive:
608 608 return
609 609 if not state['good']:
610 610 raise util.Abort(_('cannot bisect (no known good revisions)'))
611 611 else:
612 612 raise util.Abort(_('cannot bisect (no known bad revisions)'))
613 613 return True
614 614
615 615 # backward compatibility
616 616 if rev in "good bad reset init".split():
617 617 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
618 618 cmd, rev, extra = rev, extra, None
619 619 if cmd == "good":
620 620 good = True
621 621 elif cmd == "bad":
622 622 bad = True
623 623 else:
624 624 reset = True
625 625 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
626 626 raise util.Abort(_('incompatible arguments'))
627 627
628 628 if reset:
629 629 p = repo.join("bisect.state")
630 630 if os.path.exists(p):
631 631 os.unlink(p)
632 632 return
633 633
634 634 state = hbisect.load_state(repo)
635 635
636 636 if command:
637 637 changesets = 1
638 638 try:
639 639 while changesets:
640 640 # update state
641 641 status = util.system(command, out=ui.fout)
642 642 if status == 125:
643 643 transition = "skip"
644 644 elif status == 0:
645 645 transition = "good"
646 646 # status < 0 means process was killed
647 647 elif status == 127:
648 648 raise util.Abort(_("failed to execute %s") % command)
649 649 elif status < 0:
650 650 raise util.Abort(_("%s killed") % command)
651 651 else:
652 652 transition = "bad"
653 653 ctx = scmutil.revsingle(repo, rev)
654 654 rev = None # clear for future iterations
655 655 state[transition].append(ctx.node())
656 656 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
657 657 check_state(state, interactive=False)
658 658 # bisect
659 659 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
660 660 # update to next check
661 661 cmdutil.bailifchanged(repo)
662 662 hg.clean(repo, nodes[0], show_stats=False)
663 663 finally:
664 664 hbisect.save_state(repo, state)
665 665 print_result(nodes, good)
666 666 return
667 667
668 668 # update state
669 669
670 670 if rev:
671 671 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
672 672 else:
673 673 nodes = [repo.lookup('.')]
674 674
675 675 if good or bad or skip:
676 676 if good:
677 677 state['good'] += nodes
678 678 elif bad:
679 679 state['bad'] += nodes
680 680 elif skip:
681 681 state['skip'] += nodes
682 682 hbisect.save_state(repo, state)
683 683
684 684 if not check_state(state):
685 685 return
686 686
687 687 # actually bisect
688 688 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
689 689 if extend:
690 690 if not changesets:
691 691 extendnode = extendbisectrange(nodes, good)
692 692 if extendnode is not None:
693 693 ui.write(_("Extending search to changeset %d:%s\n"
694 694 % (extendnode.rev(), extendnode)))
695 695 if noupdate:
696 696 return
697 697 cmdutil.bailifchanged(repo)
698 698 return hg.clean(repo, extendnode.node())
699 699 raise util.Abort(_("nothing to extend"))
700 700
701 701 if changesets == 0:
702 702 print_result(nodes, good)
703 703 else:
704 704 assert len(nodes) == 1 # only a single node can be tested next
705 705 node = nodes[0]
706 706 # compute the approximate number of remaining tests
707 707 tests, size = 0, 2
708 708 while size <= changesets:
709 709 tests, size = tests + 1, size * 2
710 710 rev = repo.changelog.rev(node)
711 711 ui.write(_("Testing changeset %d:%s "
712 712 "(%d changesets remaining, ~%d tests)\n")
713 713 % (rev, short(node), changesets, tests))
714 714 if not noupdate:
715 715 cmdutil.bailifchanged(repo)
716 716 return hg.clean(repo, node)
717 717
718 718 @command('bookmarks',
719 719 [('f', 'force', False, _('force')),
720 720 ('r', 'rev', '', _('revision'), _('REV')),
721 721 ('d', 'delete', False, _('delete a given bookmark')),
722 722 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
723 723 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
724 724 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
725 725 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
726 726 rename=None, inactive=False):
727 727 '''track a line of development with movable markers
728 728
729 729 Bookmarks are pointers to certain commits that move when committing.
730 730 Bookmarks are local. They can be renamed, copied and deleted. It is
731 731 possible to use :hg:`merge NAME` to merge from a given bookmark, and
732 732 :hg:`update NAME` to update to a given bookmark.
733 733
734 734 You can use :hg:`bookmark NAME` to set a bookmark on the working
735 735 directory's parent revision with the given name. If you specify
736 736 a revision using -r REV (where REV may be an existing bookmark),
737 737 the bookmark is assigned to that revision.
738 738
739 739 Bookmarks can be pushed and pulled between repositories (see :hg:`help
740 740 push` and :hg:`help pull`). This requires both the local and remote
741 741 repositories to support bookmarks. For versions prior to 1.8, this means
742 742 the bookmarks extension must be enabled.
743 743 '''
744 744 hexfn = ui.debugflag and hex or short
745 745 marks = repo._bookmarks
746 746 cur = repo.changectx('.').node()
747 747
748 748 if delete:
749 749 if mark is None:
750 750 raise util.Abort(_("bookmark name required"))
751 751 if mark not in marks:
752 752 raise util.Abort(_("bookmark '%s' does not exist") % mark)
753 753 if mark == repo._bookmarkcurrent:
754 754 bookmarks.setcurrent(repo, None)
755 755 del marks[mark]
756 756 bookmarks.write(repo)
757 757 return
758 758
759 759 if rename:
760 760 if rename not in marks:
761 761 raise util.Abort(_("bookmark '%s' does not exist") % rename)
762 762 if mark in marks and not force:
763 763 raise util.Abort(_("bookmark '%s' already exists "
764 764 "(use -f to force)") % mark)
765 765 if mark is None:
766 766 raise util.Abort(_("new bookmark name required"))
767 767 marks[mark] = marks[rename]
768 768 if repo._bookmarkcurrent == rename and not inactive:
769 769 bookmarks.setcurrent(repo, mark)
770 770 del marks[rename]
771 771 bookmarks.write(repo)
772 772 return
773 773
774 774 if mark is not None:
775 775 if "\n" in mark:
776 776 raise util.Abort(_("bookmark name cannot contain newlines"))
777 777 mark = mark.strip()
778 778 if not mark:
779 779 raise util.Abort(_("bookmark names cannot consist entirely of "
780 780 "whitespace"))
781 781 if inactive and mark == repo._bookmarkcurrent:
782 782 bookmarks.setcurrent(repo, None)
783 783 return
784 784 if mark in marks and not force:
785 785 raise util.Abort(_("bookmark '%s' already exists "
786 786 "(use -f to force)") % mark)
787 787 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
788 788 and not force):
789 789 raise util.Abort(
790 790 _("a bookmark cannot have the name of an existing branch"))
791 791 if rev:
792 792 marks[mark] = repo.lookup(rev)
793 793 else:
794 794 marks[mark] = cur
795 795 if not inactive and cur == marks[mark]:
796 796 bookmarks.setcurrent(repo, mark)
797 797 bookmarks.write(repo)
798 798 return
799 799
800 800 if mark is None:
801 801 if rev:
802 802 raise util.Abort(_("bookmark name required"))
803 803 if len(marks) == 0:
804 804 ui.status(_("no bookmarks set\n"))
805 805 else:
806 806 for bmark, n in sorted(marks.iteritems()):
807 807 current = repo._bookmarkcurrent
808 808 if bmark == current and n == cur:
809 809 prefix, label = '*', 'bookmarks.current'
810 810 else:
811 811 prefix, label = ' ', ''
812 812
813 813 if ui.quiet:
814 814 ui.write("%s\n" % bmark, label=label)
815 815 else:
816 816 ui.write(" %s %-25s %d:%s\n" % (
817 817 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
818 818 label=label)
819 819 return
820 820
821 821 @command('branch',
822 822 [('f', 'force', None,
823 823 _('set branch name even if it shadows an existing branch')),
824 824 ('C', 'clean', None, _('reset branch name to parent branch name'))],
825 825 _('[-fC] [NAME]'))
826 826 def branch(ui, repo, label=None, **opts):
827 827 """set or show the current branch name
828 828
829 829 .. note::
830 830 Branch names are permanent and global. Use :hg:`bookmark` to create a
831 831 light-weight bookmark instead. See :hg:`help glossary` for more
832 832 information about named branches and bookmarks.
833 833
834 834 With no argument, show the current branch name. With one argument,
835 835 set the working directory branch name (the branch will not exist
836 836 in the repository until the next commit). Standard practice
837 837 recommends that primary development take place on the 'default'
838 838 branch.
839 839
840 840 Unless -f/--force is specified, branch will not let you set a
841 841 branch name that already exists, even if it's inactive.
842 842
843 843 Use -C/--clean to reset the working directory branch to that of
844 844 the parent of the working directory, negating a previous branch
845 845 change.
846 846
847 847 Use the command :hg:`update` to switch to an existing branch. Use
848 848 :hg:`commit --close-branch` to mark this branch as closed.
849 849
850 850 Returns 0 on success.
851 851 """
852 852
853 853 if opts.get('clean'):
854 854 label = repo[None].p1().branch()
855 855 repo.dirstate.setbranch(label)
856 856 ui.status(_('reset working directory to branch %s\n') % label)
857 857 elif label:
858 858 if not opts.get('force') and label in repo.branchtags():
859 859 if label not in [p.branch() for p in repo.parents()]:
860 860 raise util.Abort(_('a branch of the same name already exists'),
861 861 # i18n: "it" refers to an existing branch
862 862 hint=_("use 'hg update' to switch to it"))
863 863 repo.dirstate.setbranch(label)
864 864 ui.status(_('marked working directory as branch %s\n') % label)
865 ui.status(_('(branches are permanent and global, '
866 'did you want a bookmark?)\n'))
865 867 else:
866 868 ui.write("%s\n" % repo.dirstate.branch())
867 869
868 870 @command('branches',
869 871 [('a', 'active', False, _('show only branches that have unmerged heads')),
870 872 ('c', 'closed', False, _('show normal and closed branches'))],
871 873 _('[-ac]'))
872 874 def branches(ui, repo, active=False, closed=False):
873 875 """list repository named branches
874 876
875 877 List the repository's named branches, indicating which ones are
876 878 inactive. If -c/--closed is specified, also list branches which have
877 879 been marked closed (see :hg:`commit --close-branch`).
878 880
879 881 If -a/--active is specified, only show active branches. A branch
880 882 is considered active if it contains repository heads.
881 883
882 884 Use the command :hg:`update` to switch to an existing branch.
883 885
884 886 Returns 0.
885 887 """
886 888
887 889 hexfunc = ui.debugflag and hex or short
888 890 activebranches = [repo[n].branch() for n in repo.heads()]
889 891 def testactive(tag, node):
890 892 realhead = tag in activebranches
891 893 open = node in repo.branchheads(tag, closed=False)
892 894 return realhead and open
893 895 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
894 896 for tag, node in repo.branchtags().items()],
895 897 reverse=True)
896 898
897 899 for isactive, node, tag in branches:
898 900 if (not active) or isactive:
899 901 if ui.quiet:
900 902 ui.write("%s\n" % tag)
901 903 else:
902 904 hn = repo.lookup(node)
903 905 if isactive:
904 906 label = 'branches.active'
905 907 notice = ''
906 908 elif hn not in repo.branchheads(tag, closed=False):
907 909 if not closed:
908 910 continue
909 911 label = 'branches.closed'
910 912 notice = _(' (closed)')
911 913 else:
912 914 label = 'branches.inactive'
913 915 notice = _(' (inactive)')
914 916 if tag == repo.dirstate.branch():
915 917 label = 'branches.current'
916 918 rev = str(node).rjust(31 - encoding.colwidth(tag))
917 919 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
918 920 tag = ui.label(tag, label)
919 921 ui.write("%s %s%s\n" % (tag, rev, notice))
920 922
921 923 @command('bundle',
922 924 [('f', 'force', None, _('run even when the destination is unrelated')),
923 925 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
924 926 _('REV')),
925 927 ('b', 'branch', [], _('a specific branch you would like to bundle'),
926 928 _('BRANCH')),
927 929 ('', 'base', [],
928 930 _('a base changeset assumed to be available at the destination'),
929 931 _('REV')),
930 932 ('a', 'all', None, _('bundle all changesets in the repository')),
931 933 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
932 934 ] + remoteopts,
933 935 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
934 936 def bundle(ui, repo, fname, dest=None, **opts):
935 937 """create a changegroup file
936 938
937 939 Generate a compressed changegroup file collecting changesets not
938 940 known to be in another repository.
939 941
940 942 If you omit the destination repository, then hg assumes the
941 943 destination will have all the nodes you specify with --base
942 944 parameters. To create a bundle containing all changesets, use
943 945 -a/--all (or --base null).
944 946
945 947 You can change compression method with the -t/--type option.
946 948 The available compression methods are: none, bzip2, and
947 949 gzip (by default, bundles are compressed using bzip2).
948 950
949 951 The bundle file can then be transferred using conventional means
950 952 and applied to another repository with the unbundle or pull
951 953 command. This is useful when direct push and pull are not
952 954 available or when exporting an entire repository is undesirable.
953 955
954 956 Applying bundles preserves all changeset contents including
955 957 permissions, copy/rename information, and revision history.
956 958
957 959 Returns 0 on success, 1 if no changes found.
958 960 """
959 961 revs = None
960 962 if 'rev' in opts:
961 963 revs = scmutil.revrange(repo, opts['rev'])
962 964
963 965 if opts.get('all'):
964 966 base = ['null']
965 967 else:
966 968 base = scmutil.revrange(repo, opts.get('base'))
967 969 if base:
968 970 if dest:
969 971 raise util.Abort(_("--base is incompatible with specifying "
970 972 "a destination"))
971 973 common = [repo.lookup(rev) for rev in base]
972 974 heads = revs and map(repo.lookup, revs) or revs
973 975 else:
974 976 dest = ui.expandpath(dest or 'default-push', dest or 'default')
975 977 dest, branches = hg.parseurl(dest, opts.get('branch'))
976 978 other = hg.peer(repo, opts, dest)
977 979 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
978 980 heads = revs and map(repo.lookup, revs) or revs
979 981 common, outheads = discovery.findcommonoutgoing(repo, other,
980 982 onlyheads=heads,
981 983 force=opts.get('force'))
982 984
983 985 cg = repo.getbundle('bundle', common=common, heads=heads)
984 986 if not cg:
985 987 ui.status(_("no changes found\n"))
986 988 return 1
987 989
988 990 bundletype = opts.get('type', 'bzip2').lower()
989 991 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
990 992 bundletype = btypes.get(bundletype)
991 993 if bundletype not in changegroup.bundletypes:
992 994 raise util.Abort(_('unknown bundle type specified with --type'))
993 995
994 996 changegroup.writebundle(cg, fname, bundletype)
995 997
996 998 @command('cat',
997 999 [('o', 'output', '',
998 1000 _('print output to file with formatted name'), _('FORMAT')),
999 1001 ('r', 'rev', '', _('print the given revision'), _('REV')),
1000 1002 ('', 'decode', None, _('apply any matching decode filter')),
1001 1003 ] + walkopts,
1002 1004 _('[OPTION]... FILE...'))
1003 1005 def cat(ui, repo, file1, *pats, **opts):
1004 1006 """output the current or given revision of files
1005 1007
1006 1008 Print the specified files as they were at the given revision. If
1007 1009 no revision is given, the parent of the working directory is used,
1008 1010 or tip if no revision is checked out.
1009 1011
1010 1012 Output may be to a file, in which case the name of the file is
1011 1013 given using a format string. The formatting rules are the same as
1012 1014 for the export command, with the following additions:
1013 1015
1014 1016 :``%s``: basename of file being printed
1015 1017 :``%d``: dirname of file being printed, or '.' if in repository root
1016 1018 :``%p``: root-relative path name of file being printed
1017 1019
1018 1020 Returns 0 on success.
1019 1021 """
1020 1022 ctx = scmutil.revsingle(repo, opts.get('rev'))
1021 1023 err = 1
1022 1024 m = scmutil.match(ctx, (file1,) + pats, opts)
1023 1025 for abs in ctx.walk(m):
1024 1026 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1025 1027 pathname=abs)
1026 1028 data = ctx[abs].data()
1027 1029 if opts.get('decode'):
1028 1030 data = repo.wwritedata(abs, data)
1029 1031 fp.write(data)
1030 1032 fp.close()
1031 1033 err = 0
1032 1034 return err
1033 1035
1034 1036 @command('^clone',
1035 1037 [('U', 'noupdate', None,
1036 1038 _('the clone will include an empty working copy (only a repository)')),
1037 1039 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1038 1040 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1039 1041 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1040 1042 ('', 'pull', None, _('use pull protocol to copy metadata')),
1041 1043 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1042 1044 ] + remoteopts,
1043 1045 _('[OPTION]... SOURCE [DEST]'))
1044 1046 def clone(ui, source, dest=None, **opts):
1045 1047 """make a copy of an existing repository
1046 1048
1047 1049 Create a copy of an existing repository in a new directory.
1048 1050
1049 1051 If no destination directory name is specified, it defaults to the
1050 1052 basename of the source.
1051 1053
1052 1054 The location of the source is added to the new repository's
1053 1055 ``.hg/hgrc`` file, as the default to be used for future pulls.
1054 1056
1055 1057 Only local paths and ``ssh://`` URLs are supported as
1056 1058 destinations. For ``ssh://`` destinations, no working directory or
1057 1059 ``.hg/hgrc`` will be created on the remote side.
1058 1060
1059 1061 To pull only a subset of changesets, specify one or more revisions
1060 1062 identifiers with -r/--rev or branches with -b/--branch. The
1061 1063 resulting clone will contain only the specified changesets and
1062 1064 their ancestors. These options (or 'clone src#rev dest') imply
1063 1065 --pull, even for local source repositories. Note that specifying a
1064 1066 tag will include the tagged changeset but not the changeset
1065 1067 containing the tag.
1066 1068
1067 1069 To check out a particular version, use -u/--update, or
1068 1070 -U/--noupdate to create a clone with no working directory.
1069 1071
1070 1072 .. container:: verbose
1071 1073
1072 1074 For efficiency, hardlinks are used for cloning whenever the
1073 1075 source and destination are on the same filesystem (note this
1074 1076 applies only to the repository data, not to the working
1075 1077 directory). Some filesystems, such as AFS, implement hardlinking
1076 1078 incorrectly, but do not report errors. In these cases, use the
1077 1079 --pull option to avoid hardlinking.
1078 1080
1079 1081 In some cases, you can clone repositories and the working
1080 1082 directory using full hardlinks with ::
1081 1083
1082 1084 $ cp -al REPO REPOCLONE
1083 1085
1084 1086 This is the fastest way to clone, but it is not always safe. The
1085 1087 operation is not atomic (making sure REPO is not modified during
1086 1088 the operation is up to you) and you have to make sure your
1087 1089 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1088 1090 so). Also, this is not compatible with certain extensions that
1089 1091 place their metadata under the .hg directory, such as mq.
1090 1092
1091 1093 Mercurial will update the working directory to the first applicable
1092 1094 revision from this list:
1093 1095
1094 1096 a) null if -U or the source repository has no changesets
1095 1097 b) if -u . and the source repository is local, the first parent of
1096 1098 the source repository's working directory
1097 1099 c) the changeset specified with -u (if a branch name, this means the
1098 1100 latest head of that branch)
1099 1101 d) the changeset specified with -r
1100 1102 e) the tipmost head specified with -b
1101 1103 f) the tipmost head specified with the url#branch source syntax
1102 1104 g) the tipmost head of the default branch
1103 1105 h) tip
1104 1106
1105 1107 Examples:
1106 1108
1107 1109 - clone a remote repository to a new directory named hg/::
1108 1110
1109 1111 hg clone http://selenic.com/hg
1110 1112
1111 1113 - create a lightweight local clone::
1112 1114
1113 1115 hg clone project/ project-feature/
1114 1116
1115 1117 - clone from an absolute path on an ssh server (note double-slash)::
1116 1118
1117 1119 hg clone ssh://user@server//home/projects/alpha/
1118 1120
1119 1121 - do a high-speed clone over a LAN while checking out a
1120 1122 specified version::
1121 1123
1122 1124 hg clone --uncompressed http://server/repo -u 1.5
1123 1125
1124 1126 - create a repository without changesets after a particular revision::
1125 1127
1126 1128 hg clone -r 04e544 experimental/ good/
1127 1129
1128 1130 - clone (and track) a particular named branch::
1129 1131
1130 1132 hg clone http://selenic.com/hg#stable
1131 1133
1132 1134 See :hg:`help urls` for details on specifying URLs.
1133 1135
1134 1136 Returns 0 on success.
1135 1137 """
1136 1138 if opts.get('noupdate') and opts.get('updaterev'):
1137 1139 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1138 1140
1139 1141 r = hg.clone(ui, opts, source, dest,
1140 1142 pull=opts.get('pull'),
1141 1143 stream=opts.get('uncompressed'),
1142 1144 rev=opts.get('rev'),
1143 1145 update=opts.get('updaterev') or not opts.get('noupdate'),
1144 1146 branch=opts.get('branch'))
1145 1147
1146 1148 return r is None
1147 1149
1148 1150 @command('^commit|ci',
1149 1151 [('A', 'addremove', None,
1150 1152 _('mark new/missing files as added/removed before committing')),
1151 1153 ('', 'close-branch', None,
1152 1154 _('mark a branch as closed, hiding it from the branch list')),
1153 1155 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1154 1156 _('[OPTION]... [FILE]...'))
1155 1157 def commit(ui, repo, *pats, **opts):
1156 1158 """commit the specified files or all outstanding changes
1157 1159
1158 1160 Commit changes to the given files into the repository. Unlike a
1159 1161 centralized SCM, this operation is a local operation. See
1160 1162 :hg:`push` for a way to actively distribute your changes.
1161 1163
1162 1164 If a list of files is omitted, all changes reported by :hg:`status`
1163 1165 will be committed.
1164 1166
1165 1167 If you are committing the result of a merge, do not provide any
1166 1168 filenames or -I/-X filters.
1167 1169
1168 1170 If no commit message is specified, Mercurial starts your
1169 1171 configured editor where you can enter a message. In case your
1170 1172 commit fails, you will find a backup of your message in
1171 1173 ``.hg/last-message.txt``.
1172 1174
1173 1175 See :hg:`help dates` for a list of formats valid for -d/--date.
1174 1176
1175 1177 Returns 0 on success, 1 if nothing changed.
1176 1178 """
1177 1179 if opts.get('subrepos'):
1178 1180 # Let --subrepos on the command line overide config setting.
1179 1181 ui.setconfig('ui', 'commitsubrepos', True)
1180 1182
1181 1183 extra = {}
1182 1184 if opts.get('close_branch'):
1183 1185 if repo['.'].node() not in repo.branchheads():
1184 1186 # The topo heads set is included in the branch heads set of the
1185 1187 # current branch, so it's sufficient to test branchheads
1186 1188 raise util.Abort(_('can only close branch heads'))
1187 1189 extra['close'] = 1
1188 1190 e = cmdutil.commiteditor
1189 1191 if opts.get('force_editor'):
1190 1192 e = cmdutil.commitforceeditor
1191 1193
1192 1194 def commitfunc(ui, repo, message, match, opts):
1193 1195 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1194 1196 editor=e, extra=extra)
1195 1197
1196 1198 branch = repo[None].branch()
1197 1199 bheads = repo.branchheads(branch)
1198 1200
1199 1201 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1200 1202 if not node:
1201 1203 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1202 1204 if stat[3]:
1203 1205 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1204 1206 % len(stat[3]))
1205 1207 else:
1206 1208 ui.status(_("nothing changed\n"))
1207 1209 return 1
1208 1210
1209 1211 ctx = repo[node]
1210 1212 parents = ctx.parents()
1211 1213
1212 1214 if (bheads and node not in bheads and not
1213 1215 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1214 1216 ui.status(_('created new head\n'))
1215 1217 # The message is not printed for initial roots. For the other
1216 1218 # changesets, it is printed in the following situations:
1217 1219 #
1218 1220 # Par column: for the 2 parents with ...
1219 1221 # N: null or no parent
1220 1222 # B: parent is on another named branch
1221 1223 # C: parent is a regular non head changeset
1222 1224 # H: parent was a branch head of the current branch
1223 1225 # Msg column: whether we print "created new head" message
1224 1226 # In the following, it is assumed that there already exists some
1225 1227 # initial branch heads of the current branch, otherwise nothing is
1226 1228 # printed anyway.
1227 1229 #
1228 1230 # Par Msg Comment
1229 1231 # NN y additional topo root
1230 1232 #
1231 1233 # BN y additional branch root
1232 1234 # CN y additional topo head
1233 1235 # HN n usual case
1234 1236 #
1235 1237 # BB y weird additional branch root
1236 1238 # CB y branch merge
1237 1239 # HB n merge with named branch
1238 1240 #
1239 1241 # CC y additional head from merge
1240 1242 # CH n merge with a head
1241 1243 #
1242 1244 # HH n head merge: head count decreases
1243 1245
1244 1246 if not opts.get('close_branch'):
1245 1247 for r in parents:
1246 1248 if r.extra().get('close') and r.branch() == branch:
1247 1249 ui.status(_('reopening closed branch head %d\n') % r)
1248 1250
1249 1251 if ui.debugflag:
1250 1252 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1251 1253 elif ui.verbose:
1252 1254 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1253 1255
1254 1256 @command('copy|cp',
1255 1257 [('A', 'after', None, _('record a copy that has already occurred')),
1256 1258 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1257 1259 ] + walkopts + dryrunopts,
1258 1260 _('[OPTION]... [SOURCE]... DEST'))
1259 1261 def copy(ui, repo, *pats, **opts):
1260 1262 """mark files as copied for the next commit
1261 1263
1262 1264 Mark dest as having copies of source files. If dest is a
1263 1265 directory, copies are put in that directory. If dest is a file,
1264 1266 the source must be a single file.
1265 1267
1266 1268 By default, this command copies the contents of files as they
1267 1269 exist in the working directory. If invoked with -A/--after, the
1268 1270 operation is recorded, but no copying is performed.
1269 1271
1270 1272 This command takes effect with the next commit. To undo a copy
1271 1273 before that, see :hg:`revert`.
1272 1274
1273 1275 Returns 0 on success, 1 if errors are encountered.
1274 1276 """
1275 1277 wlock = repo.wlock(False)
1276 1278 try:
1277 1279 return cmdutil.copy(ui, repo, pats, opts)
1278 1280 finally:
1279 1281 wlock.release()
1280 1282
1281 1283 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1282 1284 def debugancestor(ui, repo, *args):
1283 1285 """find the ancestor revision of two revisions in a given index"""
1284 1286 if len(args) == 3:
1285 1287 index, rev1, rev2 = args
1286 1288 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1287 1289 lookup = r.lookup
1288 1290 elif len(args) == 2:
1289 1291 if not repo:
1290 1292 raise util.Abort(_("there is no Mercurial repository here "
1291 1293 "(.hg not found)"))
1292 1294 rev1, rev2 = args
1293 1295 r = repo.changelog
1294 1296 lookup = repo.lookup
1295 1297 else:
1296 1298 raise util.Abort(_('either two or three arguments required'))
1297 1299 a = r.ancestor(lookup(rev1), lookup(rev2))
1298 1300 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1299 1301
1300 1302 @command('debugbuilddag',
1301 1303 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1302 1304 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1303 1305 ('n', 'new-file', None, _('add new file at each rev'))],
1304 1306 _('[OPTION]... [TEXT]'))
1305 1307 def debugbuilddag(ui, repo, text=None,
1306 1308 mergeable_file=False,
1307 1309 overwritten_file=False,
1308 1310 new_file=False):
1309 1311 """builds a repo with a given DAG from scratch in the current empty repo
1310 1312
1311 1313 The description of the DAG is read from stdin if not given on the
1312 1314 command line.
1313 1315
1314 1316 Elements:
1315 1317
1316 1318 - "+n" is a linear run of n nodes based on the current default parent
1317 1319 - "." is a single node based on the current default parent
1318 1320 - "$" resets the default parent to null (implied at the start);
1319 1321 otherwise the default parent is always the last node created
1320 1322 - "<p" sets the default parent to the backref p
1321 1323 - "*p" is a fork at parent p, which is a backref
1322 1324 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1323 1325 - "/p2" is a merge of the preceding node and p2
1324 1326 - ":tag" defines a local tag for the preceding node
1325 1327 - "@branch" sets the named branch for subsequent nodes
1326 1328 - "#...\\n" is a comment up to the end of the line
1327 1329
1328 1330 Whitespace between the above elements is ignored.
1329 1331
1330 1332 A backref is either
1331 1333
1332 1334 - a number n, which references the node curr-n, where curr is the current
1333 1335 node, or
1334 1336 - the name of a local tag you placed earlier using ":tag", or
1335 1337 - empty to denote the default parent.
1336 1338
1337 1339 All string valued-elements are either strictly alphanumeric, or must
1338 1340 be enclosed in double quotes ("..."), with "\\" as escape character.
1339 1341 """
1340 1342
1341 1343 if text is None:
1342 1344 ui.status(_("reading DAG from stdin\n"))
1343 1345 text = ui.fin.read()
1344 1346
1345 1347 cl = repo.changelog
1346 1348 if len(cl) > 0:
1347 1349 raise util.Abort(_('repository is not empty'))
1348 1350
1349 1351 # determine number of revs in DAG
1350 1352 total = 0
1351 1353 for type, data in dagparser.parsedag(text):
1352 1354 if type == 'n':
1353 1355 total += 1
1354 1356
1355 1357 if mergeable_file:
1356 1358 linesperrev = 2
1357 1359 # make a file with k lines per rev
1358 1360 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1359 1361 initialmergedlines.append("")
1360 1362
1361 1363 tags = []
1362 1364
1363 1365 tr = repo.transaction("builddag")
1364 1366 try:
1365 1367
1366 1368 at = -1
1367 1369 atbranch = 'default'
1368 1370 nodeids = []
1369 1371 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1370 1372 for type, data in dagparser.parsedag(text):
1371 1373 if type == 'n':
1372 1374 ui.note('node %s\n' % str(data))
1373 1375 id, ps = data
1374 1376
1375 1377 files = []
1376 1378 fctxs = {}
1377 1379
1378 1380 p2 = None
1379 1381 if mergeable_file:
1380 1382 fn = "mf"
1381 1383 p1 = repo[ps[0]]
1382 1384 if len(ps) > 1:
1383 1385 p2 = repo[ps[1]]
1384 1386 pa = p1.ancestor(p2)
1385 1387 base, local, other = [x[fn].data() for x in pa, p1, p2]
1386 1388 m3 = simplemerge.Merge3Text(base, local, other)
1387 1389 ml = [l.strip() for l in m3.merge_lines()]
1388 1390 ml.append("")
1389 1391 elif at > 0:
1390 1392 ml = p1[fn].data().split("\n")
1391 1393 else:
1392 1394 ml = initialmergedlines
1393 1395 ml[id * linesperrev] += " r%i" % id
1394 1396 mergedtext = "\n".join(ml)
1395 1397 files.append(fn)
1396 1398 fctxs[fn] = context.memfilectx(fn, mergedtext)
1397 1399
1398 1400 if overwritten_file:
1399 1401 fn = "of"
1400 1402 files.append(fn)
1401 1403 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1402 1404
1403 1405 if new_file:
1404 1406 fn = "nf%i" % id
1405 1407 files.append(fn)
1406 1408 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1407 1409 if len(ps) > 1:
1408 1410 if not p2:
1409 1411 p2 = repo[ps[1]]
1410 1412 for fn in p2:
1411 1413 if fn.startswith("nf"):
1412 1414 files.append(fn)
1413 1415 fctxs[fn] = p2[fn]
1414 1416
1415 1417 def fctxfn(repo, cx, path):
1416 1418 return fctxs.get(path)
1417 1419
1418 1420 if len(ps) == 0 or ps[0] < 0:
1419 1421 pars = [None, None]
1420 1422 elif len(ps) == 1:
1421 1423 pars = [nodeids[ps[0]], None]
1422 1424 else:
1423 1425 pars = [nodeids[p] for p in ps]
1424 1426 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1425 1427 date=(id, 0),
1426 1428 user="debugbuilddag",
1427 1429 extra={'branch': atbranch})
1428 1430 nodeid = repo.commitctx(cx)
1429 1431 nodeids.append(nodeid)
1430 1432 at = id
1431 1433 elif type == 'l':
1432 1434 id, name = data
1433 1435 ui.note('tag %s\n' % name)
1434 1436 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1435 1437 elif type == 'a':
1436 1438 ui.note('branch %s\n' % data)
1437 1439 atbranch = data
1438 1440 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1439 1441 tr.close()
1440 1442 finally:
1441 1443 ui.progress(_('building'), None)
1442 1444 tr.release()
1443 1445
1444 1446 if tags:
1445 1447 repo.opener.write("localtags", "".join(tags))
1446 1448
1447 1449 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1448 1450 def debugbundle(ui, bundlepath, all=None, **opts):
1449 1451 """lists the contents of a bundle"""
1450 1452 f = url.open(ui, bundlepath)
1451 1453 try:
1452 1454 gen = changegroup.readbundle(f, bundlepath)
1453 1455 if all:
1454 1456 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1455 1457
1456 1458 def showchunks(named):
1457 1459 ui.write("\n%s\n" % named)
1458 1460 chain = None
1459 1461 while True:
1460 1462 chunkdata = gen.deltachunk(chain)
1461 1463 if not chunkdata:
1462 1464 break
1463 1465 node = chunkdata['node']
1464 1466 p1 = chunkdata['p1']
1465 1467 p2 = chunkdata['p2']
1466 1468 cs = chunkdata['cs']
1467 1469 deltabase = chunkdata['deltabase']
1468 1470 delta = chunkdata['delta']
1469 1471 ui.write("%s %s %s %s %s %s\n" %
1470 1472 (hex(node), hex(p1), hex(p2),
1471 1473 hex(cs), hex(deltabase), len(delta)))
1472 1474 chain = node
1473 1475
1474 1476 chunkdata = gen.changelogheader()
1475 1477 showchunks("changelog")
1476 1478 chunkdata = gen.manifestheader()
1477 1479 showchunks("manifest")
1478 1480 while True:
1479 1481 chunkdata = gen.filelogheader()
1480 1482 if not chunkdata:
1481 1483 break
1482 1484 fname = chunkdata['filename']
1483 1485 showchunks(fname)
1484 1486 else:
1485 1487 chunkdata = gen.changelogheader()
1486 1488 chain = None
1487 1489 while True:
1488 1490 chunkdata = gen.deltachunk(chain)
1489 1491 if not chunkdata:
1490 1492 break
1491 1493 node = chunkdata['node']
1492 1494 ui.write("%s\n" % hex(node))
1493 1495 chain = node
1494 1496 finally:
1495 1497 f.close()
1496 1498
1497 1499 @command('debugcheckstate', [], '')
1498 1500 def debugcheckstate(ui, repo):
1499 1501 """validate the correctness of the current dirstate"""
1500 1502 parent1, parent2 = repo.dirstate.parents()
1501 1503 m1 = repo[parent1].manifest()
1502 1504 m2 = repo[parent2].manifest()
1503 1505 errors = 0
1504 1506 for f in repo.dirstate:
1505 1507 state = repo.dirstate[f]
1506 1508 if state in "nr" and f not in m1:
1507 1509 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1508 1510 errors += 1
1509 1511 if state in "a" and f in m1:
1510 1512 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1511 1513 errors += 1
1512 1514 if state in "m" and f not in m1 and f not in m2:
1513 1515 ui.warn(_("%s in state %s, but not in either manifest\n") %
1514 1516 (f, state))
1515 1517 errors += 1
1516 1518 for f in m1:
1517 1519 state = repo.dirstate[f]
1518 1520 if state not in "nrm":
1519 1521 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1520 1522 errors += 1
1521 1523 if errors:
1522 1524 error = _(".hg/dirstate inconsistent with current parent's manifest")
1523 1525 raise util.Abort(error)
1524 1526
1525 1527 @command('debugcommands', [], _('[COMMAND]'))
1526 1528 def debugcommands(ui, cmd='', *args):
1527 1529 """list all available commands and options"""
1528 1530 for cmd, vals in sorted(table.iteritems()):
1529 1531 cmd = cmd.split('|')[0].strip('^')
1530 1532 opts = ', '.join([i[1] for i in vals[1]])
1531 1533 ui.write('%s: %s\n' % (cmd, opts))
1532 1534
1533 1535 @command('debugcomplete',
1534 1536 [('o', 'options', None, _('show the command options'))],
1535 1537 _('[-o] CMD'))
1536 1538 def debugcomplete(ui, cmd='', **opts):
1537 1539 """returns the completion list associated with the given command"""
1538 1540
1539 1541 if opts.get('options'):
1540 1542 options = []
1541 1543 otables = [globalopts]
1542 1544 if cmd:
1543 1545 aliases, entry = cmdutil.findcmd(cmd, table, False)
1544 1546 otables.append(entry[1])
1545 1547 for t in otables:
1546 1548 for o in t:
1547 1549 if "(DEPRECATED)" in o[3]:
1548 1550 continue
1549 1551 if o[0]:
1550 1552 options.append('-%s' % o[0])
1551 1553 options.append('--%s' % o[1])
1552 1554 ui.write("%s\n" % "\n".join(options))
1553 1555 return
1554 1556
1555 1557 cmdlist = cmdutil.findpossible(cmd, table)
1556 1558 if ui.verbose:
1557 1559 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1558 1560 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1559 1561
1560 1562 @command('debugdag',
1561 1563 [('t', 'tags', None, _('use tags as labels')),
1562 1564 ('b', 'branches', None, _('annotate with branch names')),
1563 1565 ('', 'dots', None, _('use dots for runs')),
1564 1566 ('s', 'spaces', None, _('separate elements by spaces'))],
1565 1567 _('[OPTION]... [FILE [REV]...]'))
1566 1568 def debugdag(ui, repo, file_=None, *revs, **opts):
1567 1569 """format the changelog or an index DAG as a concise textual description
1568 1570
1569 1571 If you pass a revlog index, the revlog's DAG is emitted. If you list
1570 1572 revision numbers, they get labelled in the output as rN.
1571 1573
1572 1574 Otherwise, the changelog DAG of the current repo is emitted.
1573 1575 """
1574 1576 spaces = opts.get('spaces')
1575 1577 dots = opts.get('dots')
1576 1578 if file_:
1577 1579 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1578 1580 revs = set((int(r) for r in revs))
1579 1581 def events():
1580 1582 for r in rlog:
1581 1583 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1582 1584 if r in revs:
1583 1585 yield 'l', (r, "r%i" % r)
1584 1586 elif repo:
1585 1587 cl = repo.changelog
1586 1588 tags = opts.get('tags')
1587 1589 branches = opts.get('branches')
1588 1590 if tags:
1589 1591 labels = {}
1590 1592 for l, n in repo.tags().items():
1591 1593 labels.setdefault(cl.rev(n), []).append(l)
1592 1594 def events():
1593 1595 b = "default"
1594 1596 for r in cl:
1595 1597 if branches:
1596 1598 newb = cl.read(cl.node(r))[5]['branch']
1597 1599 if newb != b:
1598 1600 yield 'a', newb
1599 1601 b = newb
1600 1602 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1601 1603 if tags:
1602 1604 ls = labels.get(r)
1603 1605 if ls:
1604 1606 for l in ls:
1605 1607 yield 'l', (r, l)
1606 1608 else:
1607 1609 raise util.Abort(_('need repo for changelog dag'))
1608 1610
1609 1611 for line in dagparser.dagtextlines(events(),
1610 1612 addspaces=spaces,
1611 1613 wraplabels=True,
1612 1614 wrapannotations=True,
1613 1615 wrapnonlinear=dots,
1614 1616 usedots=dots,
1615 1617 maxlinewidth=70):
1616 1618 ui.write(line)
1617 1619 ui.write("\n")
1618 1620
1619 1621 @command('debugdata',
1620 1622 [('c', 'changelog', False, _('open changelog')),
1621 1623 ('m', 'manifest', False, _('open manifest'))],
1622 1624 _('-c|-m|FILE REV'))
1623 1625 def debugdata(ui, repo, file_, rev = None, **opts):
1624 1626 """dump the contents of a data file revision"""
1625 1627 if opts.get('changelog') or opts.get('manifest'):
1626 1628 file_, rev = None, file_
1627 1629 elif rev is None:
1628 1630 raise error.CommandError('debugdata', _('invalid arguments'))
1629 1631 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1630 1632 try:
1631 1633 ui.write(r.revision(r.lookup(rev)))
1632 1634 except KeyError:
1633 1635 raise util.Abort(_('invalid revision identifier %s') % rev)
1634 1636
1635 1637 @command('debugdate',
1636 1638 [('e', 'extended', None, _('try extended date formats'))],
1637 1639 _('[-e] DATE [RANGE]'))
1638 1640 def debugdate(ui, date, range=None, **opts):
1639 1641 """parse and display a date"""
1640 1642 if opts["extended"]:
1641 1643 d = util.parsedate(date, util.extendeddateformats)
1642 1644 else:
1643 1645 d = util.parsedate(date)
1644 1646 ui.write("internal: %s %s\n" % d)
1645 1647 ui.write("standard: %s\n" % util.datestr(d))
1646 1648 if range:
1647 1649 m = util.matchdate(range)
1648 1650 ui.write("match: %s\n" % m(d[0]))
1649 1651
1650 1652 @command('debugdiscovery',
1651 1653 [('', 'old', None, _('use old-style discovery')),
1652 1654 ('', 'nonheads', None,
1653 1655 _('use old-style discovery with non-heads included')),
1654 1656 ] + remoteopts,
1655 1657 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1656 1658 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1657 1659 """runs the changeset discovery protocol in isolation"""
1658 1660 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1659 1661 remote = hg.peer(repo, opts, remoteurl)
1660 1662 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1661 1663
1662 1664 # make sure tests are repeatable
1663 1665 random.seed(12323)
1664 1666
1665 1667 def doit(localheads, remoteheads):
1666 1668 if opts.get('old'):
1667 1669 if localheads:
1668 1670 raise util.Abort('cannot use localheads with old style discovery')
1669 1671 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1670 1672 force=True)
1671 1673 common = set(common)
1672 1674 if not opts.get('nonheads'):
1673 1675 ui.write("unpruned common: %s\n" % " ".join([short(n)
1674 1676 for n in common]))
1675 1677 dag = dagutil.revlogdag(repo.changelog)
1676 1678 all = dag.ancestorset(dag.internalizeall(common))
1677 1679 common = dag.externalizeall(dag.headsetofconnecteds(all))
1678 1680 else:
1679 1681 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1680 1682 common = set(common)
1681 1683 rheads = set(hds)
1682 1684 lheads = set(repo.heads())
1683 1685 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1684 1686 if lheads <= common:
1685 1687 ui.write("local is subset\n")
1686 1688 elif rheads <= common:
1687 1689 ui.write("remote is subset\n")
1688 1690
1689 1691 serverlogs = opts.get('serverlog')
1690 1692 if serverlogs:
1691 1693 for filename in serverlogs:
1692 1694 logfile = open(filename, 'r')
1693 1695 try:
1694 1696 line = logfile.readline()
1695 1697 while line:
1696 1698 parts = line.strip().split(';')
1697 1699 op = parts[1]
1698 1700 if op == 'cg':
1699 1701 pass
1700 1702 elif op == 'cgss':
1701 1703 doit(parts[2].split(' '), parts[3].split(' '))
1702 1704 elif op == 'unb':
1703 1705 doit(parts[3].split(' '), parts[2].split(' '))
1704 1706 line = logfile.readline()
1705 1707 finally:
1706 1708 logfile.close()
1707 1709
1708 1710 else:
1709 1711 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1710 1712 opts.get('remote_head'))
1711 1713 localrevs = opts.get('local_head')
1712 1714 doit(localrevs, remoterevs)
1713 1715
1714 1716 @command('debugfileset', [], ('REVSPEC'))
1715 1717 def debugfileset(ui, repo, expr):
1716 1718 '''parse and apply a fileset specification'''
1717 1719 if ui.verbose:
1718 1720 tree = fileset.parse(expr)[0]
1719 1721 ui.note(tree, "\n")
1720 1722
1721 1723 for f in fileset.getfileset(repo[None], expr):
1722 1724 ui.write("%s\n" % f)
1723 1725
1724 1726 @command('debugfsinfo', [], _('[PATH]'))
1725 1727 def debugfsinfo(ui, path = "."):
1726 1728 """show information detected about current filesystem"""
1727 1729 util.writefile('.debugfsinfo', '')
1728 1730 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1729 1731 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1730 1732 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1731 1733 and 'yes' or 'no'))
1732 1734 os.unlink('.debugfsinfo')
1733 1735
1734 1736 @command('debuggetbundle',
1735 1737 [('H', 'head', [], _('id of head node'), _('ID')),
1736 1738 ('C', 'common', [], _('id of common node'), _('ID')),
1737 1739 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1738 1740 _('REPO FILE [-H|-C ID]...'))
1739 1741 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1740 1742 """retrieves a bundle from a repo
1741 1743
1742 1744 Every ID must be a full-length hex node id string. Saves the bundle to the
1743 1745 given file.
1744 1746 """
1745 1747 repo = hg.peer(ui, opts, repopath)
1746 1748 if not repo.capable('getbundle'):
1747 1749 raise util.Abort("getbundle() not supported by target repository")
1748 1750 args = {}
1749 1751 if common:
1750 1752 args['common'] = [bin(s) for s in common]
1751 1753 if head:
1752 1754 args['heads'] = [bin(s) for s in head]
1753 1755 bundle = repo.getbundle('debug', **args)
1754 1756
1755 1757 bundletype = opts.get('type', 'bzip2').lower()
1756 1758 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1757 1759 bundletype = btypes.get(bundletype)
1758 1760 if bundletype not in changegroup.bundletypes:
1759 1761 raise util.Abort(_('unknown bundle type specified with --type'))
1760 1762 changegroup.writebundle(bundle, bundlepath, bundletype)
1761 1763
1762 1764 @command('debugignore', [], '')
1763 1765 def debugignore(ui, repo, *values, **opts):
1764 1766 """display the combined ignore pattern"""
1765 1767 ignore = repo.dirstate._ignore
1766 1768 includepat = getattr(ignore, 'includepat', None)
1767 1769 if includepat is not None:
1768 1770 ui.write("%s\n" % includepat)
1769 1771 else:
1770 1772 raise util.Abort(_("no ignore patterns found"))
1771 1773
1772 1774 @command('debugindex',
1773 1775 [('c', 'changelog', False, _('open changelog')),
1774 1776 ('m', 'manifest', False, _('open manifest')),
1775 1777 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1776 1778 _('[-f FORMAT] -c|-m|FILE'))
1777 1779 def debugindex(ui, repo, file_ = None, **opts):
1778 1780 """dump the contents of an index file"""
1779 1781 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1780 1782 format = opts.get('format', 0)
1781 1783 if format not in (0, 1):
1782 1784 raise util.Abort(_("unknown format %d") % format)
1783 1785
1784 1786 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1785 1787 if generaldelta:
1786 1788 basehdr = ' delta'
1787 1789 else:
1788 1790 basehdr = ' base'
1789 1791
1790 1792 if format == 0:
1791 1793 ui.write(" rev offset length " + basehdr + " linkrev"
1792 1794 " nodeid p1 p2\n")
1793 1795 elif format == 1:
1794 1796 ui.write(" rev flag offset length"
1795 1797 " size " + basehdr + " link p1 p2 nodeid\n")
1796 1798
1797 1799 for i in r:
1798 1800 node = r.node(i)
1799 1801 if generaldelta:
1800 1802 base = r.deltaparent(i)
1801 1803 else:
1802 1804 base = r.chainbase(i)
1803 1805 if format == 0:
1804 1806 try:
1805 1807 pp = r.parents(node)
1806 1808 except:
1807 1809 pp = [nullid, nullid]
1808 1810 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1809 1811 i, r.start(i), r.length(i), base, r.linkrev(i),
1810 1812 short(node), short(pp[0]), short(pp[1])))
1811 1813 elif format == 1:
1812 1814 pr = r.parentrevs(i)
1813 1815 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1814 1816 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1815 1817 base, r.linkrev(i), pr[0], pr[1], short(node)))
1816 1818
1817 1819 @command('debugindexdot', [], _('FILE'))
1818 1820 def debugindexdot(ui, repo, file_):
1819 1821 """dump an index DAG as a graphviz dot file"""
1820 1822 r = None
1821 1823 if repo:
1822 1824 filelog = repo.file(file_)
1823 1825 if len(filelog):
1824 1826 r = filelog
1825 1827 if not r:
1826 1828 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1827 1829 ui.write("digraph G {\n")
1828 1830 for i in r:
1829 1831 node = r.node(i)
1830 1832 pp = r.parents(node)
1831 1833 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1832 1834 if pp[1] != nullid:
1833 1835 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1834 1836 ui.write("}\n")
1835 1837
1836 1838 @command('debuginstall', [], '')
1837 1839 def debuginstall(ui):
1838 1840 '''test Mercurial installation
1839 1841
1840 1842 Returns 0 on success.
1841 1843 '''
1842 1844
1843 1845 def writetemp(contents):
1844 1846 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1845 1847 f = os.fdopen(fd, "wb")
1846 1848 f.write(contents)
1847 1849 f.close()
1848 1850 return name
1849 1851
1850 1852 problems = 0
1851 1853
1852 1854 # encoding
1853 1855 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1854 1856 try:
1855 1857 encoding.fromlocal("test")
1856 1858 except util.Abort, inst:
1857 1859 ui.write(" %s\n" % inst)
1858 1860 ui.write(_(" (check that your locale is properly set)\n"))
1859 1861 problems += 1
1860 1862
1861 1863 # compiled modules
1862 1864 ui.status(_("Checking installed modules (%s)...\n")
1863 1865 % os.path.dirname(__file__))
1864 1866 try:
1865 1867 import bdiff, mpatch, base85, osutil
1866 1868 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1867 1869 except Exception, inst:
1868 1870 ui.write(" %s\n" % inst)
1869 1871 ui.write(_(" One or more extensions could not be found"))
1870 1872 ui.write(_(" (check that you compiled the extensions)\n"))
1871 1873 problems += 1
1872 1874
1873 1875 # templates
1874 1876 import templater
1875 1877 p = templater.templatepath()
1876 1878 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1877 1879 try:
1878 1880 templater.templater(templater.templatepath("map-cmdline.default"))
1879 1881 except Exception, inst:
1880 1882 ui.write(" %s\n" % inst)
1881 1883 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1882 1884 problems += 1
1883 1885
1884 1886 # editor
1885 1887 ui.status(_("Checking commit editor...\n"))
1886 1888 editor = ui.geteditor()
1887 1889 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1888 1890 if not cmdpath:
1889 1891 if editor == 'vi':
1890 1892 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1891 1893 ui.write(_(" (specify a commit editor in your configuration"
1892 1894 " file)\n"))
1893 1895 else:
1894 1896 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1895 1897 ui.write(_(" (specify a commit editor in your configuration"
1896 1898 " file)\n"))
1897 1899 problems += 1
1898 1900
1899 1901 # check username
1900 1902 ui.status(_("Checking username...\n"))
1901 1903 try:
1902 1904 ui.username()
1903 1905 except util.Abort, e:
1904 1906 ui.write(" %s\n" % e)
1905 1907 ui.write(_(" (specify a username in your configuration file)\n"))
1906 1908 problems += 1
1907 1909
1908 1910 if not problems:
1909 1911 ui.status(_("No problems detected\n"))
1910 1912 else:
1911 1913 ui.write(_("%s problems detected,"
1912 1914 " please check your install!\n") % problems)
1913 1915
1914 1916 return problems
1915 1917
1916 1918 @command('debugknown', [], _('REPO ID...'))
1917 1919 def debugknown(ui, repopath, *ids, **opts):
1918 1920 """test whether node ids are known to a repo
1919 1921
1920 1922 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1921 1923 indicating unknown/known.
1922 1924 """
1923 1925 repo = hg.peer(ui, opts, repopath)
1924 1926 if not repo.capable('known'):
1925 1927 raise util.Abort("known() not supported by target repository")
1926 1928 flags = repo.known([bin(s) for s in ids])
1927 1929 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1928 1930
1929 1931 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1930 1932 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1931 1933 '''access the pushkey key/value protocol
1932 1934
1933 1935 With two args, list the keys in the given namespace.
1934 1936
1935 1937 With five args, set a key to new if it currently is set to old.
1936 1938 Reports success or failure.
1937 1939 '''
1938 1940
1939 1941 target = hg.peer(ui, {}, repopath)
1940 1942 if keyinfo:
1941 1943 key, old, new = keyinfo
1942 1944 r = target.pushkey(namespace, key, old, new)
1943 1945 ui.status(str(r) + '\n')
1944 1946 return not r
1945 1947 else:
1946 1948 for k, v in target.listkeys(namespace).iteritems():
1947 1949 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1948 1950 v.encode('string-escape')))
1949 1951
1950 1952 @command('debugrebuildstate',
1951 1953 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1952 1954 _('[-r REV] [REV]'))
1953 1955 def debugrebuildstate(ui, repo, rev="tip"):
1954 1956 """rebuild the dirstate as it would look like for the given revision"""
1955 1957 ctx = scmutil.revsingle(repo, rev)
1956 1958 wlock = repo.wlock()
1957 1959 try:
1958 1960 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1959 1961 finally:
1960 1962 wlock.release()
1961 1963
1962 1964 @command('debugrename',
1963 1965 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1964 1966 _('[-r REV] FILE'))
1965 1967 def debugrename(ui, repo, file1, *pats, **opts):
1966 1968 """dump rename information"""
1967 1969
1968 1970 ctx = scmutil.revsingle(repo, opts.get('rev'))
1969 1971 m = scmutil.match(ctx, (file1,) + pats, opts)
1970 1972 for abs in ctx.walk(m):
1971 1973 fctx = ctx[abs]
1972 1974 o = fctx.filelog().renamed(fctx.filenode())
1973 1975 rel = m.rel(abs)
1974 1976 if o:
1975 1977 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1976 1978 else:
1977 1979 ui.write(_("%s not renamed\n") % rel)
1978 1980
1979 1981 @command('debugrevlog',
1980 1982 [('c', 'changelog', False, _('open changelog')),
1981 1983 ('m', 'manifest', False, _('open manifest')),
1982 1984 ('d', 'dump', False, _('dump index data'))],
1983 1985 _('-c|-m|FILE'))
1984 1986 def debugrevlog(ui, repo, file_ = None, **opts):
1985 1987 """show data and statistics about a revlog"""
1986 1988 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1987 1989
1988 1990 if opts.get("dump"):
1989 1991 numrevs = len(r)
1990 1992 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1991 1993 " rawsize totalsize compression heads\n")
1992 1994 ts = 0
1993 1995 heads = set()
1994 1996 for rev in xrange(numrevs):
1995 1997 dbase = r.deltaparent(rev)
1996 1998 if dbase == -1:
1997 1999 dbase = rev
1998 2000 cbase = r.chainbase(rev)
1999 2001 p1, p2 = r.parentrevs(rev)
2000 2002 rs = r.rawsize(rev)
2001 2003 ts = ts + rs
2002 2004 heads -= set(r.parentrevs(rev))
2003 2005 heads.add(rev)
2004 2006 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2005 2007 (rev, p1, p2, r.start(rev), r.end(rev),
2006 2008 r.start(dbase), r.start(cbase),
2007 2009 r.start(p1), r.start(p2),
2008 2010 rs, ts, ts / r.end(rev), len(heads)))
2009 2011 return 0
2010 2012
2011 2013 v = r.version
2012 2014 format = v & 0xFFFF
2013 2015 flags = []
2014 2016 gdelta = False
2015 2017 if v & revlog.REVLOGNGINLINEDATA:
2016 2018 flags.append('inline')
2017 2019 if v & revlog.REVLOGGENERALDELTA:
2018 2020 gdelta = True
2019 2021 flags.append('generaldelta')
2020 2022 if not flags:
2021 2023 flags = ['(none)']
2022 2024
2023 2025 nummerges = 0
2024 2026 numfull = 0
2025 2027 numprev = 0
2026 2028 nump1 = 0
2027 2029 nump2 = 0
2028 2030 numother = 0
2029 2031 nump1prev = 0
2030 2032 nump2prev = 0
2031 2033 chainlengths = []
2032 2034
2033 2035 datasize = [None, 0, 0L]
2034 2036 fullsize = [None, 0, 0L]
2035 2037 deltasize = [None, 0, 0L]
2036 2038
2037 2039 def addsize(size, l):
2038 2040 if l[0] is None or size < l[0]:
2039 2041 l[0] = size
2040 2042 if size > l[1]:
2041 2043 l[1] = size
2042 2044 l[2] += size
2043 2045
2044 2046 numrevs = len(r)
2045 2047 for rev in xrange(numrevs):
2046 2048 p1, p2 = r.parentrevs(rev)
2047 2049 delta = r.deltaparent(rev)
2048 2050 if format > 0:
2049 2051 addsize(r.rawsize(rev), datasize)
2050 2052 if p2 != nullrev:
2051 2053 nummerges += 1
2052 2054 size = r.length(rev)
2053 2055 if delta == nullrev:
2054 2056 chainlengths.append(0)
2055 2057 numfull += 1
2056 2058 addsize(size, fullsize)
2057 2059 else:
2058 2060 chainlengths.append(chainlengths[delta] + 1)
2059 2061 addsize(size, deltasize)
2060 2062 if delta == rev - 1:
2061 2063 numprev += 1
2062 2064 if delta == p1:
2063 2065 nump1prev += 1
2064 2066 elif delta == p2:
2065 2067 nump2prev += 1
2066 2068 elif delta == p1:
2067 2069 nump1 += 1
2068 2070 elif delta == p2:
2069 2071 nump2 += 1
2070 2072 elif delta != nullrev:
2071 2073 numother += 1
2072 2074
2073 2075 numdeltas = numrevs - numfull
2074 2076 numoprev = numprev - nump1prev - nump2prev
2075 2077 totalrawsize = datasize[2]
2076 2078 datasize[2] /= numrevs
2077 2079 fulltotal = fullsize[2]
2078 2080 fullsize[2] /= numfull
2079 2081 deltatotal = deltasize[2]
2080 2082 deltasize[2] /= numrevs - numfull
2081 2083 totalsize = fulltotal + deltatotal
2082 2084 avgchainlen = sum(chainlengths) / numrevs
2083 2085 compratio = totalrawsize / totalsize
2084 2086
2085 2087 basedfmtstr = '%%%dd\n'
2086 2088 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2087 2089
2088 2090 def dfmtstr(max):
2089 2091 return basedfmtstr % len(str(max))
2090 2092 def pcfmtstr(max, padding=0):
2091 2093 return basepcfmtstr % (len(str(max)), ' ' * padding)
2092 2094
2093 2095 def pcfmt(value, total):
2094 2096 return (value, 100 * float(value) / total)
2095 2097
2096 2098 ui.write('format : %d\n' % format)
2097 2099 ui.write('flags : %s\n' % ', '.join(flags))
2098 2100
2099 2101 ui.write('\n')
2100 2102 fmt = pcfmtstr(totalsize)
2101 2103 fmt2 = dfmtstr(totalsize)
2102 2104 ui.write('revisions : ' + fmt2 % numrevs)
2103 2105 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2104 2106 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2105 2107 ui.write('revisions : ' + fmt2 % numrevs)
2106 2108 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2107 2109 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2108 2110 ui.write('revision size : ' + fmt2 % totalsize)
2109 2111 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2110 2112 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2111 2113
2112 2114 ui.write('\n')
2113 2115 fmt = dfmtstr(max(avgchainlen, compratio))
2114 2116 ui.write('avg chain length : ' + fmt % avgchainlen)
2115 2117 ui.write('compression ratio : ' + fmt % compratio)
2116 2118
2117 2119 if format > 0:
2118 2120 ui.write('\n')
2119 2121 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2120 2122 % tuple(datasize))
2121 2123 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2122 2124 % tuple(fullsize))
2123 2125 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2124 2126 % tuple(deltasize))
2125 2127
2126 2128 if numdeltas > 0:
2127 2129 ui.write('\n')
2128 2130 fmt = pcfmtstr(numdeltas)
2129 2131 fmt2 = pcfmtstr(numdeltas, 4)
2130 2132 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2131 2133 if numprev > 0:
2132 2134 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2133 2135 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2134 2136 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2135 2137 if gdelta:
2136 2138 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2137 2139 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2138 2140 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2139 2141
2140 2142 @command('debugrevspec', [], ('REVSPEC'))
2141 2143 def debugrevspec(ui, repo, expr):
2142 2144 '''parse and apply a revision specification'''
2143 2145 if ui.verbose:
2144 2146 tree = revset.parse(expr)[0]
2145 2147 ui.note(tree, "\n")
2146 2148 newtree = revset.findaliases(ui, tree)
2147 2149 if newtree != tree:
2148 2150 ui.note(newtree, "\n")
2149 2151 func = revset.match(ui, expr)
2150 2152 for c in func(repo, range(len(repo))):
2151 2153 ui.write("%s\n" % c)
2152 2154
2153 2155 @command('debugsetparents', [], _('REV1 [REV2]'))
2154 2156 def debugsetparents(ui, repo, rev1, rev2=None):
2155 2157 """manually set the parents of the current working directory
2156 2158
2157 2159 This is useful for writing repository conversion tools, but should
2158 2160 be used with care.
2159 2161
2160 2162 Returns 0 on success.
2161 2163 """
2162 2164
2163 2165 r1 = scmutil.revsingle(repo, rev1).node()
2164 2166 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2165 2167
2166 2168 wlock = repo.wlock()
2167 2169 try:
2168 2170 repo.dirstate.setparents(r1, r2)
2169 2171 finally:
2170 2172 wlock.release()
2171 2173
2172 2174 @command('debugstate',
2173 2175 [('', 'nodates', None, _('do not display the saved mtime')),
2174 2176 ('', 'datesort', None, _('sort by saved mtime'))],
2175 2177 _('[OPTION]...'))
2176 2178 def debugstate(ui, repo, nodates=None, datesort=None):
2177 2179 """show the contents of the current dirstate"""
2178 2180 timestr = ""
2179 2181 showdate = not nodates
2180 2182 if datesort:
2181 2183 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2182 2184 else:
2183 2185 keyfunc = None # sort by filename
2184 2186 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2185 2187 if showdate:
2186 2188 if ent[3] == -1:
2187 2189 # Pad or slice to locale representation
2188 2190 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2189 2191 time.localtime(0)))
2190 2192 timestr = 'unset'
2191 2193 timestr = (timestr[:locale_len] +
2192 2194 ' ' * (locale_len - len(timestr)))
2193 2195 else:
2194 2196 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2195 2197 time.localtime(ent[3]))
2196 2198 if ent[1] & 020000:
2197 2199 mode = 'lnk'
2198 2200 else:
2199 2201 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2200 2202 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2201 2203 for f in repo.dirstate.copies():
2202 2204 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2203 2205
2204 2206 @command('debugsub',
2205 2207 [('r', 'rev', '',
2206 2208 _('revision to check'), _('REV'))],
2207 2209 _('[-r REV] [REV]'))
2208 2210 def debugsub(ui, repo, rev=None):
2209 2211 ctx = scmutil.revsingle(repo, rev, None)
2210 2212 for k, v in sorted(ctx.substate.items()):
2211 2213 ui.write('path %s\n' % k)
2212 2214 ui.write(' source %s\n' % v[0])
2213 2215 ui.write(' revision %s\n' % v[1])
2214 2216
2215 2217 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2216 2218 def debugwalk(ui, repo, *pats, **opts):
2217 2219 """show how files match on given patterns"""
2218 2220 m = scmutil.match(repo[None], pats, opts)
2219 2221 items = list(repo.walk(m))
2220 2222 if not items:
2221 2223 return
2222 2224 fmt = 'f %%-%ds %%-%ds %%s' % (
2223 2225 max([len(abs) for abs in items]),
2224 2226 max([len(m.rel(abs)) for abs in items]))
2225 2227 for abs in items:
2226 2228 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2227 2229 ui.write("%s\n" % line.rstrip())
2228 2230
2229 2231 @command('debugwireargs',
2230 2232 [('', 'three', '', 'three'),
2231 2233 ('', 'four', '', 'four'),
2232 2234 ('', 'five', '', 'five'),
2233 2235 ] + remoteopts,
2234 2236 _('REPO [OPTIONS]... [ONE [TWO]]'))
2235 2237 def debugwireargs(ui, repopath, *vals, **opts):
2236 2238 repo = hg.peer(ui, opts, repopath)
2237 2239 for opt in remoteopts:
2238 2240 del opts[opt[1]]
2239 2241 args = {}
2240 2242 for k, v in opts.iteritems():
2241 2243 if v:
2242 2244 args[k] = v
2243 2245 # run twice to check that we don't mess up the stream for the next command
2244 2246 res1 = repo.debugwireargs(*vals, **args)
2245 2247 res2 = repo.debugwireargs(*vals, **args)
2246 2248 ui.write("%s\n" % res1)
2247 2249 if res1 != res2:
2248 2250 ui.warn("%s\n" % res2)
2249 2251
2250 2252 @command('^diff',
2251 2253 [('r', 'rev', [], _('revision'), _('REV')),
2252 2254 ('c', 'change', '', _('change made by revision'), _('REV'))
2253 2255 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2254 2256 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2255 2257 def diff(ui, repo, *pats, **opts):
2256 2258 """diff repository (or selected files)
2257 2259
2258 2260 Show differences between revisions for the specified files.
2259 2261
2260 2262 Differences between files are shown using the unified diff format.
2261 2263
2262 2264 .. note::
2263 2265 diff may generate unexpected results for merges, as it will
2264 2266 default to comparing against the working directory's first
2265 2267 parent changeset if no revisions are specified.
2266 2268
2267 2269 When two revision arguments are given, then changes are shown
2268 2270 between those revisions. If only one revision is specified then
2269 2271 that revision is compared to the working directory, and, when no
2270 2272 revisions are specified, the working directory files are compared
2271 2273 to its parent.
2272 2274
2273 2275 Alternatively you can specify -c/--change with a revision to see
2274 2276 the changes in that changeset relative to its first parent.
2275 2277
2276 2278 Without the -a/--text option, diff will avoid generating diffs of
2277 2279 files it detects as binary. With -a, diff will generate a diff
2278 2280 anyway, probably with undesirable results.
2279 2281
2280 2282 Use the -g/--git option to generate diffs in the git extended diff
2281 2283 format. For more information, read :hg:`help diffs`.
2282 2284
2283 2285 .. container:: verbose
2284 2286
2285 2287 Examples:
2286 2288
2287 2289 - compare a file in the current working directory to its parent::
2288 2290
2289 2291 hg diff foo.c
2290 2292
2291 2293 - compare two historical versions of a directory, with rename info::
2292 2294
2293 2295 hg diff --git -r 1.0:1.2 lib/
2294 2296
2295 2297 - get change stats relative to the last change on some date::
2296 2298
2297 2299 hg diff --stat -r "date('may 2')"
2298 2300
2299 2301 - diff all newly-added files that contain a keyword::
2300 2302
2301 2303 hg diff "set:added() and grep(GNU)"
2302 2304
2303 2305 - compare a revision and its parents::
2304 2306
2305 2307 hg diff -c 9353 # compare against first parent
2306 2308 hg diff -r 9353^:9353 # same using revset syntax
2307 2309 hg diff -r 9353^2:9353 # compare against the second parent
2308 2310
2309 2311 Returns 0 on success.
2310 2312 """
2311 2313
2312 2314 revs = opts.get('rev')
2313 2315 change = opts.get('change')
2314 2316 stat = opts.get('stat')
2315 2317 reverse = opts.get('reverse')
2316 2318
2317 2319 if revs and change:
2318 2320 msg = _('cannot specify --rev and --change at the same time')
2319 2321 raise util.Abort(msg)
2320 2322 elif change:
2321 2323 node2 = scmutil.revsingle(repo, change, None).node()
2322 2324 node1 = repo[node2].p1().node()
2323 2325 else:
2324 2326 node1, node2 = scmutil.revpair(repo, revs)
2325 2327
2326 2328 if reverse:
2327 2329 node1, node2 = node2, node1
2328 2330
2329 2331 diffopts = patch.diffopts(ui, opts)
2330 2332 m = scmutil.match(repo[node2], pats, opts)
2331 2333 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2332 2334 listsubrepos=opts.get('subrepos'))
2333 2335
2334 2336 @command('^export',
2335 2337 [('o', 'output', '',
2336 2338 _('print output to file with formatted name'), _('FORMAT')),
2337 2339 ('', 'switch-parent', None, _('diff against the second parent')),
2338 2340 ('r', 'rev', [], _('revisions to export'), _('REV')),
2339 2341 ] + diffopts,
2340 2342 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2341 2343 def export(ui, repo, *changesets, **opts):
2342 2344 """dump the header and diffs for one or more changesets
2343 2345
2344 2346 Print the changeset header and diffs for one or more revisions.
2345 2347
2346 2348 The information shown in the changeset header is: author, date,
2347 2349 branch name (if non-default), changeset hash, parent(s) and commit
2348 2350 comment.
2349 2351
2350 2352 .. note::
2351 2353 export may generate unexpected diff output for merge
2352 2354 changesets, as it will compare the merge changeset against its
2353 2355 first parent only.
2354 2356
2355 2357 Output may be to a file, in which case the name of the file is
2356 2358 given using a format string. The formatting rules are as follows:
2357 2359
2358 2360 :``%%``: literal "%" character
2359 2361 :``%H``: changeset hash (40 hexadecimal digits)
2360 2362 :``%N``: number of patches being generated
2361 2363 :``%R``: changeset revision number
2362 2364 :``%b``: basename of the exporting repository
2363 2365 :``%h``: short-form changeset hash (12 hexadecimal digits)
2364 2366 :``%m``: first line of the commit message (only alphanumeric characters)
2365 2367 :``%n``: zero-padded sequence number, starting at 1
2366 2368 :``%r``: zero-padded changeset revision number
2367 2369
2368 2370 Without the -a/--text option, export will avoid generating diffs
2369 2371 of files it detects as binary. With -a, export will generate a
2370 2372 diff anyway, probably with undesirable results.
2371 2373
2372 2374 Use the -g/--git option to generate diffs in the git extended diff
2373 2375 format. See :hg:`help diffs` for more information.
2374 2376
2375 2377 With the --switch-parent option, the diff will be against the
2376 2378 second parent. It can be useful to review a merge.
2377 2379
2378 2380 .. container:: verbose
2379 2381
2380 2382 Examples:
2381 2383
2382 2384 - use export and import to transplant a bugfix to the current
2383 2385 branch::
2384 2386
2385 2387 hg export -r 9353 | hg import -
2386 2388
2387 2389 - export all the changesets between two revisions to a file with
2388 2390 rename information::
2389 2391
2390 2392 hg export --git -r 123:150 > changes.txt
2391 2393
2392 2394 - split outgoing changes into a series of patches with
2393 2395 descriptive names::
2394 2396
2395 2397 hg export -r "outgoing()" -o "%n-%m.patch"
2396 2398
2397 2399 Returns 0 on success.
2398 2400 """
2399 2401 changesets += tuple(opts.get('rev', []))
2400 2402 if not changesets:
2401 2403 raise util.Abort(_("export requires at least one changeset"))
2402 2404 revs = scmutil.revrange(repo, changesets)
2403 2405 if len(revs) > 1:
2404 2406 ui.note(_('exporting patches:\n'))
2405 2407 else:
2406 2408 ui.note(_('exporting patch:\n'))
2407 2409 cmdutil.export(repo, revs, template=opts.get('output'),
2408 2410 switch_parent=opts.get('switch_parent'),
2409 2411 opts=patch.diffopts(ui, opts))
2410 2412
2411 2413 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2412 2414 def forget(ui, repo, *pats, **opts):
2413 2415 """forget the specified files on the next commit
2414 2416
2415 2417 Mark the specified files so they will no longer be tracked
2416 2418 after the next commit.
2417 2419
2418 2420 This only removes files from the current branch, not from the
2419 2421 entire project history, and it does not delete them from the
2420 2422 working directory.
2421 2423
2422 2424 To undo a forget before the next commit, see :hg:`add`.
2423 2425
2424 2426 .. container:: verbose
2425 2427
2426 2428 Examples:
2427 2429
2428 2430 - forget newly-added binary files::
2429 2431
2430 2432 hg forget "set:added() and binary()"
2431 2433
2432 2434 - forget files that would be excluded by .hgignore::
2433 2435
2434 2436 hg forget "set:hgignore()"
2435 2437
2436 2438 Returns 0 on success.
2437 2439 """
2438 2440
2439 2441 if not pats:
2440 2442 raise util.Abort(_('no files specified'))
2441 2443
2442 2444 wctx = repo[None]
2443 2445 m = scmutil.match(wctx, pats, opts)
2444 2446 s = repo.status(match=m, clean=True)
2445 2447 forget = sorted(s[0] + s[1] + s[3] + s[6])
2446 2448 subforget = {}
2447 2449 errs = 0
2448 2450
2449 2451 for subpath in wctx.substate:
2450 2452 sub = wctx.sub(subpath)
2451 2453 try:
2452 2454 submatch = matchmod.narrowmatcher(subpath, m)
2453 2455 for fsub in sub.walk(submatch):
2454 2456 if submatch.exact(fsub):
2455 2457 subforget[subpath + '/' + fsub] = (fsub, sub)
2456 2458 except error.LookupError:
2457 2459 ui.status(_("skipping missing subrepository: %s\n") % subpath)
2458 2460
2459 2461 for f in m.files():
2460 2462 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2461 2463 if f not in subforget:
2462 2464 if os.path.exists(m.rel(f)):
2463 2465 ui.warn(_('not removing %s: file is already untracked\n')
2464 2466 % m.rel(f))
2465 2467 errs = 1
2466 2468
2467 2469 for f in forget:
2468 2470 if ui.verbose or not m.exact(f):
2469 2471 ui.status(_('removing %s\n') % m.rel(f))
2470 2472
2471 2473 if ui.verbose:
2472 2474 for f in sorted(subforget.keys()):
2473 2475 ui.status(_('removing %s\n') % m.rel(f))
2474 2476
2475 2477 wctx.forget(forget)
2476 2478
2477 2479 for f in sorted(subforget.keys()):
2478 2480 fsub, sub = subforget[f]
2479 2481 sub.forget([fsub])
2480 2482
2481 2483 return errs
2482 2484
2483 2485 @command(
2484 2486 'graft',
2485 2487 [('c', 'continue', False, _('resume interrupted graft')),
2486 2488 ('e', 'edit', False, _('invoke editor on commit messages')),
2487 2489 ('D', 'currentdate', False,
2488 2490 _('record the current date as commit date')),
2489 2491 ('U', 'currentuser', False,
2490 2492 _('record the current user as committer'), _('DATE'))]
2491 2493 + commitopts2 + mergetoolopts,
2492 2494 _('[OPTION]... REVISION...'))
2493 2495 def graft(ui, repo, *revs, **opts):
2494 2496 '''copy changes from other branches onto the current branch
2495 2497
2496 2498 This command uses Mercurial's merge logic to copy individual
2497 2499 changes from other branches without merging branches in the
2498 2500 history graph. This is sometimes known as 'backporting' or
2499 2501 'cherry-picking'. By default, graft will copy user, date, and
2500 2502 description from the source changesets.
2501 2503
2502 2504 Changesets that are ancestors of the current revision, that have
2503 2505 already been grafted, or that are merges will be skipped.
2504 2506
2505 2507 If a graft merge results in conflicts, the graft process is
2506 2508 aborted so that the current merge can be manually resolved. Once
2507 2509 all conflicts are addressed, the graft process can be continued
2508 2510 with the -c/--continue option.
2509 2511
2510 2512 .. note::
2511 2513 The -c/--continue option does not reapply earlier options.
2512 2514
2513 2515 .. container:: verbose
2514 2516
2515 2517 Examples:
2516 2518
2517 2519 - copy a single change to the stable branch and edit its description::
2518 2520
2519 2521 hg update stable
2520 2522 hg graft --edit 9393
2521 2523
2522 2524 - graft a range of changesets with one exception, updating dates::
2523 2525
2524 2526 hg graft -D "2085::2093 and not 2091"
2525 2527
2526 2528 - continue a graft after resolving conflicts::
2527 2529
2528 2530 hg graft -c
2529 2531
2530 2532 - show the source of a grafted changeset::
2531 2533
2532 2534 hg log --debug -r tip
2533 2535
2534 2536 Returns 0 on successful completion.
2535 2537 '''
2536 2538
2537 2539 if not opts.get('user') and opts.get('currentuser'):
2538 2540 opts['user'] = ui.username()
2539 2541 if not opts.get('date') and opts.get('currentdate'):
2540 2542 opts['date'] = "%d %d" % util.makedate()
2541 2543
2542 2544 editor = None
2543 2545 if opts.get('edit'):
2544 2546 editor = cmdutil.commitforceeditor
2545 2547
2546 2548 cont = False
2547 2549 if opts['continue']:
2548 2550 cont = True
2549 2551 if revs:
2550 2552 raise util.Abort(_("can't specify --continue and revisions"))
2551 2553 # read in unfinished revisions
2552 2554 try:
2553 2555 nodes = repo.opener.read('graftstate').splitlines()
2554 2556 revs = [repo[node].rev() for node in nodes]
2555 2557 except IOError, inst:
2556 2558 if inst.errno != errno.ENOENT:
2557 2559 raise
2558 2560 raise util.Abort(_("no graft state found, can't continue"))
2559 2561 else:
2560 2562 cmdutil.bailifchanged(repo)
2561 2563 if not revs:
2562 2564 raise util.Abort(_('no revisions specified'))
2563 2565 revs = scmutil.revrange(repo, revs)
2564 2566
2565 2567 # check for merges
2566 2568 for rev in repo.revs('%ld and merge()', revs):
2567 2569 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2568 2570 revs.remove(rev)
2569 2571 if not revs:
2570 2572 return -1
2571 2573
2572 2574 # check for ancestors of dest branch
2573 2575 for rev in repo.revs('::. and %ld', revs):
2574 2576 ui.warn(_('skipping ancestor revision %s\n') % rev)
2575 2577 revs.remove(rev)
2576 2578 if not revs:
2577 2579 return -1
2578 2580
2579 2581 # analyze revs for earlier grafts
2580 2582 ids = {}
2581 2583 for ctx in repo.set("%ld", revs):
2582 2584 ids[ctx.hex()] = ctx.rev()
2583 2585 n = ctx.extra().get('source')
2584 2586 if n:
2585 2587 ids[n] = ctx.rev()
2586 2588
2587 2589 # check ancestors for earlier grafts
2588 2590 ui.debug('scanning for duplicate grafts\n')
2589 2591 for ctx in repo.set("::. - ::%ld", revs):
2590 2592 n = ctx.extra().get('source')
2591 2593 if n in ids:
2592 2594 r = repo[n].rev()
2593 2595 if r in revs:
2594 2596 ui.warn(_('skipping already grafted revision %s\n') % r)
2595 2597 revs.remove(r)
2596 2598 elif ids[n] in revs:
2597 2599 ui.warn(_('skipping already grafted revision %s '
2598 2600 '(same origin %d)\n') % (ids[n], r))
2599 2601 revs.remove(ids[n])
2600 2602 elif ctx.hex() in ids:
2601 2603 r = ids[ctx.hex()]
2602 2604 ui.warn(_('skipping already grafted revision %s '
2603 2605 '(was grafted from %d)\n') % (r, ctx.rev()))
2604 2606 revs.remove(r)
2605 2607 if not revs:
2606 2608 return -1
2607 2609
2608 2610 for pos, ctx in enumerate(repo.set("%ld", revs)):
2609 2611 current = repo['.']
2610 2612 ui.status(_('grafting revision %s\n') % ctx.rev())
2611 2613
2612 2614 # we don't merge the first commit when continuing
2613 2615 if not cont:
2614 2616 # perform the graft merge with p1(rev) as 'ancestor'
2615 2617 try:
2616 2618 # ui.forcemerge is an internal variable, do not document
2617 2619 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2618 2620 stats = mergemod.update(repo, ctx.node(), True, True, False,
2619 2621 ctx.p1().node())
2620 2622 finally:
2621 2623 ui.setconfig('ui', 'forcemerge', '')
2622 2624 # drop the second merge parent
2623 2625 repo.dirstate.setparents(current.node(), nullid)
2624 2626 repo.dirstate.write()
2625 2627 # fix up dirstate for copies and renames
2626 2628 cmdutil.duplicatecopies(repo, ctx.rev(), current.node(), nullid)
2627 2629 # report any conflicts
2628 2630 if stats and stats[3] > 0:
2629 2631 # write out state for --continue
2630 2632 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2631 2633 repo.opener.write('graftstate', ''.join(nodelines))
2632 2634 raise util.Abort(
2633 2635 _("unresolved conflicts, can't continue"),
2634 2636 hint=_('use hg resolve and hg graft --continue'))
2635 2637 else:
2636 2638 cont = False
2637 2639
2638 2640 # commit
2639 2641 source = ctx.extra().get('source')
2640 2642 if not source:
2641 2643 source = ctx.hex()
2642 2644 extra = {'source': source}
2643 2645 user = ctx.user()
2644 2646 if opts.get('user'):
2645 2647 user = opts['user']
2646 2648 date = ctx.date()
2647 2649 if opts.get('date'):
2648 2650 date = opts['date']
2649 2651 repo.commit(text=ctx.description(), user=user,
2650 2652 date=date, extra=extra, editor=editor)
2651 2653
2652 2654 # remove state when we complete successfully
2653 2655 if os.path.exists(repo.join('graftstate')):
2654 2656 util.unlinkpath(repo.join('graftstate'))
2655 2657
2656 2658 return 0
2657 2659
2658 2660 @command('grep',
2659 2661 [('0', 'print0', None, _('end fields with NUL')),
2660 2662 ('', 'all', None, _('print all revisions that match')),
2661 2663 ('a', 'text', None, _('treat all files as text')),
2662 2664 ('f', 'follow', None,
2663 2665 _('follow changeset history,'
2664 2666 ' or file history across copies and renames')),
2665 2667 ('i', 'ignore-case', None, _('ignore case when matching')),
2666 2668 ('l', 'files-with-matches', None,
2667 2669 _('print only filenames and revisions that match')),
2668 2670 ('n', 'line-number', None, _('print matching line numbers')),
2669 2671 ('r', 'rev', [],
2670 2672 _('only search files changed within revision range'), _('REV')),
2671 2673 ('u', 'user', None, _('list the author (long with -v)')),
2672 2674 ('d', 'date', None, _('list the date (short with -q)')),
2673 2675 ] + walkopts,
2674 2676 _('[OPTION]... PATTERN [FILE]...'))
2675 2677 def grep(ui, repo, pattern, *pats, **opts):
2676 2678 """search for a pattern in specified files and revisions
2677 2679
2678 2680 Search revisions of files for a regular expression.
2679 2681
2680 2682 This command behaves differently than Unix grep. It only accepts
2681 2683 Python/Perl regexps. It searches repository history, not the
2682 2684 working directory. It always prints the revision number in which a
2683 2685 match appears.
2684 2686
2685 2687 By default, grep only prints output for the first revision of a
2686 2688 file in which it finds a match. To get it to print every revision
2687 2689 that contains a change in match status ("-" for a match that
2688 2690 becomes a non-match, or "+" for a non-match that becomes a match),
2689 2691 use the --all flag.
2690 2692
2691 2693 Returns 0 if a match is found, 1 otherwise.
2692 2694 """
2693 2695 reflags = 0
2694 2696 if opts.get('ignore_case'):
2695 2697 reflags |= re.I
2696 2698 try:
2697 2699 regexp = re.compile(pattern, reflags)
2698 2700 except re.error, inst:
2699 2701 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2700 2702 return 1
2701 2703 sep, eol = ':', '\n'
2702 2704 if opts.get('print0'):
2703 2705 sep = eol = '\0'
2704 2706
2705 2707 getfile = util.lrucachefunc(repo.file)
2706 2708
2707 2709 def matchlines(body):
2708 2710 begin = 0
2709 2711 linenum = 0
2710 2712 while True:
2711 2713 match = regexp.search(body, begin)
2712 2714 if not match:
2713 2715 break
2714 2716 mstart, mend = match.span()
2715 2717 linenum += body.count('\n', begin, mstart) + 1
2716 2718 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2717 2719 begin = body.find('\n', mend) + 1 or len(body) + 1
2718 2720 lend = begin - 1
2719 2721 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2720 2722
2721 2723 class linestate(object):
2722 2724 def __init__(self, line, linenum, colstart, colend):
2723 2725 self.line = line
2724 2726 self.linenum = linenum
2725 2727 self.colstart = colstart
2726 2728 self.colend = colend
2727 2729
2728 2730 def __hash__(self):
2729 2731 return hash((self.linenum, self.line))
2730 2732
2731 2733 def __eq__(self, other):
2732 2734 return self.line == other.line
2733 2735
2734 2736 matches = {}
2735 2737 copies = {}
2736 2738 def grepbody(fn, rev, body):
2737 2739 matches[rev].setdefault(fn, [])
2738 2740 m = matches[rev][fn]
2739 2741 for lnum, cstart, cend, line in matchlines(body):
2740 2742 s = linestate(line, lnum, cstart, cend)
2741 2743 m.append(s)
2742 2744
2743 2745 def difflinestates(a, b):
2744 2746 sm = difflib.SequenceMatcher(None, a, b)
2745 2747 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2746 2748 if tag == 'insert':
2747 2749 for i in xrange(blo, bhi):
2748 2750 yield ('+', b[i])
2749 2751 elif tag == 'delete':
2750 2752 for i in xrange(alo, ahi):
2751 2753 yield ('-', a[i])
2752 2754 elif tag == 'replace':
2753 2755 for i in xrange(alo, ahi):
2754 2756 yield ('-', a[i])
2755 2757 for i in xrange(blo, bhi):
2756 2758 yield ('+', b[i])
2757 2759
2758 2760 def display(fn, ctx, pstates, states):
2759 2761 rev = ctx.rev()
2760 2762 datefunc = ui.quiet and util.shortdate or util.datestr
2761 2763 found = False
2762 2764 filerevmatches = {}
2763 2765 def binary():
2764 2766 flog = getfile(fn)
2765 2767 return util.binary(flog.read(ctx.filenode(fn)))
2766 2768
2767 2769 if opts.get('all'):
2768 2770 iter = difflinestates(pstates, states)
2769 2771 else:
2770 2772 iter = [('', l) for l in states]
2771 2773 for change, l in iter:
2772 2774 cols = [fn, str(rev)]
2773 2775 before, match, after = None, None, None
2774 2776 if opts.get('line_number'):
2775 2777 cols.append(str(l.linenum))
2776 2778 if opts.get('all'):
2777 2779 cols.append(change)
2778 2780 if opts.get('user'):
2779 2781 cols.append(ui.shortuser(ctx.user()))
2780 2782 if opts.get('date'):
2781 2783 cols.append(datefunc(ctx.date()))
2782 2784 if opts.get('files_with_matches'):
2783 2785 c = (fn, rev)
2784 2786 if c in filerevmatches:
2785 2787 continue
2786 2788 filerevmatches[c] = 1
2787 2789 else:
2788 2790 before = l.line[:l.colstart]
2789 2791 match = l.line[l.colstart:l.colend]
2790 2792 after = l.line[l.colend:]
2791 2793 ui.write(sep.join(cols))
2792 2794 if before is not None:
2793 2795 if not opts.get('text') and binary():
2794 2796 ui.write(sep + " Binary file matches")
2795 2797 else:
2796 2798 ui.write(sep + before)
2797 2799 ui.write(match, label='grep.match')
2798 2800 ui.write(after)
2799 2801 ui.write(eol)
2800 2802 found = True
2801 2803 return found
2802 2804
2803 2805 skip = {}
2804 2806 revfiles = {}
2805 2807 matchfn = scmutil.match(repo[None], pats, opts)
2806 2808 found = False
2807 2809 follow = opts.get('follow')
2808 2810
2809 2811 def prep(ctx, fns):
2810 2812 rev = ctx.rev()
2811 2813 pctx = ctx.p1()
2812 2814 parent = pctx.rev()
2813 2815 matches.setdefault(rev, {})
2814 2816 matches.setdefault(parent, {})
2815 2817 files = revfiles.setdefault(rev, [])
2816 2818 for fn in fns:
2817 2819 flog = getfile(fn)
2818 2820 try:
2819 2821 fnode = ctx.filenode(fn)
2820 2822 except error.LookupError:
2821 2823 continue
2822 2824
2823 2825 copied = flog.renamed(fnode)
2824 2826 copy = follow and copied and copied[0]
2825 2827 if copy:
2826 2828 copies.setdefault(rev, {})[fn] = copy
2827 2829 if fn in skip:
2828 2830 if copy:
2829 2831 skip[copy] = True
2830 2832 continue
2831 2833 files.append(fn)
2832 2834
2833 2835 if fn not in matches[rev]:
2834 2836 grepbody(fn, rev, flog.read(fnode))
2835 2837
2836 2838 pfn = copy or fn
2837 2839 if pfn not in matches[parent]:
2838 2840 try:
2839 2841 fnode = pctx.filenode(pfn)
2840 2842 grepbody(pfn, parent, flog.read(fnode))
2841 2843 except error.LookupError:
2842 2844 pass
2843 2845
2844 2846 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2845 2847 rev = ctx.rev()
2846 2848 parent = ctx.p1().rev()
2847 2849 for fn in sorted(revfiles.get(rev, [])):
2848 2850 states = matches[rev][fn]
2849 2851 copy = copies.get(rev, {}).get(fn)
2850 2852 if fn in skip:
2851 2853 if copy:
2852 2854 skip[copy] = True
2853 2855 continue
2854 2856 pstates = matches.get(parent, {}).get(copy or fn, [])
2855 2857 if pstates or states:
2856 2858 r = display(fn, ctx, pstates, states)
2857 2859 found = found or r
2858 2860 if r and not opts.get('all'):
2859 2861 skip[fn] = True
2860 2862 if copy:
2861 2863 skip[copy] = True
2862 2864 del matches[rev]
2863 2865 del revfiles[rev]
2864 2866
2865 2867 return not found
2866 2868
2867 2869 @command('heads',
2868 2870 [('r', 'rev', '',
2869 2871 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2870 2872 ('t', 'topo', False, _('show topological heads only')),
2871 2873 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2872 2874 ('c', 'closed', False, _('show normal and closed branch heads')),
2873 2875 ] + templateopts,
2874 2876 _('[-ac] [-r STARTREV] [REV]...'))
2875 2877 def heads(ui, repo, *branchrevs, **opts):
2876 2878 """show current repository heads or show branch heads
2877 2879
2878 2880 With no arguments, show all repository branch heads.
2879 2881
2880 2882 Repository "heads" are changesets with no child changesets. They are
2881 2883 where development generally takes place and are the usual targets
2882 2884 for update and merge operations. Branch heads are changesets that have
2883 2885 no child changeset on the same branch.
2884 2886
2885 2887 If one or more REVs are given, only branch heads on the branches
2886 2888 associated with the specified changesets are shown. This means
2887 2889 that you can use :hg:`heads foo` to see the heads on a branch
2888 2890 named ``foo``.
2889 2891
2890 2892 If -c/--closed is specified, also show branch heads marked closed
2891 2893 (see :hg:`commit --close-branch`).
2892 2894
2893 2895 If STARTREV is specified, only those heads that are descendants of
2894 2896 STARTREV will be displayed.
2895 2897
2896 2898 If -t/--topo is specified, named branch mechanics will be ignored and only
2897 2899 changesets without children will be shown.
2898 2900
2899 2901 Returns 0 if matching heads are found, 1 if not.
2900 2902 """
2901 2903
2902 2904 start = None
2903 2905 if 'rev' in opts:
2904 2906 start = scmutil.revsingle(repo, opts['rev'], None).node()
2905 2907
2906 2908 if opts.get('topo'):
2907 2909 heads = [repo[h] for h in repo.heads(start)]
2908 2910 else:
2909 2911 heads = []
2910 2912 for branch in repo.branchmap():
2911 2913 heads += repo.branchheads(branch, start, opts.get('closed'))
2912 2914 heads = [repo[h] for h in heads]
2913 2915
2914 2916 if branchrevs:
2915 2917 branches = set(repo[br].branch() for br in branchrevs)
2916 2918 heads = [h for h in heads if h.branch() in branches]
2917 2919
2918 2920 if opts.get('active') and branchrevs:
2919 2921 dagheads = repo.heads(start)
2920 2922 heads = [h for h in heads if h.node() in dagheads]
2921 2923
2922 2924 if branchrevs:
2923 2925 haveheads = set(h.branch() for h in heads)
2924 2926 if branches - haveheads:
2925 2927 headless = ', '.join(b for b in branches - haveheads)
2926 2928 msg = _('no open branch heads found on branches %s')
2927 2929 if opts.get('rev'):
2928 2930 msg += _(' (started at %s)' % opts['rev'])
2929 2931 ui.warn((msg + '\n') % headless)
2930 2932
2931 2933 if not heads:
2932 2934 return 1
2933 2935
2934 2936 heads = sorted(heads, key=lambda x: -x.rev())
2935 2937 displayer = cmdutil.show_changeset(ui, repo, opts)
2936 2938 for ctx in heads:
2937 2939 displayer.show(ctx)
2938 2940 displayer.close()
2939 2941
2940 2942 @command('help',
2941 2943 [('e', 'extension', None, _('show only help for extensions')),
2942 2944 ('c', 'command', None, _('show only help for commands'))],
2943 2945 _('[-ec] [TOPIC]'))
2944 2946 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2945 2947 """show help for a given topic or a help overview
2946 2948
2947 2949 With no arguments, print a list of commands with short help messages.
2948 2950
2949 2951 Given a topic, extension, or command name, print help for that
2950 2952 topic.
2951 2953
2952 2954 Returns 0 if successful.
2953 2955 """
2954 2956
2955 2957 textwidth = min(ui.termwidth(), 80) - 2
2956 2958
2957 2959 def optrst(options):
2958 2960 data = []
2959 2961 multioccur = False
2960 2962 for option in options:
2961 2963 if len(option) == 5:
2962 2964 shortopt, longopt, default, desc, optlabel = option
2963 2965 else:
2964 2966 shortopt, longopt, default, desc = option
2965 2967 optlabel = _("VALUE") # default label
2966 2968
2967 2969 if _("DEPRECATED") in desc and not ui.verbose:
2968 2970 continue
2969 2971
2970 2972 so = ''
2971 2973 if shortopt:
2972 2974 so = '-' + shortopt
2973 2975 lo = '--' + longopt
2974 2976 if default:
2975 2977 desc += _(" (default: %s)") % default
2976 2978
2977 2979 if isinstance(default, list):
2978 2980 lo += " %s [+]" % optlabel
2979 2981 multioccur = True
2980 2982 elif (default is not None) and not isinstance(default, bool):
2981 2983 lo += " %s" % optlabel
2982 2984
2983 2985 data.append((so, lo, desc))
2984 2986
2985 2987 rst = minirst.maketable(data, 1)
2986 2988
2987 2989 if multioccur:
2988 2990 rst += _("\n[+] marked option can be specified multiple times\n")
2989 2991
2990 2992 return rst
2991 2993
2992 2994 # list all option lists
2993 2995 def opttext(optlist, width):
2994 2996 rst = ''
2995 2997 if not optlist:
2996 2998 return ''
2997 2999
2998 3000 for title, options in optlist:
2999 3001 rst += '\n%s\n' % title
3000 3002 if options:
3001 3003 rst += "\n"
3002 3004 rst += optrst(options)
3003 3005 rst += '\n'
3004 3006
3005 3007 return '\n' + minirst.format(rst, width)
3006 3008
3007 3009 def addglobalopts(optlist, aliases):
3008 3010 if ui.quiet:
3009 3011 return []
3010 3012
3011 3013 if ui.verbose:
3012 3014 optlist.append((_("global options:"), globalopts))
3013 3015 if name == 'shortlist':
3014 3016 optlist.append((_('use "hg help" for the full list '
3015 3017 'of commands'), ()))
3016 3018 else:
3017 3019 if name == 'shortlist':
3018 3020 msg = _('use "hg help" for the full list of commands '
3019 3021 'or "hg -v" for details')
3020 3022 elif name and not full:
3021 3023 msg = _('use "hg help %s" to show the full help text' % name)
3022 3024 elif aliases:
3023 3025 msg = _('use "hg -v help%s" to show builtin aliases and '
3024 3026 'global options') % (name and " " + name or "")
3025 3027 else:
3026 3028 msg = _('use "hg -v help %s" to show more info') % name
3027 3029 optlist.append((msg, ()))
3028 3030
3029 3031 def helpcmd(name):
3030 3032 try:
3031 3033 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3032 3034 except error.AmbiguousCommand, inst:
3033 3035 # py3k fix: except vars can't be used outside the scope of the
3034 3036 # except block, nor can be used inside a lambda. python issue4617
3035 3037 prefix = inst.args[0]
3036 3038 select = lambda c: c.lstrip('^').startswith(prefix)
3037 3039 helplist(select)
3038 3040 return
3039 3041
3040 3042 # check if it's an invalid alias and display its error if it is
3041 3043 if getattr(entry[0], 'badalias', False):
3042 3044 if not unknowncmd:
3043 3045 entry[0](ui)
3044 3046 return
3045 3047
3046 3048 rst = ""
3047 3049
3048 3050 # synopsis
3049 3051 if len(entry) > 2:
3050 3052 if entry[2].startswith('hg'):
3051 3053 rst += "%s\n" % entry[2]
3052 3054 else:
3053 3055 rst += 'hg %s %s\n' % (aliases[0], entry[2])
3054 3056 else:
3055 3057 rst += 'hg %s\n' % aliases[0]
3056 3058
3057 3059 # aliases
3058 3060 if full and not ui.quiet and len(aliases) > 1:
3059 3061 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
3060 3062
3061 3063 # description
3062 3064 doc = gettext(entry[0].__doc__)
3063 3065 if not doc:
3064 3066 doc = _("(no help text available)")
3065 3067 if util.safehasattr(entry[0], 'definition'): # aliased command
3066 3068 if entry[0].definition.startswith('!'): # shell alias
3067 3069 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3068 3070 else:
3069 3071 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3070 3072 if ui.quiet or not full:
3071 3073 doc = doc.splitlines()[0]
3072 3074 rst += "\n" + doc + "\n"
3073 3075
3074 3076 # check if this command shadows a non-trivial (multi-line)
3075 3077 # extension help text
3076 3078 try:
3077 3079 mod = extensions.find(name)
3078 3080 doc = gettext(mod.__doc__) or ''
3079 3081 if '\n' in doc.strip():
3080 3082 msg = _('use "hg help -e %s" to show help for '
3081 3083 'the %s extension') % (name, name)
3082 3084 rst += '\n%s\n' % msg
3083 3085 except KeyError:
3084 3086 pass
3085 3087
3086 3088 # options
3087 3089 if not ui.quiet and entry[1]:
3088 3090 rst += '\noptions:\n\n'
3089 3091 rst += optrst(entry[1])
3090 3092
3091 3093 if ui.verbose:
3092 3094 rst += '\nglobal options:\n\n'
3093 3095 rst += optrst(globalopts)
3094 3096
3095 3097 keep = ui.verbose and ['verbose'] or []
3096 3098 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
3097 3099 ui.write(formatted)
3098 3100
3099 3101 if not ui.verbose:
3100 3102 if not full:
3101 3103 ui.write(_('\nuse "hg help %s" to show the full help text\n')
3102 3104 % name)
3103 3105 elif not ui.quiet:
3104 3106 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
3105 3107
3106 3108
3107 3109 def helplist(select=None):
3108 3110 # list of commands
3109 3111 if name == "shortlist":
3110 3112 header = _('basic commands:\n\n')
3111 3113 else:
3112 3114 header = _('list of commands:\n\n')
3113 3115
3114 3116 h = {}
3115 3117 cmds = {}
3116 3118 for c, e in table.iteritems():
3117 3119 f = c.split("|", 1)[0]
3118 3120 if select and not select(f):
3119 3121 continue
3120 3122 if (not select and name != 'shortlist' and
3121 3123 e[0].__module__ != __name__):
3122 3124 continue
3123 3125 if name == "shortlist" and not f.startswith("^"):
3124 3126 continue
3125 3127 f = f.lstrip("^")
3126 3128 if not ui.debugflag and f.startswith("debug"):
3127 3129 continue
3128 3130 doc = e[0].__doc__
3129 3131 if doc and 'DEPRECATED' in doc and not ui.verbose:
3130 3132 continue
3131 3133 doc = gettext(doc)
3132 3134 if not doc:
3133 3135 doc = _("(no help text available)")
3134 3136 h[f] = doc.splitlines()[0].rstrip()
3135 3137 cmds[f] = c.lstrip("^")
3136 3138
3137 3139 if not h:
3138 3140 ui.status(_('no commands defined\n'))
3139 3141 return
3140 3142
3141 3143 ui.status(header)
3142 3144 fns = sorted(h)
3143 3145 m = max(map(len, fns))
3144 3146 for f in fns:
3145 3147 if ui.verbose:
3146 3148 commands = cmds[f].replace("|",", ")
3147 3149 ui.write(" %s:\n %s\n"%(commands, h[f]))
3148 3150 else:
3149 3151 ui.write('%s\n' % (util.wrap(h[f], textwidth,
3150 3152 initindent=' %-*s ' % (m, f),
3151 3153 hangindent=' ' * (m + 4))))
3152 3154
3153 3155 if not name:
3154 3156 text = help.listexts(_('enabled extensions:'), extensions.enabled())
3155 3157 if text:
3156 3158 ui.write("\n%s" % minirst.format(text, textwidth))
3157 3159
3158 3160 ui.write(_("\nadditional help topics:\n\n"))
3159 3161 topics = []
3160 3162 for names, header, doc in help.helptable:
3161 3163 topics.append((sorted(names, key=len, reverse=True)[0], header))
3162 3164 topics_len = max([len(s[0]) for s in topics])
3163 3165 for t, desc in topics:
3164 3166 ui.write(" %-*s %s\n" % (topics_len, t, desc))
3165 3167
3166 3168 optlist = []
3167 3169 addglobalopts(optlist, True)
3168 3170 ui.write(opttext(optlist, textwidth))
3169 3171
3170 3172 def helptopic(name):
3171 3173 for names, header, doc in help.helptable:
3172 3174 if name in names:
3173 3175 break
3174 3176 else:
3175 3177 raise error.UnknownCommand(name)
3176 3178
3177 3179 # description
3178 3180 if not doc:
3179 3181 doc = _("(no help text available)")
3180 3182 if util.safehasattr(doc, '__call__'):
3181 3183 doc = doc()
3182 3184
3183 3185 ui.write("%s\n\n" % header)
3184 3186 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
3185 3187 try:
3186 3188 cmdutil.findcmd(name, table)
3187 3189 ui.write(_('\nuse "hg help -c %s" to see help for '
3188 3190 'the %s command\n') % (name, name))
3189 3191 except error.UnknownCommand:
3190 3192 pass
3191 3193
3192 3194 def helpext(name):
3193 3195 try:
3194 3196 mod = extensions.find(name)
3195 3197 doc = gettext(mod.__doc__) or _('no help text available')
3196 3198 except KeyError:
3197 3199 mod = None
3198 3200 doc = extensions.disabledext(name)
3199 3201 if not doc:
3200 3202 raise error.UnknownCommand(name)
3201 3203
3202 3204 if '\n' not in doc:
3203 3205 head, tail = doc, ""
3204 3206 else:
3205 3207 head, tail = doc.split('\n', 1)
3206 3208 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
3207 3209 if tail:
3208 3210 ui.write(minirst.format(tail, textwidth))
3209 3211 ui.status('\n')
3210 3212
3211 3213 if mod:
3212 3214 try:
3213 3215 ct = mod.cmdtable
3214 3216 except AttributeError:
3215 3217 ct = {}
3216 3218 modcmds = set([c.split('|', 1)[0] for c in ct])
3217 3219 helplist(modcmds.__contains__)
3218 3220 else:
3219 3221 ui.write(_('use "hg help extensions" for information on enabling '
3220 3222 'extensions\n'))
3221 3223
3222 3224 def helpextcmd(name):
3223 3225 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3224 3226 doc = gettext(mod.__doc__).splitlines()[0]
3225 3227
3226 3228 msg = help.listexts(_("'%s' is provided by the following "
3227 3229 "extension:") % cmd, {ext: doc}, indent=4)
3228 3230 ui.write(minirst.format(msg, textwidth))
3229 3231 ui.write('\n')
3230 3232 ui.write(_('use "hg help extensions" for information on enabling '
3231 3233 'extensions\n'))
3232 3234
3233 3235 if name and name != 'shortlist':
3234 3236 i = None
3235 3237 if unknowncmd:
3236 3238 queries = (helpextcmd,)
3237 3239 elif opts.get('extension'):
3238 3240 queries = (helpext,)
3239 3241 elif opts.get('command'):
3240 3242 queries = (helpcmd,)
3241 3243 else:
3242 3244 queries = (helptopic, helpcmd, helpext, helpextcmd)
3243 3245 for f in queries:
3244 3246 try:
3245 3247 f(name)
3246 3248 i = None
3247 3249 break
3248 3250 except error.UnknownCommand, inst:
3249 3251 i = inst
3250 3252 if i:
3251 3253 raise i
3252 3254 else:
3253 3255 # program name
3254 3256 ui.status(_("Mercurial Distributed SCM\n"))
3255 3257 ui.status('\n')
3256 3258 helplist()
3257 3259
3258 3260
3259 3261 @command('identify|id',
3260 3262 [('r', 'rev', '',
3261 3263 _('identify the specified revision'), _('REV')),
3262 3264 ('n', 'num', None, _('show local revision number')),
3263 3265 ('i', 'id', None, _('show global revision id')),
3264 3266 ('b', 'branch', None, _('show branch')),
3265 3267 ('t', 'tags', None, _('show tags')),
3266 3268 ('B', 'bookmarks', None, _('show bookmarks')),
3267 3269 ] + remoteopts,
3268 3270 _('[-nibtB] [-r REV] [SOURCE]'))
3269 3271 def identify(ui, repo, source=None, rev=None,
3270 3272 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3271 3273 """identify the working copy or specified revision
3272 3274
3273 3275 Print a summary identifying the repository state at REV using one or
3274 3276 two parent hash identifiers, followed by a "+" if the working
3275 3277 directory has uncommitted changes, the branch name (if not default),
3276 3278 a list of tags, and a list of bookmarks.
3277 3279
3278 3280 When REV is not given, print a summary of the current state of the
3279 3281 repository.
3280 3282
3281 3283 Specifying a path to a repository root or Mercurial bundle will
3282 3284 cause lookup to operate on that repository/bundle.
3283 3285
3284 3286 .. container:: verbose
3285 3287
3286 3288 Examples:
3287 3289
3288 3290 - generate a build identifier for the working directory::
3289 3291
3290 3292 hg id --id > build-id.dat
3291 3293
3292 3294 - find the revision corresponding to a tag::
3293 3295
3294 3296 hg id -n -r 1.3
3295 3297
3296 3298 - check the most recent revision of a remote repository::
3297 3299
3298 3300 hg id -r tip http://selenic.com/hg/
3299 3301
3300 3302 Returns 0 if successful.
3301 3303 """
3302 3304
3303 3305 if not repo and not source:
3304 3306 raise util.Abort(_("there is no Mercurial repository here "
3305 3307 "(.hg not found)"))
3306 3308
3307 3309 hexfunc = ui.debugflag and hex or short
3308 3310 default = not (num or id or branch or tags or bookmarks)
3309 3311 output = []
3310 3312 revs = []
3311 3313
3312 3314 if source:
3313 3315 source, branches = hg.parseurl(ui.expandpath(source))
3314 3316 repo = hg.peer(ui, opts, source)
3315 3317 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3316 3318
3317 3319 if not repo.local():
3318 3320 if num or branch or tags:
3319 3321 raise util.Abort(
3320 3322 _("can't query remote revision number, branch, or tags"))
3321 3323 if not rev and revs:
3322 3324 rev = revs[0]
3323 3325 if not rev:
3324 3326 rev = "tip"
3325 3327
3326 3328 remoterev = repo.lookup(rev)
3327 3329 if default or id:
3328 3330 output = [hexfunc(remoterev)]
3329 3331
3330 3332 def getbms():
3331 3333 bms = []
3332 3334
3333 3335 if 'bookmarks' in repo.listkeys('namespaces'):
3334 3336 hexremoterev = hex(remoterev)
3335 3337 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3336 3338 if bmr == hexremoterev]
3337 3339
3338 3340 return bms
3339 3341
3340 3342 if bookmarks:
3341 3343 output.extend(getbms())
3342 3344 elif default and not ui.quiet:
3343 3345 # multiple bookmarks for a single parent separated by '/'
3344 3346 bm = '/'.join(getbms())
3345 3347 if bm:
3346 3348 output.append(bm)
3347 3349 else:
3348 3350 if not rev:
3349 3351 ctx = repo[None]
3350 3352 parents = ctx.parents()
3351 3353 changed = ""
3352 3354 if default or id or num:
3353 3355 changed = util.any(repo.status()) and "+" or ""
3354 3356 if default or id:
3355 3357 output = ["%s%s" %
3356 3358 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3357 3359 if num:
3358 3360 output.append("%s%s" %
3359 3361 ('+'.join([str(p.rev()) for p in parents]), changed))
3360 3362 else:
3361 3363 ctx = scmutil.revsingle(repo, rev)
3362 3364 if default or id:
3363 3365 output = [hexfunc(ctx.node())]
3364 3366 if num:
3365 3367 output.append(str(ctx.rev()))
3366 3368
3367 3369 if default and not ui.quiet:
3368 3370 b = ctx.branch()
3369 3371 if b != 'default':
3370 3372 output.append("(%s)" % b)
3371 3373
3372 3374 # multiple tags for a single parent separated by '/'
3373 3375 t = '/'.join(ctx.tags())
3374 3376 if t:
3375 3377 output.append(t)
3376 3378
3377 3379 # multiple bookmarks for a single parent separated by '/'
3378 3380 bm = '/'.join(ctx.bookmarks())
3379 3381 if bm:
3380 3382 output.append(bm)
3381 3383 else:
3382 3384 if branch:
3383 3385 output.append(ctx.branch())
3384 3386
3385 3387 if tags:
3386 3388 output.extend(ctx.tags())
3387 3389
3388 3390 if bookmarks:
3389 3391 output.extend(ctx.bookmarks())
3390 3392
3391 3393 ui.write("%s\n" % ' '.join(output))
3392 3394
3393 3395 @command('import|patch',
3394 3396 [('p', 'strip', 1,
3395 3397 _('directory strip option for patch. This has the same '
3396 3398 'meaning as the corresponding patch option'), _('NUM')),
3397 3399 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3398 3400 ('e', 'edit', False, _('invoke editor on commit messages')),
3399 3401 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3400 3402 ('', 'no-commit', None,
3401 3403 _("don't commit, just update the working directory")),
3402 3404 ('', 'bypass', None,
3403 3405 _("apply patch without touching the working directory")),
3404 3406 ('', 'exact', None,
3405 3407 _('apply patch to the nodes from which it was generated')),
3406 3408 ('', 'import-branch', None,
3407 3409 _('use any branch information in patch (implied by --exact)'))] +
3408 3410 commitopts + commitopts2 + similarityopts,
3409 3411 _('[OPTION]... PATCH...'))
3410 3412 def import_(ui, repo, patch1=None, *patches, **opts):
3411 3413 """import an ordered set of patches
3412 3414
3413 3415 Import a list of patches and commit them individually (unless
3414 3416 --no-commit is specified).
3415 3417
3416 3418 If there are outstanding changes in the working directory, import
3417 3419 will abort unless given the -f/--force flag.
3418 3420
3419 3421 You can import a patch straight from a mail message. Even patches
3420 3422 as attachments work (to use the body part, it must have type
3421 3423 text/plain or text/x-patch). From and Subject headers of email
3422 3424 message are used as default committer and commit message. All
3423 3425 text/plain body parts before first diff are added to commit
3424 3426 message.
3425 3427
3426 3428 If the imported patch was generated by :hg:`export`, user and
3427 3429 description from patch override values from message headers and
3428 3430 body. Values given on command line with -m/--message and -u/--user
3429 3431 override these.
3430 3432
3431 3433 If --exact is specified, import will set the working directory to
3432 3434 the parent of each patch before applying it, and will abort if the
3433 3435 resulting changeset has a different ID than the one recorded in
3434 3436 the patch. This may happen due to character set problems or other
3435 3437 deficiencies in the text patch format.
3436 3438
3437 3439 Use --bypass to apply and commit patches directly to the
3438 3440 repository, not touching the working directory. Without --exact,
3439 3441 patches will be applied on top of the working directory parent
3440 3442 revision.
3441 3443
3442 3444 With -s/--similarity, hg will attempt to discover renames and
3443 3445 copies in the patch in the same way as 'addremove'.
3444 3446
3445 3447 To read a patch from standard input, use "-" as the patch name. If
3446 3448 a URL is specified, the patch will be downloaded from it.
3447 3449 See :hg:`help dates` for a list of formats valid for -d/--date.
3448 3450
3449 3451 .. container:: verbose
3450 3452
3451 3453 Examples:
3452 3454
3453 3455 - import a traditional patch from a website and detect renames::
3454 3456
3455 3457 hg import -s 80 http://example.com/bugfix.patch
3456 3458
3457 3459 - import a changeset from an hgweb server::
3458 3460
3459 3461 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3460 3462
3461 3463 - import all the patches in an Unix-style mbox::
3462 3464
3463 3465 hg import incoming-patches.mbox
3464 3466
3465 3467 - attempt to exactly restore an exported changeset (not always
3466 3468 possible)::
3467 3469
3468 3470 hg import --exact proposed-fix.patch
3469 3471
3470 3472 Returns 0 on success.
3471 3473 """
3472 3474
3473 3475 if not patch1:
3474 3476 raise util.Abort(_('need at least one patch to import'))
3475 3477
3476 3478 patches = (patch1,) + patches
3477 3479
3478 3480 date = opts.get('date')
3479 3481 if date:
3480 3482 opts['date'] = util.parsedate(date)
3481 3483
3482 3484 editor = cmdutil.commiteditor
3483 3485 if opts.get('edit'):
3484 3486 editor = cmdutil.commitforceeditor
3485 3487
3486 3488 update = not opts.get('bypass')
3487 3489 if not update and opts.get('no_commit'):
3488 3490 raise util.Abort(_('cannot use --no-commit with --bypass'))
3489 3491 try:
3490 3492 sim = float(opts.get('similarity') or 0)
3491 3493 except ValueError:
3492 3494 raise util.Abort(_('similarity must be a number'))
3493 3495 if sim < 0 or sim > 100:
3494 3496 raise util.Abort(_('similarity must be between 0 and 100'))
3495 3497 if sim and not update:
3496 3498 raise util.Abort(_('cannot use --similarity with --bypass'))
3497 3499
3498 3500 if (opts.get('exact') or not opts.get('force')) and update:
3499 3501 cmdutil.bailifchanged(repo)
3500 3502
3501 3503 base = opts["base"]
3502 3504 strip = opts["strip"]
3503 3505 wlock = lock = tr = None
3504 3506 msgs = []
3505 3507
3506 3508 def checkexact(repo, n, nodeid):
3507 3509 if opts.get('exact') and hex(n) != nodeid:
3508 3510 repo.rollback()
3509 3511 raise util.Abort(_('patch is damaged or loses information'))
3510 3512
3511 3513 def tryone(ui, hunk, parents):
3512 3514 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3513 3515 patch.extract(ui, hunk)
3514 3516
3515 3517 if not tmpname:
3516 3518 return (None, None)
3517 3519 msg = _('applied to working directory')
3518 3520
3519 3521 try:
3520 3522 cmdline_message = cmdutil.logmessage(ui, opts)
3521 3523 if cmdline_message:
3522 3524 # pickup the cmdline msg
3523 3525 message = cmdline_message
3524 3526 elif message:
3525 3527 # pickup the patch msg
3526 3528 message = message.strip()
3527 3529 else:
3528 3530 # launch the editor
3529 3531 message = None
3530 3532 ui.debug('message:\n%s\n' % message)
3531 3533
3532 3534 if len(parents) == 1:
3533 3535 parents.append(repo[nullid])
3534 3536 if opts.get('exact'):
3535 3537 if not nodeid or not p1:
3536 3538 raise util.Abort(_('not a Mercurial patch'))
3537 3539 p1 = repo[p1]
3538 3540 p2 = repo[p2 or nullid]
3539 3541 elif p2:
3540 3542 try:
3541 3543 p1 = repo[p1]
3542 3544 p2 = repo[p2]
3543 3545 # Without any options, consider p2 only if the
3544 3546 # patch is being applied on top of the recorded
3545 3547 # first parent.
3546 3548 if p1 != parents[0]:
3547 3549 p1 = parents[0]
3548 3550 p2 = repo[nullid]
3549 3551 except error.RepoError:
3550 3552 p1, p2 = parents
3551 3553 else:
3552 3554 p1, p2 = parents
3553 3555
3554 3556 n = None
3555 3557 if update:
3556 3558 if p1 != parents[0]:
3557 3559 hg.clean(repo, p1.node())
3558 3560 if p2 != parents[1]:
3559 3561 repo.dirstate.setparents(p1.node(), p2.node())
3560 3562
3561 3563 if opts.get('exact') or opts.get('import_branch'):
3562 3564 repo.dirstate.setbranch(branch or 'default')
3563 3565
3564 3566 files = set()
3565 3567 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3566 3568 eolmode=None, similarity=sim / 100.0)
3567 3569 files = list(files)
3568 3570 if opts.get('no_commit'):
3569 3571 if message:
3570 3572 msgs.append(message)
3571 3573 else:
3572 3574 if opts.get('exact') or p2:
3573 3575 # If you got here, you either use --force and know what
3574 3576 # you are doing or used --exact or a merge patch while
3575 3577 # being updated to its first parent.
3576 3578 m = None
3577 3579 else:
3578 3580 m = scmutil.matchfiles(repo, files or [])
3579 3581 n = repo.commit(message, opts.get('user') or user,
3580 3582 opts.get('date') or date, match=m,
3581 3583 editor=editor)
3582 3584 checkexact(repo, n, nodeid)
3583 3585 else:
3584 3586 if opts.get('exact') or opts.get('import_branch'):
3585 3587 branch = branch or 'default'
3586 3588 else:
3587 3589 branch = p1.branch()
3588 3590 store = patch.filestore()
3589 3591 try:
3590 3592 files = set()
3591 3593 try:
3592 3594 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3593 3595 files, eolmode=None)
3594 3596 except patch.PatchError, e:
3595 3597 raise util.Abort(str(e))
3596 3598 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3597 3599 message,
3598 3600 opts.get('user') or user,
3599 3601 opts.get('date') or date,
3600 3602 branch, files, store,
3601 3603 editor=cmdutil.commiteditor)
3602 3604 repo.savecommitmessage(memctx.description())
3603 3605 n = memctx.commit()
3604 3606 checkexact(repo, n, nodeid)
3605 3607 finally:
3606 3608 store.close()
3607 3609 if n:
3608 3610 # i18n: refers to a short changeset id
3609 3611 msg = _('created %s') % short(n)
3610 3612 return (msg, n)
3611 3613 finally:
3612 3614 os.unlink(tmpname)
3613 3615
3614 3616 try:
3615 3617 try:
3616 3618 wlock = repo.wlock()
3617 3619 lock = repo.lock()
3618 3620 tr = repo.transaction('import')
3619 3621 parents = repo.parents()
3620 3622 for patchurl in patches:
3621 3623 if patchurl == '-':
3622 3624 ui.status(_('applying patch from stdin\n'))
3623 3625 patchfile = ui.fin
3624 3626 patchurl = 'stdin' # for error message
3625 3627 else:
3626 3628 patchurl = os.path.join(base, patchurl)
3627 3629 ui.status(_('applying %s\n') % patchurl)
3628 3630 patchfile = url.open(ui, patchurl)
3629 3631
3630 3632 haspatch = False
3631 3633 for hunk in patch.split(patchfile):
3632 3634 (msg, node) = tryone(ui, hunk, parents)
3633 3635 if msg:
3634 3636 haspatch = True
3635 3637 ui.note(msg + '\n')
3636 3638 if update or opts.get('exact'):
3637 3639 parents = repo.parents()
3638 3640 else:
3639 3641 parents = [repo[node]]
3640 3642
3641 3643 if not haspatch:
3642 3644 raise util.Abort(_('%s: no diffs found') % patchurl)
3643 3645
3644 3646 tr.close()
3645 3647 if msgs:
3646 3648 repo.savecommitmessage('\n* * *\n'.join(msgs))
3647 3649 except:
3648 3650 # wlock.release() indirectly calls dirstate.write(): since
3649 3651 # we're crashing, we do not want to change the working dir
3650 3652 # parent after all, so make sure it writes nothing
3651 3653 repo.dirstate.invalidate()
3652 3654 raise
3653 3655 finally:
3654 3656 if tr:
3655 3657 tr.release()
3656 3658 release(lock, wlock)
3657 3659
3658 3660 @command('incoming|in',
3659 3661 [('f', 'force', None,
3660 3662 _('run even if remote repository is unrelated')),
3661 3663 ('n', 'newest-first', None, _('show newest record first')),
3662 3664 ('', 'bundle', '',
3663 3665 _('file to store the bundles into'), _('FILE')),
3664 3666 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3665 3667 ('B', 'bookmarks', False, _("compare bookmarks")),
3666 3668 ('b', 'branch', [],
3667 3669 _('a specific branch you would like to pull'), _('BRANCH')),
3668 3670 ] + logopts + remoteopts + subrepoopts,
3669 3671 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3670 3672 def incoming(ui, repo, source="default", **opts):
3671 3673 """show new changesets found in source
3672 3674
3673 3675 Show new changesets found in the specified path/URL or the default
3674 3676 pull location. These are the changesets that would have been pulled
3675 3677 if a pull at the time you issued this command.
3676 3678
3677 3679 For remote repository, using --bundle avoids downloading the
3678 3680 changesets twice if the incoming is followed by a pull.
3679 3681
3680 3682 See pull for valid source format details.
3681 3683
3682 3684 Returns 0 if there are incoming changes, 1 otherwise.
3683 3685 """
3684 3686 if opts.get('bundle') and opts.get('subrepos'):
3685 3687 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3686 3688
3687 3689 if opts.get('bookmarks'):
3688 3690 source, branches = hg.parseurl(ui.expandpath(source),
3689 3691 opts.get('branch'))
3690 3692 other = hg.peer(repo, opts, source)
3691 3693 if 'bookmarks' not in other.listkeys('namespaces'):
3692 3694 ui.warn(_("remote doesn't support bookmarks\n"))
3693 3695 return 0
3694 3696 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3695 3697 return bookmarks.diff(ui, repo, other)
3696 3698
3697 3699 repo._subtoppath = ui.expandpath(source)
3698 3700 try:
3699 3701 return hg.incoming(ui, repo, source, opts)
3700 3702 finally:
3701 3703 del repo._subtoppath
3702 3704
3703 3705
3704 3706 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3705 3707 def init(ui, dest=".", **opts):
3706 3708 """create a new repository in the given directory
3707 3709
3708 3710 Initialize a new repository in the given directory. If the given
3709 3711 directory does not exist, it will be created.
3710 3712
3711 3713 If no directory is given, the current directory is used.
3712 3714
3713 3715 It is possible to specify an ``ssh://`` URL as the destination.
3714 3716 See :hg:`help urls` for more information.
3715 3717
3716 3718 Returns 0 on success.
3717 3719 """
3718 3720 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3719 3721
3720 3722 @command('locate',
3721 3723 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3722 3724 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3723 3725 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3724 3726 ] + walkopts,
3725 3727 _('[OPTION]... [PATTERN]...'))
3726 3728 def locate(ui, repo, *pats, **opts):
3727 3729 """locate files matching specific patterns
3728 3730
3729 3731 Print files under Mercurial control in the working directory whose
3730 3732 names match the given patterns.
3731 3733
3732 3734 By default, this command searches all directories in the working
3733 3735 directory. To search just the current directory and its
3734 3736 subdirectories, use "--include .".
3735 3737
3736 3738 If no patterns are given to match, this command prints the names
3737 3739 of all files under Mercurial control in the working directory.
3738 3740
3739 3741 If you want to feed the output of this command into the "xargs"
3740 3742 command, use the -0 option to both this command and "xargs". This
3741 3743 will avoid the problem of "xargs" treating single filenames that
3742 3744 contain whitespace as multiple filenames.
3743 3745
3744 3746 Returns 0 if a match is found, 1 otherwise.
3745 3747 """
3746 3748 end = opts.get('print0') and '\0' or '\n'
3747 3749 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3748 3750
3749 3751 ret = 1
3750 3752 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3751 3753 m.bad = lambda x, y: False
3752 3754 for abs in repo[rev].walk(m):
3753 3755 if not rev and abs not in repo.dirstate:
3754 3756 continue
3755 3757 if opts.get('fullpath'):
3756 3758 ui.write(repo.wjoin(abs), end)
3757 3759 else:
3758 3760 ui.write(((pats and m.rel(abs)) or abs), end)
3759 3761 ret = 0
3760 3762
3761 3763 return ret
3762 3764
3763 3765 @command('^log|history',
3764 3766 [('f', 'follow', None,
3765 3767 _('follow changeset history, or file history across copies and renames')),
3766 3768 ('', 'follow-first', None,
3767 3769 _('only follow the first parent of merge changesets (DEPRECATED)')),
3768 3770 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3769 3771 ('C', 'copies', None, _('show copied files')),
3770 3772 ('k', 'keyword', [],
3771 3773 _('do case-insensitive search for a given text'), _('TEXT')),
3772 3774 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3773 3775 ('', 'removed', None, _('include revisions where files were removed')),
3774 3776 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3775 3777 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3776 3778 ('', 'only-branch', [],
3777 3779 _('show only changesets within the given named branch (DEPRECATED)'),
3778 3780 _('BRANCH')),
3779 3781 ('b', 'branch', [],
3780 3782 _('show changesets within the given named branch'), _('BRANCH')),
3781 3783 ('P', 'prune', [],
3782 3784 _('do not display revision or any of its ancestors'), _('REV')),
3783 3785 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3784 3786 ] + logopts + walkopts,
3785 3787 _('[OPTION]... [FILE]'))
3786 3788 def log(ui, repo, *pats, **opts):
3787 3789 """show revision history of entire repository or files
3788 3790
3789 3791 Print the revision history of the specified files or the entire
3790 3792 project.
3791 3793
3792 3794 If no revision range is specified, the default is ``tip:0`` unless
3793 3795 --follow is set, in which case the working directory parent is
3794 3796 used as the starting revision.
3795 3797
3796 3798 File history is shown without following rename or copy history of
3797 3799 files. Use -f/--follow with a filename to follow history across
3798 3800 renames and copies. --follow without a filename will only show
3799 3801 ancestors or descendants of the starting revision.
3800 3802
3801 3803 By default this command prints revision number and changeset id,
3802 3804 tags, non-trivial parents, user, date and time, and a summary for
3803 3805 each commit. When the -v/--verbose switch is used, the list of
3804 3806 changed files and full commit message are shown.
3805 3807
3806 3808 .. note::
3807 3809 log -p/--patch may generate unexpected diff output for merge
3808 3810 changesets, as it will only compare the merge changeset against
3809 3811 its first parent. Also, only files different from BOTH parents
3810 3812 will appear in files:.
3811 3813
3812 3814 .. note::
3813 3815 for performance reasons, log FILE may omit duplicate changes
3814 3816 made on branches and will not show deletions. To see all
3815 3817 changes including duplicates and deletions, use the --removed
3816 3818 switch.
3817 3819
3818 3820 .. container:: verbose
3819 3821
3820 3822 Some examples:
3821 3823
3822 3824 - changesets with full descriptions and file lists::
3823 3825
3824 3826 hg log -v
3825 3827
3826 3828 - changesets ancestral to the working directory::
3827 3829
3828 3830 hg log -f
3829 3831
3830 3832 - last 10 commits on the current branch::
3831 3833
3832 3834 hg log -l 10 -b .
3833 3835
3834 3836 - changesets showing all modifications of a file, including removals::
3835 3837
3836 3838 hg log --removed file.c
3837 3839
3838 3840 - all changesets that touch a directory, with diffs, excluding merges::
3839 3841
3840 3842 hg log -Mp lib/
3841 3843
3842 3844 - all revision numbers that match a keyword::
3843 3845
3844 3846 hg log -k bug --template "{rev}\\n"
3845 3847
3846 3848 - check if a given changeset is included is a tagged release::
3847 3849
3848 3850 hg log -r "a21ccf and ancestor(1.9)"
3849 3851
3850 3852 - find all changesets by some user in a date range::
3851 3853
3852 3854 hg log -k alice -d "may 2008 to jul 2008"
3853 3855
3854 3856 - summary of all changesets after the last tag::
3855 3857
3856 3858 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3857 3859
3858 3860 See :hg:`help dates` for a list of formats valid for -d/--date.
3859 3861
3860 3862 See :hg:`help revisions` and :hg:`help revsets` for more about
3861 3863 specifying revisions.
3862 3864
3863 3865 Returns 0 on success.
3864 3866 """
3865 3867
3866 3868 matchfn = scmutil.match(repo[None], pats, opts)
3867 3869 limit = cmdutil.loglimit(opts)
3868 3870 count = 0
3869 3871
3870 3872 endrev = None
3871 3873 if opts.get('copies') and opts.get('rev'):
3872 3874 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3873 3875
3874 3876 df = False
3875 3877 if opts["date"]:
3876 3878 df = util.matchdate(opts["date"])
3877 3879
3878 3880 branches = opts.get('branch', []) + opts.get('only_branch', [])
3879 3881 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3880 3882
3881 3883 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3882 3884 def prep(ctx, fns):
3883 3885 rev = ctx.rev()
3884 3886 parents = [p for p in repo.changelog.parentrevs(rev)
3885 3887 if p != nullrev]
3886 3888 if opts.get('no_merges') and len(parents) == 2:
3887 3889 return
3888 3890 if opts.get('only_merges') and len(parents) != 2:
3889 3891 return
3890 3892 if opts.get('branch') and ctx.branch() not in opts['branch']:
3891 3893 return
3892 3894 if not opts.get('hidden') and ctx.hidden():
3893 3895 return
3894 3896 if df and not df(ctx.date()[0]):
3895 3897 return
3896 3898 if opts['user'] and not [k for k in opts['user']
3897 3899 if k.lower() in ctx.user().lower()]:
3898 3900 return
3899 3901 if opts.get('keyword'):
3900 3902 for k in [kw.lower() for kw in opts['keyword']]:
3901 3903 if (k in ctx.user().lower() or
3902 3904 k in ctx.description().lower() or
3903 3905 k in " ".join(ctx.files()).lower()):
3904 3906 break
3905 3907 else:
3906 3908 return
3907 3909
3908 3910 copies = None
3909 3911 if opts.get('copies') and rev:
3910 3912 copies = []
3911 3913 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3912 3914 for fn in ctx.files():
3913 3915 rename = getrenamed(fn, rev)
3914 3916 if rename:
3915 3917 copies.append((fn, rename[0]))
3916 3918
3917 3919 revmatchfn = None
3918 3920 if opts.get('patch') or opts.get('stat'):
3919 3921 if opts.get('follow') or opts.get('follow_first'):
3920 3922 # note: this might be wrong when following through merges
3921 3923 revmatchfn = scmutil.match(repo[None], fns, default='path')
3922 3924 else:
3923 3925 revmatchfn = matchfn
3924 3926
3925 3927 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3926 3928
3927 3929 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3928 3930 if count == limit:
3929 3931 break
3930 3932 if displayer.flush(ctx.rev()):
3931 3933 count += 1
3932 3934 displayer.close()
3933 3935
3934 3936 @command('manifest',
3935 3937 [('r', 'rev', '', _('revision to display'), _('REV')),
3936 3938 ('', 'all', False, _("list files from all revisions"))],
3937 3939 _('[-r REV]'))
3938 3940 def manifest(ui, repo, node=None, rev=None, **opts):
3939 3941 """output the current or given revision of the project manifest
3940 3942
3941 3943 Print a list of version controlled files for the given revision.
3942 3944 If no revision is given, the first parent of the working directory
3943 3945 is used, or the null revision if no revision is checked out.
3944 3946
3945 3947 With -v, print file permissions, symlink and executable bits.
3946 3948 With --debug, print file revision hashes.
3947 3949
3948 3950 If option --all is specified, the list of all files from all revisions
3949 3951 is printed. This includes deleted and renamed files.
3950 3952
3951 3953 Returns 0 on success.
3952 3954 """
3953 3955 if opts.get('all'):
3954 3956 if rev or node:
3955 3957 raise util.Abort(_("can't specify a revision with --all"))
3956 3958
3957 3959 res = []
3958 3960 prefix = "data/"
3959 3961 suffix = ".i"
3960 3962 plen = len(prefix)
3961 3963 slen = len(suffix)
3962 3964 lock = repo.lock()
3963 3965 try:
3964 3966 for fn, b, size in repo.store.datafiles():
3965 3967 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3966 3968 res.append(fn[plen:-slen])
3967 3969 finally:
3968 3970 lock.release()
3969 3971 for f in sorted(res):
3970 3972 ui.write("%s\n" % f)
3971 3973 return
3972 3974
3973 3975 if rev and node:
3974 3976 raise util.Abort(_("please specify just one revision"))
3975 3977
3976 3978 if not node:
3977 3979 node = rev
3978 3980
3979 3981 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3980 3982 ctx = scmutil.revsingle(repo, node)
3981 3983 for f in ctx:
3982 3984 if ui.debugflag:
3983 3985 ui.write("%40s " % hex(ctx.manifest()[f]))
3984 3986 if ui.verbose:
3985 3987 ui.write(decor[ctx.flags(f)])
3986 3988 ui.write("%s\n" % f)
3987 3989
3988 3990 @command('^merge',
3989 3991 [('f', 'force', None, _('force a merge with outstanding changes')),
3990 3992 ('r', 'rev', '', _('revision to merge'), _('REV')),
3991 3993 ('P', 'preview', None,
3992 3994 _('review revisions to merge (no merge is performed)'))
3993 3995 ] + mergetoolopts,
3994 3996 _('[-P] [-f] [[-r] REV]'))
3995 3997 def merge(ui, repo, node=None, **opts):
3996 3998 """merge working directory with another revision
3997 3999
3998 4000 The current working directory is updated with all changes made in
3999 4001 the requested revision since the last common predecessor revision.
4000 4002
4001 4003 Files that changed between either parent are marked as changed for
4002 4004 the next commit and a commit must be performed before any further
4003 4005 updates to the repository are allowed. The next commit will have
4004 4006 two parents.
4005 4007
4006 4008 ``--tool`` can be used to specify the merge tool used for file
4007 4009 merges. It overrides the HGMERGE environment variable and your
4008 4010 configuration files. See :hg:`help merge-tools` for options.
4009 4011
4010 4012 If no revision is specified, the working directory's parent is a
4011 4013 head revision, and the current branch contains exactly one other
4012 4014 head, the other head is merged with by default. Otherwise, an
4013 4015 explicit revision with which to merge with must be provided.
4014 4016
4015 4017 :hg:`resolve` must be used to resolve unresolved files.
4016 4018
4017 4019 To undo an uncommitted merge, use :hg:`update --clean .` which
4018 4020 will check out a clean copy of the original merge parent, losing
4019 4021 all changes.
4020 4022
4021 4023 Returns 0 on success, 1 if there are unresolved files.
4022 4024 """
4023 4025
4024 4026 if opts.get('rev') and node:
4025 4027 raise util.Abort(_("please specify just one revision"))
4026 4028 if not node:
4027 4029 node = opts.get('rev')
4028 4030
4029 4031 if not node:
4030 4032 branch = repo[None].branch()
4031 4033 bheads = repo.branchheads(branch)
4032 4034 if len(bheads) > 2:
4033 4035 raise util.Abort(_("branch '%s' has %d heads - "
4034 4036 "please merge with an explicit rev")
4035 4037 % (branch, len(bheads)),
4036 4038 hint=_("run 'hg heads .' to see heads"))
4037 4039
4038 4040 parent = repo.dirstate.p1()
4039 4041 if len(bheads) == 1:
4040 4042 if len(repo.heads()) > 1:
4041 4043 raise util.Abort(_("branch '%s' has one head - "
4042 4044 "please merge with an explicit rev")
4043 4045 % branch,
4044 4046 hint=_("run 'hg heads' to see all heads"))
4045 4047 msg, hint = _('nothing to merge'), None
4046 4048 if parent != repo.lookup(branch):
4047 4049 hint = _("use 'hg update' instead")
4048 4050 raise util.Abort(msg, hint=hint)
4049 4051
4050 4052 if parent not in bheads:
4051 4053 raise util.Abort(_('working directory not at a head revision'),
4052 4054 hint=_("use 'hg update' or merge with an "
4053 4055 "explicit revision"))
4054 4056 node = parent == bheads[0] and bheads[-1] or bheads[0]
4055 4057 else:
4056 4058 node = scmutil.revsingle(repo, node).node()
4057 4059
4058 4060 if opts.get('preview'):
4059 4061 # find nodes that are ancestors of p2 but not of p1
4060 4062 p1 = repo.lookup('.')
4061 4063 p2 = repo.lookup(node)
4062 4064 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4063 4065
4064 4066 displayer = cmdutil.show_changeset(ui, repo, opts)
4065 4067 for node in nodes:
4066 4068 displayer.show(repo[node])
4067 4069 displayer.close()
4068 4070 return 0
4069 4071
4070 4072 try:
4071 4073 # ui.forcemerge is an internal variable, do not document
4072 4074 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4073 4075 return hg.merge(repo, node, force=opts.get('force'))
4074 4076 finally:
4075 4077 ui.setconfig('ui', 'forcemerge', '')
4076 4078
4077 4079 @command('outgoing|out',
4078 4080 [('f', 'force', None, _('run even when the destination is unrelated')),
4079 4081 ('r', 'rev', [],
4080 4082 _('a changeset intended to be included in the destination'), _('REV')),
4081 4083 ('n', 'newest-first', None, _('show newest record first')),
4082 4084 ('B', 'bookmarks', False, _('compare bookmarks')),
4083 4085 ('b', 'branch', [], _('a specific branch you would like to push'),
4084 4086 _('BRANCH')),
4085 4087 ] + logopts + remoteopts + subrepoopts,
4086 4088 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4087 4089 def outgoing(ui, repo, dest=None, **opts):
4088 4090 """show changesets not found in the destination
4089 4091
4090 4092 Show changesets not found in the specified destination repository
4091 4093 or the default push location. These are the changesets that would
4092 4094 be pushed if a push was requested.
4093 4095
4094 4096 See pull for details of valid destination formats.
4095 4097
4096 4098 Returns 0 if there are outgoing changes, 1 otherwise.
4097 4099 """
4098 4100
4099 4101 if opts.get('bookmarks'):
4100 4102 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4101 4103 dest, branches = hg.parseurl(dest, opts.get('branch'))
4102 4104 other = hg.peer(repo, opts, dest)
4103 4105 if 'bookmarks' not in other.listkeys('namespaces'):
4104 4106 ui.warn(_("remote doesn't support bookmarks\n"))
4105 4107 return 0
4106 4108 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4107 4109 return bookmarks.diff(ui, other, repo)
4108 4110
4109 4111 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4110 4112 try:
4111 4113 return hg.outgoing(ui, repo, dest, opts)
4112 4114 finally:
4113 4115 del repo._subtoppath
4114 4116
4115 4117 @command('parents',
4116 4118 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4117 4119 ] + templateopts,
4118 4120 _('[-r REV] [FILE]'))
4119 4121 def parents(ui, repo, file_=None, **opts):
4120 4122 """show the parents of the working directory or revision
4121 4123
4122 4124 Print the working directory's parent revisions. If a revision is
4123 4125 given via -r/--rev, the parent of that revision will be printed.
4124 4126 If a file argument is given, the revision in which the file was
4125 4127 last changed (before the working directory revision or the
4126 4128 argument to --rev if given) is printed.
4127 4129
4128 4130 Returns 0 on success.
4129 4131 """
4130 4132
4131 4133 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4132 4134
4133 4135 if file_:
4134 4136 m = scmutil.match(ctx, (file_,), opts)
4135 4137 if m.anypats() or len(m.files()) != 1:
4136 4138 raise util.Abort(_('can only specify an explicit filename'))
4137 4139 file_ = m.files()[0]
4138 4140 filenodes = []
4139 4141 for cp in ctx.parents():
4140 4142 if not cp:
4141 4143 continue
4142 4144 try:
4143 4145 filenodes.append(cp.filenode(file_))
4144 4146 except error.LookupError:
4145 4147 pass
4146 4148 if not filenodes:
4147 4149 raise util.Abort(_("'%s' not found in manifest!") % file_)
4148 4150 fl = repo.file(file_)
4149 4151 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4150 4152 else:
4151 4153 p = [cp.node() for cp in ctx.parents()]
4152 4154
4153 4155 displayer = cmdutil.show_changeset(ui, repo, opts)
4154 4156 for n in p:
4155 4157 if n != nullid:
4156 4158 displayer.show(repo[n])
4157 4159 displayer.close()
4158 4160
4159 4161 @command('paths', [], _('[NAME]'))
4160 4162 def paths(ui, repo, search=None):
4161 4163 """show aliases for remote repositories
4162 4164
4163 4165 Show definition of symbolic path name NAME. If no name is given,
4164 4166 show definition of all available names.
4165 4167
4166 4168 Option -q/--quiet suppresses all output when searching for NAME
4167 4169 and shows only the path names when listing all definitions.
4168 4170
4169 4171 Path names are defined in the [paths] section of your
4170 4172 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4171 4173 repository, ``.hg/hgrc`` is used, too.
4172 4174
4173 4175 The path names ``default`` and ``default-push`` have a special
4174 4176 meaning. When performing a push or pull operation, they are used
4175 4177 as fallbacks if no location is specified on the command-line.
4176 4178 When ``default-push`` is set, it will be used for push and
4177 4179 ``default`` will be used for pull; otherwise ``default`` is used
4178 4180 as the fallback for both. When cloning a repository, the clone
4179 4181 source is written as ``default`` in ``.hg/hgrc``. Note that
4180 4182 ``default`` and ``default-push`` apply to all inbound (e.g.
4181 4183 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4182 4184 :hg:`bundle`) operations.
4183 4185
4184 4186 See :hg:`help urls` for more information.
4185 4187
4186 4188 Returns 0 on success.
4187 4189 """
4188 4190 if search:
4189 4191 for name, path in ui.configitems("paths"):
4190 4192 if name == search:
4191 4193 ui.status("%s\n" % util.hidepassword(path))
4192 4194 return
4193 4195 if not ui.quiet:
4194 4196 ui.warn(_("not found!\n"))
4195 4197 return 1
4196 4198 else:
4197 4199 for name, path in ui.configitems("paths"):
4198 4200 if ui.quiet:
4199 4201 ui.write("%s\n" % name)
4200 4202 else:
4201 4203 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4202 4204
4203 4205 def postincoming(ui, repo, modheads, optupdate, checkout):
4204 4206 if modheads == 0:
4205 4207 return
4206 4208 if optupdate:
4207 4209 try:
4208 4210 return hg.update(repo, checkout)
4209 4211 except util.Abort, inst:
4210 4212 ui.warn(_("not updating: %s\n" % str(inst)))
4211 4213 return 0
4212 4214 if modheads > 1:
4213 4215 currentbranchheads = len(repo.branchheads())
4214 4216 if currentbranchheads == modheads:
4215 4217 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4216 4218 elif currentbranchheads > 1:
4217 4219 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
4218 4220 else:
4219 4221 ui.status(_("(run 'hg heads' to see heads)\n"))
4220 4222 else:
4221 4223 ui.status(_("(run 'hg update' to get a working copy)\n"))
4222 4224
4223 4225 @command('^pull',
4224 4226 [('u', 'update', None,
4225 4227 _('update to new branch head if changesets were pulled')),
4226 4228 ('f', 'force', None, _('run even when remote repository is unrelated')),
4227 4229 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4228 4230 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4229 4231 ('b', 'branch', [], _('a specific branch you would like to pull'),
4230 4232 _('BRANCH')),
4231 4233 ] + remoteopts,
4232 4234 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4233 4235 def pull(ui, repo, source="default", **opts):
4234 4236 """pull changes from the specified source
4235 4237
4236 4238 Pull changes from a remote repository to a local one.
4237 4239
4238 4240 This finds all changes from the repository at the specified path
4239 4241 or URL and adds them to a local repository (the current one unless
4240 4242 -R is specified). By default, this does not update the copy of the
4241 4243 project in the working directory.
4242 4244
4243 4245 Use :hg:`incoming` if you want to see what would have been added
4244 4246 by a pull at the time you issued this command. If you then decide
4245 4247 to add those changes to the repository, you should use :hg:`pull
4246 4248 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4247 4249
4248 4250 If SOURCE is omitted, the 'default' path will be used.
4249 4251 See :hg:`help urls` for more information.
4250 4252
4251 4253 Returns 0 on success, 1 if an update had unresolved files.
4252 4254 """
4253 4255 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4254 4256 other = hg.peer(repo, opts, source)
4255 4257 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4256 4258 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4257 4259
4258 4260 if opts.get('bookmark'):
4259 4261 if not revs:
4260 4262 revs = []
4261 4263 rb = other.listkeys('bookmarks')
4262 4264 for b in opts['bookmark']:
4263 4265 if b not in rb:
4264 4266 raise util.Abort(_('remote bookmark %s not found!') % b)
4265 4267 revs.append(rb[b])
4266 4268
4267 4269 if revs:
4268 4270 try:
4269 4271 revs = [other.lookup(rev) for rev in revs]
4270 4272 except error.CapabilityError:
4271 4273 err = _("other repository doesn't support revision lookup, "
4272 4274 "so a rev cannot be specified.")
4273 4275 raise util.Abort(err)
4274 4276
4275 4277 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4276 4278 bookmarks.updatefromremote(ui, repo, other, source)
4277 4279 if checkout:
4278 4280 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4279 4281 repo._subtoppath = source
4280 4282 try:
4281 4283 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4282 4284
4283 4285 finally:
4284 4286 del repo._subtoppath
4285 4287
4286 4288 # update specified bookmarks
4287 4289 if opts.get('bookmark'):
4288 4290 for b in opts['bookmark']:
4289 4291 # explicit pull overrides local bookmark if any
4290 4292 ui.status(_("importing bookmark %s\n") % b)
4291 4293 repo._bookmarks[b] = repo[rb[b]].node()
4292 4294 bookmarks.write(repo)
4293 4295
4294 4296 return ret
4295 4297
4296 4298 @command('^push',
4297 4299 [('f', 'force', None, _('force push')),
4298 4300 ('r', 'rev', [],
4299 4301 _('a changeset intended to be included in the destination'),
4300 4302 _('REV')),
4301 4303 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4302 4304 ('b', 'branch', [],
4303 4305 _('a specific branch you would like to push'), _('BRANCH')),
4304 4306 ('', 'new-branch', False, _('allow pushing a new branch')),
4305 4307 ] + remoteopts,
4306 4308 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4307 4309 def push(ui, repo, dest=None, **opts):
4308 4310 """push changes to the specified destination
4309 4311
4310 4312 Push changesets from the local repository to the specified
4311 4313 destination.
4312 4314
4313 4315 This operation is symmetrical to pull: it is identical to a pull
4314 4316 in the destination repository from the current one.
4315 4317
4316 4318 By default, push will not allow creation of new heads at the
4317 4319 destination, since multiple heads would make it unclear which head
4318 4320 to use. In this situation, it is recommended to pull and merge
4319 4321 before pushing.
4320 4322
4321 4323 Use --new-branch if you want to allow push to create a new named
4322 4324 branch that is not present at the destination. This allows you to
4323 4325 only create a new branch without forcing other changes.
4324 4326
4325 4327 Use -f/--force to override the default behavior and push all
4326 4328 changesets on all branches.
4327 4329
4328 4330 If -r/--rev is used, the specified revision and all its ancestors
4329 4331 will be pushed to the remote repository.
4330 4332
4331 4333 Please see :hg:`help urls` for important details about ``ssh://``
4332 4334 URLs. If DESTINATION is omitted, a default path will be used.
4333 4335
4334 4336 Returns 0 if push was successful, 1 if nothing to push.
4335 4337 """
4336 4338
4337 4339 if opts.get('bookmark'):
4338 4340 for b in opts['bookmark']:
4339 4341 # translate -B options to -r so changesets get pushed
4340 4342 if b in repo._bookmarks:
4341 4343 opts.setdefault('rev', []).append(b)
4342 4344 else:
4343 4345 # if we try to push a deleted bookmark, translate it to null
4344 4346 # this lets simultaneous -r, -b options continue working
4345 4347 opts.setdefault('rev', []).append("null")
4346 4348
4347 4349 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4348 4350 dest, branches = hg.parseurl(dest, opts.get('branch'))
4349 4351 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4350 4352 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4351 4353 other = hg.peer(repo, opts, dest)
4352 4354 if revs:
4353 4355 revs = [repo.lookup(rev) for rev in revs]
4354 4356
4355 4357 repo._subtoppath = dest
4356 4358 try:
4357 4359 # push subrepos depth-first for coherent ordering
4358 4360 c = repo['']
4359 4361 subs = c.substate # only repos that are committed
4360 4362 for s in sorted(subs):
4361 4363 if not c.sub(s).push(opts.get('force')):
4362 4364 return False
4363 4365 finally:
4364 4366 del repo._subtoppath
4365 4367 result = repo.push(other, opts.get('force'), revs=revs,
4366 4368 newbranch=opts.get('new_branch'))
4367 4369
4368 4370 result = (result == 0)
4369 4371
4370 4372 if opts.get('bookmark'):
4371 4373 rb = other.listkeys('bookmarks')
4372 4374 for b in opts['bookmark']:
4373 4375 # explicit push overrides remote bookmark if any
4374 4376 if b in repo._bookmarks:
4375 4377 ui.status(_("exporting bookmark %s\n") % b)
4376 4378 new = repo[b].hex()
4377 4379 elif b in rb:
4378 4380 ui.status(_("deleting remote bookmark %s\n") % b)
4379 4381 new = '' # delete
4380 4382 else:
4381 4383 ui.warn(_('bookmark %s does not exist on the local '
4382 4384 'or remote repository!\n') % b)
4383 4385 return 2
4384 4386 old = rb.get(b, '')
4385 4387 r = other.pushkey('bookmarks', b, old, new)
4386 4388 if not r:
4387 4389 ui.warn(_('updating bookmark %s failed!\n') % b)
4388 4390 if not result:
4389 4391 result = 2
4390 4392
4391 4393 return result
4392 4394
4393 4395 @command('recover', [])
4394 4396 def recover(ui, repo):
4395 4397 """roll back an interrupted transaction
4396 4398
4397 4399 Recover from an interrupted commit or pull.
4398 4400
4399 4401 This command tries to fix the repository status after an
4400 4402 interrupted operation. It should only be necessary when Mercurial
4401 4403 suggests it.
4402 4404
4403 4405 Returns 0 if successful, 1 if nothing to recover or verify fails.
4404 4406 """
4405 4407 if repo.recover():
4406 4408 return hg.verify(repo)
4407 4409 return 1
4408 4410
4409 4411 @command('^remove|rm',
4410 4412 [('A', 'after', None, _('record delete for missing files')),
4411 4413 ('f', 'force', None,
4412 4414 _('remove (and delete) file even if added or modified')),
4413 4415 ] + walkopts,
4414 4416 _('[OPTION]... FILE...'))
4415 4417 def remove(ui, repo, *pats, **opts):
4416 4418 """remove the specified files on the next commit
4417 4419
4418 4420 Schedule the indicated files for removal from the current branch.
4419 4421
4420 4422 This command schedules the files to be removed at the next commit.
4421 4423 To undo a remove before that, see :hg:`revert`. To undo added
4422 4424 files, see :hg:`forget`.
4423 4425
4424 4426 .. container:: verbose
4425 4427
4426 4428 -A/--after can be used to remove only files that have already
4427 4429 been deleted, -f/--force can be used to force deletion, and -Af
4428 4430 can be used to remove files from the next revision without
4429 4431 deleting them from the working directory.
4430 4432
4431 4433 The following table details the behavior of remove for different
4432 4434 file states (columns) and option combinations (rows). The file
4433 4435 states are Added [A], Clean [C], Modified [M] and Missing [!]
4434 4436 (as reported by :hg:`status`). The actions are Warn, Remove
4435 4437 (from branch) and Delete (from disk):
4436 4438
4437 4439 ======= == == == ==
4438 4440 A C M !
4439 4441 ======= == == == ==
4440 4442 none W RD W R
4441 4443 -f R RD RD R
4442 4444 -A W W W R
4443 4445 -Af R R R R
4444 4446 ======= == == == ==
4445 4447
4446 4448 Note that remove never deletes files in Added [A] state from the
4447 4449 working directory, not even if option --force is specified.
4448 4450
4449 4451 Returns 0 on success, 1 if any warnings encountered.
4450 4452 """
4451 4453
4452 4454 ret = 0
4453 4455 after, force = opts.get('after'), opts.get('force')
4454 4456 if not pats and not after:
4455 4457 raise util.Abort(_('no files specified'))
4456 4458
4457 4459 m = scmutil.match(repo[None], pats, opts)
4458 4460 s = repo.status(match=m, clean=True)
4459 4461 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4460 4462
4461 4463 for f in m.files():
4462 4464 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4463 4465 if os.path.exists(m.rel(f)):
4464 4466 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4465 4467 ret = 1
4466 4468
4467 4469 if force:
4468 4470 list = modified + deleted + clean + added
4469 4471 elif after:
4470 4472 list = deleted
4471 4473 for f in modified + added + clean:
4472 4474 ui.warn(_('not removing %s: file still exists (use -f'
4473 4475 ' to force removal)\n') % m.rel(f))
4474 4476 ret = 1
4475 4477 else:
4476 4478 list = deleted + clean
4477 4479 for f in modified:
4478 4480 ui.warn(_('not removing %s: file is modified (use -f'
4479 4481 ' to force removal)\n') % m.rel(f))
4480 4482 ret = 1
4481 4483 for f in added:
4482 4484 ui.warn(_('not removing %s: file has been marked for add'
4483 4485 ' (use forget to undo)\n') % m.rel(f))
4484 4486 ret = 1
4485 4487
4486 4488 for f in sorted(list):
4487 4489 if ui.verbose or not m.exact(f):
4488 4490 ui.status(_('removing %s\n') % m.rel(f))
4489 4491
4490 4492 wlock = repo.wlock()
4491 4493 try:
4492 4494 if not after:
4493 4495 for f in list:
4494 4496 if f in added:
4495 4497 continue # we never unlink added files on remove
4496 4498 try:
4497 4499 util.unlinkpath(repo.wjoin(f))
4498 4500 except OSError, inst:
4499 4501 if inst.errno != errno.ENOENT:
4500 4502 raise
4501 4503 repo[None].forget(list)
4502 4504 finally:
4503 4505 wlock.release()
4504 4506
4505 4507 return ret
4506 4508
4507 4509 @command('rename|move|mv',
4508 4510 [('A', 'after', None, _('record a rename that has already occurred')),
4509 4511 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4510 4512 ] + walkopts + dryrunopts,
4511 4513 _('[OPTION]... SOURCE... DEST'))
4512 4514 def rename(ui, repo, *pats, **opts):
4513 4515 """rename files; equivalent of copy + remove
4514 4516
4515 4517 Mark dest as copies of sources; mark sources for deletion. If dest
4516 4518 is a directory, copies are put in that directory. If dest is a
4517 4519 file, there can only be one source.
4518 4520
4519 4521 By default, this command copies the contents of files as they
4520 4522 exist in the working directory. If invoked with -A/--after, the
4521 4523 operation is recorded, but no copying is performed.
4522 4524
4523 4525 This command takes effect at the next commit. To undo a rename
4524 4526 before that, see :hg:`revert`.
4525 4527
4526 4528 Returns 0 on success, 1 if errors are encountered.
4527 4529 """
4528 4530 wlock = repo.wlock(False)
4529 4531 try:
4530 4532 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4531 4533 finally:
4532 4534 wlock.release()
4533 4535
4534 4536 @command('resolve',
4535 4537 [('a', 'all', None, _('select all unresolved files')),
4536 4538 ('l', 'list', None, _('list state of files needing merge')),
4537 4539 ('m', 'mark', None, _('mark files as resolved')),
4538 4540 ('u', 'unmark', None, _('mark files as unresolved')),
4539 4541 ('n', 'no-status', None, _('hide status prefix'))]
4540 4542 + mergetoolopts + walkopts,
4541 4543 _('[OPTION]... [FILE]...'))
4542 4544 def resolve(ui, repo, *pats, **opts):
4543 4545 """redo merges or set/view the merge status of files
4544 4546
4545 4547 Merges with unresolved conflicts are often the result of
4546 4548 non-interactive merging using the ``internal:merge`` configuration
4547 4549 setting, or a command-line merge tool like ``diff3``. The resolve
4548 4550 command is used to manage the files involved in a merge, after
4549 4551 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4550 4552 working directory must have two parents).
4551 4553
4552 4554 The resolve command can be used in the following ways:
4553 4555
4554 4556 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4555 4557 files, discarding any previous merge attempts. Re-merging is not
4556 4558 performed for files already marked as resolved. Use ``--all/-a``
4557 4559 to select all unresolved files. ``--tool`` can be used to specify
4558 4560 the merge tool used for the given files. It overrides the HGMERGE
4559 4561 environment variable and your configuration files. Previous file
4560 4562 contents are saved with a ``.orig`` suffix.
4561 4563
4562 4564 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4563 4565 (e.g. after having manually fixed-up the files). The default is
4564 4566 to mark all unresolved files.
4565 4567
4566 4568 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4567 4569 default is to mark all resolved files.
4568 4570
4569 4571 - :hg:`resolve -l`: list files which had or still have conflicts.
4570 4572 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4571 4573
4572 4574 Note that Mercurial will not let you commit files with unresolved
4573 4575 merge conflicts. You must use :hg:`resolve -m ...` before you can
4574 4576 commit after a conflicting merge.
4575 4577
4576 4578 Returns 0 on success, 1 if any files fail a resolve attempt.
4577 4579 """
4578 4580
4579 4581 all, mark, unmark, show, nostatus = \
4580 4582 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4581 4583
4582 4584 if (show and (mark or unmark)) or (mark and unmark):
4583 4585 raise util.Abort(_("too many options specified"))
4584 4586 if pats and all:
4585 4587 raise util.Abort(_("can't specify --all and patterns"))
4586 4588 if not (all or pats or show or mark or unmark):
4587 4589 raise util.Abort(_('no files or directories specified; '
4588 4590 'use --all to remerge all files'))
4589 4591
4590 4592 ms = mergemod.mergestate(repo)
4591 4593 m = scmutil.match(repo[None], pats, opts)
4592 4594 ret = 0
4593 4595
4594 4596 for f in ms:
4595 4597 if m(f):
4596 4598 if show:
4597 4599 if nostatus:
4598 4600 ui.write("%s\n" % f)
4599 4601 else:
4600 4602 ui.write("%s %s\n" % (ms[f].upper(), f),
4601 4603 label='resolve.' +
4602 4604 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4603 4605 elif mark:
4604 4606 ms.mark(f, "r")
4605 4607 elif unmark:
4606 4608 ms.mark(f, "u")
4607 4609 else:
4608 4610 wctx = repo[None]
4609 4611 mctx = wctx.parents()[-1]
4610 4612
4611 4613 # backup pre-resolve (merge uses .orig for its own purposes)
4612 4614 a = repo.wjoin(f)
4613 4615 util.copyfile(a, a + ".resolve")
4614 4616
4615 4617 try:
4616 4618 # resolve file
4617 4619 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4618 4620 if ms.resolve(f, wctx, mctx):
4619 4621 ret = 1
4620 4622 finally:
4621 4623 ui.setconfig('ui', 'forcemerge', '')
4622 4624
4623 4625 # replace filemerge's .orig file with our resolve file
4624 4626 util.rename(a + ".resolve", a + ".orig")
4625 4627
4626 4628 ms.commit()
4627 4629 return ret
4628 4630
4629 4631 @command('revert',
4630 4632 [('a', 'all', None, _('revert all changes when no arguments given')),
4631 4633 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4632 4634 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4633 4635 ('C', 'no-backup', None, _('do not save backup copies of files')),
4634 4636 ] + walkopts + dryrunopts,
4635 4637 _('[OPTION]... [-r REV] [NAME]...'))
4636 4638 def revert(ui, repo, *pats, **opts):
4637 4639 """restore files to their checkout state
4638 4640
4639 4641 .. note::
4640 4642 To check out earlier revisions, you should use :hg:`update REV`.
4641 4643 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4642 4644
4643 4645 With no revision specified, revert the specified files or directories
4644 4646 to the contents they had in the parent of the working directory.
4645 4647 This restores the contents of files to an unmodified
4646 4648 state and unschedules adds, removes, copies, and renames. If the
4647 4649 working directory has two parents, you must explicitly specify a
4648 4650 revision.
4649 4651
4650 4652 Using the -r/--rev or -d/--date options, revert the given files or
4651 4653 directories to their states as of a specific revision. Because
4652 4654 revert does not change the working directory parents, this will
4653 4655 cause these files to appear modified. This can be helpful to "back
4654 4656 out" some or all of an earlier change. See :hg:`backout` for a
4655 4657 related method.
4656 4658
4657 4659 Modified files are saved with a .orig suffix before reverting.
4658 4660 To disable these backups, use --no-backup.
4659 4661
4660 4662 See :hg:`help dates` for a list of formats valid for -d/--date.
4661 4663
4662 4664 Returns 0 on success.
4663 4665 """
4664 4666
4665 4667 if opts.get("date"):
4666 4668 if opts.get("rev"):
4667 4669 raise util.Abort(_("you can't specify a revision and a date"))
4668 4670 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4669 4671
4670 4672 parent, p2 = repo.dirstate.parents()
4671 4673 if not opts.get('rev') and p2 != nullid:
4672 4674 # revert after merge is a trap for new users (issue2915)
4673 4675 raise util.Abort(_('uncommitted merge with no revision specified'),
4674 4676 hint=_('use "hg update" or see "hg help revert"'))
4675 4677
4676 4678 ctx = scmutil.revsingle(repo, opts.get('rev'))
4677 4679 node = ctx.node()
4678 4680
4679 4681 if not pats and not opts.get('all'):
4680 4682 msg = _("no files or directories specified")
4681 4683 if p2 != nullid:
4682 4684 hint = _("uncommitted merge, use --all to discard all changes,"
4683 4685 " or 'hg update -C .' to abort the merge")
4684 4686 raise util.Abort(msg, hint=hint)
4685 4687 dirty = util.any(repo.status())
4686 4688 if node != parent:
4687 4689 if dirty:
4688 4690 hint = _("uncommitted changes, use --all to discard all"
4689 4691 " changes, or 'hg update %s' to update") % ctx.rev()
4690 4692 else:
4691 4693 hint = _("use --all to revert all files,"
4692 4694 " or 'hg update %s' to update") % ctx.rev()
4693 4695 elif dirty:
4694 4696 hint = _("uncommitted changes, use --all to discard all changes")
4695 4697 else:
4696 4698 hint = _("use --all to revert all files")
4697 4699 raise util.Abort(msg, hint=hint)
4698 4700
4699 4701 mf = ctx.manifest()
4700 4702 if node == parent:
4701 4703 pmf = mf
4702 4704 else:
4703 4705 pmf = None
4704 4706
4705 4707 # need all matching names in dirstate and manifest of target rev,
4706 4708 # so have to walk both. do not print errors if files exist in one
4707 4709 # but not other.
4708 4710
4709 4711 names = {}
4710 4712
4711 4713 wlock = repo.wlock()
4712 4714 try:
4713 4715 # walk dirstate.
4714 4716
4715 4717 m = scmutil.match(repo[None], pats, opts)
4716 4718 m.bad = lambda x, y: False
4717 4719 for abs in repo.walk(m):
4718 4720 names[abs] = m.rel(abs), m.exact(abs)
4719 4721
4720 4722 # walk target manifest.
4721 4723
4722 4724 def badfn(path, msg):
4723 4725 if path in names:
4724 4726 return
4725 4727 if path in repo[node].substate:
4726 4728 ui.warn("%s: %s\n" % (m.rel(path),
4727 4729 'reverting subrepos is unsupported'))
4728 4730 return
4729 4731 path_ = path + '/'
4730 4732 for f in names:
4731 4733 if f.startswith(path_):
4732 4734 return
4733 4735 ui.warn("%s: %s\n" % (m.rel(path), msg))
4734 4736
4735 4737 m = scmutil.match(repo[node], pats, opts)
4736 4738 m.bad = badfn
4737 4739 for abs in repo[node].walk(m):
4738 4740 if abs not in names:
4739 4741 names[abs] = m.rel(abs), m.exact(abs)
4740 4742
4741 4743 m = scmutil.matchfiles(repo, names)
4742 4744 changes = repo.status(match=m)[:4]
4743 4745 modified, added, removed, deleted = map(set, changes)
4744 4746
4745 4747 # if f is a rename, also revert the source
4746 4748 cwd = repo.getcwd()
4747 4749 for f in added:
4748 4750 src = repo.dirstate.copied(f)
4749 4751 if src and src not in names and repo.dirstate[src] == 'r':
4750 4752 removed.add(src)
4751 4753 names[src] = (repo.pathto(src, cwd), True)
4752 4754
4753 4755 def removeforget(abs):
4754 4756 if repo.dirstate[abs] == 'a':
4755 4757 return _('forgetting %s\n')
4756 4758 return _('removing %s\n')
4757 4759
4758 4760 revert = ([], _('reverting %s\n'))
4759 4761 add = ([], _('adding %s\n'))
4760 4762 remove = ([], removeforget)
4761 4763 undelete = ([], _('undeleting %s\n'))
4762 4764
4763 4765 disptable = (
4764 4766 # dispatch table:
4765 4767 # file state
4766 4768 # action if in target manifest
4767 4769 # action if not in target manifest
4768 4770 # make backup if in target manifest
4769 4771 # make backup if not in target manifest
4770 4772 (modified, revert, remove, True, True),
4771 4773 (added, revert, remove, True, False),
4772 4774 (removed, undelete, None, False, False),
4773 4775 (deleted, revert, remove, False, False),
4774 4776 )
4775 4777
4776 4778 for abs, (rel, exact) in sorted(names.items()):
4777 4779 mfentry = mf.get(abs)
4778 4780 target = repo.wjoin(abs)
4779 4781 def handle(xlist, dobackup):
4780 4782 xlist[0].append(abs)
4781 4783 if (dobackup and not opts.get('no_backup') and
4782 4784 os.path.lexists(target)):
4783 4785 bakname = "%s.orig" % rel
4784 4786 ui.note(_('saving current version of %s as %s\n') %
4785 4787 (rel, bakname))
4786 4788 if not opts.get('dry_run'):
4787 4789 util.rename(target, bakname)
4788 4790 if ui.verbose or not exact:
4789 4791 msg = xlist[1]
4790 4792 if not isinstance(msg, basestring):
4791 4793 msg = msg(abs)
4792 4794 ui.status(msg % rel)
4793 4795 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4794 4796 if abs not in table:
4795 4797 continue
4796 4798 # file has changed in dirstate
4797 4799 if mfentry:
4798 4800 handle(hitlist, backuphit)
4799 4801 elif misslist is not None:
4800 4802 handle(misslist, backupmiss)
4801 4803 break
4802 4804 else:
4803 4805 if abs not in repo.dirstate:
4804 4806 if mfentry:
4805 4807 handle(add, True)
4806 4808 elif exact:
4807 4809 ui.warn(_('file not managed: %s\n') % rel)
4808 4810 continue
4809 4811 # file has not changed in dirstate
4810 4812 if node == parent:
4811 4813 if exact:
4812 4814 ui.warn(_('no changes needed to %s\n') % rel)
4813 4815 continue
4814 4816 if pmf is None:
4815 4817 # only need parent manifest in this unlikely case,
4816 4818 # so do not read by default
4817 4819 pmf = repo[parent].manifest()
4818 4820 if abs in pmf and mfentry:
4819 4821 # if version of file is same in parent and target
4820 4822 # manifests, do nothing
4821 4823 if (pmf[abs] != mfentry or
4822 4824 pmf.flags(abs) != mf.flags(abs)):
4823 4825 handle(revert, False)
4824 4826 else:
4825 4827 handle(remove, False)
4826 4828
4827 4829 if not opts.get('dry_run'):
4828 4830 def checkout(f):
4829 4831 fc = ctx[f]
4830 4832 repo.wwrite(f, fc.data(), fc.flags())
4831 4833
4832 4834 audit_path = scmutil.pathauditor(repo.root)
4833 4835 for f in remove[0]:
4834 4836 if repo.dirstate[f] == 'a':
4835 4837 repo.dirstate.drop(f)
4836 4838 continue
4837 4839 audit_path(f)
4838 4840 try:
4839 4841 util.unlinkpath(repo.wjoin(f))
4840 4842 except OSError:
4841 4843 pass
4842 4844 repo.dirstate.remove(f)
4843 4845
4844 4846 normal = None
4845 4847 if node == parent:
4846 4848 # We're reverting to our parent. If possible, we'd like status
4847 4849 # to report the file as clean. We have to use normallookup for
4848 4850 # merges to avoid losing information about merged/dirty files.
4849 4851 if p2 != nullid:
4850 4852 normal = repo.dirstate.normallookup
4851 4853 else:
4852 4854 normal = repo.dirstate.normal
4853 4855 for f in revert[0]:
4854 4856 checkout(f)
4855 4857 if normal:
4856 4858 normal(f)
4857 4859
4858 4860 for f in add[0]:
4859 4861 checkout(f)
4860 4862 repo.dirstate.add(f)
4861 4863
4862 4864 normal = repo.dirstate.normallookup
4863 4865 if node == parent and p2 == nullid:
4864 4866 normal = repo.dirstate.normal
4865 4867 for f in undelete[0]:
4866 4868 checkout(f)
4867 4869 normal(f)
4868 4870
4869 4871 finally:
4870 4872 wlock.release()
4871 4873
4872 4874 @command('rollback', dryrunopts +
4873 4875 [('f', 'force', False, _('ignore safety measures'))])
4874 4876 def rollback(ui, repo, **opts):
4875 4877 """roll back the last transaction (dangerous)
4876 4878
4877 4879 This command should be used with care. There is only one level of
4878 4880 rollback, and there is no way to undo a rollback. It will also
4879 4881 restore the dirstate at the time of the last transaction, losing
4880 4882 any dirstate changes since that time. This command does not alter
4881 4883 the working directory.
4882 4884
4883 4885 Transactions are used to encapsulate the effects of all commands
4884 4886 that create new changesets or propagate existing changesets into a
4885 4887 repository. For example, the following commands are transactional,
4886 4888 and their effects can be rolled back:
4887 4889
4888 4890 - commit
4889 4891 - import
4890 4892 - pull
4891 4893 - push (with this repository as the destination)
4892 4894 - unbundle
4893 4895
4894 4896 It's possible to lose data with rollback: commit, update back to
4895 4897 an older changeset, and then rollback. The update removes the
4896 4898 changes you committed from the working directory, and rollback
4897 4899 removes them from history. To avoid data loss, you must pass
4898 4900 --force in this case.
4899 4901
4900 4902 This command is not intended for use on public repositories. Once
4901 4903 changes are visible for pull by other users, rolling a transaction
4902 4904 back locally is ineffective (someone else may already have pulled
4903 4905 the changes). Furthermore, a race is possible with readers of the
4904 4906 repository; for example an in-progress pull from the repository
4905 4907 may fail if a rollback is performed.
4906 4908
4907 4909 Returns 0 on success, 1 if no rollback data is available.
4908 4910 """
4909 4911 return repo.rollback(dryrun=opts.get('dry_run'),
4910 4912 force=opts.get('force'))
4911 4913
4912 4914 @command('root', [])
4913 4915 def root(ui, repo):
4914 4916 """print the root (top) of the current working directory
4915 4917
4916 4918 Print the root directory of the current repository.
4917 4919
4918 4920 Returns 0 on success.
4919 4921 """
4920 4922 ui.write(repo.root + "\n")
4921 4923
4922 4924 @command('^serve',
4923 4925 [('A', 'accesslog', '', _('name of access log file to write to'),
4924 4926 _('FILE')),
4925 4927 ('d', 'daemon', None, _('run server in background')),
4926 4928 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4927 4929 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4928 4930 # use string type, then we can check if something was passed
4929 4931 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4930 4932 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4931 4933 _('ADDR')),
4932 4934 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4933 4935 _('PREFIX')),
4934 4936 ('n', 'name', '',
4935 4937 _('name to show in web pages (default: working directory)'), _('NAME')),
4936 4938 ('', 'web-conf', '',
4937 4939 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4938 4940 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4939 4941 _('FILE')),
4940 4942 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4941 4943 ('', 'stdio', None, _('for remote clients')),
4942 4944 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4943 4945 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4944 4946 ('', 'style', '', _('template style to use'), _('STYLE')),
4945 4947 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4946 4948 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4947 4949 _('[OPTION]...'))
4948 4950 def serve(ui, repo, **opts):
4949 4951 """start stand-alone webserver
4950 4952
4951 4953 Start a local HTTP repository browser and pull server. You can use
4952 4954 this for ad-hoc sharing and browsing of repositories. It is
4953 4955 recommended to use a real web server to serve a repository for
4954 4956 longer periods of time.
4955 4957
4956 4958 Please note that the server does not implement access control.
4957 4959 This means that, by default, anybody can read from the server and
4958 4960 nobody can write to it by default. Set the ``web.allow_push``
4959 4961 option to ``*`` to allow everybody to push to the server. You
4960 4962 should use a real web server if you need to authenticate users.
4961 4963
4962 4964 By default, the server logs accesses to stdout and errors to
4963 4965 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4964 4966 files.
4965 4967
4966 4968 To have the server choose a free port number to listen on, specify
4967 4969 a port number of 0; in this case, the server will print the port
4968 4970 number it uses.
4969 4971
4970 4972 Returns 0 on success.
4971 4973 """
4972 4974
4973 4975 if opts["stdio"] and opts["cmdserver"]:
4974 4976 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4975 4977
4976 4978 def checkrepo():
4977 4979 if repo is None:
4978 4980 raise error.RepoError(_("There is no Mercurial repository here"
4979 4981 " (.hg not found)"))
4980 4982
4981 4983 if opts["stdio"]:
4982 4984 checkrepo()
4983 4985 s = sshserver.sshserver(ui, repo)
4984 4986 s.serve_forever()
4985 4987
4986 4988 if opts["cmdserver"]:
4987 4989 checkrepo()
4988 4990 s = commandserver.server(ui, repo, opts["cmdserver"])
4989 4991 return s.serve()
4990 4992
4991 4993 # this way we can check if something was given in the command-line
4992 4994 if opts.get('port'):
4993 4995 opts['port'] = util.getport(opts.get('port'))
4994 4996
4995 4997 baseui = repo and repo.baseui or ui
4996 4998 optlist = ("name templates style address port prefix ipv6"
4997 4999 " accesslog errorlog certificate encoding")
4998 5000 for o in optlist.split():
4999 5001 val = opts.get(o, '')
5000 5002 if val in (None, ''): # should check against default options instead
5001 5003 continue
5002 5004 baseui.setconfig("web", o, val)
5003 5005 if repo and repo.ui != baseui:
5004 5006 repo.ui.setconfig("web", o, val)
5005 5007
5006 5008 o = opts.get('web_conf') or opts.get('webdir_conf')
5007 5009 if not o:
5008 5010 if not repo:
5009 5011 raise error.RepoError(_("There is no Mercurial repository"
5010 5012 " here (.hg not found)"))
5011 5013 o = repo.root
5012 5014
5013 5015 app = hgweb.hgweb(o, baseui=ui)
5014 5016
5015 5017 class service(object):
5016 5018 def init(self):
5017 5019 util.setsignalhandler()
5018 5020 self.httpd = hgweb.server.create_server(ui, app)
5019 5021
5020 5022 if opts['port'] and not ui.verbose:
5021 5023 return
5022 5024
5023 5025 if self.httpd.prefix:
5024 5026 prefix = self.httpd.prefix.strip('/') + '/'
5025 5027 else:
5026 5028 prefix = ''
5027 5029
5028 5030 port = ':%d' % self.httpd.port
5029 5031 if port == ':80':
5030 5032 port = ''
5031 5033
5032 5034 bindaddr = self.httpd.addr
5033 5035 if bindaddr == '0.0.0.0':
5034 5036 bindaddr = '*'
5035 5037 elif ':' in bindaddr: # IPv6
5036 5038 bindaddr = '[%s]' % bindaddr
5037 5039
5038 5040 fqaddr = self.httpd.fqaddr
5039 5041 if ':' in fqaddr:
5040 5042 fqaddr = '[%s]' % fqaddr
5041 5043 if opts['port']:
5042 5044 write = ui.status
5043 5045 else:
5044 5046 write = ui.write
5045 5047 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5046 5048 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5047 5049
5048 5050 def run(self):
5049 5051 self.httpd.serve_forever()
5050 5052
5051 5053 service = service()
5052 5054
5053 5055 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5054 5056
5055 5057 @command('showconfig|debugconfig',
5056 5058 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5057 5059 _('[-u] [NAME]...'))
5058 5060 def showconfig(ui, repo, *values, **opts):
5059 5061 """show combined config settings from all hgrc files
5060 5062
5061 5063 With no arguments, print names and values of all config items.
5062 5064
5063 5065 With one argument of the form section.name, print just the value
5064 5066 of that config item.
5065 5067
5066 5068 With multiple arguments, print names and values of all config
5067 5069 items with matching section names.
5068 5070
5069 5071 With --debug, the source (filename and line number) is printed
5070 5072 for each config item.
5071 5073
5072 5074 Returns 0 on success.
5073 5075 """
5074 5076
5075 5077 for f in scmutil.rcpath():
5076 5078 ui.debug('read config from: %s\n' % f)
5077 5079 untrusted = bool(opts.get('untrusted'))
5078 5080 if values:
5079 5081 sections = [v for v in values if '.' not in v]
5080 5082 items = [v for v in values if '.' in v]
5081 5083 if len(items) > 1 or items and sections:
5082 5084 raise util.Abort(_('only one config item permitted'))
5083 5085 for section, name, value in ui.walkconfig(untrusted=untrusted):
5084 5086 value = str(value).replace('\n', '\\n')
5085 5087 sectname = section + '.' + name
5086 5088 if values:
5087 5089 for v in values:
5088 5090 if v == section:
5089 5091 ui.debug('%s: ' %
5090 5092 ui.configsource(section, name, untrusted))
5091 5093 ui.write('%s=%s\n' % (sectname, value))
5092 5094 elif v == sectname:
5093 5095 ui.debug('%s: ' %
5094 5096 ui.configsource(section, name, untrusted))
5095 5097 ui.write(value, '\n')
5096 5098 else:
5097 5099 ui.debug('%s: ' %
5098 5100 ui.configsource(section, name, untrusted))
5099 5101 ui.write('%s=%s\n' % (sectname, value))
5100 5102
5101 5103 @command('^status|st',
5102 5104 [('A', 'all', None, _('show status of all files')),
5103 5105 ('m', 'modified', None, _('show only modified files')),
5104 5106 ('a', 'added', None, _('show only added files')),
5105 5107 ('r', 'removed', None, _('show only removed files')),
5106 5108 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5107 5109 ('c', 'clean', None, _('show only files without changes')),
5108 5110 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5109 5111 ('i', 'ignored', None, _('show only ignored files')),
5110 5112 ('n', 'no-status', None, _('hide status prefix')),
5111 5113 ('C', 'copies', None, _('show source of copied files')),
5112 5114 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5113 5115 ('', 'rev', [], _('show difference from revision'), _('REV')),
5114 5116 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5115 5117 ] + walkopts + subrepoopts,
5116 5118 _('[OPTION]... [FILE]...'))
5117 5119 def status(ui, repo, *pats, **opts):
5118 5120 """show changed files in the working directory
5119 5121
5120 5122 Show status of files in the repository. If names are given, only
5121 5123 files that match are shown. Files that are clean or ignored or
5122 5124 the source of a copy/move operation, are not listed unless
5123 5125 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5124 5126 Unless options described with "show only ..." are given, the
5125 5127 options -mardu are used.
5126 5128
5127 5129 Option -q/--quiet hides untracked (unknown and ignored) files
5128 5130 unless explicitly requested with -u/--unknown or -i/--ignored.
5129 5131
5130 5132 .. note::
5131 5133 status may appear to disagree with diff if permissions have
5132 5134 changed or a merge has occurred. The standard diff format does
5133 5135 not report permission changes and diff only reports changes
5134 5136 relative to one merge parent.
5135 5137
5136 5138 If one revision is given, it is used as the base revision.
5137 5139 If two revisions are given, the differences between them are
5138 5140 shown. The --change option can also be used as a shortcut to list
5139 5141 the changed files of a revision from its first parent.
5140 5142
5141 5143 The codes used to show the status of files are::
5142 5144
5143 5145 M = modified
5144 5146 A = added
5145 5147 R = removed
5146 5148 C = clean
5147 5149 ! = missing (deleted by non-hg command, but still tracked)
5148 5150 ? = not tracked
5149 5151 I = ignored
5150 5152 = origin of the previous file listed as A (added)
5151 5153
5152 5154 .. container:: verbose
5153 5155
5154 5156 Examples:
5155 5157
5156 5158 - show changes in the working directory relative to a changeset:
5157 5159
5158 5160 hg status --rev 9353
5159 5161
5160 5162 - show all changes including copies in an existing changeset::
5161 5163
5162 5164 hg status --copies --change 9353
5163 5165
5164 5166 - get a NUL separated list of added files, suitable for xargs::
5165 5167
5166 5168 hg status -an0
5167 5169
5168 5170 Returns 0 on success.
5169 5171 """
5170 5172
5171 5173 revs = opts.get('rev')
5172 5174 change = opts.get('change')
5173 5175
5174 5176 if revs and change:
5175 5177 msg = _('cannot specify --rev and --change at the same time')
5176 5178 raise util.Abort(msg)
5177 5179 elif change:
5178 5180 node2 = scmutil.revsingle(repo, change, None).node()
5179 5181 node1 = repo[node2].p1().node()
5180 5182 else:
5181 5183 node1, node2 = scmutil.revpair(repo, revs)
5182 5184
5183 5185 cwd = (pats and repo.getcwd()) or ''
5184 5186 end = opts.get('print0') and '\0' or '\n'
5185 5187 copy = {}
5186 5188 states = 'modified added removed deleted unknown ignored clean'.split()
5187 5189 show = [k for k in states if opts.get(k)]
5188 5190 if opts.get('all'):
5189 5191 show += ui.quiet and (states[:4] + ['clean']) or states
5190 5192 if not show:
5191 5193 show = ui.quiet and states[:4] or states[:5]
5192 5194
5193 5195 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5194 5196 'ignored' in show, 'clean' in show, 'unknown' in show,
5195 5197 opts.get('subrepos'))
5196 5198 changestates = zip(states, 'MAR!?IC', stat)
5197 5199
5198 5200 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5199 5201 ctxn = repo[nullid]
5200 5202 ctx1 = repo[node1]
5201 5203 ctx2 = repo[node2]
5202 5204 added = stat[1]
5203 5205 if node2 is None:
5204 5206 added = stat[0] + stat[1] # merged?
5205 5207
5206 5208 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
5207 5209 if k in added:
5208 5210 copy[k] = v
5209 5211 elif v in added:
5210 5212 copy[v] = k
5211 5213
5212 5214 for state, char, files in changestates:
5213 5215 if state in show:
5214 5216 format = "%s %%s%s" % (char, end)
5215 5217 if opts.get('no_status'):
5216 5218 format = "%%s%s" % end
5217 5219
5218 5220 for f in files:
5219 5221 ui.write(format % repo.pathto(f, cwd),
5220 5222 label='status.' + state)
5221 5223 if f in copy:
5222 5224 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
5223 5225 label='status.copied')
5224 5226
5225 5227 @command('^summary|sum',
5226 5228 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5227 5229 def summary(ui, repo, **opts):
5228 5230 """summarize working directory state
5229 5231
5230 5232 This generates a brief summary of the working directory state,
5231 5233 including parents, branch, commit status, and available updates.
5232 5234
5233 5235 With the --remote option, this will check the default paths for
5234 5236 incoming and outgoing changes. This can be time-consuming.
5235 5237
5236 5238 Returns 0 on success.
5237 5239 """
5238 5240
5239 5241 ctx = repo[None]
5240 5242 parents = ctx.parents()
5241 5243 pnode = parents[0].node()
5242 5244 marks = []
5243 5245
5244 5246 for p in parents:
5245 5247 # label with log.changeset (instead of log.parent) since this
5246 5248 # shows a working directory parent *changeset*:
5247 5249 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5248 5250 label='log.changeset')
5249 5251 ui.write(' '.join(p.tags()), label='log.tag')
5250 5252 if p.bookmarks():
5251 5253 marks.extend(p.bookmarks())
5252 5254 if p.rev() == -1:
5253 5255 if not len(repo):
5254 5256 ui.write(_(' (empty repository)'))
5255 5257 else:
5256 5258 ui.write(_(' (no revision checked out)'))
5257 5259 ui.write('\n')
5258 5260 if p.description():
5259 5261 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5260 5262 label='log.summary')
5261 5263
5262 5264 branch = ctx.branch()
5263 5265 bheads = repo.branchheads(branch)
5264 5266 m = _('branch: %s\n') % branch
5265 5267 if branch != 'default':
5266 5268 ui.write(m, label='log.branch')
5267 5269 else:
5268 5270 ui.status(m, label='log.branch')
5269 5271
5270 5272 if marks:
5271 5273 current = repo._bookmarkcurrent
5272 5274 ui.write(_('bookmarks:'), label='log.bookmark')
5273 5275 if current is not None:
5274 5276 try:
5275 5277 marks.remove(current)
5276 5278 ui.write(' *' + current, label='bookmarks.current')
5277 5279 except ValueError:
5278 5280 # current bookmark not in parent ctx marks
5279 5281 pass
5280 5282 for m in marks:
5281 5283 ui.write(' ' + m, label='log.bookmark')
5282 5284 ui.write('\n', label='log.bookmark')
5283 5285
5284 5286 st = list(repo.status(unknown=True))[:6]
5285 5287
5286 5288 c = repo.dirstate.copies()
5287 5289 copied, renamed = [], []
5288 5290 for d, s in c.iteritems():
5289 5291 if s in st[2]:
5290 5292 st[2].remove(s)
5291 5293 renamed.append(d)
5292 5294 else:
5293 5295 copied.append(d)
5294 5296 if d in st[1]:
5295 5297 st[1].remove(d)
5296 5298 st.insert(3, renamed)
5297 5299 st.insert(4, copied)
5298 5300
5299 5301 ms = mergemod.mergestate(repo)
5300 5302 st.append([f for f in ms if ms[f] == 'u'])
5301 5303
5302 5304 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5303 5305 st.append(subs)
5304 5306
5305 5307 labels = [ui.label(_('%d modified'), 'status.modified'),
5306 5308 ui.label(_('%d added'), 'status.added'),
5307 5309 ui.label(_('%d removed'), 'status.removed'),
5308 5310 ui.label(_('%d renamed'), 'status.copied'),
5309 5311 ui.label(_('%d copied'), 'status.copied'),
5310 5312 ui.label(_('%d deleted'), 'status.deleted'),
5311 5313 ui.label(_('%d unknown'), 'status.unknown'),
5312 5314 ui.label(_('%d ignored'), 'status.ignored'),
5313 5315 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5314 5316 ui.label(_('%d subrepos'), 'status.modified')]
5315 5317 t = []
5316 5318 for s, l in zip(st, labels):
5317 5319 if s:
5318 5320 t.append(l % len(s))
5319 5321
5320 5322 t = ', '.join(t)
5321 5323 cleanworkdir = False
5322 5324
5323 5325 if len(parents) > 1:
5324 5326 t += _(' (merge)')
5325 5327 elif branch != parents[0].branch():
5326 5328 t += _(' (new branch)')
5327 5329 elif (parents[0].extra().get('close') and
5328 5330 pnode in repo.branchheads(branch, closed=True)):
5329 5331 t += _(' (head closed)')
5330 5332 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5331 5333 t += _(' (clean)')
5332 5334 cleanworkdir = True
5333 5335 elif pnode not in bheads:
5334 5336 t += _(' (new branch head)')
5335 5337
5336 5338 if cleanworkdir:
5337 5339 ui.status(_('commit: %s\n') % t.strip())
5338 5340 else:
5339 5341 ui.write(_('commit: %s\n') % t.strip())
5340 5342
5341 5343 # all ancestors of branch heads - all ancestors of parent = new csets
5342 5344 new = [0] * len(repo)
5343 5345 cl = repo.changelog
5344 5346 for a in [cl.rev(n) for n in bheads]:
5345 5347 new[a] = 1
5346 5348 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5347 5349 new[a] = 1
5348 5350 for a in [p.rev() for p in parents]:
5349 5351 if a >= 0:
5350 5352 new[a] = 0
5351 5353 for a in cl.ancestors(*[p.rev() for p in parents]):
5352 5354 new[a] = 0
5353 5355 new = sum(new)
5354 5356
5355 5357 if new == 0:
5356 5358 ui.status(_('update: (current)\n'))
5357 5359 elif pnode not in bheads:
5358 5360 ui.write(_('update: %d new changesets (update)\n') % new)
5359 5361 else:
5360 5362 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5361 5363 (new, len(bheads)))
5362 5364
5363 5365 if opts.get('remote'):
5364 5366 t = []
5365 5367 source, branches = hg.parseurl(ui.expandpath('default'))
5366 5368 other = hg.peer(repo, {}, source)
5367 5369 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5368 5370 ui.debug('comparing with %s\n' % util.hidepassword(source))
5369 5371 repo.ui.pushbuffer()
5370 5372 commoninc = discovery.findcommonincoming(repo, other)
5371 5373 _common, incoming, _rheads = commoninc
5372 5374 repo.ui.popbuffer()
5373 5375 if incoming:
5374 5376 t.append(_('1 or more incoming'))
5375 5377
5376 5378 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5377 5379 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5378 5380 if source != dest:
5379 5381 other = hg.peer(repo, {}, dest)
5380 5382 commoninc = None
5381 5383 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5382 5384 repo.ui.pushbuffer()
5383 5385 common, outheads = discovery.findcommonoutgoing(repo, other,
5384 5386 commoninc=commoninc)
5385 5387 repo.ui.popbuffer()
5386 5388 o = repo.changelog.findmissing(common=common, heads=outheads)
5387 5389 if o:
5388 5390 t.append(_('%d outgoing') % len(o))
5389 5391 if 'bookmarks' in other.listkeys('namespaces'):
5390 5392 lmarks = repo.listkeys('bookmarks')
5391 5393 rmarks = other.listkeys('bookmarks')
5392 5394 diff = set(rmarks) - set(lmarks)
5393 5395 if len(diff) > 0:
5394 5396 t.append(_('%d incoming bookmarks') % len(diff))
5395 5397 diff = set(lmarks) - set(rmarks)
5396 5398 if len(diff) > 0:
5397 5399 t.append(_('%d outgoing bookmarks') % len(diff))
5398 5400
5399 5401 if t:
5400 5402 ui.write(_('remote: %s\n') % (', '.join(t)))
5401 5403 else:
5402 5404 ui.status(_('remote: (synced)\n'))
5403 5405
5404 5406 @command('tag',
5405 5407 [('f', 'force', None, _('force tag')),
5406 5408 ('l', 'local', None, _('make the tag local')),
5407 5409 ('r', 'rev', '', _('revision to tag'), _('REV')),
5408 5410 ('', 'remove', None, _('remove a tag')),
5409 5411 # -l/--local is already there, commitopts cannot be used
5410 5412 ('e', 'edit', None, _('edit commit message')),
5411 5413 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5412 5414 ] + commitopts2,
5413 5415 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5414 5416 def tag(ui, repo, name1, *names, **opts):
5415 5417 """add one or more tags for the current or given revision
5416 5418
5417 5419 Name a particular revision using <name>.
5418 5420
5419 5421 Tags are used to name particular revisions of the repository and are
5420 5422 very useful to compare different revisions, to go back to significant
5421 5423 earlier versions or to mark branch points as releases, etc. Changing
5422 5424 an existing tag is normally disallowed; use -f/--force to override.
5423 5425
5424 5426 If no revision is given, the parent of the working directory is
5425 5427 used, or tip if no revision is checked out.
5426 5428
5427 5429 To facilitate version control, distribution, and merging of tags,
5428 5430 they are stored as a file named ".hgtags" which is managed similarly
5429 5431 to other project files and can be hand-edited if necessary. This
5430 5432 also means that tagging creates a new commit. The file
5431 5433 ".hg/localtags" is used for local tags (not shared among
5432 5434 repositories).
5433 5435
5434 5436 Tag commits are usually made at the head of a branch. If the parent
5435 5437 of the working directory is not a branch head, :hg:`tag` aborts; use
5436 5438 -f/--force to force the tag commit to be based on a non-head
5437 5439 changeset.
5438 5440
5439 5441 See :hg:`help dates` for a list of formats valid for -d/--date.
5440 5442
5441 5443 Since tag names have priority over branch names during revision
5442 5444 lookup, using an existing branch name as a tag name is discouraged.
5443 5445
5444 5446 Returns 0 on success.
5445 5447 """
5446 5448
5447 5449 rev_ = "."
5448 5450 names = [t.strip() for t in (name1,) + names]
5449 5451 if len(names) != len(set(names)):
5450 5452 raise util.Abort(_('tag names must be unique'))
5451 5453 for n in names:
5452 5454 if n in ['tip', '.', 'null']:
5453 5455 raise util.Abort(_("the name '%s' is reserved") % n)
5454 5456 if not n:
5455 5457 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5456 5458 if opts.get('rev') and opts.get('remove'):
5457 5459 raise util.Abort(_("--rev and --remove are incompatible"))
5458 5460 if opts.get('rev'):
5459 5461 rev_ = opts['rev']
5460 5462 message = opts.get('message')
5461 5463 if opts.get('remove'):
5462 5464 expectedtype = opts.get('local') and 'local' or 'global'
5463 5465 for n in names:
5464 5466 if not repo.tagtype(n):
5465 5467 raise util.Abort(_("tag '%s' does not exist") % n)
5466 5468 if repo.tagtype(n) != expectedtype:
5467 5469 if expectedtype == 'global':
5468 5470 raise util.Abort(_("tag '%s' is not a global tag") % n)
5469 5471 else:
5470 5472 raise util.Abort(_("tag '%s' is not a local tag") % n)
5471 5473 rev_ = nullid
5472 5474 if not message:
5473 5475 # we don't translate commit messages
5474 5476 message = 'Removed tag %s' % ', '.join(names)
5475 5477 elif not opts.get('force'):
5476 5478 for n in names:
5477 5479 if n in repo.tags():
5478 5480 raise util.Abort(_("tag '%s' already exists "
5479 5481 "(use -f to force)") % n)
5480 5482 if not opts.get('local'):
5481 5483 p1, p2 = repo.dirstate.parents()
5482 5484 if p2 != nullid:
5483 5485 raise util.Abort(_('uncommitted merge'))
5484 5486 bheads = repo.branchheads()
5485 5487 if not opts.get('force') and bheads and p1 not in bheads:
5486 5488 raise util.Abort(_('not at a branch head (use -f to force)'))
5487 5489 r = scmutil.revsingle(repo, rev_).node()
5488 5490
5489 5491 if not message:
5490 5492 # we don't translate commit messages
5491 5493 message = ('Added tag %s for changeset %s' %
5492 5494 (', '.join(names), short(r)))
5493 5495
5494 5496 date = opts.get('date')
5495 5497 if date:
5496 5498 date = util.parsedate(date)
5497 5499
5498 5500 if opts.get('edit'):
5499 5501 message = ui.edit(message, ui.username())
5500 5502
5501 5503 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5502 5504
5503 5505 @command('tags', [], '')
5504 5506 def tags(ui, repo):
5505 5507 """list repository tags
5506 5508
5507 5509 This lists both regular and local tags. When the -v/--verbose
5508 5510 switch is used, a third column "local" is printed for local tags.
5509 5511
5510 5512 Returns 0 on success.
5511 5513 """
5512 5514
5513 5515 hexfunc = ui.debugflag and hex or short
5514 5516 tagtype = ""
5515 5517
5516 5518 for t, n in reversed(repo.tagslist()):
5517 5519 if ui.quiet:
5518 5520 ui.write("%s\n" % t, label='tags.normal')
5519 5521 continue
5520 5522
5521 5523 hn = hexfunc(n)
5522 5524 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5523 5525 rev = ui.label(r, 'log.changeset')
5524 5526 spaces = " " * (30 - encoding.colwidth(t))
5525 5527
5526 5528 tag = ui.label(t, 'tags.normal')
5527 5529 if ui.verbose:
5528 5530 if repo.tagtype(t) == 'local':
5529 5531 tagtype = " local"
5530 5532 tag = ui.label(t, 'tags.local')
5531 5533 else:
5532 5534 tagtype = ""
5533 5535 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5534 5536
5535 5537 @command('tip',
5536 5538 [('p', 'patch', None, _('show patch')),
5537 5539 ('g', 'git', None, _('use git extended diff format')),
5538 5540 ] + templateopts,
5539 5541 _('[-p] [-g]'))
5540 5542 def tip(ui, repo, **opts):
5541 5543 """show the tip revision
5542 5544
5543 5545 The tip revision (usually just called the tip) is the changeset
5544 5546 most recently added to the repository (and therefore the most
5545 5547 recently changed head).
5546 5548
5547 5549 If you have just made a commit, that commit will be the tip. If
5548 5550 you have just pulled changes from another repository, the tip of
5549 5551 that repository becomes the current tip. The "tip" tag is special
5550 5552 and cannot be renamed or assigned to a different changeset.
5551 5553
5552 5554 Returns 0 on success.
5553 5555 """
5554 5556 displayer = cmdutil.show_changeset(ui, repo, opts)
5555 5557 displayer.show(repo[len(repo) - 1])
5556 5558 displayer.close()
5557 5559
5558 5560 @command('unbundle',
5559 5561 [('u', 'update', None,
5560 5562 _('update to new branch head if changesets were unbundled'))],
5561 5563 _('[-u] FILE...'))
5562 5564 def unbundle(ui, repo, fname1, *fnames, **opts):
5563 5565 """apply one or more changegroup files
5564 5566
5565 5567 Apply one or more compressed changegroup files generated by the
5566 5568 bundle command.
5567 5569
5568 5570 Returns 0 on success, 1 if an update has unresolved files.
5569 5571 """
5570 5572 fnames = (fname1,) + fnames
5571 5573
5572 5574 lock = repo.lock()
5573 5575 wc = repo['.']
5574 5576 try:
5575 5577 for fname in fnames:
5576 5578 f = url.open(ui, fname)
5577 5579 gen = changegroup.readbundle(f, fname)
5578 5580 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5579 5581 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5580 5582 finally:
5581 5583 lock.release()
5582 5584 return postincoming(ui, repo, modheads, opts.get('update'), None)
5583 5585
5584 5586 @command('^update|up|checkout|co',
5585 5587 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5586 5588 ('c', 'check', None,
5587 5589 _('update across branches if no uncommitted changes')),
5588 5590 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5589 5591 ('r', 'rev', '', _('revision'), _('REV'))],
5590 5592 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5591 5593 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5592 5594 """update working directory (or switch revisions)
5593 5595
5594 5596 Update the repository's working directory to the specified
5595 5597 changeset. If no changeset is specified, update to the tip of the
5596 5598 current named branch.
5597 5599
5598 5600 If the changeset is not a descendant of the working directory's
5599 5601 parent, the update is aborted. With the -c/--check option, the
5600 5602 working directory is checked for uncommitted changes; if none are
5601 5603 found, the working directory is updated to the specified
5602 5604 changeset.
5603 5605
5604 5606 Update sets the working directory's parent revison to the specified
5605 5607 changeset (see :hg:`help parents`).
5606 5608
5607 5609 The following rules apply when the working directory contains
5608 5610 uncommitted changes:
5609 5611
5610 5612 1. If neither -c/--check nor -C/--clean is specified, and if
5611 5613 the requested changeset is an ancestor or descendant of
5612 5614 the working directory's parent, the uncommitted changes
5613 5615 are merged into the requested changeset and the merged
5614 5616 result is left uncommitted. If the requested changeset is
5615 5617 not an ancestor or descendant (that is, it is on another
5616 5618 branch), the update is aborted and the uncommitted changes
5617 5619 are preserved.
5618 5620
5619 5621 2. With the -c/--check option, the update is aborted and the
5620 5622 uncommitted changes are preserved.
5621 5623
5622 5624 3. With the -C/--clean option, uncommitted changes are discarded and
5623 5625 the working directory is updated to the requested changeset.
5624 5626
5625 5627 Use null as the changeset to remove the working directory (like
5626 5628 :hg:`clone -U`).
5627 5629
5628 5630 If you want to revert just one file to an older revision, use
5629 5631 :hg:`revert [-r REV] NAME`.
5630 5632
5631 5633 See :hg:`help dates` for a list of formats valid for -d/--date.
5632 5634
5633 5635 Returns 0 on success, 1 if there are unresolved files.
5634 5636 """
5635 5637 if rev and node:
5636 5638 raise util.Abort(_("please specify just one revision"))
5637 5639
5638 5640 if rev is None or rev == '':
5639 5641 rev = node
5640 5642
5641 5643 # if we defined a bookmark, we have to remember the original bookmark name
5642 5644 brev = rev
5643 5645 rev = scmutil.revsingle(repo, rev, rev).rev()
5644 5646
5645 5647 if check and clean:
5646 5648 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5647 5649
5648 5650 if check:
5649 5651 # we could use dirty() but we can ignore merge and branch trivia
5650 5652 c = repo[None]
5651 5653 if c.modified() or c.added() or c.removed():
5652 5654 raise util.Abort(_("uncommitted local changes"))
5653 5655
5654 5656 if date:
5655 5657 if rev is not None:
5656 5658 raise util.Abort(_("you can't specify a revision and a date"))
5657 5659 rev = cmdutil.finddate(ui, repo, date)
5658 5660
5659 5661 if clean or check:
5660 5662 ret = hg.clean(repo, rev)
5661 5663 else:
5662 5664 ret = hg.update(repo, rev)
5663 5665
5664 5666 if brev in repo._bookmarks:
5665 5667 bookmarks.setcurrent(repo, brev)
5666 5668
5667 5669 return ret
5668 5670
5669 5671 @command('verify', [])
5670 5672 def verify(ui, repo):
5671 5673 """verify the integrity of the repository
5672 5674
5673 5675 Verify the integrity of the current repository.
5674 5676
5675 5677 This will perform an extensive check of the repository's
5676 5678 integrity, validating the hashes and checksums of each entry in
5677 5679 the changelog, manifest, and tracked files, as well as the
5678 5680 integrity of their crosslinks and indices.
5679 5681
5680 5682 Returns 0 on success, 1 if errors are encountered.
5681 5683 """
5682 5684 return hg.verify(repo)
5683 5685
5684 5686 @command('version', [])
5685 5687 def version_(ui):
5686 5688 """output version and copyright information"""
5687 5689 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5688 5690 % util.version())
5689 5691 ui.status(_(
5690 5692 "(see http://mercurial.selenic.com for more information)\n"
5691 5693 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5692 5694 "This is free software; see the source for copying conditions. "
5693 5695 "There is NO\nwarranty; "
5694 5696 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5695 5697 ))
5696 5698
5697 5699 norepo = ("clone init version help debugcommands debugcomplete"
5698 5700 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5699 5701 " debugknown debuggetbundle debugbundle")
5700 5702 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5701 5703 " debugdata debugindex debugindexdot debugrevlog")
@@ -1,1923 +1,1924 b''
1 1 > do_push()
2 2 > {
3 3 > user=$1
4 4 > shift
5 5 > echo "Pushing as user $user"
6 6 > echo 'hgrc = """'
7 7 > sed -e 1,2d b/.hg/hgrc | grep -v fakegroups.py
8 8 > echo '"""'
9 9 > if test -f acl.config; then
10 10 > echo 'acl.config = """'
11 11 > cat acl.config
12 12 > echo '"""'
13 13 > fi
14 14 > # On AIX /etc/profile sets LOGNAME read-only. So
15 15 > # LOGNAME=$user hg --cws a --debug push ../b
16 16 > # fails with "This variable is read only."
17 17 > # Use env to work around this.
18 18 > env LOGNAME=$user hg --cwd a --debug push ../b
19 19 > hg --cwd b rollback
20 20 > hg --cwd b --quiet tip
21 21 > echo
22 22 > }
23 23
24 24 > init_config()
25 25 > {
26 26 > cat > fakegroups.py <<EOF
27 27 > from hgext import acl
28 28 > def fakegetusers(ui, group):
29 29 > try:
30 30 > return acl._getusersorig(ui, group)
31 31 > except:
32 32 > return ["fred", "betty"]
33 33 > acl._getusersorig = acl._getusers
34 34 > acl._getusers = fakegetusers
35 35 > EOF
36 36 > rm -f acl.config
37 37 > cat > $config <<EOF
38 38 > [hooks]
39 39 > pretxnchangegroup.acl = python:hgext.acl.hook
40 40 > [acl]
41 41 > sources = push
42 42 > [extensions]
43 43 > f=`pwd`/fakegroups.py
44 44 > EOF
45 45 > }
46 46
47 47 $ hg init a
48 48 $ cd a
49 49 $ mkdir foo foo/Bar quux
50 50 $ echo 'in foo' > foo/file.txt
51 51 $ echo 'in foo/Bar' > foo/Bar/file.txt
52 52 $ echo 'in quux' > quux/file.py
53 53 $ hg add -q
54 54 $ hg ci -m 'add files' -d '1000000 0'
55 55 $ echo >> foo/file.txt
56 56 $ hg ci -m 'change foo/file' -d '1000001 0'
57 57 $ echo >> foo/Bar/file.txt
58 58 $ hg ci -m 'change foo/Bar/file' -d '1000002 0'
59 59 $ echo >> quux/file.py
60 60 $ hg ci -m 'change quux/file' -d '1000003 0'
61 61 $ hg tip --quiet
62 62 3:911600dab2ae
63 63
64 64 $ cd ..
65 65 $ hg clone -r 0 a b
66 66 adding changesets
67 67 adding manifests
68 68 adding file changes
69 69 added 1 changesets with 3 changes to 3 files
70 70 updating to branch default
71 71 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
72 72
73 73 $ echo '[extensions]' >> $HGRCPATH
74 74 $ echo 'acl =' >> $HGRCPATH
75 75
76 76 $ config=b/.hg/hgrc
77 77
78 78 Extension disabled for lack of a hook
79 79
80 80 $ do_push fred
81 81 Pushing as user fred
82 82 hgrc = """
83 83 """
84 84 pushing to ../b
85 85 query 1; heads
86 86 searching for changes
87 87 all remote heads known locally
88 88 3 changesets found
89 89 list of changesets:
90 90 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
91 91 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
92 92 911600dab2ae7a9baff75958b84fe606851ce955
93 93 adding changesets
94 94 bundling: 1/3 changesets (33.33%)
95 95 bundling: 2/3 changesets (66.67%)
96 96 bundling: 3/3 changesets (100.00%)
97 97 bundling: 1/3 manifests (33.33%)
98 98 bundling: 2/3 manifests (66.67%)
99 99 bundling: 3/3 manifests (100.00%)
100 100 bundling: foo/Bar/file.txt 1/3 files (33.33%)
101 101 bundling: foo/file.txt 2/3 files (66.67%)
102 102 bundling: quux/file.py 3/3 files (100.00%)
103 103 changesets: 1 chunks
104 104 add changeset ef1ea85a6374
105 105 changesets: 2 chunks
106 106 add changeset f9cafe1212c8
107 107 changesets: 3 chunks
108 108 add changeset 911600dab2ae
109 109 adding manifests
110 110 manifests: 1/3 chunks (33.33%)
111 111 manifests: 2/3 chunks (66.67%)
112 112 manifests: 3/3 chunks (100.00%)
113 113 adding file changes
114 114 adding foo/Bar/file.txt revisions
115 115 files: 1/3 chunks (33.33%)
116 116 adding foo/file.txt revisions
117 117 files: 2/3 chunks (66.67%)
118 118 adding quux/file.py revisions
119 119 files: 3/3 chunks (100.00%)
120 120 added 3 changesets with 3 changes to 3 files
121 121 updating the branch cache
122 122 checking for updated bookmarks
123 123 repository tip rolled back to revision 0 (undo push)
124 124 0:6675d58eff77
125 125
126 126
127 127 $ echo '[hooks]' >> $config
128 128 $ echo 'pretxnchangegroup.acl = python:hgext.acl.hook' >> $config
129 129
130 130 Extension disabled for lack of acl.sources
131 131
132 132 $ do_push fred
133 133 Pushing as user fred
134 134 hgrc = """
135 135 [hooks]
136 136 pretxnchangegroup.acl = python:hgext.acl.hook
137 137 """
138 138 pushing to ../b
139 139 query 1; heads
140 140 searching for changes
141 141 all remote heads known locally
142 142 invalidating branch cache (tip differs)
143 143 3 changesets found
144 144 list of changesets:
145 145 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
146 146 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
147 147 911600dab2ae7a9baff75958b84fe606851ce955
148 148 adding changesets
149 149 bundling: 1/3 changesets (33.33%)
150 150 bundling: 2/3 changesets (66.67%)
151 151 bundling: 3/3 changesets (100.00%)
152 152 bundling: 1/3 manifests (33.33%)
153 153 bundling: 2/3 manifests (66.67%)
154 154 bundling: 3/3 manifests (100.00%)
155 155 bundling: foo/Bar/file.txt 1/3 files (33.33%)
156 156 bundling: foo/file.txt 2/3 files (66.67%)
157 157 bundling: quux/file.py 3/3 files (100.00%)
158 158 changesets: 1 chunks
159 159 add changeset ef1ea85a6374
160 160 changesets: 2 chunks
161 161 add changeset f9cafe1212c8
162 162 changesets: 3 chunks
163 163 add changeset 911600dab2ae
164 164 adding manifests
165 165 manifests: 1/3 chunks (33.33%)
166 166 manifests: 2/3 chunks (66.67%)
167 167 manifests: 3/3 chunks (100.00%)
168 168 adding file changes
169 169 adding foo/Bar/file.txt revisions
170 170 files: 1/3 chunks (33.33%)
171 171 adding foo/file.txt revisions
172 172 files: 2/3 chunks (66.67%)
173 173 adding quux/file.py revisions
174 174 files: 3/3 chunks (100.00%)
175 175 added 3 changesets with 3 changes to 3 files
176 176 calling hook pretxnchangegroup.acl: hgext.acl.hook
177 177 acl: changes have source "push" - skipping
178 178 updating the branch cache
179 179 checking for updated bookmarks
180 180 repository tip rolled back to revision 0 (undo push)
181 181 0:6675d58eff77
182 182
183 183
184 184 No [acl.allow]/[acl.deny]
185 185
186 186 $ echo '[acl]' >> $config
187 187 $ echo 'sources = push' >> $config
188 188 $ do_push fred
189 189 Pushing as user fred
190 190 hgrc = """
191 191 [hooks]
192 192 pretxnchangegroup.acl = python:hgext.acl.hook
193 193 [acl]
194 194 sources = push
195 195 """
196 196 pushing to ../b
197 197 query 1; heads
198 198 searching for changes
199 199 all remote heads known locally
200 200 invalidating branch cache (tip differs)
201 201 3 changesets found
202 202 list of changesets:
203 203 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
204 204 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
205 205 911600dab2ae7a9baff75958b84fe606851ce955
206 206 adding changesets
207 207 bundling: 1/3 changesets (33.33%)
208 208 bundling: 2/3 changesets (66.67%)
209 209 bundling: 3/3 changesets (100.00%)
210 210 bundling: 1/3 manifests (33.33%)
211 211 bundling: 2/3 manifests (66.67%)
212 212 bundling: 3/3 manifests (100.00%)
213 213 bundling: foo/Bar/file.txt 1/3 files (33.33%)
214 214 bundling: foo/file.txt 2/3 files (66.67%)
215 215 bundling: quux/file.py 3/3 files (100.00%)
216 216 changesets: 1 chunks
217 217 add changeset ef1ea85a6374
218 218 changesets: 2 chunks
219 219 add changeset f9cafe1212c8
220 220 changesets: 3 chunks
221 221 add changeset 911600dab2ae
222 222 adding manifests
223 223 manifests: 1/3 chunks (33.33%)
224 224 manifests: 2/3 chunks (66.67%)
225 225 manifests: 3/3 chunks (100.00%)
226 226 adding file changes
227 227 adding foo/Bar/file.txt revisions
228 228 files: 1/3 chunks (33.33%)
229 229 adding foo/file.txt revisions
230 230 files: 2/3 chunks (66.67%)
231 231 adding quux/file.py revisions
232 232 files: 3/3 chunks (100.00%)
233 233 added 3 changesets with 3 changes to 3 files
234 234 calling hook pretxnchangegroup.acl: hgext.acl.hook
235 235 acl: checking access for user "fred"
236 236 acl: acl.allow.branches not enabled
237 237 acl: acl.deny.branches not enabled
238 238 acl: acl.allow not enabled
239 239 acl: acl.deny not enabled
240 240 acl: branch access granted: "ef1ea85a6374" on branch "default"
241 241 acl: path access granted: "ef1ea85a6374"
242 242 acl: branch access granted: "f9cafe1212c8" on branch "default"
243 243 acl: path access granted: "f9cafe1212c8"
244 244 acl: branch access granted: "911600dab2ae" on branch "default"
245 245 acl: path access granted: "911600dab2ae"
246 246 updating the branch cache
247 247 checking for updated bookmarks
248 248 repository tip rolled back to revision 0 (undo push)
249 249 0:6675d58eff77
250 250
251 251
252 252 Empty [acl.allow]
253 253
254 254 $ echo '[acl.allow]' >> $config
255 255 $ do_push fred
256 256 Pushing as user fred
257 257 hgrc = """
258 258 [hooks]
259 259 pretxnchangegroup.acl = python:hgext.acl.hook
260 260 [acl]
261 261 sources = push
262 262 [acl.allow]
263 263 """
264 264 pushing to ../b
265 265 query 1; heads
266 266 searching for changes
267 267 all remote heads known locally
268 268 invalidating branch cache (tip differs)
269 269 3 changesets found
270 270 list of changesets:
271 271 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
272 272 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
273 273 911600dab2ae7a9baff75958b84fe606851ce955
274 274 adding changesets
275 275 bundling: 1/3 changesets (33.33%)
276 276 bundling: 2/3 changesets (66.67%)
277 277 bundling: 3/3 changesets (100.00%)
278 278 bundling: 1/3 manifests (33.33%)
279 279 bundling: 2/3 manifests (66.67%)
280 280 bundling: 3/3 manifests (100.00%)
281 281 bundling: foo/Bar/file.txt 1/3 files (33.33%)
282 282 bundling: foo/file.txt 2/3 files (66.67%)
283 283 bundling: quux/file.py 3/3 files (100.00%)
284 284 changesets: 1 chunks
285 285 add changeset ef1ea85a6374
286 286 changesets: 2 chunks
287 287 add changeset f9cafe1212c8
288 288 changesets: 3 chunks
289 289 add changeset 911600dab2ae
290 290 adding manifests
291 291 manifests: 1/3 chunks (33.33%)
292 292 manifests: 2/3 chunks (66.67%)
293 293 manifests: 3/3 chunks (100.00%)
294 294 adding file changes
295 295 adding foo/Bar/file.txt revisions
296 296 files: 1/3 chunks (33.33%)
297 297 adding foo/file.txt revisions
298 298 files: 2/3 chunks (66.67%)
299 299 adding quux/file.py revisions
300 300 files: 3/3 chunks (100.00%)
301 301 added 3 changesets with 3 changes to 3 files
302 302 calling hook pretxnchangegroup.acl: hgext.acl.hook
303 303 acl: checking access for user "fred"
304 304 acl: acl.allow.branches not enabled
305 305 acl: acl.deny.branches not enabled
306 306 acl: acl.allow enabled, 0 entries for user fred
307 307 acl: acl.deny not enabled
308 308 acl: branch access granted: "ef1ea85a6374" on branch "default"
309 309 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
310 310 transaction abort!
311 311 rollback completed
312 312 abort: acl: user "fred" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
313 313 no rollback information available
314 314 0:6675d58eff77
315 315
316 316
317 317 fred is allowed inside foo/
318 318
319 319 $ echo 'foo/** = fred' >> $config
320 320 $ do_push fred
321 321 Pushing as user fred
322 322 hgrc = """
323 323 [hooks]
324 324 pretxnchangegroup.acl = python:hgext.acl.hook
325 325 [acl]
326 326 sources = push
327 327 [acl.allow]
328 328 foo/** = fred
329 329 """
330 330 pushing to ../b
331 331 query 1; heads
332 332 searching for changes
333 333 all remote heads known locally
334 334 3 changesets found
335 335 list of changesets:
336 336 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
337 337 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
338 338 911600dab2ae7a9baff75958b84fe606851ce955
339 339 adding changesets
340 340 bundling: 1/3 changesets (33.33%)
341 341 bundling: 2/3 changesets (66.67%)
342 342 bundling: 3/3 changesets (100.00%)
343 343 bundling: 1/3 manifests (33.33%)
344 344 bundling: 2/3 manifests (66.67%)
345 345 bundling: 3/3 manifests (100.00%)
346 346 bundling: foo/Bar/file.txt 1/3 files (33.33%)
347 347 bundling: foo/file.txt 2/3 files (66.67%)
348 348 bundling: quux/file.py 3/3 files (100.00%)
349 349 changesets: 1 chunks
350 350 add changeset ef1ea85a6374
351 351 changesets: 2 chunks
352 352 add changeset f9cafe1212c8
353 353 changesets: 3 chunks
354 354 add changeset 911600dab2ae
355 355 adding manifests
356 356 manifests: 1/3 chunks (33.33%)
357 357 manifests: 2/3 chunks (66.67%)
358 358 manifests: 3/3 chunks (100.00%)
359 359 adding file changes
360 360 adding foo/Bar/file.txt revisions
361 361 files: 1/3 chunks (33.33%)
362 362 adding foo/file.txt revisions
363 363 files: 2/3 chunks (66.67%)
364 364 adding quux/file.py revisions
365 365 files: 3/3 chunks (100.00%)
366 366 added 3 changesets with 3 changes to 3 files
367 367 calling hook pretxnchangegroup.acl: hgext.acl.hook
368 368 acl: checking access for user "fred"
369 369 acl: acl.allow.branches not enabled
370 370 acl: acl.deny.branches not enabled
371 371 acl: acl.allow enabled, 1 entries for user fred
372 372 acl: acl.deny not enabled
373 373 acl: branch access granted: "ef1ea85a6374" on branch "default"
374 374 acl: path access granted: "ef1ea85a6374"
375 375 acl: branch access granted: "f9cafe1212c8" on branch "default"
376 376 acl: path access granted: "f9cafe1212c8"
377 377 acl: branch access granted: "911600dab2ae" on branch "default"
378 378 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
379 379 transaction abort!
380 380 rollback completed
381 381 abort: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
382 382 no rollback information available
383 383 0:6675d58eff77
384 384
385 385
386 386 Empty [acl.deny]
387 387
388 388 $ echo '[acl.deny]' >> $config
389 389 $ do_push barney
390 390 Pushing as user barney
391 391 hgrc = """
392 392 [hooks]
393 393 pretxnchangegroup.acl = python:hgext.acl.hook
394 394 [acl]
395 395 sources = push
396 396 [acl.allow]
397 397 foo/** = fred
398 398 [acl.deny]
399 399 """
400 400 pushing to ../b
401 401 query 1; heads
402 402 searching for changes
403 403 all remote heads known locally
404 404 3 changesets found
405 405 list of changesets:
406 406 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
407 407 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
408 408 911600dab2ae7a9baff75958b84fe606851ce955
409 409 adding changesets
410 410 bundling: 1/3 changesets (33.33%)
411 411 bundling: 2/3 changesets (66.67%)
412 412 bundling: 3/3 changesets (100.00%)
413 413 bundling: 1/3 manifests (33.33%)
414 414 bundling: 2/3 manifests (66.67%)
415 415 bundling: 3/3 manifests (100.00%)
416 416 bundling: foo/Bar/file.txt 1/3 files (33.33%)
417 417 bundling: foo/file.txt 2/3 files (66.67%)
418 418 bundling: quux/file.py 3/3 files (100.00%)
419 419 changesets: 1 chunks
420 420 add changeset ef1ea85a6374
421 421 changesets: 2 chunks
422 422 add changeset f9cafe1212c8
423 423 changesets: 3 chunks
424 424 add changeset 911600dab2ae
425 425 adding manifests
426 426 manifests: 1/3 chunks (33.33%)
427 427 manifests: 2/3 chunks (66.67%)
428 428 manifests: 3/3 chunks (100.00%)
429 429 adding file changes
430 430 adding foo/Bar/file.txt revisions
431 431 files: 1/3 chunks (33.33%)
432 432 adding foo/file.txt revisions
433 433 files: 2/3 chunks (66.67%)
434 434 adding quux/file.py revisions
435 435 files: 3/3 chunks (100.00%)
436 436 added 3 changesets with 3 changes to 3 files
437 437 calling hook pretxnchangegroup.acl: hgext.acl.hook
438 438 acl: checking access for user "barney"
439 439 acl: acl.allow.branches not enabled
440 440 acl: acl.deny.branches not enabled
441 441 acl: acl.allow enabled, 0 entries for user barney
442 442 acl: acl.deny enabled, 0 entries for user barney
443 443 acl: branch access granted: "ef1ea85a6374" on branch "default"
444 444 error: pretxnchangegroup.acl hook failed: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
445 445 transaction abort!
446 446 rollback completed
447 447 abort: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
448 448 no rollback information available
449 449 0:6675d58eff77
450 450
451 451
452 452 fred is allowed inside foo/, but not foo/bar/ (case matters)
453 453
454 454 $ echo 'foo/bar/** = fred' >> $config
455 455 $ do_push fred
456 456 Pushing as user fred
457 457 hgrc = """
458 458 [hooks]
459 459 pretxnchangegroup.acl = python:hgext.acl.hook
460 460 [acl]
461 461 sources = push
462 462 [acl.allow]
463 463 foo/** = fred
464 464 [acl.deny]
465 465 foo/bar/** = fred
466 466 """
467 467 pushing to ../b
468 468 query 1; heads
469 469 searching for changes
470 470 all remote heads known locally
471 471 3 changesets found
472 472 list of changesets:
473 473 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
474 474 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
475 475 911600dab2ae7a9baff75958b84fe606851ce955
476 476 adding changesets
477 477 bundling: 1/3 changesets (33.33%)
478 478 bundling: 2/3 changesets (66.67%)
479 479 bundling: 3/3 changesets (100.00%)
480 480 bundling: 1/3 manifests (33.33%)
481 481 bundling: 2/3 manifests (66.67%)
482 482 bundling: 3/3 manifests (100.00%)
483 483 bundling: foo/Bar/file.txt 1/3 files (33.33%)
484 484 bundling: foo/file.txt 2/3 files (66.67%)
485 485 bundling: quux/file.py 3/3 files (100.00%)
486 486 changesets: 1 chunks
487 487 add changeset ef1ea85a6374
488 488 changesets: 2 chunks
489 489 add changeset f9cafe1212c8
490 490 changesets: 3 chunks
491 491 add changeset 911600dab2ae
492 492 adding manifests
493 493 manifests: 1/3 chunks (33.33%)
494 494 manifests: 2/3 chunks (66.67%)
495 495 manifests: 3/3 chunks (100.00%)
496 496 adding file changes
497 497 adding foo/Bar/file.txt revisions
498 498 files: 1/3 chunks (33.33%)
499 499 adding foo/file.txt revisions
500 500 files: 2/3 chunks (66.67%)
501 501 adding quux/file.py revisions
502 502 files: 3/3 chunks (100.00%)
503 503 added 3 changesets with 3 changes to 3 files
504 504 calling hook pretxnchangegroup.acl: hgext.acl.hook
505 505 acl: checking access for user "fred"
506 506 acl: acl.allow.branches not enabled
507 507 acl: acl.deny.branches not enabled
508 508 acl: acl.allow enabled, 1 entries for user fred
509 509 acl: acl.deny enabled, 1 entries for user fred
510 510 acl: branch access granted: "ef1ea85a6374" on branch "default"
511 511 acl: path access granted: "ef1ea85a6374"
512 512 acl: branch access granted: "f9cafe1212c8" on branch "default"
513 513 acl: path access granted: "f9cafe1212c8"
514 514 acl: branch access granted: "911600dab2ae" on branch "default"
515 515 error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
516 516 transaction abort!
517 517 rollback completed
518 518 abort: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
519 519 no rollback information available
520 520 0:6675d58eff77
521 521
522 522
523 523 fred is allowed inside foo/, but not foo/Bar/
524 524
525 525 $ echo 'foo/Bar/** = fred' >> $config
526 526 $ do_push fred
527 527 Pushing as user fred
528 528 hgrc = """
529 529 [hooks]
530 530 pretxnchangegroup.acl = python:hgext.acl.hook
531 531 [acl]
532 532 sources = push
533 533 [acl.allow]
534 534 foo/** = fred
535 535 [acl.deny]
536 536 foo/bar/** = fred
537 537 foo/Bar/** = fred
538 538 """
539 539 pushing to ../b
540 540 query 1; heads
541 541 searching for changes
542 542 all remote heads known locally
543 543 3 changesets found
544 544 list of changesets:
545 545 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
546 546 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
547 547 911600dab2ae7a9baff75958b84fe606851ce955
548 548 adding changesets
549 549 bundling: 1/3 changesets (33.33%)
550 550 bundling: 2/3 changesets (66.67%)
551 551 bundling: 3/3 changesets (100.00%)
552 552 bundling: 1/3 manifests (33.33%)
553 553 bundling: 2/3 manifests (66.67%)
554 554 bundling: 3/3 manifests (100.00%)
555 555 bundling: foo/Bar/file.txt 1/3 files (33.33%)
556 556 bundling: foo/file.txt 2/3 files (66.67%)
557 557 bundling: quux/file.py 3/3 files (100.00%)
558 558 changesets: 1 chunks
559 559 add changeset ef1ea85a6374
560 560 changesets: 2 chunks
561 561 add changeset f9cafe1212c8
562 562 changesets: 3 chunks
563 563 add changeset 911600dab2ae
564 564 adding manifests
565 565 manifests: 1/3 chunks (33.33%)
566 566 manifests: 2/3 chunks (66.67%)
567 567 manifests: 3/3 chunks (100.00%)
568 568 adding file changes
569 569 adding foo/Bar/file.txt revisions
570 570 files: 1/3 chunks (33.33%)
571 571 adding foo/file.txt revisions
572 572 files: 2/3 chunks (66.67%)
573 573 adding quux/file.py revisions
574 574 files: 3/3 chunks (100.00%)
575 575 added 3 changesets with 3 changes to 3 files
576 576 calling hook pretxnchangegroup.acl: hgext.acl.hook
577 577 acl: checking access for user "fred"
578 578 acl: acl.allow.branches not enabled
579 579 acl: acl.deny.branches not enabled
580 580 acl: acl.allow enabled, 1 entries for user fred
581 581 acl: acl.deny enabled, 2 entries for user fred
582 582 acl: branch access granted: "ef1ea85a6374" on branch "default"
583 583 acl: path access granted: "ef1ea85a6374"
584 584 acl: branch access granted: "f9cafe1212c8" on branch "default"
585 585 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
586 586 transaction abort!
587 587 rollback completed
588 588 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
589 589 no rollback information available
590 590 0:6675d58eff77
591 591
592 592
593 593 $ echo 'barney is not mentioned => not allowed anywhere'
594 594 barney is not mentioned => not allowed anywhere
595 595 $ do_push barney
596 596 Pushing as user barney
597 597 hgrc = """
598 598 [hooks]
599 599 pretxnchangegroup.acl = python:hgext.acl.hook
600 600 [acl]
601 601 sources = push
602 602 [acl.allow]
603 603 foo/** = fred
604 604 [acl.deny]
605 605 foo/bar/** = fred
606 606 foo/Bar/** = fred
607 607 """
608 608 pushing to ../b
609 609 query 1; heads
610 610 searching for changes
611 611 all remote heads known locally
612 612 3 changesets found
613 613 list of changesets:
614 614 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
615 615 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
616 616 911600dab2ae7a9baff75958b84fe606851ce955
617 617 adding changesets
618 618 bundling: 1/3 changesets (33.33%)
619 619 bundling: 2/3 changesets (66.67%)
620 620 bundling: 3/3 changesets (100.00%)
621 621 bundling: 1/3 manifests (33.33%)
622 622 bundling: 2/3 manifests (66.67%)
623 623 bundling: 3/3 manifests (100.00%)
624 624 bundling: foo/Bar/file.txt 1/3 files (33.33%)
625 625 bundling: foo/file.txt 2/3 files (66.67%)
626 626 bundling: quux/file.py 3/3 files (100.00%)
627 627 changesets: 1 chunks
628 628 add changeset ef1ea85a6374
629 629 changesets: 2 chunks
630 630 add changeset f9cafe1212c8
631 631 changesets: 3 chunks
632 632 add changeset 911600dab2ae
633 633 adding manifests
634 634 manifests: 1/3 chunks (33.33%)
635 635 manifests: 2/3 chunks (66.67%)
636 636 manifests: 3/3 chunks (100.00%)
637 637 adding file changes
638 638 adding foo/Bar/file.txt revisions
639 639 files: 1/3 chunks (33.33%)
640 640 adding foo/file.txt revisions
641 641 files: 2/3 chunks (66.67%)
642 642 adding quux/file.py revisions
643 643 files: 3/3 chunks (100.00%)
644 644 added 3 changesets with 3 changes to 3 files
645 645 calling hook pretxnchangegroup.acl: hgext.acl.hook
646 646 acl: checking access for user "barney"
647 647 acl: acl.allow.branches not enabled
648 648 acl: acl.deny.branches not enabled
649 649 acl: acl.allow enabled, 0 entries for user barney
650 650 acl: acl.deny enabled, 0 entries for user barney
651 651 acl: branch access granted: "ef1ea85a6374" on branch "default"
652 652 error: pretxnchangegroup.acl hook failed: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
653 653 transaction abort!
654 654 rollback completed
655 655 abort: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
656 656 no rollback information available
657 657 0:6675d58eff77
658 658
659 659
660 660 barney is allowed everywhere
661 661
662 662 $ echo '[acl.allow]' >> $config
663 663 $ echo '** = barney' >> $config
664 664 $ do_push barney
665 665 Pushing as user barney
666 666 hgrc = """
667 667 [hooks]
668 668 pretxnchangegroup.acl = python:hgext.acl.hook
669 669 [acl]
670 670 sources = push
671 671 [acl.allow]
672 672 foo/** = fred
673 673 [acl.deny]
674 674 foo/bar/** = fred
675 675 foo/Bar/** = fred
676 676 [acl.allow]
677 677 ** = barney
678 678 """
679 679 pushing to ../b
680 680 query 1; heads
681 681 searching for changes
682 682 all remote heads known locally
683 683 3 changesets found
684 684 list of changesets:
685 685 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
686 686 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
687 687 911600dab2ae7a9baff75958b84fe606851ce955
688 688 adding changesets
689 689 bundling: 1/3 changesets (33.33%)
690 690 bundling: 2/3 changesets (66.67%)
691 691 bundling: 3/3 changesets (100.00%)
692 692 bundling: 1/3 manifests (33.33%)
693 693 bundling: 2/3 manifests (66.67%)
694 694 bundling: 3/3 manifests (100.00%)
695 695 bundling: foo/Bar/file.txt 1/3 files (33.33%)
696 696 bundling: foo/file.txt 2/3 files (66.67%)
697 697 bundling: quux/file.py 3/3 files (100.00%)
698 698 changesets: 1 chunks
699 699 add changeset ef1ea85a6374
700 700 changesets: 2 chunks
701 701 add changeset f9cafe1212c8
702 702 changesets: 3 chunks
703 703 add changeset 911600dab2ae
704 704 adding manifests
705 705 manifests: 1/3 chunks (33.33%)
706 706 manifests: 2/3 chunks (66.67%)
707 707 manifests: 3/3 chunks (100.00%)
708 708 adding file changes
709 709 adding foo/Bar/file.txt revisions
710 710 files: 1/3 chunks (33.33%)
711 711 adding foo/file.txt revisions
712 712 files: 2/3 chunks (66.67%)
713 713 adding quux/file.py revisions
714 714 files: 3/3 chunks (100.00%)
715 715 added 3 changesets with 3 changes to 3 files
716 716 calling hook pretxnchangegroup.acl: hgext.acl.hook
717 717 acl: checking access for user "barney"
718 718 acl: acl.allow.branches not enabled
719 719 acl: acl.deny.branches not enabled
720 720 acl: acl.allow enabled, 1 entries for user barney
721 721 acl: acl.deny enabled, 0 entries for user barney
722 722 acl: branch access granted: "ef1ea85a6374" on branch "default"
723 723 acl: path access granted: "ef1ea85a6374"
724 724 acl: branch access granted: "f9cafe1212c8" on branch "default"
725 725 acl: path access granted: "f9cafe1212c8"
726 726 acl: branch access granted: "911600dab2ae" on branch "default"
727 727 acl: path access granted: "911600dab2ae"
728 728 updating the branch cache
729 729 checking for updated bookmarks
730 730 repository tip rolled back to revision 0 (undo push)
731 731 0:6675d58eff77
732 732
733 733
734 734 wilma can change files with a .txt extension
735 735
736 736 $ echo '**/*.txt = wilma' >> $config
737 737 $ do_push wilma
738 738 Pushing as user wilma
739 739 hgrc = """
740 740 [hooks]
741 741 pretxnchangegroup.acl = python:hgext.acl.hook
742 742 [acl]
743 743 sources = push
744 744 [acl.allow]
745 745 foo/** = fred
746 746 [acl.deny]
747 747 foo/bar/** = fred
748 748 foo/Bar/** = fred
749 749 [acl.allow]
750 750 ** = barney
751 751 **/*.txt = wilma
752 752 """
753 753 pushing to ../b
754 754 query 1; heads
755 755 searching for changes
756 756 all remote heads known locally
757 757 invalidating branch cache (tip differs)
758 758 3 changesets found
759 759 list of changesets:
760 760 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
761 761 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
762 762 911600dab2ae7a9baff75958b84fe606851ce955
763 763 adding changesets
764 764 bundling: 1/3 changesets (33.33%)
765 765 bundling: 2/3 changesets (66.67%)
766 766 bundling: 3/3 changesets (100.00%)
767 767 bundling: 1/3 manifests (33.33%)
768 768 bundling: 2/3 manifests (66.67%)
769 769 bundling: 3/3 manifests (100.00%)
770 770 bundling: foo/Bar/file.txt 1/3 files (33.33%)
771 771 bundling: foo/file.txt 2/3 files (66.67%)
772 772 bundling: quux/file.py 3/3 files (100.00%)
773 773 changesets: 1 chunks
774 774 add changeset ef1ea85a6374
775 775 changesets: 2 chunks
776 776 add changeset f9cafe1212c8
777 777 changesets: 3 chunks
778 778 add changeset 911600dab2ae
779 779 adding manifests
780 780 manifests: 1/3 chunks (33.33%)
781 781 manifests: 2/3 chunks (66.67%)
782 782 manifests: 3/3 chunks (100.00%)
783 783 adding file changes
784 784 adding foo/Bar/file.txt revisions
785 785 files: 1/3 chunks (33.33%)
786 786 adding foo/file.txt revisions
787 787 files: 2/3 chunks (66.67%)
788 788 adding quux/file.py revisions
789 789 files: 3/3 chunks (100.00%)
790 790 added 3 changesets with 3 changes to 3 files
791 791 calling hook pretxnchangegroup.acl: hgext.acl.hook
792 792 acl: checking access for user "wilma"
793 793 acl: acl.allow.branches not enabled
794 794 acl: acl.deny.branches not enabled
795 795 acl: acl.allow enabled, 1 entries for user wilma
796 796 acl: acl.deny enabled, 0 entries for user wilma
797 797 acl: branch access granted: "ef1ea85a6374" on branch "default"
798 798 acl: path access granted: "ef1ea85a6374"
799 799 acl: branch access granted: "f9cafe1212c8" on branch "default"
800 800 acl: path access granted: "f9cafe1212c8"
801 801 acl: branch access granted: "911600dab2ae" on branch "default"
802 802 error: pretxnchangegroup.acl hook failed: acl: user "wilma" not allowed on "quux/file.py" (changeset "911600dab2ae")
803 803 transaction abort!
804 804 rollback completed
805 805 abort: acl: user "wilma" not allowed on "quux/file.py" (changeset "911600dab2ae")
806 806 no rollback information available
807 807 0:6675d58eff77
808 808
809 809
810 810 file specified by acl.config does not exist
811 811
812 812 $ echo '[acl]' >> $config
813 813 $ echo 'config = ../acl.config' >> $config
814 814 $ do_push barney
815 815 Pushing as user barney
816 816 hgrc = """
817 817 [hooks]
818 818 pretxnchangegroup.acl = python:hgext.acl.hook
819 819 [acl]
820 820 sources = push
821 821 [acl.allow]
822 822 foo/** = fred
823 823 [acl.deny]
824 824 foo/bar/** = fred
825 825 foo/Bar/** = fred
826 826 [acl.allow]
827 827 ** = barney
828 828 **/*.txt = wilma
829 829 [acl]
830 830 config = ../acl.config
831 831 """
832 832 pushing to ../b
833 833 query 1; heads
834 834 searching for changes
835 835 all remote heads known locally
836 836 3 changesets found
837 837 list of changesets:
838 838 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
839 839 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
840 840 911600dab2ae7a9baff75958b84fe606851ce955
841 841 adding changesets
842 842 bundling: 1/3 changesets (33.33%)
843 843 bundling: 2/3 changesets (66.67%)
844 844 bundling: 3/3 changesets (100.00%)
845 845 bundling: 1/3 manifests (33.33%)
846 846 bundling: 2/3 manifests (66.67%)
847 847 bundling: 3/3 manifests (100.00%)
848 848 bundling: foo/Bar/file.txt 1/3 files (33.33%)
849 849 bundling: foo/file.txt 2/3 files (66.67%)
850 850 bundling: quux/file.py 3/3 files (100.00%)
851 851 changesets: 1 chunks
852 852 add changeset ef1ea85a6374
853 853 changesets: 2 chunks
854 854 add changeset f9cafe1212c8
855 855 changesets: 3 chunks
856 856 add changeset 911600dab2ae
857 857 adding manifests
858 858 manifests: 1/3 chunks (33.33%)
859 859 manifests: 2/3 chunks (66.67%)
860 860 manifests: 3/3 chunks (100.00%)
861 861 adding file changes
862 862 adding foo/Bar/file.txt revisions
863 863 files: 1/3 chunks (33.33%)
864 864 adding foo/file.txt revisions
865 865 files: 2/3 chunks (66.67%)
866 866 adding quux/file.py revisions
867 867 files: 3/3 chunks (100.00%)
868 868 added 3 changesets with 3 changes to 3 files
869 869 calling hook pretxnchangegroup.acl: hgext.acl.hook
870 870 acl: checking access for user "barney"
871 871 error: pretxnchangegroup.acl hook raised an exception: [Errno 2] *: '../acl.config' (glob)
872 872 transaction abort!
873 873 rollback completed
874 874 abort: *: ../acl.config (glob)
875 875 no rollback information available
876 876 0:6675d58eff77
877 877
878 878
879 879 betty is allowed inside foo/ by a acl.config file
880 880
881 881 $ echo '[acl.allow]' >> acl.config
882 882 $ echo 'foo/** = betty' >> acl.config
883 883 $ do_push betty
884 884 Pushing as user betty
885 885 hgrc = """
886 886 [hooks]
887 887 pretxnchangegroup.acl = python:hgext.acl.hook
888 888 [acl]
889 889 sources = push
890 890 [acl.allow]
891 891 foo/** = fred
892 892 [acl.deny]
893 893 foo/bar/** = fred
894 894 foo/Bar/** = fred
895 895 [acl.allow]
896 896 ** = barney
897 897 **/*.txt = wilma
898 898 [acl]
899 899 config = ../acl.config
900 900 """
901 901 acl.config = """
902 902 [acl.allow]
903 903 foo/** = betty
904 904 """
905 905 pushing to ../b
906 906 query 1; heads
907 907 searching for changes
908 908 all remote heads known locally
909 909 3 changesets found
910 910 list of changesets:
911 911 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
912 912 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
913 913 911600dab2ae7a9baff75958b84fe606851ce955
914 914 adding changesets
915 915 bundling: 1/3 changesets (33.33%)
916 916 bundling: 2/3 changesets (66.67%)
917 917 bundling: 3/3 changesets (100.00%)
918 918 bundling: 1/3 manifests (33.33%)
919 919 bundling: 2/3 manifests (66.67%)
920 920 bundling: 3/3 manifests (100.00%)
921 921 bundling: foo/Bar/file.txt 1/3 files (33.33%)
922 922 bundling: foo/file.txt 2/3 files (66.67%)
923 923 bundling: quux/file.py 3/3 files (100.00%)
924 924 changesets: 1 chunks
925 925 add changeset ef1ea85a6374
926 926 changesets: 2 chunks
927 927 add changeset f9cafe1212c8
928 928 changesets: 3 chunks
929 929 add changeset 911600dab2ae
930 930 adding manifests
931 931 manifests: 1/3 chunks (33.33%)
932 932 manifests: 2/3 chunks (66.67%)
933 933 manifests: 3/3 chunks (100.00%)
934 934 adding file changes
935 935 adding foo/Bar/file.txt revisions
936 936 files: 1/3 chunks (33.33%)
937 937 adding foo/file.txt revisions
938 938 files: 2/3 chunks (66.67%)
939 939 adding quux/file.py revisions
940 940 files: 3/3 chunks (100.00%)
941 941 added 3 changesets with 3 changes to 3 files
942 942 calling hook pretxnchangegroup.acl: hgext.acl.hook
943 943 acl: checking access for user "betty"
944 944 acl: acl.allow.branches not enabled
945 945 acl: acl.deny.branches not enabled
946 946 acl: acl.allow enabled, 1 entries for user betty
947 947 acl: acl.deny enabled, 0 entries for user betty
948 948 acl: branch access granted: "ef1ea85a6374" on branch "default"
949 949 acl: path access granted: "ef1ea85a6374"
950 950 acl: branch access granted: "f9cafe1212c8" on branch "default"
951 951 acl: path access granted: "f9cafe1212c8"
952 952 acl: branch access granted: "911600dab2ae" on branch "default"
953 953 error: pretxnchangegroup.acl hook failed: acl: user "betty" not allowed on "quux/file.py" (changeset "911600dab2ae")
954 954 transaction abort!
955 955 rollback completed
956 956 abort: acl: user "betty" not allowed on "quux/file.py" (changeset "911600dab2ae")
957 957 no rollback information available
958 958 0:6675d58eff77
959 959
960 960
961 961 acl.config can set only [acl.allow]/[acl.deny]
962 962
963 963 $ echo '[hooks]' >> acl.config
964 964 $ echo 'changegroup.acl = false' >> acl.config
965 965 $ do_push barney
966 966 Pushing as user barney
967 967 hgrc = """
968 968 [hooks]
969 969 pretxnchangegroup.acl = python:hgext.acl.hook
970 970 [acl]
971 971 sources = push
972 972 [acl.allow]
973 973 foo/** = fred
974 974 [acl.deny]
975 975 foo/bar/** = fred
976 976 foo/Bar/** = fred
977 977 [acl.allow]
978 978 ** = barney
979 979 **/*.txt = wilma
980 980 [acl]
981 981 config = ../acl.config
982 982 """
983 983 acl.config = """
984 984 [acl.allow]
985 985 foo/** = betty
986 986 [hooks]
987 987 changegroup.acl = false
988 988 """
989 989 pushing to ../b
990 990 query 1; heads
991 991 searching for changes
992 992 all remote heads known locally
993 993 3 changesets found
994 994 list of changesets:
995 995 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
996 996 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
997 997 911600dab2ae7a9baff75958b84fe606851ce955
998 998 adding changesets
999 999 bundling: 1/3 changesets (33.33%)
1000 1000 bundling: 2/3 changesets (66.67%)
1001 1001 bundling: 3/3 changesets (100.00%)
1002 1002 bundling: 1/3 manifests (33.33%)
1003 1003 bundling: 2/3 manifests (66.67%)
1004 1004 bundling: 3/3 manifests (100.00%)
1005 1005 bundling: foo/Bar/file.txt 1/3 files (33.33%)
1006 1006 bundling: foo/file.txt 2/3 files (66.67%)
1007 1007 bundling: quux/file.py 3/3 files (100.00%)
1008 1008 changesets: 1 chunks
1009 1009 add changeset ef1ea85a6374
1010 1010 changesets: 2 chunks
1011 1011 add changeset f9cafe1212c8
1012 1012 changesets: 3 chunks
1013 1013 add changeset 911600dab2ae
1014 1014 adding manifests
1015 1015 manifests: 1/3 chunks (33.33%)
1016 1016 manifests: 2/3 chunks (66.67%)
1017 1017 manifests: 3/3 chunks (100.00%)
1018 1018 adding file changes
1019 1019 adding foo/Bar/file.txt revisions
1020 1020 files: 1/3 chunks (33.33%)
1021 1021 adding foo/file.txt revisions
1022 1022 files: 2/3 chunks (66.67%)
1023 1023 adding quux/file.py revisions
1024 1024 files: 3/3 chunks (100.00%)
1025 1025 added 3 changesets with 3 changes to 3 files
1026 1026 calling hook pretxnchangegroup.acl: hgext.acl.hook
1027 1027 acl: checking access for user "barney"
1028 1028 acl: acl.allow.branches not enabled
1029 1029 acl: acl.deny.branches not enabled
1030 1030 acl: acl.allow enabled, 1 entries for user barney
1031 1031 acl: acl.deny enabled, 0 entries for user barney
1032 1032 acl: branch access granted: "ef1ea85a6374" on branch "default"
1033 1033 acl: path access granted: "ef1ea85a6374"
1034 1034 acl: branch access granted: "f9cafe1212c8" on branch "default"
1035 1035 acl: path access granted: "f9cafe1212c8"
1036 1036 acl: branch access granted: "911600dab2ae" on branch "default"
1037 1037 acl: path access granted: "911600dab2ae"
1038 1038 updating the branch cache
1039 1039 checking for updated bookmarks
1040 1040 repository tip rolled back to revision 0 (undo push)
1041 1041 0:6675d58eff77
1042 1042
1043 1043
1044 1044 asterisk
1045 1045
1046 1046 $ init_config
1047 1047
1048 1048 asterisk test
1049 1049
1050 1050 $ echo '[acl.allow]' >> $config
1051 1051 $ echo "** = fred" >> $config
1052 1052
1053 1053 fred is always allowed
1054 1054
1055 1055 $ do_push fred
1056 1056 Pushing as user fred
1057 1057 hgrc = """
1058 1058 [acl]
1059 1059 sources = push
1060 1060 [extensions]
1061 1061 [acl.allow]
1062 1062 ** = fred
1063 1063 """
1064 1064 pushing to ../b
1065 1065 query 1; heads
1066 1066 searching for changes
1067 1067 all remote heads known locally
1068 1068 invalidating branch cache (tip differs)
1069 1069 3 changesets found
1070 1070 list of changesets:
1071 1071 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1072 1072 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1073 1073 911600dab2ae7a9baff75958b84fe606851ce955
1074 1074 adding changesets
1075 1075 bundling: 1/3 changesets (33.33%)
1076 1076 bundling: 2/3 changesets (66.67%)
1077 1077 bundling: 3/3 changesets (100.00%)
1078 1078 bundling: 1/3 manifests (33.33%)
1079 1079 bundling: 2/3 manifests (66.67%)
1080 1080 bundling: 3/3 manifests (100.00%)
1081 1081 bundling: foo/Bar/file.txt 1/3 files (33.33%)
1082 1082 bundling: foo/file.txt 2/3 files (66.67%)
1083 1083 bundling: quux/file.py 3/3 files (100.00%)
1084 1084 changesets: 1 chunks
1085 1085 add changeset ef1ea85a6374
1086 1086 changesets: 2 chunks
1087 1087 add changeset f9cafe1212c8
1088 1088 changesets: 3 chunks
1089 1089 add changeset 911600dab2ae
1090 1090 adding manifests
1091 1091 manifests: 1/3 chunks (33.33%)
1092 1092 manifests: 2/3 chunks (66.67%)
1093 1093 manifests: 3/3 chunks (100.00%)
1094 1094 adding file changes
1095 1095 adding foo/Bar/file.txt revisions
1096 1096 files: 1/3 chunks (33.33%)
1097 1097 adding foo/file.txt revisions
1098 1098 files: 2/3 chunks (66.67%)
1099 1099 adding quux/file.py revisions
1100 1100 files: 3/3 chunks (100.00%)
1101 1101 added 3 changesets with 3 changes to 3 files
1102 1102 calling hook pretxnchangegroup.acl: hgext.acl.hook
1103 1103 acl: checking access for user "fred"
1104 1104 acl: acl.allow.branches not enabled
1105 1105 acl: acl.deny.branches not enabled
1106 1106 acl: acl.allow enabled, 1 entries for user fred
1107 1107 acl: acl.deny not enabled
1108 1108 acl: branch access granted: "ef1ea85a6374" on branch "default"
1109 1109 acl: path access granted: "ef1ea85a6374"
1110 1110 acl: branch access granted: "f9cafe1212c8" on branch "default"
1111 1111 acl: path access granted: "f9cafe1212c8"
1112 1112 acl: branch access granted: "911600dab2ae" on branch "default"
1113 1113 acl: path access granted: "911600dab2ae"
1114 1114 updating the branch cache
1115 1115 checking for updated bookmarks
1116 1116 repository tip rolled back to revision 0 (undo push)
1117 1117 0:6675d58eff77
1118 1118
1119 1119
1120 1120 $ echo '[acl.deny]' >> $config
1121 1121 $ echo "foo/Bar/** = *" >> $config
1122 1122
1123 1123 no one is allowed inside foo/Bar/
1124 1124
1125 1125 $ do_push fred
1126 1126 Pushing as user fred
1127 1127 hgrc = """
1128 1128 [acl]
1129 1129 sources = push
1130 1130 [extensions]
1131 1131 [acl.allow]
1132 1132 ** = fred
1133 1133 [acl.deny]
1134 1134 foo/Bar/** = *
1135 1135 """
1136 1136 pushing to ../b
1137 1137 query 1; heads
1138 1138 searching for changes
1139 1139 all remote heads known locally
1140 1140 invalidating branch cache (tip differs)
1141 1141 3 changesets found
1142 1142 list of changesets:
1143 1143 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1144 1144 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1145 1145 911600dab2ae7a9baff75958b84fe606851ce955
1146 1146 adding changesets
1147 1147 bundling: 1/3 changesets (33.33%)
1148 1148 bundling: 2/3 changesets (66.67%)
1149 1149 bundling: 3/3 changesets (100.00%)
1150 1150 bundling: 1/3 manifests (33.33%)
1151 1151 bundling: 2/3 manifests (66.67%)
1152 1152 bundling: 3/3 manifests (100.00%)
1153 1153 bundling: foo/Bar/file.txt 1/3 files (33.33%)
1154 1154 bundling: foo/file.txt 2/3 files (66.67%)
1155 1155 bundling: quux/file.py 3/3 files (100.00%)
1156 1156 changesets: 1 chunks
1157 1157 add changeset ef1ea85a6374
1158 1158 changesets: 2 chunks
1159 1159 add changeset f9cafe1212c8
1160 1160 changesets: 3 chunks
1161 1161 add changeset 911600dab2ae
1162 1162 adding manifests
1163 1163 manifests: 1/3 chunks (33.33%)
1164 1164 manifests: 2/3 chunks (66.67%)
1165 1165 manifests: 3/3 chunks (100.00%)
1166 1166 adding file changes
1167 1167 adding foo/Bar/file.txt revisions
1168 1168 files: 1/3 chunks (33.33%)
1169 1169 adding foo/file.txt revisions
1170 1170 files: 2/3 chunks (66.67%)
1171 1171 adding quux/file.py revisions
1172 1172 files: 3/3 chunks (100.00%)
1173 1173 added 3 changesets with 3 changes to 3 files
1174 1174 calling hook pretxnchangegroup.acl: hgext.acl.hook
1175 1175 acl: checking access for user "fred"
1176 1176 acl: acl.allow.branches not enabled
1177 1177 acl: acl.deny.branches not enabled
1178 1178 acl: acl.allow enabled, 1 entries for user fred
1179 1179 acl: acl.deny enabled, 1 entries for user fred
1180 1180 acl: branch access granted: "ef1ea85a6374" on branch "default"
1181 1181 acl: path access granted: "ef1ea85a6374"
1182 1182 acl: branch access granted: "f9cafe1212c8" on branch "default"
1183 1183 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1184 1184 transaction abort!
1185 1185 rollback completed
1186 1186 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1187 1187 no rollback information available
1188 1188 0:6675d58eff77
1189 1189
1190 1190
1191 1191 Groups
1192 1192
1193 1193 $ init_config
1194 1194
1195 1195 OS-level groups
1196 1196
1197 1197 $ echo '[acl.allow]' >> $config
1198 1198 $ echo "** = @group1" >> $config
1199 1199
1200 1200 @group1 is always allowed
1201 1201
1202 1202 $ do_push fred
1203 1203 Pushing as user fred
1204 1204 hgrc = """
1205 1205 [acl]
1206 1206 sources = push
1207 1207 [extensions]
1208 1208 [acl.allow]
1209 1209 ** = @group1
1210 1210 """
1211 1211 pushing to ../b
1212 1212 query 1; heads
1213 1213 searching for changes
1214 1214 all remote heads known locally
1215 1215 3 changesets found
1216 1216 list of changesets:
1217 1217 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1218 1218 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1219 1219 911600dab2ae7a9baff75958b84fe606851ce955
1220 1220 adding changesets
1221 1221 bundling: 1/3 changesets (33.33%)
1222 1222 bundling: 2/3 changesets (66.67%)
1223 1223 bundling: 3/3 changesets (100.00%)
1224 1224 bundling: 1/3 manifests (33.33%)
1225 1225 bundling: 2/3 manifests (66.67%)
1226 1226 bundling: 3/3 manifests (100.00%)
1227 1227 bundling: foo/Bar/file.txt 1/3 files (33.33%)
1228 1228 bundling: foo/file.txt 2/3 files (66.67%)
1229 1229 bundling: quux/file.py 3/3 files (100.00%)
1230 1230 changesets: 1 chunks
1231 1231 add changeset ef1ea85a6374
1232 1232 changesets: 2 chunks
1233 1233 add changeset f9cafe1212c8
1234 1234 changesets: 3 chunks
1235 1235 add changeset 911600dab2ae
1236 1236 adding manifests
1237 1237 manifests: 1/3 chunks (33.33%)
1238 1238 manifests: 2/3 chunks (66.67%)
1239 1239 manifests: 3/3 chunks (100.00%)
1240 1240 adding file changes
1241 1241 adding foo/Bar/file.txt revisions
1242 1242 files: 1/3 chunks (33.33%)
1243 1243 adding foo/file.txt revisions
1244 1244 files: 2/3 chunks (66.67%)
1245 1245 adding quux/file.py revisions
1246 1246 files: 3/3 chunks (100.00%)
1247 1247 added 3 changesets with 3 changes to 3 files
1248 1248 calling hook pretxnchangegroup.acl: hgext.acl.hook
1249 1249 acl: checking access for user "fred"
1250 1250 acl: acl.allow.branches not enabled
1251 1251 acl: acl.deny.branches not enabled
1252 1252 acl: "group1" not defined in [acl.groups]
1253 1253 acl: acl.allow enabled, 1 entries for user fred
1254 1254 acl: acl.deny not enabled
1255 1255 acl: branch access granted: "ef1ea85a6374" on branch "default"
1256 1256 acl: path access granted: "ef1ea85a6374"
1257 1257 acl: branch access granted: "f9cafe1212c8" on branch "default"
1258 1258 acl: path access granted: "f9cafe1212c8"
1259 1259 acl: branch access granted: "911600dab2ae" on branch "default"
1260 1260 acl: path access granted: "911600dab2ae"
1261 1261 updating the branch cache
1262 1262 checking for updated bookmarks
1263 1263 repository tip rolled back to revision 0 (undo push)
1264 1264 0:6675d58eff77
1265 1265
1266 1266
1267 1267 $ echo '[acl.deny]' >> $config
1268 1268 $ echo "foo/Bar/** = @group1" >> $config
1269 1269
1270 1270 @group is allowed inside anything but foo/Bar/
1271 1271
1272 1272 $ do_push fred
1273 1273 Pushing as user fred
1274 1274 hgrc = """
1275 1275 [acl]
1276 1276 sources = push
1277 1277 [extensions]
1278 1278 [acl.allow]
1279 1279 ** = @group1
1280 1280 [acl.deny]
1281 1281 foo/Bar/** = @group1
1282 1282 """
1283 1283 pushing to ../b
1284 1284 query 1; heads
1285 1285 searching for changes
1286 1286 all remote heads known locally
1287 1287 invalidating branch cache (tip differs)
1288 1288 3 changesets found
1289 1289 list of changesets:
1290 1290 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1291 1291 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1292 1292 911600dab2ae7a9baff75958b84fe606851ce955
1293 1293 adding changesets
1294 1294 bundling: 1/3 changesets (33.33%)
1295 1295 bundling: 2/3 changesets (66.67%)
1296 1296 bundling: 3/3 changesets (100.00%)
1297 1297 bundling: 1/3 manifests (33.33%)
1298 1298 bundling: 2/3 manifests (66.67%)
1299 1299 bundling: 3/3 manifests (100.00%)
1300 1300 bundling: foo/Bar/file.txt 1/3 files (33.33%)
1301 1301 bundling: foo/file.txt 2/3 files (66.67%)
1302 1302 bundling: quux/file.py 3/3 files (100.00%)
1303 1303 changesets: 1 chunks
1304 1304 add changeset ef1ea85a6374
1305 1305 changesets: 2 chunks
1306 1306 add changeset f9cafe1212c8
1307 1307 changesets: 3 chunks
1308 1308 add changeset 911600dab2ae
1309 1309 adding manifests
1310 1310 manifests: 1/3 chunks (33.33%)
1311 1311 manifests: 2/3 chunks (66.67%)
1312 1312 manifests: 3/3 chunks (100.00%)
1313 1313 adding file changes
1314 1314 adding foo/Bar/file.txt revisions
1315 1315 files: 1/3 chunks (33.33%)
1316 1316 adding foo/file.txt revisions
1317 1317 files: 2/3 chunks (66.67%)
1318 1318 adding quux/file.py revisions
1319 1319 files: 3/3 chunks (100.00%)
1320 1320 added 3 changesets with 3 changes to 3 files
1321 1321 calling hook pretxnchangegroup.acl: hgext.acl.hook
1322 1322 acl: checking access for user "fred"
1323 1323 acl: acl.allow.branches not enabled
1324 1324 acl: acl.deny.branches not enabled
1325 1325 acl: "group1" not defined in [acl.groups]
1326 1326 acl: acl.allow enabled, 1 entries for user fred
1327 1327 acl: "group1" not defined in [acl.groups]
1328 1328 acl: acl.deny enabled, 1 entries for user fred
1329 1329 acl: branch access granted: "ef1ea85a6374" on branch "default"
1330 1330 acl: path access granted: "ef1ea85a6374"
1331 1331 acl: branch access granted: "f9cafe1212c8" on branch "default"
1332 1332 error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1333 1333 transaction abort!
1334 1334 rollback completed
1335 1335 abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
1336 1336 no rollback information available
1337 1337 0:6675d58eff77
1338 1338
1339 1339
1340 1340 Invalid group
1341 1341
1342 1342 Disable the fakegroups trick to get real failures
1343 1343
1344 1344 $ grep -v fakegroups $config > config.tmp
1345 1345 $ mv config.tmp $config
1346 1346 $ echo '[acl.allow]' >> $config
1347 1347 $ echo "** = @unlikelytoexist" >> $config
1348 1348 $ do_push fred 2>&1 | grep unlikelytoexist
1349 1349 ** = @unlikelytoexist
1350 1350 acl: "unlikelytoexist" not defined in [acl.groups]
1351 1351 error: pretxnchangegroup.acl hook failed: group 'unlikelytoexist' is undefined
1352 1352 abort: group 'unlikelytoexist' is undefined
1353 1353
1354 1354
1355 1355 Branch acl tests setup
1356 1356
1357 1357 $ init_config
1358 1358 $ cd b
1359 1359 $ hg up
1360 1360 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1361 1361 $ hg branch foobar
1362 1362 marked working directory as branch foobar
1363 (branches are permanent and global, did you want a bookmark?)
1363 1364 $ hg commit -m 'create foobar'
1364 1365 $ echo 'foo contents' > abc.txt
1365 1366 $ hg add abc.txt
1366 1367 $ hg commit -m 'foobar contents'
1367 1368 $ cd ..
1368 1369 $ hg --cwd a pull ../b
1369 1370 pulling from ../b
1370 1371 searching for changes
1371 1372 adding changesets
1372 1373 adding manifests
1373 1374 adding file changes
1374 1375 added 2 changesets with 1 changes to 1 files (+1 heads)
1375 1376 (run 'hg heads' to see heads)
1376 1377
1377 1378 Create additional changeset on foobar branch
1378 1379
1379 1380 $ cd a
1380 1381 $ hg up -C foobar
1381 1382 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1382 1383 $ echo 'foo contents2' > abc.txt
1383 1384 $ hg commit -m 'foobar contents2'
1384 1385 $ cd ..
1385 1386
1386 1387
1387 1388 No branch acls specified
1388 1389
1389 1390 $ do_push astro
1390 1391 Pushing as user astro
1391 1392 hgrc = """
1392 1393 [acl]
1393 1394 sources = push
1394 1395 [extensions]
1395 1396 """
1396 1397 pushing to ../b
1397 1398 query 1; heads
1398 1399 searching for changes
1399 1400 all remote heads known locally
1400 1401 4 changesets found
1401 1402 list of changesets:
1402 1403 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1403 1404 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1404 1405 911600dab2ae7a9baff75958b84fe606851ce955
1405 1406 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1406 1407 adding changesets
1407 1408 bundling: 1/4 changesets (25.00%)
1408 1409 bundling: 2/4 changesets (50.00%)
1409 1410 bundling: 3/4 changesets (75.00%)
1410 1411 bundling: 4/4 changesets (100.00%)
1411 1412 bundling: 1/4 manifests (25.00%)
1412 1413 bundling: 2/4 manifests (50.00%)
1413 1414 bundling: 3/4 manifests (75.00%)
1414 1415 bundling: 4/4 manifests (100.00%)
1415 1416 bundling: abc.txt 1/4 files (25.00%)
1416 1417 bundling: foo/Bar/file.txt 2/4 files (50.00%)
1417 1418 bundling: foo/file.txt 3/4 files (75.00%)
1418 1419 bundling: quux/file.py 4/4 files (100.00%)
1419 1420 changesets: 1 chunks
1420 1421 add changeset ef1ea85a6374
1421 1422 changesets: 2 chunks
1422 1423 add changeset f9cafe1212c8
1423 1424 changesets: 3 chunks
1424 1425 add changeset 911600dab2ae
1425 1426 changesets: 4 chunks
1426 1427 add changeset e8fc755d4d82
1427 1428 adding manifests
1428 1429 manifests: 1/4 chunks (25.00%)
1429 1430 manifests: 2/4 chunks (50.00%)
1430 1431 manifests: 3/4 chunks (75.00%)
1431 1432 manifests: 4/4 chunks (100.00%)
1432 1433 adding file changes
1433 1434 adding abc.txt revisions
1434 1435 files: 1/4 chunks (25.00%)
1435 1436 adding foo/Bar/file.txt revisions
1436 1437 files: 2/4 chunks (50.00%)
1437 1438 adding foo/file.txt revisions
1438 1439 files: 3/4 chunks (75.00%)
1439 1440 adding quux/file.py revisions
1440 1441 files: 4/4 chunks (100.00%)
1441 1442 added 4 changesets with 4 changes to 4 files (+1 heads)
1442 1443 calling hook pretxnchangegroup.acl: hgext.acl.hook
1443 1444 acl: checking access for user "astro"
1444 1445 acl: acl.allow.branches not enabled
1445 1446 acl: acl.deny.branches not enabled
1446 1447 acl: acl.allow not enabled
1447 1448 acl: acl.deny not enabled
1448 1449 acl: branch access granted: "ef1ea85a6374" on branch "default"
1449 1450 acl: path access granted: "ef1ea85a6374"
1450 1451 acl: branch access granted: "f9cafe1212c8" on branch "default"
1451 1452 acl: path access granted: "f9cafe1212c8"
1452 1453 acl: branch access granted: "911600dab2ae" on branch "default"
1453 1454 acl: path access granted: "911600dab2ae"
1454 1455 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1455 1456 acl: path access granted: "e8fc755d4d82"
1456 1457 updating the branch cache
1457 1458 checking for updated bookmarks
1458 1459 repository tip rolled back to revision 2 (undo push)
1459 1460 2:fb35475503ef
1460 1461
1461 1462
1462 1463 Branch acl deny test
1463 1464
1464 1465 $ echo "[acl.deny.branches]" >> $config
1465 1466 $ echo "foobar = *" >> $config
1466 1467 $ do_push astro
1467 1468 Pushing as user astro
1468 1469 hgrc = """
1469 1470 [acl]
1470 1471 sources = push
1471 1472 [extensions]
1472 1473 [acl.deny.branches]
1473 1474 foobar = *
1474 1475 """
1475 1476 pushing to ../b
1476 1477 query 1; heads
1477 1478 searching for changes
1478 1479 all remote heads known locally
1479 1480 invalidating branch cache (tip differs)
1480 1481 4 changesets found
1481 1482 list of changesets:
1482 1483 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1483 1484 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1484 1485 911600dab2ae7a9baff75958b84fe606851ce955
1485 1486 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1486 1487 adding changesets
1487 1488 bundling: 1/4 changesets (25.00%)
1488 1489 bundling: 2/4 changesets (50.00%)
1489 1490 bundling: 3/4 changesets (75.00%)
1490 1491 bundling: 4/4 changesets (100.00%)
1491 1492 bundling: 1/4 manifests (25.00%)
1492 1493 bundling: 2/4 manifests (50.00%)
1493 1494 bundling: 3/4 manifests (75.00%)
1494 1495 bundling: 4/4 manifests (100.00%)
1495 1496 bundling: abc.txt 1/4 files (25.00%)
1496 1497 bundling: foo/Bar/file.txt 2/4 files (50.00%)
1497 1498 bundling: foo/file.txt 3/4 files (75.00%)
1498 1499 bundling: quux/file.py 4/4 files (100.00%)
1499 1500 changesets: 1 chunks
1500 1501 add changeset ef1ea85a6374
1501 1502 changesets: 2 chunks
1502 1503 add changeset f9cafe1212c8
1503 1504 changesets: 3 chunks
1504 1505 add changeset 911600dab2ae
1505 1506 changesets: 4 chunks
1506 1507 add changeset e8fc755d4d82
1507 1508 adding manifests
1508 1509 manifests: 1/4 chunks (25.00%)
1509 1510 manifests: 2/4 chunks (50.00%)
1510 1511 manifests: 3/4 chunks (75.00%)
1511 1512 manifests: 4/4 chunks (100.00%)
1512 1513 adding file changes
1513 1514 adding abc.txt revisions
1514 1515 files: 1/4 chunks (25.00%)
1515 1516 adding foo/Bar/file.txt revisions
1516 1517 files: 2/4 chunks (50.00%)
1517 1518 adding foo/file.txt revisions
1518 1519 files: 3/4 chunks (75.00%)
1519 1520 adding quux/file.py revisions
1520 1521 files: 4/4 chunks (100.00%)
1521 1522 added 4 changesets with 4 changes to 4 files (+1 heads)
1522 1523 calling hook pretxnchangegroup.acl: hgext.acl.hook
1523 1524 acl: checking access for user "astro"
1524 1525 acl: acl.allow.branches not enabled
1525 1526 acl: acl.deny.branches enabled, 1 entries for user astro
1526 1527 acl: acl.allow not enabled
1527 1528 acl: acl.deny not enabled
1528 1529 acl: branch access granted: "ef1ea85a6374" on branch "default"
1529 1530 acl: path access granted: "ef1ea85a6374"
1530 1531 acl: branch access granted: "f9cafe1212c8" on branch "default"
1531 1532 acl: path access granted: "f9cafe1212c8"
1532 1533 acl: branch access granted: "911600dab2ae" on branch "default"
1533 1534 acl: path access granted: "911600dab2ae"
1534 1535 error: pretxnchangegroup.acl hook failed: acl: user "astro" denied on branch "foobar" (changeset "e8fc755d4d82")
1535 1536 transaction abort!
1536 1537 rollback completed
1537 1538 abort: acl: user "astro" denied on branch "foobar" (changeset "e8fc755d4d82")
1538 1539 no rollback information available
1539 1540 2:fb35475503ef
1540 1541
1541 1542
1542 1543 Branch acl empty allow test
1543 1544
1544 1545 $ init_config
1545 1546 $ echo "[acl.allow.branches]" >> $config
1546 1547 $ do_push astro
1547 1548 Pushing as user astro
1548 1549 hgrc = """
1549 1550 [acl]
1550 1551 sources = push
1551 1552 [extensions]
1552 1553 [acl.allow.branches]
1553 1554 """
1554 1555 pushing to ../b
1555 1556 query 1; heads
1556 1557 searching for changes
1557 1558 all remote heads known locally
1558 1559 4 changesets found
1559 1560 list of changesets:
1560 1561 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1561 1562 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1562 1563 911600dab2ae7a9baff75958b84fe606851ce955
1563 1564 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1564 1565 adding changesets
1565 1566 bundling: 1/4 changesets (25.00%)
1566 1567 bundling: 2/4 changesets (50.00%)
1567 1568 bundling: 3/4 changesets (75.00%)
1568 1569 bundling: 4/4 changesets (100.00%)
1569 1570 bundling: 1/4 manifests (25.00%)
1570 1571 bundling: 2/4 manifests (50.00%)
1571 1572 bundling: 3/4 manifests (75.00%)
1572 1573 bundling: 4/4 manifests (100.00%)
1573 1574 bundling: abc.txt 1/4 files (25.00%)
1574 1575 bundling: foo/Bar/file.txt 2/4 files (50.00%)
1575 1576 bundling: foo/file.txt 3/4 files (75.00%)
1576 1577 bundling: quux/file.py 4/4 files (100.00%)
1577 1578 changesets: 1 chunks
1578 1579 add changeset ef1ea85a6374
1579 1580 changesets: 2 chunks
1580 1581 add changeset f9cafe1212c8
1581 1582 changesets: 3 chunks
1582 1583 add changeset 911600dab2ae
1583 1584 changesets: 4 chunks
1584 1585 add changeset e8fc755d4d82
1585 1586 adding manifests
1586 1587 manifests: 1/4 chunks (25.00%)
1587 1588 manifests: 2/4 chunks (50.00%)
1588 1589 manifests: 3/4 chunks (75.00%)
1589 1590 manifests: 4/4 chunks (100.00%)
1590 1591 adding file changes
1591 1592 adding abc.txt revisions
1592 1593 files: 1/4 chunks (25.00%)
1593 1594 adding foo/Bar/file.txt revisions
1594 1595 files: 2/4 chunks (50.00%)
1595 1596 adding foo/file.txt revisions
1596 1597 files: 3/4 chunks (75.00%)
1597 1598 adding quux/file.py revisions
1598 1599 files: 4/4 chunks (100.00%)
1599 1600 added 4 changesets with 4 changes to 4 files (+1 heads)
1600 1601 calling hook pretxnchangegroup.acl: hgext.acl.hook
1601 1602 acl: checking access for user "astro"
1602 1603 acl: acl.allow.branches enabled, 0 entries for user astro
1603 1604 acl: acl.deny.branches not enabled
1604 1605 acl: acl.allow not enabled
1605 1606 acl: acl.deny not enabled
1606 1607 error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1607 1608 transaction abort!
1608 1609 rollback completed
1609 1610 abort: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1610 1611 no rollback information available
1611 1612 2:fb35475503ef
1612 1613
1613 1614
1614 1615 Branch acl allow other
1615 1616
1616 1617 $ init_config
1617 1618 $ echo "[acl.allow.branches]" >> $config
1618 1619 $ echo "* = george" >> $config
1619 1620 $ do_push astro
1620 1621 Pushing as user astro
1621 1622 hgrc = """
1622 1623 [acl]
1623 1624 sources = push
1624 1625 [extensions]
1625 1626 [acl.allow.branches]
1626 1627 * = george
1627 1628 """
1628 1629 pushing to ../b
1629 1630 query 1; heads
1630 1631 searching for changes
1631 1632 all remote heads known locally
1632 1633 4 changesets found
1633 1634 list of changesets:
1634 1635 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1635 1636 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1636 1637 911600dab2ae7a9baff75958b84fe606851ce955
1637 1638 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1638 1639 adding changesets
1639 1640 bundling: 1/4 changesets (25.00%)
1640 1641 bundling: 2/4 changesets (50.00%)
1641 1642 bundling: 3/4 changesets (75.00%)
1642 1643 bundling: 4/4 changesets (100.00%)
1643 1644 bundling: 1/4 manifests (25.00%)
1644 1645 bundling: 2/4 manifests (50.00%)
1645 1646 bundling: 3/4 manifests (75.00%)
1646 1647 bundling: 4/4 manifests (100.00%)
1647 1648 bundling: abc.txt 1/4 files (25.00%)
1648 1649 bundling: foo/Bar/file.txt 2/4 files (50.00%)
1649 1650 bundling: foo/file.txt 3/4 files (75.00%)
1650 1651 bundling: quux/file.py 4/4 files (100.00%)
1651 1652 changesets: 1 chunks
1652 1653 add changeset ef1ea85a6374
1653 1654 changesets: 2 chunks
1654 1655 add changeset f9cafe1212c8
1655 1656 changesets: 3 chunks
1656 1657 add changeset 911600dab2ae
1657 1658 changesets: 4 chunks
1658 1659 add changeset e8fc755d4d82
1659 1660 adding manifests
1660 1661 manifests: 1/4 chunks (25.00%)
1661 1662 manifests: 2/4 chunks (50.00%)
1662 1663 manifests: 3/4 chunks (75.00%)
1663 1664 manifests: 4/4 chunks (100.00%)
1664 1665 adding file changes
1665 1666 adding abc.txt revisions
1666 1667 files: 1/4 chunks (25.00%)
1667 1668 adding foo/Bar/file.txt revisions
1668 1669 files: 2/4 chunks (50.00%)
1669 1670 adding foo/file.txt revisions
1670 1671 files: 3/4 chunks (75.00%)
1671 1672 adding quux/file.py revisions
1672 1673 files: 4/4 chunks (100.00%)
1673 1674 added 4 changesets with 4 changes to 4 files (+1 heads)
1674 1675 calling hook pretxnchangegroup.acl: hgext.acl.hook
1675 1676 acl: checking access for user "astro"
1676 1677 acl: acl.allow.branches enabled, 0 entries for user astro
1677 1678 acl: acl.deny.branches not enabled
1678 1679 acl: acl.allow not enabled
1679 1680 acl: acl.deny not enabled
1680 1681 error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1681 1682 transaction abort!
1682 1683 rollback completed
1683 1684 abort: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
1684 1685 no rollback information available
1685 1686 2:fb35475503ef
1686 1687
1687 1688 $ do_push george
1688 1689 Pushing as user george
1689 1690 hgrc = """
1690 1691 [acl]
1691 1692 sources = push
1692 1693 [extensions]
1693 1694 [acl.allow.branches]
1694 1695 * = george
1695 1696 """
1696 1697 pushing to ../b
1697 1698 query 1; heads
1698 1699 searching for changes
1699 1700 all remote heads known locally
1700 1701 4 changesets found
1701 1702 list of changesets:
1702 1703 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1703 1704 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1704 1705 911600dab2ae7a9baff75958b84fe606851ce955
1705 1706 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1706 1707 adding changesets
1707 1708 bundling: 1/4 changesets (25.00%)
1708 1709 bundling: 2/4 changesets (50.00%)
1709 1710 bundling: 3/4 changesets (75.00%)
1710 1711 bundling: 4/4 changesets (100.00%)
1711 1712 bundling: 1/4 manifests (25.00%)
1712 1713 bundling: 2/4 manifests (50.00%)
1713 1714 bundling: 3/4 manifests (75.00%)
1714 1715 bundling: 4/4 manifests (100.00%)
1715 1716 bundling: abc.txt 1/4 files (25.00%)
1716 1717 bundling: foo/Bar/file.txt 2/4 files (50.00%)
1717 1718 bundling: foo/file.txt 3/4 files (75.00%)
1718 1719 bundling: quux/file.py 4/4 files (100.00%)
1719 1720 changesets: 1 chunks
1720 1721 add changeset ef1ea85a6374
1721 1722 changesets: 2 chunks
1722 1723 add changeset f9cafe1212c8
1723 1724 changesets: 3 chunks
1724 1725 add changeset 911600dab2ae
1725 1726 changesets: 4 chunks
1726 1727 add changeset e8fc755d4d82
1727 1728 adding manifests
1728 1729 manifests: 1/4 chunks (25.00%)
1729 1730 manifests: 2/4 chunks (50.00%)
1730 1731 manifests: 3/4 chunks (75.00%)
1731 1732 manifests: 4/4 chunks (100.00%)
1732 1733 adding file changes
1733 1734 adding abc.txt revisions
1734 1735 files: 1/4 chunks (25.00%)
1735 1736 adding foo/Bar/file.txt revisions
1736 1737 files: 2/4 chunks (50.00%)
1737 1738 adding foo/file.txt revisions
1738 1739 files: 3/4 chunks (75.00%)
1739 1740 adding quux/file.py revisions
1740 1741 files: 4/4 chunks (100.00%)
1741 1742 added 4 changesets with 4 changes to 4 files (+1 heads)
1742 1743 calling hook pretxnchangegroup.acl: hgext.acl.hook
1743 1744 acl: checking access for user "george"
1744 1745 acl: acl.allow.branches enabled, 1 entries for user george
1745 1746 acl: acl.deny.branches not enabled
1746 1747 acl: acl.allow not enabled
1747 1748 acl: acl.deny not enabled
1748 1749 acl: branch access granted: "ef1ea85a6374" on branch "default"
1749 1750 acl: path access granted: "ef1ea85a6374"
1750 1751 acl: branch access granted: "f9cafe1212c8" on branch "default"
1751 1752 acl: path access granted: "f9cafe1212c8"
1752 1753 acl: branch access granted: "911600dab2ae" on branch "default"
1753 1754 acl: path access granted: "911600dab2ae"
1754 1755 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1755 1756 acl: path access granted: "e8fc755d4d82"
1756 1757 updating the branch cache
1757 1758 checking for updated bookmarks
1758 1759 repository tip rolled back to revision 2 (undo push)
1759 1760 2:fb35475503ef
1760 1761
1761 1762
1762 1763 Branch acl conflicting allow
1763 1764 asterisk ends up applying to all branches and allowing george to
1764 1765 push foobar into the remote
1765 1766
1766 1767 $ init_config
1767 1768 $ echo "[acl.allow.branches]" >> $config
1768 1769 $ echo "foobar = astro" >> $config
1769 1770 $ echo "* = george" >> $config
1770 1771 $ do_push george
1771 1772 Pushing as user george
1772 1773 hgrc = """
1773 1774 [acl]
1774 1775 sources = push
1775 1776 [extensions]
1776 1777 [acl.allow.branches]
1777 1778 foobar = astro
1778 1779 * = george
1779 1780 """
1780 1781 pushing to ../b
1781 1782 query 1; heads
1782 1783 searching for changes
1783 1784 all remote heads known locally
1784 1785 invalidating branch cache (tip differs)
1785 1786 4 changesets found
1786 1787 list of changesets:
1787 1788 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1788 1789 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1789 1790 911600dab2ae7a9baff75958b84fe606851ce955
1790 1791 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1791 1792 adding changesets
1792 1793 bundling: 1/4 changesets (25.00%)
1793 1794 bundling: 2/4 changesets (50.00%)
1794 1795 bundling: 3/4 changesets (75.00%)
1795 1796 bundling: 4/4 changesets (100.00%)
1796 1797 bundling: 1/4 manifests (25.00%)
1797 1798 bundling: 2/4 manifests (50.00%)
1798 1799 bundling: 3/4 manifests (75.00%)
1799 1800 bundling: 4/4 manifests (100.00%)
1800 1801 bundling: abc.txt 1/4 files (25.00%)
1801 1802 bundling: foo/Bar/file.txt 2/4 files (50.00%)
1802 1803 bundling: foo/file.txt 3/4 files (75.00%)
1803 1804 bundling: quux/file.py 4/4 files (100.00%)
1804 1805 changesets: 1 chunks
1805 1806 add changeset ef1ea85a6374
1806 1807 changesets: 2 chunks
1807 1808 add changeset f9cafe1212c8
1808 1809 changesets: 3 chunks
1809 1810 add changeset 911600dab2ae
1810 1811 changesets: 4 chunks
1811 1812 add changeset e8fc755d4d82
1812 1813 adding manifests
1813 1814 manifests: 1/4 chunks (25.00%)
1814 1815 manifests: 2/4 chunks (50.00%)
1815 1816 manifests: 3/4 chunks (75.00%)
1816 1817 manifests: 4/4 chunks (100.00%)
1817 1818 adding file changes
1818 1819 adding abc.txt revisions
1819 1820 files: 1/4 chunks (25.00%)
1820 1821 adding foo/Bar/file.txt revisions
1821 1822 files: 2/4 chunks (50.00%)
1822 1823 adding foo/file.txt revisions
1823 1824 files: 3/4 chunks (75.00%)
1824 1825 adding quux/file.py revisions
1825 1826 files: 4/4 chunks (100.00%)
1826 1827 added 4 changesets with 4 changes to 4 files (+1 heads)
1827 1828 calling hook pretxnchangegroup.acl: hgext.acl.hook
1828 1829 acl: checking access for user "george"
1829 1830 acl: acl.allow.branches enabled, 1 entries for user george
1830 1831 acl: acl.deny.branches not enabled
1831 1832 acl: acl.allow not enabled
1832 1833 acl: acl.deny not enabled
1833 1834 acl: branch access granted: "ef1ea85a6374" on branch "default"
1834 1835 acl: path access granted: "ef1ea85a6374"
1835 1836 acl: branch access granted: "f9cafe1212c8" on branch "default"
1836 1837 acl: path access granted: "f9cafe1212c8"
1837 1838 acl: branch access granted: "911600dab2ae" on branch "default"
1838 1839 acl: path access granted: "911600dab2ae"
1839 1840 acl: branch access granted: "e8fc755d4d82" on branch "foobar"
1840 1841 acl: path access granted: "e8fc755d4d82"
1841 1842 updating the branch cache
1842 1843 checking for updated bookmarks
1843 1844 repository tip rolled back to revision 2 (undo push)
1844 1845 2:fb35475503ef
1845 1846
1846 1847 Branch acl conflicting deny
1847 1848
1848 1849 $ init_config
1849 1850 $ echo "[acl.deny.branches]" >> $config
1850 1851 $ echo "foobar = astro" >> $config
1851 1852 $ echo "default = astro" >> $config
1852 1853 $ echo "* = george" >> $config
1853 1854 $ do_push george
1854 1855 Pushing as user george
1855 1856 hgrc = """
1856 1857 [acl]
1857 1858 sources = push
1858 1859 [extensions]
1859 1860 [acl.deny.branches]
1860 1861 foobar = astro
1861 1862 default = astro
1862 1863 * = george
1863 1864 """
1864 1865 pushing to ../b
1865 1866 query 1; heads
1866 1867 searching for changes
1867 1868 all remote heads known locally
1868 1869 invalidating branch cache (tip differs)
1869 1870 4 changesets found
1870 1871 list of changesets:
1871 1872 ef1ea85a6374b77d6da9dcda9541f498f2d17df7
1872 1873 f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
1873 1874 911600dab2ae7a9baff75958b84fe606851ce955
1874 1875 e8fc755d4d8217ee5b0c2bb41558c40d43b92c01
1875 1876 adding changesets
1876 1877 bundling: 1/4 changesets (25.00%)
1877 1878 bundling: 2/4 changesets (50.00%)
1878 1879 bundling: 3/4 changesets (75.00%)
1879 1880 bundling: 4/4 changesets (100.00%)
1880 1881 bundling: 1/4 manifests (25.00%)
1881 1882 bundling: 2/4 manifests (50.00%)
1882 1883 bundling: 3/4 manifests (75.00%)
1883 1884 bundling: 4/4 manifests (100.00%)
1884 1885 bundling: abc.txt 1/4 files (25.00%)
1885 1886 bundling: foo/Bar/file.txt 2/4 files (50.00%)
1886 1887 bundling: foo/file.txt 3/4 files (75.00%)
1887 1888 bundling: quux/file.py 4/4 files (100.00%)
1888 1889 changesets: 1 chunks
1889 1890 add changeset ef1ea85a6374
1890 1891 changesets: 2 chunks
1891 1892 add changeset f9cafe1212c8
1892 1893 changesets: 3 chunks
1893 1894 add changeset 911600dab2ae
1894 1895 changesets: 4 chunks
1895 1896 add changeset e8fc755d4d82
1896 1897 adding manifests
1897 1898 manifests: 1/4 chunks (25.00%)
1898 1899 manifests: 2/4 chunks (50.00%)
1899 1900 manifests: 3/4 chunks (75.00%)
1900 1901 manifests: 4/4 chunks (100.00%)
1901 1902 adding file changes
1902 1903 adding abc.txt revisions
1903 1904 files: 1/4 chunks (25.00%)
1904 1905 adding foo/Bar/file.txt revisions
1905 1906 files: 2/4 chunks (50.00%)
1906 1907 adding foo/file.txt revisions
1907 1908 files: 3/4 chunks (75.00%)
1908 1909 adding quux/file.py revisions
1909 1910 files: 4/4 chunks (100.00%)
1910 1911 added 4 changesets with 4 changes to 4 files (+1 heads)
1911 1912 calling hook pretxnchangegroup.acl: hgext.acl.hook
1912 1913 acl: checking access for user "george"
1913 1914 acl: acl.allow.branches not enabled
1914 1915 acl: acl.deny.branches enabled, 1 entries for user george
1915 1916 acl: acl.allow not enabled
1916 1917 acl: acl.deny not enabled
1917 1918 error: pretxnchangegroup.acl hook failed: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
1918 1919 transaction abort!
1919 1920 rollback completed
1920 1921 abort: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
1921 1922 no rollback information available
1922 1923 2:fb35475503ef
1923 1924
@@ -1,288 +1,290 b''
1 1 $ hg init basic
2 2 $ cd basic
3 3
4 4 should complain
5 5
6 6 $ hg backout
7 7 abort: please specify a revision to backout
8 8 [255]
9 9 $ hg backout -r 0 0
10 10 abort: please specify just one revision
11 11 [255]
12 12
13 13 basic operation
14 14
15 15 $ echo a > a
16 16 $ hg commit -d '0 0' -A -m a
17 17 adding a
18 18 $ echo b >> a
19 19 $ hg commit -d '1 0' -m b
20 20
21 21 $ hg backout -d '2 0' tip --tool=true
22 22 reverting a
23 23 changeset 2:2929462c3dff backs out changeset 1:a820f4f40a57
24 24 $ cat a
25 25 a
26 26
27 27 file that was removed is recreated
28 28
29 29 $ cd ..
30 30 $ hg init remove
31 31 $ cd remove
32 32
33 33 $ echo content > a
34 34 $ hg commit -d '0 0' -A -m a
35 35 adding a
36 36
37 37 $ hg rm a
38 38 $ hg commit -d '1 0' -m b
39 39
40 40 $ hg backout -d '2 0' tip --tool=true
41 41 adding a
42 42 changeset 2:de31bdc76c0d backs out changeset 1:76862dcce372
43 43 $ cat a
44 44 content
45 45
46 46 backout of backout is as if nothing happened
47 47
48 48 $ hg backout -d '3 0' --merge tip --tool=true
49 49 removing a
50 50 changeset 3:7f6d0f120113 backs out changeset 2:de31bdc76c0d
51 51 $ test -f a
52 52 [1]
53 53
54 54 across branch
55 55
56 56 $ cd ..
57 57 $ hg init branch
58 58 $ cd branch
59 59 $ echo a > a
60 60 $ hg ci -Am0
61 61 adding a
62 62 $ echo b > b
63 63 $ hg ci -Am1
64 64 adding b
65 65 $ hg co -C 0
66 66 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
67 67
68 68 should fail
69 69
70 70 $ hg backout 1
71 71 abort: cannot backout change on a different branch
72 72 [255]
73 73 $ echo c > c
74 74 $ hg ci -Am2
75 75 adding c
76 76 created new head
77 77
78 78 should fail
79 79
80 80 $ hg backout 1
81 81 abort: cannot backout change on a different branch
82 82 [255]
83 83
84 84 backout with merge
85 85
86 86 $ cd ..
87 87 $ hg init merge
88 88 $ cd merge
89 89
90 90 $ echo line 1 > a
91 91 $ echo line 2 >> a
92 92 $ hg commit -d '0 0' -A -m a
93 93 adding a
94 94
95 95 remove line 1
96 96
97 97 $ echo line 2 > a
98 98 $ hg commit -d '1 0' -m b
99 99
100 100 $ echo line 3 >> a
101 101 $ hg commit -d '2 0' -m c
102 102
103 103 $ hg backout --merge -d '3 0' 1 --tool=true
104 104 reverting a
105 105 created new head
106 106 changeset 3:26b8ccb9ad91 backs out changeset 1:5a50a024c182
107 107 merging with changeset 3:26b8ccb9ad91
108 108 merging a
109 109 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
110 110 (branch merge, don't forget to commit)
111 111 $ hg commit -d '4 0' -m d
112 112
113 113 check line 1 is back
114 114
115 115 $ cat a
116 116 line 1
117 117 line 2
118 118 line 3
119 119
120 120 backout should not back out subsequent changesets
121 121
122 122 $ hg init onecs
123 123 $ cd onecs
124 124 $ echo 1 > a
125 125 $ hg commit -d '0 0' -A -m a
126 126 adding a
127 127 $ echo 2 >> a
128 128 $ hg commit -d '1 0' -m b
129 129 $ echo 1 > b
130 130 $ hg commit -d '2 0' -A -m c
131 131 adding b
132 132
133 133 without --merge
134 134 $ hg backout -d '3 0' 1 --tool=true
135 135 reverting a
136 136 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
137 137 $ hg locate b
138 138 b
139 139 $ hg update -C tip
140 140 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 141 $ hg locate b
142 142 b
143 143
144 144 with --merge
145 145 $ hg backout --merge -d '3 0' 1 --tool=true
146 146 reverting a
147 147 created new head
148 148 changeset 3:3202beb76721 backs out changeset 1:22bca4c721e5
149 149 merging with changeset 3:3202beb76721
150 150 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
151 151 (branch merge, don't forget to commit)
152 152 $ hg locate b
153 153 b
154 154 $ hg update -C tip
155 155 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
156 156 $ hg locate b
157 157 [1]
158 158
159 159 $ cd ..
160 160 $ hg init m
161 161 $ cd m
162 162 $ echo a > a
163 163 $ hg commit -d '0 0' -A -m a
164 164 adding a
165 165 $ echo b > b
166 166 $ hg commit -d '1 0' -A -m b
167 167 adding b
168 168 $ echo c > c
169 169 $ hg commit -d '2 0' -A -m b
170 170 adding c
171 171 $ hg update 1
172 172 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
173 173 $ echo d > d
174 174 $ hg commit -d '3 0' -A -m c
175 175 adding d
176 176 created new head
177 177 $ hg merge 2
178 178 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
179 179 (branch merge, don't forget to commit)
180 180 $ hg commit -d '4 0' -A -m d
181 181
182 182 backout of merge should fail
183 183
184 184 $ hg backout 4
185 185 abort: cannot backout a merge changeset
186 186 [255]
187 187
188 188 backout of merge with bad parent should fail
189 189
190 190 $ hg backout --parent 0 4
191 191 abort: cb9a9f314b8b is not a parent of b2f3bb92043e
192 192 [255]
193 193
194 194 backout of non-merge with parent should fail
195 195
196 196 $ hg backout --parent 0 3
197 197 abort: cannot use --parent on non-merge changeset
198 198 [255]
199 199
200 200 backout with valid parent should be ok
201 201
202 202 $ hg backout -d '5 0' --parent 2 4 --tool=true
203 203 removing d
204 204 changeset 5:10e5328c8435 backs out changeset 4:b2f3bb92043e
205 205
206 206 $ hg rollback
207 207 repository tip rolled back to revision 4 (undo commit)
208 208 working directory now based on revision 4
209 209 $ hg update -C
210 210 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
211 211
212 212 $ hg backout -d '6 0' --parent 3 4 --tool=true
213 213 removing c
214 214 changeset 5:033590168430 backs out changeset 4:b2f3bb92043e
215 215
216 216 $ cd ..
217 217
218 218 named branches
219 219
220 220 $ hg init named_branches
221 221 $ cd named_branches
222 222
223 223 $ echo default > default
224 224 $ hg ci -d '0 0' -Am default
225 225 adding default
226 226 $ hg branch branch1
227 227 marked working directory as branch branch1
228 (branches are permanent and global, did you want a bookmark?)
228 229 $ echo branch1 > file1
229 230 $ hg ci -d '1 0' -Am file1
230 231 adding file1
231 232 $ hg branch branch2
232 233 marked working directory as branch branch2
234 (branches are permanent and global, did you want a bookmark?)
233 235 $ echo branch2 > file2
234 236 $ hg ci -d '2 0' -Am file2
235 237 adding file2
236 238
237 239 without --merge
238 240 $ hg backout -r 1 --tool=true
239 241 removing file1
240 242 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
241 243 $ hg branch
242 244 branch2
243 245 $ hg status -A
244 246 R file1
245 247 C default
246 248 C file2
247 249
248 250 with --merge
249 251 $ hg update -qC
250 252 $ hg backout --merge -d '3 0' -r 1 -m 'backout on branch1' --tool=true
251 253 removing file1
252 254 created new head
253 255 changeset 3:d4e8f6db59fb backs out changeset 1:bf1602f437f3
254 256 merging with changeset 3:d4e8f6db59fb
255 257 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
256 258 (branch merge, don't forget to commit)
257 259 $ hg update -q -C 2
258 260
259 261 on branch2 with branch1 not merged, so file1 should still exist:
260 262
261 263 $ hg id
262 264 45bbcd363bf0 (branch2)
263 265 $ hg st -A
264 266 C default
265 267 C file1
266 268 C file2
267 269
268 270 on branch2 with branch1 merged, so file1 should be gone:
269 271
270 272 $ hg merge
271 273 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
272 274 (branch merge, don't forget to commit)
273 275 $ hg ci -d '4 0' -m 'merge backout of branch1'
274 276 $ hg id
275 277 22149cdde76d (branch2) tip
276 278 $ hg st -A
277 279 C default
278 280 C file2
279 281
280 282 on branch1, so no file1 and file2:
281 283
282 284 $ hg co -C branch1
283 285 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
284 286 $ hg id
285 287 bf1602f437f3 (branch1)
286 288 $ hg st -A
287 289 C default
288 290 C file1
@@ -1,367 +1,374 b''
1 1 $ heads()
2 2 > {
3 3 > hg heads --template '{rev}: {desc|firstline|strip} ({branches})\n' "$@"
4 4 > }
5 5
6 6 $ hg init a
7 7 $ cd a
8 8 $ echo 'root' >root
9 9 $ hg add root
10 10 $ hg commit -m "Adding root node"
11 11 $ heads
12 12 0: Adding root node ()
13 13 -------
14 14 $ heads .
15 15 0: Adding root node ()
16 16
17 17 =======
18 18
19 19 $ echo 'a' >a
20 20 $ hg add a
21 21 $ hg branch a
22 22 marked working directory as branch a
23 (branches are permanent and global, did you want a bookmark?)
23 24 $ hg commit -m "Adding a branch"
24 25 $ heads
25 26 1: Adding a branch (a)
26 27 0: Adding root node ()
27 28 -------
28 29 $ heads .
29 30 1: Adding a branch (a)
30 31
31 32 =======
32 33
33 34 $ hg update -C 0
34 35 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
35 36 $ echo 'b' >b
36 37 $ hg add b
37 38 $ hg branch b
38 39 marked working directory as branch b
40 (branches are permanent and global, did you want a bookmark?)
39 41 $ hg commit -m "Adding b branch"
40 42 $ heads
41 43 2: Adding b branch (b)
42 44 1: Adding a branch (a)
43 45 0: Adding root node ()
44 46 -------
45 47 $ heads .
46 48 2: Adding b branch (b)
47 49
48 50 =======
49 51
50 52 $ echo 'bh1' >bh1
51 53 $ hg add bh1
52 54 $ hg commit -m "Adding b branch head 1"
53 55 $ heads
54 56 3: Adding b branch head 1 (b)
55 57 1: Adding a branch (a)
56 58 0: Adding root node ()
57 59 -------
58 60 $ heads .
59 61 3: Adding b branch head 1 (b)
60 62
61 63 =======
62 64
63 65 $ hg update -C 2
64 66 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
65 67 $ echo 'bh2' >bh2
66 68 $ hg add bh2
67 69 $ hg commit -m "Adding b branch head 2"
68 70 created new head
69 71 $ heads
70 72 4: Adding b branch head 2 (b)
71 73 3: Adding b branch head 1 (b)
72 74 1: Adding a branch (a)
73 75 0: Adding root node ()
74 76 $ heads .
75 77 4: Adding b branch head 2 (b)
76 78 3: Adding b branch head 1 (b)
77 79
78 80 =======
79 81
80 82 $ hg update -C 2
81 83 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
82 84 $ echo 'bh3' >bh3
83 85 $ hg add bh3
84 86 $ hg commit -m "Adding b branch head 3"
85 87 created new head
86 88 $ heads
87 89 5: Adding b branch head 3 (b)
88 90 4: Adding b branch head 2 (b)
89 91 3: Adding b branch head 1 (b)
90 92 1: Adding a branch (a)
91 93 0: Adding root node ()
92 94 -------
93 95 $ heads .
94 96 5: Adding b branch head 3 (b)
95 97 4: Adding b branch head 2 (b)
96 98 3: Adding b branch head 1 (b)
97 99
98 100 =======
99 101
100 102 $ hg merge 4
101 103 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
102 104 (branch merge, don't forget to commit)
103 105 $ hg commit -m "Merging b branch head 2 and b branch head 3"
104 106 $ heads
105 107 6: Merging b branch head 2 and b branch head 3 (b)
106 108 3: Adding b branch head 1 (b)
107 109 1: Adding a branch (a)
108 110 0: Adding root node ()
109 111 -------
110 112 $ heads .
111 113 6: Merging b branch head 2 and b branch head 3 (b)
112 114 3: Adding b branch head 1 (b)
113 115
114 116 =======
115 117
116 118 $ echo 'c' >c
117 119 $ hg add c
118 120 $ hg branch c
119 121 marked working directory as branch c
122 (branches are permanent and global, did you want a bookmark?)
120 123 $ hg commit -m "Adding c branch"
121 124 $ heads
122 125 7: Adding c branch (c)
123 126 6: Merging b branch head 2 and b branch head 3 (b)
124 127 3: Adding b branch head 1 (b)
125 128 1: Adding a branch (a)
126 129 0: Adding root node ()
127 130 -------
128 131 $ heads .
129 132 7: Adding c branch (c)
130 133
131 134 =======
132 135
133 136 $ heads -r 3 .
134 137 no open branch heads found on branches c (started at 3)
135 138 [1]
136 139 $ heads -r 2 .
137 140 7: Adding c branch (c)
138 141 -------
139 142 $ hg update -C 4
140 143 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
141 144 -------
142 145 $ heads -r 3 .
143 146 3: Adding b branch head 1 (b)
144 147 -------
145 148 $ heads -r 2 .
146 149 6: Merging b branch head 2 and b branch head 3 (b)
147 150 3: Adding b branch head 1 (b)
148 151 -------
149 152 $ heads -r 7 .
150 153 no open branch heads found on branches b (started at 7)
151 154 [1]
152 155
153 156 =======
154 157
155 158 $ for i in 0 1 2 3 4 5 6 7; do
156 159 > hg update -C "$i"
157 160 > heads
158 161 > echo '-------'
159 162 > heads .
160 163 > echo '-------'
161 164 > done
162 165 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
163 166 7: Adding c branch (c)
164 167 6: Merging b branch head 2 and b branch head 3 (b)
165 168 3: Adding b branch head 1 (b)
166 169 1: Adding a branch (a)
167 170 0: Adding root node ()
168 171 -------
169 172 0: Adding root node ()
170 173 -------
171 174 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
172 175 7: Adding c branch (c)
173 176 6: Merging b branch head 2 and b branch head 3 (b)
174 177 3: Adding b branch head 1 (b)
175 178 1: Adding a branch (a)
176 179 0: Adding root node ()
177 180 -------
178 181 1: Adding a branch (a)
179 182 -------
180 183 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
181 184 7: Adding c branch (c)
182 185 6: Merging b branch head 2 and b branch head 3 (b)
183 186 3: Adding b branch head 1 (b)
184 187 1: Adding a branch (a)
185 188 0: Adding root node ()
186 189 -------
187 190 6: Merging b branch head 2 and b branch head 3 (b)
188 191 3: Adding b branch head 1 (b)
189 192 -------
190 193 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 194 7: Adding c branch (c)
192 195 6: Merging b branch head 2 and b branch head 3 (b)
193 196 3: Adding b branch head 1 (b)
194 197 1: Adding a branch (a)
195 198 0: Adding root node ()
196 199 -------
197 200 6: Merging b branch head 2 and b branch head 3 (b)
198 201 3: Adding b branch head 1 (b)
199 202 -------
200 203 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
201 204 7: Adding c branch (c)
202 205 6: Merging b branch head 2 and b branch head 3 (b)
203 206 3: Adding b branch head 1 (b)
204 207 1: Adding a branch (a)
205 208 0: Adding root node ()
206 209 -------
207 210 6: Merging b branch head 2 and b branch head 3 (b)
208 211 3: Adding b branch head 1 (b)
209 212 -------
210 213 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
211 214 7: Adding c branch (c)
212 215 6: Merging b branch head 2 and b branch head 3 (b)
213 216 3: Adding b branch head 1 (b)
214 217 1: Adding a branch (a)
215 218 0: Adding root node ()
216 219 -------
217 220 6: Merging b branch head 2 and b branch head 3 (b)
218 221 3: Adding b branch head 1 (b)
219 222 -------
220 223 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
221 224 7: Adding c branch (c)
222 225 6: Merging b branch head 2 and b branch head 3 (b)
223 226 3: Adding b branch head 1 (b)
224 227 1: Adding a branch (a)
225 228 0: Adding root node ()
226 229 -------
227 230 6: Merging b branch head 2 and b branch head 3 (b)
228 231 3: Adding b branch head 1 (b)
229 232 -------
230 233 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
231 234 7: Adding c branch (c)
232 235 6: Merging b branch head 2 and b branch head 3 (b)
233 236 3: Adding b branch head 1 (b)
234 237 1: Adding a branch (a)
235 238 0: Adding root node ()
236 239 -------
237 240 7: Adding c branch (c)
238 241 -------
239 242
240 243 =======
241 244
242 245 $ for i in a b c z; do
243 246 > heads "$i"
244 247 > echo '-------'
245 248 > done
246 249 1: Adding a branch (a)
247 250 -------
248 251 6: Merging b branch head 2 and b branch head 3 (b)
249 252 3: Adding b branch head 1 (b)
250 253 -------
251 254 7: Adding c branch (c)
252 255 -------
253 256 abort: unknown revision 'z'!
254 257 -------
255 258
256 259 =======
257 260
258 261 $ heads 0 1 2 3 4 5 6 7
259 262 7: Adding c branch (c)
260 263 6: Merging b branch head 2 and b branch head 3 (b)
261 264 3: Adding b branch head 1 (b)
262 265 1: Adding a branch (a)
263 266 0: Adding root node ()
264 267
265 268 Topological heads:
266 269
267 270 $ heads -t
268 271 7: Adding c branch (c)
269 272 3: Adding b branch head 1 (b)
270 273 1: Adding a branch (a)
271 274
272 275 $ cd ..
273 276 ______________
274 277
275 278 "created new head" message tests
276 279
277 280 $ hg init newheadmsg
278 281 $ cd newheadmsg
279 282
280 283 Init: no msg
281 284
282 285 $ echo 1 > a
283 286 $ hg ci -Am "a0: Initial root"
284 287 adding a
285 288 $ echo 2 >> a
286 289 $ hg ci -m "a1 (HN)"
287 290
288 291 $ hg branch b
289 292 marked working directory as branch b
293 (branches are permanent and global, did you want a bookmark?)
290 294 $ echo 1 > b
291 295 $ hg ci -Am "b2: Initial root for branch b"
292 296 adding b
293 297 $ echo 2 >> b
294 298 $ hg ci -m "b3 (HN)"
295 299
296 300 Case NN: msg
297 301
298 302 $ hg up -q null
299 303 $ hg branch -f b
300 304 marked working directory as branch b
305 (branches are permanent and global, did you want a bookmark?)
301 306 $ echo 1 > bb
302 307 $ hg ci -Am "b4 (NN): new topo root for branch b"
303 308 adding bb
304 309 created new head
305 310
306 311 Case HN: no msg
307 312
308 313 $ echo 2 >> bb
309 314 $ hg ci -m "b5 (HN)"
310 315
311 316 Case BN: msg
312 317
313 318 $ hg branch -f default
314 319 marked working directory as branch default
320 (branches are permanent and global, did you want a bookmark?)
315 321 $ echo 1 > aa
316 322 $ hg ci -Am "a6 (BN): new branch root"
317 323 adding aa
318 324 created new head
319 325
320 326 Case CN: msg
321 327
322 328 $ hg up -q 4
323 329 $ echo 3 >> bbb
324 330 $ hg ci -Am "b7 (CN): regular new head"
325 331 adding bbb
326 332 created new head
327 333
328 334 Case BB: msg
329 335
330 336 $ hg up -q 4
331 337 $ hg merge -q 3
332 338 $ hg branch -f default
333 339 marked working directory as branch default
340 (branches are permanent and global, did you want a bookmark?)
334 341 $ hg ci -m "a8 (BB): weird new branch root"
335 342 created new head
336 343
337 344 Case CB: msg
338 345
339 346 $ hg up -q 4
340 347 $ hg merge -q 1
341 348 $ hg ci -m "b9 (CB): new head from branch merge"
342 349 created new head
343 350
344 351 Case HB: no msg
345 352
346 353 $ hg up -q 7
347 354 $ hg merge -q 6
348 355 $ hg ci -m "b10 (HB): continuing head from branch merge"
349 356
350 357 Case CC: msg
351 358
352 359 $ hg up -q 4
353 360 $ hg merge -q 2
354 361 $ hg ci -m "b11 (CC): new head from merge"
355 362 created new head
356 363
357 364 Case CH: no msg
358 365
359 366 $ hg up -q 2
360 367 $ hg merge -q 10
361 368 $ hg ci -m "b12 (CH): continuing head from merge"
362 369
363 370 Case HH: no msg
364 371
365 372 $ hg merge -q 3
366 373 $ hg ci -m "b12 (HH): merging two heads"
367 374
@@ -1,361 +1,362 b''
1 1 $ hg init
2 2
3 3 no bookmarks
4 4
5 5 $ hg bookmarks
6 6 no bookmarks set
7 7
8 8 bookmark rev -1
9 9
10 10 $ hg bookmark X
11 11
12 12 list bookmarks
13 13
14 14 $ hg bookmarks
15 15 * X -1:000000000000
16 16
17 17 list bookmarks with color
18 18
19 19 $ hg --config extensions.color= --config color.mode=ansi \
20 20 > bookmarks --color=always
21 21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
22 22
23 23 $ echo a > a
24 24 $ hg add a
25 25 $ hg commit -m 0
26 26
27 27 bookmark X moved to rev 0
28 28
29 29 $ hg bookmarks
30 30 * X 0:f7b1eb17ad24
31 31
32 32 look up bookmark
33 33
34 34 $ hg log -r X
35 35 changeset: 0:f7b1eb17ad24
36 36 bookmark: X
37 37 tag: tip
38 38 user: test
39 39 date: Thu Jan 01 00:00:00 1970 +0000
40 40 summary: 0
41 41
42 42
43 43 second bookmark for rev 0
44 44
45 45 $ hg bookmark X2
46 46
47 47 bookmark rev -1 again
48 48
49 49 $ hg bookmark -r null Y
50 50
51 51 list bookmarks
52 52
53 53 $ hg bookmarks
54 54 X 0:f7b1eb17ad24
55 55 * X2 0:f7b1eb17ad24
56 56 Y -1:000000000000
57 57
58 58 $ echo b > b
59 59 $ hg add b
60 60 $ hg commit -m 1
61 61
62 62 bookmarks revset
63 63
64 64 $ hg log -r 'bookmark()'
65 65 changeset: 0:f7b1eb17ad24
66 66 bookmark: X
67 67 user: test
68 68 date: Thu Jan 01 00:00:00 1970 +0000
69 69 summary: 0
70 70
71 71 changeset: 1:925d80f479bb
72 72 bookmark: X2
73 73 tag: tip
74 74 user: test
75 75 date: Thu Jan 01 00:00:00 1970 +0000
76 76 summary: 1
77 77
78 78 $ hg log -r 'bookmark(Y)'
79 79 $ hg log -r 'bookmark(X2)'
80 80 changeset: 1:925d80f479bb
81 81 bookmark: X2
82 82 tag: tip
83 83 user: test
84 84 date: Thu Jan 01 00:00:00 1970 +0000
85 85 summary: 1
86 86
87 87 $ hg log -r 'bookmark(unknown)'
88 88 abort: bookmark 'unknown' does not exist
89 89 [255]
90 90
91 91 $ hg help revsets | grep 'bookmark('
92 92 "bookmark([name])"
93 93
94 94 bookmarks X and X2 moved to rev 1, Y at rev -1
95 95
96 96 $ hg bookmarks
97 97 X 0:f7b1eb17ad24
98 98 * X2 1:925d80f479bb
99 99 Y -1:000000000000
100 100
101 101 bookmark rev 0 again
102 102
103 103 $ hg bookmark -r 0 Z
104 104
105 105 $ hg update X
106 106 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
107 107 $ echo c > c
108 108 $ hg add c
109 109 $ hg commit -m 2
110 110 created new head
111 111
112 112 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
113 113
114 114 $ hg bookmarks
115 115 * X 2:db815d6d32e6
116 116 X2 1:925d80f479bb
117 117 Y -1:000000000000
118 118 Z 0:f7b1eb17ad24
119 119
120 120 rename nonexistent bookmark
121 121
122 122 $ hg bookmark -m A B
123 123 abort: bookmark 'A' does not exist
124 124 [255]
125 125
126 126 rename to existent bookmark
127 127
128 128 $ hg bookmark -m X Y
129 129 abort: bookmark 'Y' already exists (use -f to force)
130 130 [255]
131 131
132 132 force rename to existent bookmark
133 133
134 134 $ hg bookmark -f -m X Y
135 135
136 136 list bookmarks
137 137
138 138 $ hg bookmark
139 139 X2 1:925d80f479bb
140 140 * Y 2:db815d6d32e6
141 141 Z 0:f7b1eb17ad24
142 142
143 143 rename without new name
144 144
145 145 $ hg bookmark -m Y
146 146 abort: new bookmark name required
147 147 [255]
148 148
149 149 delete without name
150 150
151 151 $ hg bookmark -d
152 152 abort: bookmark name required
153 153 [255]
154 154
155 155 delete nonexistent bookmark
156 156
157 157 $ hg bookmark -d A
158 158 abort: bookmark 'A' does not exist
159 159 [255]
160 160
161 161 bookmark name with spaces should be stripped
162 162
163 163 $ hg bookmark ' x y '
164 164
165 165 list bookmarks
166 166
167 167 $ hg bookmarks
168 168 X2 1:925d80f479bb
169 169 Y 2:db815d6d32e6
170 170 Z 0:f7b1eb17ad24
171 171 * x y 2:db815d6d32e6
172 172
173 173 look up stripped bookmark name
174 174
175 175 $ hg log -r '"x y"'
176 176 changeset: 2:db815d6d32e6
177 177 bookmark: Y
178 178 bookmark: x y
179 179 tag: tip
180 180 parent: 0:f7b1eb17ad24
181 181 user: test
182 182 date: Thu Jan 01 00:00:00 1970 +0000
183 183 summary: 2
184 184
185 185
186 186 reject bookmark name with newline
187 187
188 188 $ hg bookmark '
189 189 > '
190 190 abort: bookmark name cannot contain newlines
191 191 [255]
192 192
193 193 bookmark with existing name
194 194
195 195 $ hg bookmark Z
196 196 abort: bookmark 'Z' already exists (use -f to force)
197 197 [255]
198 198
199 199 force bookmark with existing name
200 200
201 201 $ hg bookmark -f Z
202 202
203 203 list bookmarks
204 204
205 205 $ hg bookmark
206 206 X2 1:925d80f479bb
207 207 Y 2:db815d6d32e6
208 208 * Z 2:db815d6d32e6
209 209 x y 2:db815d6d32e6
210 210
211 211 revision but no bookmark name
212 212
213 213 $ hg bookmark -r .
214 214 abort: bookmark name required
215 215 [255]
216 216
217 217 bookmark name with whitespace only
218 218
219 219 $ hg bookmark ' '
220 220 abort: bookmark names cannot consist entirely of whitespace
221 221 [255]
222 222
223 223 invalid bookmark
224 224
225 225 $ hg bookmark 'foo:bar'
226 226 abort: bookmark 'foo:bar' contains illegal character
227 227 [255]
228 228
229 229 the bookmark extension should be ignored now that it is part of core
230 230
231 231 $ echo "[extensions]" >> $HGRCPATH
232 232 $ echo "bookmarks=" >> $HGRCPATH
233 233 $ hg bookmarks
234 234 X2 1:925d80f479bb
235 235 Y 2:db815d6d32e6
236 236 * Z 2:db815d6d32e6
237 237 x y 2:db815d6d32e6
238 238
239 239 test summary
240 240
241 241 $ hg summary
242 242 parent: 2:db815d6d32e6 tip
243 243 2
244 244 branch: default
245 245 bookmarks: *Z Y x y
246 246 commit: (clean)
247 247 update: 1 new changesets, 2 branch heads (merge)
248 248
249 249 test id
250 250
251 251 $ hg id
252 252 db815d6d32e6 tip Y/Z/x y
253 253
254 254 test rollback
255 255
256 256 $ echo foo > f1
257 257 $ hg ci -Amr
258 258 adding f1
259 259 $ hg bookmark -f Y -r 1
260 260 $ hg bookmark -f Z -r 1
261 261 $ hg rollback
262 262 repository tip rolled back to revision 2 (undo commit)
263 263 working directory now based on revision 2
264 264 $ hg bookmarks
265 265 X2 1:925d80f479bb
266 266 Y 2:db815d6d32e6
267 267 * Z 2:db815d6d32e6
268 268 x y 2:db815d6d32e6
269 269
270 270 test clone
271 271
272 272 $ hg bookmarks
273 273 X2 1:925d80f479bb
274 274 Y 2:db815d6d32e6
275 275 * Z 2:db815d6d32e6
276 276 x y 2:db815d6d32e6
277 277 $ hg clone . cloned-bookmarks
278 278 updating to branch default
279 279 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
280 280 $ hg -R cloned-bookmarks bookmarks
281 281 X2 1:925d80f479bb
282 282 Y 2:db815d6d32e6
283 283 Z 2:db815d6d32e6
284 284 x y 2:db815d6d32e6
285 285
286 286 test clone with pull protocol
287 287
288 288 $ hg clone --pull . cloned-bookmarks-pull
289 289 requesting all changes
290 290 adding changesets
291 291 adding manifests
292 292 adding file changes
293 293 added 3 changesets with 3 changes to 3 files (+1 heads)
294 294 updating to branch default
295 295 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
296 296 $ hg -R cloned-bookmarks-pull bookmarks
297 297 X2 1:925d80f479bb
298 298 Y 2:db815d6d32e6
299 299 Z 2:db815d6d32e6
300 300 x y 2:db815d6d32e6
301 301
302 302 test clone with a specific revision
303 303
304 304 $ hg clone -r 925d80 . cloned-bookmarks-rev
305 305 adding changesets
306 306 adding manifests
307 307 adding file changes
308 308 added 2 changesets with 2 changes to 2 files
309 309 updating to branch default
310 310 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
311 311 $ hg -R cloned-bookmarks-rev bookmarks
312 312 X2 1:925d80f479bb
313 313
314 314 create bundle with two heads
315 315
316 316 $ hg clone . tobundle
317 317 updating to branch default
318 318 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
319 319 $ echo x > tobundle/x
320 320 $ hg -R tobundle add tobundle/x
321 321 $ hg -R tobundle commit -m'x'
322 322 $ hg -R tobundle update -r -2
323 323 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
324 324 $ echo y > tobundle/y
325 325 $ hg -R tobundle branch test
326 326 marked working directory as branch test
327 (branches are permanent and global, did you want a bookmark?)
327 328 $ hg -R tobundle add tobundle/y
328 329 $ hg -R tobundle commit -m'y'
329 330 $ hg -R tobundle bundle tobundle.hg
330 331 searching for changes
331 332 2 changesets found
332 333 $ hg unbundle tobundle.hg
333 334 adding changesets
334 335 adding manifests
335 336 adding file changes
336 337 added 2 changesets with 2 changes to 2 files (+1 heads)
337 338 (run 'hg heads' to see heads, 'hg merge' to merge)
338 339 $ hg update
339 340 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
340 341 $ hg bookmarks
341 342 X2 1:925d80f479bb
342 343 Y 2:db815d6d32e6
343 344 * Z 3:125c9a1d6df6
344 345 x y 2:db815d6d32e6
345 346
346 347 test wrongly formated bookmark
347 348
348 349 $ echo '' >> .hg/bookmarks
349 350 $ hg bookmarks
350 351 X2 1:925d80f479bb
351 352 Y 2:db815d6d32e6
352 353 * Z 3:125c9a1d6df6
353 354 x y 2:db815d6d32e6
354 355 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
355 356 $ hg bookmarks
356 357 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
357 358 X2 1:925d80f479bb
358 359 Y 2:db815d6d32e6
359 360 * Z 3:125c9a1d6df6
360 361 x y 2:db815d6d32e6
361 362
@@ -1,126 +1,132 b''
1 1 test branch selection options
2 2
3 3 $ hg init branch
4 4 $ cd branch
5 5 $ hg branch a
6 6 marked working directory as branch a
7 (branches are permanent and global, did you want a bookmark?)
7 8 $ echo a > foo
8 9 $ hg ci -d '0 0' -Ama
9 10 adding foo
10 11 $ echo a2 > foo
11 12 $ hg ci -d '0 0' -ma2
12 13 $ hg up 0
13 14 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
14 15 $ hg branch c
15 16 marked working directory as branch c
17 (branches are permanent and global, did you want a bookmark?)
16 18 $ echo c > foo
17 19 $ hg ci -d '0 0' -mc
18 20 $ hg tag -l z
19 21 $ cd ..
20 22 $ hg clone -r 0 branch branch2
21 23 adding changesets
22 24 adding manifests
23 25 adding file changes
24 26 added 1 changesets with 1 changes to 1 files
25 27 updating to branch a
26 28 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
27 29 $ cd branch2
28 30 $ hg up 0
29 31 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
30 32 $ hg branch b
31 33 marked working directory as branch b
34 (branches are permanent and global, did you want a bookmark?)
32 35 $ echo b > foo
33 36 $ hg ci -d '0 0' -mb
34 37 $ hg up 0
35 38 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
36 39 $ hg --encoding utf-8 branch æ
37 40 marked working directory as branch \xc3\xa6 (esc)
41 (branches are permanent and global, did you want a bookmark?)
38 42 $ echo ae1 > foo
39 43 $ hg ci -d '0 0' -mae1
40 44 $ hg up 0
41 45 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 46 $ hg --encoding utf-8 branch -f æ
43 47 marked working directory as branch \xc3\xa6 (esc)
48 (branches are permanent and global, did you want a bookmark?)
44 49 $ echo ae2 > foo
45 50 $ hg ci -d '0 0' -mae2
46 51 created new head
47 52 $ hg up 0
48 53 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 54 $ hg branch -f b
50 55 marked working directory as branch b
56 (branches are permanent and global, did you want a bookmark?)
51 57 $ echo b2 > foo
52 58 $ hg ci -d '0 0' -mb2
53 59 created new head
54 60
55 61 unknown branch and fallback
56 62
57 63 $ hg in -qbz
58 64 abort: unknown branch 'z'!
59 65 [255]
60 66 $ hg in -q ../branch#z
61 67 2:f25d57ab0566
62 68 $ hg out -qbz
63 69 abort: unknown branch 'z'!
64 70 [255]
65 71
66 72 in rev c branch a
67 73
68 74 $ hg in -qr c ../branch#a
69 75 1:dd6e60a716c6
70 76 2:f25d57ab0566
71 77 $ hg in -qr c -b a
72 78 1:dd6e60a716c6
73 79 2:f25d57ab0566
74 80
75 81 out branch .
76 82
77 83 $ hg out -q ../branch#.
78 84 1:b84708d77ab7
79 85 4:65511d0e2b55
80 86 $ hg out -q -b .
81 87 1:b84708d77ab7
82 88 4:65511d0e2b55
83 89
84 90 out branch . non-ascii
85 91
86 92 $ hg --encoding utf-8 up æ
87 93 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 94 $ hg --encoding latin1 out -q ../branch#.
89 95 2:df5a44224d4e
90 96 3:4f4a5125ca10
91 97 $ hg --encoding latin1 out -q -b .
92 98 2:df5a44224d4e
93 99 3:4f4a5125ca10
94 100
95 101 clone branch b
96 102
97 103 $ cd ..
98 104 $ hg clone branch2#b branch3
99 105 adding changesets
100 106 adding manifests
101 107 adding file changes
102 108 added 3 changesets with 3 changes to 1 files (+1 heads)
103 109 updating to branch b
104 110 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
105 111 $ hg -q -R branch3 heads b
106 112 2:65511d0e2b55
107 113 1:b84708d77ab7
108 114 $ hg -q -R branch3 parents
109 115 2:65511d0e2b55
110 116 $ rm -rf branch3
111 117
112 118 clone rev a branch b
113 119
114 120 $ hg clone -r a branch2#b branch3
115 121 adding changesets
116 122 adding manifests
117 123 adding file changes
118 124 added 3 changesets with 3 changes to 1 files (+1 heads)
119 125 updating to branch a
120 126 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 127 $ hg -q -R branch3 heads b
122 128 2:65511d0e2b55
123 129 1:b84708d77ab7
124 130 $ hg -q -R branch3 parents
125 131 0:5b65ba7c951d
126 132 $ rm -rf branch3
@@ -1,62 +1,63 b''
1 1 Initial setup.
2 2
3 3 $ hg init repo
4 4 $ cd repo
5 5 $ touch thefile
6 6 $ hg ci -A -m 'Initial commit.'
7 7 adding thefile
8 8
9 9 Create a tag.
10 10
11 11 $ hg tag branchortag
12 12
13 13 Create a branch with the same name as the tag.
14 14
15 15 $ hg branch branchortag
16 16 marked working directory as branch branchortag
17 (branches are permanent and global, did you want a bookmark?)
17 18 $ hg ci -m 'Create a branch with the same name as a tag.'
18 19
19 20 This is what we have:
20 21
21 22 $ hg log
22 23 changeset: 2:10519b3f489a
23 24 branch: branchortag
24 25 tag: tip
25 26 user: test
26 27 date: Thu Jan 01 00:00:00 1970 +0000
27 28 summary: Create a branch with the same name as a tag.
28 29
29 30 changeset: 1:2635c45ca99b
30 31 user: test
31 32 date: Thu Jan 01 00:00:00 1970 +0000
32 33 summary: Added tag branchortag for changeset f57387372b5d
33 34
34 35 changeset: 0:f57387372b5d
35 36 tag: branchortag
36 37 user: test
37 38 date: Thu Jan 01 00:00:00 1970 +0000
38 39 summary: Initial commit.
39 40
40 41 Update to the tag:
41 42
42 43 $ hg up 'tag(branchortag)'
43 44 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
44 45 $ hg parents
45 46 changeset: 0:f57387372b5d
46 47 tag: branchortag
47 48 user: test
48 49 date: Thu Jan 01 00:00:00 1970 +0000
49 50 summary: Initial commit.
50 51
51 52 Updating to the branch:
52 53
53 54 $ hg up 'branch(branchortag)'
54 55 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
55 56 $ hg parents
56 57 changeset: 2:10519b3f489a
57 58 branch: branchortag
58 59 tag: tip
59 60 user: test
60 61 date: Thu Jan 01 00:00:00 1970 +0000
61 62 summary: Create a branch with the same name as a tag.
62 63
@@ -1,400 +1,405 b''
1 1 $ hg init a
2 2 $ cd a
3 3 $ echo 'root' >root
4 4 $ hg add root
5 5 $ hg commit -d '0 0' -m "Adding root node"
6 6
7 7 $ echo 'a' >a
8 8 $ hg add a
9 9 $ hg branch a
10 10 marked working directory as branch a
11 (branches are permanent and global, did you want a bookmark?)
11 12 $ hg commit -d '1 0' -m "Adding a branch"
12 13
13 14 $ hg branch q
14 15 marked working directory as branch q
16 (branches are permanent and global, did you want a bookmark?)
15 17 $ echo 'aa' >a
16 18 $ hg branch -C
17 19 reset working directory to branch a
18 20 $ hg commit -d '2 0' -m "Adding to a branch"
19 21
20 22 $ hg update -C 0
21 23 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
22 24 $ echo 'b' >b
23 25 $ hg add b
24 26 $ hg branch b
25 27 marked working directory as branch b
28 (branches are permanent and global, did you want a bookmark?)
26 29 $ hg commit -d '2 0' -m "Adding b branch"
27 30
28 31 $ echo 'bh1' >bh1
29 32 $ hg add bh1
30 33 $ hg commit -d '3 0' -m "Adding b branch head 1"
31 34
32 35 $ hg update -C 2
33 36 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
34 37 $ echo 'bh2' >bh2
35 38 $ hg add bh2
36 39 $ hg commit -d '4 0' -m "Adding b branch head 2"
37 40
38 41 $ echo 'c' >c
39 42 $ hg add c
40 43 $ hg branch c
41 44 marked working directory as branch c
45 (branches are permanent and global, did you want a bookmark?)
42 46 $ hg commit -d '5 0' -m "Adding c branch"
43 47
44 48 $ hg branch tip
45 49 abort: the name 'tip' is reserved
46 50 [255]
47 51 $ hg branch null
48 52 abort: the name 'null' is reserved
49 53 [255]
50 54 $ hg branch .
51 55 abort: the name '.' is reserved
52 56 [255]
53 57
54 58 $ echo 'd' >d
55 59 $ hg add d
56 60 $ hg branch 'a branch name much longer than the default justification used by branches'
57 61 marked working directory as branch a branch name much longer than the default justification used by branches
62 (branches are permanent and global, did you want a bookmark?)
58 63 $ hg commit -d '6 0' -m "Adding d branch"
59 64
60 65 $ hg branches
61 66 a branch name much longer than the default justification used by branches 7:10ff5895aa57
62 67 b 4:aee39cd168d0
63 68 c 6:589736a22561 (inactive)
64 69 a 5:d8cbc61dbaa6 (inactive)
65 70 default 0:19709c5a4e75 (inactive)
66 71
67 72 -------
68 73
69 74 $ hg branches -a
70 75 a branch name much longer than the default justification used by branches 7:10ff5895aa57
71 76 b 4:aee39cd168d0
72 77
73 78 --- Branch a
74 79
75 80 $ hg log -b a
76 81 changeset: 5:d8cbc61dbaa6
77 82 branch: a
78 83 parent: 2:881fe2b92ad0
79 84 user: test
80 85 date: Thu Jan 01 00:00:04 1970 +0000
81 86 summary: Adding b branch head 2
82 87
83 88 changeset: 2:881fe2b92ad0
84 89 branch: a
85 90 user: test
86 91 date: Thu Jan 01 00:00:02 1970 +0000
87 92 summary: Adding to a branch
88 93
89 94 changeset: 1:dd6b440dd85a
90 95 branch: a
91 96 user: test
92 97 date: Thu Jan 01 00:00:01 1970 +0000
93 98 summary: Adding a branch
94 99
95 100
96 101 ---- Branch b
97 102
98 103 $ hg log -b b
99 104 changeset: 4:aee39cd168d0
100 105 branch: b
101 106 user: test
102 107 date: Thu Jan 01 00:00:03 1970 +0000
103 108 summary: Adding b branch head 1
104 109
105 110 changeset: 3:ac22033332d1
106 111 branch: b
107 112 parent: 0:19709c5a4e75
108 113 user: test
109 114 date: Thu Jan 01 00:00:02 1970 +0000
110 115 summary: Adding b branch
111 116
112 117
113 118 ---- going to test branch closing
114 119
115 120 $ hg branches
116 121 a branch name much longer than the default justification used by branches 7:10ff5895aa57
117 122 b 4:aee39cd168d0
118 123 c 6:589736a22561 (inactive)
119 124 a 5:d8cbc61dbaa6 (inactive)
120 125 default 0:19709c5a4e75 (inactive)
121 126 $ hg up -C b
122 127 2 files updated, 0 files merged, 4 files removed, 0 files unresolved
123 128 $ echo 'xxx1' >> b
124 129 $ hg commit -d '7 0' -m 'adding cset to branch b'
125 130 $ hg up -C aee39cd168d0
126 131 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
127 132 $ echo 'xxx2' >> b
128 133 $ hg commit -d '8 0' -m 'adding head to branch b'
129 134 created new head
130 135 $ echo 'xxx3' >> b
131 136 $ hg commit -d '9 0' -m 'adding another cset to branch b'
132 137 $ hg branches
133 138 b 10:bfbe841b666e
134 139 a branch name much longer than the default justification used by branches 7:10ff5895aa57
135 140 c 6:589736a22561 (inactive)
136 141 a 5:d8cbc61dbaa6 (inactive)
137 142 default 0:19709c5a4e75 (inactive)
138 143 $ hg heads --closed
139 144 changeset: 10:bfbe841b666e
140 145 branch: b
141 146 tag: tip
142 147 user: test
143 148 date: Thu Jan 01 00:00:09 1970 +0000
144 149 summary: adding another cset to branch b
145 150
146 151 changeset: 8:eebb944467c9
147 152 branch: b
148 153 parent: 4:aee39cd168d0
149 154 user: test
150 155 date: Thu Jan 01 00:00:07 1970 +0000
151 156 summary: adding cset to branch b
152 157
153 158 changeset: 7:10ff5895aa57
154 159 branch: a branch name much longer than the default justification used by branches
155 160 user: test
156 161 date: Thu Jan 01 00:00:06 1970 +0000
157 162 summary: Adding d branch
158 163
159 164 changeset: 6:589736a22561
160 165 branch: c
161 166 user: test
162 167 date: Thu Jan 01 00:00:05 1970 +0000
163 168 summary: Adding c branch
164 169
165 170 changeset: 5:d8cbc61dbaa6
166 171 branch: a
167 172 parent: 2:881fe2b92ad0
168 173 user: test
169 174 date: Thu Jan 01 00:00:04 1970 +0000
170 175 summary: Adding b branch head 2
171 176
172 177 changeset: 0:19709c5a4e75
173 178 user: test
174 179 date: Thu Jan 01 00:00:00 1970 +0000
175 180 summary: Adding root node
176 181
177 182 $ hg heads
178 183 changeset: 10:bfbe841b666e
179 184 branch: b
180 185 tag: tip
181 186 user: test
182 187 date: Thu Jan 01 00:00:09 1970 +0000
183 188 summary: adding another cset to branch b
184 189
185 190 changeset: 8:eebb944467c9
186 191 branch: b
187 192 parent: 4:aee39cd168d0
188 193 user: test
189 194 date: Thu Jan 01 00:00:07 1970 +0000
190 195 summary: adding cset to branch b
191 196
192 197 changeset: 7:10ff5895aa57
193 198 branch: a branch name much longer than the default justification used by branches
194 199 user: test
195 200 date: Thu Jan 01 00:00:06 1970 +0000
196 201 summary: Adding d branch
197 202
198 203 changeset: 6:589736a22561
199 204 branch: c
200 205 user: test
201 206 date: Thu Jan 01 00:00:05 1970 +0000
202 207 summary: Adding c branch
203 208
204 209 changeset: 5:d8cbc61dbaa6
205 210 branch: a
206 211 parent: 2:881fe2b92ad0
207 212 user: test
208 213 date: Thu Jan 01 00:00:04 1970 +0000
209 214 summary: Adding b branch head 2
210 215
211 216 changeset: 0:19709c5a4e75
212 217 user: test
213 218 date: Thu Jan 01 00:00:00 1970 +0000
214 219 summary: Adding root node
215 220
216 221 $ hg commit -d '9 0' --close-branch -m 'prune bad branch'
217 222 $ hg branches -a
218 223 b 8:eebb944467c9
219 224 a branch name much longer than the default justification used by branches 7:10ff5895aa57
220 225 $ hg up -C b
221 226 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
222 227 $ hg commit -d '9 0' --close-branch -m 'close this part branch too'
223 228
224 229 --- b branch should be inactive
225 230
226 231 $ hg branches
227 232 a branch name much longer than the default justification used by branches 7:10ff5895aa57
228 233 c 6:589736a22561 (inactive)
229 234 a 5:d8cbc61dbaa6 (inactive)
230 235 default 0:19709c5a4e75 (inactive)
231 236 $ hg branches -c
232 237 a branch name much longer than the default justification used by branches 7:10ff5895aa57
233 238 b 12:e3d49c0575d8 (closed)
234 239 c 6:589736a22561 (inactive)
235 240 a 5:d8cbc61dbaa6 (inactive)
236 241 default 0:19709c5a4e75 (inactive)
237 242 $ hg branches -a
238 243 a branch name much longer than the default justification used by branches 7:10ff5895aa57
239 244 $ hg heads b
240 245 no open branch heads found on branches b
241 246 [1]
242 247 $ hg heads --closed b
243 248 changeset: 12:e3d49c0575d8
244 249 branch: b
245 250 tag: tip
246 251 parent: 8:eebb944467c9
247 252 user: test
248 253 date: Thu Jan 01 00:00:09 1970 +0000
249 254 summary: close this part branch too
250 255
251 256 changeset: 11:d3f163457ebf
252 257 branch: b
253 258 user: test
254 259 date: Thu Jan 01 00:00:09 1970 +0000
255 260 summary: prune bad branch
256 261
257 262 $ echo 'xxx4' >> b
258 263 $ hg commit -d '9 0' -m 'reopen branch with a change'
259 264 reopening closed branch head 12
260 265
261 266 --- branch b is back in action
262 267
263 268 $ hg branches -a
264 269 b 13:e23b5505d1ad
265 270 a branch name much longer than the default justification used by branches 7:10ff5895aa57
266 271
267 272 ---- test heads listings
268 273
269 274 $ hg heads
270 275 changeset: 13:e23b5505d1ad
271 276 branch: b
272 277 tag: tip
273 278 user: test
274 279 date: Thu Jan 01 00:00:09 1970 +0000
275 280 summary: reopen branch with a change
276 281
277 282 changeset: 7:10ff5895aa57
278 283 branch: a branch name much longer than the default justification used by branches
279 284 user: test
280 285 date: Thu Jan 01 00:00:06 1970 +0000
281 286 summary: Adding d branch
282 287
283 288 changeset: 6:589736a22561
284 289 branch: c
285 290 user: test
286 291 date: Thu Jan 01 00:00:05 1970 +0000
287 292 summary: Adding c branch
288 293
289 294 changeset: 5:d8cbc61dbaa6
290 295 branch: a
291 296 parent: 2:881fe2b92ad0
292 297 user: test
293 298 date: Thu Jan 01 00:00:04 1970 +0000
294 299 summary: Adding b branch head 2
295 300
296 301 changeset: 0:19709c5a4e75
297 302 user: test
298 303 date: Thu Jan 01 00:00:00 1970 +0000
299 304 summary: Adding root node
300 305
301 306
302 307 branch default
303 308
304 309 $ hg heads default
305 310 changeset: 0:19709c5a4e75
306 311 user: test
307 312 date: Thu Jan 01 00:00:00 1970 +0000
308 313 summary: Adding root node
309 314
310 315
311 316 branch a
312 317
313 318 $ hg heads a
314 319 changeset: 5:d8cbc61dbaa6
315 320 branch: a
316 321 parent: 2:881fe2b92ad0
317 322 user: test
318 323 date: Thu Jan 01 00:00:04 1970 +0000
319 324 summary: Adding b branch head 2
320 325
321 326 $ hg heads --active a
322 327 no open branch heads found on branches a
323 328 [1]
324 329
325 330 branch b
326 331
327 332 $ hg heads b
328 333 changeset: 13:e23b5505d1ad
329 334 branch: b
330 335 tag: tip
331 336 user: test
332 337 date: Thu Jan 01 00:00:09 1970 +0000
333 338 summary: reopen branch with a change
334 339
335 340 $ hg heads --closed b
336 341 changeset: 13:e23b5505d1ad
337 342 branch: b
338 343 tag: tip
339 344 user: test
340 345 date: Thu Jan 01 00:00:09 1970 +0000
341 346 summary: reopen branch with a change
342 347
343 348 changeset: 11:d3f163457ebf
344 349 branch: b
345 350 user: test
346 351 date: Thu Jan 01 00:00:09 1970 +0000
347 352 summary: prune bad branch
348 353
349 354 default branch colors:
350 355
351 356 $ echo "[extensions]" >> $HGRCPATH
352 357 $ echo "color =" >> $HGRCPATH
353 358 $ echo "[color]" >> $HGRCPATH
354 359 $ echo "mode = ansi" >> $HGRCPATH
355 360
356 361 $ hg up -C c
357 362 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
358 363 $ hg commit -d '9 0' --close-branch -m 'reclosing this branch'
359 364 $ hg up -C b
360 365 2 files updated, 0 files merged, 3 files removed, 0 files unresolved
361 366 $ hg branches --color=always
362 367 \x1b[0;32mb\x1b[0m \x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
363 368 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;33m7:10ff5895aa57\x1b[0m (esc)
364 369 \x1b[0;0ma\x1b[0m \x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
365 370 \x1b[0;0mdefault\x1b[0m \x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
366 371
367 372 default closed branch color:
368 373
369 374 $ hg branches --color=always --closed
370 375 \x1b[0;32mb\x1b[0m \x1b[0;33m 13:e23b5505d1ad\x1b[0m (esc)
371 376 \x1b[0;0ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;33m7:10ff5895aa57\x1b[0m (esc)
372 377 \x1b[0;30;1mc\x1b[0m \x1b[0;33m 14:f894c25619d3\x1b[0m (closed) (esc)
373 378 \x1b[0;0ma\x1b[0m \x1b[0;33m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
374 379 \x1b[0;0mdefault\x1b[0m \x1b[0;33m 0:19709c5a4e75\x1b[0m (inactive) (esc)
375 380
376 381 $ echo "[extensions]" >> $HGRCPATH
377 382 $ echo "color =" >> $HGRCPATH
378 383 $ echo "[color]" >> $HGRCPATH
379 384 $ echo "branches.active = green" >> $HGRCPATH
380 385 $ echo "branches.closed = blue" >> $HGRCPATH
381 386 $ echo "branches.current = red" >> $HGRCPATH
382 387 $ echo "branches.inactive = magenta" >> $HGRCPATH
383 388 $ echo "log.changeset = cyan" >> $HGRCPATH
384 389
385 390 custom branch colors:
386 391
387 392 $ hg branches --color=always
388 393 \x1b[0;31mb\x1b[0m \x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
389 394 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;36m7:10ff5895aa57\x1b[0m (esc)
390 395 \x1b[0;35ma\x1b[0m \x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
391 396 \x1b[0;35mdefault\x1b[0m \x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
392 397
393 398 custom closed branch color:
394 399
395 400 $ hg branches --color=always --closed
396 401 \x1b[0;31mb\x1b[0m \x1b[0;36m 13:e23b5505d1ad\x1b[0m (esc)
397 402 \x1b[0;32ma branch name much longer than the default justification used by branches\x1b[0m \x1b[0;36m7:10ff5895aa57\x1b[0m (esc)
398 403 \x1b[0;34mc\x1b[0m \x1b[0;36m 14:f894c25619d3\x1b[0m (closed) (esc)
399 404 \x1b[0;35ma\x1b[0m \x1b[0;36m 5:d8cbc61dbaa6\x1b[0m (inactive) (esc)
400 405 \x1b[0;35mdefault\x1b[0m \x1b[0;36m 0:19709c5a4e75\x1b[0m (inactive) (esc)
@@ -1,103 +1,105 b''
1 1 $ hg init
2 2 $ echo foo > bar
3 3 $ hg commit -Am default
4 4 adding bar
5 5 $ hg up -r null
6 6 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
7 7 $ hg branch mine
8 8 marked working directory as branch mine
9 (branches are permanent and global, did you want a bookmark?)
9 10 $ echo hello > world
10 11 $ hg commit -Am hello
11 12 adding world
12 13 $ hg up -r null
13 14 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
14 15 $ hg branch other
15 16 marked working directory as branch other
17 (branches are permanent and global, did you want a bookmark?)
16 18 $ echo good > bye
17 19 $ hg commit -Am other
18 20 adding bye
19 21 $ hg up -r mine
20 22 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
21 23
22 24 $ hg clone -U -u . .#other ../b -r 0 -r 1 -r 2 -b other
23 25 abort: cannot specify both --noupdate and --updaterev
24 26 [255]
25 27
26 28 $ hg clone -U .#other ../b -r 0 -r 1 -r 2 -b other
27 29 adding changesets
28 30 adding manifests
29 31 adding file changes
30 32 added 3 changesets with 3 changes to 3 files (+2 heads)
31 33 $ rm -rf ../b
32 34
33 35 $ hg clone -u . .#other ../b -r 0 -r 1 -r 2 -b other
34 36 adding changesets
35 37 adding manifests
36 38 adding file changes
37 39 added 3 changesets with 3 changes to 3 files (+2 heads)
38 40 updating to branch mine
39 41 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
40 42 $ rm -rf ../b
41 43
42 44 $ hg clone -u 0 .#other ../b -r 0 -r 1 -r 2 -b other
43 45 adding changesets
44 46 adding manifests
45 47 adding file changes
46 48 added 3 changesets with 3 changes to 3 files (+2 heads)
47 49 updating to branch default
48 50 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
49 51 $ rm -rf ../b
50 52
51 53 $ hg clone -u 1 .#other ../b -r 0 -r 1 -r 2 -b other
52 54 adding changesets
53 55 adding manifests
54 56 adding file changes
55 57 added 3 changesets with 3 changes to 3 files (+2 heads)
56 58 updating to branch mine
57 59 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
58 60 $ rm -rf ../b
59 61
60 62 $ hg clone -u 2 .#other ../b -r 0 -r 1 -r 2 -b other
61 63 adding changesets
62 64 adding manifests
63 65 adding file changes
64 66 added 3 changesets with 3 changes to 3 files (+2 heads)
65 67 updating to branch other
66 68 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 69 $ rm -rf ../b
68 70
69 71 Test -r mine ... mine is ignored:
70 72
71 73 $ hg clone -u 2 .#other ../b -r mine -r 0 -r 1 -r 2 -b other
72 74 adding changesets
73 75 adding manifests
74 76 adding file changes
75 77 added 3 changesets with 3 changes to 3 files (+2 heads)
76 78 updating to branch other
77 79 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
78 80 $ rm -rf ../b
79 81
80 82 $ hg clone .#other ../b -b default -b mine
81 83 adding changesets
82 84 adding manifests
83 85 adding file changes
84 86 added 3 changesets with 3 changes to 3 files (+2 heads)
85 87 updating to branch default
86 88 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 89 $ rm -rf ../b
88 90
89 91 $ hg clone .#other ../b
90 92 adding changesets
91 93 adding manifests
92 94 adding file changes
93 95 added 1 changesets with 1 changes to 1 files
94 96 updating to branch other
95 97 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
96 98 $ rm -rf ../b
97 99
98 100 $ hg clone -U . ../c -r 1 -r 2 > /dev/null
99 101 $ hg clone ../c ../b
100 102 updating to branch other
101 103 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
102 104 $ rm -rf ../b ../c
103 105
@@ -1,459 +1,460 b''
1 1 Prepare repo a:
2 2
3 3 $ hg init a
4 4 $ cd a
5 5 $ echo a > a
6 6 $ hg add a
7 7 $ hg commit -m test
8 8 $ echo first line > b
9 9 $ hg add b
10 10
11 11 Create a non-inlined filelog:
12 12
13 13 $ python -c 'file("data1", "wb").write("".join("%s\n" % x for x in range(10000)))'
14 14 $ for j in 0 1 2 3 4 5 6 7 8 9; do
15 15 > cat data1 >> b
16 16 > hg commit -m test
17 17 > done
18 18
19 19 List files in store/data (should show a 'b.d'):
20 20
21 21 $ for i in .hg/store/data/*; do
22 22 > echo $i
23 23 > done
24 24 .hg/store/data/a.i
25 25 .hg/store/data/b.d
26 26 .hg/store/data/b.i
27 27
28 28 Default operation:
29 29
30 30 $ hg clone . ../b
31 31 updating to branch default
32 32 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
33 33 $ cd ../b
34 34 $ cat a
35 35 a
36 36 $ hg verify
37 37 checking changesets
38 38 checking manifests
39 39 crosschecking files in changesets and manifests
40 40 checking files
41 41 2 files, 11 changesets, 11 total revisions
42 42
43 43 Invalid dest '' must abort:
44 44
45 45 $ hg clone . ''
46 46 abort: * (glob)
47 47 [255]
48 48
49 49 No update, with debug option:
50 50
51 51 $ hg --debug clone -U . ../c
52 52 linked 8 files
53 53 $ cd ../c
54 54 $ cat a 2>/dev/null || echo "a not present"
55 55 a not present
56 56 $ hg verify
57 57 checking changesets
58 58 checking manifests
59 59 crosschecking files in changesets and manifests
60 60 checking files
61 61 2 files, 11 changesets, 11 total revisions
62 62
63 63 Default destination:
64 64
65 65 $ mkdir ../d
66 66 $ cd ../d
67 67 $ hg clone ../a
68 68 destination directory: a
69 69 updating to branch default
70 70 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
71 71 $ cd a
72 72 $ hg cat a
73 73 a
74 74 $ cd ../..
75 75
76 76 Check that we drop the 'file:' from the path before writing the .hgrc:
77 77
78 78 $ hg clone file:a e
79 79 updating to branch default
80 80 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
81 81 $ grep 'file:' e/.hg/hgrc
82 82 [1]
83 83
84 84 Check that path aliases are expanded:
85 85
86 86 $ hg clone -q -U --config 'paths.foobar=a#0' foobar f
87 87 $ hg -R f showconfig paths.default
88 88 $TESTTMP/a#0 (glob)
89 89
90 90 Use --pull:
91 91
92 92 $ hg clone --pull a g
93 93 requesting all changes
94 94 adding changesets
95 95 adding manifests
96 96 adding file changes
97 97 added 11 changesets with 11 changes to 2 files
98 98 updating to branch default
99 99 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 100 $ hg -R g verify
101 101 checking changesets
102 102 checking manifests
103 103 crosschecking files in changesets and manifests
104 104 checking files
105 105 2 files, 11 changesets, 11 total revisions
106 106
107 107 Invalid dest '' with --pull must abort (issue2528):
108 108
109 109 $ hg clone --pull a ''
110 110 abort: * (glob)
111 111 [255]
112 112
113 113 Clone to '.':
114 114
115 115 $ mkdir h
116 116 $ cd h
117 117 $ hg clone ../a .
118 118 updating to branch default
119 119 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
120 120 $ cd ..
121 121
122 122
123 123 *** Tests for option -u ***
124 124
125 125 Adding some more history to repo a:
126 126
127 127 $ cd a
128 128 $ hg tag ref1
129 129 $ echo the quick brown fox >a
130 130 $ hg ci -m "hacked default"
131 131 $ hg up ref1
132 132 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
133 133 $ hg branch stable
134 134 marked working directory as branch stable
135 (branches are permanent and global, did you want a bookmark?)
135 136 $ echo some text >a
136 137 $ hg ci -m "starting branch stable"
137 138 $ hg tag ref2
138 139 $ echo some more text >a
139 140 $ hg ci -m "another change for branch stable"
140 141 $ hg up ref2
141 142 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
142 143 $ hg parents
143 144 changeset: 13:e8ece76546a6
144 145 branch: stable
145 146 tag: ref2
146 147 parent: 10:a7949464abda
147 148 user: test
148 149 date: Thu Jan 01 00:00:00 1970 +0000
149 150 summary: starting branch stable
150 151
151 152
152 153 Repo a has two heads:
153 154
154 155 $ hg heads
155 156 changeset: 15:0aae7cf88f0d
156 157 branch: stable
157 158 tag: tip
158 159 user: test
159 160 date: Thu Jan 01 00:00:00 1970 +0000
160 161 summary: another change for branch stable
161 162
162 163 changeset: 12:f21241060d6a
163 164 user: test
164 165 date: Thu Jan 01 00:00:00 1970 +0000
165 166 summary: hacked default
166 167
167 168
168 169 $ cd ..
169 170
170 171
171 172 Testing --noupdate with --updaterev (must abort):
172 173
173 174 $ hg clone --noupdate --updaterev 1 a ua
174 175 abort: cannot specify both --noupdate and --updaterev
175 176 [255]
176 177
177 178
178 179 Testing clone -u:
179 180
180 181 $ hg clone -u . a ua
181 182 updating to branch stable
182 183 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
183 184
184 185 Repo ua has both heads:
185 186
186 187 $ hg -R ua heads
187 188 changeset: 15:0aae7cf88f0d
188 189 branch: stable
189 190 tag: tip
190 191 user: test
191 192 date: Thu Jan 01 00:00:00 1970 +0000
192 193 summary: another change for branch stable
193 194
194 195 changeset: 12:f21241060d6a
195 196 user: test
196 197 date: Thu Jan 01 00:00:00 1970 +0000
197 198 summary: hacked default
198 199
199 200
200 201 Same revision checked out in repo a and ua:
201 202
202 203 $ hg -R a parents --template "{node|short}\n"
203 204 e8ece76546a6
204 205 $ hg -R ua parents --template "{node|short}\n"
205 206 e8ece76546a6
206 207
207 208 $ rm -r ua
208 209
209 210
210 211 Testing clone --pull -u:
211 212
212 213 $ hg clone --pull -u . a ua
213 214 requesting all changes
214 215 adding changesets
215 216 adding manifests
216 217 adding file changes
217 218 added 16 changesets with 16 changes to 3 files (+1 heads)
218 219 updating to branch stable
219 220 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 221
221 222 Repo ua has both heads:
222 223
223 224 $ hg -R ua heads
224 225 changeset: 15:0aae7cf88f0d
225 226 branch: stable
226 227 tag: tip
227 228 user: test
228 229 date: Thu Jan 01 00:00:00 1970 +0000
229 230 summary: another change for branch stable
230 231
231 232 changeset: 12:f21241060d6a
232 233 user: test
233 234 date: Thu Jan 01 00:00:00 1970 +0000
234 235 summary: hacked default
235 236
236 237
237 238 Same revision checked out in repo a and ua:
238 239
239 240 $ hg -R a parents --template "{node|short}\n"
240 241 e8ece76546a6
241 242 $ hg -R ua parents --template "{node|short}\n"
242 243 e8ece76546a6
243 244
244 245 $ rm -r ua
245 246
246 247
247 248 Testing clone -u <branch>:
248 249
249 250 $ hg clone -u stable a ua
250 251 updating to branch stable
251 252 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
252 253
253 254 Repo ua has both heads:
254 255
255 256 $ hg -R ua heads
256 257 changeset: 15:0aae7cf88f0d
257 258 branch: stable
258 259 tag: tip
259 260 user: test
260 261 date: Thu Jan 01 00:00:00 1970 +0000
261 262 summary: another change for branch stable
262 263
263 264 changeset: 12:f21241060d6a
264 265 user: test
265 266 date: Thu Jan 01 00:00:00 1970 +0000
266 267 summary: hacked default
267 268
268 269
269 270 Branch 'stable' is checked out:
270 271
271 272 $ hg -R ua parents
272 273 changeset: 15:0aae7cf88f0d
273 274 branch: stable
274 275 tag: tip
275 276 user: test
276 277 date: Thu Jan 01 00:00:00 1970 +0000
277 278 summary: another change for branch stable
278 279
279 280
280 281 $ rm -r ua
281 282
282 283
283 284 Testing default checkout:
284 285
285 286 $ hg clone a ua
286 287 updating to branch default
287 288 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
288 289
289 290 Repo ua has both heads:
290 291
291 292 $ hg -R ua heads
292 293 changeset: 15:0aae7cf88f0d
293 294 branch: stable
294 295 tag: tip
295 296 user: test
296 297 date: Thu Jan 01 00:00:00 1970 +0000
297 298 summary: another change for branch stable
298 299
299 300 changeset: 12:f21241060d6a
300 301 user: test
301 302 date: Thu Jan 01 00:00:00 1970 +0000
302 303 summary: hacked default
303 304
304 305
305 306 Branch 'default' is checked out:
306 307
307 308 $ hg -R ua parents
308 309 changeset: 12:f21241060d6a
309 310 user: test
310 311 date: Thu Jan 01 00:00:00 1970 +0000
311 312 summary: hacked default
312 313
313 314
314 315 $ rm -r ua
315 316
316 317
317 318 Testing #<branch>:
318 319
319 320 $ hg clone -u . a#stable ua
320 321 adding changesets
321 322 adding manifests
322 323 adding file changes
323 324 added 14 changesets with 14 changes to 3 files
324 325 updating to branch stable
325 326 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
326 327
327 328 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
328 329
329 330 $ hg -R ua heads
330 331 changeset: 13:0aae7cf88f0d
331 332 branch: stable
332 333 tag: tip
333 334 user: test
334 335 date: Thu Jan 01 00:00:00 1970 +0000
335 336 summary: another change for branch stable
336 337
337 338 changeset: 10:a7949464abda
338 339 user: test
339 340 date: Thu Jan 01 00:00:00 1970 +0000
340 341 summary: test
341 342
342 343
343 344 Same revision checked out in repo a and ua:
344 345
345 346 $ hg -R a parents --template "{node|short}\n"
346 347 e8ece76546a6
347 348 $ hg -R ua parents --template "{node|short}\n"
348 349 e8ece76546a6
349 350
350 351 $ rm -r ua
351 352
352 353
353 354 Testing -u -r <branch>:
354 355
355 356 $ hg clone -u . -r stable a ua
356 357 adding changesets
357 358 adding manifests
358 359 adding file changes
359 360 added 14 changesets with 14 changes to 3 files
360 361 updating to branch stable
361 362 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
362 363
363 364 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
364 365
365 366 $ hg -R ua heads
366 367 changeset: 13:0aae7cf88f0d
367 368 branch: stable
368 369 tag: tip
369 370 user: test
370 371 date: Thu Jan 01 00:00:00 1970 +0000
371 372 summary: another change for branch stable
372 373
373 374 changeset: 10:a7949464abda
374 375 user: test
375 376 date: Thu Jan 01 00:00:00 1970 +0000
376 377 summary: test
377 378
378 379
379 380 Same revision checked out in repo a and ua:
380 381
381 382 $ hg -R a parents --template "{node|short}\n"
382 383 e8ece76546a6
383 384 $ hg -R ua parents --template "{node|short}\n"
384 385 e8ece76546a6
385 386
386 387 $ rm -r ua
387 388
388 389
389 390 Testing -r <branch>:
390 391
391 392 $ hg clone -r stable a ua
392 393 adding changesets
393 394 adding manifests
394 395 adding file changes
395 396 added 14 changesets with 14 changes to 3 files
396 397 updating to branch stable
397 398 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
398 399
399 400 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
400 401
401 402 $ hg -R ua heads
402 403 changeset: 13:0aae7cf88f0d
403 404 branch: stable
404 405 tag: tip
405 406 user: test
406 407 date: Thu Jan 01 00:00:00 1970 +0000
407 408 summary: another change for branch stable
408 409
409 410 changeset: 10:a7949464abda
410 411 user: test
411 412 date: Thu Jan 01 00:00:00 1970 +0000
412 413 summary: test
413 414
414 415
415 416 Branch 'stable' is checked out:
416 417
417 418 $ hg -R ua parents
418 419 changeset: 13:0aae7cf88f0d
419 420 branch: stable
420 421 tag: tip
421 422 user: test
422 423 date: Thu Jan 01 00:00:00 1970 +0000
423 424 summary: another change for branch stable
424 425
425 426
426 427 $ rm -r ua
427 428
428 429
429 430 Issue2267: Error in 1.6 hg.py: TypeError: 'NoneType' object is not
430 431 iterable in addbranchrevs()
431 432
432 433 $ cat <<EOF > simpleclone.py
433 434 > from mercurial import ui, hg
434 435 > myui = ui.ui()
435 436 > repo = hg.repository(myui, 'a')
436 437 > hg.clone(myui, {}, repo, dest="ua")
437 438 > EOF
438 439
439 440 $ python simpleclone.py
440 441 updating to branch default
441 442 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
442 443
443 444 $ rm -r ua
444 445
445 446 $ cat <<EOF > branchclone.py
446 447 > from mercurial import ui, hg
447 448 > myui = ui.ui()
448 449 > repo = hg.repository(myui, 'a')
449 450 > hg.clone(myui, {}, repo, dest="ua", branch=["stable",])
450 451 > EOF
451 452
452 453 $ python branchclone.py
453 454 adding changesets
454 455 adding manifests
455 456 adding file changes
456 457 added 14 changesets with 14 changes to 3 files
457 458 updating to branch stable
458 459 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
459 460 $ rm -r ua
@@ -1,129 +1,131 b''
1 1 # reproduce issue2264, issue2516
2 2
3 3 create test repo
4 4 $ cat <<EOF >> $HGRCPATH
5 5 > [extensions]
6 6 > transplant =
7 7 > graphlog =
8 8 > EOF
9 9 $ hg init repo
10 10 $ cd repo
11 11 $ template="{rev} {desc|firstline} [{branch}]\n"
12 12
13 13 # we need to start out with two changesets on the default branch
14 14 # in order to avoid the cute little optimization where transplant
15 15 # pulls rather than transplants
16 16 add initial changesets
17 17 $ echo feature1 > file1
18 18 $ hg ci -Am"feature 1"
19 19 adding file1
20 20 $ echo feature2 >> file2
21 21 $ hg ci -Am"feature 2"
22 22 adding file2
23 23
24 24 # The changes to 'bugfix' are enough to show the bug: in fact, with only
25 25 # those changes, it's a very noisy crash ("RuntimeError: nothing
26 26 # committed after transplant"). But if we modify a second file in the
27 27 # transplanted changesets, the bug is much more subtle: transplant
28 28 # silently drops the second change to 'bugfix' on the floor, and we only
29 29 # see it when we run 'hg status' after transplanting. Subtle data loss
30 30 # bugs are worse than crashes, so reproduce the subtle case here.
31 31 commit bug fixes on bug fix branch
32 32 $ hg branch fixes
33 33 marked working directory as branch fixes
34 (branches are permanent and global, did you want a bookmark?)
34 35 $ echo fix1 > bugfix
35 36 $ echo fix1 >> file1
36 37 $ hg ci -Am"fix 1"
37 38 adding bugfix
38 39 $ echo fix2 > bugfix
39 40 $ echo fix2 >> file1
40 41 $ hg ci -Am"fix 2"
41 42 $ hg glog --template="$template"
42 43 @ 3 fix 2 [fixes]
43 44 |
44 45 o 2 fix 1 [fixes]
45 46 |
46 47 o 1 feature 2 [default]
47 48 |
48 49 o 0 feature 1 [default]
49 50
50 51 transplant bug fixes onto release branch
51 52 $ hg update 0
52 53 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
53 54 $ hg branch release
54 55 marked working directory as branch release
56 (branches are permanent and global, did you want a bookmark?)
55 57 $ hg transplant 2 3
56 58 applying [0-9a-f]{12} (re)
57 59 [0-9a-f]{12} transplanted to [0-9a-f]{12} (re)
58 60 applying [0-9a-f]{12} (re)
59 61 [0-9a-f]{12} transplanted to [0-9a-f]{12} (re)
60 62 $ hg glog --template="$template"
61 63 @ 5 fix 2 [release]
62 64 |
63 65 o 4 fix 1 [release]
64 66 |
65 67 | o 3 fix 2 [fixes]
66 68 | |
67 69 | o 2 fix 1 [fixes]
68 70 | |
69 71 | o 1 feature 2 [default]
70 72 |/
71 73 o 0 feature 1 [default]
72 74
73 75 $ hg status
74 76 $ hg status --rev 0:4
75 77 M file1
76 78 A bugfix
77 79 $ hg status --rev 4:5
78 80 M bugfix
79 81 M file1
80 82
81 83 now test that we fixed the bug for all scripts/extensions
82 84 $ cat > $TESTTMP/committwice.py <<__EOF__
83 85 > from mercurial import ui, hg, match, node
84 86 > from time import sleep
85 87 >
86 88 > def replacebyte(fn, b):
87 89 > f = open(fn, "rb+")
88 90 > f.seek(0, 0)
89 91 > f.write(b)
90 92 > f.close()
91 93 >
92 94 > def printfiles(repo, rev):
93 95 > print "revision %s files: %s" % (rev, repo[rev].files())
94 96 >
95 97 > repo = hg.repository(ui.ui(), '.')
96 98 > assert len(repo) == 6, \
97 99 > "initial: len(repo): %d, expected: 6" % len(repo)
98 100 >
99 101 > replacebyte("bugfix", "u")
100 102 > sleep(2)
101 103 > try:
102 104 > print "PRE: len(repo): %d" % len(repo)
103 105 > wlock = repo.wlock()
104 106 > lock = repo.lock()
105 107 > replacebyte("file1", "x")
106 108 > repo.commit(text="x", user="test", date=(0, 0))
107 109 > replacebyte("file1", "y")
108 110 > repo.commit(text="y", user="test", date=(0, 0))
109 111 > print "POST: len(repo): %d" % len(repo)
110 112 > finally:
111 113 > lock.release()
112 114 > wlock.release()
113 115 > printfiles(repo, 6)
114 116 > printfiles(repo, 7)
115 117 > __EOF__
116 118 $ $PYTHON $TESTTMP/committwice.py
117 119 PRE: len(repo): 6
118 120 POST: len(repo): 8
119 121 revision 6 files: ['bugfix', 'file1']
120 122 revision 7 files: ['file1']
121 123
122 124 Do a size-preserving modification outside of that process
123 125 $ echo abcd > bugfix
124 126 $ hg status
125 127 M bugfix
126 128 $ hg log --template "{rev} {desc} {files}\n" -r5:
127 129 5 fix 2 bugfix file1
128 130 6 x bugfix file1
129 131 7 y file1
@@ -1,84 +1,88 b''
1 1
2 2 $ echo "[extensions]" >> $HGRCPATH
3 3 $ echo "convert = " >> $HGRCPATH
4 4 $ echo "[convert]" >> $HGRCPATH
5 5 $ echo "hg.tagsbranch=0" >> $HGRCPATH
6 6 $ hg init source
7 7 $ cd source
8 8 $ echo a > a
9 9 $ hg ci -qAm adda
10 10
11 11 Add a merge with one parent in the same branch
12 12
13 13 $ echo a >> a
14 14 $ hg ci -qAm changea
15 15 $ hg up -qC 0
16 16 $ hg branch branch0
17 17 marked working directory as branch branch0
18 (branches are permanent and global, did you want a bookmark?)
18 19 $ echo b > b
19 20 $ hg ci -qAm addb
20 21 $ hg up -qC
21 22 $ hg merge default
22 23 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
23 24 (branch merge, don't forget to commit)
24 25 $ hg ci -qm mergeab
25 26 $ hg tag -ql mergeab
26 27 $ cd ..
27 28
28 29 Miss perl... sometimes
29 30
30 31 $ cat > filter.py <<EOF
31 32 > import sys, re
32 33 >
33 34 > r = re.compile(r'^(?:\d+|pulling from)')
34 35 > sys.stdout.writelines([l for l in sys.stdin if r.search(l)])
35 36 > EOF
36 37
37 38 convert
38 39
39 40 $ hg convert -v --config convert.hg.clonebranches=1 source dest |
40 41 > python filter.py
41 42 3 adda
42 43 2 changea
43 44 1 addb
44 45 pulling from default into branch0
45 46 1 changesets found
46 47 0 mergeab
47 48 pulling from default into branch0
48 49 1 changesets found
49 50
50 51 Add a merge with both parents and child in different branches
51 52
52 53 $ cd source
53 54 $ hg branch branch1
54 55 marked working directory as branch branch1
56 (branches are permanent and global, did you want a bookmark?)
55 57 $ echo a > file1
56 58 $ hg ci -qAm c1
57 59 $ hg up -qC mergeab
58 60 $ hg branch branch2
59 61 marked working directory as branch branch2
62 (branches are permanent and global, did you want a bookmark?)
60 63 $ echo a > file2
61 64 $ hg ci -qAm c2
62 65 $ hg merge branch1
63 66 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
64 67 (branch merge, don't forget to commit)
65 68 $ hg branch branch3
66 69 marked working directory as branch branch3
70 (branches are permanent and global, did you want a bookmark?)
67 71 $ hg ci -qAm c3
68 72 $ cd ..
69 73
70 74 incremental conversion
71 75
72 76 $ hg convert -v --config convert.hg.clonebranches=1 source dest |
73 77 > python filter.py
74 78 2 c1
75 79 pulling from branch0 into branch1
76 80 4 changesets found
77 81 1 c2
78 82 pulling from branch0 into branch2
79 83 4 changesets found
80 84 0 c3
81 85 pulling from branch2 into branch3
82 86 5 changesets found
83 87 pulling from branch1 into branch3
84 88 1 changesets found
@@ -1,117 +1,119 b''
1 1
2 2 $ cat >> $HGRCPATH <<EOF
3 3 > [extensions]
4 4 > convert=
5 5 > graphlog=
6 6 > EOF
7 7 $ hg init t
8 8 $ cd t
9 9 $ echo a >> a
10 10 $ hg ci -Am a0 -d '1 0'
11 11 adding a
12 12 $ hg branch brancha
13 13 marked working directory as branch brancha
14 (branches are permanent and global, did you want a bookmark?)
14 15 $ echo a >> a
15 16 $ hg ci -m a1 -d '2 0'
16 17 $ echo a >> a
17 18 $ hg ci -m a2 -d '3 0'
18 19 $ echo a >> a
19 20 $ hg ci -m a3 -d '4 0'
20 21 $ hg up -C 0
21 22 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 23 $ hg branch branchb
23 24 marked working directory as branch branchb
25 (branches are permanent and global, did you want a bookmark?)
24 26 $ echo b >> b
25 27 $ hg ci -Am b0 -d '6 0'
26 28 adding b
27 29 $ hg up -C brancha
28 30 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
29 31 $ echo a >> a
30 32 $ hg ci -m a4 -d '5 0'
31 33 $ echo a >> a
32 34 $ hg ci -m a5 -d '7 0'
33 35 $ echo a >> a
34 36 $ hg ci -m a6 -d '8 0'
35 37 $ hg up -C branchb
36 38 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
37 39 $ echo b >> b
38 40 $ hg ci -m b1 -d '9 0'
39 41 $ cd ..
40 42
41 43 convert with datesort
42 44
43 45 $ hg convert --datesort t t-datesort
44 46 initializing destination t-datesort repository
45 47 scanning source...
46 48 sorting...
47 49 converting...
48 50 8 a0
49 51 7 a1
50 52 6 a2
51 53 5 a3
52 54 4 a4
53 55 3 b0
54 56 2 a5
55 57 1 a6
56 58 0 b1
57 59
58 60 graph converted repo
59 61
60 62 $ hg -R t-datesort glog --template '{rev} "{desc}"\n'
61 63 o 8 "b1"
62 64 |
63 65 | o 7 "a6"
64 66 | |
65 67 | o 6 "a5"
66 68 | |
67 69 o | 5 "b0"
68 70 | |
69 71 | o 4 "a4"
70 72 | |
71 73 | o 3 "a3"
72 74 | |
73 75 | o 2 "a2"
74 76 | |
75 77 | o 1 "a1"
76 78 |/
77 79 o 0 "a0"
78 80
79 81
80 82 convert with datesort (default mode)
81 83
82 84 $ hg convert t t-sourcesort
83 85 initializing destination t-sourcesort repository
84 86 scanning source...
85 87 sorting...
86 88 converting...
87 89 8 a0
88 90 7 a1
89 91 6 a2
90 92 5 a3
91 93 4 b0
92 94 3 a4
93 95 2 a5
94 96 1 a6
95 97 0 b1
96 98
97 99 graph converted repo
98 100
99 101 $ hg -R t-sourcesort glog --template '{rev} "{desc}"\n'
100 102 o 8 "b1"
101 103 |
102 104 | o 7 "a6"
103 105 | |
104 106 | o 6 "a5"
105 107 | |
106 108 | o 5 "a4"
107 109 | |
108 110 o | 4 "b0"
109 111 | |
110 112 | o 3 "a3"
111 113 | |
112 114 | o 2 "a2"
113 115 | |
114 116 | o 1 "a1"
115 117 |/
116 118 o 0 "a0"
117 119
@@ -1,374 +1,377 b''
1 1
2 2 $ HGMERGE=true; export HGMERGE
3 3 $ echo '[extensions]' >> $HGRCPATH
4 4 $ echo 'graphlog =' >> $HGRCPATH
5 5 $ echo 'convert =' >> $HGRCPATH
6 6 $ glog()
7 7 > {
8 8 > hg glog --template '{rev} "{desc}" files: {files}\n' "$@"
9 9 > }
10 10 $ hg init source
11 11 $ cd source
12 12 $ echo foo > foo
13 13 $ echo baz > baz
14 14 $ mkdir -p dir/subdir
15 15 $ echo dir/file >> dir/file
16 16 $ echo dir/file2 >> dir/file2
17 17 $ echo dir/file3 >> dir/file3 # to be corrupted in rev 0
18 18 $ echo dir/subdir/file3 >> dir/subdir/file3
19 19 $ echo dir/subdir/file4 >> dir/subdir/file4
20 20 $ hg ci -d '0 0' -qAm '0: add foo baz dir/'
21 21 $ echo bar > bar
22 22 $ echo quux > quux
23 23 $ echo dir/file4 >> dir/file4 # to be corrupted in rev 1
24 24 $ hg copy foo copied
25 25 $ hg ci -d '1 0' -qAm '1: add bar quux; copy foo to copied'
26 26 $ echo >> foo
27 27 $ hg ci -d '2 0' -m '2: change foo'
28 28 $ hg up -qC 1
29 29 $ echo >> bar
30 30 $ echo >> quux
31 31 $ hg ci -d '3 0' -m '3: change bar quux'
32 32 created new head
33 33 $ hg up -qC 2
34 34 $ hg merge -qr 3
35 35 $ echo >> bar
36 36 $ echo >> baz
37 37 $ hg ci -d '4 0' -m '4: first merge; change bar baz'
38 38 $ echo >> bar
39 39 $ echo 1 >> baz
40 40 $ echo >> quux
41 41 $ hg ci -d '5 0' -m '5: change bar baz quux'
42 42 $ hg up -qC 4
43 43 $ echo >> foo
44 44 $ echo 2 >> baz
45 45 $ hg ci -d '6 0' -m '6: change foo baz'
46 46 created new head
47 47 $ hg up -qC 5
48 48 $ hg merge -qr 6
49 49 $ echo >> bar
50 50 $ hg ci -d '7 0' -m '7: second merge; change bar'
51 51 $ echo >> foo
52 52 $ hg ci -m '8: change foo'
53 53 $ glog
54 54 @ 8 "8: change foo" files: foo
55 55 |
56 56 o 7 "7: second merge; change bar" files: bar baz
57 57 |\
58 58 | o 6 "6: change foo baz" files: baz foo
59 59 | |
60 60 o | 5 "5: change bar baz quux" files: bar baz quux
61 61 |/
62 62 o 4 "4: first merge; change bar baz" files: bar baz
63 63 |\
64 64 | o 3 "3: change bar quux" files: bar quux
65 65 | |
66 66 o | 2 "2: change foo" files: foo
67 67 |/
68 68 o 1 "1: add bar quux; copy foo to copied" files: bar copied dir/file4 quux
69 69 |
70 70 o 0 "0: add foo baz dir/" files: baz dir/file dir/file2 dir/file3 dir/subdir/file3 dir/subdir/file4 foo
71 71
72 72
73 73 final file versions in this repo:
74 74
75 75 $ hg manifest --debug
76 76 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
77 77 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
78 78 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
79 79 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir/file
80 80 75e6d3f8328f5f6ace6bf10b98df793416a09dca 644 dir/file2
81 81 e96dce0bc6a217656a3a410e5e6bec2c4f42bf7c 644 dir/file3
82 82 6edd55f559cdce67132b12ca09e09cee08b60442 644 dir/file4
83 83 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir/subdir/file3
84 84 57a1c1511590f3de52874adfa04effe8a77d64af 644 dir/subdir/file4
85 85 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
86 86 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
87 87 $ hg debugrename copied
88 88 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
89 89
90 90 $ cd ..
91 91 $ splitrepo()
92 92 > {
93 93 > msg="$1"
94 94 > files="$2"
95 95 > opts=$3
96 96 > echo "% $files: $msg"
97 97 > prefix=`echo "$files" | sed -e 's/ /-/g'`
98 98 > fmap="$prefix.fmap"
99 99 > repo="$prefix.repo"
100 100 > for i in $files; do
101 101 > echo "include $i" >> "$fmap"
102 102 > done
103 103 > hg -q convert $opts --filemap "$fmap" --datesort source "$repo"
104 104 > hg up -q -R "$repo"
105 105 > glog -R "$repo"
106 106 > hg -R "$repo" manifest --debug
107 107 > }
108 108 $ splitrepo 'skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd' foo
109 109 % foo: skip unwanted merges; use 1st parent in 1st merge, 2nd in 2nd
110 110 @ 3 "8: change foo" files: foo
111 111 |
112 112 o 2 "6: change foo baz" files: foo
113 113 |
114 114 o 1 "2: change foo" files: foo
115 115 |
116 116 o 0 "0: add foo baz dir/" files: foo
117 117
118 118 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
119 119 $ splitrepo 'merges are not merges anymore' bar
120 120 % bar: merges are not merges anymore
121 121 @ 4 "7: second merge; change bar" files: bar
122 122 |
123 123 o 3 "5: change bar baz quux" files: bar
124 124 |
125 125 o 2 "4: first merge; change bar baz" files: bar
126 126 |
127 127 o 1 "3: change bar quux" files: bar
128 128 |
129 129 o 0 "1: add bar quux; copy foo to copied" files: bar
130 130
131 131 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
132 132 $ splitrepo '1st merge is not a merge anymore; 2nd still is' baz
133 133 % baz: 1st merge is not a merge anymore; 2nd still is
134 134 @ 4 "7: second merge; change bar" files: baz
135 135 |\
136 136 | o 3 "6: change foo baz" files: baz
137 137 | |
138 138 o | 2 "5: change bar baz quux" files: baz
139 139 |/
140 140 o 1 "4: first merge; change bar baz" files: baz
141 141 |
142 142 o 0 "0: add foo baz dir/" files: baz
143 143
144 144 94c1be4dfde2ee8d78db8bbfcf81210813307c3d 644 baz
145 145 $ splitrepo 'we add additional merges when they are interesting' 'foo quux'
146 146 % foo quux: we add additional merges when they are interesting
147 147 @ 8 "8: change foo" files: foo
148 148 |
149 149 o 7 "7: second merge; change bar" files:
150 150 |\
151 151 | o 6 "6: change foo baz" files: foo
152 152 | |
153 153 o | 5 "5: change bar baz quux" files: quux
154 154 |/
155 155 o 4 "4: first merge; change bar baz" files:
156 156 |\
157 157 | o 3 "3: change bar quux" files: quux
158 158 | |
159 159 o | 2 "2: change foo" files: foo
160 160 |/
161 161 o 1 "1: add bar quux; copy foo to copied" files: quux
162 162 |
163 163 o 0 "0: add foo baz dir/" files: foo
164 164
165 165 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
166 166 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
167 167 $ splitrepo 'partial conversion' 'bar quux' '-r 3'
168 168 % bar quux: partial conversion
169 169 @ 1 "3: change bar quux" files: bar quux
170 170 |
171 171 o 0 "1: add bar quux; copy foo to copied" files: bar quux
172 172
173 173 b79105bedc55102f394e90a789c9c380117c1b4a 644 bar
174 174 db0421cc6b685a458c8d86c7d5c004f94429ea23 644 quux
175 175 $ splitrepo 'complete the partial conversion' 'bar quux'
176 176 % bar quux: complete the partial conversion
177 177 @ 4 "7: second merge; change bar" files: bar
178 178 |
179 179 o 3 "5: change bar baz quux" files: bar quux
180 180 |
181 181 o 2 "4: first merge; change bar baz" files: bar
182 182 |
183 183 o 1 "3: change bar quux" files: bar quux
184 184 |
185 185 o 0 "1: add bar quux; copy foo to copied" files: bar quux
186 186
187 187 9463f52fe115e377cf2878d4fc548117211063f2 644 bar
188 188 bc3eca3f47023a3e70ca0d8cc95a22a6827db19d 644 quux
189 189 $ rm -r foo.repo
190 190 $ splitrepo 'partial conversion' 'foo' '-r 3'
191 191 % foo: partial conversion
192 192 @ 0 "0: add foo baz dir/" files: foo
193 193
194 194 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 foo
195 195 $ splitrepo 'complete the partial conversion' 'foo'
196 196 % foo: complete the partial conversion
197 197 @ 3 "8: change foo" files: foo
198 198 |
199 199 o 2 "6: change foo baz" files: foo
200 200 |
201 201 o 1 "2: change foo" files: foo
202 202 |
203 203 o 0 "0: add foo baz dir/" files: foo
204 204
205 205 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
206 206 $ splitrepo 'copied file; source not included in new repo' copied
207 207 % copied: copied file; source not included in new repo
208 208 @ 0 "1: add bar quux; copy foo to copied" files: copied
209 209
210 210 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 copied
211 211 $ hg --cwd copied.repo debugrename copied
212 212 copied not renamed
213 213 $ splitrepo 'copied file; source included in new repo' 'foo copied'
214 214 % foo copied: copied file; source included in new repo
215 215 @ 4 "8: change foo" files: foo
216 216 |
217 217 o 3 "6: change foo baz" files: foo
218 218 |
219 219 o 2 "2: change foo" files: foo
220 220 |
221 221 o 1 "1: add bar quux; copy foo to copied" files: copied
222 222 |
223 223 o 0 "0: add foo baz dir/" files: foo
224 224
225 225 7711d36246cc83e61fb29cd6d4ef394c63f1ceaf 644 copied
226 226 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo
227 227 $ hg --cwd foo-copied.repo debugrename copied
228 228 copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
229 229 $ cat > renames.fmap <<EOF
230 230 > include dir
231 231 > exclude dir/file2
232 232 > rename dir dir2
233 233 > include foo
234 234 > include copied
235 235 > rename foo foo2
236 236 > rename copied copied2
237 237 > exclude dir/subdir
238 238 > include dir/subdir/file3
239 239 > EOF
240 240 $ rm source/.hg/store/data/dir/file3.i
241 241 $ rm source/.hg/store/data/dir/file4.i
242 242 $ hg -q convert --filemap renames.fmap --datesort source dummydest
243 243 abort: data/dir/file3.i@e96dce0bc6a2: no match found!
244 244 [255]
245 245 $ hg -q convert --filemap renames.fmap --datesort --config convert.hg.ignoreerrors=1 source renames.repo
246 246 ignoring: data/dir/file3.i@e96dce0bc6a2: no match found
247 247 ignoring: data/dir/file4.i@6edd55f559cd: no match found
248 248 $ hg up -q -R renames.repo
249 249 $ glog -R renames.repo
250 250 @ 4 "8: change foo" files: foo2
251 251 |
252 252 o 3 "6: change foo baz" files: foo2
253 253 |
254 254 o 2 "2: change foo" files: foo2
255 255 |
256 256 o 1 "1: add bar quux; copy foo to copied" files: copied2
257 257 |
258 258 o 0 "0: add foo baz dir/" files: dir2/file dir2/subdir/file3 foo2
259 259
260 260 $ hg -R renames.repo manifest --debug
261 261 d43feacba7a4f1f2080dde4a4b985bd8a0236d46 644 copied2
262 262 3e20847584beff41d7cd16136b7331ab3d754be0 644 dir2/file
263 263 5fe139720576e18e34bcc9f79174db8897c8afe9 644 dir2/subdir/file3
264 264 9a7b52012991e4873687192c3e17e61ba3e837a3 644 foo2
265 265 $ hg --cwd renames.repo debugrename copied2
266 266 copied2 renamed from foo2:2ed2a3912a0b24502043eae84ee4b279c18b90dd
267 267
268 268 copied:
269 269
270 270 $ hg --cwd source cat copied
271 271 foo
272 272
273 273 copied2:
274 274
275 275 $ hg --cwd renames.repo cat copied2
276 276 foo
277 277
278 278 filemap errors
279 279
280 280 $ cat > errors.fmap <<EOF
281 281 > include dir/ # beware that comments changes error line numbers!
282 282 > exclude /dir
283 283 > rename dir//dir /dir//dir/ "out of sync"
284 284 > include
285 285 > EOF
286 286 $ hg -q convert --filemap errors.fmap source errors.repo
287 287 errors.fmap:1: superfluous / in exclude 'dir/'
288 288 errors.fmap:3: superfluous / in include '/dir'
289 289 errors.fmap:3: superfluous / in rename '/dir'
290 290 errors.fmap:3: superfluous / in exclude 'dir//dir'
291 291 errors.fmap:4: unknown directive 'out of sync'
292 292 errors.fmap:5: path to exclude is missing
293 293 abort: errors in filemap
294 294 [255]
295 295
296 296 test branch closing revision pruning if branch is pruned
297 297
298 298 $ hg init branchpruning
299 299 $ cd branchpruning
300 300 $ hg branch foo
301 301 marked working directory as branch foo
302 (branches are permanent and global, did you want a bookmark?)
302 303 $ echo a > a
303 304 $ hg ci -Am adda
304 305 adding a
305 306 $ hg ci --close-branch -m closefoo
306 307 $ hg up 0
307 308 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
308 309 $ hg branch empty
309 310 marked working directory as branch empty
311 (branches are permanent and global, did you want a bookmark?)
310 312 $ hg ci -m emptybranch
311 313 $ hg ci --close-branch -m closeempty
312 314 $ hg up 0
313 315 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
314 316 $ hg branch default
315 317 marked working directory as branch default
318 (branches are permanent and global, did you want a bookmark?)
316 319 $ echo b > b
317 320 $ hg ci -Am addb
318 321 adding b
319 322 $ hg ci --close-branch -m closedefault
320 323 $ cat > filemap <<EOF
321 324 > include b
322 325 > EOF
323 326 $ cd ..
324 327 $ hg convert branchpruning branchpruning-hg1
325 328 initializing destination branchpruning-hg1 repository
326 329 scanning source...
327 330 sorting...
328 331 converting...
329 332 5 adda
330 333 4 closefoo
331 334 3 emptybranch
332 335 2 closeempty
333 336 1 addb
334 337 0 closedefault
335 338 $ glog -R branchpruning-hg1
336 339 o 5 "closedefault" files:
337 340 |
338 341 o 4 "addb" files: b
339 342 |
340 343 | o 3 "closeempty" files:
341 344 | |
342 345 | o 2 "emptybranch" files:
343 346 |/
344 347 | o 1 "closefoo" files:
345 348 |/
346 349 o 0 "adda" files: a
347 350
348 351
349 352 exercise incremental conversion at the same time
350 353
351 354 $ hg convert -r0 --filemap branchpruning/filemap branchpruning branchpruning-hg2
352 355 initializing destination branchpruning-hg2 repository
353 356 scanning source...
354 357 sorting...
355 358 converting...
356 359 0 adda
357 360 $ hg convert -r4 --filemap branchpruning/filemap branchpruning branchpruning-hg2
358 361 scanning source...
359 362 sorting...
360 363 converting...
361 364 0 addb
362 365 $ hg convert --filemap branchpruning/filemap branchpruning branchpruning-hg2
363 366 scanning source...
364 367 sorting...
365 368 converting...
366 369 3 closefoo
367 370 2 emptybranch
368 371 1 closeempty
369 372 0 closedefault
370 373 $ glog -R branchpruning-hg2
371 374 o 1 "closedefault" files:
372 375 |
373 376 o 0 "addb" files: b
374 377
@@ -1,140 +1,143 b''
1 1 Test alignment of multibyte characters
2 2
3 3 $ HGENCODING=utf-8
4 4 $ export HGENCODING
5 5 $ hg init t
6 6 $ cd t
7 7 $ python << EOF
8 8 > # (byte, width) = (6, 4)
9 9 > s = "\xe7\x9f\xad\xe5\x90\x8d"
10 10 > # (byte, width) = (7, 7): odd width is good for alignment test
11 11 > m = "MIDDLE_"
12 12 > # (byte, width) = (18, 12)
13 13 > l = "\xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d"
14 14 > f = file('s', 'w'); f.write(s); f.close()
15 15 > f = file('m', 'w'); f.write(m); f.close()
16 16 > f = file('l', 'w'); f.write(l); f.close()
17 17 > # instant extension to show list of options
18 18 > f = file('showoptlist.py', 'w'); f.write("""# encoding: utf-8
19 19 > def showoptlist(ui, repo, *pats, **opts):
20 20 > '''dummy command to show option descriptions'''
21 21 > return 0
22 22 > cmdtable = {
23 23 > 'showoptlist':
24 24 > (showoptlist,
25 25 > [('s', 'opt1', '', 'short width' + ' %(s)s' * 8, '%(s)s'),
26 26 > ('m', 'opt2', '', 'middle width' + ' %(m)s' * 8, '%(m)s'),
27 27 > ('l', 'opt3', '', 'long width' + ' %(l)s' * 8, '%(l)s')
28 28 > ],
29 29 > ""
30 30 > )
31 31 > }
32 32 > """ % globals())
33 33 > f.close()
34 34 > EOF
35 35 $ S=`cat s`
36 36 $ M=`cat m`
37 37 $ L=`cat l`
38 38
39 39 alignment of option descriptions in help
40 40
41 41 $ cat <<EOF > .hg/hgrc
42 42 > [extensions]
43 43 > ja_ext = `pwd`/showoptlist.py
44 44 > EOF
45 45
46 46 check alignment of option descriptions in help
47 47
48 48 $ hg help showoptlist
49 49 hg showoptlist
50 50
51 51 dummy command to show option descriptions
52 52
53 53 options:
54 54
55 55 -s --opt1 \xe7\x9f\xad\xe5\x90\x8d short width \xe7\x9f\xad\xe5\x90\x8d \xe7\x9f\xad\xe5\x90\x8d \xe7\x9f\xad\xe5\x90\x8d \xe7\x9f\xad\xe5\x90\x8d \xe7\x9f\xad\xe5\x90\x8d \xe7\x9f\xad\xe5\x90\x8d \xe7\x9f\xad\xe5\x90\x8d \xe7\x9f\xad\xe5\x90\x8d (esc)
56 56 -m --opt2 MIDDLE_ middle width MIDDLE_ MIDDLE_ MIDDLE_ MIDDLE_ MIDDLE_
57 57 MIDDLE_ MIDDLE_ MIDDLE_
58 58 -l --opt3 \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d long width \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d (esc)
59 59 \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d (esc)
60 60 \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d (esc)
61 61
62 62 use "hg -v help showoptlist" to show more info
63 63
64 64
65 65 $ rm -f s; touch s
66 66 $ rm -f m; touch m
67 67 $ rm -f l; touch l
68 68
69 69 add files
70 70
71 71 $ cp s $S
72 72 $ hg add $S
73 73 $ cp m $M
74 74 $ hg add $M
75 75 $ cp l $L
76 76 $ hg add $L
77 77
78 78 commit(1)
79 79
80 80 $ echo 'first line(1)' >> s; cp s $S
81 81 $ echo 'first line(2)' >> m; cp m $M
82 82 $ echo 'first line(3)' >> l; cp l $L
83 83 $ hg commit -m 'first commit' -u $S
84 84
85 85 commit(2)
86 86
87 87 $ echo 'second line(1)' >> s; cp s $S
88 88 $ echo 'second line(2)' >> m; cp m $M
89 89 $ echo 'second line(3)' >> l; cp l $L
90 90 $ hg commit -m 'second commit' -u $M
91 91
92 92 commit(3)
93 93
94 94 $ echo 'third line(1)' >> s; cp s $S
95 95 $ echo 'third line(2)' >> m; cp m $M
96 96 $ echo 'third line(3)' >> l; cp l $L
97 97 $ hg commit -m 'third commit' -u $L
98 98
99 99 check alignment of user names in annotate
100 100
101 101 $ hg annotate -u $M
102 102 \xe7\x9f\xad\xe5\x90\x8d: first line(2) (esc)
103 103 MIDDLE_: second line(2)
104 104 \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d: third line(2) (esc)
105 105
106 106 check alignment of filenames in diffstat
107 107
108 108 $ hg diff -c tip --stat
109 109 MIDDLE_ | 1 +
110 110 \xe7\x9f\xad\xe5\x90\x8d | 1 + (esc)
111 111 \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d | 1 + (esc)
112 112 3 files changed, 3 insertions(+), 0 deletions(-)
113 113
114 114 add branches/tags
115 115
116 116 $ hg branch $S
117 117 marked working directory as branch \xe7\x9f\xad\xe5\x90\x8d (esc)
118 (branches are permanent and global, did you want a bookmark?)
118 119 $ hg tag $S
119 120 $ hg branch $M
120 121 marked working directory as branch MIDDLE_
122 (branches are permanent and global, did you want a bookmark?)
121 123 $ hg tag $M
122 124 $ hg branch $L
123 125 marked working directory as branch \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d (esc)
126 (branches are permanent and global, did you want a bookmark?)
124 127 $ hg tag $L
125 128
126 129 check alignment of branches
127 130
128 131 $ hg tags
129 132 tip 5:d745ff46155b
130 133 \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d 4:9259be597f19 (esc)
131 134 MIDDLE_ 3:b06c5b6def9e
132 135 \xe7\x9f\xad\xe5\x90\x8d 2:64a70663cee8 (esc)
133 136
134 137 check alignment of tags
135 138
136 139 $ hg tags
137 140 tip 5:d745ff46155b
138 141 \xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d 4:9259be597f19 (esc)
139 142 MIDDLE_ 3:b06c5b6def9e
140 143 \xe7\x9f\xad\xe5\x90\x8d 2:64a70663cee8 (esc)
@@ -1,249 +1,250 b''
1 1 Test character encoding
2 2
3 3 $ hg init t
4 4 $ cd t
5 5
6 6 we need a repo with some legacy latin-1 changesets
7 7
8 8 $ hg unbundle $TESTDIR/bundles/legacy-encoding.hg
9 9 adding changesets
10 10 adding manifests
11 11 adding file changes
12 12 added 2 changesets with 2 changes to 1 files
13 13 (run 'hg update' to get a working copy)
14 14 $ hg co
15 15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 16 $ python << EOF
17 17 > f = file('latin-1', 'w'); f.write("latin-1 e' encoded: \xe9"); f.close()
18 18 > f = file('utf-8', 'w'); f.write("utf-8 e' encoded: \xc3\xa9"); f.close()
19 19 > f = file('latin-1-tag', 'w'); f.write("\xe9"); f.close()
20 20 > EOF
21 21
22 22 should fail with encoding error
23 23
24 24 $ echo "plain old ascii" > a
25 25 $ hg st
26 26 M a
27 27 ? latin-1
28 28 ? latin-1-tag
29 29 ? utf-8
30 30 $ HGENCODING=ascii hg ci -l latin-1
31 31 transaction abort!
32 32 rollback completed
33 33 abort: decoding near ' encoded: \xe9': 'ascii' codec can't decode byte 0xe9 in position 20: ordinal not in range(128)! (esc)
34 34 [255]
35 35
36 36 these should work
37 37
38 38 $ echo "latin-1" > a
39 39 $ HGENCODING=latin-1 hg ci -l latin-1
40 40 $ echo "utf-8" > a
41 41 $ HGENCODING=utf-8 hg ci -l utf-8
42 42 $ HGENCODING=latin-1 hg tag `cat latin-1-tag`
43 43 $ HGENCODING=latin-1 hg branch `cat latin-1-tag`
44 44 marked working directory as branch \xe9 (esc)
45 (branches are permanent and global, did you want a bookmark?)
45 46 $ HGENCODING=latin-1 hg ci -m 'latin1 branch'
46 47 $ rm .hg/branch
47 48
48 49 hg log (ascii)
49 50
50 51 $ hg --encoding ascii log
51 52 changeset: 5:a52c0692f24a
52 53 branch: ?
53 54 tag: tip
54 55 user: test
55 56 date: Thu Jan 01 00:00:00 1970 +0000
56 57 summary: latin1 branch
57 58
58 59 changeset: 4:94db611b4196
59 60 user: test
60 61 date: Thu Jan 01 00:00:00 1970 +0000
61 62 summary: Added tag ? for changeset ca661e7520de
62 63
63 64 changeset: 3:ca661e7520de
64 65 tag: ?
65 66 user: test
66 67 date: Thu Jan 01 00:00:00 1970 +0000
67 68 summary: utf-8 e' encoded: ?
68 69
69 70 changeset: 2:650c6f3d55dd
70 71 user: test
71 72 date: Thu Jan 01 00:00:00 1970 +0000
72 73 summary: latin-1 e' encoded: ?
73 74
74 75 changeset: 1:0e5b7e3f9c4a
75 76 user: test
76 77 date: Mon Jan 12 13:46:40 1970 +0000
77 78 summary: koi8-r: ????? = u'\u0440\u0442\u0443\u0442\u044c'
78 79
79 80 changeset: 0:1e78a93102a3
80 81 user: test
81 82 date: Mon Jan 12 13:46:40 1970 +0000
82 83 summary: latin-1 e': ? = u'\xe9'
83 84
84 85
85 86 hg log (latin-1)
86 87
87 88 $ hg --encoding latin-1 log
88 89 changeset: 5:a52c0692f24a
89 90 branch: \xe9 (esc)
90 91 tag: tip
91 92 user: test
92 93 date: Thu Jan 01 00:00:00 1970 +0000
93 94 summary: latin1 branch
94 95
95 96 changeset: 4:94db611b4196
96 97 user: test
97 98 date: Thu Jan 01 00:00:00 1970 +0000
98 99 summary: Added tag \xe9 for changeset ca661e7520de (esc)
99 100
100 101 changeset: 3:ca661e7520de
101 102 tag: \xe9 (esc)
102 103 user: test
103 104 date: Thu Jan 01 00:00:00 1970 +0000
104 105 summary: utf-8 e' encoded: \xe9 (esc)
105 106
106 107 changeset: 2:650c6f3d55dd
107 108 user: test
108 109 date: Thu Jan 01 00:00:00 1970 +0000
109 110 summary: latin-1 e' encoded: \xe9 (esc)
110 111
111 112 changeset: 1:0e5b7e3f9c4a
112 113 user: test
113 114 date: Mon Jan 12 13:46:40 1970 +0000
114 115 summary: koi8-r: \xd2\xd4\xd5\xd4\xd8 = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
115 116
116 117 changeset: 0:1e78a93102a3
117 118 user: test
118 119 date: Mon Jan 12 13:46:40 1970 +0000
119 120 summary: latin-1 e': \xe9 = u'\\xe9' (esc)
120 121
121 122
122 123 hg log (utf-8)
123 124
124 125 $ hg --encoding utf-8 log
125 126 changeset: 5:a52c0692f24a
126 127 branch: \xc3\xa9 (esc)
127 128 tag: tip
128 129 user: test
129 130 date: Thu Jan 01 00:00:00 1970 +0000
130 131 summary: latin1 branch
131 132
132 133 changeset: 4:94db611b4196
133 134 user: test
134 135 date: Thu Jan 01 00:00:00 1970 +0000
135 136 summary: Added tag \xc3\xa9 for changeset ca661e7520de (esc)
136 137
137 138 changeset: 3:ca661e7520de
138 139 tag: \xc3\xa9 (esc)
139 140 user: test
140 141 date: Thu Jan 01 00:00:00 1970 +0000
141 142 summary: utf-8 e' encoded: \xc3\xa9 (esc)
142 143
143 144 changeset: 2:650c6f3d55dd
144 145 user: test
145 146 date: Thu Jan 01 00:00:00 1970 +0000
146 147 summary: latin-1 e' encoded: \xc3\xa9 (esc)
147 148
148 149 changeset: 1:0e5b7e3f9c4a
149 150 user: test
150 151 date: Mon Jan 12 13:46:40 1970 +0000
151 152 summary: koi8-r: \xc3\x92\xc3\x94\xc3\x95\xc3\x94\xc3\x98 = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
152 153
153 154 changeset: 0:1e78a93102a3
154 155 user: test
155 156 date: Mon Jan 12 13:46:40 1970 +0000
156 157 summary: latin-1 e': \xc3\xa9 = u'\\xe9' (esc)
157 158
158 159
159 160 hg tags (ascii)
160 161
161 162 $ HGENCODING=ascii hg tags
162 163 tip 5:a52c0692f24a
163 164 ? 3:ca661e7520de
164 165
165 166 hg tags (latin-1)
166 167
167 168 $ HGENCODING=latin-1 hg tags
168 169 tip 5:a52c0692f24a
169 170 \xe9 3:ca661e7520de (esc)
170 171
171 172 hg tags (utf-8)
172 173
173 174 $ HGENCODING=utf-8 hg tags
174 175 tip 5:a52c0692f24a
175 176 \xc3\xa9 3:ca661e7520de (esc)
176 177
177 178 hg branches (ascii)
178 179
179 180 $ HGENCODING=ascii hg branches
180 181 ? 5:a52c0692f24a
181 182 default 4:94db611b4196 (inactive)
182 183
183 184 hg branches (latin-1)
184 185
185 186 $ HGENCODING=latin-1 hg branches
186 187 \xe9 5:a52c0692f24a (esc)
187 188 default 4:94db611b4196 (inactive)
188 189
189 190 hg branches (utf-8)
190 191
191 192 $ HGENCODING=utf-8 hg branches
192 193 \xc3\xa9 5:a52c0692f24a (esc)
193 194 default 4:94db611b4196 (inactive)
194 195 $ echo '[ui]' >> .hg/hgrc
195 196 $ echo 'fallbackencoding = koi8-r' >> .hg/hgrc
196 197
197 198 hg log (utf-8)
198 199
199 200 $ HGENCODING=utf-8 hg log
200 201 changeset: 5:a52c0692f24a
201 202 branch: \xc3\xa9 (esc)
202 203 tag: tip
203 204 user: test
204 205 date: Thu Jan 01 00:00:00 1970 +0000
205 206 summary: latin1 branch
206 207
207 208 changeset: 4:94db611b4196
208 209 user: test
209 210 date: Thu Jan 01 00:00:00 1970 +0000
210 211 summary: Added tag \xc3\xa9 for changeset ca661e7520de (esc)
211 212
212 213 changeset: 3:ca661e7520de
213 214 tag: \xc3\xa9 (esc)
214 215 user: test
215 216 date: Thu Jan 01 00:00:00 1970 +0000
216 217 summary: utf-8 e' encoded: \xc3\xa9 (esc)
217 218
218 219 changeset: 2:650c6f3d55dd
219 220 user: test
220 221 date: Thu Jan 01 00:00:00 1970 +0000
221 222 summary: latin-1 e' encoded: \xc3\xa9 (esc)
222 223
223 224 changeset: 1:0e5b7e3f9c4a
224 225 user: test
225 226 date: Mon Jan 12 13:46:40 1970 +0000
226 227 summary: koi8-r: \xd1\x80\xd1\x82\xd1\x83\xd1\x82\xd1\x8c = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
227 228
228 229 changeset: 0:1e78a93102a3
229 230 user: test
230 231 date: Mon Jan 12 13:46:40 1970 +0000
231 232 summary: latin-1 e': \xd0\x98 = u'\\xe9' (esc)
232 233
233 234
234 235 hg log (dolphin)
235 236
236 237 $ HGENCODING=dolphin hg log
237 238 abort: unknown encoding: dolphin, please check your locale settings
238 239 [255]
239 240 $ HGENCODING=ascii hg branch `cat latin-1-tag`
240 241 abort: decoding near '\xe9': 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128)! (esc)
241 242 [255]
242 243 $ cp latin-1-tag .hg/branch
243 244 $ HGENCODING=latin-1 hg ci -m 'auto-promote legacy name'
244 245
245 246 Test roundtrip encoding of lookup tables when not using UTF-8 (issue2763)
246 247
247 248 $ HGENCODING=latin-1 hg up `cat latin-1-tag`
248 249 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
249 250
@@ -1,407 +1,412 b''
1 1 $ "$TESTDIR/hghave" serve || exit 80
2 2
3 3 $ echo "[extensions]" >> $HGRCPATH
4 4 $ echo "fetch=" >> $HGRCPATH
5 5
6 6 test fetch with default branches only
7 7
8 8 $ hg init a
9 9 $ echo a > a/a
10 10 $ hg --cwd a commit -Ama
11 11 adding a
12 12 $ hg clone a b
13 13 updating to branch default
14 14 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 15 $ hg clone a c
16 16 updating to branch default
17 17 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
18 18 $ echo b > a/b
19 19 $ hg --cwd a commit -Amb
20 20 adding b
21 21 $ hg --cwd a parents -q
22 22 1:d2ae7f538514
23 23
24 24 should pull one change
25 25
26 26 $ hg --cwd b fetch ../a
27 27 pulling from ../a
28 28 searching for changes
29 29 adding changesets
30 30 adding manifests
31 31 adding file changes
32 32 added 1 changesets with 1 changes to 1 files
33 33 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 34 $ hg --cwd b parents -q
35 35 1:d2ae7f538514
36 36 $ echo c > c/c
37 37 $ hg --cwd c commit -Amc
38 38 adding c
39 39 $ hg clone c d
40 40 updating to branch default
41 41 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 42 $ hg clone c e
43 43 updating to branch default
44 44 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
45 45
46 46 We cannot use the default commit message if fetching from a local
47 47 repo, because the path of the repo will be included in the commit
48 48 message, making every commit appear different.
49 49 should merge c into a
50 50
51 51 $ hg --cwd c fetch -d '0 0' -m 'automated merge' ../a
52 52 pulling from ../a
53 53 searching for changes
54 54 adding changesets
55 55 adding manifests
56 56 adding file changes
57 57 added 1 changesets with 1 changes to 1 files (+1 heads)
58 58 updating to 2:d2ae7f538514
59 59 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
60 60 merging with 1:d36c0562f908
61 61 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
62 62 new changeset 3:a323a0c43ec4 merges remote changes with local
63 63 $ ls c
64 64 a
65 65 b
66 66 c
67 67 $ hg --cwd a serve -a localhost -p $HGPORT -d --pid-file=hg.pid
68 68 $ cat a/hg.pid >> "$DAEMON_PIDS"
69 69
70 70 fetch over http, no auth
71 71
72 72 $ hg --cwd d fetch http://localhost:$HGPORT/
73 73 pulling from http://localhost:$HGPORT/
74 74 searching for changes
75 75 adding changesets
76 76 adding manifests
77 77 adding file changes
78 78 added 1 changesets with 1 changes to 1 files (+1 heads)
79 79 updating to 2:d2ae7f538514
80 80 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
81 81 merging with 1:d36c0562f908
82 82 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
83 83 new changeset 3:* merges remote changes with local (glob)
84 84 $ hg --cwd d tip --template '{desc}\n'
85 85 Automated merge with http://localhost:$HGPORT/
86 86
87 87 fetch over http with auth (should be hidden in desc)
88 88
89 89 $ hg --cwd e fetch http://user:password@localhost:$HGPORT/
90 90 pulling from http://user:***@localhost:$HGPORT/
91 91 searching for changes
92 92 adding changesets
93 93 adding manifests
94 94 adding file changes
95 95 added 1 changesets with 1 changes to 1 files (+1 heads)
96 96 updating to 2:d2ae7f538514
97 97 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
98 98 merging with 1:d36c0562f908
99 99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 100 new changeset 3:* merges remote changes with local (glob)
101 101 $ hg --cwd e tip --template '{desc}\n'
102 102 Automated merge with http://localhost:$HGPORT/
103 103 $ hg clone a f
104 104 updating to branch default
105 105 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
106 106 $ hg clone a g
107 107 updating to branch default
108 108 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 109 $ echo f > f/f
110 110 $ hg --cwd f ci -Amf
111 111 adding f
112 112 $ echo g > g/g
113 113 $ hg --cwd g ci -Amg
114 114 adding g
115 115 $ hg clone -q f h
116 116 $ hg clone -q g i
117 117
118 118 should merge f into g
119 119
120 120 $ hg --cwd g fetch -d '0 0' --switch -m 'automated merge' ../f
121 121 pulling from ../f
122 122 searching for changes
123 123 adding changesets
124 124 adding manifests
125 125 adding file changes
126 126 added 1 changesets with 1 changes to 1 files (+1 heads)
127 127 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
128 128 merging with 3:6343ca3eff20
129 129 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
130 130 new changeset 4:f7faa0b7d3c6 merges remote changes with local
131 131 $ rm i/g
132 132
133 133 should abort, because i is modified
134 134
135 135 $ hg --cwd i fetch ../h
136 136 abort: working directory is missing some files
137 137 [255]
138 138
139 139 test fetch with named branches
140 140
141 141 $ hg init nbase
142 142 $ echo base > nbase/a
143 143 $ hg -R nbase ci -Am base
144 144 adding a
145 145 $ hg -R nbase branch a
146 146 marked working directory as branch a
147 (branches are permanent and global, did you want a bookmark?)
147 148 $ echo a > nbase/a
148 149 $ hg -R nbase ci -m a
149 150 $ hg -R nbase up -C 0
150 151 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
151 152 $ hg -R nbase branch b
152 153 marked working directory as branch b
154 (branches are permanent and global, did you want a bookmark?)
153 155 $ echo b > nbase/b
154 156 $ hg -R nbase ci -Am b
155 157 adding b
156 158
157 159 pull in change on foreign branch
158 160
159 161 $ hg clone nbase n1
160 162 updating to branch default
161 163 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
162 164 $ hg clone nbase n2
163 165 updating to branch default
164 166 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
165 167 $ hg -R n1 up -C a
166 168 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
167 169 $ echo aa > n1/a
168 170 $ hg -R n1 ci -m a1
169 171 $ hg -R n2 up -C b
170 172 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
171 173 $ hg -R n2 fetch -m 'merge' n1
172 174 pulling from n1
173 175 searching for changes
174 176 adding changesets
175 177 adding manifests
176 178 adding file changes
177 179 added 1 changesets with 1 changes to 1 files
178 180
179 181 parent should be 2 (no automatic update)
180 182
181 183 $ hg -R n2 parents --template '{rev}\n'
182 184 2
183 185 $ rm -fr n1 n2
184 186
185 187 pull in changes on both foreign and local branches
186 188
187 189 $ hg clone nbase n1
188 190 updating to branch default
189 191 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 192 $ hg clone nbase n2
191 193 updating to branch default
192 194 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
193 195 $ hg -R n1 up -C a
194 196 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
195 197 $ echo aa > n1/a
196 198 $ hg -R n1 ci -m a1
197 199 $ hg -R n1 up -C b
198 200 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
199 201 $ echo bb > n1/b
200 202 $ hg -R n1 ci -m b1
201 203 $ hg -R n2 up -C b
202 204 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
203 205 $ hg -R n2 fetch -m 'merge' n1
204 206 pulling from n1
205 207 searching for changes
206 208 adding changesets
207 209 adding manifests
208 210 adding file changes
209 211 added 2 changesets with 2 changes to 2 files
210 212 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
211 213
212 214 parent should be 4 (fast forward)
213 215
214 216 $ hg -R n2 parents --template '{rev}\n'
215 217 4
216 218 $ rm -fr n1 n2
217 219
218 220 pull changes on foreign (2 new heads) and local (1 new head) branches
219 221 with a local change
220 222
221 223 $ hg clone nbase n1
222 224 updating to branch default
223 225 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
224 226 $ hg clone nbase n2
225 227 updating to branch default
226 228 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
227 229 $ hg -R n1 up -C a
228 230 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
229 231 $ echo a1 > n1/a
230 232 $ hg -R n1 ci -m a1
231 233 $ hg -R n1 up -C b
232 234 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
233 235 $ echo bb > n1/b
234 236 $ hg -R n1 ci -m b1
235 237 $ hg -R n1 up -C 1
236 238 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
237 239 $ echo a2 > n1/a
238 240 $ hg -R n1 ci -m a2
239 241 created new head
240 242 $ hg -R n2 up -C b
241 243 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
242 244 $ echo change >> n2/c
243 245 $ hg -R n2 ci -A -m local
244 246 adding c
245 247 $ hg -R n2 fetch -d '0 0' -m 'merge' n1
246 248 pulling from n1
247 249 searching for changes
248 250 adding changesets
249 251 adding manifests
250 252 adding file changes
251 253 added 3 changesets with 3 changes to 2 files (+2 heads)
252 254 updating to 5:3c4a837a864f
253 255 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
254 256 merging with 3:1267f84a9ea5
255 257 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
256 258 new changeset 7:2cf2a1261f21 merges remote changes with local
257 259
258 260 parent should be 7 (new merge changeset)
259 261
260 262 $ hg -R n2 parents --template '{rev}\n'
261 263 7
262 264 $ rm -fr n1 n2
263 265
264 266 pull in changes on foreign (merge of local branch) and local (2 new
265 267 heads) with a local change
266 268
267 269 $ hg clone nbase n1
268 270 updating to branch default
269 271 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
270 272 $ hg clone nbase n2
271 273 updating to branch default
272 274 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
273 275 $ hg -R n1 up -C a
274 276 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
275 277 $ hg -R n1 merge b
276 278 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
277 279 (branch merge, don't forget to commit)
278 280 $ hg -R n1 ci -m merge
279 281 $ hg -R n1 up -C 2
280 282 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
281 283 $ echo c > n1/a
282 284 $ hg -R n1 ci -m c
283 285 $ hg -R n1 up -C 2
284 286 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
285 287 $ echo cc > n1/a
286 288 $ hg -R n1 ci -m cc
287 289 created new head
288 290 $ hg -R n2 up -C b
289 291 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
290 292 $ echo change >> n2/b
291 293 $ hg -R n2 ci -A -m local
292 294 $ hg -R n2 fetch -m 'merge' n1
293 295 pulling from n1
294 296 searching for changes
295 297 adding changesets
296 298 adding manifests
297 299 adding file changes
298 300 added 3 changesets with 2 changes to 1 files (+2 heads)
299 301 not merging with 1 other new branch heads (use "hg heads ." and "hg merge" to merge them)
300 302 [1]
301 303
302 304 parent should be 3 (fetch did not merge anything)
303 305
304 306 $ hg -R n2 parents --template '{rev}\n'
305 307 3
306 308 $ rm -fr n1 n2
307 309
308 310 pull in change on different branch than dirstate
309 311
310 312 $ hg init n1
311 313 $ echo a > n1/a
312 314 $ hg -R n1 ci -Am initial
313 315 adding a
314 316 $ hg clone n1 n2
315 317 updating to branch default
316 318 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
317 319 $ echo b > n1/a
318 320 $ hg -R n1 ci -m next
319 321 $ hg -R n2 branch topic
320 322 marked working directory as branch topic
323 (branches are permanent and global, did you want a bookmark?)
321 324 $ hg -R n2 fetch -m merge n1
322 325 abort: working dir not at branch tip (use "hg update" to check out branch tip)
323 326 [255]
324 327
325 328 parent should be 0 (fetch did not update or merge anything)
326 329
327 330 $ hg -R n2 parents --template '{rev}\n'
328 331 0
329 332 $ rm -fr n1 n2
330 333
331 334 test fetch with inactive branches
332 335
333 336 $ hg init ib1
334 337 $ echo a > ib1/a
335 338 $ hg --cwd ib1 ci -Am base
336 339 adding a
337 340 $ hg --cwd ib1 branch second
338 341 marked working directory as branch second
342 (branches are permanent and global, did you want a bookmark?)
339 343 $ echo b > ib1/b
340 344 $ hg --cwd ib1 ci -Am onsecond
341 345 adding b
342 346 $ hg --cwd ib1 branch -f default
343 347 marked working directory as branch default
348 (branches are permanent and global, did you want a bookmark?)
344 349 $ echo c > ib1/c
345 350 $ hg --cwd ib1 ci -Am newdefault
346 351 adding c
347 352 created new head
348 353 $ hg clone ib1 ib2
349 354 updating to branch default
350 355 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
351 356
352 357 fetch should succeed
353 358
354 359 $ hg --cwd ib2 fetch ../ib1
355 360 pulling from ../ib1
356 361 searching for changes
357 362 no changes found
358 363 $ rm -fr ib1 ib2
359 364
360 365 test issue1726
361 366
362 367 $ hg init i1726r1
363 368 $ echo a > i1726r1/a
364 369 $ hg --cwd i1726r1 ci -Am base
365 370 adding a
366 371 $ hg clone i1726r1 i1726r2
367 372 updating to branch default
368 373 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
369 374 $ echo b > i1726r1/a
370 375 $ hg --cwd i1726r1 ci -m second
371 376 $ echo c > i1726r2/a
372 377 $ hg --cwd i1726r2 ci -m third
373 378 $ HGMERGE=true hg --cwd i1726r2 fetch ../i1726r1
374 379 pulling from ../i1726r1
375 380 searching for changes
376 381 adding changesets
377 382 adding manifests
378 383 adding file changes
379 384 added 1 changesets with 1 changes to 1 files (+1 heads)
380 385 updating to 2:7837755a2789
381 386 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
382 387 merging with 1:d1f0c6c48ebd
383 388 merging a
384 389 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
385 390 new changeset 3:* merges remote changes with local (glob)
386 391 $ hg --cwd i1726r2 heads default --template '{rev}\n'
387 392 3
388 393
389 394 test issue2047
390 395
391 396 $ hg -q init i2047a
392 397 $ cd i2047a
393 398 $ echo a > a
394 399 $ hg -q ci -Am a
395 400 $ hg -q branch stable
396 401 $ echo b > b
397 402 $ hg -q ci -Am b
398 403 $ cd ..
399 404 $ hg -q clone -r 0 i2047a i2047b
400 405 $ cd i2047b
401 406 $ hg fetch ../i2047a
402 407 pulling from ../i2047a
403 408 searching for changes
404 409 adding changesets
405 410 adding manifests
406 411 adding file changes
407 412 added 1 changesets with 1 changes to 1 files
@@ -1,1159 +1,1160 b''
1 1 $ "$TESTDIR/hghave" serve || exit 80
2 2
3 3 An attempt at more fully testing the hgweb web interface.
4 4 The following things are tested elsewhere and are therefore omitted:
5 5 - archive, tested in test-archive
6 6 - unbundle, tested in test-push-http
7 7 - changegroupsubset, tested in test-pull
8 8
9 9 Set up the repo
10 10
11 11 $ hg init test
12 12 $ cd test
13 13 $ mkdir da
14 14 $ echo foo > da/foo
15 15 $ echo foo > foo
16 16 $ hg ci -Ambase
17 17 adding da/foo
18 18 adding foo
19 19 $ hg tag 1.0
20 20 $ hg bookmark something
21 21 $ hg bookmark -r0 anotherthing
22 22 $ echo another > foo
23 23 $ hg branch stable
24 24 marked working directory as branch stable
25 (branches are permanent and global, did you want a bookmark?)
25 26 $ hg ci -Ambranch
26 27 $ hg serve --config server.uncompressed=False -n test -p $HGPORT -d --pid-file=hg.pid -E errors.log
27 28 $ cat hg.pid >> $DAEMON_PIDS
28 29
29 30 Logs and changes
30 31
31 32 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/?style=atom'
32 33 200 Script output follows
33 34
34 35 <?xml version="1.0" encoding="ascii"?>
35 36 <feed xmlns="http://www.w3.org/2005/Atom">
36 37 <!-- Changelog -->
37 38 <id>http://*:$HGPORT/</id> (glob)
38 39 <link rel="self" href="http://*:$HGPORT/atom-log"/> (glob)
39 40 <link rel="alternate" href="http://*:$HGPORT/"/> (glob)
40 41 <title>test Changelog</title>
41 42 <updated>1970-01-01T00:00:00+00:00</updated>
42 43
43 44 <entry>
44 45 <title>branch</title>
45 46 <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
46 47 <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
47 48 <author>
48 49 <name>test</name>
49 50 <email>&#116;&#101;&#115;&#116;</email>
50 51 </author>
51 52 <updated>1970-01-01T00:00:00+00:00</updated>
52 53 <published>1970-01-01T00:00:00+00:00</published>
53 54 <content type="xhtml">
54 55 <div xmlns="http://www.w3.org/1999/xhtml">
55 56 <pre xml:space="preserve">branch</pre>
56 57 </div>
57 58 </content>
58 59 </entry>
59 60 <entry>
60 61 <title>Added tag 1.0 for changeset 2ef0ac749a14</title>
61 62 <id>http://*:$HGPORT/#changeset-a4f92ed23982be056b9852de5dfe873eaac7f0de</id> (glob)
62 63 <link href="http://*:$HGPORT/rev/a4f92ed23982"/> (glob)
63 64 <author>
64 65 <name>test</name>
65 66 <email>&#116;&#101;&#115;&#116;</email>
66 67 </author>
67 68 <updated>1970-01-01T00:00:00+00:00</updated>
68 69 <published>1970-01-01T00:00:00+00:00</published>
69 70 <content type="xhtml">
70 71 <div xmlns="http://www.w3.org/1999/xhtml">
71 72 <pre xml:space="preserve">Added tag 1.0 for changeset 2ef0ac749a14</pre>
72 73 </div>
73 74 </content>
74 75 </entry>
75 76 <entry>
76 77 <title>base</title>
77 78 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
78 79 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
79 80 <author>
80 81 <name>test</name>
81 82 <email>&#116;&#101;&#115;&#116;</email>
82 83 </author>
83 84 <updated>1970-01-01T00:00:00+00:00</updated>
84 85 <published>1970-01-01T00:00:00+00:00</published>
85 86 <content type="xhtml">
86 87 <div xmlns="http://www.w3.org/1999/xhtml">
87 88 <pre xml:space="preserve">base</pre>
88 89 </div>
89 90 </content>
90 91 </entry>
91 92
92 93 </feed>
93 94 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/?style=atom'
94 95 200 Script output follows
95 96
96 97 <?xml version="1.0" encoding="ascii"?>
97 98 <feed xmlns="http://www.w3.org/2005/Atom">
98 99 <!-- Changelog -->
99 100 <id>http://*:$HGPORT/</id> (glob)
100 101 <link rel="self" href="http://*:$HGPORT/atom-log"/> (glob)
101 102 <link rel="alternate" href="http://*:$HGPORT/"/> (glob)
102 103 <title>test Changelog</title>
103 104 <updated>1970-01-01T00:00:00+00:00</updated>
104 105
105 106 <entry>
106 107 <title>branch</title>
107 108 <id>http://*:$HGPORT/#changeset-1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe</id> (glob)
108 109 <link href="http://*:$HGPORT/rev/1d22e65f027e"/> (glob)
109 110 <author>
110 111 <name>test</name>
111 112 <email>&#116;&#101;&#115;&#116;</email>
112 113 </author>
113 114 <updated>1970-01-01T00:00:00+00:00</updated>
114 115 <published>1970-01-01T00:00:00+00:00</published>
115 116 <content type="xhtml">
116 117 <div xmlns="http://www.w3.org/1999/xhtml">
117 118 <pre xml:space="preserve">branch</pre>
118 119 </div>
119 120 </content>
120 121 </entry>
121 122 <entry>
122 123 <title>Added tag 1.0 for changeset 2ef0ac749a14</title>
123 124 <id>http://*:$HGPORT/#changeset-a4f92ed23982be056b9852de5dfe873eaac7f0de</id> (glob)
124 125 <link href="http://*:$HGPORT/rev/a4f92ed23982"/> (glob)
125 126 <author>
126 127 <name>test</name>
127 128 <email>&#116;&#101;&#115;&#116;</email>
128 129 </author>
129 130 <updated>1970-01-01T00:00:00+00:00</updated>
130 131 <published>1970-01-01T00:00:00+00:00</published>
131 132 <content type="xhtml">
132 133 <div xmlns="http://www.w3.org/1999/xhtml">
133 134 <pre xml:space="preserve">Added tag 1.0 for changeset 2ef0ac749a14</pre>
134 135 </div>
135 136 </content>
136 137 </entry>
137 138 <entry>
138 139 <title>base</title>
139 140 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
140 141 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
141 142 <author>
142 143 <name>test</name>
143 144 <email>&#116;&#101;&#115;&#116;</email>
144 145 </author>
145 146 <updated>1970-01-01T00:00:00+00:00</updated>
146 147 <published>1970-01-01T00:00:00+00:00</published>
147 148 <content type="xhtml">
148 149 <div xmlns="http://www.w3.org/1999/xhtml">
149 150 <pre xml:space="preserve">base</pre>
150 151 </div>
151 152 </content>
152 153 </entry>
153 154
154 155 </feed>
155 156 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/foo/?style=atom'
156 157 200 Script output follows
157 158
158 159 <?xml version="1.0" encoding="ascii"?>
159 160 <feed xmlns="http://www.w3.org/2005/Atom">
160 161 <id>http://*:$HGPORT/atom-log/tip/foo</id> (glob)
161 162 <link rel="self" href="http://*:$HGPORT/atom-log/tip/foo"/> (glob)
162 163 <title>test: foo history</title>
163 164 <updated>1970-01-01T00:00:00+00:00</updated>
164 165
165 166 <entry>
166 167 <title>base</title>
167 168 <id>http://*:$HGPORT/#changeset-2ef0ac749a14e4f57a5a822464a0902c6f7f448f</id> (glob)
168 169 <link href="http://*:$HGPORT/rev/2ef0ac749a14"/> (glob)
169 170 <author>
170 171 <name>test</name>
171 172 <email>&#116;&#101;&#115;&#116;</email>
172 173 </author>
173 174 <updated>1970-01-01T00:00:00+00:00</updated>
174 175 <published>1970-01-01T00:00:00+00:00</published>
175 176 <content type="xhtml">
176 177 <div xmlns="http://www.w3.org/1999/xhtml">
177 178 <pre xml:space="preserve">base</pre>
178 179 </div>
179 180 </content>
180 181 </entry>
181 182
182 183 </feed>
183 184 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/shortlog/'
184 185 200 Script output follows
185 186
186 187 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
187 188 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
188 189 <head>
189 190 <link rel="icon" href="/static/hgicon.png" type="image/png" />
190 191 <meta name="robots" content="index, nofollow" />
191 192 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
192 193 <script type="text/javascript" src="/static/mercurial.js"></script>
193 194
194 195 <title>test: log</title>
195 196 <link rel="alternate" type="application/atom+xml"
196 197 href="/atom-log" title="Atom feed for test" />
197 198 <link rel="alternate" type="application/rss+xml"
198 199 href="/rss-log" title="RSS feed for test" />
199 200 </head>
200 201 <body>
201 202
202 203 <div class="container">
203 204 <div class="menu">
204 205 <div class="logo">
205 206 <a href="http://mercurial.selenic.com/">
206 207 <img src="/static/hglogo.png" alt="mercurial" /></a>
207 208 </div>
208 209 <ul>
209 210 <li class="active">log</li>
210 211 <li><a href="/graph/1d22e65f027e">graph</a></li>
211 212 <li><a href="/tags">tags</a></li>
212 213 <li><a href="/bookmarks">bookmarks</a></li>
213 214 <li><a href="/branches">branches</a></li>
214 215 </ul>
215 216 <ul>
216 217 <li><a href="/rev/1d22e65f027e">changeset</a></li>
217 218 <li><a href="/file/1d22e65f027e">browse</a></li>
218 219 </ul>
219 220 <ul>
220 221
221 222 </ul>
222 223 <ul>
223 224 <li><a href="/help">help</a></li>
224 225 </ul>
225 226 </div>
226 227
227 228 <div class="main">
228 229 <h2><a href="/">test</a></h2>
229 230 <h3>log</h3>
230 231
231 232 <form class="search" action="/log">
232 233
233 234 <p><input name="rev" id="search1" type="text" size="30" /></p>
234 235 <div id="hint">find changesets by author, revision,
235 236 files, or words in the commit message</div>
236 237 </form>
237 238
238 239 <div class="navigate">
239 240 <a href="/shortlog/2?revcount=30">less</a>
240 241 <a href="/shortlog/2?revcount=120">more</a>
241 242 | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
242 243 </div>
243 244
244 245 <table class="bigtable">
245 246 <tr>
246 247 <th class="age">age</th>
247 248 <th class="author">author</th>
248 249 <th class="description">description</th>
249 250 </tr>
250 251 <tr class="parity0">
251 252 <td class="age">Thu, 01 Jan 1970 00:00:00 +0000</td>
252 253 <td class="author">test</td>
253 254 <td class="description"><a href="/rev/1d22e65f027e">branch</a><span class="branchhead">stable</span> <span class="tag">tip</span> <span class="tag">something</span> </td>
254 255 </tr>
255 256 <tr class="parity1">
256 257 <td class="age">Thu, 01 Jan 1970 00:00:00 +0000</td>
257 258 <td class="author">test</td>
258 259 <td class="description"><a href="/rev/a4f92ed23982">Added tag 1.0 for changeset 2ef0ac749a14</a><span class="branchhead">default</span> </td>
259 260 </tr>
260 261 <tr class="parity0">
261 262 <td class="age">Thu, 01 Jan 1970 00:00:00 +0000</td>
262 263 <td class="author">test</td>
263 264 <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> <span class="tag">anotherthing</span> </td>
264 265 </tr>
265 266
266 267 </table>
267 268
268 269 <div class="navigate">
269 270 <a href="/shortlog/2?revcount=30">less</a>
270 271 <a href="/shortlog/2?revcount=120">more</a>
271 272 | rev 2: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a>
272 273 </div>
273 274
274 275 </div>
275 276 </div>
276 277
277 278 <script type="text/javascript">process_dates()</script>
278 279
279 280
280 281 </body>
281 282 </html>
282 283
283 284 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/0/'
284 285 200 Script output follows
285 286
286 287 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
287 288 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
288 289 <head>
289 290 <link rel="icon" href="/static/hgicon.png" type="image/png" />
290 291 <meta name="robots" content="index, nofollow" />
291 292 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
292 293 <script type="text/javascript" src="/static/mercurial.js"></script>
293 294
294 295 <title>test: 2ef0ac749a14</title>
295 296 </head>
296 297 <body>
297 298 <div class="container">
298 299 <div class="menu">
299 300 <div class="logo">
300 301 <a href="http://mercurial.selenic.com/">
301 302 <img src="/static/hglogo.png" alt="mercurial" /></a>
302 303 </div>
303 304 <ul>
304 305 <li><a href="/shortlog/2ef0ac749a14">log</a></li>
305 306 <li><a href="/graph/2ef0ac749a14">graph</a></li>
306 307 <li><a href="/tags">tags</a></li>
307 308 <li><a href="/bookmarks">bookmarks</a></li>
308 309 <li><a href="/branches">branches</a></li>
309 310 </ul>
310 311 <ul>
311 312 <li class="active">changeset</li>
312 313 <li><a href="/raw-rev/2ef0ac749a14">raw</a></li>
313 314 <li><a href="/file/2ef0ac749a14">browse</a></li>
314 315 </ul>
315 316 <ul>
316 317
317 318 </ul>
318 319 <ul>
319 320 <li><a href="/help">help</a></li>
320 321 </ul>
321 322 </div>
322 323
323 324 <div class="main">
324 325
325 326 <h2><a href="/">test</a></h2>
326 327 <h3>changeset 0:2ef0ac749a14 <span class="tag">1.0</span> <span class="tag">anotherthing</span> </h3>
327 328
328 329 <form class="search" action="/log">
329 330
330 331 <p><input name="rev" id="search1" type="text" size="30" /></p>
331 332 <div id="hint">find changesets by author, revision,
332 333 files, or words in the commit message</div>
333 334 </form>
334 335
335 336 <div class="description">base</div>
336 337
337 338 <table id="changesetEntry">
338 339 <tr>
339 340 <th class="author">author</th>
340 341 <td class="author">&#116;&#101;&#115;&#116;</td>
341 342 </tr>
342 343 <tr>
343 344 <th class="date">date</th>
344 345 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td></tr>
345 346 <tr>
346 347 <th class="author">parents</th>
347 348 <td class="author"></td>
348 349 </tr>
349 350 <tr>
350 351 <th class="author">children</th>
351 352 <td class="author"> <a href="/rev/a4f92ed23982">a4f92ed23982</a></td>
352 353 </tr>
353 354 <tr>
354 355 <th class="files">files</th>
355 356 <td class="files"><a href="/file/2ef0ac749a14/da/foo">da/foo</a> <a href="/file/2ef0ac749a14/foo">foo</a> </td>
356 357 </tr>
357 358 <tr>
358 359 <th class="diffstat">diffstat</th>
359 360 <td class="diffstat">
360 361 2 files changed, 2 insertions(+), 0 deletions(-)
361 362
362 363 <a id="diffstatexpand" href="javascript:showDiffstat()"/>[<tt>+</tt>]</a>
363 364 <div id="diffstatdetails" style="display:none;">
364 365 <a href="javascript:hideDiffstat()"/>[<tt>-</tt>]</a>
365 366 <p>
366 367 <table> <tr class="parity0">
367 368 <td class="diffstat-file"><a href="#l1.1">da/foo</a></td>
368 369 <td class="diffstat-total" align="right">1</td>
369 370 <td class="diffstat-graph">
370 371 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
371 372 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
372 373 </td>
373 374 </tr>
374 375 <tr class="parity1">
375 376 <td class="diffstat-file"><a href="#l2.1">foo</a></td>
376 377 <td class="diffstat-total" align="right">1</td>
377 378 <td class="diffstat-graph">
378 379 <span class="diffstat-add" style="width:100.0%;">&nbsp;</span>
379 380 <span class="diffstat-remove" style="width:0.0%;">&nbsp;</span>
380 381 </td>
381 382 </tr>
382 383 </table>
383 384 </div>
384 385 </td>
385 386 </tr>
386 387 </table>
387 388
388 389 <div class="overflow">
389 390 <div class="sourcefirst"> line diff</div>
390 391
391 392 <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1"> 1.1</a> <span class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000
392 393 </span><a href="#l1.2" id="l1.2"> 1.2</a> <span class="plusline">+++ b/da/foo Thu Jan 01 00:00:00 1970 +0000
393 394 </span><a href="#l1.3" id="l1.3"> 1.3</a> <span class="atline">@@ -0,0 +1,1 @@
394 395 </span><a href="#l1.4" id="l1.4"> 1.4</a> <span class="plusline">+foo
395 396 </span></pre></div><div class="source bottomline parity1"><pre><a href="#l2.1" id="l2.1"> 2.1</a> <span class="minusline">--- /dev/null Thu Jan 01 00:00:00 1970 +0000
396 397 </span><a href="#l2.2" id="l2.2"> 2.2</a> <span class="plusline">+++ b/foo Thu Jan 01 00:00:00 1970 +0000
397 398 </span><a href="#l2.3" id="l2.3"> 2.3</a> <span class="atline">@@ -0,0 +1,1 @@
398 399 </span><a href="#l2.4" id="l2.4"> 2.4</a> <span class="plusline">+foo
399 400 </span></pre></div>
400 401 </div>
401 402
402 403 </div>
403 404 </div>
404 405 <script type="text/javascript">process_dates()</script>
405 406
406 407
407 408 </body>
408 409 </html>
409 410
410 411 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/1/?style=raw'
411 412 200 Script output follows
412 413
413 414
414 415 # HG changeset patch
415 416 # User test
416 417 # Date 0 0
417 418 # Node ID a4f92ed23982be056b9852de5dfe873eaac7f0de
418 419 # Parent 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
419 420 Added tag 1.0 for changeset 2ef0ac749a14
420 421
421 422 diff -r 2ef0ac749a14 -r a4f92ed23982 .hgtags
422 423 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
423 424 +++ b/.hgtags Thu Jan 01 00:00:00 1970 +0000
424 425 @@ -0,0 +1,1 @@
425 426 +2ef0ac749a14e4f57a5a822464a0902c6f7f448f 1.0
426 427
427 428 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log?rev=base'
428 429 200 Script output follows
429 430
430 431 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
431 432 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
432 433 <head>
433 434 <link rel="icon" href="/static/hgicon.png" type="image/png" />
434 435 <meta name="robots" content="index, nofollow" />
435 436 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
436 437 <script type="text/javascript" src="/static/mercurial.js"></script>
437 438
438 439 <title>test: searching for base</title>
439 440 </head>
440 441 <body>
441 442
442 443 <div class="container">
443 444 <div class="menu">
444 445 <div class="logo">
445 446 <a href="http://mercurial.selenic.com/">
446 447 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
447 448 </div>
448 449 <ul>
449 450 <li><a href="/shortlog">log</a></li>
450 451 <li><a href="/graph">graph</a></li>
451 452 <li><a href="/tags">tags</a></li>
452 453 <li><a href="/bookmarks">bookmarks</a></li>
453 454 <li><a href="/branches">branches</a></li>
454 455 <li><a href="/help">help</a></li>
455 456 </ul>
456 457 </div>
457 458
458 459 <div class="main">
459 460 <h2><a href="/">test</a></h2>
460 461 <h3>searching for 'base'</h3>
461 462
462 463 <form class="search" action="/log">
463 464
464 465 <p><input name="rev" id="search1" type="text" size="30"></p>
465 466 <div id="hint">find changesets by author, revision,
466 467 files, or words in the commit message</div>
467 468 </form>
468 469
469 470 <div class="navigate">
470 471 <a href="/search/?rev=base&revcount=5">less</a>
471 472 <a href="/search/?rev=base&revcount=20">more</a>
472 473 </div>
473 474
474 475 <table class="bigtable">
475 476 <tr>
476 477 <th class="age">age</th>
477 478 <th class="author">author</th>
478 479 <th class="description">description</th>
479 480 </tr>
480 481 <tr class="parity0">
481 482 <td class="age">Thu, 01 Jan 1970 00:00:00 +0000</td>
482 483 <td class="author">test</td>
483 484 <td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> <span class="tag">anotherthing</span> </td>
484 485 </tr>
485 486
486 487 </table>
487 488
488 489 <div class="navigate">
489 490 <a href="/search/?rev=base&revcount=5">less</a>
490 491 <a href="/search/?rev=base&revcount=20">more</a>
491 492 </div>
492 493
493 494 </div>
494 495 </div>
495 496
496 497 <script type="text/javascript">process_dates()</script>
497 498
498 499
499 500 </body>
500 501 </html>
501 502
502 503
503 504 File-related
504 505
505 506 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo/?style=raw'
506 507 200 Script output follows
507 508
508 509 foo
509 510 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/annotate/1/foo/?style=raw'
510 511 200 Script output follows
511 512
512 513
513 514 test@0: foo
514 515
515 516
516 517
517 518
518 519 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/?style=raw'
519 520 200 Script output follows
520 521
521 522
522 523 drwxr-xr-x da
523 524 -rw-r--r-- 45 .hgtags
524 525 -rw-r--r-- 4 foo
525 526
526 527
527 528 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo'
528 529 200 Script output follows
529 530
530 531 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
531 532 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
532 533 <head>
533 534 <link rel="icon" href="/static/hgicon.png" type="image/png" />
534 535 <meta name="robots" content="index, nofollow" />
535 536 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
536 537 <script type="text/javascript" src="/static/mercurial.js"></script>
537 538
538 539 <title>test: a4f92ed23982 foo</title>
539 540 </head>
540 541 <body>
541 542
542 543 <div class="container">
543 544 <div class="menu">
544 545 <div class="logo">
545 546 <a href="http://mercurial.selenic.com/">
546 547 <img src="/static/hglogo.png" alt="mercurial" /></a>
547 548 </div>
548 549 <ul>
549 550 <li><a href="/shortlog/a4f92ed23982">log</a></li>
550 551 <li><a href="/graph/a4f92ed23982">graph</a></li>
551 552 <li><a href="/tags">tags</a></li>
552 553 <li><a href="/branches">branches</a></li>
553 554 </ul>
554 555 <ul>
555 556 <li><a href="/rev/a4f92ed23982">changeset</a></li>
556 557 <li><a href="/file/a4f92ed23982/">browse</a></li>
557 558 </ul>
558 559 <ul>
559 560 <li class="active">file</li>
560 561 <li><a href="/file/tip/foo">latest</a></li>
561 562 <li><a href="/diff/a4f92ed23982/foo">diff</a></li>
562 563 <li><a href="/annotate/a4f92ed23982/foo">annotate</a></li>
563 564 <li><a href="/log/a4f92ed23982/foo">file log</a></li>
564 565 <li><a href="/raw-file/a4f92ed23982/foo">raw</a></li>
565 566 </ul>
566 567 <ul>
567 568 <li><a href="/help">help</a></li>
568 569 </ul>
569 570 </div>
570 571
571 572 <div class="main">
572 573 <h2><a href="/">test</a></h2>
573 574 <h3>view foo @ 1:a4f92ed23982</h3>
574 575
575 576 <form class="search" action="/log">
576 577
577 578 <p><input name="rev" id="search1" type="text" size="30" /></p>
578 579 <div id="hint">find changesets by author, revision,
579 580 files, or words in the commit message</div>
580 581 </form>
581 582
582 583 <div class="description">Added tag 1.0 for changeset 2ef0ac749a14</div>
583 584
584 585 <table id="changesetEntry">
585 586 <tr>
586 587 <th class="author">author</th>
587 588 <td class="author">&#116;&#101;&#115;&#116;</td>
588 589 </tr>
589 590 <tr>
590 591 <th class="date">date</th>
591 592 <td class="date age">Thu, 01 Jan 1970 00:00:00 +0000</td>
592 593 </tr>
593 594 <tr>
594 595 <th class="author">parents</th>
595 596 <td class="author"></td>
596 597 </tr>
597 598 <tr>
598 599 <th class="author">children</th>
599 600 <td class="author"><a href="/file/1d22e65f027e/foo">1d22e65f027e</a> </td>
600 601 </tr>
601 602
602 603 </table>
603 604
604 605 <div class="overflow">
605 606 <div class="sourcefirst"> line source</div>
606 607
607 608 <div class="parity0 source"><a href="#l1" id="l1"> 1</a> foo
608 609 </div>
609 610 <div class="sourcelast"></div>
610 611 </div>
611 612 </div>
612 613 </div>
613 614
614 615 <script type="text/javascript">process_dates()</script>
615 616
616 617
617 618 </body>
618 619 </html>
619 620
620 621 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/filediff/1/foo/?style=raw'
621 622 200 Script output follows
622 623
623 624
624 625 diff -r 000000000000 -r a4f92ed23982 foo
625 626 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
626 627 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
627 628 @@ -0,0 +1,1 @@
628 629 +foo
629 630
630 631
631 632
632 633
633 634
634 635 Overviews
635 636
636 637 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-tags'
637 638 200 Script output follows
638 639
639 640 tip 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
640 641 1.0 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
641 642 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-branches'
642 643 200 Script output follows
643 644
644 645 stable 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe open
645 646 default a4f92ed23982be056b9852de5dfe873eaac7f0de inactive
646 647 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-bookmarks'
647 648 200 Script output follows
648 649
649 650 anotherthing 2ef0ac749a14e4f57a5a822464a0902c6f7f448f
650 651 something 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
651 652 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/summary/?style=gitweb'
652 653 200 Script output follows
653 654
654 655 <?xml version="1.0" encoding="ascii"?>
655 656 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
656 657 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
657 658 <head>
658 659 <link rel="icon" href="/static/hgicon.png" type="image/png" />
659 660 <meta name="robots" content="index, nofollow"/>
660 661 <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
661 662 <script type="text/javascript" src="/static/mercurial.js"></script>
662 663
663 664 <title>test: Summary</title>
664 665 <link rel="alternate" type="application/atom+xml"
665 666 href="/atom-log" title="Atom feed for test"/>
666 667 <link rel="alternate" type="application/rss+xml"
667 668 href="/rss-log" title="RSS feed for test"/>
668 669 </head>
669 670 <body>
670 671
671 672 <div class="page_header">
672 673 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="/summary?style=gitweb">test</a> / summary
673 674
674 675 <form action="/log">
675 676 <input type="hidden" name="style" value="gitweb" />
676 677 <div class="search">
677 678 <input type="text" name="rev" />
678 679 </div>
679 680 </form>
680 681 </div>
681 682
682 683 <div class="page_nav">
683 684 summary |
684 685 <a href="/shortlog?style=gitweb">shortlog</a> |
685 686 <a href="/log?style=gitweb">changelog</a> |
686 687 <a href="/graph?style=gitweb">graph</a> |
687 688 <a href="/tags?style=gitweb">tags</a> |
688 689 <a href="/bookmarks?style=gitweb">bookmarks</a> |
689 690 <a href="/branches?style=gitweb">branches</a> |
690 691 <a href="/file/1d22e65f027e?style=gitweb">files</a> |
691 692 <a href="/help?style=gitweb">help</a>
692 693 <br/>
693 694 </div>
694 695
695 696 <div class="title">&nbsp;</div>
696 697 <table cellspacing="0">
697 698 <tr><td>description</td><td>unknown</td></tr>
698 699 <tr><td>owner</td><td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td></tr>
699 700 <tr><td>last change</td><td>Thu, 01 Jan 1970 00:00:00 +0000</td></tr>
700 701 </table>
701 702
702 703 <div><a class="title" href="/shortlog?style=gitweb">changes</a></div>
703 704 <table cellspacing="0">
704 705
705 706 <tr class="parity0">
706 707 <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
707 708 <td><i>test</i></td>
708 709 <td>
709 710 <a class="list" href="/rev/1d22e65f027e?style=gitweb">
710 711 <b>branch</b>
711 712 <span class="logtags"><span class="branchtag" title="stable">stable</span> <span class="tagtag" title="tip">tip</span> <span class="bookmarktag" title="something">something</span> </span>
712 713 </a>
713 714 </td>
714 715 <td class="link" nowrap>
715 716 <a href="/rev/1d22e65f027e?style=gitweb">changeset</a> |
716 717 <a href="/file/1d22e65f027e?style=gitweb">files</a>
717 718 </td>
718 719 </tr>
719 720 <tr class="parity1">
720 721 <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
721 722 <td><i>test</i></td>
722 723 <td>
723 724 <a class="list" href="/rev/a4f92ed23982?style=gitweb">
724 725 <b>Added tag 1.0 for changeset 2ef0ac749a14</b>
725 726 <span class="logtags"><span class="branchtag" title="default">default</span> </span>
726 727 </a>
727 728 </td>
728 729 <td class="link" nowrap>
729 730 <a href="/rev/a4f92ed23982?style=gitweb">changeset</a> |
730 731 <a href="/file/a4f92ed23982?style=gitweb">files</a>
731 732 </td>
732 733 </tr>
733 734 <tr class="parity0">
734 735 <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
735 736 <td><i>test</i></td>
736 737 <td>
737 738 <a class="list" href="/rev/2ef0ac749a14?style=gitweb">
738 739 <b>base</b>
739 740 <span class="logtags"><span class="tagtag" title="1.0">1.0</span> <span class="bookmarktag" title="anotherthing">anotherthing</span> </span>
740 741 </a>
741 742 </td>
742 743 <td class="link" nowrap>
743 744 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
744 745 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
745 746 </td>
746 747 </tr>
747 748 <tr class="light"><td colspan="4"><a class="list" href="/shortlog?style=gitweb">...</a></td></tr>
748 749 </table>
749 750
750 751 <div><a class="title" href="/tags?style=gitweb">tags</a></div>
751 752 <table cellspacing="0">
752 753
753 754 <tr class="parity0">
754 755 <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
755 756 <td><a class="list" href="/rev/2ef0ac749a14?style=gitweb"><b>1.0</b></a></td>
756 757 <td class="link">
757 758 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
758 759 <a href="/log/2ef0ac749a14?style=gitweb">changelog</a> |
759 760 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
760 761 </td>
761 762 </tr>
762 763 <tr class="light"><td colspan="3"><a class="list" href="/tags?style=gitweb">...</a></td></tr>
763 764 </table>
764 765
765 766 <div><a class="title" href="/bookmarks?style=gitweb">bookmarks</a></div>
766 767 <table cellspacing="0">
767 768
768 769 <tr class="parity0">
769 770 <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
770 771 <td><a class="list" href="/rev/2ef0ac749a14?style=gitweb"><b>anotherthing</b></a></td>
771 772 <td class="link">
772 773 <a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
773 774 <a href="/log/2ef0ac749a14?style=gitweb">changelog</a> |
774 775 <a href="/file/2ef0ac749a14?style=gitweb">files</a>
775 776 </td>
776 777 </tr>
777 778 <tr class="parity1">
778 779 <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
779 780 <td><a class="list" href="/rev/1d22e65f027e?style=gitweb"><b>something</b></a></td>
780 781 <td class="link">
781 782 <a href="/rev/1d22e65f027e?style=gitweb">changeset</a> |
782 783 <a href="/log/1d22e65f027e?style=gitweb">changelog</a> |
783 784 <a href="/file/1d22e65f027e?style=gitweb">files</a>
784 785 </td>
785 786 </tr>
786 787 <tr class="light"><td colspan="3"><a class="list" href="/bookmarks?style=gitweb">...</a></td></tr>
787 788 </table>
788 789
789 790 <div><a class="title" href="#">branches</a></div>
790 791 <table cellspacing="0">
791 792
792 793 <tr class="parity0">
793 794 <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
794 795 <td><a class="list" href="/shortlog/1d22e65f027e?style=gitweb"><b>1d22e65f027e</b></a></td>
795 796 <td class="">stable</td>
796 797 <td class="link">
797 798 <a href="/changeset/1d22e65f027e?style=gitweb">changeset</a> |
798 799 <a href="/log/1d22e65f027e?style=gitweb">changelog</a> |
799 800 <a href="/file/1d22e65f027e?style=gitweb">files</a>
800 801 </td>
801 802 </tr>
802 803 <tr class="parity1">
803 804 <td class="age"><i class="age">Thu, 01 Jan 1970 00:00:00 +0000</i></td>
804 805 <td><a class="list" href="/shortlog/a4f92ed23982?style=gitweb"><b>a4f92ed23982</b></a></td>
805 806 <td class="">default</td>
806 807 <td class="link">
807 808 <a href="/changeset/a4f92ed23982?style=gitweb">changeset</a> |
808 809 <a href="/log/a4f92ed23982?style=gitweb">changelog</a> |
809 810 <a href="/file/a4f92ed23982?style=gitweb">files</a>
810 811 </td>
811 812 </tr>
812 813 <tr class="light">
813 814 <td colspan="4"><a class="list" href="#">...</a></td>
814 815 </tr>
815 816 </table>
816 817 <script type="text/javascript">process_dates()</script>
817 818 <div class="page_footer">
818 819 <div class="page_footer_text">test</div>
819 820 <div class="rss_logo">
820 821 <a href="/rss-log">RSS</a>
821 822 <a href="/atom-log">Atom</a>
822 823 </div>
823 824 <br />
824 825
825 826 </div>
826 827 </body>
827 828 </html>
828 829
829 830 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/?style=gitweb'
830 831 200 Script output follows
831 832
832 833 <?xml version="1.0" encoding="ascii"?>
833 834 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
834 835 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
835 836 <head>
836 837 <link rel="icon" href="/static/hgicon.png" type="image/png" />
837 838 <meta name="robots" content="index, nofollow"/>
838 839 <link rel="stylesheet" href="/static/style-gitweb.css" type="text/css" />
839 840 <script type="text/javascript" src="/static/mercurial.js"></script>
840 841
841 842 <title>test: Graph</title>
842 843 <link rel="alternate" type="application/atom+xml"
843 844 href="/atom-log" title="Atom feed for test"/>
844 845 <link rel="alternate" type="application/rss+xml"
845 846 href="/rss-log" title="RSS feed for test"/>
846 847 <!--[if IE]><script type="text/javascript" src="/static/excanvas.js"></script><![endif]-->
847 848 </head>
848 849 <body>
849 850
850 851 <div class="page_header">
851 852 <a href="http://mercurial.selenic.com/" title="Mercurial" style="float: right;">Mercurial</a><a href="/summary?style=gitweb">test</a> / graph
852 853 </div>
853 854
854 855 <form action="/log">
855 856 <input type="hidden" name="style" value="gitweb" />
856 857 <div class="search">
857 858 <input type="text" name="rev" />
858 859 </div>
859 860 </form>
860 861 <div class="page_nav">
861 862 <a href="/summary?style=gitweb">summary</a> |
862 863 <a href="/shortlog?style=gitweb">shortlog</a> |
863 864 <a href="/log/2?style=gitweb">changelog</a> |
864 865 graph |
865 866 <a href="/tags?style=gitweb">tags</a> |
866 867 <a href="/bookmarks?style=gitweb">bookmarks</a> |
867 868 <a href="/branches?style=gitweb">branches</a> |
868 869 <a href="/file/1d22e65f027e?style=gitweb">files</a> |
869 870 <a href="/help?style=gitweb">help</a>
870 871 <br/>
871 872 <a href="/graph/2?style=gitweb&revcount=30">less</a>
872 873 <a href="/graph/2?style=gitweb&revcount=120">more</a>
873 874 | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-2</a> <a href="/graph/tip?style=gitweb">tip</a> <br/>
874 875 </div>
875 876
876 877 <div class="title">&nbsp;</div>
877 878
878 879 <noscript>The revision graph only works with JavaScript-enabled browsers.</noscript>
879 880
880 881 <div id="wrapper">
881 882 <ul id="nodebgs"></ul>
882 883 <canvas id="graph" width="480" height="129"></canvas>
883 884 <ul id="graphnodes"></ul>
884 885 </div>
885 886
886 887 <script>
887 888 <!-- hide script content
888 889
889 890 var data = [["1d22e65f027e", [0, 1], [[0, 0, 1]], "branch", "test", "1970-01-01", ["stable", true], ["tip"], ["something"]], ["a4f92ed23982", [0, 1], [[0, 0, 1]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], ["anotherthing"]]];
890 891 var graph = new Graph();
891 892 graph.scale(39);
892 893
893 894 graph.edge = function(x0, y0, x1, y1, color) {
894 895
895 896 this.setColor(color, 0.0, 0.65);
896 897 this.ctx.beginPath();
897 898 this.ctx.moveTo(x0, y0);
898 899 this.ctx.lineTo(x1, y1);
899 900 this.ctx.stroke();
900 901
901 902 }
902 903
903 904 var revlink = '<li style="_STYLE"><span class="desc">';
904 905 revlink += '<a class="list" href="/rev/_NODEID?style=gitweb" title="_NODEID"><b>_DESC</b></a>';
905 906 revlink += '</span> _TAGS';
906 907 revlink += '<span class="info">_DATE, by _USER</span></li>';
907 908
908 909 graph.vertex = function(x, y, color, parity, cur) {
909 910
910 911 this.ctx.beginPath();
911 912 color = this.setColor(color, 0.25, 0.75);
912 913 this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
913 914 this.ctx.fill();
914 915
915 916 var bg = '<li class="bg parity' + parity + '"></li>';
916 917 var left = (this.columns + 1) * this.bg_height;
917 918 var nstyle = 'padding-left: ' + left + 'px;';
918 919 var item = revlink.replace(/_STYLE/, nstyle);
919 920 item = item.replace(/_PARITY/, 'parity' + parity);
920 921 item = item.replace(/_NODEID/, cur[0]);
921 922 item = item.replace(/_NODEID/, cur[0]);
922 923 item = item.replace(/_DESC/, cur[3]);
923 924 item = item.replace(/_USER/, cur[4]);
924 925 item = item.replace(/_DATE/, cur[5]);
925 926
926 927 var tagspan = '';
927 928 if (cur[7].length || cur[8].length || (cur[6][0] != 'default' || cur[6][1])) {
928 929 tagspan = '<span class="logtags">';
929 930 if (cur[6][1]) {
930 931 tagspan += '<span class="branchtag" title="' + cur[6][0] + '">';
931 932 tagspan += cur[6][0] + '</span> ';
932 933 } else if (!cur[6][1] && cur[6][0] != 'default') {
933 934 tagspan += '<span class="inbranchtag" title="' + cur[6][0] + '">';
934 935 tagspan += cur[6][0] + '</span> ';
935 936 }
936 937 if (cur[7].length) {
937 938 for (var t in cur[7]) {
938 939 var tag = cur[7][t];
939 940 tagspan += '<span class="tagtag">' + tag + '</span> ';
940 941 }
941 942 }
942 943 if (cur[8].length) {
943 944 for (var t in cur[8]) {
944 945 var bookmark = cur[8][t];
945 946 tagspan += '<span class="bookmarktag">' + bookmark + '</span> ';
946 947 }
947 948 }
948 949 tagspan += '</span>';
949 950 }
950 951
951 952 item = item.replace(/_TAGS/, tagspan);
952 953 return [bg, item];
953 954
954 955 }
955 956
956 957 graph.render(data);
957 958
958 959 // stop hiding script -->
959 960 </script>
960 961
961 962 <div class="page_nav">
962 963 <a href="/graph/2?style=gitweb&revcount=30">less</a>
963 964 <a href="/graph/2?style=gitweb&revcount=120">more</a>
964 965 | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/2ef0ac749a14?style=gitweb">-2</a> <a href="/graph/tip?style=gitweb">tip</a>
965 966 </div>
966 967
967 968 <script type="text/javascript">process_dates()</script>
968 969 <div class="page_footer">
969 970 <div class="page_footer_text">test</div>
970 971 <div class="rss_logo">
971 972 <a href="/rss-log">RSS</a>
972 973 <a href="/atom-log">Atom</a>
973 974 </div>
974 975 <br />
975 976
976 977 </div>
977 978 </body>
978 979 </html>
979 980
980 981
981 982 capabilities
982 983
983 984 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=capabilities'; echo
984 985 200 Script output follows
985 986
986 987 lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024
987 988
988 989 heads
989 990
990 991 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=heads'
991 992 200 Script output follows
992 993
993 994 1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
994 995
995 996 branches
996 997
997 998 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=branches&nodes=0000000000000000000000000000000000000000'
998 999 200 Script output follows
999 1000
1000 1001 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
1001 1002
1002 1003 changegroup
1003 1004
1004 1005 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=changegroup&roots=0000000000000000000000000000000000000000'
1005 1006 200 Script output follows
1006 1007
1007 1008 x\x9c\xbdTMHUA\x14\xbe\xa8\xf9\xec\xda&\x10\x11*\xb8\x88\x81\x99\xbef\xe6\xce\xbdw\xc6\xf2a\x16E\x1b\x11[%\x98\xcc\xaf\x8f\x8c\xf7\xc0\xf7\x82 (esc)
1008 1009 4\x11KP2m\x95\xad*\xabE\x05AP\xd0\xc22Z\x14\xf9\x03\xb9j\xa3\x9b$\xa4MJ\xb4\x90\xc0\x9a\x9bO0\x10\xdf\x13\xa2\x81\x0f\x869g\xe6|\xe7\x9c\xef\x8ceY\xf7\xa2KO\xd2\xb7K\x16~\\n\xe9\xad\x90w\x86\xab\x93W\x8e\xdf\xb0r\\Y\xee6(\xa2)\xf6\x95\xc6\x01\xe4\x1az\x80R\xe8kN\x98\xe7R\xa4\xa9K@\xe0!A\xb4k\xa7U*m\x03\x07\xd8\x92\x1d\xd2\xc9\xa4\x1d\xc2\xe6,\xa5\xcc+\x1f\xef\xafDgi\xef\xab\x1d\x1d\xb7\x9a\xe7[W\xfbc\x8f\xde-\xcd\xe7\xcaz\xb3\xbb\x19\xd3\x81\x10>c>\x08\x00"X\x11\xc2\x84@\xd2\xe7B*L\x00\x01P\x04R\xc3@\xbaB0\xdb8#\x83:\x83\xa2h\xbc=\xcd\xdaS\xe1Y,L\xd3\xa0\xf2\xa8\x94J:\xe6\xd8\x81Q\xe0\xe8d\xa7#\xe2,\xd1\xaeR*\xed \xa5\x01\x13\x01\xa6\x0cb\xe3;\xbe\xaf\xfcK[^wK\xe1N\xaf\xbbk\xe8B\xd1\xf4\xc1\x07\xb3\xab[\x10\xfdkmvwcB\xa6\xa4\xd4G\xc4D\xc2\x141\xad\x91\x10\x00\x08J\x81\xcb}\xee \xee+W\xba\x8a\x80\x90|\xd4\xa0\xd6\xa0\xd4T\xde\xe1\x9d,!\xe2\xb5\xa94\xe3\xe7\xd5\x9f\x06\x18\xcba\x03aP\xb8f\xcd\x04\x1a_\\9\xf1\xed\xe4\x9e\xe5\xa6\xd1\xd2\x9f\x03\xa7o\xae\x90H\xf3\xfb\xef\xffH3\xadk (esc)
1009 1010 \xb0\x90\x92\x88\xb9\x14"\x068\xc2\x1e@\x00\xbb\x8a)\xd3'\x859 (esc)
1010 1011 \xa8\x80\x84S \xa5\xbd-g\x13`\xe4\xdc\xc3H^\xdf\xe2\xc0TM\xc7\xf4BO\xcf\xde\xae\xe5\xae#\x1frM(K\x97`F\x19\x16s\x05GD\xb9\x01\xc1\x00+\x8c|\x9fp\xc11\xf0\x14\x00\x9cJ\x82<\xe0\x12\x9f\xc1\x90\xd0\xf5\xc8\x19>Pr\xaa\xeaW\xf5\xc4\xae\xd1\xfc\x17\xcf'\x13u\xb1\x9e\xcdHnC\x0e\xcc`\xc8\xa0&\xac\x0e\xf1|\x8c\x10$\xc4\x8c\xa2p\x05`\xdc\x08 \x80\xc4\xd7Rr-\x94\x10\x102\xedi;\xf3f\xf1z\x16\x86\xdb\xd8d\xe5\xe7\x8b\xf5\x8d\rzp\xb2\xfe\xac\xf5\xf2\xd3\xfe\xfckws\xedt\x96b\xd5l\x1c\x0b\x85\xb5\x170\x8f\x11\x84\xb0\x8f\x19\xa0\x00 _\x07\x1ac\xa2\xc3\x89Z\xe7\x96\xf9 \xccNFg\xc7F\xaa\x8a+\x9a\x9cc_\x17\x1b\x17\x9e]z38<\x97+\xb5,",\xc8\xc8?\\\x91\xff\x17.~U\x96\x97\xf5%\xdeN<\x8e\xf5\x97%\xe7^\xcfL\xed~\xda\x96k\xdc->\x86\x02\x83"\x96H\xa6\xe3\xaas=-\xeb7\xe5\xda\x8f\xbc (no-eol) (esc)
1011 1012
1012 1013 stream_out
1013 1014
1014 1015 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=stream_out'
1015 1016 200 Script output follows
1016 1017
1017 1018 1
1018 1019
1019 1020 failing unbundle, requires POST request
1020 1021
1021 1022 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=unbundle'
1022 1023 405 push requires POST request
1023 1024
1024 1025 0
1025 1026 push requires POST request
1026 1027 [1]
1027 1028
1028 1029 Static files
1029 1030
1030 1031 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/static/style.css'
1031 1032 200 Script output follows
1032 1033
1033 1034 a { text-decoration:none; }
1034 1035 .age { white-space:nowrap; }
1035 1036 .date { white-space:nowrap; }
1036 1037 .indexlinks { white-space:nowrap; }
1037 1038 .parity0 { background-color: #ddd; }
1038 1039 .parity1 { background-color: #eee; }
1039 1040 .lineno { width: 60px; color: #aaa; font-size: smaller;
1040 1041 text-align: right; }
1041 1042 .plusline { color: green; }
1042 1043 .minusline { color: red; }
1043 1044 .atline { color: purple; }
1044 1045 .annotate { font-size: smaller; text-align: right; padding-right: 1em; }
1045 1046 .buttons a {
1046 1047 background-color: #666;
1047 1048 padding: 2pt;
1048 1049 color: white;
1049 1050 font-family: sans;
1050 1051 font-weight: bold;
1051 1052 }
1052 1053 .navigate a {
1053 1054 background-color: #ccc;
1054 1055 padding: 2pt;
1055 1056 font-family: sans;
1056 1057 color: black;
1057 1058 }
1058 1059
1059 1060 .metatag {
1060 1061 background-color: #888;
1061 1062 color: white;
1062 1063 text-align: right;
1063 1064 }
1064 1065
1065 1066 /* Common */
1066 1067 pre { margin: 0; }
1067 1068
1068 1069 .logo {
1069 1070 float: right;
1070 1071 clear: right;
1071 1072 }
1072 1073
1073 1074 /* Changelog/Filelog entries */
1074 1075 .logEntry { width: 100%; }
1075 1076 .logEntry .age { width: 15%; }
1076 1077 .logEntry th { font-weight: normal; text-align: right; vertical-align: top; }
1077 1078 .logEntry th.age, .logEntry th.firstline { font-weight: bold; }
1078 1079 .logEntry th.firstline { text-align: left; width: inherit; }
1079 1080
1080 1081 /* Shortlog entries */
1081 1082 .slogEntry { width: 100%; }
1082 1083 .slogEntry .age { width: 8em; }
1083 1084 .slogEntry td { font-weight: normal; text-align: left; vertical-align: top; }
1084 1085 .slogEntry td.author { width: 15em; }
1085 1086
1086 1087 /* Tag entries */
1087 1088 #tagEntries { list-style: none; margin: 0; padding: 0; }
1088 1089 #tagEntries .tagEntry { list-style: none; margin: 0; padding: 0; }
1089 1090
1090 1091 /* Changeset entry */
1091 1092 #changesetEntry { }
1092 1093 #changesetEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
1093 1094 #changesetEntry th.files, #changesetEntry th.description { vertical-align: top; }
1094 1095
1095 1096 /* File diff view */
1096 1097 #filediffEntry { }
1097 1098 #filediffEntry th { font-weight: normal; background-color: #888; color: #fff; text-align: right; }
1098 1099
1099 1100 /* Graph */
1100 1101 div#wrapper {
1101 1102 position: relative;
1102 1103 margin: 0;
1103 1104 padding: 0;
1104 1105 }
1105 1106
1106 1107 canvas {
1107 1108 position: absolute;
1108 1109 z-index: 5;
1109 1110 top: -0.6em;
1110 1111 margin: 0;
1111 1112 }
1112 1113
1113 1114 ul#nodebgs {
1114 1115 list-style: none inside none;
1115 1116 padding: 0;
1116 1117 margin: 0;
1117 1118 top: -0.7em;
1118 1119 }
1119 1120
1120 1121 ul#graphnodes li, ul#nodebgs li {
1121 1122 height: 39px;
1122 1123 }
1123 1124
1124 1125 ul#graphnodes {
1125 1126 position: absolute;
1126 1127 z-index: 10;
1127 1128 top: -0.85em;
1128 1129 list-style: none inside none;
1129 1130 padding: 0;
1130 1131 }
1131 1132
1132 1133 ul#graphnodes li .info {
1133 1134 display: block;
1134 1135 font-size: 70%;
1135 1136 position: relative;
1136 1137 top: -1px;
1137 1138 }
1138 1139
1139 1140 Stop and restart with HGENCODING=cp932
1140 1141
1141 1142 $ "$TESTDIR/killdaemons.py"
1142 1143 $ HGENCODING=cp932 hg serve --config server.uncompressed=False -n test \
1143 1144 > -p $HGPORT -d --pid-file=hg.pid -E errors.log
1144 1145 $ cat hg.pid >> $DAEMON_PIDS
1145 1146
1146 1147 commit message with Japanese Kanji 'Noh', which ends with '\x5c'
1147 1148
1148 1149 $ echo foo >> foo
1149 1150 $ HGENCODING=cp932 hg ci -m `python -c 'print("\x94\x5c")'`
1150 1151
1151 1152 Graph json escape of multibyte character
1152 1153
1153 1154 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/' \
1154 1155 > | grep '^var data ='
1155 1156 var data = [["40b4d6888e92", [0, 1], [[0, 0, 1]], "\u80fd", "test", "1970-01-01", ["stable", true], ["tip"], ["something"]], ["1d22e65f027e", [0, 1], [[0, 0, 1]], "branch", "test", "1970-01-01", ["stable", false], [], []], ["a4f92ed23982", [0, 1], [[0, 0, 1]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], ["anotherthing"]]];
1156 1157
1157 1158 ERRORS ENCOUNTERED
1158 1159
1159 1160 $ cat errors.log
@@ -1,93 +1,94 b''
1 1 $ "$TESTDIR/hghave" serve || exit 80
2 2
3 3 $ hgserve() {
4 4 > hg serve -a localhost -p $HGPORT1 -d --pid-file=hg.pid -E errors.log -v $@
5 5 > cat hg.pid >> "$DAEMON_PIDS"
6 6 > }
7 7 $ hg init a
8 8 $ hg --encoding utf-8 -R a branch æ
9 9 marked working directory as branch \xc3\xa6 (esc)
10 (branches are permanent and global, did you want a bookmark?)
10 11 $ echo foo > a/foo
11 12 $ hg -R a ci -Am foo
12 13 adding foo
13 14 $ hgserve -R a --config web.push_ssl=False --config web.allow_push=* --encoding latin1
14 15 listening at http://*:$HGPORT1/ (bound to 127.0.0.1:$HGPORT1) (glob)
15 16 $ hg --encoding utf-8 clone http://localhost:$HGPORT1 b
16 17 requesting all changes
17 18 adding changesets
18 19 adding manifests
19 20 adding file changes
20 21 added 1 changesets with 1 changes to 1 files
21 22 updating to branch \xc3\xa6 (esc)
22 23 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
23 24 $ hg --encoding utf-8 -R b log
24 25 changeset: 0:867c11ce77b8
25 26 branch: \xc3\xa6 (esc)
26 27 tag: tip
27 28 user: test
28 29 date: Thu Jan 01 00:00:00 1970 +0000
29 30 summary: foo
30 31
31 32 $ echo bar >> b/foo
32 33 $ hg -R b ci -m bar
33 34 $ hg --encoding utf-8 -R b push
34 35 pushing to http://localhost:$HGPORT1/
35 36 searching for changes
36 37 remote: adding changesets
37 38 remote: adding manifests
38 39 remote: adding file changes
39 40 remote: added 1 changesets with 1 changes to 1 files
40 41 $ hg -R a --encoding utf-8 log
41 42 changeset: 1:58e7c90d67cb
42 43 branch: \xc3\xa6 (esc)
43 44 tag: tip
44 45 user: test
45 46 date: Thu Jan 01 00:00:00 1970 +0000
46 47 summary: bar
47 48
48 49 changeset: 0:867c11ce77b8
49 50 branch: \xc3\xa6 (esc)
50 51 user: test
51 52 date: Thu Jan 01 00:00:00 1970 +0000
52 53 summary: foo
53 54
54 55 $ kill `cat hg.pid`
55 56
56 57 verify 7e7d56fe4833 (encoding fallback in branchmap to maintain compatibility with 1.3.x)
57 58
58 59 $ cat <<EOF > oldhg
59 60 > import sys
60 61 > from mercurial import ui, hg, commands
61 62 >
62 63 > class StdoutWrapper(object):
63 64 > def __init__(self, stdout):
64 65 > self._file = stdout
65 66 >
66 67 > def write(self, data):
67 68 > if data == '47\n':
68 69 > # latin1 encoding is one %xx (3 bytes) shorter
69 70 > data = '44\n'
70 71 > elif data.startswith('%C3%A6 '):
71 72 > # translate to latin1 encoding
72 73 > data = '%%E6 %s' % data[7:]
73 74 > self._file.write(data)
74 75 >
75 76 > def __getattr__(self, name):
76 77 > return getattr(self._file, name)
77 78 >
78 79 > sys.stdout = StdoutWrapper(sys.stdout)
79 80 > sys.stderr = StdoutWrapper(sys.stderr)
80 81 >
81 82 > myui = ui.ui()
82 83 > repo = hg.repository(myui, 'a')
83 84 > commands.serve(myui, repo, stdio=True, cmdserver=False)
84 85 > EOF
85 86 $ echo baz >> b/foo
86 87 $ hg -R b ci -m baz
87 88 $ hg push -R b -e 'python oldhg' ssh://dummy/ --encoding latin1
88 89 pushing to ssh://dummy/
89 90 searching for changes
90 91 remote: adding changesets
91 92 remote: adding manifests
92 93 remote: adding file changes
93 94 remote: added 1 changesets with 1 changes to 1 files
@@ -1,56 +1,57 b''
1 1 $ cat >findbranch.py <<EOF
2 2 > import re, sys
3 3 >
4 4 > head_re = re.compile('^#(?:(?:\\s+([A-Za-z][A-Za-z0-9_]*)(?:\\s.*)?)|(?:\\s*))$')
5 5 >
6 6 > for line in sys.stdin:
7 7 > hmatch = head_re.match(line)
8 8 > if not hmatch:
9 9 > sys.exit(1)
10 10 > if hmatch.group(1) == 'Branch':
11 11 > sys.exit(0)
12 12 > sys.exit(1)
13 13 > EOF
14 14
15 15 $ hg init a
16 16 $ cd a
17 17 $ echo "Rev 1" >rev
18 18 $ hg add rev
19 19 $ hg commit -m "No branch."
20 20 $ hg branch abranch
21 21 marked working directory as branch abranch
22 (branches are permanent and global, did you want a bookmark?)
22 23 $ echo "Rev 2" >rev
23 24 $ hg commit -m "With branch."
24 25
25 26 $ hg export 0 > ../r0.patch
26 27 $ hg export 1 > ../r1.patch
27 28 $ cd ..
28 29
29 30 $ if python findbranch.py < r0.patch; then
30 31 > echo "Export of default branch revision has Branch header" 1>&2
31 32 > exit 1
32 33 > fi
33 34
34 35 $ if python findbranch.py < r1.patch; then
35 36 > : # Do nothing
36 37 > else
37 38 > echo "Export of branch revision is missing Branch header" 1>&2
38 39 > exit 1
39 40 > fi
40 41
41 42 Make sure import still works with branch information in patches.
42 43
43 44 $ hg init b
44 45 $ cd b
45 46 $ hg import ../r0.patch
46 47 applying ../r0.patch
47 48 $ hg import ../r1.patch
48 49 applying ../r1.patch
49 50 $ cd ..
50 51
51 52 $ hg init c
52 53 $ cd c
53 54 $ hg import --exact ../r0.patch
54 55 applying ../r0.patch
55 56 $ hg import --exact ../r1.patch
56 57 applying ../r1.patch
@@ -1,258 +1,259 b''
1 1 $ "$TESTDIR/hghave" symlink execbit || exit 80
2 2
3 3 $ echo "[extensions]" >> $HGRCPATH
4 4 $ echo "purge=" >> $HGRCPATH
5 5 $ echo "graphlog=" >> $HGRCPATH
6 6
7 7 $ shortlog() {
8 8 > hg glog --template '{rev}:{node|short} {author} {date|hgdate} - {branch} - {desc|firstline}\n'
9 9 > }
10 10
11 11 Test --bypass with other options
12 12
13 13 $ hg init repo-options
14 14 $ cd repo-options
15 15 $ echo a > a
16 16 $ hg ci -Am adda
17 17 adding a
18 18 $ echo a >> a
19 19 $ hg branch foo
20 20 marked working directory as branch foo
21 (branches are permanent and global, did you want a bookmark?)
21 22 $ hg ci -Am changea
22 23 $ hg export . > ../test.diff
23 24 $ hg up null
24 25 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
25 26
26 27 Test importing an existing revision
27 28
28 29 $ hg import --bypass --exact ../test.diff
29 30 applying ../test.diff
30 31 $ shortlog
31 32 o 1:4e322f7ce8e3 test 0 0 - foo - changea
32 33 |
33 34 o 0:07f494440405 test 0 0 - default - adda
34 35
35 36
36 37 Test failure without --exact
37 38
38 39 $ hg import --bypass ../test.diff
39 40 applying ../test.diff
40 41 unable to find 'a' for patching
41 42 abort: patch failed to apply
42 43 [255]
43 44 $ hg st
44 45 $ shortlog
45 46 o 1:4e322f7ce8e3 test 0 0 - foo - changea
46 47 |
47 48 o 0:07f494440405 test 0 0 - default - adda
48 49
49 50
50 51 Test --user, --date and --message
51 52
52 53 $ hg up 0
53 54 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
54 55 $ hg import --bypass --u test2 -d '1 0' -m patch2 ../test.diff
55 56 applying ../test.diff
56 57 $ cat .hg/last-message.txt
57 58 patch2 (no-eol)
58 59 $ shortlog
59 60 o 2:2e127d1da504 test2 1 0 - default - patch2
60 61 |
61 62 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
62 63 |/
63 64 @ 0:07f494440405 test 0 0 - default - adda
64 65
65 66 $ hg rollback
66 67 repository tip rolled back to revision 1 (undo import)
67 68
68 69 Test --import-branch
69 70
70 71 $ hg import --bypass --import-branch ../test.diff
71 72 applying ../test.diff
72 73 $ shortlog
73 74 o 1:4e322f7ce8e3 test 0 0 - foo - changea
74 75 |
75 76 @ 0:07f494440405 test 0 0 - default - adda
76 77
77 78 $ hg rollback
78 79 repository tip rolled back to revision 1 (undo import)
79 80
80 81 Test --strip
81 82
82 83 $ hg import --bypass --strip 0 - <<EOF
83 84 > # HG changeset patch
84 85 > # User test
85 86 > # Date 0 0
86 87 > # Branch foo
87 88 > # Node ID 4e322f7ce8e3e4203950eac9ece27bf7e45ffa6c
88 89 > # Parent 07f4944404050f47db2e5c5071e0e84e7a27bba9
89 90 > changea
90 91 >
91 92 > diff -r 07f494440405 -r 4e322f7ce8e3 a
92 93 > --- a Thu Jan 01 00:00:00 1970 +0000
93 94 > +++ a Thu Jan 01 00:00:00 1970 +0000
94 95 > @@ -1,1 +1,2 @@
95 96 > a
96 97 > +a
97 98 > EOF
98 99 applying patch from stdin
99 100 $ hg rollback
100 101 repository tip rolled back to revision 1 (undo import)
101 102
102 103 Test unsupported combinations
103 104
104 105 $ hg import --bypass --no-commit ../test.diff
105 106 abort: cannot use --no-commit with --bypass
106 107 [255]
107 108 $ hg import --bypass --similarity 50 ../test.diff
108 109 abort: cannot use --similarity with --bypass
109 110 [255]
110 111
111 112 Test commit editor
112 113
113 114 $ hg diff -c 1 > ../test.diff
114 115 $ HGEDITOR=cat hg import --bypass ../test.diff
115 116 applying ../test.diff
116 117
117 118
118 119 HG: Enter commit message. Lines beginning with 'HG:' are removed.
119 120 HG: Leave message empty to abort commit.
120 121 HG: --
121 122 HG: user: test
122 123 HG: branch 'default'
123 124 HG: changed a
124 125 abort: empty commit message
125 126 [255]
126 127
127 128 Test patch.eol is handled
128 129
129 130 $ python -c 'file("a", "wb").write("a\r\n")'
130 131 $ hg ci -m makeacrlf
131 132 $ hg import -m 'should fail because of eol' --bypass ../test.diff
132 133 applying ../test.diff
133 134 patching file a
134 135 Hunk #1 FAILED at 0
135 136 abort: patch failed to apply
136 137 [255]
137 138 $ hg --config patch.eol=auto import -d '0 0' -m 'test patch.eol' --bypass ../test.diff
138 139 applying ../test.diff
139 140 $ shortlog
140 141 o 3:d7805b4d2cb3 test 0 0 - default - test patch.eol
141 142 |
142 143 @ 2:872023de769d test 0 0 - default - makeacrlf
143 144 |
144 145 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
145 146 |/
146 147 o 0:07f494440405 test 0 0 - default - adda
147 148
148 149
149 150 Test applying multiple patches
150 151
151 152 $ hg up -qC 0
152 153 $ echo e > e
153 154 $ hg ci -Am adde
154 155 adding e
155 156 created new head
156 157 $ hg export . > ../patch1.diff
157 158 $ hg up -qC 1
158 159 $ echo f > f
159 160 $ hg ci -Am addf
160 161 adding f
161 162 $ hg export . > ../patch2.diff
162 163 $ cd ..
163 164 $ hg clone -r1 repo-options repo-multi1
164 165 adding changesets
165 166 adding manifests
166 167 adding file changes
167 168 added 2 changesets with 2 changes to 1 files
168 169 updating to branch foo
169 170 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
170 171 $ cd repo-multi1
171 172 $ hg up 0
172 173 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
173 174 $ hg import --bypass ../patch1.diff ../patch2.diff
174 175 applying ../patch1.diff
175 176 applying ../patch2.diff
176 177 $ shortlog
177 178 o 3:bc8ca3f8a7c4 test 0 0 - default - addf
178 179 |
179 180 o 2:16581080145e test 0 0 - default - adde
180 181 |
181 182 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
182 183 |/
183 184 @ 0:07f494440405 test 0 0 - default - adda
184 185
185 186
186 187 Test applying multiple patches with --exact
187 188
188 189 $ cd ..
189 190 $ hg clone -r1 repo-options repo-multi2
190 191 adding changesets
191 192 adding manifests
192 193 adding file changes
193 194 added 2 changesets with 2 changes to 1 files
194 195 updating to branch foo
195 196 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
196 197 $ cd repo-multi2
197 198 $ hg import --bypass --exact ../patch1.diff ../patch2.diff
198 199 applying ../patch1.diff
199 200 applying ../patch2.diff
200 201 $ shortlog
201 202 o 3:d60cb8989666 test 0 0 - foo - addf
202 203 |
203 204 | o 2:16581080145e test 0 0 - default - adde
204 205 | |
205 206 @ | 1:4e322f7ce8e3 test 0 0 - foo - changea
206 207 |/
207 208 o 0:07f494440405 test 0 0 - default - adda
208 209
209 210
210 211 $ cd ..
211 212
212 213 Test complicated patch with --exact
213 214
214 215 $ hg init repo-exact
215 216 $ cd repo-exact
216 217 $ echo a > a
217 218 $ echo c > c
218 219 $ echo d > d
219 220 $ echo e > e
220 221 $ echo f > f
221 222 $ chmod +x f
222 223 $ ln -s c linkc
223 224 $ hg ci -Am t
224 225 adding a
225 226 adding c
226 227 adding d
227 228 adding e
228 229 adding f
229 230 adding linkc
230 231 $ hg cp a aa1
231 232 $ echo b >> a
232 233 $ echo b > b
233 234 $ hg add b
234 235 $ hg cp a aa2
235 236 $ echo aa >> aa2
236 237 $ chmod +x e
237 238 $ chmod -x f
238 239 $ ln -s a linka
239 240 $ hg rm d
240 241 $ hg rm linkc
241 242 $ hg mv c cc
242 243 $ hg ci -m patch
243 244 $ hg export --git . > ../test.diff
244 245 $ hg up -C null
245 246 0 files updated, 0 files merged, 7 files removed, 0 files unresolved
246 247 $ hg purge
247 248 $ hg st
248 249 $ hg import --bypass --exact ../test.diff
249 250 applying ../test.diff
250 251
251 252 The patch should have matched the exported revision and generated no additional
252 253 data. If not, diff both heads to debug it.
253 254
254 255 $ shortlog
255 256 o 1:2978fd5c8aa4 test 0 0 - default - patch
256 257 |
257 258 o 0:a0e19e636a43 test 0 0 - default - t
258 259
@@ -1,95 +1,96 b''
1 1 http://mercurial.selenic.com/bts/issue1306
2 2
3 3 Initialize remote repo with branches:
4 4
5 5 $ hg init remote
6 6 $ cd remote
7 7
8 8 $ echo a > a
9 9 $ hg ci -Ama
10 10 adding a
11 11
12 12 $ hg branch br
13 13 marked working directory as branch br
14 (branches are permanent and global, did you want a bookmark?)
14 15 $ hg ci -Amb
15 16
16 17 $ echo c > c
17 18 $ hg ci -Amc
18 19 adding c
19 20
20 21 $ hg log
21 22 changeset: 2:ae3d9c30ec50
22 23 branch: br
23 24 tag: tip
24 25 user: test
25 26 date: Thu Jan 01 00:00:00 1970 +0000
26 27 summary: c
27 28
28 29 changeset: 1:3f7f930ca414
29 30 branch: br
30 31 user: test
31 32 date: Thu Jan 01 00:00:00 1970 +0000
32 33 summary: b
33 34
34 35 changeset: 0:cb9a9f314b8b
35 36 user: test
36 37 date: Thu Jan 01 00:00:00 1970 +0000
37 38 summary: a
38 39
39 40
40 41 $ cd ..
41 42
42 43 Try cloning -r branch:
43 44
44 45 $ hg clone -rbr remote local1
45 46 adding changesets
46 47 adding manifests
47 48 adding file changes
48 49 added 3 changesets with 2 changes to 2 files
49 50 updating to branch br
50 51 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
51 52
52 53 $ hg -R local1 parents
53 54 changeset: 2:ae3d9c30ec50
54 55 branch: br
55 56 tag: tip
56 57 user: test
57 58 date: Thu Jan 01 00:00:00 1970 +0000
58 59 summary: c
59 60
60 61
61 62 Try cloning -rother clone#branch:
62 63
63 64 $ hg clone -r0 remote#br local2
64 65 adding changesets
65 66 adding manifests
66 67 adding file changes
67 68 added 3 changesets with 2 changes to 2 files
68 69 updating to branch default
69 70 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 71
71 72 $ hg -R local2 parents
72 73 changeset: 0:cb9a9f314b8b
73 74 user: test
74 75 date: Thu Jan 01 00:00:00 1970 +0000
75 76 summary: a
76 77
77 78
78 79 Try cloning -r1 clone#branch:
79 80
80 81 $ hg clone -r1 remote#br local3
81 82 adding changesets
82 83 adding manifests
83 84 adding file changes
84 85 added 3 changesets with 2 changes to 2 files
85 86 updating to branch br
86 87 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 88
88 89 $ hg -R local3 parents
89 90 changeset: 1:3f7f930ca414
90 91 branch: br
91 92 user: test
92 93 date: Thu Jan 01 00:00:00 1970 +0000
93 94 summary: b
94 95
95 96
@@ -1,29 +1,30 b''
1 1 http://mercurial.selenic.com/bts/issue619
2 2
3 3 $ hg init
4 4 $ echo a > a
5 5 $ hg ci -Ama
6 6 adding a
7 7
8 8 $ echo b > b
9 9 $ hg branch b
10 10 marked working directory as branch b
11 (branches are permanent and global, did you want a bookmark?)
11 12 $ hg ci -Amb
12 13 adding b
13 14
14 15 $ hg co -C 0
15 16 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
16 17
17 18 Fast-forward:
18 19
19 20 $ hg merge b
20 21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
21 22 (branch merge, don't forget to commit)
22 23 $ hg ci -Ammerge
23 24
24 25 Bogus fast-forward should fail:
25 26
26 27 $ hg merge b
27 28 abort: merging with a working directory ancestor has no effect
28 29 [255]
29 30
@@ -1,38 +1,39 b''
1 1 http://mercurial.selenic.com/bts/issue842
2 2
3 3 $ hg init
4 4 $ echo foo > a
5 5 $ hg ci -Ama
6 6 adding a
7 7
8 8 $ hg up -r0000
9 9 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
10 10
11 11 $ echo bar > a
12 12
13 13 Should issue new head warning:
14 14
15 15 $ hg ci -Amb
16 16 adding a
17 17 created new head
18 18
19 19 $ hg up -r0000
20 20 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
21 21
22 22 $ echo stuffy > a
23 23
24 24 Should not issue new head warning:
25 25
26 26 $ hg ci -q -Amc
27 27
28 28 $ hg up -r0000
29 29 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
30 30
31 31 $ echo crap > a
32 32 $ hg branch testing
33 33 marked working directory as branch testing
34 (branches are permanent and global, did you want a bookmark?)
34 35
35 36 Should not issue warning:
36 37
37 38 $ hg ci -q -Amd
38 39
@@ -1,1088 +1,1089 b''
1 1 $ "$TESTDIR/hghave" symlink unix-permissions serve || exit 80
2 2
3 3 $ cat <<EOF >> $HGRCPATH
4 4 > [extensions]
5 5 > keyword =
6 6 > mq =
7 7 > notify =
8 8 > record =
9 9 > transplant =
10 10 > [ui]
11 11 > interactive = true
12 12 > EOF
13 13
14 14 Run kwdemo before [keyword] files are set up
15 15 as it would succeed without uisetup otherwise
16 16
17 17 $ hg --quiet kwdemo
18 18 [extensions]
19 19 keyword =
20 20 [keyword]
21 21 demo.txt =
22 22 [keywordset]
23 23 svn = False
24 24 [keywordmaps]
25 25 Author = {author|user}
26 26 Date = {date|utcdate}
27 27 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
28 28 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
29 29 RCSFile = {file|basename},v
30 30 RCSfile = {file|basename},v
31 31 Revision = {node|short}
32 32 Source = {root}/{file},v
33 33 $Author: test $
34 34 $Date: ????/??/?? ??:??:?? $ (glob)
35 35 $Header: */demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
36 36 $Id: demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
37 37 $RCSFile: demo.txt,v $
38 38 $RCSfile: demo.txt,v $
39 39 $Revision: ???????????? $ (glob)
40 40 $Source: */demo.txt,v $ (glob)
41 41
42 42 $ hg --quiet kwdemo "Branch = {branches}"
43 43 [extensions]
44 44 keyword =
45 45 [keyword]
46 46 demo.txt =
47 47 [keywordset]
48 48 svn = False
49 49 [keywordmaps]
50 50 Branch = {branches}
51 51 $Branch: demobranch $
52 52
53 53 $ cat <<EOF >> $HGRCPATH
54 54 > [keyword]
55 55 > ** =
56 56 > b = ignore
57 57 > i = ignore
58 58 > [hooks]
59 59 > EOF
60 60 $ cp $HGRCPATH $HGRCPATH.nohooks
61 61 > cat <<EOF >> $HGRCPATH
62 62 > commit=
63 63 > commit.test=cp a hooktest
64 64 > EOF
65 65
66 66 $ hg init Test-bndl
67 67 $ cd Test-bndl
68 68
69 69 kwshrink should exit silently in empty/invalid repo
70 70
71 71 $ hg kwshrink
72 72
73 73 Symlinks cannot be created on Windows.
74 74 A bundle to test this was made with:
75 75 hg init t
76 76 cd t
77 77 echo a > a
78 78 ln -s a sym
79 79 hg add sym
80 80 hg ci -m addsym -u mercurial
81 81 hg bundle --base null ../test-keyword.hg
82 82
83 83 $ hg pull -u "$TESTDIR"/bundles/test-keyword.hg
84 84 pulling from *test-keyword.hg (glob)
85 85 requesting all changes
86 86 adding changesets
87 87 adding manifests
88 88 adding file changes
89 89 added 1 changesets with 1 changes to 1 files
90 90 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 91
92 92 $ echo 'expand $Id$' > a
93 93 $ echo 'do not process $Id:' >> a
94 94 $ echo 'xxx $' >> a
95 95 $ echo 'ignore $Id$' > b
96 96
97 97 Output files as they were created
98 98
99 99 $ cat a b
100 100 expand $Id$
101 101 do not process $Id:
102 102 xxx $
103 103 ignore $Id$
104 104
105 105 no kwfiles
106 106
107 107 $ hg kwfiles
108 108
109 109 untracked candidates
110 110
111 111 $ hg -v kwfiles --unknown
112 112 k a
113 113
114 114 Add files and check status
115 115
116 116 $ hg addremove
117 117 adding a
118 118 adding b
119 119 $ hg status
120 120 A a
121 121 A b
122 122
123 123
124 124 Default keyword expansion including commit hook
125 125 Interrupted commit should not change state or run commit hook
126 126
127 127 $ hg --debug commit
128 128 abort: empty commit message
129 129 [255]
130 130 $ hg status
131 131 A a
132 132 A b
133 133
134 134 Commit with several checks
135 135
136 136 $ hg --debug commit -mabsym -u 'User Name <user@example.com>'
137 137 a
138 138 b
139 139 overwriting a expanding keywords
140 140 running hook commit.test: cp a hooktest
141 141 committed changeset 1:ef63ca68695bc9495032c6fda1350c71e6d256e9
142 142 $ hg status
143 143 ? hooktest
144 144 $ hg debugrebuildstate
145 145 $ hg --quiet identify
146 146 ef63ca68695b
147 147
148 148 cat files in working directory with keywords expanded
149 149
150 150 $ cat a b
151 151 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
152 152 do not process $Id:
153 153 xxx $
154 154 ignore $Id$
155 155
156 156 hg cat files and symlink, no expansion
157 157
158 158 $ hg cat sym a b && echo
159 159 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
160 160 do not process $Id:
161 161 xxx $
162 162 ignore $Id$
163 163 a
164 164
165 165 Test hook execution
166 166
167 167 $ diff a hooktest
168 168
169 169 $ cp $HGRCPATH.nohooks $HGRCPATH
170 170 $ rm hooktest
171 171
172 172 bundle
173 173
174 174 $ hg bundle --base null ../kw.hg
175 175 2 changesets found
176 176 $ cd ..
177 177 $ hg init Test
178 178 $ cd Test
179 179
180 180 Notify on pull to check whether keywords stay as is in email
181 181 ie. if patch.diff wrapper acts as it should
182 182
183 183 $ cat <<EOF >> $HGRCPATH
184 184 > [hooks]
185 185 > incoming.notify = python:hgext.notify.hook
186 186 > [notify]
187 187 > sources = pull
188 188 > diffstat = False
189 189 > maxsubject = 15
190 190 > [reposubs]
191 191 > * = Test
192 192 > EOF
193 193
194 194 Pull from bundle and trigger notify
195 195
196 196 $ hg pull -u ../kw.hg
197 197 pulling from ../kw.hg
198 198 requesting all changes
199 199 adding changesets
200 200 adding manifests
201 201 adding file changes
202 202 added 2 changesets with 3 changes to 3 files
203 203 Content-Type: text/plain; charset="us-ascii"
204 204 MIME-Version: 1.0
205 205 Content-Transfer-Encoding: 7bit
206 206 Date: * (glob)
207 207 Subject: changeset in...
208 208 From: mercurial
209 209 X-Hg-Notification: changeset a2392c293916
210 210 Message-Id: <hg.a2392c293916*> (glob)
211 211 To: Test
212 212
213 213 changeset a2392c293916 in $TESTTMP/Test (glob)
214 214 details: $TESTTMP/Test?cmd=changeset;node=a2392c293916
215 215 description:
216 216 addsym
217 217
218 218 diffs (6 lines):
219 219
220 220 diff -r 000000000000 -r a2392c293916 sym
221 221 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
222 222 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
223 223 @@ -0,0 +1,1 @@
224 224 +a
225 225 \ No newline at end of file
226 226 Content-Type: text/plain; charset="us-ascii"
227 227 MIME-Version: 1.0
228 228 Content-Transfer-Encoding: 7bit
229 229 Date:* (glob)
230 230 Subject: changeset in...
231 231 From: User Name <user@example.com>
232 232 X-Hg-Notification: changeset ef63ca68695b
233 233 Message-Id: <hg.ef63ca68695b*> (glob)
234 234 To: Test
235 235
236 236 changeset ef63ca68695b in $TESTTMP/Test (glob)
237 237 details: $TESTTMP/Test?cmd=changeset;node=ef63ca68695b
238 238 description:
239 239 absym
240 240
241 241 diffs (12 lines):
242 242
243 243 diff -r a2392c293916 -r ef63ca68695b a
244 244 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
245 245 +++ b/a Thu Jan 01 00:00:00 1970 +0000
246 246 @@ -0,0 +1,3 @@
247 247 +expand $Id$
248 248 +do not process $Id:
249 249 +xxx $
250 250 diff -r a2392c293916 -r ef63ca68695b b
251 251 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
252 252 +++ b/b Thu Jan 01 00:00:00 1970 +0000
253 253 @@ -0,0 +1,1 @@
254 254 +ignore $Id$
255 255 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
256 256
257 257 $ cp $HGRCPATH.nohooks $HGRCPATH
258 258
259 259 Touch files and check with status
260 260
261 261 $ touch a b
262 262 $ hg status
263 263
264 264 Update and expand
265 265
266 266 $ rm sym a b
267 267 $ hg update -C
268 268 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
269 269 $ cat a b
270 270 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
271 271 do not process $Id:
272 272 xxx $
273 273 ignore $Id$
274 274
275 275 Check whether expansion is filewise and file mode is preserved
276 276
277 277 $ echo '$Id$' > c
278 278 $ echo 'tests for different changenodes' >> c
279 279 $ chmod 600 c
280 280 $ ls -l c | cut -b 1-10
281 281 -rw-------
282 282
283 283 commit file c
284 284
285 285 $ hg commit -A -mcndiff -d '1 0' -u 'User Name <user@example.com>'
286 286 adding c
287 287 $ ls -l c | cut -b 1-10
288 288 -rw-------
289 289
290 290 force expansion
291 291
292 292 $ hg -v kwexpand
293 293 overwriting a expanding keywords
294 294 overwriting c expanding keywords
295 295
296 296 compare changenodes in a and c
297 297
298 298 $ cat a c
299 299 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
300 300 do not process $Id:
301 301 xxx $
302 302 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
303 303 tests for different changenodes
304 304
305 305 record
306 306
307 307 $ echo '$Id$' > r
308 308 $ hg add r
309 309
310 310 record chunk
311 311
312 312 >>> lines = open('a').readlines()
313 313 >>> lines.insert(1, 'foo\n')
314 314 >>> lines.append('bar\n')
315 315 >>> open('a', 'w').writelines(lines)
316 316 $ hg record -d '1 10' -m rectest a<<EOF
317 317 > y
318 318 > y
319 319 > n
320 320 > EOF
321 321 diff --git a/a b/a
322 322 2 hunks, 2 lines changed
323 323 examine changes to 'a'? [Ynsfdaq?]
324 324 @@ -1,3 +1,4 @@
325 325 expand $Id$
326 326 +foo
327 327 do not process $Id:
328 328 xxx $
329 329 record change 1/2 to 'a'? [Ynsfdaq?]
330 330 @@ -2,2 +3,3 @@
331 331 do not process $Id:
332 332 xxx $
333 333 +bar
334 334 record change 2/2 to 'a'? [Ynsfdaq?]
335 335
336 336 $ hg identify
337 337 d17e03c92c97+ tip
338 338 $ hg status
339 339 M a
340 340 A r
341 341
342 342 Cat modified file a
343 343
344 344 $ cat a
345 345 expand $Id: a,v d17e03c92c97 1970/01/01 00:00:01 test $
346 346 foo
347 347 do not process $Id:
348 348 xxx $
349 349 bar
350 350
351 351 Diff remaining chunk
352 352
353 353 $ hg diff a
354 354 diff -r d17e03c92c97 a
355 355 --- a/a Wed Dec 31 23:59:51 1969 -0000
356 356 +++ b/a * (glob)
357 357 @@ -2,3 +2,4 @@
358 358 foo
359 359 do not process $Id:
360 360 xxx $
361 361 +bar
362 362
363 363 $ hg rollback
364 364 repository tip rolled back to revision 2 (undo commit)
365 365 working directory now based on revision 2
366 366
367 367 Record all chunks in file a
368 368
369 369 $ echo foo > msg
370 370
371 371 - do not use "hg record -m" here!
372 372
373 373 $ hg record -l msg -d '1 11' a<<EOF
374 374 > y
375 375 > y
376 376 > y
377 377 > EOF
378 378 diff --git a/a b/a
379 379 2 hunks, 2 lines changed
380 380 examine changes to 'a'? [Ynsfdaq?]
381 381 @@ -1,3 +1,4 @@
382 382 expand $Id$
383 383 +foo
384 384 do not process $Id:
385 385 xxx $
386 386 record change 1/2 to 'a'? [Ynsfdaq?]
387 387 @@ -2,2 +3,3 @@
388 388 do not process $Id:
389 389 xxx $
390 390 +bar
391 391 record change 2/2 to 'a'? [Ynsfdaq?]
392 392
393 393 File a should be clean
394 394
395 395 $ hg status -A a
396 396 C a
397 397
398 398 rollback and revert expansion
399 399
400 400 $ cat a
401 401 expand $Id: a,v 59f969a3b52c 1970/01/01 00:00:01 test $
402 402 foo
403 403 do not process $Id:
404 404 xxx $
405 405 bar
406 406 $ hg --verbose rollback
407 407 repository tip rolled back to revision 2 (undo commit)
408 408 working directory now based on revision 2
409 409 overwriting a expanding keywords
410 410 $ hg status a
411 411 M a
412 412 $ cat a
413 413 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
414 414 foo
415 415 do not process $Id:
416 416 xxx $
417 417 bar
418 418 $ echo '$Id$' > y
419 419 $ echo '$Id$' > z
420 420 $ hg add y
421 421 $ hg commit -Am "rollback only" z
422 422 $ cat z
423 423 $Id: z,v 45a5d3adce53 1970/01/01 00:00:00 test $
424 424 $ hg --verbose rollback
425 425 repository tip rolled back to revision 2 (undo commit)
426 426 working directory now based on revision 2
427 427 overwriting z shrinking keywords
428 428
429 429 Only z should be overwritten
430 430
431 431 $ hg status a y z
432 432 M a
433 433 A y
434 434 A z
435 435 $ cat z
436 436 $Id$
437 437 $ hg forget y z
438 438 $ rm y z
439 439
440 440 record added file alone
441 441
442 442 $ hg -v record -l msg -d '1 12' r<<EOF
443 443 > y
444 444 > EOF
445 445 diff --git a/r b/r
446 446 new file mode 100644
447 447 examine changes to 'r'? [Ynsfdaq?]
448 448 r
449 449 committed changeset 3:899491280810
450 450 overwriting r expanding keywords
451 451 - status call required for dirstate.normallookup() check
452 452 $ hg status r
453 453 $ hg --verbose rollback
454 454 repository tip rolled back to revision 2 (undo commit)
455 455 working directory now based on revision 2
456 456 overwriting r shrinking keywords
457 457 $ hg forget r
458 458 $ rm msg r
459 459 $ hg update -C
460 460 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 461
462 462 record added keyword ignored file
463 463
464 464 $ echo '$Id$' > i
465 465 $ hg add i
466 466 $ hg --verbose record -d '1 13' -m recignored<<EOF
467 467 > y
468 468 > EOF
469 469 diff --git a/i b/i
470 470 new file mode 100644
471 471 examine changes to 'i'? [Ynsfdaq?]
472 472 i
473 473 committed changeset 3:5f40fe93bbdc
474 474 $ cat i
475 475 $Id$
476 476 $ hg -q rollback
477 477 $ hg forget i
478 478 $ rm i
479 479
480 480 Test patch queue repo
481 481
482 482 $ hg init --mq
483 483 $ hg qimport -r tip -n mqtest.diff
484 484 $ hg commit --mq -m mqtest
485 485
486 486 Keywords should not be expanded in patch
487 487
488 488 $ cat .hg/patches/mqtest.diff
489 489 # HG changeset patch
490 490 # User User Name <user@example.com>
491 491 # Date 1 0
492 492 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
493 493 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
494 494 cndiff
495 495
496 496 diff -r ef63ca68695b -r 40a904bbbe4c c
497 497 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
498 498 +++ b/c Thu Jan 01 00:00:01 1970 +0000
499 499 @@ -0,0 +1,2 @@
500 500 +$Id$
501 501 +tests for different changenodes
502 502
503 503 $ hg qpop
504 504 popping mqtest.diff
505 505 patch queue now empty
506 506
507 507 qgoto, implying qpush, should expand
508 508
509 509 $ hg qgoto mqtest.diff
510 510 applying mqtest.diff
511 511 now at: mqtest.diff
512 512 $ cat c
513 513 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
514 514 tests for different changenodes
515 515 $ hg cat c
516 516 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
517 517 tests for different changenodes
518 518
519 519 Keywords should not be expanded in filelog
520 520
521 521 $ hg --config 'extensions.keyword=!' cat c
522 522 $Id$
523 523 tests for different changenodes
524 524
525 525 qpop and move on
526 526
527 527 $ hg qpop
528 528 popping mqtest.diff
529 529 patch queue now empty
530 530
531 531 Copy and show added kwfiles
532 532
533 533 $ hg cp a c
534 534 $ hg kwfiles
535 535 a
536 536 c
537 537
538 538 Commit and show expansion in original and copy
539 539
540 540 $ hg --debug commit -ma2c -d '1 0' -u 'User Name <user@example.com>'
541 541 c
542 542 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
543 543 overwriting c expanding keywords
544 544 committed changeset 2:25736cf2f5cbe41f6be4e6784ef6ecf9f3bbcc7d
545 545 $ cat a c
546 546 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
547 547 do not process $Id:
548 548 xxx $
549 549 expand $Id: c,v 25736cf2f5cb 1970/01/01 00:00:01 user $
550 550 do not process $Id:
551 551 xxx $
552 552
553 553 Touch copied c and check its status
554 554
555 555 $ touch c
556 556 $ hg status
557 557
558 558 Copy kwfile to keyword ignored file unexpanding keywords
559 559
560 560 $ hg --verbose copy a i
561 561 copying a to i
562 562 overwriting i shrinking keywords
563 563 $ head -n 1 i
564 564 expand $Id$
565 565 $ hg forget i
566 566 $ rm i
567 567
568 568 Copy ignored file to ignored file: no overwriting
569 569
570 570 $ hg --verbose copy b i
571 571 copying b to i
572 572 $ hg forget i
573 573 $ rm i
574 574
575 575 cp symlink file; hg cp -A symlink file (part1)
576 576 - copied symlink points to kwfile: overwrite
577 577
578 578 $ cp sym i
579 579 $ ls -l i
580 580 -rw-r--r--* (glob)
581 581 $ head -1 i
582 582 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
583 583 $ hg copy --after --verbose sym i
584 584 copying sym to i
585 585 overwriting i shrinking keywords
586 586 $ head -1 i
587 587 expand $Id$
588 588 $ hg forget i
589 589 $ rm i
590 590
591 591 Test different options of hg kwfiles
592 592
593 593 $ hg kwfiles
594 594 a
595 595 c
596 596 $ hg -v kwfiles --ignore
597 597 I b
598 598 I sym
599 599 $ hg kwfiles --all
600 600 K a
601 601 K c
602 602 I b
603 603 I sym
604 604
605 605 Diff specific revision
606 606
607 607 $ hg diff --rev 1
608 608 diff -r ef63ca68695b c
609 609 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
610 610 +++ b/c * (glob)
611 611 @@ -0,0 +1,3 @@
612 612 +expand $Id$
613 613 +do not process $Id:
614 614 +xxx $
615 615
616 616 Status after rollback:
617 617
618 618 $ hg rollback
619 619 repository tip rolled back to revision 1 (undo commit)
620 620 working directory now based on revision 1
621 621 $ hg status
622 622 A c
623 623 $ hg update --clean
624 624 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
625 625
626 626 cp symlink file; hg cp -A symlink file (part2)
627 627 - copied symlink points to kw ignored file: do not overwrite
628 628
629 629 $ cat a > i
630 630 $ ln -s i symignored
631 631 $ hg commit -Am 'fake expansion in ignored and symlink' i symignored
632 632 $ cp symignored x
633 633 $ hg copy --after --verbose symignored x
634 634 copying symignored to x
635 635 $ head -n 1 x
636 636 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
637 637 $ hg forget x
638 638 $ rm x
639 639
640 640 $ hg rollback
641 641 repository tip rolled back to revision 1 (undo commit)
642 642 working directory now based on revision 1
643 643 $ hg update --clean
644 644 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
645 645 $ rm i symignored
646 646
647 647 Custom keywordmaps as argument to kwdemo
648 648
649 649 $ hg --quiet kwdemo "Xinfo = {author}: {desc}"
650 650 [extensions]
651 651 keyword =
652 652 [keyword]
653 653 ** =
654 654 b = ignore
655 655 demo.txt =
656 656 i = ignore
657 657 [keywordset]
658 658 svn = False
659 659 [keywordmaps]
660 660 Xinfo = {author}: {desc}
661 661 $Xinfo: test: hg keyword configuration and expansion example $
662 662
663 663 Configure custom keywordmaps
664 664
665 665 $ cat <<EOF >>$HGRCPATH
666 666 > [keywordmaps]
667 667 > Id = {file} {node|short} {date|rfc822date} {author|user}
668 668 > Xinfo = {author}: {desc}
669 669 > EOF
670 670
671 671 Cat and hg cat files before custom expansion
672 672
673 673 $ cat a b
674 674 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
675 675 do not process $Id:
676 676 xxx $
677 677 ignore $Id$
678 678 $ hg cat sym a b && echo
679 679 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
680 680 do not process $Id:
681 681 xxx $
682 682 ignore $Id$
683 683 a
684 684
685 685 Write custom keyword and prepare multiline commit message
686 686
687 687 $ echo '$Xinfo$' >> a
688 688 $ cat <<EOF >> log
689 689 > firstline
690 690 > secondline
691 691 > EOF
692 692
693 693 Interrupted commit should not change state
694 694
695 695 $ hg commit
696 696 abort: empty commit message
697 697 [255]
698 698 $ hg status
699 699 M a
700 700 ? c
701 701 ? log
702 702
703 703 Commit with multiline message and custom expansion
704 704
705 705 $ hg --debug commit -l log -d '2 0' -u 'User Name <user@example.com>'
706 706 a
707 707 overwriting a expanding keywords
708 708 committed changeset 2:bb948857c743469b22bbf51f7ec8112279ca5d83
709 709 $ rm log
710 710
711 711 Stat, verify and show custom expansion (firstline)
712 712
713 713 $ hg status
714 714 ? c
715 715 $ hg verify
716 716 checking changesets
717 717 checking manifests
718 718 crosschecking files in changesets and manifests
719 719 checking files
720 720 3 files, 3 changesets, 4 total revisions
721 721 $ cat a b
722 722 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
723 723 do not process $Id:
724 724 xxx $
725 725 $Xinfo: User Name <user@example.com>: firstline $
726 726 ignore $Id$
727 727 $ hg cat sym a b && echo
728 728 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
729 729 do not process $Id:
730 730 xxx $
731 731 $Xinfo: User Name <user@example.com>: firstline $
732 732 ignore $Id$
733 733 a
734 734
735 735 annotate
736 736
737 737 $ hg annotate a
738 738 1: expand $Id$
739 739 1: do not process $Id:
740 740 1: xxx $
741 741 2: $Xinfo$
742 742
743 743 remove with status checks
744 744
745 745 $ hg debugrebuildstate
746 746 $ hg remove a
747 747 $ hg --debug commit -m rma
748 748 committed changeset 3:d14c712653769de926994cf7fbb06c8fbd68f012
749 749 $ hg status
750 750 ? c
751 751
752 752 Rollback, revert, and check expansion
753 753
754 754 $ hg rollback
755 755 repository tip rolled back to revision 2 (undo commit)
756 756 working directory now based on revision 2
757 757 $ hg status
758 758 R a
759 759 ? c
760 760 $ hg revert --no-backup --rev tip a
761 761 $ cat a
762 762 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
763 763 do not process $Id:
764 764 xxx $
765 765 $Xinfo: User Name <user@example.com>: firstline $
766 766
767 767 Clone to test global and local configurations
768 768
769 769 $ cd ..
770 770
771 771 Expansion in destinaton with global configuration
772 772
773 773 $ hg --quiet clone Test globalconf
774 774 $ cat globalconf/a
775 775 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
776 776 do not process $Id:
777 777 xxx $
778 778 $Xinfo: User Name <user@example.com>: firstline $
779 779
780 780 No expansion in destination with local configuration in origin only
781 781
782 782 $ hg --quiet --config 'keyword.**=ignore' clone Test localconf
783 783 $ cat localconf/a
784 784 expand $Id$
785 785 do not process $Id:
786 786 xxx $
787 787 $Xinfo$
788 788
789 789 Clone to test incoming
790 790
791 791 $ hg clone -r1 Test Test-a
792 792 adding changesets
793 793 adding manifests
794 794 adding file changes
795 795 added 2 changesets with 3 changes to 3 files
796 796 updating to branch default
797 797 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
798 798 $ cd Test-a
799 799 $ cat <<EOF >> .hg/hgrc
800 800 > [paths]
801 801 > default = ../Test
802 802 > EOF
803 803 $ hg incoming
804 804 comparing with $TESTTMP/Test (glob)
805 805 searching for changes
806 806 changeset: 2:bb948857c743
807 807 tag: tip
808 808 user: User Name <user@example.com>
809 809 date: Thu Jan 01 00:00:02 1970 +0000
810 810 summary: firstline
811 811
812 812 Imported patch should not be rejected
813 813
814 814 >>> import re
815 815 >>> text = re.sub(r'(Id.*)', r'\1 rejecttest', open('a').read())
816 816 >>> open('a', 'wb').write(text)
817 817 $ hg --debug commit -m'rejects?' -d '3 0' -u 'User Name <user@example.com>'
818 818 a
819 819 overwriting a expanding keywords
820 820 committed changeset 2:85e279d709ffc28c9fdd1b868570985fc3d87082
821 821 $ hg export -o ../rejecttest.diff tip
822 822 $ cd ../Test
823 823 $ hg import ../rejecttest.diff
824 824 applying ../rejecttest.diff
825 825 $ cat a b
826 826 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
827 827 do not process $Id: rejecttest
828 828 xxx $
829 829 $Xinfo: User Name <user@example.com>: rejects? $
830 830 ignore $Id$
831 831
832 832 $ hg rollback
833 833 repository tip rolled back to revision 2 (undo import)
834 834 working directory now based on revision 2
835 835 $ hg update --clean
836 836 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
837 837
838 838 kwexpand/kwshrink on selected files
839 839
840 840 $ mkdir x
841 841 $ hg copy a x/a
842 842 $ hg --verbose kwshrink a
843 843 overwriting a shrinking keywords
844 844 - sleep required for dirstate.normal() check
845 845 $ sleep 1
846 846 $ hg status a
847 847 $ hg --verbose kwexpand a
848 848 overwriting a expanding keywords
849 849 $ hg status a
850 850
851 851 kwexpand x/a should abort
852 852
853 853 $ hg --verbose kwexpand x/a
854 854 abort: outstanding uncommitted changes
855 855 [255]
856 856 $ cd x
857 857 $ hg --debug commit -m xa -d '3 0' -u 'User Name <user@example.com>'
858 858 x/a
859 859 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
860 860 overwriting x/a expanding keywords
861 861 committed changeset 3:b4560182a3f9a358179fd2d835c15e9da379c1e4
862 862 $ cat a
863 863 expand $Id: x/a b4560182a3f9 Thu, 01 Jan 1970 00:00:03 +0000 user $
864 864 do not process $Id:
865 865 xxx $
866 866 $Xinfo: User Name <user@example.com>: xa $
867 867
868 868 kwshrink a inside directory x
869 869
870 870 $ hg --verbose kwshrink a
871 871 overwriting x/a shrinking keywords
872 872 $ cat a
873 873 expand $Id$
874 874 do not process $Id:
875 875 xxx $
876 876 $Xinfo$
877 877 $ cd ..
878 878
879 879 kwexpand nonexistent
880 880
881 881 $ hg kwexpand nonexistent
882 882 nonexistent:* (glob)
883 883
884 884
885 885 hg serve
886 886 - expand with hgweb file
887 887 - no expansion with hgweb annotate/changeset/filediff
888 888 - check errors
889 889
890 890 $ hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
891 891 $ cat hg.pid >> $DAEMON_PIDS
892 892 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/file/tip/a/?style=raw'
893 893 200 Script output follows
894 894
895 895 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
896 896 do not process $Id:
897 897 xxx $
898 898 $Xinfo: User Name <user@example.com>: firstline $
899 899 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/annotate/tip/a/?style=raw'
900 900 200 Script output follows
901 901
902 902
903 903 user@1: expand $Id$
904 904 user@1: do not process $Id:
905 905 user@1: xxx $
906 906 user@2: $Xinfo$
907 907
908 908
909 909
910 910
911 911 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/rev/tip/?style=raw'
912 912 200 Script output follows
913 913
914 914
915 915 # HG changeset patch
916 916 # User User Name <user@example.com>
917 917 # Date 3 0
918 918 # Node ID b4560182a3f9a358179fd2d835c15e9da379c1e4
919 919 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
920 920 xa
921 921
922 922 diff -r bb948857c743 -r b4560182a3f9 x/a
923 923 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
924 924 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
925 925 @@ -0,0 +1,4 @@
926 926 +expand $Id$
927 927 +do not process $Id:
928 928 +xxx $
929 929 +$Xinfo$
930 930
931 931 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/diff/bb948857c743/a?style=raw'
932 932 200 Script output follows
933 933
934 934
935 935 diff -r ef63ca68695b -r bb948857c743 a
936 936 --- a/a Thu Jan 01 00:00:00 1970 +0000
937 937 +++ b/a Thu Jan 01 00:00:02 1970 +0000
938 938 @@ -1,3 +1,4 @@
939 939 expand $Id$
940 940 do not process $Id:
941 941 xxx $
942 942 +$Xinfo$
943 943
944 944
945 945
946 946
947 947 $ cat errors.log
948 948
949 949 Prepare merge and resolve tests
950 950
951 951 $ echo '$Id$' > m
952 952 $ hg add m
953 953 $ hg commit -m 4kw
954 954 $ echo foo >> m
955 955 $ hg commit -m 5foo
956 956
957 957 simplemerge
958 958
959 959 $ hg update 4
960 960 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
961 961 $ echo foo >> m
962 962 $ hg commit -m 6foo
963 963 created new head
964 964 $ hg merge
965 965 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
966 966 (branch merge, don't forget to commit)
967 967 $ hg commit -m simplemerge
968 968 $ cat m
969 969 $Id: m 27d48ee14f67 Thu, 01 Jan 1970 00:00:00 +0000 test $
970 970 foo
971 971
972 972 conflict: keyword should stay outside conflict zone
973 973
974 974 $ hg update 4
975 975 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
976 976 $ echo bar >> m
977 977 $ hg commit -m 8bar
978 978 created new head
979 979 $ hg merge
980 980 merging m
981 981 warning: conflicts during merge.
982 982 merging m incomplete! (edit conflicts, then use 'hg resolve --mark')
983 983 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
984 984 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
985 985 [1]
986 986 $ cat m
987 987 $Id$
988 988 <<<<<<< local
989 989 bar
990 990 =======
991 991 foo
992 992 >>>>>>> other
993 993
994 994 resolve to local
995 995
996 996 $ HGMERGE=internal:local hg resolve -a
997 997 $ hg commit -m localresolve
998 998 $ cat m
999 999 $Id: m 800511b3a22d Thu, 01 Jan 1970 00:00:00 +0000 test $
1000 1000 bar
1001 1001
1002 1002 Test restricted mode with transplant -b
1003 1003
1004 1004 $ hg update 6
1005 1005 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1006 1006 $ hg branch foo
1007 1007 marked working directory as branch foo
1008 (branches are permanent and global, did you want a bookmark?)
1008 1009 $ mv a a.bak
1009 1010 $ echo foobranch > a
1010 1011 $ cat a.bak >> a
1011 1012 $ rm a.bak
1012 1013 $ hg commit -m 9foobranch
1013 1014 $ hg update default
1014 1015 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1015 1016 $ hg -y transplant -b foo tip
1016 1017 applying 4aa30d025d50
1017 1018 4aa30d025d50 transplanted to e00abbf63521
1018 1019
1019 1020 Expansion in changeset but not in file
1020 1021
1021 1022 $ hg tip -p
1022 1023 changeset: 11:e00abbf63521
1023 1024 tag: tip
1024 1025 parent: 9:800511b3a22d
1025 1026 user: test
1026 1027 date: Thu Jan 01 00:00:00 1970 +0000
1027 1028 summary: 9foobranch
1028 1029
1029 1030 diff -r 800511b3a22d -r e00abbf63521 a
1030 1031 --- a/a Thu Jan 01 00:00:00 1970 +0000
1031 1032 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1032 1033 @@ -1,3 +1,4 @@
1033 1034 +foobranch
1034 1035 expand $Id$
1035 1036 do not process $Id:
1036 1037 xxx $
1037 1038
1038 1039 $ head -n 2 a
1039 1040 foobranch
1040 1041 expand $Id: a e00abbf63521 Thu, 01 Jan 1970 00:00:00 +0000 test $
1041 1042
1042 1043 Turn off expansion
1043 1044
1044 1045 $ hg -q rollback
1045 1046 $ hg -q update -C
1046 1047
1047 1048 kwshrink with unknown file u
1048 1049
1049 1050 $ cp a u
1050 1051 $ hg --verbose kwshrink
1051 1052 overwriting a shrinking keywords
1052 1053 overwriting m shrinking keywords
1053 1054 overwriting x/a shrinking keywords
1054 1055
1055 1056 Keywords shrunk in working directory, but not yet disabled
1056 1057 - cat shows unexpanded keywords
1057 1058 - hg cat shows expanded keywords
1058 1059
1059 1060 $ cat a b
1060 1061 expand $Id$
1061 1062 do not process $Id:
1062 1063 xxx $
1063 1064 $Xinfo$
1064 1065 ignore $Id$
1065 1066 $ hg cat sym a b && echo
1066 1067 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
1067 1068 do not process $Id:
1068 1069 xxx $
1069 1070 $Xinfo: User Name <user@example.com>: firstline $
1070 1071 ignore $Id$
1071 1072 a
1072 1073
1073 1074 Now disable keyword expansion
1074 1075
1075 1076 $ rm "$HGRCPATH"
1076 1077 $ cat a b
1077 1078 expand $Id$
1078 1079 do not process $Id:
1079 1080 xxx $
1080 1081 $Xinfo$
1081 1082 ignore $Id$
1082 1083 $ hg cat sym a b && echo
1083 1084 expand $Id$
1084 1085 do not process $Id:
1085 1086 xxx $
1086 1087 $Xinfo$
1087 1088 ignore $Id$
1088 1089 a
@@ -1,1160 +1,1161 b''
1 1 $ "$TESTDIR/hghave" execbit || exit 80
2 2
3 3 $ hg init a
4 4
5 5 $ cd a
6 6 $ echo a > a
7 7 $ hg ci -Ama -d '1 0'
8 8 adding a
9 9
10 10 $ hg cp a b
11 11 $ hg ci -mb -d '2 0'
12 12
13 13 $ mkdir dir
14 14 $ hg mv b dir
15 15 $ hg ci -mc -d '3 0'
16 16
17 17 $ hg mv a b
18 18 $ echo a > d
19 19 $ hg add d
20 20 $ hg ci -md -d '4 0'
21 21
22 22 $ hg mv dir/b e
23 23 $ hg ci -me -d '5 0'
24 24
25 25 $ hg log a
26 26 changeset: 0:8580ff50825a
27 27 user: test
28 28 date: Thu Jan 01 00:00:01 1970 +0000
29 29 summary: a
30 30
31 31
32 32 -f, directory
33 33
34 34 $ hg log -f dir
35 35 abort: cannot follow nonexistent file: "dir"
36 36 [255]
37 37
38 38 -f, but no args
39 39
40 40 $ hg log -f
41 41 changeset: 4:66c1345dc4f9
42 42 tag: tip
43 43 user: test
44 44 date: Thu Jan 01 00:00:05 1970 +0000
45 45 summary: e
46 46
47 47 changeset: 3:7c6c671bb7cc
48 48 user: test
49 49 date: Thu Jan 01 00:00:04 1970 +0000
50 50 summary: d
51 51
52 52 changeset: 2:41dd4284081e
53 53 user: test
54 54 date: Thu Jan 01 00:00:03 1970 +0000
55 55 summary: c
56 56
57 57 changeset: 1:784de7cef101
58 58 user: test
59 59 date: Thu Jan 01 00:00:02 1970 +0000
60 60 summary: b
61 61
62 62 changeset: 0:8580ff50825a
63 63 user: test
64 64 date: Thu Jan 01 00:00:01 1970 +0000
65 65 summary: a
66 66
67 67
68 68 one rename
69 69
70 70 $ hg log -vf a
71 71 changeset: 0:8580ff50825a
72 72 user: test
73 73 date: Thu Jan 01 00:00:01 1970 +0000
74 74 files: a
75 75 description:
76 76 a
77 77
78 78
79 79
80 80 many renames
81 81
82 82 $ hg log -vf e
83 83 changeset: 4:66c1345dc4f9
84 84 tag: tip
85 85 user: test
86 86 date: Thu Jan 01 00:00:05 1970 +0000
87 87 files: dir/b e
88 88 description:
89 89 e
90 90
91 91
92 92 changeset: 2:41dd4284081e
93 93 user: test
94 94 date: Thu Jan 01 00:00:03 1970 +0000
95 95 files: b dir/b
96 96 description:
97 97 c
98 98
99 99
100 100 changeset: 1:784de7cef101
101 101 user: test
102 102 date: Thu Jan 01 00:00:02 1970 +0000
103 103 files: b
104 104 description:
105 105 b
106 106
107 107
108 108 changeset: 0:8580ff50825a
109 109 user: test
110 110 date: Thu Jan 01 00:00:01 1970 +0000
111 111 files: a
112 112 description:
113 113 a
114 114
115 115
116 116
117 117
118 118 log -pf dir/b
119 119
120 120 $ hg log -pf dir/b
121 121 changeset: 2:41dd4284081e
122 122 user: test
123 123 date: Thu Jan 01 00:00:03 1970 +0000
124 124 summary: c
125 125
126 126 diff -r 784de7cef101 -r 41dd4284081e dir/b
127 127 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
128 128 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
129 129 @@ -0,0 +1,1 @@
130 130 +a
131 131
132 132 changeset: 1:784de7cef101
133 133 user: test
134 134 date: Thu Jan 01 00:00:02 1970 +0000
135 135 summary: b
136 136
137 137 diff -r 8580ff50825a -r 784de7cef101 b
138 138 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
139 139 +++ b/b Thu Jan 01 00:00:02 1970 +0000
140 140 @@ -0,0 +1,1 @@
141 141 +a
142 142
143 143 changeset: 0:8580ff50825a
144 144 user: test
145 145 date: Thu Jan 01 00:00:01 1970 +0000
146 146 summary: a
147 147
148 148 diff -r 000000000000 -r 8580ff50825a a
149 149 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
150 150 +++ b/a Thu Jan 01 00:00:01 1970 +0000
151 151 @@ -0,0 +1,1 @@
152 152 +a
153 153
154 154
155 155 log -vf dir/b
156 156
157 157 $ hg log -vf dir/b
158 158 changeset: 2:41dd4284081e
159 159 user: test
160 160 date: Thu Jan 01 00:00:03 1970 +0000
161 161 files: b dir/b
162 162 description:
163 163 c
164 164
165 165
166 166 changeset: 1:784de7cef101
167 167 user: test
168 168 date: Thu Jan 01 00:00:02 1970 +0000
169 169 files: b
170 170 description:
171 171 b
172 172
173 173
174 174 changeset: 0:8580ff50825a
175 175 user: test
176 176 date: Thu Jan 01 00:00:01 1970 +0000
177 177 files: a
178 178 description:
179 179 a
180 180
181 181
182 182
183 183
184 184 log copies with --copies
185 185
186 186 $ hg log -vC --template '{rev} {file_copies}\n'
187 187 4 e (dir/b)
188 188 3 b (a)
189 189 2 dir/b (b)
190 190 1 b (a)
191 191 0
192 192
193 193 log copies switch without --copies, with old filecopy template
194 194
195 195 $ hg log -v --template '{rev} {file_copies_switch%filecopy}\n'
196 196 4
197 197 3
198 198 2
199 199 1
200 200 0
201 201
202 202 log copies switch with --copies
203 203
204 204 $ hg log -vC --template '{rev} {file_copies_switch}\n'
205 205 4 e (dir/b)
206 206 3 b (a)
207 207 2 dir/b (b)
208 208 1 b (a)
209 209 0
210 210
211 211
212 212 log copies with hardcoded style and with --style=default
213 213
214 214 $ hg log -vC -r4
215 215 changeset: 4:66c1345dc4f9
216 216 tag: tip
217 217 user: test
218 218 date: Thu Jan 01 00:00:05 1970 +0000
219 219 files: dir/b e
220 220 copies: e (dir/b)
221 221 description:
222 222 e
223 223
224 224
225 225 $ hg log -vC -r4 --style=default
226 226 changeset: 4:66c1345dc4f9
227 227 tag: tip
228 228 user: test
229 229 date: Thu Jan 01 00:00:05 1970 +0000
230 230 files: dir/b e
231 231 copies: e (dir/b)
232 232 description:
233 233 e
234 234
235 235
236 236
237 237
238 238 log copies, non-linear manifest
239 239
240 240 $ hg up -C 3
241 241 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
242 242 $ hg mv dir/b e
243 243 $ echo foo > foo
244 244 $ hg ci -Ame2 -d '6 0'
245 245 adding foo
246 246 created new head
247 247 $ hg log -v --template '{rev} {file_copies}\n' -r 5
248 248 5 e (dir/b)
249 249
250 250
251 251 log copies, execute bit set
252 252
253 253 $ chmod +x e
254 254 $ hg ci -me3 -d '7 0'
255 255 $ hg log -v --template '{rev} {file_copies}\n' -r 6
256 256 6
257 257
258 258
259 259 log -p d
260 260
261 261 $ hg log -pv d
262 262 changeset: 3:7c6c671bb7cc
263 263 user: test
264 264 date: Thu Jan 01 00:00:04 1970 +0000
265 265 files: a b d
266 266 description:
267 267 d
268 268
269 269
270 270 diff -r 41dd4284081e -r 7c6c671bb7cc d
271 271 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
272 272 +++ b/d Thu Jan 01 00:00:04 1970 +0000
273 273 @@ -0,0 +1,1 @@
274 274 +a
275 275
276 276
277 277
278 278 log --removed file
279 279
280 280 $ hg log --removed -v a
281 281 changeset: 3:7c6c671bb7cc
282 282 user: test
283 283 date: Thu Jan 01 00:00:04 1970 +0000
284 284 files: a b d
285 285 description:
286 286 d
287 287
288 288
289 289 changeset: 0:8580ff50825a
290 290 user: test
291 291 date: Thu Jan 01 00:00:01 1970 +0000
292 292 files: a
293 293 description:
294 294 a
295 295
296 296
297 297
298 298 log --removed revrange file
299 299
300 300 $ hg log --removed -v -r0:2 a
301 301 changeset: 0:8580ff50825a
302 302 user: test
303 303 date: Thu Jan 01 00:00:01 1970 +0000
304 304 files: a
305 305 description:
306 306 a
307 307
308 308
309 309
310 310
311 311 log --follow tests
312 312
313 313 $ hg init ../follow
314 314 $ cd ../follow
315 315
316 316 $ echo base > base
317 317 $ hg ci -Ambase -d '1 0'
318 318 adding base
319 319
320 320 $ echo r1 >> base
321 321 $ hg ci -Amr1 -d '1 0'
322 322 $ echo r2 >> base
323 323 $ hg ci -Amr2 -d '1 0'
324 324
325 325 $ hg up -C 1
326 326 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
327 327 $ echo b1 > b1
328 328 $ hg ci -Amb1 -d '1 0'
329 329 adding b1
330 330 created new head
331 331
332 332
333 333 log -f
334 334
335 335 $ hg log -f
336 336 changeset: 3:e62f78d544b4
337 337 tag: tip
338 338 parent: 1:3d5bf5654eda
339 339 user: test
340 340 date: Thu Jan 01 00:00:01 1970 +0000
341 341 summary: b1
342 342
343 343 changeset: 1:3d5bf5654eda
344 344 user: test
345 345 date: Thu Jan 01 00:00:01 1970 +0000
346 346 summary: r1
347 347
348 348 changeset: 0:67e992f2c4f3
349 349 user: test
350 350 date: Thu Jan 01 00:00:01 1970 +0000
351 351 summary: base
352 352
353 353
354 354
355 355 log -f -r 1:tip
356 356
357 357 $ hg up -C 0
358 358 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
359 359 $ echo b2 > b2
360 360 $ hg ci -Amb2 -d '1 0'
361 361 adding b2
362 362 created new head
363 363 $ hg log -f -r 1:tip
364 364 changeset: 1:3d5bf5654eda
365 365 user: test
366 366 date: Thu Jan 01 00:00:01 1970 +0000
367 367 summary: r1
368 368
369 369 changeset: 2:60c670bf5b30
370 370 user: test
371 371 date: Thu Jan 01 00:00:01 1970 +0000
372 372 summary: r2
373 373
374 374 changeset: 3:e62f78d544b4
375 375 parent: 1:3d5bf5654eda
376 376 user: test
377 377 date: Thu Jan 01 00:00:01 1970 +0000
378 378 summary: b1
379 379
380 380
381 381
382 382 log -r . with two parents
383 383
384 384 $ hg up -C 3
385 385 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
386 386 $ hg merge tip
387 387 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
388 388 (branch merge, don't forget to commit)
389 389 $ hg log -r .
390 390 changeset: 3:e62f78d544b4
391 391 parent: 1:3d5bf5654eda
392 392 user: test
393 393 date: Thu Jan 01 00:00:01 1970 +0000
394 394 summary: b1
395 395
396 396
397 397
398 398 log -r . with one parent
399 399
400 400 $ hg ci -mm12 -d '1 0'
401 401 $ hg log -r .
402 402 changeset: 5:302e9dd6890d
403 403 tag: tip
404 404 parent: 3:e62f78d544b4
405 405 parent: 4:ddb82e70d1a1
406 406 user: test
407 407 date: Thu Jan 01 00:00:01 1970 +0000
408 408 summary: m12
409 409
410 410
411 411 $ echo postm >> b1
412 412 $ hg ci -Amb1.1 -d'1 0'
413 413
414 414
415 415 log --follow-first
416 416
417 417 $ hg log --follow-first
418 418 changeset: 6:2404bbcab562
419 419 tag: tip
420 420 user: test
421 421 date: Thu Jan 01 00:00:01 1970 +0000
422 422 summary: b1.1
423 423
424 424 changeset: 5:302e9dd6890d
425 425 parent: 3:e62f78d544b4
426 426 parent: 4:ddb82e70d1a1
427 427 user: test
428 428 date: Thu Jan 01 00:00:01 1970 +0000
429 429 summary: m12
430 430
431 431 changeset: 3:e62f78d544b4
432 432 parent: 1:3d5bf5654eda
433 433 user: test
434 434 date: Thu Jan 01 00:00:01 1970 +0000
435 435 summary: b1
436 436
437 437 changeset: 1:3d5bf5654eda
438 438 user: test
439 439 date: Thu Jan 01 00:00:01 1970 +0000
440 440 summary: r1
441 441
442 442 changeset: 0:67e992f2c4f3
443 443 user: test
444 444 date: Thu Jan 01 00:00:01 1970 +0000
445 445 summary: base
446 446
447 447
448 448
449 449 log -P 2
450 450
451 451 $ hg log -P 2
452 452 changeset: 6:2404bbcab562
453 453 tag: tip
454 454 user: test
455 455 date: Thu Jan 01 00:00:01 1970 +0000
456 456 summary: b1.1
457 457
458 458 changeset: 5:302e9dd6890d
459 459 parent: 3:e62f78d544b4
460 460 parent: 4:ddb82e70d1a1
461 461 user: test
462 462 date: Thu Jan 01 00:00:01 1970 +0000
463 463 summary: m12
464 464
465 465 changeset: 4:ddb82e70d1a1
466 466 parent: 0:67e992f2c4f3
467 467 user: test
468 468 date: Thu Jan 01 00:00:01 1970 +0000
469 469 summary: b2
470 470
471 471 changeset: 3:e62f78d544b4
472 472 parent: 1:3d5bf5654eda
473 473 user: test
474 474 date: Thu Jan 01 00:00:01 1970 +0000
475 475 summary: b1
476 476
477 477
478 478
479 479 log -r tip -p --git
480 480
481 481 $ hg log -r tip -p --git
482 482 changeset: 6:2404bbcab562
483 483 tag: tip
484 484 user: test
485 485 date: Thu Jan 01 00:00:01 1970 +0000
486 486 summary: b1.1
487 487
488 488 diff --git a/b1 b/b1
489 489 --- a/b1
490 490 +++ b/b1
491 491 @@ -1,1 +1,2 @@
492 492 b1
493 493 +postm
494 494
495 495
496 496
497 497 log -r ""
498 498
499 499 $ hg log -r ''
500 500 hg: parse error: empty query
501 501 [255]
502 502
503 503 log -r <some unknown node id>
504 504
505 505 $ hg log -r 1000000000000000000000000000000000000000
506 506 abort: unknown revision '1000000000000000000000000000000000000000'!
507 507 [255]
508 508
509 509 log -k r1
510 510
511 511 $ hg log -k r1
512 512 changeset: 1:3d5bf5654eda
513 513 user: test
514 514 date: Thu Jan 01 00:00:01 1970 +0000
515 515 summary: r1
516 516
517 517 log -d " " (whitespaces only)
518 518
519 519 $ hg log -d " "
520 520 abort: dates cannot consist entirely of whitespace
521 521 [255]
522 522
523 523 log -d -1
524 524
525 525 $ hg log -d -1
526 526
527 527 log -d ">"
528 528
529 529 $ hg log -d ">"
530 530 abort: invalid day spec, use '>DATE'
531 531 [255]
532 532
533 533 log -d "<"
534 534
535 535 $ hg log -d "<"
536 536 abort: invalid day spec, use '<DATE'
537 537 [255]
538 538
539 539 Negative ranges
540 540 $ hg log -d "--2"
541 541 abort: -2 must be nonnegative (see 'hg help dates')
542 542 [255]
543 543
544 544
545 545 log -p -l2 --color=always
546 546
547 547 $ hg --config extensions.color= --config color.mode=ansi \
548 548 > log -p -l2 --color=always
549 549 \x1b[0;33mchangeset: 6:2404bbcab562\x1b[0m (esc)
550 550 tag: tip
551 551 user: test
552 552 date: Thu Jan 01 00:00:01 1970 +0000
553 553 summary: b1.1
554 554
555 555 \x1b[0;1mdiff -r 302e9dd6890d -r 2404bbcab562 b1\x1b[0m (esc)
556 556 \x1b[0;31;1m--- a/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
557 557 \x1b[0;32;1m+++ b/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
558 558 \x1b[0;35m@@ -1,1 +1,2 @@\x1b[0m (esc)
559 559 b1
560 560 \x1b[0;32m+postm\x1b[0m (esc)
561 561
562 562 \x1b[0;33mchangeset: 5:302e9dd6890d\x1b[0m (esc)
563 563 parent: 3:e62f78d544b4
564 564 parent: 4:ddb82e70d1a1
565 565 user: test
566 566 date: Thu Jan 01 00:00:01 1970 +0000
567 567 summary: m12
568 568
569 569 \x1b[0;1mdiff -r e62f78d544b4 -r 302e9dd6890d b2\x1b[0m (esc)
570 570 \x1b[0;31;1m--- /dev/null Thu Jan 01 00:00:00 1970 +0000\x1b[0m (esc)
571 571 \x1b[0;32;1m+++ b/b2 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
572 572 \x1b[0;35m@@ -0,0 +1,1 @@\x1b[0m (esc)
573 573 \x1b[0;32m+b2\x1b[0m (esc)
574 574
575 575
576 576
577 577 log -r tip --stat
578 578
579 579 $ hg log -r tip --stat
580 580 changeset: 6:2404bbcab562
581 581 tag: tip
582 582 user: test
583 583 date: Thu Jan 01 00:00:01 1970 +0000
584 584 summary: b1.1
585 585
586 586 b1 | 1 +
587 587 1 files changed, 1 insertions(+), 0 deletions(-)
588 588
589 589
590 590 $ cd ..
591 591
592 592 $ hg init usertest
593 593 $ cd usertest
594 594
595 595 $ echo a > a
596 596 $ hg ci -A -m "a" -u "User One <user1@example.org>"
597 597 adding a
598 598 $ echo b > b
599 599 $ hg ci -A -m "b" -u "User Two <user2@example.org>"
600 600 adding b
601 601
602 602 $ hg log -u "User One <user1@example.org>"
603 603 changeset: 0:29a4c94f1924
604 604 user: User One <user1@example.org>
605 605 date: Thu Jan 01 00:00:00 1970 +0000
606 606 summary: a
607 607
608 608 $ hg log -u "user1" -u "user2"
609 609 changeset: 1:e834b5e69c0e
610 610 tag: tip
611 611 user: User Two <user2@example.org>
612 612 date: Thu Jan 01 00:00:00 1970 +0000
613 613 summary: b
614 614
615 615 changeset: 0:29a4c94f1924
616 616 user: User One <user1@example.org>
617 617 date: Thu Jan 01 00:00:00 1970 +0000
618 618 summary: a
619 619
620 620 $ hg log -u "user3"
621 621
622 622 $ cd ..
623 623
624 624 $ hg init branches
625 625 $ cd branches
626 626
627 627 $ echo a > a
628 628 $ hg ci -A -m "commit on default"
629 629 adding a
630 630 $ hg branch test
631 631 marked working directory as branch test
632 (branches are permanent and global, did you want a bookmark?)
632 633 $ echo b > b
633 634 $ hg ci -A -m "commit on test"
634 635 adding b
635 636
636 637 $ hg up default
637 638 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
638 639 $ echo c > c
639 640 $ hg ci -A -m "commit on default"
640 641 adding c
641 642 $ hg up test
642 643 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
643 644 $ echo c > c
644 645 $ hg ci -A -m "commit on test"
645 646 adding c
646 647
647 648
648 649 log -b default
649 650
650 651 $ hg log -b default
651 652 changeset: 2:c3a4f03cc9a7
652 653 parent: 0:24427303d56f
653 654 user: test
654 655 date: Thu Jan 01 00:00:00 1970 +0000
655 656 summary: commit on default
656 657
657 658 changeset: 0:24427303d56f
658 659 user: test
659 660 date: Thu Jan 01 00:00:00 1970 +0000
660 661 summary: commit on default
661 662
662 663
663 664
664 665 log -b test
665 666
666 667 $ hg log -b test
667 668 changeset: 3:f5d8de11c2e2
668 669 branch: test
669 670 tag: tip
670 671 parent: 1:d32277701ccb
671 672 user: test
672 673 date: Thu Jan 01 00:00:00 1970 +0000
673 674 summary: commit on test
674 675
675 676 changeset: 1:d32277701ccb
676 677 branch: test
677 678 user: test
678 679 date: Thu Jan 01 00:00:00 1970 +0000
679 680 summary: commit on test
680 681
681 682
682 683
683 684 log -b dummy
684 685
685 686 $ hg log -b dummy
686 687 abort: unknown revision 'dummy'!
687 688 [255]
688 689
689 690
690 691 log -b .
691 692
692 693 $ hg log -b .
693 694 changeset: 3:f5d8de11c2e2
694 695 branch: test
695 696 tag: tip
696 697 parent: 1:d32277701ccb
697 698 user: test
698 699 date: Thu Jan 01 00:00:00 1970 +0000
699 700 summary: commit on test
700 701
701 702 changeset: 1:d32277701ccb
702 703 branch: test
703 704 user: test
704 705 date: Thu Jan 01 00:00:00 1970 +0000
705 706 summary: commit on test
706 707
707 708
708 709
709 710 log -b default -b test
710 711
711 712 $ hg log -b default -b test
712 713 changeset: 3:f5d8de11c2e2
713 714 branch: test
714 715 tag: tip
715 716 parent: 1:d32277701ccb
716 717 user: test
717 718 date: Thu Jan 01 00:00:00 1970 +0000
718 719 summary: commit on test
719 720
720 721 changeset: 2:c3a4f03cc9a7
721 722 parent: 0:24427303d56f
722 723 user: test
723 724 date: Thu Jan 01 00:00:00 1970 +0000
724 725 summary: commit on default
725 726
726 727 changeset: 1:d32277701ccb
727 728 branch: test
728 729 user: test
729 730 date: Thu Jan 01 00:00:00 1970 +0000
730 731 summary: commit on test
731 732
732 733 changeset: 0:24427303d56f
733 734 user: test
734 735 date: Thu Jan 01 00:00:00 1970 +0000
735 736 summary: commit on default
736 737
737 738
738 739
739 740 log -b default -b .
740 741
741 742 $ hg log -b default -b .
742 743 changeset: 3:f5d8de11c2e2
743 744 branch: test
744 745 tag: tip
745 746 parent: 1:d32277701ccb
746 747 user: test
747 748 date: Thu Jan 01 00:00:00 1970 +0000
748 749 summary: commit on test
749 750
750 751 changeset: 2:c3a4f03cc9a7
751 752 parent: 0:24427303d56f
752 753 user: test
753 754 date: Thu Jan 01 00:00:00 1970 +0000
754 755 summary: commit on default
755 756
756 757 changeset: 1:d32277701ccb
757 758 branch: test
758 759 user: test
759 760 date: Thu Jan 01 00:00:00 1970 +0000
760 761 summary: commit on test
761 762
762 763 changeset: 0:24427303d56f
763 764 user: test
764 765 date: Thu Jan 01 00:00:00 1970 +0000
765 766 summary: commit on default
766 767
767 768
768 769
769 770 log -b . -b test
770 771
771 772 $ hg log -b . -b test
772 773 changeset: 3:f5d8de11c2e2
773 774 branch: test
774 775 tag: tip
775 776 parent: 1:d32277701ccb
776 777 user: test
777 778 date: Thu Jan 01 00:00:00 1970 +0000
778 779 summary: commit on test
779 780
780 781 changeset: 1:d32277701ccb
781 782 branch: test
782 783 user: test
783 784 date: Thu Jan 01 00:00:00 1970 +0000
784 785 summary: commit on test
785 786
786 787
787 788
788 789 log -b 2
789 790
790 791 $ hg log -b 2
791 792 changeset: 2:c3a4f03cc9a7
792 793 parent: 0:24427303d56f
793 794 user: test
794 795 date: Thu Jan 01 00:00:00 1970 +0000
795 796 summary: commit on default
796 797
797 798 changeset: 0:24427303d56f
798 799 user: test
799 800 date: Thu Jan 01 00:00:00 1970 +0000
800 801 summary: commit on default
801 802
802 803
803 804
804 805 log -p --cwd dir (in subdir)
805 806
806 807 $ mkdir dir
807 808 $ hg log -p --cwd dir
808 809 changeset: 3:f5d8de11c2e2
809 810 branch: test
810 811 tag: tip
811 812 parent: 1:d32277701ccb
812 813 user: test
813 814 date: Thu Jan 01 00:00:00 1970 +0000
814 815 summary: commit on test
815 816
816 817 diff -r d32277701ccb -r f5d8de11c2e2 c
817 818 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
818 819 +++ b/c Thu Jan 01 00:00:00 1970 +0000
819 820 @@ -0,0 +1,1 @@
820 821 +c
821 822
822 823 changeset: 2:c3a4f03cc9a7
823 824 parent: 0:24427303d56f
824 825 user: test
825 826 date: Thu Jan 01 00:00:00 1970 +0000
826 827 summary: commit on default
827 828
828 829 diff -r 24427303d56f -r c3a4f03cc9a7 c
829 830 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
830 831 +++ b/c Thu Jan 01 00:00:00 1970 +0000
831 832 @@ -0,0 +1,1 @@
832 833 +c
833 834
834 835 changeset: 1:d32277701ccb
835 836 branch: test
836 837 user: test
837 838 date: Thu Jan 01 00:00:00 1970 +0000
838 839 summary: commit on test
839 840
840 841 diff -r 24427303d56f -r d32277701ccb b
841 842 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
842 843 +++ b/b Thu Jan 01 00:00:00 1970 +0000
843 844 @@ -0,0 +1,1 @@
844 845 +b
845 846
846 847 changeset: 0:24427303d56f
847 848 user: test
848 849 date: Thu Jan 01 00:00:00 1970 +0000
849 850 summary: commit on default
850 851
851 852 diff -r 000000000000 -r 24427303d56f a
852 853 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
853 854 +++ b/a Thu Jan 01 00:00:00 1970 +0000
854 855 @@ -0,0 +1,1 @@
855 856 +a
856 857
857 858
858 859
859 860 log -p -R repo
860 861
861 862 $ cd dir
862 863 $ hg log -p -R .. ../a
863 864 changeset: 0:24427303d56f
864 865 user: test
865 866 date: Thu Jan 01 00:00:00 1970 +0000
866 867 summary: commit on default
867 868
868 869 diff -r 000000000000 -r 24427303d56f a
869 870 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
870 871 +++ b/a Thu Jan 01 00:00:00 1970 +0000
871 872 @@ -0,0 +1,1 @@
872 873 +a
873 874
874 875
875 876
876 877 $ cd ..
877 878 $ hg init follow2
878 879 $ cd follow2
879 880
880 881
881 882 # Build the following history:
882 883 # tip - o - x - o - x - x
883 884 # \ /
884 885 # o - o - o - x
885 886 # \ /
886 887 # o
887 888 #
888 889 # Where "o" is a revision containing "foo" and
889 890 # "x" is a revision without "foo"
890 891
891 892 $ touch init
892 893 $ hg ci -A -m "init, unrelated"
893 894 adding init
894 895 $ echo 'foo' > init
895 896 $ hg ci -m "change, unrelated"
896 897 $ echo 'foo' > foo
897 898 $ hg ci -A -m "add unrelated old foo"
898 899 adding foo
899 900 $ hg rm foo
900 901 $ hg ci -m "delete foo, unrelated"
901 902 $ echo 'related' > foo
902 903 $ hg ci -A -m "add foo, related"
903 904 adding foo
904 905
905 906 $ hg up 0
906 907 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
907 908 $ touch branch
908 909 $ hg ci -A -m "first branch, unrelated"
909 910 adding branch
910 911 created new head
911 912 $ touch foo
912 913 $ hg ci -A -m "create foo, related"
913 914 adding foo
914 915 $ echo 'change' > foo
915 916 $ hg ci -m "change foo, related"
916 917
917 918 $ hg up 6
918 919 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
919 920 $ echo 'change foo in branch' > foo
920 921 $ hg ci -m "change foo in branch, related"
921 922 created new head
922 923 $ hg merge 7
923 924 merging foo
924 925 warning: conflicts during merge.
925 926 merging foo incomplete! (edit conflicts, then use 'hg resolve --mark')
926 927 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
927 928 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
928 929 [1]
929 930 $ echo 'merge 1' > foo
930 931 $ hg resolve -m foo
931 932 $ hg ci -m "First merge, related"
932 933
933 934 $ hg merge 4
934 935 merging foo
935 936 warning: conflicts during merge.
936 937 merging foo incomplete! (edit conflicts, then use 'hg resolve --mark')
937 938 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
938 939 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
939 940 [1]
940 941 $ echo 'merge 2' > foo
941 942 $ hg resolve -m foo
942 943 $ hg ci -m "Last merge, related"
943 944
944 945 $ hg --config "extensions.graphlog=" glog
945 946 @ changeset: 10:4dae8563d2c5
946 947 |\ tag: tip
947 948 | | parent: 9:7b35701b003e
948 949 | | parent: 4:88176d361b69
949 950 | | user: test
950 951 | | date: Thu Jan 01 00:00:00 1970 +0000
951 952 | | summary: Last merge, related
952 953 | |
953 954 | o changeset: 9:7b35701b003e
954 955 | |\ parent: 8:e5416ad8a855
955 956 | | | parent: 7:87fe3144dcfa
956 957 | | | user: test
957 958 | | | date: Thu Jan 01 00:00:00 1970 +0000
958 959 | | | summary: First merge, related
959 960 | | |
960 961 | | o changeset: 8:e5416ad8a855
961 962 | | | parent: 6:dc6c325fe5ee
962 963 | | | user: test
963 964 | | | date: Thu Jan 01 00:00:00 1970 +0000
964 965 | | | summary: change foo in branch, related
965 966 | | |
966 967 | o | changeset: 7:87fe3144dcfa
967 968 | |/ user: test
968 969 | | date: Thu Jan 01 00:00:00 1970 +0000
969 970 | | summary: change foo, related
970 971 | |
971 972 | o changeset: 6:dc6c325fe5ee
972 973 | | user: test
973 974 | | date: Thu Jan 01 00:00:00 1970 +0000
974 975 | | summary: create foo, related
975 976 | |
976 977 | o changeset: 5:73db34516eb9
977 978 | | parent: 0:e87515fd044a
978 979 | | user: test
979 980 | | date: Thu Jan 01 00:00:00 1970 +0000
980 981 | | summary: first branch, unrelated
981 982 | |
982 983 o | changeset: 4:88176d361b69
983 984 | | user: test
984 985 | | date: Thu Jan 01 00:00:00 1970 +0000
985 986 | | summary: add foo, related
986 987 | |
987 988 o | changeset: 3:dd78ae4afb56
988 989 | | user: test
989 990 | | date: Thu Jan 01 00:00:00 1970 +0000
990 991 | | summary: delete foo, unrelated
991 992 | |
992 993 o | changeset: 2:c4c64aedf0f7
993 994 | | user: test
994 995 | | date: Thu Jan 01 00:00:00 1970 +0000
995 996 | | summary: add unrelated old foo
996 997 | |
997 998 o | changeset: 1:e5faa7440653
998 999 |/ user: test
999 1000 | date: Thu Jan 01 00:00:00 1970 +0000
1000 1001 | summary: change, unrelated
1001 1002 |
1002 1003 o changeset: 0:e87515fd044a
1003 1004 user: test
1004 1005 date: Thu Jan 01 00:00:00 1970 +0000
1005 1006 summary: init, unrelated
1006 1007
1007 1008
1008 1009 $ hg --traceback log -f foo
1009 1010 changeset: 10:4dae8563d2c5
1010 1011 tag: tip
1011 1012 parent: 9:7b35701b003e
1012 1013 parent: 4:88176d361b69
1013 1014 user: test
1014 1015 date: Thu Jan 01 00:00:00 1970 +0000
1015 1016 summary: Last merge, related
1016 1017
1017 1018 changeset: 9:7b35701b003e
1018 1019 parent: 8:e5416ad8a855
1019 1020 parent: 7:87fe3144dcfa
1020 1021 user: test
1021 1022 date: Thu Jan 01 00:00:00 1970 +0000
1022 1023 summary: First merge, related
1023 1024
1024 1025 changeset: 8:e5416ad8a855
1025 1026 parent: 6:dc6c325fe5ee
1026 1027 user: test
1027 1028 date: Thu Jan 01 00:00:00 1970 +0000
1028 1029 summary: change foo in branch, related
1029 1030
1030 1031 changeset: 7:87fe3144dcfa
1031 1032 user: test
1032 1033 date: Thu Jan 01 00:00:00 1970 +0000
1033 1034 summary: change foo, related
1034 1035
1035 1036 changeset: 6:dc6c325fe5ee
1036 1037 user: test
1037 1038 date: Thu Jan 01 00:00:00 1970 +0000
1038 1039 summary: create foo, related
1039 1040
1040 1041 changeset: 4:88176d361b69
1041 1042 user: test
1042 1043 date: Thu Jan 01 00:00:00 1970 +0000
1043 1044 summary: add foo, related
1044 1045
1045 1046
1046 1047 Also check when maxrev < lastrevfilelog
1047 1048
1048 1049 $ hg --traceback log -f -r4 foo
1049 1050 changeset: 4:88176d361b69
1050 1051 user: test
1051 1052 date: Thu Jan 01 00:00:00 1970 +0000
1052 1053 summary: add foo, related
1053 1054
1054 1055
1055 1056 Issue2383: hg log showing _less_ differences than hg diff
1056 1057
1057 1058 $ hg init issue2383
1058 1059 $ cd issue2383
1059 1060
1060 1061 Create a test repo:
1061 1062
1062 1063 $ echo a > a
1063 1064 $ hg ci -Am0
1064 1065 adding a
1065 1066 $ echo b > b
1066 1067 $ hg ci -Am1
1067 1068 adding b
1068 1069 $ hg co 0
1069 1070 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1070 1071 $ echo b > a
1071 1072 $ hg ci -m2
1072 1073 created new head
1073 1074
1074 1075 Merge:
1075 1076
1076 1077 $ hg merge
1077 1078 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1078 1079 (branch merge, don't forget to commit)
1079 1080
1080 1081 Make sure there's a file listed in the merge to trigger the bug:
1081 1082
1082 1083 $ echo c > a
1083 1084 $ hg ci -m3
1084 1085
1085 1086 Two files shown here in diff:
1086 1087
1087 1088 $ hg diff --rev 2:3
1088 1089 diff -r b09be438c43a -r 8e07aafe1edc a
1089 1090 --- a/a Thu Jan 01 00:00:00 1970 +0000
1090 1091 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1091 1092 @@ -1,1 +1,1 @@
1092 1093 -b
1093 1094 +c
1094 1095 diff -r b09be438c43a -r 8e07aafe1edc b
1095 1096 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1096 1097 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1097 1098 @@ -0,0 +1,1 @@
1098 1099 +b
1099 1100
1100 1101 Diff here should be the same:
1101 1102
1102 1103 $ hg log -vpr 3
1103 1104 changeset: 3:8e07aafe1edc
1104 1105 tag: tip
1105 1106 parent: 2:b09be438c43a
1106 1107 parent: 1:925d80f479bb
1107 1108 user: test
1108 1109 date: Thu Jan 01 00:00:00 1970 +0000
1109 1110 files: a
1110 1111 description:
1111 1112 3
1112 1113
1113 1114
1114 1115 diff -r b09be438c43a -r 8e07aafe1edc a
1115 1116 --- a/a Thu Jan 01 00:00:00 1970 +0000
1116 1117 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1117 1118 @@ -1,1 +1,1 @@
1118 1119 -b
1119 1120 +c
1120 1121 diff -r b09be438c43a -r 8e07aafe1edc b
1121 1122 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1122 1123 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1123 1124 @@ -0,0 +1,1 @@
1124 1125 +b
1125 1126
1126 1127 $ cd ..
1127 1128
1128 1129 'hg log -r rev fn' when last(filelog(fn)) != rev
1129 1130
1130 1131 $ hg init simplelog; cd simplelog
1131 1132 $ echo f > a
1132 1133 $ hg ci -Am'a' -d '0 0'
1133 1134 adding a
1134 1135 $ echo f >> a
1135 1136 $ hg ci -Am'a bis' -d '1 0'
1136 1137
1137 1138 $ hg log -r0 a
1138 1139 changeset: 0:9f758d63dcde
1139 1140 user: test
1140 1141 date: Thu Jan 01 00:00:00 1970 +0000
1141 1142 summary: a
1142 1143
1143 1144 $ cat > $HGTMP/testhidden.py << EOF
1144 1145 > def reposetup(ui, repo):
1145 1146 > for line in repo.opener('hidden'):
1146 1147 > ctx = repo[line.strip()]
1147 1148 > repo.changelog.hiddenrevs.add(ctx.rev())
1148 1149 > EOF
1149 1150 $ echo '[extensions]' >> $HGRCPATH
1150 1151 $ echo "hidden=$HGTMP/testhidden.py" >> $HGRCPATH
1151 1152 $ touch .hg/hidden
1152 1153 $ hg log --template='{rev}:{node}\n'
1153 1154 1:a765632148dc55d38c35c4f247c618701886cb2f
1154 1155 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1155 1156 $ echo a765632148dc55d38c35c4f247c618701886cb2f > .hg/hidden
1156 1157 $ hg log --template='{rev}:{node}\n'
1157 1158 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1158 1159 $ hg log --template='{rev}:{node}\n' --hidden
1159 1160 1:a765632148dc55d38c35c4f247c618701886cb2f
1160 1161 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
@@ -1,85 +1,86 b''
1 1 $ hgcommit() {
2 2 > hg commit -u user "$@"
3 3 > }
4 4
5 5 $ hg init clhead
6 6 $ cd clhead
7 7
8 8 $ touch foo && hg add && hgcommit -m 'foo'
9 9 adding foo
10 10 $ touch bar && hg add && hgcommit -m 'bar'
11 11 adding bar
12 12 $ touch baz && hg add && hgcommit -m 'baz'
13 13 adding baz
14 14
15 15 $ echo "flub" > foo
16 16 $ hgcommit -m "flub"
17 17 $ echo "nub" > foo
18 18 $ hgcommit -m "nub"
19 19
20 20 $ hg up -C 2
21 21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 22
23 23 $ echo "c1" > c1
24 24 $ hg add c1
25 25 $ hgcommit -m "c1"
26 26 created new head
27 27 $ echo "c2" > c1
28 28 $ hgcommit -m "c2"
29 29
30 30 $ hg up -C 2
31 31 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
32 32
33 33 $ echo "d1" > d1
34 34 $ hg add d1
35 35 $ hgcommit -m "d1"
36 36 created new head
37 37 $ echo "d2" > d1
38 38 $ hgcommit -m "d2"
39 39 $ hg tag -l good
40 40
41 41 fail with three heads
42 42 $ hg up -C good
43 43 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
44 44 $ hg merge
45 45 abort: branch 'default' has 3 heads - please merge with an explicit rev
46 46 (run 'hg heads .' to see heads)
47 47 [255]
48 48
49 49 close one of the heads
50 50 $ hg up -C 6
51 51 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
52 52 $ hgcommit -m 'close this head' --close-branch
53 53
54 54 succeed with two open heads
55 55 $ hg up -C good
56 56 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
57 57 $ hg up -C good
58 58 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
59 59 $ hg merge
60 60 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
61 61 (branch merge, don't forget to commit)
62 62 $ hgcommit -m 'merged heads'
63 63
64 64 hg update -C 8
65 65 $ hg update -C 8
66 66 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 67
68 68 hg branch some-branch
69 69 $ hg branch some-branch
70 70 marked working directory as branch some-branch
71 (branches are permanent and global, did you want a bookmark?)
71 72 hg commit
72 73 $ hgcommit -m 'started some-branch'
73 74 hg commit --close-branch
74 75 $ hgcommit --close-branch -m 'closed some-branch'
75 76
76 77 hg update default
77 78 $ hg update default
78 79 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
79 80 hg merge some-branch
80 81 $ hg merge some-branch
81 82 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
82 83 (branch merge, don't forget to commit)
83 84 hg commit (no reopening of some-branch)
84 85 $ hgcommit -m 'merge with closed branch'
85 86
@@ -1,110 +1,111 b''
1 1 $ hg init
2 2 $ echo a > a
3 3 $ hg commit -A -ma
4 4 adding a
5 5
6 6 $ echo b >> a
7 7 $ hg commit -mb
8 8
9 9 $ echo c >> a
10 10 $ hg commit -mc
11 11
12 12 $ hg up 1
13 13 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
14 14 $ echo d >> a
15 15 $ hg commit -md
16 16 created new head
17 17
18 18 $ hg up 1
19 19 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
20 20 $ echo e >> a
21 21 $ hg commit -me
22 22 created new head
23 23
24 24 $ hg up 1
25 25 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
26 26
27 27 Should fail because not at a head:
28 28
29 29 $ hg merge
30 30 abort: branch 'default' has 3 heads - please merge with an explicit rev
31 31 (run 'hg heads .' to see heads)
32 32 [255]
33 33
34 34 $ hg up
35 35 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
36 36
37 37 Should fail because > 2 heads:
38 38
39 39 $ HGMERGE=internal:other; export HGMERGE
40 40 $ hg merge
41 41 abort: branch 'default' has 3 heads - please merge with an explicit rev
42 42 (run 'hg heads .' to see heads)
43 43 [255]
44 44
45 45 Should succeed:
46 46
47 47 $ hg merge 2
48 48 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
49 49 (branch merge, don't forget to commit)
50 50 $ hg commit -mm1
51 51
52 52 Should succeed - 2 heads:
53 53
54 54 $ hg merge -P
55 55 changeset: 3:ea9ff125ff88
56 56 parent: 1:1846eede8b68
57 57 user: test
58 58 date: Thu Jan 01 00:00:00 1970 +0000
59 59 summary: d
60 60
61 61 $ hg merge
62 62 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
63 63 (branch merge, don't forget to commit)
64 64 $ hg commit -mm2
65 65
66 66 Should fail because at tip:
67 67
68 68 $ hg merge
69 69 abort: nothing to merge
70 70 [255]
71 71
72 72 $ hg up 0
73 73 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
74 74
75 75 Should fail because there is only one head:
76 76
77 77 $ hg merge
78 78 abort: nothing to merge
79 79 (use 'hg update' instead)
80 80 [255]
81 81
82 82 $ hg up 3
83 83 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
84 84
85 85 $ echo f >> a
86 86 $ hg branch foobranch
87 87 marked working directory as branch foobranch
88 (branches are permanent and global, did you want a bookmark?)
88 89 $ hg commit -mf
89 90
90 91 Should fail because merge with other branch:
91 92
92 93 $ hg merge
93 94 abort: branch 'foobranch' has one head - please merge with an explicit rev
94 95 (run 'hg heads' to see all heads)
95 96 [255]
96 97
97 98
98 99 Test for issue2043: ensure that 'merge -P' shows ancestors of 6 that
99 100 are not ancestors of 7, regardless of where their least common
100 101 ancestor is.
101 102
102 103 Merge preview not affected by common ancestor:
103 104
104 105 $ hg up -q 7
105 106 $ hg merge -q -P 6
106 107 2:2d95304fed5d
107 108 4:f25cbe84d8b3
108 109 5:a431fabd6039
109 110 6:e88e33f3bf62
110 111
@@ -1,175 +1,177 b''
1 1 $ echo '[extensions]' >> $HGRCPATH
2 2 $ echo 'mq =' >> $HGRCPATH
3 3
4 4 $ hg init repo
5 5 $ cd repo
6 6
7 7 $ echo foo > foo
8 8 $ hg ci -qAm 'add a file'
9 9
10 10 $ hg qinit
11 11
12 12 $ hg qnew foo
13 13 $ echo foo >> foo
14 14 $ hg qrefresh -m 'append foo'
15 15
16 16 $ hg qnew bar
17 17 $ echo bar >> foo
18 18 $ hg qrefresh -m 'append bar'
19 19
20 20
21 21 try to commit on top of a patch
22 22
23 23 $ echo quux >> foo
24 24 $ hg ci -m 'append quux'
25 25 abort: cannot commit over an applied mq patch
26 26 [255]
27 27
28 28
29 29 cheat a bit...
30 30
31 31 $ mv .hg/patches .hg/patches2
32 32 $ hg ci -m 'append quux'
33 33 $ mv .hg/patches2 .hg/patches
34 34
35 35
36 36 qpop/qrefresh on the wrong revision
37 37
38 38 $ hg qpop
39 39 abort: popping would remove a revision not managed by this patch queue
40 40 [255]
41 41 $ hg qpop -n patches
42 42 using patch queue: $TESTTMP/repo/.hg/patches (glob)
43 43 abort: popping would remove a revision not managed by this patch queue
44 44 [255]
45 45 $ hg qrefresh
46 46 abort: working directory revision is not qtip
47 47 [255]
48 48
49 49 $ hg up -C qtip
50 50 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
51 51 $ hg qpop
52 52 abort: popping would remove a revision not managed by this patch queue
53 53 [255]
54 54 $ hg qrefresh
55 55 abort: cannot refresh a revision with children
56 56 [255]
57 57 $ hg tip --template '{rev} {desc}\n'
58 58 3 append quux
59 59
60 60
61 61 qpush warning branchheads
62 62
63 63 $ cd ..
64 64 $ hg init branchy
65 65 $ cd branchy
66 66 $ echo q > q
67 67 $ hg add q
68 68 $ hg qnew -f qp
69 69 $ hg qpop
70 70 popping qp
71 71 patch queue now empty
72 72 $ echo a > a
73 73 $ hg ci -Ama
74 74 adding a
75 75 $ hg up null
76 76 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
77 77 $ hg branch b
78 78 marked working directory as branch b
79 (branches are permanent and global, did you want a bookmark?)
79 80 $ echo c > c
80 81 $ hg ci -Amc
81 82 adding c
82 83 $ hg merge default
83 84 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
84 85 (branch merge, don't forget to commit)
85 86 $ hg ci -mmerge
86 87 $ hg up default
87 88 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
88 89 $ hg log
89 90 changeset: 2:65309210bf4e
90 91 branch: b
91 92 tag: tip
92 93 parent: 1:707adb4c8ae1
93 94 parent: 0:cb9a9f314b8b
94 95 user: test
95 96 date: Thu Jan 01 00:00:00 1970 +0000
96 97 summary: merge
97 98
98 99 changeset: 1:707adb4c8ae1
99 100 branch: b
100 101 parent: -1:000000000000
101 102 user: test
102 103 date: Thu Jan 01 00:00:00 1970 +0000
103 104 summary: c
104 105
105 106 changeset: 0:cb9a9f314b8b
106 107 user: test
107 108 date: Thu Jan 01 00:00:00 1970 +0000
108 109 summary: a
109 110
110 111 $ hg qpush
111 112 applying qp
112 113 now at: qp
113 114
114 115 Testing applied patches, push and --force
115 116
116 117 $ cd ..
117 118 $ hg init forcepush
118 119 $ cd forcepush
119 120 $ echo a > a
120 121 $ hg ci -Am adda
121 122 adding a
122 123 $ echo a >> a
123 124 $ hg ci -m changea
124 125 $ hg up 0
125 126 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 127 $ hg branch branch
127 128 marked working directory as branch branch
129 (branches are permanent and global, did you want a bookmark?)
128 130 $ echo b > b
129 131 $ hg ci -Am addb
130 132 adding b
131 133 $ hg up 0
132 134 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
133 135 $ hg --cwd .. clone -r 0 forcepush forcepush2
134 136 adding changesets
135 137 adding manifests
136 138 adding file changes
137 139 added 1 changesets with 1 changes to 1 files
138 140 updating to branch default
139 141 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 142 $ echo a >> a
141 143 $ hg qnew patch
142 144
143 145 Pushing applied patch with --rev without --force
144 146
145 147 $ hg push -r default ../forcepush2
146 148 pushing to ../forcepush2
147 149 abort: source has mq patches applied
148 150 [255]
149 151
150 152 Pushing applied patch with branchhash, without --force
151 153
152 154 $ hg push ../forcepush2#default
153 155 pushing to ../forcepush2
154 156 abort: source has mq patches applied
155 157 [255]
156 158
157 159 Pushing revs excluding applied patch
158 160
159 161 $ hg push --new-branch -r branch -r 2 ../forcepush2
160 162 pushing to ../forcepush2
161 163 searching for changes
162 164 adding changesets
163 165 adding manifests
164 166 adding file changes
165 167 added 1 changesets with 1 changes to 1 files
166 168
167 169 Pushing applied patch with --force
168 170
169 171 $ hg push --force -r default ../forcepush2
170 172 pushing to ../forcepush2
171 173 searching for changes
172 174 adding changesets
173 175 adding manifests
174 176 adding file changes
175 177 added 1 changesets with 1 changes to 1 files (+1 heads)
@@ -1,322 +1,328 b''
1 1 $ branchcache=.hg/cache/branchheads
2 2
3 3 $ hg init t
4 4 $ cd t
5 5
6 6 $ hg branches
7 7 $ echo foo > a
8 8 $ hg add a
9 9 $ hg ci -m "initial"
10 10 $ hg branch foo
11 11 marked working directory as branch foo
12 (branches are permanent and global, did you want a bookmark?)
12 13 $ hg branch
13 14 foo
14 15 $ hg ci -m "add branch name"
15 16 $ hg branch bar
16 17 marked working directory as branch bar
18 (branches are permanent and global, did you want a bookmark?)
17 19 $ hg ci -m "change branch name"
18 20
19 21 Branch shadowing:
20 22
21 23 $ hg branch default
22 24 abort: a branch of the same name already exists
23 25 (use 'hg update' to switch to it)
24 26 [255]
25 27
26 28 $ hg branch -f default
27 29 marked working directory as branch default
30 (branches are permanent and global, did you want a bookmark?)
28 31
29 32 $ hg ci -m "clear branch name"
30 33 created new head
31 34
32 35 There should be only one default branch head
33 36
34 37 $ hg heads .
35 38 changeset: 3:1c28f494dae6
36 39 tag: tip
37 40 user: test
38 41 date: Thu Jan 01 00:00:00 1970 +0000
39 42 summary: clear branch name
40 43
41 44
42 45 $ hg co foo
43 46 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
44 47 $ hg branch
45 48 foo
46 49 $ echo bleah > a
47 50 $ hg ci -m "modify a branch"
48 51
49 52 $ hg merge default
50 53 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
51 54 (branch merge, don't forget to commit)
52 55
53 56 $ hg branch
54 57 foo
55 58 $ hg ci -m "merge"
56 59
57 60 $ hg log
58 61 changeset: 5:530046499edf
59 62 branch: foo
60 63 tag: tip
61 64 parent: 4:adf1a74a7f7b
62 65 parent: 3:1c28f494dae6
63 66 user: test
64 67 date: Thu Jan 01 00:00:00 1970 +0000
65 68 summary: merge
66 69
67 70 changeset: 4:adf1a74a7f7b
68 71 branch: foo
69 72 parent: 1:6c0e42da283a
70 73 user: test
71 74 date: Thu Jan 01 00:00:00 1970 +0000
72 75 summary: modify a branch
73 76
74 77 changeset: 3:1c28f494dae6
75 78 user: test
76 79 date: Thu Jan 01 00:00:00 1970 +0000
77 80 summary: clear branch name
78 81
79 82 changeset: 2:c21617b13b22
80 83 branch: bar
81 84 user: test
82 85 date: Thu Jan 01 00:00:00 1970 +0000
83 86 summary: change branch name
84 87
85 88 changeset: 1:6c0e42da283a
86 89 branch: foo
87 90 user: test
88 91 date: Thu Jan 01 00:00:00 1970 +0000
89 92 summary: add branch name
90 93
91 94 changeset: 0:db01e8ea3388
92 95 user: test
93 96 date: Thu Jan 01 00:00:00 1970 +0000
94 97 summary: initial
95 98
96 99 $ hg branches
97 100 foo 5:530046499edf
98 101 default 3:1c28f494dae6 (inactive)
99 102 bar 2:c21617b13b22 (inactive)
100 103
101 104 $ hg branches -q
102 105 foo
103 106 default
104 107 bar
105 108
106 109 Test for invalid branch cache:
107 110
108 111 $ hg rollback
109 112 repository tip rolled back to revision 4 (undo commit)
110 113 working directory now based on revisions 4 and 3
111 114
112 115 $ cp $branchcache .hg/bc-invalid
113 116
114 117 $ hg log -r foo
115 118 changeset: 4:adf1a74a7f7b
116 119 branch: foo
117 120 tag: tip
118 121 parent: 1:6c0e42da283a
119 122 user: test
120 123 date: Thu Jan 01 00:00:00 1970 +0000
121 124 summary: modify a branch
122 125
123 126 $ cp .hg/bc-invalid $branchcache
124 127
125 128 $ hg --debug log -r foo
126 129 invalidating branch cache (tip differs)
127 130 changeset: 4:adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6
128 131 branch: foo
129 132 tag: tip
130 133 parent: 1:6c0e42da283a56b5edc5b4fadb491365ec7f5fa8
131 134 parent: -1:0000000000000000000000000000000000000000
132 135 manifest: 1:8c342a37dfba0b3d3ce073562a00d8a813c54ffe
133 136 user: test
134 137 date: Thu Jan 01 00:00:00 1970 +0000
135 138 files: a
136 139 extra: branch=foo
137 140 description:
138 141 modify a branch
139 142
140 143
141 144 $ rm $branchcache
142 145 $ echo corrupted > $branchcache
143 146
144 147 $ hg log -qr foo
145 148 4:adf1a74a7f7b
146 149
147 150 $ cat $branchcache
148 151 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4
149 152 1c28f494dae69a2f8fc815059d257eccf3fcfe75 default
150 153 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 foo
151 154 c21617b13b220988e7a2e26290fbe4325ffa7139 bar
152 155
153 156 Push should update the branch cache:
154 157
155 158 $ hg init ../target
156 159
157 160 Pushing just rev 0:
158 161
159 162 $ hg push -qr 0 ../target
160 163
161 164 $ cat ../target/$branchcache
162 165 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 0
163 166 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 default
164 167
165 168 Pushing everything:
166 169
167 170 $ hg push -qf ../target
168 171
169 172 $ cat ../target/$branchcache
170 173 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4
171 174 1c28f494dae69a2f8fc815059d257eccf3fcfe75 default
172 175 adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 foo
173 176 c21617b13b220988e7a2e26290fbe4325ffa7139 bar
174 177
175 178 Update with no arguments: tipmost revision of the current branch:
176 179
177 180 $ hg up -q -C 0
178 181 $ hg up -q
179 182 $ hg id
180 183 1c28f494dae6
181 184
182 185 $ hg up -q 1
183 186 $ hg up -q
184 187 $ hg id
185 188 adf1a74a7f7b (foo) tip
186 189
187 190 $ hg branch foobar
188 191 marked working directory as branch foobar
192 (branches are permanent and global, did you want a bookmark?)
189 193
190 194 $ hg up
191 195 abort: branch foobar not found
192 196 [255]
193 197
194 198 Fastforward merge:
195 199
196 200 $ hg branch ff
197 201 marked working directory as branch ff
202 (branches are permanent and global, did you want a bookmark?)
198 203
199 204 $ echo ff > ff
200 205 $ hg ci -Am'fast forward'
201 206 adding ff
202 207
203 208 $ hg up foo
204 209 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
205 210
206 211 $ hg merge ff
207 212 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
208 213 (branch merge, don't forget to commit)
209 214
210 215 $ hg branch
211 216 foo
212 217 $ hg commit -m'Merge ff into foo'
213 218 $ hg parents
214 219 changeset: 6:185ffbfefa30
215 220 branch: foo
216 221 tag: tip
217 222 parent: 4:adf1a74a7f7b
218 223 parent: 5:1a3c27dc5e11
219 224 user: test
220 225 date: Thu Jan 01 00:00:00 1970 +0000
221 226 summary: Merge ff into foo
222 227
223 228 $ hg manifest
224 229 a
225 230 ff
226 231
227 232
228 233 Test merging, add 3 default heads and one test head:
229 234
230 235 $ cd ..
231 236 $ hg init merges
232 237 $ cd merges
233 238 $ echo a > a
234 239 $ hg ci -Ama
235 240 adding a
236 241
237 242 $ echo b > b
238 243 $ hg ci -Amb
239 244 adding b
240 245
241 246 $ hg up 0
242 247 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
243 248 $ echo c > c
244 249 $ hg ci -Amc
245 250 adding c
246 251 created new head
247 252
248 253 $ hg up 0
249 254 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
250 255 $ echo d > d
251 256 $ hg ci -Amd
252 257 adding d
253 258 created new head
254 259
255 260 $ hg up 0
256 261 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
257 262 $ hg branch test
258 263 marked working directory as branch test
264 (branches are permanent and global, did you want a bookmark?)
259 265 $ echo e >> e
260 266 $ hg ci -Ame
261 267 adding e
262 268
263 269 $ hg log
264 270 changeset: 4:3a1e01ed1df4
265 271 branch: test
266 272 tag: tip
267 273 parent: 0:cb9a9f314b8b
268 274 user: test
269 275 date: Thu Jan 01 00:00:00 1970 +0000
270 276 summary: e
271 277
272 278 changeset: 3:980f7dc84c29
273 279 parent: 0:cb9a9f314b8b
274 280 user: test
275 281 date: Thu Jan 01 00:00:00 1970 +0000
276 282 summary: d
277 283
278 284 changeset: 2:d36c0562f908
279 285 parent: 0:cb9a9f314b8b
280 286 user: test
281 287 date: Thu Jan 01 00:00:00 1970 +0000
282 288 summary: c
283 289
284 290 changeset: 1:d2ae7f538514
285 291 user: test
286 292 date: Thu Jan 01 00:00:00 1970 +0000
287 293 summary: b
288 294
289 295 changeset: 0:cb9a9f314b8b
290 296 user: test
291 297 date: Thu Jan 01 00:00:00 1970 +0000
292 298 summary: a
293 299
294 300 Implicit merge with test branch as parent:
295 301
296 302 $ hg merge
297 303 abort: branch 'test' has one head - please merge with an explicit rev
298 304 (run 'hg heads' to see all heads)
299 305 [255]
300 306 $ hg up -C default
301 307 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
302 308
303 309 Implicit merge with default branch as parent:
304 310
305 311 $ hg merge
306 312 abort: branch 'default' has 3 heads - please merge with an explicit rev
307 313 (run 'hg heads .' to see heads)
308 314 [255]
309 315
310 316 3 branch heads, explicit merge required:
311 317
312 318 $ hg merge 2
313 319 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
314 320 (branch merge, don't forget to commit)
315 321 $ hg ci -m merge
316 322
317 323 2 branch heads, implicit merge works:
318 324
319 325 $ hg merge
320 326 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
321 327 (branch merge, don't forget to commit)
322 328
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now