##// END OF EJS Templates
merge with stable
Martin Geisler -
r13234:0935ff76 merge default
parent child Browse files
Show More
@@ -1,1099 +1,1100 b''
1 1 ======
2 2 hgrc
3 3 ======
4 4
5 5 ---------------------------------
6 6 configuration files for Mercurial
7 7 ---------------------------------
8 8
9 9 :Author: Bryan O'Sullivan <bos@serpentine.com>
10 10 :Organization: Mercurial
11 11 :Manual section: 5
12 12 :Manual group: Mercurial Manual
13 13
14 14 .. contents::
15 15 :backlinks: top
16 16 :class: htmlonly
17 17
18 18
19 19 Synopsis
20 20 --------
21 21
22 22 The Mercurial system uses a set of configuration files to control
23 23 aspects of its behavior.
24 24
25 25 Files
26 26 -----
27 27
28 28 Mercurial reads configuration data from several files, if they exist.
29 29 The names of these files depend on the system on which Mercurial is
30 30 installed. ``*.rc`` files from a single directory are read in
31 31 alphabetical order, later ones overriding earlier ones. Where multiple
32 32 paths are given below, settings from earlier paths override later
33 33 ones.
34 34
35 35 | (Unix, Windows) ``<repo>/.hg/hgrc``
36 36
37 37 Per-repository configuration options that only apply in a
38 38 particular repository. This file is not version-controlled, and
39 39 will not get transferred during a "clone" operation. Options in
40 40 this file override options in all other configuration files. On
41 41 Unix, most of this file will be ignored if it doesn't belong to a
42 42 trusted user or to a trusted group. See the documentation for the
43 43 trusted_ section below for more details.
44 44
45 45 | (Unix) ``$HOME/.hgrc``
46 46 | (Windows) ``%USERPROFILE%\.hgrc``
47 47 | (Windows) ``%USERPROFILE%\Mercurial.ini``
48 48 | (Windows) ``%HOME%\.hgrc``
49 49 | (Windows) ``%HOME%\Mercurial.ini``
50 50
51 51 Per-user configuration file(s), for the user running Mercurial. On
52 52 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
53 53 files apply to all Mercurial commands executed by this user in any
54 54 directory. Options in these files override per-system and per-installation
55 55 options.
56 56
57 57 | (Unix) ``/etc/mercurial/hgrc``
58 58 | (Unix) ``/etc/mercurial/hgrc.d/*.rc``
59 59
60 60 Per-system configuration files, for the system on which Mercurial
61 61 is running. Options in these files apply to all Mercurial commands
62 62 executed by any user in any directory. Options in these files
63 63 override per-installation options.
64 64
65 65 | (Unix) ``<install-root>/etc/mercurial/hgrc``
66 66 | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
67 67
68 68 Per-installation configuration files, searched for in the
69 69 directory where Mercurial is installed. ``<install-root>`` is the
70 70 parent directory of the **hg** executable (or symlink) being run. For
71 71 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
72 72 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
73 73 to all Mercurial commands executed by any user in any directory.
74 74
75 75 | (Windows) ``<install-dir>\Mercurial.ini``
76 76 | (Windows) ``<install-dir>\hgrc.d\*.rc``
77 77 | (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial``
78 78
79 79 Per-installation/system configuration files, for the system on
80 80 which Mercurial is running. Options in these files apply to all
81 81 Mercurial commands executed by any user in any directory. Registry
82 82 keys contain PATH-like strings, every part of which must reference
83 83 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
84 84 be read. Mercurial checks each of these locations in the specified
85 85 order until one or more configuration files are detected. If the
86 86 pywin32 extensions are not installed, Mercurial will only look for
87 87 site-wide configuration in ``C:\Mercurial\Mercurial.ini``.
88 88
89 89 Syntax
90 90 ------
91 91
92 92 A configuration file consists of sections, led by a ``[section]`` header
93 93 and followed by ``name = value`` entries (sometimes called
94 94 ``configuration keys``)::
95 95
96 96 [spam]
97 97 eggs=ham
98 98 green=
99 99 eggs
100 100
101 101 Each line contains one entry. If the lines that follow are indented,
102 102 they are treated as continuations of that entry. Leading whitespace is
103 103 removed from values. Empty lines are skipped. Lines beginning with
104 104 ``#`` or ``;`` are ignored and may be used to provide comments.
105 105
106 106 Configuration keys can be set multiple times, in which case mercurial
107 107 will use the value that was configured last. As an example::
108 108
109 109 [spam]
110 110 eggs=large
111 111 ham=serrano
112 112 eggs=small
113 113
114 114 This would set the configuration key named ``eggs`` to ``small``.
115 115
116 116 It is also possible to define a section multiple times. A section can
117 117 be redefined on the same and/or on different hgrc files. For example::
118 118
119 119 [foo]
120 120 eggs=large
121 121 ham=serrano
122 122 eggs=small
123 123
124 124 [bar]
125 125 eggs=ham
126 126 green=
127 127 eggs
128 128
129 129 [foo]
130 130 ham=prosciutto
131 131 eggs=medium
132 132 bread=toasted
133 133
134 134 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
135 135 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
136 136 respectively. As you can see there only thing that matters is the last
137 137 value that was set for each of the configuration keys.
138 138
139 139 If a configuration key is set multiple times in different
140 140 configuration files the final value will depend on the order in which
141 141 the different configuration files are read, with settings from earlier
142 142 paths overriding later ones as described on the ``Files`` section
143 143 above.
144 144
145 145 A line of the form ``%include file`` will include ``file`` into the
146 146 current configuration file. The inclusion is recursive, which means
147 147 that included files can include other files. Filenames are relative to
148 148 the configuration file in which the ``%include`` directive is found.
149 149 Environment variables and ``~user`` constructs are expanded in
150 150 ``file``. This lets you do something like::
151 151
152 152 %include ~/.hgrc.d/$HOST.rc
153 153
154 154 to include a different configuration file on each computer you use.
155 155
156 156 A line with ``%unset name`` will remove ``name`` from the current
157 157 section, if it has been set previously.
158 158
159 159 The values are either free-form text strings, lists of text strings,
160 160 or Boolean values. Boolean values can be set to true using any of "1",
161 161 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
162 162 (all case insensitive).
163 163
164 164 List values are separated by whitespace or comma, except when values are
165 165 placed in double quotation marks::
166 166
167 167 allow_read = "John Doe, PhD", brian, betty
168 168
169 169 Quotation marks can be escaped by prefixing them with a backslash. Only
170 170 quotation marks at the beginning of a word is counted as a quotation
171 171 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
172 172
173 173 Sections
174 174 --------
175 175
176 176 This section describes the different sections that may appear in a
177 177 Mercurial "hgrc" file, the purpose of each section, its possible keys,
178 178 and their possible values.
179 179
180 180 ``alias``
181 181 """""""""
182 182 Defines command aliases.
183 183 Aliases allow you to define your own commands in terms of other
184 184 commands (or aliases), optionally including arguments.
185 185
186 186 Alias definitions consist of lines of the form::
187 187
188 188 <alias> = <command> [<argument]...
189 189
190 190 For example, this definition::
191 191
192 192 latest = log --limit 5
193 193
194 194 creates a new command ``latest`` that shows only the five most recent
195 195 changesets. You can define subsequent aliases using earlier ones::
196 196
197 197 stable5 = latest -b stable
198 198
199 199 .. note:: It is possible to create aliases with the same names as
200 200 existing commands, which will then override the original
201 201 definitions. This is almost always a bad idea!
202 202
203 203
204 204 ``auth``
205 205 """"""""
206 206
207 207 Authentication credentials for HTTP authentication. This section
208 208 allows you to store usernames and passwords for use when logging
209 209 *into* HTTP servers. See the web_ configuration section if you want to
210 210 configure *who* can login to your HTTP server.
211 211
212 212 Each line has the following format::
213 213
214 214 <name>.<argument> = <value>
215 215
216 216 where ``<name>`` is used to group arguments into authentication
217 217 entries. Example::
218 218
219 219 foo.prefix = hg.intevation.org/mercurial
220 220 foo.username = foo
221 221 foo.password = bar
222 222 foo.schemes = http https
223 223
224 224 bar.prefix = secure.example.org
225 225 bar.key = path/to/file.key
226 226 bar.cert = path/to/file.cert
227 227 bar.schemes = https
228 228
229 229 Supported arguments:
230 230
231 231 ``prefix``
232 232 Either ``*`` or a URI prefix with or without the scheme part.
233 233 The authentication entry with the longest matching prefix is used
234 234 (where ``*`` matches everything and counts as a match of length
235 235 1). If the prefix doesn't include a scheme, the match is performed
236 236 against the URI with its scheme stripped as well, and the schemes
237 237 argument, q.v., is then subsequently consulted.
238 238 ``username``
239 239 Optional. Username to authenticate with. If not given, and the
240 240 remote site requires basic or digest authentication, the user will
241 241 be prompted for it. Environment variables are expanded in the
242 242 username letting you do ``foo.username = $USER``.
243 243 ``password``
244 244 Optional. Password to authenticate with. If not given, and the
245 245 remote site requires basic or digest authentication, the user
246 246 will be prompted for it.
247 247 ``key``
248 248 Optional. PEM encoded client certificate key file. Environment
249 249 variables are expanded in the filename.
250 250 ``cert``
251 251 Optional. PEM encoded client certificate chain file. Environment
252 252 variables are expanded in the filename.
253 253 ``schemes``
254 254 Optional. Space separated list of URI schemes to use this
255 255 authentication entry with. Only used if the prefix doesn't include
256 256 a scheme. Supported schemes are http and https. They will match
257 257 static-http and static-https respectively, as well.
258 258 Default: https.
259 259
260 260 If no suitable authentication entry is found, the user is prompted
261 261 for credentials as usual if required by the remote.
262 262
263 263
264 264 ``decode/encode``
265 265 """""""""""""""""
266 266 Filters for transforming files on checkout/checkin. This would
267 267 typically be used for newline processing or other
268 268 localization/canonicalization of files.
269 269
270 270 Filters consist of a filter pattern followed by a filter command.
271 271 Filter patterns are globs by default, rooted at the repository root.
272 272 For example, to match any file ending in ``.txt`` in the root
273 273 directory only, use the pattern ``*.txt``. To match any file ending
274 274 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
275 275 For each file only the first matching filter applies.
276 276
277 277 The filter command can start with a specifier, either ``pipe:`` or
278 278 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
279 279
280 280 A ``pipe:`` command must accept data on stdin and return the transformed
281 281 data on stdout.
282 282
283 283 Pipe example::
284 284
285 285 [encode]
286 286 # uncompress gzip files on checkin to improve delta compression
287 287 # note: not necessarily a good idea, just an example
288 288 *.gz = pipe: gunzip
289 289
290 290 [decode]
291 291 # recompress gzip files when writing them to the working dir (we
292 292 # can safely omit "pipe:", because it's the default)
293 293 *.gz = gzip
294 294
295 295 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
296 296 with the name of a temporary file that contains the data to be
297 297 filtered by the command. The string ``OUTFILE`` is replaced with the name
298 298 of an empty temporary file, where the filtered data must be written by
299 299 the command.
300 300
301 301 .. note:: The tempfile mechanism is recommended for Windows systems,
302 302 where the standard shell I/O redirection operators often have
303 303 strange effects and may corrupt the contents of your files.
304 304
305 305 This filter mechanism is used internally by the ``eol`` extension to
306 306 translate line ending characters between Windows (CRLF) and Unix (LF)
307 307 format. We suggest you use the ``eol`` extension for convenience.
308 308
309 309
310 310 ``defaults``
311 311 """"""""""""
312 312
313 313 (defaults are deprecated. Don't use them. Use aliases instead)
314 314
315 315 Use the ``[defaults]`` section to define command defaults, i.e. the
316 316 default options/arguments to pass to the specified commands.
317 317
318 318 The following example makes :hg:`log` run in verbose mode, and
319 319 :hg:`status` show only the modified files, by default::
320 320
321 321 [defaults]
322 322 log = -v
323 323 status = -m
324 324
325 325 The actual commands, instead of their aliases, must be used when
326 326 defining command defaults. The command defaults will also be applied
327 327 to the aliases of the commands defined.
328 328
329 329
330 330 ``diff``
331 331 """"""""
332 332
333 333 Settings used when displaying diffs. They are all Boolean and
334 334 defaults to False.
335 335
336 336 ``git``
337 337 Use git extended diff format.
338 338 ``nodates``
339 339 Don't include dates in diff headers.
340 340 ``showfunc``
341 341 Show which function each change is in.
342 342 ``ignorews``
343 343 Ignore white space when comparing lines.
344 344 ``ignorewsamount``
345 345 Ignore changes in the amount of white space.
346 346 ``ignoreblanklines``
347 347 Ignore changes whose lines are all blank.
348 348
349 349 ``email``
350 350 """""""""
351 351 Settings for extensions that send email messages.
352 352
353 353 ``from``
354 354 Optional. Email address to use in "From" header and SMTP envelope
355 355 of outgoing messages.
356 356 ``to``
357 357 Optional. Comma-separated list of recipients' email addresses.
358 358 ``cc``
359 359 Optional. Comma-separated list of carbon copy recipients'
360 360 email addresses.
361 361 ``bcc``
362 362 Optional. Comma-separated list of blind carbon copy recipients'
363 363 email addresses.
364 364 ``method``
365 365 Optional. Method to use to send email messages. If value is ``smtp``
366 366 (default), use SMTP (see the SMTP_ section for configuration).
367 367 Otherwise, use as name of program to run that acts like sendmail
368 368 (takes ``-f`` option for sender, list of recipients on command line,
369 369 message on stdin). Normally, setting this to ``sendmail`` or
370 370 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
371 371 ``charsets``
372 372 Optional. Comma-separated list of character sets considered
373 373 convenient for recipients. Addresses, headers, and parts not
374 374 containing patches of outgoing messages will be encoded in the
375 375 first character set to which conversion from local encoding
376 376 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
377 377 conversion fails, the text in question is sent as is. Defaults to
378 378 empty (explicit) list.
379 379
380 380 Order of outgoing email character sets:
381 381
382 382 1. ``us-ascii``: always first, regardless of settings
383 383 2. ``email.charsets``: in order given by user
384 384 3. ``ui.fallbackencoding``: if not in email.charsets
385 385 4. ``$HGENCODING``: if not in email.charsets
386 386 5. ``utf-8``: always last, regardless of settings
387 387
388 388 Email example::
389 389
390 390 [email]
391 391 from = Joseph User <joe.user@example.com>
392 392 method = /usr/sbin/sendmail
393 393 # charsets for western Europeans
394 394 # us-ascii, utf-8 omitted, as they are tried first and last
395 395 charsets = iso-8859-1, iso-8859-15, windows-1252
396 396
397 397
398 398 ``extensions``
399 399 """"""""""""""
400 400
401 401 Mercurial has an extension mechanism for adding new features. To
402 402 enable an extension, create an entry for it in this section.
403 403
404 404 If you know that the extension is already in Python's search path,
405 405 you can give the name of the module, followed by ``=``, with nothing
406 406 after the ``=``.
407 407
408 408 Otherwise, give a name that you choose, followed by ``=``, followed by
409 409 the path to the ``.py`` file (including the file name extension) that
410 410 defines the extension.
411 411
412 412 To explicitly disable an extension that is enabled in an hgrc of
413 413 broader scope, prepend its path with ``!``, as in
414 414 ``hgext.foo = !/ext/path`` or ``hgext.foo = !`` when path is not
415 415 supplied.
416 416
417 417 Example for ``~/.hgrc``::
418 418
419 419 [extensions]
420 420 # (the mq extension will get loaded from Mercurial's path)
421 421 hgext.mq =
422 422 # (this extension will get loaded from the file specified)
423 423 myfeature = ~/.hgext/myfeature.py
424 424
425 425
426 426 ``format``
427 427 """"""""""
428 428
429 429 ``usestore``
430 430 Enable or disable the "store" repository format which improves
431 431 compatibility with systems that fold case or otherwise mangle
432 432 filenames. Enabled by default. Disabling this option will allow
433 433 you to store longer filenames in some situations at the expense of
434 434 compatibility and ensures that the on-disk format of newly created
435 435 repositories will be compatible with Mercurial before version 0.9.4.
436 436
437 437 ``usefncache``
438 438 Enable or disable the "fncache" repository format which enhances
439 439 the "store" repository format (which has to be enabled to use
440 440 fncache) to allow longer filenames and avoids using Windows
441 441 reserved names, e.g. "nul". Enabled by default. Disabling this
442 442 option ensures that the on-disk format of newly created
443 443 repositories will be compatible with Mercurial before version 1.1.
444 444
445 445 ``dotencode``
446 446 Enable or disable the "dotencode" repository format which enhances
447 447 the "fncache" repository format (which has to be enabled to use
448 448 dotencode) to avoid issues with filenames starting with ._ on
449 449 Mac OS X and spaces on Windows. Enabled by default. Disabling this
450 450 option ensures that the on-disk format of newly created
451 451 repositories will be compatible with Mercurial before version 1.7.
452 452
453 453 ``merge-patterns``
454 454 """"""""""""""""""
455 455
456 456 This section specifies merge tools to associate with particular file
457 457 patterns. Tools matched here will take precedence over the default
458 458 merge tool. Patterns are globs by default, rooted at the repository
459 459 root.
460 460
461 461 Example::
462 462
463 463 [merge-patterns]
464 464 **.c = kdiff3
465 465 **.jpg = myimgmerge
466 466
467 467 ``merge-tools``
468 468 """""""""""""""
469 469
470 470 This section configures external merge tools to use for file-level
471 471 merges.
472 472
473 473 Example ``~/.hgrc``::
474 474
475 475 [merge-tools]
476 476 # Override stock tool location
477 477 kdiff3.executable = ~/bin/kdiff3
478 478 # Specify command line
479 479 kdiff3.args = $base $local $other -o $output
480 480 # Give higher priority
481 481 kdiff3.priority = 1
482 482
483 483 # Define new tool
484 484 myHtmlTool.args = -m $local $other $base $output
485 485 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
486 486 myHtmlTool.priority = 1
487 487
488 488 Supported arguments:
489 489
490 490 ``priority``
491 491 The priority in which to evaluate this tool.
492 492 Default: 0.
493 493 ``executable``
494 494 Either just the name of the executable or its pathname. On Windows,
495 495 the path can use environment variables with ${ProgramFiles} syntax.
496 496 Default: the tool name.
497 497 ``args``
498 498 The arguments to pass to the tool executable. You can refer to the
499 499 files being merged as well as the output file through these
500 500 variables: ``$base``, ``$local``, ``$other``, ``$output``.
501 501 Default: ``$local $base $other``
502 502 ``premerge``
503 503 Attempt to run internal non-interactive 3-way merge tool before
504 504 launching external tool. Options are ``true``, ``false``, or ``keep``
505 505 to leave markers in the file if the premerge fails.
506 506 Default: True
507 507 ``binary``
508 508 This tool can merge binary files. Defaults to False, unless tool
509 509 was selected by file pattern match.
510 510 ``symlink``
511 511 This tool can merge symlinks. Defaults to False, even if tool was
512 512 selected by file pattern match.
513 513 ``check``
514 514 A list of merge success-checking options:
515 515
516 516 ``changed``
517 517 Ask whether merge was successful when the merged file shows no changes.
518 518 ``conflicts``
519 519 Check whether there are conflicts even though the tool reported success.
520 520 ``prompt``
521 521 Always prompt for merge success, regardless of success reported by tool.
522 522
523 523 ``checkchanged``
524 524 True is equivalent to ``check = changed``.
525 525 Default: False
526 526 ``checkconflicts``
527 527 True is equivalent to ``check = conflicts``.
528 528 Default: False
529 529 ``fixeol``
530 530 Attempt to fix up EOL changes caused by the merge tool.
531 531 Default: False
532 532 ``gui``
533 533 This tool requires a graphical interface to run. Default: False
534 534 ``regkey``
535 535 Windows registry key which describes install location of this
536 536 tool. Mercurial will search for this key first under
537 537 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
538 538 Default: None
539 539 ``regname``
540 540 Name of value to read from specified registry key. Defaults to the
541 541 unnamed (default) value.
542 542 ``regappend``
543 543 String to append to the value read from the registry, typically
544 544 the executable name of the tool.
545 545 Default: None
546 546
547 547
548 548 ``hooks``
549 549 """""""""
550 550 Commands or Python functions that get automatically executed by
551 551 various actions such as starting or finishing a commit. Multiple
552 552 hooks can be run for the same action by appending a suffix to the
553 553 action. Overriding a site-wide hook can be done by changing its
554 554 value or setting it to an empty string.
555 555
556 556 Example ``.hg/hgrc``::
557 557
558 558 [hooks]
559 559 # update working directory after adding changesets
560 560 changegroup.update = hg update
561 561 # do not use the site-wide hook
562 562 incoming =
563 563 incoming.email = /my/email/hook
564 564 incoming.autobuild = /my/build/hook
565 565
566 566 Most hooks are run with environment variables set that give useful
567 567 additional information. For each hook below, the environment
568 568 variables it is passed are listed with names of the form ``$HG_foo``.
569 569
570 570 ``changegroup``
571 571 Run after a changegroup has been added via push, pull or unbundle.
572 572 ID of the first new changeset is in ``$HG_NODE``. URL from which
573 573 changes came is in ``$HG_URL``.
574 574 ``commit``
575 575 Run after a changeset has been created in the local repository. ID
576 576 of the newly created changeset is in ``$HG_NODE``. Parent changeset
577 577 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
578 578 ``incoming``
579 579 Run after a changeset has been pulled, pushed, or unbundled into
580 580 the local repository. The ID of the newly arrived changeset is in
581 581 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
582 582 ``outgoing``
583 583 Run after sending changes from local repository to another. ID of
584 584 first changeset sent is in ``$HG_NODE``. Source of operation is in
585 585 ``$HG_SOURCE``; see "preoutgoing" hook for description.
586 586 ``post-<command>``
587 587 Run after successful invocations of the associated command. The
588 588 contents of the command line are passed as ``$HG_ARGS`` and the result
589 589 code in ``$HG_RESULT``. Parsed command line arguments are passed as
590 590 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
591 591 the python data internally passed to <command>. ``$HG_OPTS`` is a
592 592 dictionary of options (with unspecified options set to their defaults).
593 593 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
594 594 ``pre-<command>``
595 595 Run before executing the associated command. The contents of the
596 596 command line are passed as ``$HG_ARGS``. Parsed command line arguments
597 597 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
598 598 representations of the data internally passed to <command>. ``$HG_OPTS``
599 599 is a dictionary of options (with unspecified options set to their
600 600 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
601 601 failure, the command doesn't execute and Mercurial returns the failure
602 602 code.
603 603 ``prechangegroup``
604 604 Run before a changegroup is added via push, pull or unbundle. Exit
605 605 status 0 allows the changegroup to proceed. Non-zero status will
606 606 cause the push, pull or unbundle to fail. URL from which changes
607 607 will come is in ``$HG_URL``.
608 608 ``precommit``
609 609 Run before starting a local commit. Exit status 0 allows the
610 610 commit to proceed. Non-zero status will cause the commit to fail.
611 611 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
612 612 ``preoutgoing``
613 613 Run before collecting changes to send from the local repository to
614 614 another. Non-zero status will cause failure. This lets you prevent
615 615 pull over HTTP or SSH. Also prevents against local pull, push
616 616 (outbound) or bundle commands, but not effective, since you can
617 617 just copy files instead then. Source of operation is in
618 618 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
619 619 SSH or HTTP repository. If "push", "pull" or "bundle", operation
620 620 is happening on behalf of repository on same system.
621 621 ``pretag``
622 622 Run before creating a tag. Exit status 0 allows the tag to be
623 623 created. Non-zero status will cause the tag to fail. ID of
624 624 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
625 625 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
626 626 ``pretxnchangegroup``
627 627 Run after a changegroup has been added via push, pull or unbundle,
628 628 but before the transaction has been committed. Changegroup is
629 629 visible to hook program. This lets you validate incoming changes
630 630 before accepting them. Passed the ID of the first new changeset in
631 631 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
632 632 status will cause the transaction to be rolled back and the push,
633 633 pull or unbundle will fail. URL that was source of changes is in
634 634 ``$HG_URL``.
635 635 ``pretxncommit``
636 636 Run after a changeset has been created but the transaction not yet
637 637 committed. Changeset is visible to hook program. This lets you
638 638 validate commit message and changes. Exit status 0 allows the
639 639 commit to proceed. Non-zero status will cause the transaction to
640 640 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
641 641 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
642 642 ``preupdate``
643 643 Run before updating the working directory. Exit status 0 allows
644 644 the update to proceed. Non-zero status will prevent the update.
645 645 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
646 646 of second new parent is in ``$HG_PARENT2``.
647 647 ``tag``
648 648 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
649 649 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
650 650 repository if ``$HG_LOCAL=0``.
651 651 ``update``
652 652 Run after updating the working directory. Changeset ID of first
653 653 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
654 654 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
655 655 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
656 656
657 657 .. note:: It is generally better to use standard hooks rather than the
658 658 generic pre- and post- command hooks as they are guaranteed to be
659 659 called in the appropriate contexts for influencing transactions.
660 660 Also, hooks like "commit" will be called in all contexts that
661 661 generate a commit (e.g. tag) and not just the commit command.
662 662
663 663 .. note:: Environment variables with empty values may not be passed to
664 664 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
665 665 will have an empty value under Unix-like platforms for non-merge
666 666 changesets, while it will not be available at all under Windows.
667 667
668 668 The syntax for Python hooks is as follows::
669 669
670 670 hookname = python:modulename.submodule.callable
671 671 hookname = python:/path/to/python/module.py:callable
672 672
673 673 Python hooks are run within the Mercurial process. Each hook is
674 674 called with at least three keyword arguments: a ui object (keyword
675 675 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
676 676 keyword that tells what kind of hook is used. Arguments listed as
677 677 environment variables above are passed as keyword arguments, with no
678 678 ``HG_`` prefix, and names in lower case.
679 679
680 680 If a Python hook returns a "true" value or raises an exception, this
681 681 is treated as a failure.
682 682
683 683
684 684 ``http_proxy``
685 685 """"""""""""""
686 686 Used to access web-based Mercurial repositories through a HTTP
687 687 proxy.
688 688
689 689 ``host``
690 690 Host name and (optional) port of the proxy server, for example
691 691 "myproxy:8000".
692 692 ``no``
693 693 Optional. Comma-separated list of host names that should bypass
694 694 the proxy.
695 695 ``passwd``
696 696 Optional. Password to authenticate with at the proxy server.
697 697 ``user``
698 698 Optional. User name to authenticate with at the proxy server.
699 699 ``always``
700 700 Optional. Always use the proxy, even for localhost and any entries
701 701 in ``http_proxy.no``. True or False. Default: False.
702 702
703 703 ``smtp``
704 704 """"""""
705 705 Configuration for extensions that need to send email messages.
706 706
707 707 ``host``
708 708 Host name of mail server, e.g. "mail.example.com".
709 709 ``port``
710 710 Optional. Port to connect to on mail server. Default: 25.
711 711 ``tls``
712 712 Optional. Method to enable TLS when connecting to mail server: starttls,
713 713 smtps or none. Default: none.
714 714 ``username``
715 715 Optional. User name for authenticating with the SMTP server.
716 716 Default: none.
717 717 ``password``
718 718 Optional. Password for authenticating with the SMTP server. If not
719 719 specified, interactive sessions will prompt the user for a
720 720 password; non-interactive sessions will fail. Default: none.
721 721 ``local_hostname``
722 722 Optional. It's the hostname that the sender can use to identify
723 723 itself to the MTA.
724 724
725 725
726 726 ``patch``
727 727 """""""""
728 728 Settings used when applying patches, for instance through the 'import'
729 729 command or with Mercurial Queues extension.
730 730
731 731 ``eol``
732 732 When set to 'strict' patch content and patched files end of lines
733 733 are preserved. When set to ``lf`` or ``crlf``, both files end of
734 734 lines are ignored when patching and the result line endings are
735 735 normalized to either LF (Unix) or CRLF (Windows). When set to
736 736 ``auto``, end of lines are again ignored while patching but line
737 737 endings in patched files are normalized to their original setting
738 738 on a per-file basis. If target file does not exist or has no end
739 739 of line, patch line endings are preserved.
740 740 Default: strict.
741 741
742 742
743 743 ``paths``
744 744 """""""""
745 745 Assigns symbolic names to repositories. The left side is the
746 746 symbolic name, and the right gives the directory or URL that is the
747 747 location of the repository. Default paths can be declared by setting
748 748 the following entries.
749 749
750 750 ``default``
751 751 Directory or URL to use when pulling if no source is specified.
752 752 Default is set to repository from which the current repository was
753 753 cloned.
754 754 ``default-push``
755 755 Optional. Directory or URL to use when pushing if no destination
756 756 is specified.
757 757
758 758
759 759 ``profiling``
760 760 """""""""""""
761 761 Specifies profiling format and file output. In this section
762 762 description, 'profiling data' stands for the raw data collected
763 763 during profiling, while 'profiling report' stands for a statistical
764 764 text report generated from the profiling data. The profiling is done
765 765 using lsprof.
766 766
767 767 ``format``
768 768 Profiling format.
769 769 Default: text.
770 770
771 771 ``text``
772 772 Generate a profiling report. When saving to a file, it should be
773 773 noted that only the report is saved, and the profiling data is
774 774 not kept.
775 775 ``kcachegrind``
776 776 Format profiling data for kcachegrind use: when saving to a
777 777 file, the generated file can directly be loaded into
778 778 kcachegrind.
779 779 ``output``
780 780 File path where profiling data or report should be saved. If the
781 781 file exists, it is replaced. Default: None, data is printed on
782 782 stderr
783 783
784 784 ``server``
785 785 """"""""""
786 786 Controls generic server settings.
787 787
788 788 ``uncompressed``
789 789 Whether to allow clients to clone a repository using the
790 790 uncompressed streaming protocol. This transfers about 40% more
791 791 data than a regular clone, but uses less memory and CPU on both
792 792 server and client. Over a LAN (100 Mbps or better) or a very fast
793 793 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
794 794 regular clone. Over most WAN connections (anything slower than
795 795 about 6 Mbps), uncompressed streaming is slower, because of the
796 796 extra data transfer overhead. This mode will also temporarily hold
797 797 the write lock while determining what data to transfer.
798 798 Default is True.
799 799
800 800 ``validate``
801 801 Whether to validate the completeness of pushed changesets by
802 802 checking that all new file revisions specified in manifests are
803 803 present. Default is False.
804 804
805 805 ``subpaths``
806 806 """"""""""""
807 807 Defines subrepositories source locations rewriting rules of the form::
808 808
809 809 <pattern> = <replacement>
810 810
811 811 Where ``pattern`` is a regular expression matching the source and
812 812 ``replacement`` is the replacement string used to rewrite it. Groups
813 813 can be matched in ``pattern`` and referenced in ``replacements``. For
814 814 instance::
815 815
816 816 http://server/(.*)-hg/ = http://hg.server/\1/
817 817
818 818 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
819 819
820 820 All patterns are applied in definition order.
821 821
822 822 ``trusted``
823 823 """""""""""
824 824
825 825 Mercurial will not use the settings in the
826 826 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
827 827 user or to a trusted group, as various hgrc features allow arbitrary
828 828 commands to be run. This issue is often encountered when configuring
829 829 hooks or extensions for shared repositories or servers. However,
830 830 the web interface will use some safe settings from the ``[web]``
831 831 section.
832 832
833 833 This section specifies what users and groups are trusted. The
834 834 current user is always trusted. To trust everybody, list a user or a
835 835 group with name ``*``. These settings must be placed in an
836 836 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
837 837 user or service running Mercurial.
838 838
839 839 ``users``
840 840 Comma-separated list of trusted users.
841 841 ``groups``
842 842 Comma-separated list of trusted groups.
843 843
844 844
845 845 ``ui``
846 846 """"""
847 847
848 848 User interface controls.
849 849
850 850 ``archivemeta``
851 851 Whether to include the .hg_archival.txt file containing meta data
852 852 (hashes for the repository base and for tip) in archives created
853 853 by the :hg:`archive` command or downloaded via hgweb.
854 854 Default is True.
855 855 ``askusername``
856 856 Whether to prompt for a username when committing. If True, and
857 857 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
858 858 be prompted to enter a username. If no username is entered, the
859 859 default ``USER@HOST`` is used instead.
860 860 Default is False.
861 861 ``debug``
862 862 Print debugging information. True or False. Default is False.
863 863 ``editor``
864 864 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
865 865 ``fallbackencoding``
866 866 Encoding to try if it's not possible to decode the changelog using
867 867 UTF-8. Default is ISO-8859-1.
868 868 ``ignore``
869 869 A file to read per-user ignore patterns from. This file should be
870 870 in the same format as a repository-wide .hgignore file. This
871 871 option supports hook syntax, so if you want to specify multiple
872 872 ignore files, you can do so by setting something like
873 873 ``ignore.other = ~/.hgignore2``. For details of the ignore file
874 874 format, see the |hgignore(5)|_ man page.
875 875 ``interactive``
876 876 Allow to prompt the user. True or False. Default is True.
877 877 ``logtemplate``
878 878 Template string for commands that print changesets.
879 879 ``merge``
880 880 The conflict resolution program to use during a manual merge.
881 881 For more information on merge tools see :hg:`help merge-tools`.
882 882 For configuring merge tools see the merge-tools_ section.
883 883 ``patch``
884 884 command to use to apply patches. Look for ``gpatch`` or ``patch`` in
885 885 PATH if unset.
886 886 ``quiet``
887 887 Reduce the amount of output printed. True or False. Default is False.
888 888 ``remotecmd``
889 889 remote command to use for clone/push/pull operations. Default is ``hg``.
890 890 ``report_untrusted``
891 891 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
892 892 trusted user or group. True or False. Default is True.
893 893 ``slash``
894 894 Display paths using a slash (``/``) as the path separator. This
895 895 only makes a difference on systems where the default path
896 896 separator is not the slash character (e.g. Windows uses the
897 897 backslash character (``\``)).
898 898 Default is False.
899 899 ``ssh``
900 900 command to use for SSH connections. Default is ``ssh``.
901 901 ``strict``
902 902 Require exact command names, instead of allowing unambiguous
903 903 abbreviations. True or False. Default is False.
904 904 ``style``
905 905 Name of style to use for command output.
906 906 ``timeout``
907 907 The timeout used when a lock is held (in seconds), a negative value
908 908 means no timeout. Default is 600.
909 909 ``traceback``
910 910 Mercurial always prints a traceback when an unknown exception
911 911 occurs. Setting this to True will make Mercurial print a traceback
912 912 on all exceptions, even those recognized by Mercurial (such as
913 913 IOError or MemoryError). Default is False.
914 914 ``username``
915 915 The committer of a changeset created when running "commit".
916 916 Typically a person's name and email address, e.g. ``Fred Widget
917 917 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
918 918 the username in hgrc is empty, it has to be specified manually or
919 919 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
920 920 ``username =`` in the system hgrc). Environment variables in the
921 921 username are expanded.
922 922 ``verbose``
923 923 Increase the amount of output printed. True or False. Default is False.
924 924
925 925
926 926 ``web``
927 927 """""""
928 928
929 929 Web interface configuration. The settings in this section apply to
930 930 both the builtin webserver (started by :hg:`serve`) and the script you
931 931 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
932 932 and WSGI).
933 933
934 934 The Mercurial webserver does no authentication (it does not prompt for
935 935 usernames and passwords to validate *who* users are), but it does do
936 936 authorization (it grants or denies access for *authenticated users*
937 937 based on settings in this section). You must either configure your
938 938 webserver to do authentication for you, or disable the authorization
939 939 checks.
940 940
941 941 For a quick setup in a trusted environment, e.g., a private LAN, where
942 942 you want it to accept pushes from anybody, you can use the following
943 943 command line::
944 944
945 945 $ hg --config web.allow_push=* --config web.push_ssl=False serve
946 946
947 947 Note that this will allow anybody to push anything to the server and
948 948 that this should not be used for public servers.
949 949
950 950 The full set of options is:
951 951
952 952 ``accesslog``
953 953 Where to output the access log. Default is stdout.
954 954 ``address``
955 955 Interface address to bind to. Default is all.
956 956 ``allow_archive``
957 957 List of archive format (bz2, gz, zip) allowed for downloading.
958 958 Default is empty.
959 959 ``allowbz2``
960 960 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
961 961 revisions.
962 962 Default is False.
963 963 ``allowgz``
964 964 (DEPRECATED) Whether to allow .tar.gz downloading of repository
965 965 revisions.
966 966 Default is False.
967 967 ``allowpull``
968 968 Whether to allow pulling from the repository. Default is True.
969 969 ``allow_push``
970 970 Whether to allow pushing to the repository. If empty or not set,
971 971 push is not allowed. If the special value ``*``, any remote user can
972 972 push, including unauthenticated users. Otherwise, the remote user
973 973 must have been authenticated, and the authenticated user name must
974 974 be present in this list. The contents of the allow_push list are
975 975 examined after the deny_push list.
976 976 ``allow_read``
977 977 If the user has not already been denied repository access due to
978 978 the contents of deny_read, this list determines whether to grant
979 979 repository access to the user. If this list is not empty, and the
980 980 user is unauthenticated or not present in the list, then access is
981 981 denied for the user. If the list is empty or not set, then access
982 982 is permitted to all users by default. Setting allow_read to the
983 983 special value ``*`` is equivalent to it not being set (i.e. access
984 984 is permitted to all users). The contents of the allow_read list are
985 985 examined after the deny_read list.
986 986 ``allowzip``
987 987 (DEPRECATED) Whether to allow .zip downloading of repository
988 988 revisions. Default is False. This feature creates temporary files.
989 989 ``baseurl``
990 990 Base URL to use when publishing URLs in other locations, so
991 991 third-party tools like email notification hooks can construct
992 992 URLs. Example: ``http://hgserver/repos/``.
993 993 ``cacerts``
994 Path to file containing a list of PEM encoded certificate authority
995 certificates. If specified on the client, then it will verify the identity
996 of remote HTTPS servers with these certificates. The form must be
997 as follows::
994 Path to file containing a list of PEM encoded certificate
995 authority certificates. Environment variables and ``~user``
996 constructs are expanded in the filename. If specified on the
997 client, then it will verify the identity of remote HTTPS servers
998 with these certificates. The form must be as follows::
998 999
999 1000 -----BEGIN CERTIFICATE-----
1000 1001 ... (certificate in base64 PEM encoding) ...
1001 1002 -----END CERTIFICATE-----
1002 1003 -----BEGIN CERTIFICATE-----
1003 1004 ... (certificate in base64 PEM encoding) ...
1004 1005 -----END CERTIFICATE-----
1005 1006
1006 1007 This feature is only supported when using Python 2.6 or later. If you wish
1007 1008 to use it with earlier versions of Python, install the backported
1008 1009 version of the ssl library that is available from
1009 1010 ``http://pypi.python.org``.
1010 1011
1011 1012 You can use OpenSSL's CA certificate file if your platform has one.
1012 1013 On most Linux systems this will be ``/etc/ssl/certs/ca-certificates.crt``.
1013 1014 Otherwise you will have to generate this file manually.
1014 1015 ``contact``
1015 1016 Name or email address of the person in charge of the repository.
1016 1017 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1017 1018 ``deny_push``
1018 1019 Whether to deny pushing to the repository. If empty or not set,
1019 1020 push is not denied. If the special value ``*``, all remote users are
1020 1021 denied push. Otherwise, unauthenticated users are all denied, and
1021 1022 any authenticated user name present in this list is also denied. The
1022 1023 contents of the deny_push list are examined before the allow_push list.
1023 1024 ``deny_read``
1024 1025 Whether to deny reading/viewing of the repository. If this list is
1025 1026 not empty, unauthenticated users are all denied, and any
1026 1027 authenticated user name present in this list is also denied access to
1027 1028 the repository. If set to the special value ``*``, all remote users
1028 1029 are denied access (rarely needed ;). If deny_read is empty or not set,
1029 1030 the determination of repository access depends on the presence and
1030 1031 content of the allow_read list (see description). If both
1031 1032 deny_read and allow_read are empty or not set, then access is
1032 1033 permitted to all users by default. If the repository is being
1033 1034 served via hgwebdir, denied users will not be able to see it in
1034 1035 the list of repositories. The contents of the deny_read list have
1035 1036 priority over (are examined before) the contents of the allow_read
1036 1037 list.
1037 1038 ``descend``
1038 1039 hgwebdir indexes will not descend into subdirectories. Only repositories
1039 1040 directly in the current path will be shown (other repositories are still
1040 1041 available from the index corresponding to their containing path).
1041 1042 ``description``
1042 1043 Textual description of the repository's purpose or contents.
1043 1044 Default is "unknown".
1044 1045 ``encoding``
1045 1046 Character encoding name. Default is the current locale charset.
1046 1047 Example: "UTF-8"
1047 1048 ``errorlog``
1048 1049 Where to output the error log. Default is stderr.
1049 1050 ``hidden``
1050 1051 Whether to hide the repository in the hgwebdir index.
1051 1052 Default is False.
1052 1053 ``ipv6``
1053 1054 Whether to use IPv6. Default is False.
1054 1055 ``name``
1055 1056 Repository name to use in the web interface. Default is current
1056 1057 working directory.
1057 1058 ``maxchanges``
1058 1059 Maximum number of changes to list on the changelog. Default is 10.
1059 1060 ``maxfiles``
1060 1061 Maximum number of files to list per changeset. Default is 10.
1061 1062 ``port``
1062 1063 Port to listen on. Default is 8000.
1063 1064 ``prefix``
1064 1065 Prefix path to serve from. Default is '' (server root).
1065 1066 ``push_ssl``
1066 1067 Whether to require that inbound pushes be transported over SSL to
1067 1068 prevent password sniffing. Default is True.
1068 1069 ``staticurl``
1069 1070 Base URL to use for static files. If unset, static files (e.g. the
1070 1071 hgicon.png favicon) will be served by the CGI script itself. Use
1071 1072 this setting to serve them directly with the HTTP server.
1072 1073 Example: ``http://hgserver/static/``.
1073 1074 ``stripes``
1074 1075 How many lines a "zebra stripe" should span in multiline output.
1075 1076 Default is 1; set to 0 to disable.
1076 1077 ``style``
1077 1078 Which template map style to use.
1078 1079 ``templates``
1079 1080 Where to find the HTML templates. Default is install path.
1080 1081
1081 1082
1082 1083 Author
1083 1084 ------
1084 1085 Bryan O'Sullivan <bos@serpentine.com>.
1085 1086
1086 1087 Mercurial was written by Matt Mackall <mpm@selenic.com>.
1087 1088
1088 1089 See Also
1089 1090 --------
1090 1091 |hg(1)|_, |hgignore(5)|_
1091 1092
1092 1093 Copying
1093 1094 -------
1094 1095 This manual page is copyright 2005 Bryan O'Sullivan.
1095 1096 Mercurial is copyright 2005-2010 Matt Mackall.
1096 1097 Free use of this software is granted under the terms of the GNU General
1097 1098 Public License version 2 or any later version.
1098 1099
1099 1100 .. include:: common.txt
@@ -1,4535 +1,4535 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, nullid, nullrev, short
9 9 from lock import release
10 10 from i18n import _, gettext
11 11 import os, re, sys, difflib, time, tempfile
12 12 import hg, util, revlog, extensions, copies, error
13 13 import patch, help, mdiff, url, encoding, templatekw, discovery
14 14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 15 import merge as mergemod
16 16 import minirst, revset
17 17 import dagparser
18 18
19 19 # Commands start here, listed alphabetically
20 20
21 21 def add(ui, repo, *pats, **opts):
22 22 """add the specified files on the next commit
23 23
24 24 Schedule files to be version controlled and added to the
25 25 repository.
26 26
27 27 The files will be added to the repository at the next commit. To
28 28 undo an add before that, see :hg:`forget`.
29 29
30 30 If no names are given, add all files to the repository.
31 31
32 32 .. container:: verbose
33 33
34 34 An example showing how new (unknown) files are added
35 35 automatically by :hg:`add`::
36 36
37 37 $ ls
38 38 foo.c
39 39 $ hg status
40 40 ? foo.c
41 41 $ hg add
42 42 adding foo.c
43 43 $ hg status
44 44 A foo.c
45 45
46 46 Returns 0 if all files are successfully added.
47 47 """
48 48
49 49 m = cmdutil.match(repo, pats, opts)
50 50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
51 51 opts.get('subrepos'), prefix="")
52 52 return rejected and 1 or 0
53 53
54 54 def addremove(ui, repo, *pats, **opts):
55 55 """add all new files, delete all missing files
56 56
57 57 Add all new files and remove all missing files from the
58 58 repository.
59 59
60 60 New files are ignored if they match any of the patterns in
61 61 .hgignore. As with add, these changes take effect at the next
62 62 commit.
63 63
64 64 Use the -s/--similarity option to detect renamed files. With a
65 65 parameter greater than 0, this compares every removed file with
66 66 every added file and records those similar enough as renames. This
67 67 option takes a percentage between 0 (disabled) and 100 (files must
68 68 be identical) as its parameter. Detecting renamed files this way
69 69 can be expensive. After using this option, :hg:`status -C` can be
70 70 used to check which files were identified as moved or renamed.
71 71
72 72 Returns 0 if all files are successfully added.
73 73 """
74 74 try:
75 75 sim = float(opts.get('similarity') or 100)
76 76 except ValueError:
77 77 raise util.Abort(_('similarity must be a number'))
78 78 if sim < 0 or sim > 100:
79 79 raise util.Abort(_('similarity must be between 0 and 100'))
80 80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
81 81
82 82 def annotate(ui, repo, *pats, **opts):
83 83 """show changeset information by line for each file
84 84
85 85 List changes in files, showing the revision id responsible for
86 86 each line
87 87
88 88 This command is useful for discovering when a change was made and
89 89 by whom.
90 90
91 91 Without the -a/--text option, annotate will avoid processing files
92 92 it detects as binary. With -a, annotate will annotate the file
93 93 anyway, although the results will probably be neither useful
94 94 nor desirable.
95 95
96 96 Returns 0 on success.
97 97 """
98 98 if opts.get('follow'):
99 99 # --follow is deprecated and now just an alias for -f/--file
100 100 # to mimic the behavior of Mercurial before version 1.5
101 101 opts['file'] = 1
102 102
103 103 datefunc = ui.quiet and util.shortdate or util.datestr
104 104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
105 105
106 106 if not pats:
107 107 raise util.Abort(_('at least one filename or pattern is required'))
108 108
109 109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
110 110 ('number', lambda x: str(x[0].rev())),
111 111 ('changeset', lambda x: short(x[0].node())),
112 112 ('date', getdate),
113 113 ('file', lambda x: x[0].path()),
114 114 ]
115 115
116 116 if (not opts.get('user') and not opts.get('changeset')
117 117 and not opts.get('date') and not opts.get('file')):
118 118 opts['number'] = 1
119 119
120 120 linenumber = opts.get('line_number') is not None
121 121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
122 122 raise util.Abort(_('at least one of -n/-c is required for -l'))
123 123
124 124 funcmap = [func for op, func in opmap if opts.get(op)]
125 125 if linenumber:
126 126 lastfunc = funcmap[-1]
127 127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
128 128
129 129 ctx = cmdutil.revsingle(repo, opts.get('rev'))
130 130 m = cmdutil.match(repo, pats, opts)
131 131 follow = not opts.get('no_follow')
132 132 for abs in ctx.walk(m):
133 133 fctx = ctx[abs]
134 134 if not opts.get('text') and util.binary(fctx.data()):
135 135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
136 136 continue
137 137
138 138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
139 139 pieces = []
140 140
141 141 for f in funcmap:
142 142 l = [f(n) for n, dummy in lines]
143 143 if l:
144 144 sized = [(x, encoding.colwidth(x)) for x in l]
145 145 ml = max([w for x, w in sized])
146 146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
147 147
148 148 if pieces:
149 149 for p, l in zip(zip(*pieces), lines):
150 150 ui.write("%s: %s" % (" ".join(p), l[1]))
151 151
152 152 def archive(ui, repo, dest, **opts):
153 153 '''create an unversioned archive of a repository revision
154 154
155 155 By default, the revision used is the parent of the working
156 156 directory; use -r/--rev to specify a different revision.
157 157
158 158 The archive type is automatically detected based on file
159 159 extension (or override using -t/--type).
160 160
161 161 Valid types are:
162 162
163 163 :``files``: a directory full of files (default)
164 164 :``tar``: tar archive, uncompressed
165 165 :``tbz2``: tar archive, compressed using bzip2
166 166 :``tgz``: tar archive, compressed using gzip
167 167 :``uzip``: zip archive, uncompressed
168 168 :``zip``: zip archive, compressed using deflate
169 169
170 170 The exact name of the destination archive or directory is given
171 171 using a format string; see :hg:`help export` for details.
172 172
173 173 Each member added to an archive file has a directory prefix
174 174 prepended. Use -p/--prefix to specify a format string for the
175 175 prefix. The default is the basename of the archive, with suffixes
176 176 removed.
177 177
178 178 Returns 0 on success.
179 179 '''
180 180
181 181 ctx = cmdutil.revsingle(repo, opts.get('rev'))
182 182 if not ctx:
183 183 raise util.Abort(_('no working directory: please specify a revision'))
184 184 node = ctx.node()
185 185 dest = cmdutil.make_filename(repo, dest, node)
186 186 if os.path.realpath(dest) == repo.root:
187 187 raise util.Abort(_('repository root cannot be destination'))
188 188
189 189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
190 190 prefix = opts.get('prefix')
191 191
192 192 if dest == '-':
193 193 if kind == 'files':
194 194 raise util.Abort(_('cannot archive plain files to stdout'))
195 195 dest = sys.stdout
196 196 if not prefix:
197 197 prefix = os.path.basename(repo.root) + '-%h'
198 198
199 199 prefix = cmdutil.make_filename(repo, prefix, node)
200 200 matchfn = cmdutil.match(repo, [], opts)
201 201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
202 202 matchfn, prefix, subrepos=opts.get('subrepos'))
203 203
204 204 def backout(ui, repo, node=None, rev=None, **opts):
205 205 '''reverse effect of earlier changeset
206 206
207 207 The backout command merges the reverse effect of the reverted
208 208 changeset into the working directory.
209 209
210 210 With the --merge option, it first commits the reverted changes
211 211 as a new changeset. This new changeset is a child of the reverted
212 212 changeset.
213 213 The --merge option remembers the parent of the working directory
214 214 before starting the backout, then merges the new head with that
215 215 changeset afterwards.
216 216 This will result in an explicit merge in the history.
217 217
218 218 If you backout a changeset other than the original parent of the
219 219 working directory, the result of this merge is not committed,
220 220 as with a normal merge. Otherwise, no merge is needed and the
221 221 commit is automatic.
222 222
223 223 Note that the default behavior (without --merge) has changed in
224 224 version 1.7. To restore the previous default behavior, use
225 225 :hg:`backout --merge` and then :hg:`update --clean .` to get rid of
226 226 the ongoing merge.
227 227
228 228 See :hg:`help dates` for a list of formats valid for -d/--date.
229 229
230 230 Returns 0 on success.
231 231 '''
232 232 if rev and node:
233 233 raise util.Abort(_("please specify just one revision"))
234 234
235 235 if not rev:
236 236 rev = node
237 237
238 238 if not rev:
239 239 raise util.Abort(_("please specify a revision to backout"))
240 240
241 241 date = opts.get('date')
242 242 if date:
243 243 opts['date'] = util.parsedate(date)
244 244
245 245 cmdutil.bail_if_changed(repo)
246 246 node = cmdutil.revsingle(repo, rev).node()
247 247
248 248 op1, op2 = repo.dirstate.parents()
249 249 a = repo.changelog.ancestor(op1, node)
250 250 if a != node:
251 251 raise util.Abort(_('cannot backout change on a different branch'))
252 252
253 253 p1, p2 = repo.changelog.parents(node)
254 254 if p1 == nullid:
255 255 raise util.Abort(_('cannot backout a change with no parents'))
256 256 if p2 != nullid:
257 257 if not opts.get('parent'):
258 258 raise util.Abort(_('cannot backout a merge changeset without '
259 259 '--parent'))
260 260 p = repo.lookup(opts['parent'])
261 261 if p not in (p1, p2):
262 262 raise util.Abort(_('%s is not a parent of %s') %
263 263 (short(p), short(node)))
264 264 parent = p
265 265 else:
266 266 if opts.get('parent'):
267 267 raise util.Abort(_('cannot use --parent on non-merge changeset'))
268 268 parent = p1
269 269
270 270 # the backout should appear on the same branch
271 271 branch = repo.dirstate.branch()
272 272 hg.clean(repo, node, show_stats=False)
273 273 repo.dirstate.setbranch(branch)
274 274 revert_opts = opts.copy()
275 275 revert_opts['date'] = None
276 276 revert_opts['all'] = True
277 277 revert_opts['rev'] = hex(parent)
278 278 revert_opts['no_backup'] = None
279 279 revert(ui, repo, **revert_opts)
280 280 if not opts.get('merge') and op1 != node:
281 281 try:
282 282 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
283 283 return hg.update(repo, op1)
284 284 finally:
285 285 ui.setconfig('ui', 'forcemerge', '')
286 286
287 287 commit_opts = opts.copy()
288 288 commit_opts['addremove'] = False
289 289 if not commit_opts['message'] and not commit_opts['logfile']:
290 290 # we don't translate commit messages
291 291 commit_opts['message'] = "Backed out changeset %s" % short(node)
292 292 commit_opts['force_editor'] = True
293 293 commit(ui, repo, **commit_opts)
294 294 def nice(node):
295 295 return '%d:%s' % (repo.changelog.rev(node), short(node))
296 296 ui.status(_('changeset %s backs out changeset %s\n') %
297 297 (nice(repo.changelog.tip()), nice(node)))
298 298 if opts.get('merge') and op1 != node:
299 299 hg.clean(repo, op1, show_stats=False)
300 300 ui.status(_('merging with changeset %s\n')
301 301 % nice(repo.changelog.tip()))
302 302 try:
303 303 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
304 304 return hg.merge(repo, hex(repo.changelog.tip()))
305 305 finally:
306 306 ui.setconfig('ui', 'forcemerge', '')
307 307 return 0
308 308
309 309 def bisect(ui, repo, rev=None, extra=None, command=None,
310 310 reset=None, good=None, bad=None, skip=None, noupdate=None):
311 311 """subdivision search of changesets
312 312
313 313 This command helps to find changesets which introduce problems. To
314 314 use, mark the earliest changeset you know exhibits the problem as
315 315 bad, then mark the latest changeset which is free from the problem
316 316 as good. Bisect will update your working directory to a revision
317 317 for testing (unless the -U/--noupdate option is specified). Once
318 318 you have performed tests, mark the working directory as good or
319 319 bad, and bisect will either update to another candidate changeset
320 320 or announce that it has found the bad revision.
321 321
322 322 As a shortcut, you can also use the revision argument to mark a
323 323 revision as good or bad without checking it out first.
324 324
325 325 If you supply a command, it will be used for automatic bisection.
326 326 Its exit status will be used to mark revisions as good or bad:
327 327 status 0 means good, 125 means to skip the revision, 127
328 328 (command not found) will abort the bisection, and any other
329 329 non-zero exit status means the revision is bad.
330 330
331 331 Returns 0 on success.
332 332 """
333 333 def print_result(nodes, good):
334 334 displayer = cmdutil.show_changeset(ui, repo, {})
335 335 if len(nodes) == 1:
336 336 # narrowed it down to a single revision
337 337 if good:
338 338 ui.write(_("The first good revision is:\n"))
339 339 else:
340 340 ui.write(_("The first bad revision is:\n"))
341 341 displayer.show(repo[nodes[0]])
342 342 parents = repo[nodes[0]].parents()
343 343 if len(parents) > 1:
344 344 side = good and state['bad'] or state['good']
345 345 num = len(set(i.node() for i in parents) & set(side))
346 346 if num == 1:
347 347 common = parents[0].ancestor(parents[1])
348 348 ui.write(_('Not all ancestors of this changeset have been'
349 349 ' checked.\nTo check the other ancestors, start'
350 350 ' from the common ancestor, %s.\n' % common))
351 351 else:
352 352 # multiple possible revisions
353 353 if good:
354 354 ui.write(_("Due to skipped revisions, the first "
355 355 "good revision could be any of:\n"))
356 356 else:
357 357 ui.write(_("Due to skipped revisions, the first "
358 358 "bad revision could be any of:\n"))
359 359 for n in nodes:
360 360 displayer.show(repo[n])
361 361 displayer.close()
362 362
363 363 def check_state(state, interactive=True):
364 364 if not state['good'] or not state['bad']:
365 365 if (good or bad or skip or reset) and interactive:
366 366 return
367 367 if not state['good']:
368 368 raise util.Abort(_('cannot bisect (no known good revisions)'))
369 369 else:
370 370 raise util.Abort(_('cannot bisect (no known bad revisions)'))
371 371 return True
372 372
373 373 # backward compatibility
374 374 if rev in "good bad reset init".split():
375 375 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
376 376 cmd, rev, extra = rev, extra, None
377 377 if cmd == "good":
378 378 good = True
379 379 elif cmd == "bad":
380 380 bad = True
381 381 else:
382 382 reset = True
383 383 elif extra or good + bad + skip + reset + bool(command) > 1:
384 384 raise util.Abort(_('incompatible arguments'))
385 385
386 386 if reset:
387 387 p = repo.join("bisect.state")
388 388 if os.path.exists(p):
389 389 os.unlink(p)
390 390 return
391 391
392 392 state = hbisect.load_state(repo)
393 393
394 394 if command:
395 395 changesets = 1
396 396 try:
397 397 while changesets:
398 398 # update state
399 399 status = util.system(command)
400 400 if status == 125:
401 401 transition = "skip"
402 402 elif status == 0:
403 403 transition = "good"
404 404 # status < 0 means process was killed
405 405 elif status == 127:
406 406 raise util.Abort(_("failed to execute %s") % command)
407 407 elif status < 0:
408 408 raise util.Abort(_("%s killed") % command)
409 409 else:
410 410 transition = "bad"
411 411 ctx = cmdutil.revsingle(repo, rev)
412 412 rev = None # clear for future iterations
413 413 state[transition].append(ctx.node())
414 414 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
415 415 check_state(state, interactive=False)
416 416 # bisect
417 417 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
418 418 # update to next check
419 419 cmdutil.bail_if_changed(repo)
420 420 hg.clean(repo, nodes[0], show_stats=False)
421 421 finally:
422 422 hbisect.save_state(repo, state)
423 423 print_result(nodes, good)
424 424 return
425 425
426 426 # update state
427 427
428 428 if rev:
429 429 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
430 430 else:
431 431 nodes = [repo.lookup('.')]
432 432
433 433 if good or bad or skip:
434 434 if good:
435 435 state['good'] += nodes
436 436 elif bad:
437 437 state['bad'] += nodes
438 438 elif skip:
439 439 state['skip'] += nodes
440 440 hbisect.save_state(repo, state)
441 441
442 442 if not check_state(state):
443 443 return
444 444
445 445 # actually bisect
446 446 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
447 447 if changesets == 0:
448 448 print_result(nodes, good)
449 449 else:
450 450 assert len(nodes) == 1 # only a single node can be tested next
451 451 node = nodes[0]
452 452 # compute the approximate number of remaining tests
453 453 tests, size = 0, 2
454 454 while size <= changesets:
455 455 tests, size = tests + 1, size * 2
456 456 rev = repo.changelog.rev(node)
457 457 ui.write(_("Testing changeset %d:%s "
458 458 "(%d changesets remaining, ~%d tests)\n")
459 459 % (rev, short(node), changesets, tests))
460 460 if not noupdate:
461 461 cmdutil.bail_if_changed(repo)
462 462 return hg.clean(repo, node)
463 463
464 464 def branch(ui, repo, label=None, **opts):
465 465 """set or show the current branch name
466 466
467 467 With no argument, show the current branch name. With one argument,
468 468 set the working directory branch name (the branch will not exist
469 469 in the repository until the next commit). Standard practice
470 470 recommends that primary development take place on the 'default'
471 471 branch.
472 472
473 473 Unless -f/--force is specified, branch will not let you set a
474 474 branch name that already exists, even if it's inactive.
475 475
476 476 Use -C/--clean to reset the working directory branch to that of
477 477 the parent of the working directory, negating a previous branch
478 478 change.
479 479
480 480 Use the command :hg:`update` to switch to an existing branch. Use
481 481 :hg:`commit --close-branch` to mark this branch as closed.
482 482
483 483 Returns 0 on success.
484 484 """
485 485
486 486 if opts.get('clean'):
487 487 label = repo[None].parents()[0].branch()
488 488 repo.dirstate.setbranch(label)
489 489 ui.status(_('reset working directory to branch %s\n') % label)
490 490 elif label:
491 491 if not opts.get('force') and label in repo.branchtags():
492 492 if label not in [p.branch() for p in repo.parents()]:
493 493 raise util.Abort(_('a branch of the same name already exists'
494 494 " (use 'hg update' to switch to it)"))
495 495 repo.dirstate.setbranch(label)
496 496 ui.status(_('marked working directory as branch %s\n') % label)
497 497 else:
498 498 ui.write("%s\n" % repo.dirstate.branch())
499 499
500 500 def branches(ui, repo, active=False, closed=False):
501 501 """list repository named branches
502 502
503 503 List the repository's named branches, indicating which ones are
504 504 inactive. If -c/--closed is specified, also list branches which have
505 505 been marked closed (see :hg:`commit --close-branch`).
506 506
507 507 If -a/--active is specified, only show active branches. A branch
508 508 is considered active if it contains repository heads.
509 509
510 510 Use the command :hg:`update` to switch to an existing branch.
511 511
512 512 Returns 0.
513 513 """
514 514
515 515 hexfunc = ui.debugflag and hex or short
516 516 activebranches = [repo[n].branch() for n in repo.heads()]
517 517 def testactive(tag, node):
518 518 realhead = tag in activebranches
519 519 open = node in repo.branchheads(tag, closed=False)
520 520 return realhead and open
521 521 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
522 522 for tag, node in repo.branchtags().items()],
523 523 reverse=True)
524 524
525 525 for isactive, node, tag in branches:
526 526 if (not active) or isactive:
527 527 if ui.quiet:
528 528 ui.write("%s\n" % tag)
529 529 else:
530 530 hn = repo.lookup(node)
531 531 if isactive:
532 532 label = 'branches.active'
533 533 notice = ''
534 534 elif hn not in repo.branchheads(tag, closed=False):
535 535 if not closed:
536 536 continue
537 537 label = 'branches.closed'
538 538 notice = _(' (closed)')
539 539 else:
540 540 label = 'branches.inactive'
541 541 notice = _(' (inactive)')
542 542 if tag == repo.dirstate.branch():
543 543 label = 'branches.current'
544 544 rev = str(node).rjust(31 - encoding.colwidth(tag))
545 545 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
546 546 tag = ui.label(tag, label)
547 547 ui.write("%s %s%s\n" % (tag, rev, notice))
548 548
549 549 def bundle(ui, repo, fname, dest=None, **opts):
550 550 """create a changegroup file
551 551
552 552 Generate a compressed changegroup file collecting changesets not
553 553 known to be in another repository.
554 554
555 555 If you omit the destination repository, then hg assumes the
556 556 destination will have all the nodes you specify with --base
557 557 parameters. To create a bundle containing all changesets, use
558 558 -a/--all (or --base null).
559 559
560 560 You can change compression method with the -t/--type option.
561 561 The available compression methods are: none, bzip2, and
562 562 gzip (by default, bundles are compressed using bzip2).
563 563
564 564 The bundle file can then be transferred using conventional means
565 565 and applied to another repository with the unbundle or pull
566 566 command. This is useful when direct push and pull are not
567 567 available or when exporting an entire repository is undesirable.
568 568
569 569 Applying bundles preserves all changeset contents including
570 570 permissions, copy/rename information, and revision history.
571 571
572 572 Returns 0 on success, 1 if no changes found.
573 573 """
574 574 revs = None
575 575 if 'rev' in opts:
576 576 revs = cmdutil.revrange(repo, opts['rev'])
577 577
578 578 if opts.get('all'):
579 579 base = ['null']
580 580 else:
581 581 base = cmdutil.revrange(repo, opts.get('base'))
582 582 if base:
583 583 if dest:
584 584 raise util.Abort(_("--base is incompatible with specifying "
585 585 "a destination"))
586 586 base = [repo.lookup(rev) for rev in base]
587 587 # create the right base
588 588 # XXX: nodesbetween / changegroup* should be "fixed" instead
589 589 o = []
590 590 has = set((nullid,))
591 591 for n in base:
592 592 has.update(repo.changelog.reachable(n))
593 593 if revs:
594 594 revs = [repo.lookup(rev) for rev in revs]
595 595 visit = revs[:]
596 596 has.difference_update(visit)
597 597 else:
598 598 visit = repo.changelog.heads()
599 599 seen = {}
600 600 while visit:
601 601 n = visit.pop(0)
602 602 parents = [p for p in repo.changelog.parents(n) if p not in has]
603 603 if len(parents) == 0:
604 604 if n not in has:
605 605 o.append(n)
606 606 else:
607 607 for p in parents:
608 608 if p not in seen:
609 609 seen[p] = 1
610 610 visit.append(p)
611 611 else:
612 612 dest = ui.expandpath(dest or 'default-push', dest or 'default')
613 613 dest, branches = hg.parseurl(dest, opts.get('branch'))
614 614 other = hg.repository(hg.remoteui(repo, opts), dest)
615 615 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
616 616 if revs:
617 617 revs = [repo.lookup(rev) for rev in revs]
618 618 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
619 619
620 620 if not o:
621 621 ui.status(_("no changes found\n"))
622 622 return 1
623 623
624 624 if revs:
625 625 cg = repo.changegroupsubset(o, revs, 'bundle')
626 626 else:
627 627 cg = repo.changegroup(o, 'bundle')
628 628
629 629 bundletype = opts.get('type', 'bzip2').lower()
630 630 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
631 631 bundletype = btypes.get(bundletype)
632 632 if bundletype not in changegroup.bundletypes:
633 633 raise util.Abort(_('unknown bundle type specified with --type'))
634 634
635 635 changegroup.writebundle(cg, fname, bundletype)
636 636
637 637 def cat(ui, repo, file1, *pats, **opts):
638 638 """output the current or given revision of files
639 639
640 640 Print the specified files as they were at the given revision. If
641 641 no revision is given, the parent of the working directory is used,
642 642 or tip if no revision is checked out.
643 643
644 644 Output may be to a file, in which case the name of the file is
645 645 given using a format string. The formatting rules are the same as
646 646 for the export command, with the following additions:
647 647
648 648 :``%s``: basename of file being printed
649 649 :``%d``: dirname of file being printed, or '.' if in repository root
650 650 :``%p``: root-relative path name of file being printed
651 651
652 652 Returns 0 on success.
653 653 """
654 654 ctx = cmdutil.revsingle(repo, opts.get('rev'))
655 655 err = 1
656 656 m = cmdutil.match(repo, (file1,) + pats, opts)
657 657 for abs in ctx.walk(m):
658 658 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
659 659 data = ctx[abs].data()
660 660 if opts.get('decode'):
661 661 data = repo.wwritedata(abs, data)
662 662 fp.write(data)
663 663 err = 0
664 664 return err
665 665
666 666 def clone(ui, source, dest=None, **opts):
667 667 """make a copy of an existing repository
668 668
669 669 Create a copy of an existing repository in a new directory.
670 670
671 671 If no destination directory name is specified, it defaults to the
672 672 basename of the source.
673 673
674 674 The location of the source is added to the new repository's
675 675 .hg/hgrc file, as the default to be used for future pulls.
676 676
677 677 See :hg:`help urls` for valid source format details.
678 678
679 679 It is possible to specify an ``ssh://`` URL as the destination, but no
680 680 .hg/hgrc and working directory will be created on the remote side.
681 681 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
682 682
683 683 A set of changesets (tags, or branch names) to pull may be specified
684 684 by listing each changeset (tag, or branch name) with -r/--rev.
685 685 If -r/--rev is used, the cloned repository will contain only a subset
686 686 of the changesets of the source repository. Only the set of changesets
687 687 defined by all -r/--rev options (including all their ancestors)
688 688 will be pulled into the destination repository.
689 689 No subsequent changesets (including subsequent tags) will be present
690 690 in the destination.
691 691
692 692 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
693 693 local source repositories.
694 694
695 695 For efficiency, hardlinks are used for cloning whenever the source
696 696 and destination are on the same filesystem (note this applies only
697 697 to the repository data, not to the working directory). Some
698 698 filesystems, such as AFS, implement hardlinking incorrectly, but
699 699 do not report errors. In these cases, use the --pull option to
700 700 avoid hardlinking.
701 701
702 702 In some cases, you can clone repositories and the working directory
703 703 using full hardlinks with ::
704 704
705 705 $ cp -al REPO REPOCLONE
706 706
707 707 This is the fastest way to clone, but it is not always safe. The
708 708 operation is not atomic (making sure REPO is not modified during
709 709 the operation is up to you) and you have to make sure your editor
710 710 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
711 711 this is not compatible with certain extensions that place their
712 712 metadata under the .hg directory, such as mq.
713 713
714 714 Mercurial will update the working directory to the first applicable
715 715 revision from this list:
716 716
717 717 a) null if -U or the source repository has no changesets
718 718 b) if -u . and the source repository is local, the first parent of
719 719 the source repository's working directory
720 720 c) the changeset specified with -u (if a branch name, this means the
721 721 latest head of that branch)
722 722 d) the changeset specified with -r
723 723 e) the tipmost head specified with -b
724 724 f) the tipmost head specified with the url#branch source syntax
725 725 g) the tipmost head of the default branch
726 726 h) tip
727 727
728 728 Returns 0 on success.
729 729 """
730 730 if opts.get('noupdate') and opts.get('updaterev'):
731 731 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
732 732
733 733 r = hg.clone(hg.remoteui(ui, opts), source, dest,
734 734 pull=opts.get('pull'),
735 735 stream=opts.get('uncompressed'),
736 736 rev=opts.get('rev'),
737 737 update=opts.get('updaterev') or not opts.get('noupdate'),
738 738 branch=opts.get('branch'))
739 739
740 740 return r is None
741 741
742 742 def commit(ui, repo, *pats, **opts):
743 743 """commit the specified files or all outstanding changes
744 744
745 745 Commit changes to the given files into the repository. Unlike a
746 746 centralized RCS, this operation is a local operation. See
747 747 :hg:`push` for a way to actively distribute your changes.
748 748
749 749 If a list of files is omitted, all changes reported by :hg:`status`
750 750 will be committed.
751 751
752 752 If you are committing the result of a merge, do not provide any
753 753 filenames or -I/-X filters.
754 754
755 755 If no commit message is specified, Mercurial starts your
756 756 configured editor where you can enter a message. In case your
757 757 commit fails, you will find a backup of your message in
758 758 ``.hg/last-message.txt``.
759 759
760 760 See :hg:`help dates` for a list of formats valid for -d/--date.
761 761
762 762 Returns 0 on success, 1 if nothing changed.
763 763 """
764 764 extra = {}
765 765 if opts.get('close_branch'):
766 766 if repo['.'].node() not in repo.branchheads():
767 767 # The topo heads set is included in the branch heads set of the
768 768 # current branch, so it's sufficient to test branchheads
769 769 raise util.Abort(_('can only close branch heads'))
770 770 extra['close'] = 1
771 771 e = cmdutil.commiteditor
772 772 if opts.get('force_editor'):
773 773 e = cmdutil.commitforceeditor
774 774
775 775 def commitfunc(ui, repo, message, match, opts):
776 776 return repo.commit(message, opts.get('user'), opts.get('date'), match,
777 777 editor=e, extra=extra)
778 778
779 779 branch = repo[None].branch()
780 780 bheads = repo.branchheads(branch)
781 781
782 782 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
783 783 if not node:
784 784 ui.status(_("nothing changed\n"))
785 785 return 1
786 786
787 787 ctx = repo[node]
788 788 parents = ctx.parents()
789 789
790 790 if bheads and not [x for x in parents
791 791 if x.node() in bheads and x.branch() == branch]:
792 792 ui.status(_('created new head\n'))
793 793 # The message is not printed for initial roots. For the other
794 794 # changesets, it is printed in the following situations:
795 795 #
796 796 # Par column: for the 2 parents with ...
797 797 # N: null or no parent
798 798 # B: parent is on another named branch
799 799 # C: parent is a regular non head changeset
800 800 # H: parent was a branch head of the current branch
801 801 # Msg column: whether we print "created new head" message
802 802 # In the following, it is assumed that there already exists some
803 803 # initial branch heads of the current branch, otherwise nothing is
804 804 # printed anyway.
805 805 #
806 806 # Par Msg Comment
807 807 # NN y additional topo root
808 808 #
809 809 # BN y additional branch root
810 810 # CN y additional topo head
811 811 # HN n usual case
812 812 #
813 813 # BB y weird additional branch root
814 814 # CB y branch merge
815 815 # HB n merge with named branch
816 816 #
817 817 # CC y additional head from merge
818 818 # CH n merge with a head
819 819 #
820 820 # HH n head merge: head count decreases
821 821
822 822 if not opts.get('close_branch'):
823 823 for r in parents:
824 824 if r.extra().get('close') and r.branch() == branch:
825 825 ui.status(_('reopening closed branch head %d\n') % r)
826 826
827 827 if ui.debugflag:
828 828 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
829 829 elif ui.verbose:
830 830 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
831 831
832 832 def copy(ui, repo, *pats, **opts):
833 833 """mark files as copied for the next commit
834 834
835 835 Mark dest as having copies of source files. If dest is a
836 836 directory, copies are put in that directory. If dest is a file,
837 837 the source must be a single file.
838 838
839 839 By default, this command copies the contents of files as they
840 840 exist in the working directory. If invoked with -A/--after, the
841 841 operation is recorded, but no copying is performed.
842 842
843 843 This command takes effect with the next commit. To undo a copy
844 844 before that, see :hg:`revert`.
845 845
846 846 Returns 0 on success, 1 if errors are encountered.
847 847 """
848 848 wlock = repo.wlock(False)
849 849 try:
850 850 return cmdutil.copy(ui, repo, pats, opts)
851 851 finally:
852 852 wlock.release()
853 853
854 854 def debugancestor(ui, repo, *args):
855 855 """find the ancestor revision of two revisions in a given index"""
856 856 if len(args) == 3:
857 857 index, rev1, rev2 = args
858 858 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
859 859 lookup = r.lookup
860 860 elif len(args) == 2:
861 861 if not repo:
862 862 raise util.Abort(_("there is no Mercurial repository here "
863 863 "(.hg not found)"))
864 864 rev1, rev2 = args
865 865 r = repo.changelog
866 866 lookup = repo.lookup
867 867 else:
868 868 raise util.Abort(_('either two or three arguments required'))
869 869 a = r.ancestor(lookup(rev1), lookup(rev2))
870 870 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
871 871
872 872 def debugbuilddag(ui, repo, text,
873 873 mergeable_file=False,
874 874 appended_file=False,
875 875 overwritten_file=False,
876 876 new_file=False):
877 877 """builds a repo with a given dag from scratch in the current empty repo
878 878
879 879 Elements:
880 880
881 881 - "+n" is a linear run of n nodes based on the current default parent
882 882 - "." is a single node based on the current default parent
883 883 - "$" resets the default parent to null (implied at the start);
884 884 otherwise the default parent is always the last node created
885 885 - "<p" sets the default parent to the backref p
886 886 - "*p" is a fork at parent p, which is a backref
887 887 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
888 888 - "/p2" is a merge of the preceding node and p2
889 889 - ":tag" defines a local tag for the preceding node
890 890 - "@branch" sets the named branch for subsequent nodes
891 891 - "!command" runs the command using your shell
892 892 - "!!my command\\n" is like "!", but to the end of the line
893 893 - "#...\\n" is a comment up to the end of the line
894 894
895 895 Whitespace between the above elements is ignored.
896 896
897 897 A backref is either
898 898
899 899 - a number n, which references the node curr-n, where curr is the current
900 900 node, or
901 901 - the name of a local tag you placed earlier using ":tag", or
902 902 - empty to denote the default parent.
903 903
904 904 All string valued-elements are either strictly alphanumeric, or must
905 905 be enclosed in double quotes ("..."), with "\\" as escape character.
906 906
907 907 Note that the --overwritten-file and --appended-file options imply the
908 908 use of "HGMERGE=internal:local" during DAG buildup.
909 909 """
910 910
911 911 if not (mergeable_file or appended_file or overwritten_file or new_file):
912 912 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
913 913
914 914 if len(repo.changelog) > 0:
915 915 raise util.Abort(_('repository is not empty'))
916 916
917 917 if overwritten_file or appended_file:
918 918 # we don't want to fail in merges during buildup
919 919 os.environ['HGMERGE'] = 'internal:local'
920 920
921 921 def writefile(fname, text, fmode="wb"):
922 922 f = open(fname, fmode)
923 923 try:
924 924 f.write(text)
925 925 finally:
926 926 f.close()
927 927
928 928 if mergeable_file:
929 929 linesperrev = 2
930 930 # determine number of revs in DAG
931 931 n = 0
932 932 for type, data in dagparser.parsedag(text):
933 933 if type == 'n':
934 934 n += 1
935 935 # make a file with k lines per rev
936 936 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
937 937 + "\n")
938 938
939 939 at = -1
940 940 atbranch = 'default'
941 941 for type, data in dagparser.parsedag(text):
942 942 if type == 'n':
943 943 ui.status('node %s\n' % str(data))
944 944 id, ps = data
945 945 p1 = ps[0]
946 946 if p1 != at:
947 947 update(ui, repo, node=str(p1), clean=True)
948 948 at = p1
949 949 if repo.dirstate.branch() != atbranch:
950 950 branch(ui, repo, atbranch, force=True)
951 951 if len(ps) > 1:
952 952 p2 = ps[1]
953 953 merge(ui, repo, node=p2)
954 954
955 955 if mergeable_file:
956 956 f = open("mf", "rb+")
957 957 try:
958 958 lines = f.read().split("\n")
959 959 lines[id * linesperrev] += " r%i" % id
960 960 f.seek(0)
961 961 f.write("\n".join(lines))
962 962 finally:
963 963 f.close()
964 964
965 965 if appended_file:
966 966 writefile("af", "r%i\n" % id, "ab")
967 967
968 968 if overwritten_file:
969 969 writefile("of", "r%i\n" % id)
970 970
971 971 if new_file:
972 972 writefile("nf%i" % id, "r%i\n" % id)
973 973
974 974 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
975 975 at = id
976 976 elif type == 'l':
977 977 id, name = data
978 978 ui.status('tag %s\n' % name)
979 979 tag(ui, repo, name, local=True)
980 980 elif type == 'a':
981 981 ui.status('branch %s\n' % data)
982 982 atbranch = data
983 983 elif type in 'cC':
984 984 r = util.system(data, cwd=repo.root)
985 985 if r:
986 986 desc, r = util.explain_exit(r)
987 987 raise util.Abort(_('%s command %s') % (data, desc))
988 988
989 989 def debugcommands(ui, cmd='', *args):
990 990 """list all available commands and options"""
991 991 for cmd, vals in sorted(table.iteritems()):
992 992 cmd = cmd.split('|')[0].strip('^')
993 993 opts = ', '.join([i[1] for i in vals[1]])
994 994 ui.write('%s: %s\n' % (cmd, opts))
995 995
996 996 def debugcomplete(ui, cmd='', **opts):
997 997 """returns the completion list associated with the given command"""
998 998
999 999 if opts.get('options'):
1000 1000 options = []
1001 1001 otables = [globalopts]
1002 1002 if cmd:
1003 1003 aliases, entry = cmdutil.findcmd(cmd, table, False)
1004 1004 otables.append(entry[1])
1005 1005 for t in otables:
1006 1006 for o in t:
1007 1007 if "(DEPRECATED)" in o[3]:
1008 1008 continue
1009 1009 if o[0]:
1010 1010 options.append('-%s' % o[0])
1011 1011 options.append('--%s' % o[1])
1012 1012 ui.write("%s\n" % "\n".join(options))
1013 1013 return
1014 1014
1015 1015 cmdlist = cmdutil.findpossible(cmd, table)
1016 1016 if ui.verbose:
1017 1017 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1018 1018 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1019 1019
1020 1020 def debugfsinfo(ui, path = "."):
1021 1021 """show information detected about current filesystem"""
1022 1022 open('.debugfsinfo', 'w').write('')
1023 1023 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1024 1024 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1025 1025 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1026 1026 and 'yes' or 'no'))
1027 1027 os.unlink('.debugfsinfo')
1028 1028
1029 1029 def debugrebuildstate(ui, repo, rev="tip"):
1030 1030 """rebuild the dirstate as it would look like for the given revision"""
1031 1031 ctx = cmdutil.revsingle(repo, rev)
1032 1032 wlock = repo.wlock()
1033 1033 try:
1034 1034 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1035 1035 finally:
1036 1036 wlock.release()
1037 1037
1038 1038 def debugcheckstate(ui, repo):
1039 1039 """validate the correctness of the current dirstate"""
1040 1040 parent1, parent2 = repo.dirstate.parents()
1041 1041 m1 = repo[parent1].manifest()
1042 1042 m2 = repo[parent2].manifest()
1043 1043 errors = 0
1044 1044 for f in repo.dirstate:
1045 1045 state = repo.dirstate[f]
1046 1046 if state in "nr" and f not in m1:
1047 1047 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1048 1048 errors += 1
1049 1049 if state in "a" and f in m1:
1050 1050 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1051 1051 errors += 1
1052 1052 if state in "m" and f not in m1 and f not in m2:
1053 1053 ui.warn(_("%s in state %s, but not in either manifest\n") %
1054 1054 (f, state))
1055 1055 errors += 1
1056 1056 for f in m1:
1057 1057 state = repo.dirstate[f]
1058 1058 if state not in "nrm":
1059 1059 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1060 1060 errors += 1
1061 1061 if errors:
1062 1062 error = _(".hg/dirstate inconsistent with current parent's manifest")
1063 1063 raise util.Abort(error)
1064 1064
1065 1065 def showconfig(ui, repo, *values, **opts):
1066 1066 """show combined config settings from all hgrc files
1067 1067
1068 1068 With no arguments, print names and values of all config items.
1069 1069
1070 1070 With one argument of the form section.name, print just the value
1071 1071 of that config item.
1072 1072
1073 1073 With multiple arguments, print names and values of all config
1074 1074 items with matching section names.
1075 1075
1076 1076 With --debug, the source (filename and line number) is printed
1077 1077 for each config item.
1078 1078
1079 1079 Returns 0 on success.
1080 1080 """
1081 1081
1082 1082 for f in util.rcpath():
1083 1083 ui.debug(_('read config from: %s\n') % f)
1084 1084 untrusted = bool(opts.get('untrusted'))
1085 1085 if values:
1086 1086 sections = [v for v in values if '.' not in v]
1087 1087 items = [v for v in values if '.' in v]
1088 1088 if len(items) > 1 or items and sections:
1089 1089 raise util.Abort(_('only one config item permitted'))
1090 1090 for section, name, value in ui.walkconfig(untrusted=untrusted):
1091 1091 sectname = section + '.' + name
1092 1092 if values:
1093 1093 for v in values:
1094 1094 if v == section:
1095 1095 ui.debug('%s: ' %
1096 1096 ui.configsource(section, name, untrusted))
1097 1097 ui.write('%s=%s\n' % (sectname, value))
1098 1098 elif v == sectname:
1099 1099 ui.debug('%s: ' %
1100 1100 ui.configsource(section, name, untrusted))
1101 1101 ui.write(value, '\n')
1102 1102 else:
1103 1103 ui.debug('%s: ' %
1104 1104 ui.configsource(section, name, untrusted))
1105 1105 ui.write('%s=%s\n' % (sectname, value))
1106 1106
1107 1107 def debugpushkey(ui, repopath, namespace, *keyinfo):
1108 1108 '''access the pushkey key/value protocol
1109 1109
1110 1110 With two args, list the keys in the given namespace.
1111 1111
1112 1112 With five args, set a key to new if it currently is set to old.
1113 1113 Reports success or failure.
1114 1114 '''
1115 1115
1116 1116 target = hg.repository(ui, repopath)
1117 1117 if keyinfo:
1118 1118 key, old, new = keyinfo
1119 1119 r = target.pushkey(namespace, key, old, new)
1120 1120 ui.status(str(r) + '\n')
1121 1121 return not r
1122 1122 else:
1123 1123 for k, v in target.listkeys(namespace).iteritems():
1124 1124 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1125 1125 v.encode('string-escape')))
1126 1126
1127 1127 def debugrevspec(ui, repo, expr):
1128 1128 '''parse and apply a revision specification'''
1129 1129 if ui.verbose:
1130 1130 tree = revset.parse(expr)
1131 1131 ui.note(tree, "\n")
1132 1132 func = revset.match(expr)
1133 1133 for c in func(repo, range(len(repo))):
1134 1134 ui.write("%s\n" % c)
1135 1135
1136 1136 def debugsetparents(ui, repo, rev1, rev2=None):
1137 1137 """manually set the parents of the current working directory
1138 1138
1139 1139 This is useful for writing repository conversion tools, but should
1140 1140 be used with care.
1141 1141
1142 1142 Returns 0 on success.
1143 1143 """
1144 1144
1145 1145 r1 = cmdutil.revsingle(repo, rev1).node()
1146 1146 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1147 1147
1148 1148 wlock = repo.wlock()
1149 1149 try:
1150 1150 repo.dirstate.setparents(r1, r2)
1151 1151 finally:
1152 1152 wlock.release()
1153 1153
1154 1154 def debugstate(ui, repo, nodates=None):
1155 1155 """show the contents of the current dirstate"""
1156 1156 timestr = ""
1157 1157 showdate = not nodates
1158 1158 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1159 1159 if showdate:
1160 1160 if ent[3] == -1:
1161 1161 # Pad or slice to locale representation
1162 1162 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1163 1163 time.localtime(0)))
1164 1164 timestr = 'unset'
1165 1165 timestr = (timestr[:locale_len] +
1166 1166 ' ' * (locale_len - len(timestr)))
1167 1167 else:
1168 1168 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1169 1169 time.localtime(ent[3]))
1170 1170 if ent[1] & 020000:
1171 1171 mode = 'lnk'
1172 1172 else:
1173 1173 mode = '%3o' % (ent[1] & 0777)
1174 1174 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1175 1175 for f in repo.dirstate.copies():
1176 1176 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1177 1177
1178 1178 def debugsub(ui, repo, rev=None):
1179 1179 ctx = cmdutil.revsingle(repo, rev, None)
1180 1180 for k, v in sorted(ctx.substate.items()):
1181 1181 ui.write('path %s\n' % k)
1182 1182 ui.write(' source %s\n' % v[0])
1183 1183 ui.write(' revision %s\n' % v[1])
1184 1184
1185 1185 def debugdag(ui, repo, file_=None, *revs, **opts):
1186 1186 """format the changelog or an index DAG as a concise textual description
1187 1187
1188 1188 If you pass a revlog index, the revlog's DAG is emitted. If you list
1189 1189 revision numbers, they get labelled in the output as rN.
1190 1190
1191 1191 Otherwise, the changelog DAG of the current repo is emitted.
1192 1192 """
1193 1193 spaces = opts.get('spaces')
1194 1194 dots = opts.get('dots')
1195 1195 if file_:
1196 1196 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1197 1197 revs = set((int(r) for r in revs))
1198 1198 def events():
1199 1199 for r in rlog:
1200 1200 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1201 1201 if r in revs:
1202 1202 yield 'l', (r, "r%i" % r)
1203 1203 elif repo:
1204 1204 cl = repo.changelog
1205 1205 tags = opts.get('tags')
1206 1206 branches = opts.get('branches')
1207 1207 if tags:
1208 1208 labels = {}
1209 1209 for l, n in repo.tags().items():
1210 1210 labels.setdefault(cl.rev(n), []).append(l)
1211 1211 def events():
1212 1212 b = "default"
1213 1213 for r in cl:
1214 1214 if branches:
1215 1215 newb = cl.read(cl.node(r))[5]['branch']
1216 1216 if newb != b:
1217 1217 yield 'a', newb
1218 1218 b = newb
1219 1219 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1220 1220 if tags:
1221 1221 ls = labels.get(r)
1222 1222 if ls:
1223 1223 for l in ls:
1224 1224 yield 'l', (r, l)
1225 1225 else:
1226 1226 raise util.Abort(_('need repo for changelog dag'))
1227 1227
1228 1228 for line in dagparser.dagtextlines(events(),
1229 1229 addspaces=spaces,
1230 1230 wraplabels=True,
1231 1231 wrapannotations=True,
1232 1232 wrapnonlinear=dots,
1233 1233 usedots=dots,
1234 1234 maxlinewidth=70):
1235 1235 ui.write(line)
1236 1236 ui.write("\n")
1237 1237
1238 1238 def debugdata(ui, repo, file_, rev):
1239 1239 """dump the contents of a data file revision"""
1240 1240 r = None
1241 1241 if repo:
1242 1242 filelog = repo.file(file_)
1243 1243 if len(filelog):
1244 1244 r = filelog
1245 1245 if not r:
1246 1246 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1247 1247 try:
1248 1248 ui.write(r.revision(r.lookup(rev)))
1249 1249 except KeyError:
1250 1250 raise util.Abort(_('invalid revision identifier %s') % rev)
1251 1251
1252 1252 def debugdate(ui, date, range=None, **opts):
1253 1253 """parse and display a date"""
1254 1254 if opts["extended"]:
1255 1255 d = util.parsedate(date, util.extendeddateformats)
1256 1256 else:
1257 1257 d = util.parsedate(date)
1258 1258 ui.write("internal: %s %s\n" % d)
1259 1259 ui.write("standard: %s\n" % util.datestr(d))
1260 1260 if range:
1261 1261 m = util.matchdate(range)
1262 1262 ui.write("match: %s\n" % m(d[0]))
1263 1263
1264 1264 def debugindex(ui, repo, file_, **opts):
1265 1265 """dump the contents of an index file"""
1266 1266 r = None
1267 1267 if repo:
1268 1268 filelog = repo.file(file_)
1269 1269 if len(filelog):
1270 1270 r = filelog
1271 1271
1272 1272 format = opts.get('format', 0)
1273 1273 if format not in (0, 1):
1274 1274 raise util.Abort("unknown format %d" % format)
1275 1275
1276 1276 if not r:
1277 1277 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1278 1278
1279 1279 if format == 0:
1280 1280 ui.write(" rev offset length base linkrev"
1281 1281 " nodeid p1 p2\n")
1282 1282 elif format == 1:
1283 1283 ui.write(" rev flag offset length"
1284 1284 " size base link p1 p2 nodeid\n")
1285 1285
1286 1286 for i in r:
1287 1287 node = r.node(i)
1288 1288 if format == 0:
1289 1289 try:
1290 1290 pp = r.parents(node)
1291 1291 except:
1292 1292 pp = [nullid, nullid]
1293 1293 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1294 1294 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1295 1295 short(node), short(pp[0]), short(pp[1])))
1296 1296 elif format == 1:
1297 1297 pr = r.parentrevs(i)
1298 1298 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1299 1299 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1300 1300 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1301 1301
1302 1302 def debugindexdot(ui, repo, file_):
1303 1303 """dump an index DAG as a graphviz dot file"""
1304 1304 r = None
1305 1305 if repo:
1306 1306 filelog = repo.file(file_)
1307 1307 if len(filelog):
1308 1308 r = filelog
1309 1309 if not r:
1310 1310 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1311 1311 ui.write("digraph G {\n")
1312 1312 for i in r:
1313 1313 node = r.node(i)
1314 1314 pp = r.parents(node)
1315 1315 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1316 1316 if pp[1] != nullid:
1317 1317 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1318 1318 ui.write("}\n")
1319 1319
1320 1320 def debuginstall(ui):
1321 1321 '''test Mercurial installation
1322 1322
1323 1323 Returns 0 on success.
1324 1324 '''
1325 1325
1326 1326 def writetemp(contents):
1327 1327 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1328 1328 f = os.fdopen(fd, "wb")
1329 1329 f.write(contents)
1330 1330 f.close()
1331 1331 return name
1332 1332
1333 1333 problems = 0
1334 1334
1335 1335 # encoding
1336 1336 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1337 1337 try:
1338 1338 encoding.fromlocal("test")
1339 1339 except util.Abort, inst:
1340 1340 ui.write(" %s\n" % inst)
1341 1341 ui.write(_(" (check that your locale is properly set)\n"))
1342 1342 problems += 1
1343 1343
1344 1344 # compiled modules
1345 1345 ui.status(_("Checking installed modules (%s)...\n")
1346 1346 % os.path.dirname(__file__))
1347 1347 try:
1348 1348 import bdiff, mpatch, base85, osutil
1349 1349 except Exception, inst:
1350 1350 ui.write(" %s\n" % inst)
1351 1351 ui.write(_(" One or more extensions could not be found"))
1352 1352 ui.write(_(" (check that you compiled the extensions)\n"))
1353 1353 problems += 1
1354 1354
1355 1355 # templates
1356 1356 ui.status(_("Checking templates...\n"))
1357 1357 try:
1358 1358 import templater
1359 1359 templater.templater(templater.templatepath("map-cmdline.default"))
1360 1360 except Exception, inst:
1361 1361 ui.write(" %s\n" % inst)
1362 1362 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1363 1363 problems += 1
1364 1364
1365 1365 # patch
1366 1366 ui.status(_("Checking patch...\n"))
1367 1367 patchproblems = 0
1368 1368 a = "1\n2\n3\n4\n"
1369 1369 b = "1\n2\n3\ninsert\n4\n"
1370 1370 fa = writetemp(a)
1371 1371 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1372 1372 os.path.basename(fa))
1373 1373 fd = writetemp(d)
1374 1374
1375 1375 files = {}
1376 1376 try:
1377 1377 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1378 1378 except util.Abort, e:
1379 1379 ui.write(_(" patch call failed:\n"))
1380 1380 ui.write(" " + str(e) + "\n")
1381 1381 patchproblems += 1
1382 1382 else:
1383 1383 if list(files) != [os.path.basename(fa)]:
1384 1384 ui.write(_(" unexpected patch output!\n"))
1385 1385 patchproblems += 1
1386 1386 a = open(fa).read()
1387 1387 if a != b:
1388 1388 ui.write(_(" patch test failed!\n"))
1389 1389 patchproblems += 1
1390 1390
1391 1391 if patchproblems:
1392 1392 if ui.config('ui', 'patch'):
1393 1393 ui.write(_(" (Current patch tool may be incompatible with patch,"
1394 1394 " or misconfigured. Please check your configuration"
1395 1395 " file)\n"))
1396 1396 else:
1397 1397 ui.write(_(" Internal patcher failure, please report this error"
1398 1398 " to http://mercurial.selenic.com/wiki/BugTracker\n"))
1399 1399 problems += patchproblems
1400 1400
1401 1401 os.unlink(fa)
1402 1402 os.unlink(fd)
1403 1403
1404 1404 # editor
1405 1405 ui.status(_("Checking commit editor...\n"))
1406 1406 editor = ui.geteditor()
1407 1407 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1408 1408 if not cmdpath:
1409 1409 if editor == 'vi':
1410 1410 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1411 1411 ui.write(_(" (specify a commit editor in your configuration"
1412 1412 " file)\n"))
1413 1413 else:
1414 1414 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1415 1415 ui.write(_(" (specify a commit editor in your configuration"
1416 1416 " file)\n"))
1417 1417 problems += 1
1418 1418
1419 1419 # check username
1420 1420 ui.status(_("Checking username...\n"))
1421 1421 try:
1422 1422 ui.username()
1423 1423 except util.Abort, e:
1424 1424 ui.write(" %s\n" % e)
1425 1425 ui.write(_(" (specify a username in your configuration file)\n"))
1426 1426 problems += 1
1427 1427
1428 1428 if not problems:
1429 1429 ui.status(_("No problems detected\n"))
1430 1430 else:
1431 1431 ui.write(_("%s problems detected,"
1432 1432 " please check your install!\n") % problems)
1433 1433
1434 1434 return problems
1435 1435
1436 1436 def debugrename(ui, repo, file1, *pats, **opts):
1437 1437 """dump rename information"""
1438 1438
1439 1439 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1440 1440 m = cmdutil.match(repo, (file1,) + pats, opts)
1441 1441 for abs in ctx.walk(m):
1442 1442 fctx = ctx[abs]
1443 1443 o = fctx.filelog().renamed(fctx.filenode())
1444 1444 rel = m.rel(abs)
1445 1445 if o:
1446 1446 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1447 1447 else:
1448 1448 ui.write(_("%s not renamed\n") % rel)
1449 1449
1450 1450 def debugwalk(ui, repo, *pats, **opts):
1451 1451 """show how files match on given patterns"""
1452 1452 m = cmdutil.match(repo, pats, opts)
1453 1453 items = list(repo.walk(m))
1454 1454 if not items:
1455 1455 return
1456 1456 fmt = 'f %%-%ds %%-%ds %%s' % (
1457 1457 max([len(abs) for abs in items]),
1458 1458 max([len(m.rel(abs)) for abs in items]))
1459 1459 for abs in items:
1460 1460 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1461 1461 ui.write("%s\n" % line.rstrip())
1462 1462
1463 1463 def diff(ui, repo, *pats, **opts):
1464 1464 """diff repository (or selected files)
1465 1465
1466 1466 Show differences between revisions for the specified files.
1467 1467
1468 1468 Differences between files are shown using the unified diff format.
1469 1469
1470 1470 .. note::
1471 1471 diff may generate unexpected results for merges, as it will
1472 1472 default to comparing against the working directory's first
1473 1473 parent changeset if no revisions are specified.
1474 1474
1475 1475 When two revision arguments are given, then changes are shown
1476 1476 between those revisions. If only one revision is specified then
1477 1477 that revision is compared to the working directory, and, when no
1478 1478 revisions are specified, the working directory files are compared
1479 1479 to its parent.
1480 1480
1481 1481 Alternatively you can specify -c/--change with a revision to see
1482 1482 the changes in that changeset relative to its first parent.
1483 1483
1484 1484 Without the -a/--text option, diff will avoid generating diffs of
1485 1485 files it detects as binary. With -a, diff will generate a diff
1486 1486 anyway, probably with undesirable results.
1487 1487
1488 1488 Use the -g/--git option to generate diffs in the git extended diff
1489 1489 format. For more information, read :hg:`help diffs`.
1490 1490
1491 1491 Returns 0 on success.
1492 1492 """
1493 1493
1494 1494 revs = opts.get('rev')
1495 1495 change = opts.get('change')
1496 1496 stat = opts.get('stat')
1497 1497 reverse = opts.get('reverse')
1498 1498
1499 1499 if revs and change:
1500 1500 msg = _('cannot specify --rev and --change at the same time')
1501 1501 raise util.Abort(msg)
1502 1502 elif change:
1503 1503 node2 = repo.lookup(change)
1504 1504 node1 = repo[node2].parents()[0].node()
1505 1505 else:
1506 1506 node1, node2 = cmdutil.revpair(repo, revs)
1507 1507
1508 1508 if reverse:
1509 1509 node1, node2 = node2, node1
1510 1510
1511 1511 diffopts = patch.diffopts(ui, opts)
1512 1512 m = cmdutil.match(repo, pats, opts)
1513 1513 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1514 1514 listsubrepos=opts.get('subrepos'))
1515 1515
1516 1516 def export(ui, repo, *changesets, **opts):
1517 1517 """dump the header and diffs for one or more changesets
1518 1518
1519 1519 Print the changeset header and diffs for one or more revisions.
1520 1520
1521 1521 The information shown in the changeset header is: author, date,
1522 1522 branch name (if non-default), changeset hash, parent(s) and commit
1523 1523 comment.
1524 1524
1525 1525 .. note::
1526 1526 export may generate unexpected diff output for merge
1527 1527 changesets, as it will compare the merge changeset against its
1528 1528 first parent only.
1529 1529
1530 1530 Output may be to a file, in which case the name of the file is
1531 1531 given using a format string. The formatting rules are as follows:
1532 1532
1533 1533 :``%%``: literal "%" character
1534 1534 :``%H``: changeset hash (40 hexadecimal digits)
1535 1535 :``%N``: number of patches being generated
1536 1536 :``%R``: changeset revision number
1537 1537 :``%b``: basename of the exporting repository
1538 1538 :``%h``: short-form changeset hash (12 hexadecimal digits)
1539 1539 :``%n``: zero-padded sequence number, starting at 1
1540 1540 :``%r``: zero-padded changeset revision number
1541 1541
1542 1542 Without the -a/--text option, export will avoid generating diffs
1543 1543 of files it detects as binary. With -a, export will generate a
1544 1544 diff anyway, probably with undesirable results.
1545 1545
1546 1546 Use the -g/--git option to generate diffs in the git extended diff
1547 1547 format. See :hg:`help diffs` for more information.
1548 1548
1549 1549 With the --switch-parent option, the diff will be against the
1550 1550 second parent. It can be useful to review a merge.
1551 1551
1552 1552 Returns 0 on success.
1553 1553 """
1554 1554 changesets += tuple(opts.get('rev', []))
1555 1555 if not changesets:
1556 1556 raise util.Abort(_("export requires at least one changeset"))
1557 1557 revs = cmdutil.revrange(repo, changesets)
1558 1558 if len(revs) > 1:
1559 1559 ui.note(_('exporting patches:\n'))
1560 1560 else:
1561 1561 ui.note(_('exporting patch:\n'))
1562 1562 cmdutil.export(repo, revs, template=opts.get('output'),
1563 1563 switch_parent=opts.get('switch_parent'),
1564 1564 opts=patch.diffopts(ui, opts))
1565 1565
1566 1566 def forget(ui, repo, *pats, **opts):
1567 1567 """forget the specified files on the next commit
1568 1568
1569 1569 Mark the specified files so they will no longer be tracked
1570 1570 after the next commit.
1571 1571
1572 1572 This only removes files from the current branch, not from the
1573 1573 entire project history, and it does not delete them from the
1574 1574 working directory.
1575 1575
1576 1576 To undo a forget before the next commit, see :hg:`add`.
1577 1577
1578 1578 Returns 0 on success.
1579 1579 """
1580 1580
1581 1581 if not pats:
1582 1582 raise util.Abort(_('no files specified'))
1583 1583
1584 1584 m = cmdutil.match(repo, pats, opts)
1585 1585 s = repo.status(match=m, clean=True)
1586 1586 forget = sorted(s[0] + s[1] + s[3] + s[6])
1587 1587 errs = 0
1588 1588
1589 1589 for f in m.files():
1590 1590 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1591 1591 ui.warn(_('not removing %s: file is already untracked\n')
1592 1592 % m.rel(f))
1593 1593 errs = 1
1594 1594
1595 1595 for f in forget:
1596 1596 if ui.verbose or not m.exact(f):
1597 1597 ui.status(_('removing %s\n') % m.rel(f))
1598 1598
1599 1599 repo[None].remove(forget, unlink=False)
1600 1600 return errs
1601 1601
1602 1602 def grep(ui, repo, pattern, *pats, **opts):
1603 1603 """search for a pattern in specified files and revisions
1604 1604
1605 1605 Search revisions of files for a regular expression.
1606 1606
1607 1607 This command behaves differently than Unix grep. It only accepts
1608 1608 Python/Perl regexps. It searches repository history, not the
1609 1609 working directory. It always prints the revision number in which a
1610 1610 match appears.
1611 1611
1612 1612 By default, grep only prints output for the first revision of a
1613 1613 file in which it finds a match. To get it to print every revision
1614 1614 that contains a change in match status ("-" for a match that
1615 1615 becomes a non-match, or "+" for a non-match that becomes a match),
1616 1616 use the --all flag.
1617 1617
1618 1618 Returns 0 if a match is found, 1 otherwise.
1619 1619 """
1620 1620 reflags = 0
1621 1621 if opts.get('ignore_case'):
1622 1622 reflags |= re.I
1623 1623 try:
1624 1624 regexp = re.compile(pattern, reflags)
1625 1625 except re.error, inst:
1626 1626 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1627 1627 return 1
1628 1628 sep, eol = ':', '\n'
1629 1629 if opts.get('print0'):
1630 1630 sep = eol = '\0'
1631 1631
1632 1632 getfile = util.lrucachefunc(repo.file)
1633 1633
1634 1634 def matchlines(body):
1635 1635 begin = 0
1636 1636 linenum = 0
1637 1637 while True:
1638 1638 match = regexp.search(body, begin)
1639 1639 if not match:
1640 1640 break
1641 1641 mstart, mend = match.span()
1642 1642 linenum += body.count('\n', begin, mstart) + 1
1643 1643 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1644 1644 begin = body.find('\n', mend) + 1 or len(body)
1645 1645 lend = begin - 1
1646 1646 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1647 1647
1648 1648 class linestate(object):
1649 1649 def __init__(self, line, linenum, colstart, colend):
1650 1650 self.line = line
1651 1651 self.linenum = linenum
1652 1652 self.colstart = colstart
1653 1653 self.colend = colend
1654 1654
1655 1655 def __hash__(self):
1656 1656 return hash((self.linenum, self.line))
1657 1657
1658 1658 def __eq__(self, other):
1659 1659 return self.line == other.line
1660 1660
1661 1661 matches = {}
1662 1662 copies = {}
1663 1663 def grepbody(fn, rev, body):
1664 1664 matches[rev].setdefault(fn, [])
1665 1665 m = matches[rev][fn]
1666 1666 for lnum, cstart, cend, line in matchlines(body):
1667 1667 s = linestate(line, lnum, cstart, cend)
1668 1668 m.append(s)
1669 1669
1670 1670 def difflinestates(a, b):
1671 1671 sm = difflib.SequenceMatcher(None, a, b)
1672 1672 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1673 1673 if tag == 'insert':
1674 1674 for i in xrange(blo, bhi):
1675 1675 yield ('+', b[i])
1676 1676 elif tag == 'delete':
1677 1677 for i in xrange(alo, ahi):
1678 1678 yield ('-', a[i])
1679 1679 elif tag == 'replace':
1680 1680 for i in xrange(alo, ahi):
1681 1681 yield ('-', a[i])
1682 1682 for i in xrange(blo, bhi):
1683 1683 yield ('+', b[i])
1684 1684
1685 1685 def display(fn, ctx, pstates, states):
1686 1686 rev = ctx.rev()
1687 1687 datefunc = ui.quiet and util.shortdate or util.datestr
1688 1688 found = False
1689 1689 filerevmatches = {}
1690 1690 if opts.get('all'):
1691 1691 iter = difflinestates(pstates, states)
1692 1692 else:
1693 1693 iter = [('', l) for l in states]
1694 1694 for change, l in iter:
1695 1695 cols = [fn, str(rev)]
1696 1696 before, match, after = None, None, None
1697 1697 if opts.get('line_number'):
1698 1698 cols.append(str(l.linenum))
1699 1699 if opts.get('all'):
1700 1700 cols.append(change)
1701 1701 if opts.get('user'):
1702 1702 cols.append(ui.shortuser(ctx.user()))
1703 1703 if opts.get('date'):
1704 1704 cols.append(datefunc(ctx.date()))
1705 1705 if opts.get('files_with_matches'):
1706 1706 c = (fn, rev)
1707 1707 if c in filerevmatches:
1708 1708 continue
1709 1709 filerevmatches[c] = 1
1710 1710 else:
1711 1711 before = l.line[:l.colstart]
1712 1712 match = l.line[l.colstart:l.colend]
1713 1713 after = l.line[l.colend:]
1714 1714 ui.write(sep.join(cols))
1715 1715 if before is not None:
1716 1716 ui.write(sep + before)
1717 1717 ui.write(match, label='grep.match')
1718 1718 ui.write(after)
1719 1719 ui.write(eol)
1720 1720 found = True
1721 1721 return found
1722 1722
1723 1723 skip = {}
1724 1724 revfiles = {}
1725 1725 matchfn = cmdutil.match(repo, pats, opts)
1726 1726 found = False
1727 1727 follow = opts.get('follow')
1728 1728
1729 1729 def prep(ctx, fns):
1730 1730 rev = ctx.rev()
1731 1731 pctx = ctx.parents()[0]
1732 1732 parent = pctx.rev()
1733 1733 matches.setdefault(rev, {})
1734 1734 matches.setdefault(parent, {})
1735 1735 files = revfiles.setdefault(rev, [])
1736 1736 for fn in fns:
1737 1737 flog = getfile(fn)
1738 1738 try:
1739 1739 fnode = ctx.filenode(fn)
1740 1740 except error.LookupError:
1741 1741 continue
1742 1742
1743 1743 copied = flog.renamed(fnode)
1744 1744 copy = follow and copied and copied[0]
1745 1745 if copy:
1746 1746 copies.setdefault(rev, {})[fn] = copy
1747 1747 if fn in skip:
1748 1748 if copy:
1749 1749 skip[copy] = True
1750 1750 continue
1751 1751 files.append(fn)
1752 1752
1753 1753 if fn not in matches[rev]:
1754 1754 grepbody(fn, rev, flog.read(fnode))
1755 1755
1756 1756 pfn = copy or fn
1757 1757 if pfn not in matches[parent]:
1758 1758 try:
1759 1759 fnode = pctx.filenode(pfn)
1760 1760 grepbody(pfn, parent, flog.read(fnode))
1761 1761 except error.LookupError:
1762 1762 pass
1763 1763
1764 1764 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1765 1765 rev = ctx.rev()
1766 1766 parent = ctx.parents()[0].rev()
1767 1767 for fn in sorted(revfiles.get(rev, [])):
1768 1768 states = matches[rev][fn]
1769 1769 copy = copies.get(rev, {}).get(fn)
1770 1770 if fn in skip:
1771 1771 if copy:
1772 1772 skip[copy] = True
1773 1773 continue
1774 1774 pstates = matches.get(parent, {}).get(copy or fn, [])
1775 1775 if pstates or states:
1776 1776 r = display(fn, ctx, pstates, states)
1777 1777 found = found or r
1778 1778 if r and not opts.get('all'):
1779 1779 skip[fn] = True
1780 1780 if copy:
1781 1781 skip[copy] = True
1782 1782 del matches[rev]
1783 1783 del revfiles[rev]
1784 1784
1785 1785 return not found
1786 1786
1787 1787 def heads(ui, repo, *branchrevs, **opts):
1788 1788 """show current repository heads or show branch heads
1789 1789
1790 1790 With no arguments, show all repository branch heads.
1791 1791
1792 1792 Repository "heads" are changesets with no child changesets. They are
1793 1793 where development generally takes place and are the usual targets
1794 1794 for update and merge operations. Branch heads are changesets that have
1795 1795 no child changeset on the same branch.
1796 1796
1797 1797 If one or more REVs are given, only branch heads on the branches
1798 1798 associated with the specified changesets are shown.
1799 1799
1800 1800 If -c/--closed is specified, also show branch heads marked closed
1801 1801 (see :hg:`commit --close-branch`).
1802 1802
1803 1803 If STARTREV is specified, only those heads that are descendants of
1804 1804 STARTREV will be displayed.
1805 1805
1806 1806 If -t/--topo is specified, named branch mechanics will be ignored and only
1807 1807 changesets without children will be shown.
1808 1808
1809 1809 Returns 0 if matching heads are found, 1 if not.
1810 1810 """
1811 1811
1812 1812 start = None
1813 1813 if 'rev' in opts:
1814 1814 start = cmdutil.revsingle(repo, opts['rev'], None).node()
1815 1815
1816 1816 if opts.get('topo'):
1817 1817 heads = [repo[h] for h in repo.heads(start)]
1818 1818 else:
1819 1819 heads = []
1820 1820 for b, ls in repo.branchmap().iteritems():
1821 1821 if start is None:
1822 1822 heads += [repo[h] for h in ls]
1823 1823 continue
1824 1824 startrev = repo.changelog.rev(start)
1825 1825 descendants = set(repo.changelog.descendants(startrev))
1826 1826 descendants.add(startrev)
1827 1827 rev = repo.changelog.rev
1828 1828 heads += [repo[h] for h in ls if rev(h) in descendants]
1829 1829
1830 1830 if branchrevs:
1831 1831 branches = set(repo[br].branch() for br in branchrevs)
1832 1832 heads = [h for h in heads if h.branch() in branches]
1833 1833
1834 1834 if not opts.get('closed'):
1835 1835 heads = [h for h in heads if not h.extra().get('close')]
1836 1836
1837 1837 if opts.get('active') and branchrevs:
1838 1838 dagheads = repo.heads(start)
1839 1839 heads = [h for h in heads if h.node() in dagheads]
1840 1840
1841 1841 if branchrevs:
1842 1842 haveheads = set(h.branch() for h in heads)
1843 1843 if branches - haveheads:
1844 1844 headless = ', '.join(b for b in branches - haveheads)
1845 1845 msg = _('no open branch heads found on branches %s')
1846 1846 if opts.get('rev'):
1847 1847 msg += _(' (started at %s)' % opts['rev'])
1848 1848 ui.warn((msg + '\n') % headless)
1849 1849
1850 1850 if not heads:
1851 1851 return 1
1852 1852
1853 1853 heads = sorted(heads, key=lambda x: -x.rev())
1854 1854 displayer = cmdutil.show_changeset(ui, repo, opts)
1855 1855 for ctx in heads:
1856 1856 displayer.show(ctx)
1857 1857 displayer.close()
1858 1858
1859 1859 def help_(ui, name=None, with_version=False, unknowncmd=False):
1860 1860 """show help for a given topic or a help overview
1861 1861
1862 1862 With no arguments, print a list of commands with short help messages.
1863 1863
1864 1864 Given a topic, extension, or command name, print help for that
1865 1865 topic.
1866 1866
1867 1867 Returns 0 if successful.
1868 1868 """
1869 1869 option_lists = []
1870 1870 textwidth = ui.termwidth() - 2
1871 1871
1872 1872 def addglobalopts(aliases):
1873 1873 if ui.verbose:
1874 1874 option_lists.append((_("global options:"), globalopts))
1875 1875 if name == 'shortlist':
1876 1876 option_lists.append((_('use "hg help" for the full list '
1877 1877 'of commands'), ()))
1878 1878 else:
1879 1879 if name == 'shortlist':
1880 1880 msg = _('use "hg help" for the full list of commands '
1881 1881 'or "hg -v" for details')
1882 1882 elif aliases:
1883 msg = _('use "hg -v help%s" to show aliases and '
1883 msg = _('use "hg -v help%s" to show builtin aliases and '
1884 1884 'global options') % (name and " " + name or "")
1885 1885 else:
1886 1886 msg = _('use "hg -v help %s" to show global options') % name
1887 1887 option_lists.append((msg, ()))
1888 1888
1889 1889 def helpcmd(name):
1890 1890 if with_version:
1891 1891 version_(ui)
1892 1892 ui.write('\n')
1893 1893
1894 1894 try:
1895 1895 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1896 1896 except error.AmbiguousCommand, inst:
1897 1897 # py3k fix: except vars can't be used outside the scope of the
1898 1898 # except block, nor can be used inside a lambda. python issue4617
1899 1899 prefix = inst.args[0]
1900 1900 select = lambda c: c.lstrip('^').startswith(prefix)
1901 1901 helplist(_('list of commands:\n\n'), select)
1902 1902 return
1903 1903
1904 1904 # check if it's an invalid alias and display its error if it is
1905 1905 if getattr(entry[0], 'badalias', False):
1906 1906 if not unknowncmd:
1907 1907 entry[0](ui)
1908 1908 return
1909 1909
1910 1910 # synopsis
1911 1911 if len(entry) > 2:
1912 1912 if entry[2].startswith('hg'):
1913 1913 ui.write("%s\n" % entry[2])
1914 1914 else:
1915 1915 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1916 1916 else:
1917 1917 ui.write('hg %s\n' % aliases[0])
1918 1918
1919 1919 # aliases
1920 1920 if not ui.quiet and len(aliases) > 1:
1921 1921 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1922 1922
1923 1923 # description
1924 1924 doc = gettext(entry[0].__doc__)
1925 1925 if not doc:
1926 1926 doc = _("(no help text available)")
1927 1927 if hasattr(entry[0], 'definition'): # aliased command
1928 1928 if entry[0].definition.startswith('!'): # shell alias
1929 1929 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1930 1930 else:
1931 1931 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1932 1932 if ui.quiet:
1933 1933 doc = doc.splitlines()[0]
1934 1934 keep = ui.verbose and ['verbose'] or []
1935 1935 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1936 1936 ui.write("\n%s\n" % formatted)
1937 1937 if pruned:
1938 1938 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1939 1939
1940 1940 if not ui.quiet:
1941 1941 # options
1942 1942 if entry[1]:
1943 1943 option_lists.append((_("options:\n"), entry[1]))
1944 1944
1945 1945 addglobalopts(False)
1946 1946
1947 1947 def helplist(header, select=None):
1948 1948 h = {}
1949 1949 cmds = {}
1950 1950 for c, e in table.iteritems():
1951 1951 f = c.split("|", 1)[0]
1952 1952 if select and not select(f):
1953 1953 continue
1954 1954 if (not select and name != 'shortlist' and
1955 1955 e[0].__module__ != __name__):
1956 1956 continue
1957 1957 if name == "shortlist" and not f.startswith("^"):
1958 1958 continue
1959 1959 f = f.lstrip("^")
1960 1960 if not ui.debugflag and f.startswith("debug"):
1961 1961 continue
1962 1962 doc = e[0].__doc__
1963 1963 if doc and 'DEPRECATED' in doc and not ui.verbose:
1964 1964 continue
1965 1965 doc = gettext(doc)
1966 1966 if not doc:
1967 1967 doc = _("(no help text available)")
1968 1968 h[f] = doc.splitlines()[0].rstrip()
1969 1969 cmds[f] = c.lstrip("^")
1970 1970
1971 1971 if not h:
1972 1972 ui.status(_('no commands defined\n'))
1973 1973 return
1974 1974
1975 1975 ui.status(header)
1976 1976 fns = sorted(h)
1977 1977 m = max(map(len, fns))
1978 1978 for f in fns:
1979 1979 if ui.verbose:
1980 1980 commands = cmds[f].replace("|",", ")
1981 1981 ui.write(" %s:\n %s\n"%(commands, h[f]))
1982 1982 else:
1983 1983 ui.write('%s\n' % (util.wrap(h[f], textwidth,
1984 1984 initindent=' %-*s ' % (m, f),
1985 1985 hangindent=' ' * (m + 4))))
1986 1986
1987 1987 if not ui.quiet:
1988 1988 addglobalopts(True)
1989 1989
1990 1990 def helptopic(name):
1991 1991 for names, header, doc in help.helptable:
1992 1992 if name in names:
1993 1993 break
1994 1994 else:
1995 1995 raise error.UnknownCommand(name)
1996 1996
1997 1997 # description
1998 1998 if not doc:
1999 1999 doc = _("(no help text available)")
2000 2000 if hasattr(doc, '__call__'):
2001 2001 doc = doc()
2002 2002
2003 2003 ui.write("%s\n\n" % header)
2004 2004 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2005 2005
2006 2006 def helpext(name):
2007 2007 try:
2008 2008 mod = extensions.find(name)
2009 2009 doc = gettext(mod.__doc__) or _('no help text available')
2010 2010 except KeyError:
2011 2011 mod = None
2012 2012 doc = extensions.disabledext(name)
2013 2013 if not doc:
2014 2014 raise error.UnknownCommand(name)
2015 2015
2016 2016 if '\n' not in doc:
2017 2017 head, tail = doc, ""
2018 2018 else:
2019 2019 head, tail = doc.split('\n', 1)
2020 2020 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2021 2021 if tail:
2022 2022 ui.write(minirst.format(tail, textwidth))
2023 2023 ui.status('\n\n')
2024 2024
2025 2025 if mod:
2026 2026 try:
2027 2027 ct = mod.cmdtable
2028 2028 except AttributeError:
2029 2029 ct = {}
2030 2030 modcmds = set([c.split('|', 1)[0] for c in ct])
2031 2031 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2032 2032 else:
2033 2033 ui.write(_('use "hg help extensions" for information on enabling '
2034 2034 'extensions\n'))
2035 2035
2036 2036 def helpextcmd(name):
2037 2037 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2038 2038 doc = gettext(mod.__doc__).splitlines()[0]
2039 2039
2040 2040 msg = help.listexts(_("'%s' is provided by the following "
2041 2041 "extension:") % cmd, {ext: doc}, len(ext),
2042 2042 indent=4)
2043 2043 ui.write(minirst.format(msg, textwidth))
2044 2044 ui.write('\n\n')
2045 2045 ui.write(_('use "hg help extensions" for information on enabling '
2046 2046 'extensions\n'))
2047 2047
2048 2048 help.addtopichook('revsets', revset.makedoc)
2049 2049
2050 2050 if name and name != 'shortlist':
2051 2051 i = None
2052 2052 if unknowncmd:
2053 2053 queries = (helpextcmd,)
2054 2054 else:
2055 2055 queries = (helptopic, helpcmd, helpext, helpextcmd)
2056 2056 for f in queries:
2057 2057 try:
2058 2058 f(name)
2059 2059 i = None
2060 2060 break
2061 2061 except error.UnknownCommand, inst:
2062 2062 i = inst
2063 2063 if i:
2064 2064 raise i
2065 2065
2066 2066 else:
2067 2067 # program name
2068 2068 if ui.verbose or with_version:
2069 2069 version_(ui)
2070 2070 else:
2071 2071 ui.status(_("Mercurial Distributed SCM\n"))
2072 2072 ui.status('\n')
2073 2073
2074 2074 # list of commands
2075 2075 if name == "shortlist":
2076 2076 header = _('basic commands:\n\n')
2077 2077 else:
2078 2078 header = _('list of commands:\n\n')
2079 2079
2080 2080 helplist(header)
2081 2081 if name != 'shortlist':
2082 2082 exts, maxlength = extensions.enabled()
2083 2083 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2084 2084 if text:
2085 2085 ui.write("\n%s\n" % minirst.format(text, textwidth))
2086 2086
2087 2087 # list all option lists
2088 2088 opt_output = []
2089 2089 multioccur = False
2090 2090 for title, options in option_lists:
2091 2091 opt_output.append(("\n%s" % title, None))
2092 2092 for option in options:
2093 2093 if len(option) == 5:
2094 2094 shortopt, longopt, default, desc, optlabel = option
2095 2095 else:
2096 2096 shortopt, longopt, default, desc = option
2097 2097 optlabel = _("VALUE") # default label
2098 2098
2099 2099 if _("DEPRECATED") in desc and not ui.verbose:
2100 2100 continue
2101 2101 if isinstance(default, list):
2102 2102 numqualifier = " %s [+]" % optlabel
2103 2103 multioccur = True
2104 2104 elif (default is not None) and not isinstance(default, bool):
2105 2105 numqualifier = " %s" % optlabel
2106 2106 else:
2107 2107 numqualifier = ""
2108 2108 opt_output.append(("%2s%s" %
2109 2109 (shortopt and "-%s" % shortopt,
2110 2110 longopt and " --%s%s" %
2111 2111 (longopt, numqualifier)),
2112 2112 "%s%s" % (desc,
2113 2113 default
2114 2114 and _(" (default: %s)") % default
2115 2115 or "")))
2116 2116 if multioccur:
2117 2117 msg = _("\n[+] marked option can be specified multiple times")
2118 2118 if ui.verbose and name != 'shortlist':
2119 2119 opt_output.append((msg, None))
2120 2120 else:
2121 2121 opt_output.insert(-1, (msg, None))
2122 2122
2123 2123 if not name:
2124 2124 ui.write(_("\nadditional help topics:\n\n"))
2125 2125 topics = []
2126 2126 for names, header, doc in help.helptable:
2127 2127 topics.append((sorted(names, key=len, reverse=True)[0], header))
2128 2128 topics_len = max([len(s[0]) for s in topics])
2129 2129 for t, desc in topics:
2130 2130 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2131 2131
2132 2132 if opt_output:
2133 2133 colwidth = encoding.colwidth
2134 2134 # normalize: (opt or message, desc or None, width of opt)
2135 2135 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2136 2136 for opt, desc in opt_output]
2137 2137 hanging = max([e[2] for e in entries])
2138 2138 for opt, desc, width in entries:
2139 2139 if desc:
2140 2140 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2141 2141 hangindent = ' ' * (hanging + 3)
2142 2142 ui.write('%s\n' % (util.wrap(desc, textwidth,
2143 2143 initindent=initindent,
2144 2144 hangindent=hangindent)))
2145 2145 else:
2146 2146 ui.write("%s\n" % opt)
2147 2147
2148 2148 def identify(ui, repo, source=None,
2149 2149 rev=None, num=None, id=None, branch=None, tags=None):
2150 2150 """identify the working copy or specified revision
2151 2151
2152 2152 With no revision, print a summary of the current state of the
2153 2153 repository.
2154 2154
2155 2155 Specifying a path to a repository root or Mercurial bundle will
2156 2156 cause lookup to operate on that repository/bundle.
2157 2157
2158 2158 This summary identifies the repository state using one or two
2159 2159 parent hash identifiers, followed by a "+" if there are
2160 2160 uncommitted changes in the working directory, a list of tags for
2161 2161 this revision and a branch name for non-default branches.
2162 2162
2163 2163 Returns 0 if successful.
2164 2164 """
2165 2165
2166 2166 if not repo and not source:
2167 2167 raise util.Abort(_("there is no Mercurial repository here "
2168 2168 "(.hg not found)"))
2169 2169
2170 2170 hexfunc = ui.debugflag and hex or short
2171 2171 default = not (num or id or branch or tags)
2172 2172 output = []
2173 2173
2174 2174 revs = []
2175 2175 if source:
2176 2176 source, branches = hg.parseurl(ui.expandpath(source))
2177 2177 repo = hg.repository(ui, source)
2178 2178 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2179 2179
2180 2180 if not repo.local():
2181 2181 if not rev and revs:
2182 2182 rev = revs[0]
2183 2183 if not rev:
2184 2184 rev = "tip"
2185 2185 if num or branch or tags:
2186 2186 raise util.Abort(
2187 2187 "can't query remote revision number, branch, or tags")
2188 2188 output = [hexfunc(repo.lookup(rev))]
2189 2189 elif not rev:
2190 2190 ctx = repo[None]
2191 2191 parents = ctx.parents()
2192 2192 changed = False
2193 2193 if default or id or num:
2194 2194 changed = util.any(repo.status())
2195 2195 if default or id:
2196 2196 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2197 2197 (changed) and "+" or "")]
2198 2198 if num:
2199 2199 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2200 2200 (changed) and "+" or ""))
2201 2201 else:
2202 2202 ctx = cmdutil.revsingle(repo, rev)
2203 2203 if default or id:
2204 2204 output = [hexfunc(ctx.node())]
2205 2205 if num:
2206 2206 output.append(str(ctx.rev()))
2207 2207
2208 2208 if repo.local() and default and not ui.quiet:
2209 2209 b = ctx.branch()
2210 2210 if b != 'default':
2211 2211 output.append("(%s)" % b)
2212 2212
2213 2213 # multiple tags for a single parent separated by '/'
2214 2214 t = "/".join(ctx.tags())
2215 2215 if t:
2216 2216 output.append(t)
2217 2217
2218 2218 if branch:
2219 2219 output.append(ctx.branch())
2220 2220
2221 2221 if tags:
2222 2222 output.extend(ctx.tags())
2223 2223
2224 2224 ui.write("%s\n" % ' '.join(output))
2225 2225
2226 2226 def import_(ui, repo, patch1, *patches, **opts):
2227 2227 """import an ordered set of patches
2228 2228
2229 2229 Import a list of patches and commit them individually (unless
2230 2230 --no-commit is specified).
2231 2231
2232 2232 If there are outstanding changes in the working directory, import
2233 2233 will abort unless given the -f/--force flag.
2234 2234
2235 2235 You can import a patch straight from a mail message. Even patches
2236 2236 as attachments work (to use the body part, it must have type
2237 2237 text/plain or text/x-patch). From and Subject headers of email
2238 2238 message are used as default committer and commit message. All
2239 2239 text/plain body parts before first diff are added to commit
2240 2240 message.
2241 2241
2242 2242 If the imported patch was generated by :hg:`export`, user and
2243 2243 description from patch override values from message headers and
2244 2244 body. Values given on command line with -m/--message and -u/--user
2245 2245 override these.
2246 2246
2247 2247 If --exact is specified, import will set the working directory to
2248 2248 the parent of each patch before applying it, and will abort if the
2249 2249 resulting changeset has a different ID than the one recorded in
2250 2250 the patch. This may happen due to character set problems or other
2251 2251 deficiencies in the text patch format.
2252 2252
2253 2253 With -s/--similarity, hg will attempt to discover renames and
2254 2254 copies in the patch in the same way as 'addremove'.
2255 2255
2256 2256 To read a patch from standard input, use "-" as the patch name. If
2257 2257 a URL is specified, the patch will be downloaded from it.
2258 2258 See :hg:`help dates` for a list of formats valid for -d/--date.
2259 2259
2260 2260 Returns 0 on success.
2261 2261 """
2262 2262 patches = (patch1,) + patches
2263 2263
2264 2264 date = opts.get('date')
2265 2265 if date:
2266 2266 opts['date'] = util.parsedate(date)
2267 2267
2268 2268 try:
2269 2269 sim = float(opts.get('similarity') or 0)
2270 2270 except ValueError:
2271 2271 raise util.Abort(_('similarity must be a number'))
2272 2272 if sim < 0 or sim > 100:
2273 2273 raise util.Abort(_('similarity must be between 0 and 100'))
2274 2274
2275 2275 if opts.get('exact') or not opts.get('force'):
2276 2276 cmdutil.bail_if_changed(repo)
2277 2277
2278 2278 d = opts["base"]
2279 2279 strip = opts["strip"]
2280 2280 wlock = lock = None
2281 2281 msgs = []
2282 2282
2283 2283 def tryone(ui, hunk):
2284 2284 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2285 2285 patch.extract(ui, hunk)
2286 2286
2287 2287 if not tmpname:
2288 2288 return None
2289 2289 commitid = _('to working directory')
2290 2290
2291 2291 try:
2292 2292 cmdline_message = cmdutil.logmessage(opts)
2293 2293 if cmdline_message:
2294 2294 # pickup the cmdline msg
2295 2295 message = cmdline_message
2296 2296 elif message:
2297 2297 # pickup the patch msg
2298 2298 message = message.strip()
2299 2299 else:
2300 2300 # launch the editor
2301 2301 message = None
2302 2302 ui.debug('message:\n%s\n' % message)
2303 2303
2304 2304 wp = repo.parents()
2305 2305 if opts.get('exact'):
2306 2306 if not nodeid or not p1:
2307 2307 raise util.Abort(_('not a Mercurial patch'))
2308 2308 p1 = repo.lookup(p1)
2309 2309 p2 = repo.lookup(p2 or hex(nullid))
2310 2310
2311 2311 if p1 != wp[0].node():
2312 2312 hg.clean(repo, p1)
2313 2313 repo.dirstate.setparents(p1, p2)
2314 2314 elif p2:
2315 2315 try:
2316 2316 p1 = repo.lookup(p1)
2317 2317 p2 = repo.lookup(p2)
2318 2318 if p1 == wp[0].node():
2319 2319 repo.dirstate.setparents(p1, p2)
2320 2320 except error.RepoError:
2321 2321 pass
2322 2322 if opts.get('exact') or opts.get('import_branch'):
2323 2323 repo.dirstate.setbranch(branch or 'default')
2324 2324
2325 2325 files = {}
2326 2326 try:
2327 2327 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2328 2328 files=files, eolmode=None)
2329 2329 finally:
2330 2330 files = cmdutil.updatedir(ui, repo, files,
2331 2331 similarity=sim / 100.0)
2332 2332 if opts.get('no_commit'):
2333 2333 if message:
2334 2334 msgs.append(message)
2335 2335 else:
2336 2336 if opts.get('exact'):
2337 2337 m = None
2338 2338 else:
2339 2339 m = cmdutil.matchfiles(repo, files or [])
2340 2340 n = repo.commit(message, opts.get('user') or user,
2341 2341 opts.get('date') or date, match=m,
2342 2342 editor=cmdutil.commiteditor)
2343 2343 if opts.get('exact'):
2344 2344 if hex(n) != nodeid:
2345 2345 repo.rollback()
2346 2346 raise util.Abort(_('patch is damaged'
2347 2347 ' or loses information'))
2348 2348 # Force a dirstate write so that the next transaction
2349 2349 # backups an up-do-date file.
2350 2350 repo.dirstate.write()
2351 2351 if n:
2352 2352 commitid = short(n)
2353 2353
2354 2354 return commitid
2355 2355 finally:
2356 2356 os.unlink(tmpname)
2357 2357
2358 2358 try:
2359 2359 wlock = repo.wlock()
2360 2360 lock = repo.lock()
2361 2361 lastcommit = None
2362 2362 for p in patches:
2363 2363 pf = os.path.join(d, p)
2364 2364
2365 2365 if pf == '-':
2366 2366 ui.status(_("applying patch from stdin\n"))
2367 2367 pf = sys.stdin
2368 2368 else:
2369 2369 ui.status(_("applying %s\n") % p)
2370 2370 pf = url.open(ui, pf)
2371 2371
2372 2372 haspatch = False
2373 2373 for hunk in patch.split(pf):
2374 2374 commitid = tryone(ui, hunk)
2375 2375 if commitid:
2376 2376 haspatch = True
2377 2377 if lastcommit:
2378 2378 ui.status(_('applied %s\n') % lastcommit)
2379 2379 lastcommit = commitid
2380 2380
2381 2381 if not haspatch:
2382 2382 raise util.Abort(_('no diffs found'))
2383 2383
2384 2384 if msgs:
2385 2385 repo.opener('last-message.txt', 'wb').write('\n* * *\n'.join(msgs))
2386 2386 finally:
2387 2387 release(lock, wlock)
2388 2388
2389 2389 def incoming(ui, repo, source="default", **opts):
2390 2390 """show new changesets found in source
2391 2391
2392 2392 Show new changesets found in the specified path/URL or the default
2393 2393 pull location. These are the changesets that would have been pulled
2394 2394 if a pull at the time you issued this command.
2395 2395
2396 2396 For remote repository, using --bundle avoids downloading the
2397 2397 changesets twice if the incoming is followed by a pull.
2398 2398
2399 2399 See pull for valid source format details.
2400 2400
2401 2401 Returns 0 if there are incoming changes, 1 otherwise.
2402 2402 """
2403 2403 if opts.get('bundle') and opts.get('subrepos'):
2404 2404 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2405 2405
2406 2406 ret = hg.incoming(ui, repo, source, opts)
2407 2407 return ret
2408 2408
2409 2409 def init(ui, dest=".", **opts):
2410 2410 """create a new repository in the given directory
2411 2411
2412 2412 Initialize a new repository in the given directory. If the given
2413 2413 directory does not exist, it will be created.
2414 2414
2415 2415 If no directory is given, the current directory is used.
2416 2416
2417 2417 It is possible to specify an ``ssh://`` URL as the destination.
2418 2418 See :hg:`help urls` for more information.
2419 2419
2420 2420 Returns 0 on success.
2421 2421 """
2422 2422 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2423 2423
2424 2424 def locate(ui, repo, *pats, **opts):
2425 2425 """locate files matching specific patterns
2426 2426
2427 2427 Print files under Mercurial control in the working directory whose
2428 2428 names match the given patterns.
2429 2429
2430 2430 By default, this command searches all directories in the working
2431 2431 directory. To search just the current directory and its
2432 2432 subdirectories, use "--include .".
2433 2433
2434 2434 If no patterns are given to match, this command prints the names
2435 2435 of all files under Mercurial control in the working directory.
2436 2436
2437 2437 If you want to feed the output of this command into the "xargs"
2438 2438 command, use the -0 option to both this command and "xargs". This
2439 2439 will avoid the problem of "xargs" treating single filenames that
2440 2440 contain whitespace as multiple filenames.
2441 2441
2442 2442 Returns 0 if a match is found, 1 otherwise.
2443 2443 """
2444 2444 end = opts.get('print0') and '\0' or '\n'
2445 2445 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
2446 2446
2447 2447 ret = 1
2448 2448 m = cmdutil.match(repo, pats, opts, default='relglob')
2449 2449 m.bad = lambda x, y: False
2450 2450 for abs in repo[rev].walk(m):
2451 2451 if not rev and abs not in repo.dirstate:
2452 2452 continue
2453 2453 if opts.get('fullpath'):
2454 2454 ui.write(repo.wjoin(abs), end)
2455 2455 else:
2456 2456 ui.write(((pats and m.rel(abs)) or abs), end)
2457 2457 ret = 0
2458 2458
2459 2459 return ret
2460 2460
2461 2461 def log(ui, repo, *pats, **opts):
2462 2462 """show revision history of entire repository or files
2463 2463
2464 2464 Print the revision history of the specified files or the entire
2465 2465 project.
2466 2466
2467 2467 File history is shown without following rename or copy history of
2468 2468 files. Use -f/--follow with a filename to follow history across
2469 2469 renames and copies. --follow without a filename will only show
2470 2470 ancestors or descendants of the starting revision. --follow-first
2471 2471 only follows the first parent of merge revisions.
2472 2472
2473 2473 If no revision range is specified, the default is ``tip:0`` unless
2474 2474 --follow is set, in which case the working directory parent is
2475 2475 used as the starting revision. You can specify a revision set for
2476 2476 log, see :hg:`help revsets` for more information.
2477 2477
2478 2478 See :hg:`help dates` for a list of formats valid for -d/--date.
2479 2479
2480 2480 By default this command prints revision number and changeset id,
2481 2481 tags, non-trivial parents, user, date and time, and a summary for
2482 2482 each commit. When the -v/--verbose switch is used, the list of
2483 2483 changed files and full commit message are shown.
2484 2484
2485 2485 .. note::
2486 2486 log -p/--patch may generate unexpected diff output for merge
2487 2487 changesets, as it will only compare the merge changeset against
2488 2488 its first parent. Also, only files different from BOTH parents
2489 2489 will appear in files:.
2490 2490
2491 2491 Returns 0 on success.
2492 2492 """
2493 2493
2494 2494 matchfn = cmdutil.match(repo, pats, opts)
2495 2495 limit = cmdutil.loglimit(opts)
2496 2496 count = 0
2497 2497
2498 2498 endrev = None
2499 2499 if opts.get('copies') and opts.get('rev'):
2500 2500 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2501 2501
2502 2502 df = False
2503 2503 if opts["date"]:
2504 2504 df = util.matchdate(opts["date"])
2505 2505
2506 2506 branches = opts.get('branch', []) + opts.get('only_branch', [])
2507 2507 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2508 2508
2509 2509 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2510 2510 def prep(ctx, fns):
2511 2511 rev = ctx.rev()
2512 2512 parents = [p for p in repo.changelog.parentrevs(rev)
2513 2513 if p != nullrev]
2514 2514 if opts.get('no_merges') and len(parents) == 2:
2515 2515 return
2516 2516 if opts.get('only_merges') and len(parents) != 2:
2517 2517 return
2518 2518 if opts.get('branch') and ctx.branch() not in opts['branch']:
2519 2519 return
2520 2520 if df and not df(ctx.date()[0]):
2521 2521 return
2522 2522 if opts['user'] and not [k for k in opts['user']
2523 2523 if k.lower() in ctx.user().lower()]:
2524 2524 return
2525 2525 if opts.get('keyword'):
2526 2526 for k in [kw.lower() for kw in opts['keyword']]:
2527 2527 if (k in ctx.user().lower() or
2528 2528 k in ctx.description().lower() or
2529 2529 k in " ".join(ctx.files()).lower()):
2530 2530 break
2531 2531 else:
2532 2532 return
2533 2533
2534 2534 copies = None
2535 2535 if opts.get('copies') and rev:
2536 2536 copies = []
2537 2537 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2538 2538 for fn in ctx.files():
2539 2539 rename = getrenamed(fn, rev)
2540 2540 if rename:
2541 2541 copies.append((fn, rename[0]))
2542 2542
2543 2543 revmatchfn = None
2544 2544 if opts.get('patch') or opts.get('stat'):
2545 2545 if opts.get('follow') or opts.get('follow_first'):
2546 2546 # note: this might be wrong when following through merges
2547 2547 revmatchfn = cmdutil.match(repo, fns, default='path')
2548 2548 else:
2549 2549 revmatchfn = matchfn
2550 2550
2551 2551 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2552 2552
2553 2553 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2554 2554 if count == limit:
2555 2555 break
2556 2556 if displayer.flush(ctx.rev()):
2557 2557 count += 1
2558 2558 displayer.close()
2559 2559
2560 2560 def manifest(ui, repo, node=None, rev=None):
2561 2561 """output the current or given revision of the project manifest
2562 2562
2563 2563 Print a list of version controlled files for the given revision.
2564 2564 If no revision is given, the first parent of the working directory
2565 2565 is used, or the null revision if no revision is checked out.
2566 2566
2567 2567 With -v, print file permissions, symlink and executable bits.
2568 2568 With --debug, print file revision hashes.
2569 2569
2570 2570 Returns 0 on success.
2571 2571 """
2572 2572
2573 2573 if rev and node:
2574 2574 raise util.Abort(_("please specify just one revision"))
2575 2575
2576 2576 if not node:
2577 2577 node = rev
2578 2578
2579 2579 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2580 2580 ctx = cmdutil.revsingle(repo, node)
2581 2581 for f in ctx:
2582 2582 if ui.debugflag:
2583 2583 ui.write("%40s " % hex(ctx.manifest()[f]))
2584 2584 if ui.verbose:
2585 2585 ui.write(decor[ctx.flags(f)])
2586 2586 ui.write("%s\n" % f)
2587 2587
2588 2588 def merge(ui, repo, node=None, **opts):
2589 2589 """merge working directory with another revision
2590 2590
2591 2591 The current working directory is updated with all changes made in
2592 2592 the requested revision since the last common predecessor revision.
2593 2593
2594 2594 Files that changed between either parent are marked as changed for
2595 2595 the next commit and a commit must be performed before any further
2596 2596 updates to the repository are allowed. The next commit will have
2597 2597 two parents.
2598 2598
2599 2599 ``--tool`` can be used to specify the merge tool used for file
2600 2600 merges. It overrides the HGMERGE environment variable and your
2601 2601 configuration files.
2602 2602
2603 2603 If no revision is specified, the working directory's parent is a
2604 2604 head revision, and the current branch contains exactly one other
2605 2605 head, the other head is merged with by default. Otherwise, an
2606 2606 explicit revision with which to merge with must be provided.
2607 2607
2608 2608 :hg:`resolve` must be used to resolve unresolved files.
2609 2609
2610 2610 To undo an uncommitted merge, use :hg:`update --clean .` which
2611 2611 will check out a clean copy of the original merge parent, losing
2612 2612 all changes.
2613 2613
2614 2614 Returns 0 on success, 1 if there are unresolved files.
2615 2615 """
2616 2616
2617 2617 if opts.get('rev') and node:
2618 2618 raise util.Abort(_("please specify just one revision"))
2619 2619 if not node:
2620 2620 node = opts.get('rev')
2621 2621
2622 2622 if not node:
2623 2623 branch = repo[None].branch()
2624 2624 bheads = repo.branchheads(branch)
2625 2625 if len(bheads) > 2:
2626 2626 raise util.Abort(_(
2627 2627 'branch \'%s\' has %d heads - '
2628 2628 'please merge with an explicit rev\n'
2629 2629 '(run \'hg heads .\' to see heads)')
2630 2630 % (branch, len(bheads)))
2631 2631
2632 2632 parent = repo.dirstate.parents()[0]
2633 2633 if len(bheads) == 1:
2634 2634 if len(repo.heads()) > 1:
2635 2635 raise util.Abort(_(
2636 2636 'branch \'%s\' has one head - '
2637 2637 'please merge with an explicit rev\n'
2638 2638 '(run \'hg heads\' to see all heads)')
2639 2639 % branch)
2640 2640 msg = _('there is nothing to merge')
2641 2641 if parent != repo.lookup(repo[None].branch()):
2642 2642 msg = _('%s - use "hg update" instead') % msg
2643 2643 raise util.Abort(msg)
2644 2644
2645 2645 if parent not in bheads:
2646 2646 raise util.Abort(_('working dir not at a head rev - '
2647 2647 'use "hg update" or merge with an explicit rev'))
2648 2648 node = parent == bheads[0] and bheads[-1] or bheads[0]
2649 2649 else:
2650 2650 node = cmdutil.revsingle(repo, node).node()
2651 2651
2652 2652 if opts.get('preview'):
2653 2653 # find nodes that are ancestors of p2 but not of p1
2654 2654 p1 = repo.lookup('.')
2655 2655 p2 = repo.lookup(node)
2656 2656 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2657 2657
2658 2658 displayer = cmdutil.show_changeset(ui, repo, opts)
2659 2659 for node in nodes:
2660 2660 displayer.show(repo[node])
2661 2661 displayer.close()
2662 2662 return 0
2663 2663
2664 2664 try:
2665 2665 # ui.forcemerge is an internal variable, do not document
2666 2666 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2667 2667 return hg.merge(repo, node, force=opts.get('force'))
2668 2668 finally:
2669 2669 ui.setconfig('ui', 'forcemerge', '')
2670 2670
2671 2671 def outgoing(ui, repo, dest=None, **opts):
2672 2672 """show changesets not found in the destination
2673 2673
2674 2674 Show changesets not found in the specified destination repository
2675 2675 or the default push location. These are the changesets that would
2676 2676 be pushed if a push was requested.
2677 2677
2678 2678 See pull for details of valid destination formats.
2679 2679
2680 2680 Returns 0 if there are outgoing changes, 1 otherwise.
2681 2681 """
2682 2682 ret = hg.outgoing(ui, repo, dest, opts)
2683 2683 return ret
2684 2684
2685 2685 def parents(ui, repo, file_=None, **opts):
2686 2686 """show the parents of the working directory or revision
2687 2687
2688 2688 Print the working directory's parent revisions. If a revision is
2689 2689 given via -r/--rev, the parent of that revision will be printed.
2690 2690 If a file argument is given, the revision in which the file was
2691 2691 last changed (before the working directory revision or the
2692 2692 argument to --rev if given) is printed.
2693 2693
2694 2694 Returns 0 on success.
2695 2695 """
2696 2696
2697 2697 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
2698 2698
2699 2699 if file_:
2700 2700 m = cmdutil.match(repo, (file_,), opts)
2701 2701 if m.anypats() or len(m.files()) != 1:
2702 2702 raise util.Abort(_('can only specify an explicit filename'))
2703 2703 file_ = m.files()[0]
2704 2704 filenodes = []
2705 2705 for cp in ctx.parents():
2706 2706 if not cp:
2707 2707 continue
2708 2708 try:
2709 2709 filenodes.append(cp.filenode(file_))
2710 2710 except error.LookupError:
2711 2711 pass
2712 2712 if not filenodes:
2713 2713 raise util.Abort(_("'%s' not found in manifest!") % file_)
2714 2714 fl = repo.file(file_)
2715 2715 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2716 2716 else:
2717 2717 p = [cp.node() for cp in ctx.parents()]
2718 2718
2719 2719 displayer = cmdutil.show_changeset(ui, repo, opts)
2720 2720 for n in p:
2721 2721 if n != nullid:
2722 2722 displayer.show(repo[n])
2723 2723 displayer.close()
2724 2724
2725 2725 def paths(ui, repo, search=None):
2726 2726 """show aliases for remote repositories
2727 2727
2728 2728 Show definition of symbolic path name NAME. If no name is given,
2729 2729 show definition of all available names.
2730 2730
2731 2731 Path names are defined in the [paths] section of your
2732 2732 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2733 2733 repository, ``.hg/hgrc`` is used, too.
2734 2734
2735 2735 The path names ``default`` and ``default-push`` have a special
2736 2736 meaning. When performing a push or pull operation, they are used
2737 2737 as fallbacks if no location is specified on the command-line.
2738 2738 When ``default-push`` is set, it will be used for push and
2739 2739 ``default`` will be used for pull; otherwise ``default`` is used
2740 2740 as the fallback for both. When cloning a repository, the clone
2741 2741 source is written as ``default`` in ``.hg/hgrc``. Note that
2742 2742 ``default`` and ``default-push`` apply to all inbound (e.g.
2743 2743 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2744 2744 :hg:`bundle`) operations.
2745 2745
2746 2746 See :hg:`help urls` for more information.
2747 2747
2748 2748 Returns 0 on success.
2749 2749 """
2750 2750 if search:
2751 2751 for name, path in ui.configitems("paths"):
2752 2752 if name == search:
2753 2753 ui.write("%s\n" % url.hidepassword(path))
2754 2754 return
2755 2755 ui.warn(_("not found!\n"))
2756 2756 return 1
2757 2757 else:
2758 2758 for name, path in ui.configitems("paths"):
2759 2759 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2760 2760
2761 2761 def postincoming(ui, repo, modheads, optupdate, checkout):
2762 2762 if modheads == 0:
2763 2763 return
2764 2764 if optupdate:
2765 2765 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2766 2766 return hg.update(repo, checkout)
2767 2767 else:
2768 2768 ui.status(_("not updating, since new heads added\n"))
2769 2769 if modheads > 1:
2770 2770 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2771 2771 else:
2772 2772 ui.status(_("(run 'hg update' to get a working copy)\n"))
2773 2773
2774 2774 def pull(ui, repo, source="default", **opts):
2775 2775 """pull changes from the specified source
2776 2776
2777 2777 Pull changes from a remote repository to a local one.
2778 2778
2779 2779 This finds all changes from the repository at the specified path
2780 2780 or URL and adds them to a local repository (the current one unless
2781 2781 -R is specified). By default, this does not update the copy of the
2782 2782 project in the working directory.
2783 2783
2784 2784 Use :hg:`incoming` if you want to see what would have been added
2785 2785 by a pull at the time you issued this command. If you then decide
2786 2786 to add those changes to the repository, you should use :hg:`pull
2787 2787 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2788 2788
2789 2789 If SOURCE is omitted, the 'default' path will be used.
2790 2790 See :hg:`help urls` for more information.
2791 2791
2792 2792 Returns 0 on success, 1 if an update had unresolved files.
2793 2793 """
2794 2794 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2795 2795 other = hg.repository(hg.remoteui(repo, opts), source)
2796 2796 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2797 2797 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2798 2798 if revs:
2799 2799 try:
2800 2800 revs = [other.lookup(rev) for rev in revs]
2801 2801 except error.CapabilityError:
2802 2802 err = _("other repository doesn't support revision lookup, "
2803 2803 "so a rev cannot be specified.")
2804 2804 raise util.Abort(err)
2805 2805
2806 2806 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2807 2807 if checkout:
2808 2808 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2809 2809 repo._subtoppath = source
2810 2810 try:
2811 2811 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2812 2812 finally:
2813 2813 del repo._subtoppath
2814 2814
2815 2815 def push(ui, repo, dest=None, **opts):
2816 2816 """push changes to the specified destination
2817 2817
2818 2818 Push changesets from the local repository to the specified
2819 2819 destination.
2820 2820
2821 2821 This operation is symmetrical to pull: it is identical to a pull
2822 2822 in the destination repository from the current one.
2823 2823
2824 2824 By default, push will not allow creation of new heads at the
2825 2825 destination, since multiple heads would make it unclear which head
2826 2826 to use. In this situation, it is recommended to pull and merge
2827 2827 before pushing.
2828 2828
2829 2829 Use --new-branch if you want to allow push to create a new named
2830 2830 branch that is not present at the destination. This allows you to
2831 2831 only create a new branch without forcing other changes.
2832 2832
2833 2833 Use -f/--force to override the default behavior and push all
2834 2834 changesets on all branches.
2835 2835
2836 2836 If -r/--rev is used, the specified revision and all its ancestors
2837 2837 will be pushed to the remote repository.
2838 2838
2839 2839 Please see :hg:`help urls` for important details about ``ssh://``
2840 2840 URLs. If DESTINATION is omitted, a default path will be used.
2841 2841
2842 2842 Returns 0 if push was successful, 1 if nothing to push.
2843 2843 """
2844 2844 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2845 2845 dest, branches = hg.parseurl(dest, opts.get('branch'))
2846 2846 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2847 2847 other = hg.repository(hg.remoteui(repo, opts), dest)
2848 2848 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2849 2849 if revs:
2850 2850 revs = [repo.lookup(rev) for rev in revs]
2851 2851
2852 2852 repo._subtoppath = dest
2853 2853 try:
2854 2854 # push subrepos depth-first for coherent ordering
2855 2855 c = repo['']
2856 2856 subs = c.substate # only repos that are committed
2857 2857 for s in sorted(subs):
2858 2858 if not c.sub(s).push(opts.get('force')):
2859 2859 return False
2860 2860 finally:
2861 2861 del repo._subtoppath
2862 2862 r = repo.push(other, opts.get('force'), revs=revs,
2863 2863 newbranch=opts.get('new_branch'))
2864 2864 return r == 0
2865 2865
2866 2866 def recover(ui, repo):
2867 2867 """roll back an interrupted transaction
2868 2868
2869 2869 Recover from an interrupted commit or pull.
2870 2870
2871 2871 This command tries to fix the repository status after an
2872 2872 interrupted operation. It should only be necessary when Mercurial
2873 2873 suggests it.
2874 2874
2875 2875 Returns 0 if successful, 1 if nothing to recover or verify fails.
2876 2876 """
2877 2877 if repo.recover():
2878 2878 return hg.verify(repo)
2879 2879 return 1
2880 2880
2881 2881 def remove(ui, repo, *pats, **opts):
2882 2882 """remove the specified files on the next commit
2883 2883
2884 2884 Schedule the indicated files for removal from the repository.
2885 2885
2886 2886 This only removes files from the current branch, not from the
2887 2887 entire project history. -A/--after can be used to remove only
2888 2888 files that have already been deleted, -f/--force can be used to
2889 2889 force deletion, and -Af can be used to remove files from the next
2890 2890 revision without deleting them from the working directory.
2891 2891
2892 2892 The following table details the behavior of remove for different
2893 2893 file states (columns) and option combinations (rows). The file
2894 2894 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2895 2895 reported by :hg:`status`). The actions are Warn, Remove (from
2896 2896 branch) and Delete (from disk)::
2897 2897
2898 2898 A C M !
2899 2899 none W RD W R
2900 2900 -f R RD RD R
2901 2901 -A W W W R
2902 2902 -Af R R R R
2903 2903
2904 2904 This command schedules the files to be removed at the next commit.
2905 2905 To undo a remove before that, see :hg:`revert`.
2906 2906
2907 2907 Returns 0 on success, 1 if any warnings encountered.
2908 2908 """
2909 2909
2910 2910 ret = 0
2911 2911 after, force = opts.get('after'), opts.get('force')
2912 2912 if not pats and not after:
2913 2913 raise util.Abort(_('no files specified'))
2914 2914
2915 2915 m = cmdutil.match(repo, pats, opts)
2916 2916 s = repo.status(match=m, clean=True)
2917 2917 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2918 2918
2919 2919 for f in m.files():
2920 2920 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2921 2921 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2922 2922 ret = 1
2923 2923
2924 2924 if force:
2925 2925 remove, forget = modified + deleted + clean, added
2926 2926 elif after:
2927 2927 remove, forget = deleted, []
2928 2928 for f in modified + added + clean:
2929 2929 ui.warn(_('not removing %s: file still exists (use -f'
2930 2930 ' to force removal)\n') % m.rel(f))
2931 2931 ret = 1
2932 2932 else:
2933 2933 remove, forget = deleted + clean, []
2934 2934 for f in modified:
2935 2935 ui.warn(_('not removing %s: file is modified (use -f'
2936 2936 ' to force removal)\n') % m.rel(f))
2937 2937 ret = 1
2938 2938 for f in added:
2939 2939 ui.warn(_('not removing %s: file has been marked for add (use -f'
2940 2940 ' to force removal)\n') % m.rel(f))
2941 2941 ret = 1
2942 2942
2943 2943 for f in sorted(remove + forget):
2944 2944 if ui.verbose or not m.exact(f):
2945 2945 ui.status(_('removing %s\n') % m.rel(f))
2946 2946
2947 2947 repo[None].forget(forget)
2948 2948 repo[None].remove(remove, unlink=not after)
2949 2949 return ret
2950 2950
2951 2951 def rename(ui, repo, *pats, **opts):
2952 2952 """rename files; equivalent of copy + remove
2953 2953
2954 2954 Mark dest as copies of sources; mark sources for deletion. If dest
2955 2955 is a directory, copies are put in that directory. If dest is a
2956 2956 file, there can only be one source.
2957 2957
2958 2958 By default, this command copies the contents of files as they
2959 2959 exist in the working directory. If invoked with -A/--after, the
2960 2960 operation is recorded, but no copying is performed.
2961 2961
2962 2962 This command takes effect at the next commit. To undo a rename
2963 2963 before that, see :hg:`revert`.
2964 2964
2965 2965 Returns 0 on success, 1 if errors are encountered.
2966 2966 """
2967 2967 wlock = repo.wlock(False)
2968 2968 try:
2969 2969 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2970 2970 finally:
2971 2971 wlock.release()
2972 2972
2973 2973 def resolve(ui, repo, *pats, **opts):
2974 2974 """redo merges or set/view the merge status of files
2975 2975
2976 2976 Merges with unresolved conflicts are often the result of
2977 2977 non-interactive merging using the ``internal:merge`` configuration
2978 2978 setting, or a command-line merge tool like ``diff3``. The resolve
2979 2979 command is used to manage the files involved in a merge, after
2980 2980 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2981 2981 working directory must have two parents).
2982 2982
2983 2983 The resolve command can be used in the following ways:
2984 2984
2985 2985 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
2986 2986 files, discarding any previous merge attempts. Re-merging is not
2987 2987 performed for files already marked as resolved. Use ``--all/-a``
2988 2988 to selects all unresolved files. ``--tool`` can be used to specify
2989 2989 the merge tool used for the given files. It overrides the HGMERGE
2990 2990 environment variable and your configuration files.
2991 2991
2992 2992 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
2993 2993 (e.g. after having manually fixed-up the files). The default is
2994 2994 to mark all unresolved files.
2995 2995
2996 2996 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
2997 2997 default is to mark all resolved files.
2998 2998
2999 2999 - :hg:`resolve -l`: list files which had or still have conflicts.
3000 3000 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3001 3001
3002 3002 Note that Mercurial will not let you commit files with unresolved
3003 3003 merge conflicts. You must use :hg:`resolve -m ...` before you can
3004 3004 commit after a conflicting merge.
3005 3005
3006 3006 Returns 0 on success, 1 if any files fail a resolve attempt.
3007 3007 """
3008 3008
3009 3009 all, mark, unmark, show, nostatus = \
3010 3010 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3011 3011
3012 3012 if (show and (mark or unmark)) or (mark and unmark):
3013 3013 raise util.Abort(_("too many options specified"))
3014 3014 if pats and all:
3015 3015 raise util.Abort(_("can't specify --all and patterns"))
3016 3016 if not (all or pats or show or mark or unmark):
3017 3017 raise util.Abort(_('no files or directories specified; '
3018 3018 'use --all to remerge all files'))
3019 3019
3020 3020 ms = mergemod.mergestate(repo)
3021 3021 m = cmdutil.match(repo, pats, opts)
3022 3022 ret = 0
3023 3023
3024 3024 for f in ms:
3025 3025 if m(f):
3026 3026 if show:
3027 3027 if nostatus:
3028 3028 ui.write("%s\n" % f)
3029 3029 else:
3030 3030 ui.write("%s %s\n" % (ms[f].upper(), f),
3031 3031 label='resolve.' +
3032 3032 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3033 3033 elif mark:
3034 3034 ms.mark(f, "r")
3035 3035 elif unmark:
3036 3036 ms.mark(f, "u")
3037 3037 else:
3038 3038 wctx = repo[None]
3039 3039 mctx = wctx.parents()[-1]
3040 3040
3041 3041 # backup pre-resolve (merge uses .orig for its own purposes)
3042 3042 a = repo.wjoin(f)
3043 3043 util.copyfile(a, a + ".resolve")
3044 3044
3045 3045 try:
3046 3046 # resolve file
3047 3047 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3048 3048 if ms.resolve(f, wctx, mctx):
3049 3049 ret = 1
3050 3050 finally:
3051 3051 ui.setconfig('ui', 'forcemerge', '')
3052 3052
3053 3053 # replace filemerge's .orig file with our resolve file
3054 3054 util.rename(a + ".resolve", a + ".orig")
3055 3055
3056 3056 ms.commit()
3057 3057 return ret
3058 3058
3059 3059 def revert(ui, repo, *pats, **opts):
3060 3060 """restore individual files or directories to an earlier state
3061 3061
3062 3062 .. note::
3063 3063 This command is most likely not what you are looking for.
3064 3064 Revert will partially overwrite content in the working
3065 3065 directory without changing the working directory parents. Use
3066 3066 :hg:`update -r rev` to check out earlier revisions, or
3067 3067 :hg:`update --clean .` to undo a merge which has added another
3068 3068 parent.
3069 3069
3070 3070 With no revision specified, revert the named files or directories
3071 3071 to the contents they had in the parent of the working directory.
3072 3072 This restores the contents of the affected files to an unmodified
3073 3073 state and unschedules adds, removes, copies, and renames. If the
3074 3074 working directory has two parents, you must explicitly specify a
3075 3075 revision.
3076 3076
3077 3077 Using the -r/--rev option, revert the given files or directories
3078 3078 to their contents as of a specific revision. This can be helpful
3079 3079 to "roll back" some or all of an earlier change. See :hg:`help
3080 3080 dates` for a list of formats valid for -d/--date.
3081 3081
3082 3082 Revert modifies the working directory. It does not commit any
3083 3083 changes, or change the parent of the working directory. If you
3084 3084 revert to a revision other than the parent of the working
3085 3085 directory, the reverted files will thus appear modified
3086 3086 afterwards.
3087 3087
3088 3088 If a file has been deleted, it is restored. If the executable mode
3089 3089 of a file was changed, it is reset.
3090 3090
3091 3091 If names are given, all files matching the names are reverted.
3092 3092 If no arguments are given, no files are reverted.
3093 3093
3094 3094 Modified files are saved with a .orig suffix before reverting.
3095 3095 To disable these backups, use --no-backup.
3096 3096
3097 3097 Returns 0 on success.
3098 3098 """
3099 3099
3100 3100 if opts.get("date"):
3101 3101 if opts.get("rev"):
3102 3102 raise util.Abort(_("you can't specify a revision and a date"))
3103 3103 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3104 3104
3105 3105 parent, p2 = repo.dirstate.parents()
3106 3106 if not opts.get('rev') and p2 != nullid:
3107 3107 raise util.Abort(_('uncommitted merge - '
3108 3108 'use "hg update", see "hg help revert"'))
3109 3109
3110 3110 if not pats and not opts.get('all'):
3111 3111 raise util.Abort(_('no files or directories specified; '
3112 3112 'use --all to revert the whole repo'))
3113 3113
3114 3114 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3115 3115 node = ctx.node()
3116 3116 mf = ctx.manifest()
3117 3117 if node == parent:
3118 3118 pmf = mf
3119 3119 else:
3120 3120 pmf = None
3121 3121
3122 3122 # need all matching names in dirstate and manifest of target rev,
3123 3123 # so have to walk both. do not print errors if files exist in one
3124 3124 # but not other.
3125 3125
3126 3126 names = {}
3127 3127
3128 3128 wlock = repo.wlock()
3129 3129 try:
3130 3130 # walk dirstate.
3131 3131
3132 3132 m = cmdutil.match(repo, pats, opts)
3133 3133 m.bad = lambda x, y: False
3134 3134 for abs in repo.walk(m):
3135 3135 names[abs] = m.rel(abs), m.exact(abs)
3136 3136
3137 3137 # walk target manifest.
3138 3138
3139 3139 def badfn(path, msg):
3140 3140 if path in names:
3141 3141 return
3142 3142 path_ = path + '/'
3143 3143 for f in names:
3144 3144 if f.startswith(path_):
3145 3145 return
3146 3146 ui.warn("%s: %s\n" % (m.rel(path), msg))
3147 3147
3148 3148 m = cmdutil.match(repo, pats, opts)
3149 3149 m.bad = badfn
3150 3150 for abs in repo[node].walk(m):
3151 3151 if abs not in names:
3152 3152 names[abs] = m.rel(abs), m.exact(abs)
3153 3153
3154 3154 m = cmdutil.matchfiles(repo, names)
3155 3155 changes = repo.status(match=m)[:4]
3156 3156 modified, added, removed, deleted = map(set, changes)
3157 3157
3158 3158 # if f is a rename, also revert the source
3159 3159 cwd = repo.getcwd()
3160 3160 for f in added:
3161 3161 src = repo.dirstate.copied(f)
3162 3162 if src and src not in names and repo.dirstate[src] == 'r':
3163 3163 removed.add(src)
3164 3164 names[src] = (repo.pathto(src, cwd), True)
3165 3165
3166 3166 def removeforget(abs):
3167 3167 if repo.dirstate[abs] == 'a':
3168 3168 return _('forgetting %s\n')
3169 3169 return _('removing %s\n')
3170 3170
3171 3171 revert = ([], _('reverting %s\n'))
3172 3172 add = ([], _('adding %s\n'))
3173 3173 remove = ([], removeforget)
3174 3174 undelete = ([], _('undeleting %s\n'))
3175 3175
3176 3176 disptable = (
3177 3177 # dispatch table:
3178 3178 # file state
3179 3179 # action if in target manifest
3180 3180 # action if not in target manifest
3181 3181 # make backup if in target manifest
3182 3182 # make backup if not in target manifest
3183 3183 (modified, revert, remove, True, True),
3184 3184 (added, revert, remove, True, False),
3185 3185 (removed, undelete, None, False, False),
3186 3186 (deleted, revert, remove, False, False),
3187 3187 )
3188 3188
3189 3189 for abs, (rel, exact) in sorted(names.items()):
3190 3190 mfentry = mf.get(abs)
3191 3191 target = repo.wjoin(abs)
3192 3192 def handle(xlist, dobackup):
3193 3193 xlist[0].append(abs)
3194 3194 if (dobackup and not opts.get('no_backup') and
3195 3195 os.path.lexists(target)):
3196 3196 bakname = "%s.orig" % rel
3197 3197 ui.note(_('saving current version of %s as %s\n') %
3198 3198 (rel, bakname))
3199 3199 if not opts.get('dry_run'):
3200 3200 util.rename(target, bakname)
3201 3201 if ui.verbose or not exact:
3202 3202 msg = xlist[1]
3203 3203 if not isinstance(msg, basestring):
3204 3204 msg = msg(abs)
3205 3205 ui.status(msg % rel)
3206 3206 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3207 3207 if abs not in table:
3208 3208 continue
3209 3209 # file has changed in dirstate
3210 3210 if mfentry:
3211 3211 handle(hitlist, backuphit)
3212 3212 elif misslist is not None:
3213 3213 handle(misslist, backupmiss)
3214 3214 break
3215 3215 else:
3216 3216 if abs not in repo.dirstate:
3217 3217 if mfentry:
3218 3218 handle(add, True)
3219 3219 elif exact:
3220 3220 ui.warn(_('file not managed: %s\n') % rel)
3221 3221 continue
3222 3222 # file has not changed in dirstate
3223 3223 if node == parent:
3224 3224 if exact:
3225 3225 ui.warn(_('no changes needed to %s\n') % rel)
3226 3226 continue
3227 3227 if pmf is None:
3228 3228 # only need parent manifest in this unlikely case,
3229 3229 # so do not read by default
3230 3230 pmf = repo[parent].manifest()
3231 3231 if abs in pmf:
3232 3232 if mfentry:
3233 3233 # if version of file is same in parent and target
3234 3234 # manifests, do nothing
3235 3235 if (pmf[abs] != mfentry or
3236 3236 pmf.flags(abs) != mf.flags(abs)):
3237 3237 handle(revert, False)
3238 3238 else:
3239 3239 handle(remove, False)
3240 3240
3241 3241 if not opts.get('dry_run'):
3242 3242 def checkout(f):
3243 3243 fc = ctx[f]
3244 3244 repo.wwrite(f, fc.data(), fc.flags())
3245 3245
3246 3246 audit_path = util.path_auditor(repo.root)
3247 3247 for f in remove[0]:
3248 3248 if repo.dirstate[f] == 'a':
3249 3249 repo.dirstate.forget(f)
3250 3250 continue
3251 3251 audit_path(f)
3252 3252 try:
3253 3253 util.unlink(repo.wjoin(f))
3254 3254 except OSError:
3255 3255 pass
3256 3256 repo.dirstate.remove(f)
3257 3257
3258 3258 normal = None
3259 3259 if node == parent:
3260 3260 # We're reverting to our parent. If possible, we'd like status
3261 3261 # to report the file as clean. We have to use normallookup for
3262 3262 # merges to avoid losing information about merged/dirty files.
3263 3263 if p2 != nullid:
3264 3264 normal = repo.dirstate.normallookup
3265 3265 else:
3266 3266 normal = repo.dirstate.normal
3267 3267 for f in revert[0]:
3268 3268 checkout(f)
3269 3269 if normal:
3270 3270 normal(f)
3271 3271
3272 3272 for f in add[0]:
3273 3273 checkout(f)
3274 3274 repo.dirstate.add(f)
3275 3275
3276 3276 normal = repo.dirstate.normallookup
3277 3277 if node == parent and p2 == nullid:
3278 3278 normal = repo.dirstate.normal
3279 3279 for f in undelete[0]:
3280 3280 checkout(f)
3281 3281 normal(f)
3282 3282
3283 3283 finally:
3284 3284 wlock.release()
3285 3285
3286 3286 def rollback(ui, repo, **opts):
3287 3287 """roll back the last transaction (dangerous)
3288 3288
3289 3289 This command should be used with care. There is only one level of
3290 3290 rollback, and there is no way to undo a rollback. It will also
3291 3291 restore the dirstate at the time of the last transaction, losing
3292 3292 any dirstate changes since that time. This command does not alter
3293 3293 the working directory.
3294 3294
3295 3295 Transactions are used to encapsulate the effects of all commands
3296 3296 that create new changesets or propagate existing changesets into a
3297 3297 repository. For example, the following commands are transactional,
3298 3298 and their effects can be rolled back:
3299 3299
3300 3300 - commit
3301 3301 - import
3302 3302 - pull
3303 3303 - push (with this repository as the destination)
3304 3304 - unbundle
3305 3305
3306 3306 This command is not intended for use on public repositories. Once
3307 3307 changes are visible for pull by other users, rolling a transaction
3308 3308 back locally is ineffective (someone else may already have pulled
3309 3309 the changes). Furthermore, a race is possible with readers of the
3310 3310 repository; for example an in-progress pull from the repository
3311 3311 may fail if a rollback is performed.
3312 3312
3313 3313 Returns 0 on success, 1 if no rollback data is available.
3314 3314 """
3315 3315 return repo.rollback(opts.get('dry_run'))
3316 3316
3317 3317 def root(ui, repo):
3318 3318 """print the root (top) of the current working directory
3319 3319
3320 3320 Print the root directory of the current repository.
3321 3321
3322 3322 Returns 0 on success.
3323 3323 """
3324 3324 ui.write(repo.root + "\n")
3325 3325
3326 3326 def serve(ui, repo, **opts):
3327 3327 """start stand-alone webserver
3328 3328
3329 3329 Start a local HTTP repository browser and pull server. You can use
3330 3330 this for ad-hoc sharing and browsing of repositories. It is
3331 3331 recommended to use a real web server to serve a repository for
3332 3332 longer periods of time.
3333 3333
3334 3334 Please note that the server does not implement access control.
3335 3335 This means that, by default, anybody can read from the server and
3336 3336 nobody can write to it by default. Set the ``web.allow_push``
3337 3337 option to ``*`` to allow everybody to push to the server. You
3338 3338 should use a real web server if you need to authenticate users.
3339 3339
3340 3340 By default, the server logs accesses to stdout and errors to
3341 3341 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3342 3342 files.
3343 3343
3344 3344 To have the server choose a free port number to listen on, specify
3345 3345 a port number of 0; in this case, the server will print the port
3346 3346 number it uses.
3347 3347
3348 3348 Returns 0 on success.
3349 3349 """
3350 3350
3351 3351 if opts["stdio"]:
3352 3352 if repo is None:
3353 3353 raise error.RepoError(_("There is no Mercurial repository here"
3354 3354 " (.hg not found)"))
3355 3355 s = sshserver.sshserver(ui, repo)
3356 3356 s.serve_forever()
3357 3357
3358 3358 # this way we can check if something was given in the command-line
3359 3359 if opts.get('port'):
3360 3360 opts['port'] = util.getport(opts.get('port'))
3361 3361
3362 3362 baseui = repo and repo.baseui or ui
3363 3363 optlist = ("name templates style address port prefix ipv6"
3364 3364 " accesslog errorlog certificate encoding")
3365 3365 for o in optlist.split():
3366 3366 val = opts.get(o, '')
3367 3367 if val in (None, ''): # should check against default options instead
3368 3368 continue
3369 3369 baseui.setconfig("web", o, val)
3370 3370 if repo and repo.ui != baseui:
3371 3371 repo.ui.setconfig("web", o, val)
3372 3372
3373 3373 o = opts.get('web_conf') or opts.get('webdir_conf')
3374 3374 if not o:
3375 3375 if not repo:
3376 3376 raise error.RepoError(_("There is no Mercurial repository"
3377 3377 " here (.hg not found)"))
3378 3378 o = repo.root
3379 3379
3380 3380 app = hgweb.hgweb(o, baseui=ui)
3381 3381
3382 3382 class service(object):
3383 3383 def init(self):
3384 3384 util.set_signal_handler()
3385 3385 self.httpd = hgweb.server.create_server(ui, app)
3386 3386
3387 3387 if opts['port'] and not ui.verbose:
3388 3388 return
3389 3389
3390 3390 if self.httpd.prefix:
3391 3391 prefix = self.httpd.prefix.strip('/') + '/'
3392 3392 else:
3393 3393 prefix = ''
3394 3394
3395 3395 port = ':%d' % self.httpd.port
3396 3396 if port == ':80':
3397 3397 port = ''
3398 3398
3399 3399 bindaddr = self.httpd.addr
3400 3400 if bindaddr == '0.0.0.0':
3401 3401 bindaddr = '*'
3402 3402 elif ':' in bindaddr: # IPv6
3403 3403 bindaddr = '[%s]' % bindaddr
3404 3404
3405 3405 fqaddr = self.httpd.fqaddr
3406 3406 if ':' in fqaddr:
3407 3407 fqaddr = '[%s]' % fqaddr
3408 3408 if opts['port']:
3409 3409 write = ui.status
3410 3410 else:
3411 3411 write = ui.write
3412 3412 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3413 3413 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3414 3414
3415 3415 def run(self):
3416 3416 self.httpd.serve_forever()
3417 3417
3418 3418 service = service()
3419 3419
3420 3420 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3421 3421
3422 3422 def status(ui, repo, *pats, **opts):
3423 3423 """show changed files in the working directory
3424 3424
3425 3425 Show status of files in the repository. If names are given, only
3426 3426 files that match are shown. Files that are clean or ignored or
3427 3427 the source of a copy/move operation, are not listed unless
3428 3428 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3429 3429 Unless options described with "show only ..." are given, the
3430 3430 options -mardu are used.
3431 3431
3432 3432 Option -q/--quiet hides untracked (unknown and ignored) files
3433 3433 unless explicitly requested with -u/--unknown or -i/--ignored.
3434 3434
3435 3435 .. note::
3436 3436 status may appear to disagree with diff if permissions have
3437 3437 changed or a merge has occurred. The standard diff format does
3438 3438 not report permission changes and diff only reports changes
3439 3439 relative to one merge parent.
3440 3440
3441 3441 If one revision is given, it is used as the base revision.
3442 3442 If two revisions are given, the differences between them are
3443 3443 shown. The --change option can also be used as a shortcut to list
3444 3444 the changed files of a revision from its first parent.
3445 3445
3446 3446 The codes used to show the status of files are::
3447 3447
3448 3448 M = modified
3449 3449 A = added
3450 3450 R = removed
3451 3451 C = clean
3452 3452 ! = missing (deleted by non-hg command, but still tracked)
3453 3453 ? = not tracked
3454 3454 I = ignored
3455 3455 = origin of the previous file listed as A (added)
3456 3456
3457 3457 Returns 0 on success.
3458 3458 """
3459 3459
3460 3460 revs = opts.get('rev')
3461 3461 change = opts.get('change')
3462 3462
3463 3463 if revs and change:
3464 3464 msg = _('cannot specify --rev and --change at the same time')
3465 3465 raise util.Abort(msg)
3466 3466 elif change:
3467 3467 node2 = repo.lookup(change)
3468 3468 node1 = repo[node2].parents()[0].node()
3469 3469 else:
3470 3470 node1, node2 = cmdutil.revpair(repo, revs)
3471 3471
3472 3472 cwd = (pats and repo.getcwd()) or ''
3473 3473 end = opts.get('print0') and '\0' or '\n'
3474 3474 copy = {}
3475 3475 states = 'modified added removed deleted unknown ignored clean'.split()
3476 3476 show = [k for k in states if opts.get(k)]
3477 3477 if opts.get('all'):
3478 3478 show += ui.quiet and (states[:4] + ['clean']) or states
3479 3479 if not show:
3480 3480 show = ui.quiet and states[:4] or states[:5]
3481 3481
3482 3482 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3483 3483 'ignored' in show, 'clean' in show, 'unknown' in show,
3484 3484 opts.get('subrepos'))
3485 3485 changestates = zip(states, 'MAR!?IC', stat)
3486 3486
3487 3487 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3488 3488 ctxn = repo[nullid]
3489 3489 ctx1 = repo[node1]
3490 3490 ctx2 = repo[node2]
3491 3491 added = stat[1]
3492 3492 if node2 is None:
3493 3493 added = stat[0] + stat[1] # merged?
3494 3494
3495 3495 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3496 3496 if k in added:
3497 3497 copy[k] = v
3498 3498 elif v in added:
3499 3499 copy[v] = k
3500 3500
3501 3501 for state, char, files in changestates:
3502 3502 if state in show:
3503 3503 format = "%s %%s%s" % (char, end)
3504 3504 if opts.get('no_status'):
3505 3505 format = "%%s%s" % end
3506 3506
3507 3507 for f in files:
3508 3508 ui.write(format % repo.pathto(f, cwd),
3509 3509 label='status.' + state)
3510 3510 if f in copy:
3511 3511 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3512 3512 label='status.copied')
3513 3513
3514 3514 def summary(ui, repo, **opts):
3515 3515 """summarize working directory state
3516 3516
3517 3517 This generates a brief summary of the working directory state,
3518 3518 including parents, branch, commit status, and available updates.
3519 3519
3520 3520 With the --remote option, this will check the default paths for
3521 3521 incoming and outgoing changes. This can be time-consuming.
3522 3522
3523 3523 Returns 0 on success.
3524 3524 """
3525 3525
3526 3526 ctx = repo[None]
3527 3527 parents = ctx.parents()
3528 3528 pnode = parents[0].node()
3529 3529
3530 3530 for p in parents:
3531 3531 # label with log.changeset (instead of log.parent) since this
3532 3532 # shows a working directory parent *changeset*:
3533 3533 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3534 3534 label='log.changeset')
3535 3535 ui.write(' '.join(p.tags()), label='log.tag')
3536 3536 if p.rev() == -1:
3537 3537 if not len(repo):
3538 3538 ui.write(_(' (empty repository)'))
3539 3539 else:
3540 3540 ui.write(_(' (no revision checked out)'))
3541 3541 ui.write('\n')
3542 3542 if p.description():
3543 3543 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3544 3544 label='log.summary')
3545 3545
3546 3546 branch = ctx.branch()
3547 3547 bheads = repo.branchheads(branch)
3548 3548 m = _('branch: %s\n') % branch
3549 3549 if branch != 'default':
3550 3550 ui.write(m, label='log.branch')
3551 3551 else:
3552 3552 ui.status(m, label='log.branch')
3553 3553
3554 3554 st = list(repo.status(unknown=True))[:6]
3555 3555
3556 3556 c = repo.dirstate.copies()
3557 3557 copied, renamed = [], []
3558 3558 for d, s in c.iteritems():
3559 3559 if s in st[2]:
3560 3560 st[2].remove(s)
3561 3561 renamed.append(d)
3562 3562 else:
3563 3563 copied.append(d)
3564 3564 if d in st[1]:
3565 3565 st[1].remove(d)
3566 3566 st.insert(3, renamed)
3567 3567 st.insert(4, copied)
3568 3568
3569 3569 ms = mergemod.mergestate(repo)
3570 3570 st.append([f for f in ms if ms[f] == 'u'])
3571 3571
3572 3572 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3573 3573 st.append(subs)
3574 3574
3575 3575 labels = [ui.label(_('%d modified'), 'status.modified'),
3576 3576 ui.label(_('%d added'), 'status.added'),
3577 3577 ui.label(_('%d removed'), 'status.removed'),
3578 3578 ui.label(_('%d renamed'), 'status.copied'),
3579 3579 ui.label(_('%d copied'), 'status.copied'),
3580 3580 ui.label(_('%d deleted'), 'status.deleted'),
3581 3581 ui.label(_('%d unknown'), 'status.unknown'),
3582 3582 ui.label(_('%d ignored'), 'status.ignored'),
3583 3583 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3584 3584 ui.label(_('%d subrepos'), 'status.modified')]
3585 3585 t = []
3586 3586 for s, l in zip(st, labels):
3587 3587 if s:
3588 3588 t.append(l % len(s))
3589 3589
3590 3590 t = ', '.join(t)
3591 3591 cleanworkdir = False
3592 3592
3593 3593 if len(parents) > 1:
3594 3594 t += _(' (merge)')
3595 3595 elif branch != parents[0].branch():
3596 3596 t += _(' (new branch)')
3597 3597 elif (parents[0].extra().get('close') and
3598 3598 pnode in repo.branchheads(branch, closed=True)):
3599 3599 t += _(' (head closed)')
3600 3600 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3601 3601 t += _(' (clean)')
3602 3602 cleanworkdir = True
3603 3603 elif pnode not in bheads:
3604 3604 t += _(' (new branch head)')
3605 3605
3606 3606 if cleanworkdir:
3607 3607 ui.status(_('commit: %s\n') % t.strip())
3608 3608 else:
3609 3609 ui.write(_('commit: %s\n') % t.strip())
3610 3610
3611 3611 # all ancestors of branch heads - all ancestors of parent = new csets
3612 3612 new = [0] * len(repo)
3613 3613 cl = repo.changelog
3614 3614 for a in [cl.rev(n) for n in bheads]:
3615 3615 new[a] = 1
3616 3616 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3617 3617 new[a] = 1
3618 3618 for a in [p.rev() for p in parents]:
3619 3619 if a >= 0:
3620 3620 new[a] = 0
3621 3621 for a in cl.ancestors(*[p.rev() for p in parents]):
3622 3622 new[a] = 0
3623 3623 new = sum(new)
3624 3624
3625 3625 if new == 0:
3626 3626 ui.status(_('update: (current)\n'))
3627 3627 elif pnode not in bheads:
3628 3628 ui.write(_('update: %d new changesets (update)\n') % new)
3629 3629 else:
3630 3630 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3631 3631 (new, len(bheads)))
3632 3632
3633 3633 if opts.get('remote'):
3634 3634 t = []
3635 3635 source, branches = hg.parseurl(ui.expandpath('default'))
3636 3636 other = hg.repository(hg.remoteui(repo, {}), source)
3637 3637 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3638 3638 ui.debug('comparing with %s\n' % url.hidepassword(source))
3639 3639 repo.ui.pushbuffer()
3640 3640 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3641 3641 repo.ui.popbuffer()
3642 3642 if incoming:
3643 3643 t.append(_('1 or more incoming'))
3644 3644
3645 3645 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3646 3646 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3647 3647 other = hg.repository(hg.remoteui(repo, {}), dest)
3648 3648 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3649 3649 repo.ui.pushbuffer()
3650 3650 o = discovery.findoutgoing(repo, other)
3651 3651 repo.ui.popbuffer()
3652 3652 o = repo.changelog.nodesbetween(o, None)[0]
3653 3653 if o:
3654 3654 t.append(_('%d outgoing') % len(o))
3655 3655
3656 3656 if t:
3657 3657 ui.write(_('remote: %s\n') % (', '.join(t)))
3658 3658 else:
3659 3659 ui.status(_('remote: (synced)\n'))
3660 3660
3661 3661 def tag(ui, repo, name1, *names, **opts):
3662 3662 """add one or more tags for the current or given revision
3663 3663
3664 3664 Name a particular revision using <name>.
3665 3665
3666 3666 Tags are used to name particular revisions of the repository and are
3667 3667 very useful to compare different revisions, to go back to significant
3668 3668 earlier versions or to mark branch points as releases, etc. Changing
3669 3669 an existing tag is normally disallowed; use -f/--force to override.
3670 3670
3671 3671 If no revision is given, the parent of the working directory is
3672 3672 used, or tip if no revision is checked out.
3673 3673
3674 3674 To facilitate version control, distribution, and merging of tags,
3675 3675 they are stored as a file named ".hgtags" which is managed similarly
3676 3676 to other project files and can be hand-edited if necessary. This
3677 3677 also means that tagging creates a new commit. The file
3678 3678 ".hg/localtags" is used for local tags (not shared among
3679 3679 repositories).
3680 3680
3681 3681 Tag commits are usually made at the head of a branch. If the parent
3682 3682 of the working directory is not a branch head, :hg:`tag` aborts; use
3683 3683 -f/--force to force the tag commit to be based on a non-head
3684 3684 changeset.
3685 3685
3686 3686 See :hg:`help dates` for a list of formats valid for -d/--date.
3687 3687
3688 3688 Since tag names have priority over branch names during revision
3689 3689 lookup, using an existing branch name as a tag name is discouraged.
3690 3690
3691 3691 Returns 0 on success.
3692 3692 """
3693 3693
3694 3694 rev_ = "."
3695 3695 names = [t.strip() for t in (name1,) + names]
3696 3696 if len(names) != len(set(names)):
3697 3697 raise util.Abort(_('tag names must be unique'))
3698 3698 for n in names:
3699 3699 if n in ['tip', '.', 'null']:
3700 3700 raise util.Abort(_('the name \'%s\' is reserved') % n)
3701 3701 if not n:
3702 3702 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3703 3703 if opts.get('rev') and opts.get('remove'):
3704 3704 raise util.Abort(_("--rev and --remove are incompatible"))
3705 3705 if opts.get('rev'):
3706 3706 rev_ = opts['rev']
3707 3707 message = opts.get('message')
3708 3708 if opts.get('remove'):
3709 3709 expectedtype = opts.get('local') and 'local' or 'global'
3710 3710 for n in names:
3711 3711 if not repo.tagtype(n):
3712 3712 raise util.Abort(_('tag \'%s\' does not exist') % n)
3713 3713 if repo.tagtype(n) != expectedtype:
3714 3714 if expectedtype == 'global':
3715 3715 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3716 3716 else:
3717 3717 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3718 3718 rev_ = nullid
3719 3719 if not message:
3720 3720 # we don't translate commit messages
3721 3721 message = 'Removed tag %s' % ', '.join(names)
3722 3722 elif not opts.get('force'):
3723 3723 for n in names:
3724 3724 if n in repo.tags():
3725 3725 raise util.Abort(_('tag \'%s\' already exists '
3726 3726 '(use -f to force)') % n)
3727 3727 if not opts.get('local'):
3728 3728 p1, p2 = repo.dirstate.parents()
3729 3729 if p2 != nullid:
3730 3730 raise util.Abort(_('uncommitted merge'))
3731 3731 bheads = repo.branchheads()
3732 3732 if not opts.get('force') and bheads and p1 not in bheads:
3733 3733 raise util.Abort(_('not at a branch head (use -f to force)'))
3734 3734 r = cmdutil.revsingle(repo, rev_).node()
3735 3735
3736 3736 if not message:
3737 3737 # we don't translate commit messages
3738 3738 message = ('Added tag %s for changeset %s' %
3739 3739 (', '.join(names), short(r)))
3740 3740
3741 3741 date = opts.get('date')
3742 3742 if date:
3743 3743 date = util.parsedate(date)
3744 3744
3745 3745 if opts.get('edit'):
3746 3746 message = ui.edit(message, ui.username())
3747 3747
3748 3748 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3749 3749
3750 3750 def tags(ui, repo):
3751 3751 """list repository tags
3752 3752
3753 3753 This lists both regular and local tags. When the -v/--verbose
3754 3754 switch is used, a third column "local" is printed for local tags.
3755 3755
3756 3756 Returns 0 on success.
3757 3757 """
3758 3758
3759 3759 hexfunc = ui.debugflag and hex or short
3760 3760 tagtype = ""
3761 3761
3762 3762 for t, n in reversed(repo.tagslist()):
3763 3763 if ui.quiet:
3764 3764 ui.write("%s\n" % t)
3765 3765 continue
3766 3766
3767 3767 try:
3768 3768 hn = hexfunc(n)
3769 3769 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3770 3770 except error.LookupError:
3771 3771 r = " ?:%s" % hn
3772 3772 else:
3773 3773 spaces = " " * (30 - encoding.colwidth(t))
3774 3774 if ui.verbose:
3775 3775 if repo.tagtype(t) == 'local':
3776 3776 tagtype = " local"
3777 3777 else:
3778 3778 tagtype = ""
3779 3779 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3780 3780
3781 3781 def tip(ui, repo, **opts):
3782 3782 """show the tip revision
3783 3783
3784 3784 The tip revision (usually just called the tip) is the changeset
3785 3785 most recently added to the repository (and therefore the most
3786 3786 recently changed head).
3787 3787
3788 3788 If you have just made a commit, that commit will be the tip. If
3789 3789 you have just pulled changes from another repository, the tip of
3790 3790 that repository becomes the current tip. The "tip" tag is special
3791 3791 and cannot be renamed or assigned to a different changeset.
3792 3792
3793 3793 Returns 0 on success.
3794 3794 """
3795 3795 displayer = cmdutil.show_changeset(ui, repo, opts)
3796 3796 displayer.show(repo[len(repo) - 1])
3797 3797 displayer.close()
3798 3798
3799 3799 def unbundle(ui, repo, fname1, *fnames, **opts):
3800 3800 """apply one or more changegroup files
3801 3801
3802 3802 Apply one or more compressed changegroup files generated by the
3803 3803 bundle command.
3804 3804
3805 3805 Returns 0 on success, 1 if an update has unresolved files.
3806 3806 """
3807 3807 fnames = (fname1,) + fnames
3808 3808
3809 3809 lock = repo.lock()
3810 3810 try:
3811 3811 for fname in fnames:
3812 3812 f = url.open(ui, fname)
3813 3813 gen = changegroup.readbundle(f, fname)
3814 3814 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3815 3815 lock=lock)
3816 3816 finally:
3817 3817 lock.release()
3818 3818
3819 3819 return postincoming(ui, repo, modheads, opts.get('update'), None)
3820 3820
3821 3821 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3822 3822 """update working directory (or switch revisions)
3823 3823
3824 3824 Update the repository's working directory to the specified
3825 3825 changeset. If no changeset is specified, update to the tip of the
3826 3826 current named branch.
3827 3827
3828 3828 If the changeset is not a descendant of the working directory's
3829 3829 parent, the update is aborted. With the -c/--check option, the
3830 3830 working directory is checked for uncommitted changes; if none are
3831 3831 found, the working directory is updated to the specified
3832 3832 changeset.
3833 3833
3834 3834 The following rules apply when the working directory contains
3835 3835 uncommitted changes:
3836 3836
3837 3837 1. If neither -c/--check nor -C/--clean is specified, and if
3838 3838 the requested changeset is an ancestor or descendant of
3839 3839 the working directory's parent, the uncommitted changes
3840 3840 are merged into the requested changeset and the merged
3841 3841 result is left uncommitted. If the requested changeset is
3842 3842 not an ancestor or descendant (that is, it is on another
3843 3843 branch), the update is aborted and the uncommitted changes
3844 3844 are preserved.
3845 3845
3846 3846 2. With the -c/--check option, the update is aborted and the
3847 3847 uncommitted changes are preserved.
3848 3848
3849 3849 3. With the -C/--clean option, uncommitted changes are discarded and
3850 3850 the working directory is updated to the requested changeset.
3851 3851
3852 3852 Use null as the changeset to remove the working directory (like
3853 3853 :hg:`clone -U`).
3854 3854
3855 3855 If you want to update just one file to an older changeset, use
3856 3856 :hg:`revert`.
3857 3857
3858 3858 See :hg:`help dates` for a list of formats valid for -d/--date.
3859 3859
3860 3860 Returns 0 on success, 1 if there are unresolved files.
3861 3861 """
3862 3862 if rev and node:
3863 3863 raise util.Abort(_("please specify just one revision"))
3864 3864
3865 3865 if not rev:
3866 3866 rev = node
3867 3867
3868 3868 rev = cmdutil.revsingle(repo, rev, rev).rev()
3869 3869
3870 3870 if check and clean:
3871 3871 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3872 3872
3873 3873 if check:
3874 3874 # we could use dirty() but we can ignore merge and branch trivia
3875 3875 c = repo[None]
3876 3876 if c.modified() or c.added() or c.removed():
3877 3877 raise util.Abort(_("uncommitted local changes"))
3878 3878
3879 3879 if date:
3880 3880 if rev:
3881 3881 raise util.Abort(_("you can't specify a revision and a date"))
3882 3882 rev = cmdutil.finddate(ui, repo, date)
3883 3883
3884 3884 if clean or check:
3885 3885 return hg.clean(repo, rev)
3886 3886 else:
3887 3887 return hg.update(repo, rev)
3888 3888
3889 3889 def verify(ui, repo):
3890 3890 """verify the integrity of the repository
3891 3891
3892 3892 Verify the integrity of the current repository.
3893 3893
3894 3894 This will perform an extensive check of the repository's
3895 3895 integrity, validating the hashes and checksums of each entry in
3896 3896 the changelog, manifest, and tracked files, as well as the
3897 3897 integrity of their crosslinks and indices.
3898 3898
3899 3899 Returns 0 on success, 1 if errors are encountered.
3900 3900 """
3901 3901 return hg.verify(repo)
3902 3902
3903 3903 def version_(ui):
3904 3904 """output version and copyright information"""
3905 3905 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3906 3906 % util.version())
3907 3907 ui.status(_(
3908 3908 "(see http://mercurial.selenic.com for more information)\n"
3909 3909 "\nCopyright (C) 2005-2010 Matt Mackall and others\n"
3910 3910 "This is free software; see the source for copying conditions. "
3911 3911 "There is NO\nwarranty; "
3912 3912 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3913 3913 ))
3914 3914
3915 3915 # Command options and aliases are listed here, alphabetically
3916 3916
3917 3917 globalopts = [
3918 3918 ('R', 'repository', '',
3919 3919 _('repository root directory or name of overlay bundle file'),
3920 3920 _('REPO')),
3921 3921 ('', 'cwd', '',
3922 3922 _('change working directory'), _('DIR')),
3923 3923 ('y', 'noninteractive', None,
3924 3924 _('do not prompt, assume \'yes\' for any required answers')),
3925 3925 ('q', 'quiet', None, _('suppress output')),
3926 3926 ('v', 'verbose', None, _('enable additional output')),
3927 3927 ('', 'config', [],
3928 3928 _('set/override config option (use \'section.name=value\')'),
3929 3929 _('CONFIG')),
3930 3930 ('', 'debug', None, _('enable debugging output')),
3931 3931 ('', 'debugger', None, _('start debugger')),
3932 3932 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3933 3933 _('ENCODE')),
3934 3934 ('', 'encodingmode', encoding.encodingmode,
3935 3935 _('set the charset encoding mode'), _('MODE')),
3936 3936 ('', 'traceback', None, _('always print a traceback on exception')),
3937 3937 ('', 'time', None, _('time how long the command takes')),
3938 3938 ('', 'profile', None, _('print command execution profile')),
3939 3939 ('', 'version', None, _('output version information and exit')),
3940 3940 ('h', 'help', None, _('display help and exit')),
3941 3941 ]
3942 3942
3943 3943 dryrunopts = [('n', 'dry-run', None,
3944 3944 _('do not perform actions, just print output'))]
3945 3945
3946 3946 remoteopts = [
3947 3947 ('e', 'ssh', '',
3948 3948 _('specify ssh command to use'), _('CMD')),
3949 3949 ('', 'remotecmd', '',
3950 3950 _('specify hg command to run on the remote side'), _('CMD')),
3951 3951 ]
3952 3952
3953 3953 walkopts = [
3954 3954 ('I', 'include', [],
3955 3955 _('include names matching the given patterns'), _('PATTERN')),
3956 3956 ('X', 'exclude', [],
3957 3957 _('exclude names matching the given patterns'), _('PATTERN')),
3958 3958 ]
3959 3959
3960 3960 commitopts = [
3961 3961 ('m', 'message', '',
3962 3962 _('use text as commit message'), _('TEXT')),
3963 3963 ('l', 'logfile', '',
3964 3964 _('read commit message from file'), _('FILE')),
3965 3965 ]
3966 3966
3967 3967 commitopts2 = [
3968 3968 ('d', 'date', '',
3969 3969 _('record datecode as commit date'), _('DATE')),
3970 3970 ('u', 'user', '',
3971 3971 _('record the specified user as committer'), _('USER')),
3972 3972 ]
3973 3973
3974 3974 templateopts = [
3975 3975 ('', 'style', '',
3976 3976 _('display using template map file'), _('STYLE')),
3977 3977 ('', 'template', '',
3978 3978 _('display with template'), _('TEMPLATE')),
3979 3979 ]
3980 3980
3981 3981 logopts = [
3982 3982 ('p', 'patch', None, _('show patch')),
3983 3983 ('g', 'git', None, _('use git extended diff format')),
3984 3984 ('l', 'limit', '',
3985 3985 _('limit number of changes displayed'), _('NUM')),
3986 3986 ('M', 'no-merges', None, _('do not show merges')),
3987 3987 ('', 'stat', None, _('output diffstat-style summary of changes')),
3988 3988 ] + templateopts
3989 3989
3990 3990 diffopts = [
3991 3991 ('a', 'text', None, _('treat all files as text')),
3992 3992 ('g', 'git', None, _('use git extended diff format')),
3993 3993 ('', 'nodates', None, _('omit dates from diff headers'))
3994 3994 ]
3995 3995
3996 3996 diffopts2 = [
3997 3997 ('p', 'show-function', None, _('show which function each change is in')),
3998 3998 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3999 3999 ('w', 'ignore-all-space', None,
4000 4000 _('ignore white space when comparing lines')),
4001 4001 ('b', 'ignore-space-change', None,
4002 4002 _('ignore changes in the amount of white space')),
4003 4003 ('B', 'ignore-blank-lines', None,
4004 4004 _('ignore changes whose lines are all blank')),
4005 4005 ('U', 'unified', '',
4006 4006 _('number of lines of context to show'), _('NUM')),
4007 4007 ('', 'stat', None, _('output diffstat-style summary of changes')),
4008 4008 ]
4009 4009
4010 4010 similarityopts = [
4011 4011 ('s', 'similarity', '',
4012 4012 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4013 4013 ]
4014 4014
4015 4015 subrepoopts = [
4016 4016 ('S', 'subrepos', None,
4017 4017 _('recurse into subrepositories'))
4018 4018 ]
4019 4019
4020 4020 table = {
4021 4021 "^add": (add, walkopts + subrepoopts + dryrunopts,
4022 4022 _('[OPTION]... [FILE]...')),
4023 4023 "addremove":
4024 4024 (addremove, similarityopts + walkopts + dryrunopts,
4025 4025 _('[OPTION]... [FILE]...')),
4026 4026 "^annotate|blame":
4027 4027 (annotate,
4028 4028 [('r', 'rev', '',
4029 4029 _('annotate the specified revision'), _('REV')),
4030 4030 ('', 'follow', None,
4031 4031 _('follow copies/renames and list the filename (DEPRECATED)')),
4032 4032 ('', 'no-follow', None, _("don't follow copies and renames")),
4033 4033 ('a', 'text', None, _('treat all files as text')),
4034 4034 ('u', 'user', None, _('list the author (long with -v)')),
4035 4035 ('f', 'file', None, _('list the filename')),
4036 4036 ('d', 'date', None, _('list the date (short with -q)')),
4037 4037 ('n', 'number', None, _('list the revision number (default)')),
4038 4038 ('c', 'changeset', None, _('list the changeset')),
4039 4039 ('l', 'line-number', None,
4040 4040 _('show line number at the first appearance'))
4041 4041 ] + walkopts,
4042 4042 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4043 4043 "archive":
4044 4044 (archive,
4045 4045 [('', 'no-decode', None, _('do not pass files through decoders')),
4046 4046 ('p', 'prefix', '',
4047 4047 _('directory prefix for files in archive'), _('PREFIX')),
4048 4048 ('r', 'rev', '',
4049 4049 _('revision to distribute'), _('REV')),
4050 4050 ('t', 'type', '',
4051 4051 _('type of distribution to create'), _('TYPE')),
4052 4052 ] + subrepoopts + walkopts,
4053 4053 _('[OPTION]... DEST')),
4054 4054 "backout":
4055 4055 (backout,
4056 4056 [('', 'merge', None,
4057 4057 _('merge with old dirstate parent after backout')),
4058 4058 ('', 'parent', '',
4059 4059 _('parent to choose when backing out merge'), _('REV')),
4060 4060 ('t', 'tool', '',
4061 4061 _('specify merge tool')),
4062 4062 ('r', 'rev', '',
4063 4063 _('revision to backout'), _('REV')),
4064 4064 ] + walkopts + commitopts + commitopts2,
4065 4065 _('[OPTION]... [-r] REV')),
4066 4066 "bisect":
4067 4067 (bisect,
4068 4068 [('r', 'reset', False, _('reset bisect state')),
4069 4069 ('g', 'good', False, _('mark changeset good')),
4070 4070 ('b', 'bad', False, _('mark changeset bad')),
4071 4071 ('s', 'skip', False, _('skip testing changeset')),
4072 4072 ('c', 'command', '',
4073 4073 _('use command to check changeset state'), _('CMD')),
4074 4074 ('U', 'noupdate', False, _('do not update to target'))],
4075 4075 _("[-gbsr] [-U] [-c CMD] [REV]")),
4076 4076 "branch":
4077 4077 (branch,
4078 4078 [('f', 'force', None,
4079 4079 _('set branch name even if it shadows an existing branch')),
4080 4080 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4081 4081 _('[-fC] [NAME]')),
4082 4082 "branches":
4083 4083 (branches,
4084 4084 [('a', 'active', False,
4085 4085 _('show only branches that have unmerged heads')),
4086 4086 ('c', 'closed', False,
4087 4087 _('show normal and closed branches'))],
4088 4088 _('[-ac]')),
4089 4089 "bundle":
4090 4090 (bundle,
4091 4091 [('f', 'force', None,
4092 4092 _('run even when the destination is unrelated')),
4093 4093 ('r', 'rev', [],
4094 4094 _('a changeset intended to be added to the destination'),
4095 4095 _('REV')),
4096 4096 ('b', 'branch', [],
4097 4097 _('a specific branch you would like to bundle'),
4098 4098 _('BRANCH')),
4099 4099 ('', 'base', [],
4100 4100 _('a base changeset assumed to be available at the destination'),
4101 4101 _('REV')),
4102 4102 ('a', 'all', None, _('bundle all changesets in the repository')),
4103 4103 ('t', 'type', 'bzip2',
4104 4104 _('bundle compression type to use'), _('TYPE')),
4105 4105 ] + remoteopts,
4106 4106 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4107 4107 "cat":
4108 4108 (cat,
4109 4109 [('o', 'output', '',
4110 4110 _('print output to file with formatted name'), _('FORMAT')),
4111 4111 ('r', 'rev', '',
4112 4112 _('print the given revision'), _('REV')),
4113 4113 ('', 'decode', None, _('apply any matching decode filter')),
4114 4114 ] + walkopts,
4115 4115 _('[OPTION]... FILE...')),
4116 4116 "^clone":
4117 4117 (clone,
4118 4118 [('U', 'noupdate', None,
4119 4119 _('the clone will include an empty working copy (only a repository)')),
4120 4120 ('u', 'updaterev', '',
4121 4121 _('revision, tag or branch to check out'), _('REV')),
4122 4122 ('r', 'rev', [],
4123 4123 _('include the specified changeset'), _('REV')),
4124 4124 ('b', 'branch', [],
4125 4125 _('clone only the specified branch'), _('BRANCH')),
4126 4126 ('', 'pull', None, _('use pull protocol to copy metadata')),
4127 4127 ('', 'uncompressed', None,
4128 4128 _('use uncompressed transfer (fast over LAN)')),
4129 4129 ] + remoteopts,
4130 4130 _('[OPTION]... SOURCE [DEST]')),
4131 4131 "^commit|ci":
4132 4132 (commit,
4133 4133 [('A', 'addremove', None,
4134 4134 _('mark new/missing files as added/removed before committing')),
4135 4135 ('', 'close-branch', None,
4136 4136 _('mark a branch as closed, hiding it from the branch list')),
4137 4137 ] + walkopts + commitopts + commitopts2,
4138 4138 _('[OPTION]... [FILE]...')),
4139 4139 "copy|cp":
4140 4140 (copy,
4141 4141 [('A', 'after', None, _('record a copy that has already occurred')),
4142 4142 ('f', 'force', None,
4143 4143 _('forcibly copy over an existing managed file')),
4144 4144 ] + walkopts + dryrunopts,
4145 4145 _('[OPTION]... [SOURCE]... DEST')),
4146 4146 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4147 4147 "debugbuilddag":
4148 4148 (debugbuilddag,
4149 4149 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4150 4150 ('a', 'appended-file', None, _('add single file all revs append to')),
4151 4151 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4152 4152 ('n', 'new-file', None, _('add new file at each rev')),
4153 4153 ],
4154 4154 _('[OPTION]... TEXT')),
4155 4155 "debugcheckstate": (debugcheckstate, [], ''),
4156 4156 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4157 4157 "debugcomplete":
4158 4158 (debugcomplete,
4159 4159 [('o', 'options', None, _('show the command options'))],
4160 4160 _('[-o] CMD')),
4161 4161 "debugdag":
4162 4162 (debugdag,
4163 4163 [('t', 'tags', None, _('use tags as labels')),
4164 4164 ('b', 'branches', None, _('annotate with branch names')),
4165 4165 ('', 'dots', None, _('use dots for runs')),
4166 4166 ('s', 'spaces', None, _('separate elements by spaces')),
4167 4167 ],
4168 4168 _('[OPTION]... [FILE [REV]...]')),
4169 4169 "debugdate":
4170 4170 (debugdate,
4171 4171 [('e', 'extended', None, _('try extended date formats'))],
4172 4172 _('[-e] DATE [RANGE]')),
4173 4173 "debugdata": (debugdata, [], _('FILE REV')),
4174 4174 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4175 4175 "debugindex": (debugindex,
4176 4176 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4177 4177 _('FILE')),
4178 4178 "debugindexdot": (debugindexdot, [], _('FILE')),
4179 4179 "debuginstall": (debuginstall, [], ''),
4180 4180 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4181 4181 "debugrebuildstate":
4182 4182 (debugrebuildstate,
4183 4183 [('r', 'rev', '',
4184 4184 _('revision to rebuild to'), _('REV'))],
4185 4185 _('[-r REV] [REV]')),
4186 4186 "debugrename":
4187 4187 (debugrename,
4188 4188 [('r', 'rev', '',
4189 4189 _('revision to debug'), _('REV'))],
4190 4190 _('[-r REV] FILE')),
4191 4191 "debugrevspec":
4192 4192 (debugrevspec, [], ('REVSPEC')),
4193 4193 "debugsetparents":
4194 4194 (debugsetparents, [], _('REV1 [REV2]')),
4195 4195 "debugstate":
4196 4196 (debugstate,
4197 4197 [('', 'nodates', None, _('do not display the saved mtime'))],
4198 4198 _('[OPTION]...')),
4199 4199 "debugsub":
4200 4200 (debugsub,
4201 4201 [('r', 'rev', '',
4202 4202 _('revision to check'), _('REV'))],
4203 4203 _('[-r REV] [REV]')),
4204 4204 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4205 4205 "^diff":
4206 4206 (diff,
4207 4207 [('r', 'rev', [],
4208 4208 _('revision'), _('REV')),
4209 4209 ('c', 'change', '',
4210 4210 _('change made by revision'), _('REV'))
4211 4211 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4212 4212 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4213 4213 "^export":
4214 4214 (export,
4215 4215 [('o', 'output', '',
4216 4216 _('print output to file with formatted name'), _('FORMAT')),
4217 4217 ('', 'switch-parent', None, _('diff against the second parent')),
4218 4218 ('r', 'rev', [],
4219 4219 _('revisions to export'), _('REV')),
4220 4220 ] + diffopts,
4221 4221 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4222 4222 "^forget":
4223 4223 (forget,
4224 4224 [] + walkopts,
4225 4225 _('[OPTION]... FILE...')),
4226 4226 "grep":
4227 4227 (grep,
4228 4228 [('0', 'print0', None, _('end fields with NUL')),
4229 4229 ('', 'all', None, _('print all revisions that match')),
4230 4230 ('f', 'follow', None,
4231 4231 _('follow changeset history,'
4232 4232 ' or file history across copies and renames')),
4233 4233 ('i', 'ignore-case', None, _('ignore case when matching')),
4234 4234 ('l', 'files-with-matches', None,
4235 4235 _('print only filenames and revisions that match')),
4236 4236 ('n', 'line-number', None, _('print matching line numbers')),
4237 4237 ('r', 'rev', [],
4238 4238 _('only search files changed within revision range'), _('REV')),
4239 4239 ('u', 'user', None, _('list the author (long with -v)')),
4240 4240 ('d', 'date', None, _('list the date (short with -q)')),
4241 4241 ] + walkopts,
4242 4242 _('[OPTION]... PATTERN [FILE]...')),
4243 4243 "heads":
4244 4244 (heads,
4245 4245 [('r', 'rev', '',
4246 4246 _('show only heads which are descendants of STARTREV'),
4247 4247 _('STARTREV')),
4248 4248 ('t', 'topo', False, _('show topological heads only')),
4249 4249 ('a', 'active', False,
4250 4250 _('show active branchheads only (DEPRECATED)')),
4251 4251 ('c', 'closed', False,
4252 4252 _('show normal and closed branch heads')),
4253 4253 ] + templateopts,
4254 4254 _('[-ac] [-r STARTREV] [REV]...')),
4255 4255 "help": (help_, [], _('[TOPIC]')),
4256 4256 "identify|id":
4257 4257 (identify,
4258 4258 [('r', 'rev', '',
4259 4259 _('identify the specified revision'), _('REV')),
4260 4260 ('n', 'num', None, _('show local revision number')),
4261 4261 ('i', 'id', None, _('show global revision id')),
4262 4262 ('b', 'branch', None, _('show branch')),
4263 4263 ('t', 'tags', None, _('show tags'))],
4264 4264 _('[-nibt] [-r REV] [SOURCE]')),
4265 4265 "import|patch":
4266 4266 (import_,
4267 4267 [('p', 'strip', 1,
4268 4268 _('directory strip option for patch. This has the same '
4269 4269 'meaning as the corresponding patch option'),
4270 4270 _('NUM')),
4271 4271 ('b', 'base', '',
4272 4272 _('base path'), _('PATH')),
4273 4273 ('f', 'force', None,
4274 4274 _('skip check for outstanding uncommitted changes')),
4275 4275 ('', 'no-commit', None,
4276 4276 _("don't commit, just update the working directory")),
4277 4277 ('', 'exact', None,
4278 4278 _('apply patch to the nodes from which it was generated')),
4279 4279 ('', 'import-branch', None,
4280 4280 _('use any branch information in patch (implied by --exact)'))] +
4281 4281 commitopts + commitopts2 + similarityopts,
4282 4282 _('[OPTION]... PATCH...')),
4283 4283 "incoming|in":
4284 4284 (incoming,
4285 4285 [('f', 'force', None,
4286 4286 _('run even if remote repository is unrelated')),
4287 4287 ('n', 'newest-first', None, _('show newest record first')),
4288 4288 ('', 'bundle', '',
4289 4289 _('file to store the bundles into'), _('FILE')),
4290 4290 ('r', 'rev', [],
4291 4291 _('a remote changeset intended to be added'), _('REV')),
4292 4292 ('b', 'branch', [],
4293 4293 _('a specific branch you would like to pull'), _('BRANCH')),
4294 4294 ] + logopts + remoteopts + subrepoopts,
4295 4295 _('[-p] [-n] [-M] [-f] [-r REV]...'
4296 4296 ' [--bundle FILENAME] [SOURCE]')),
4297 4297 "^init":
4298 4298 (init,
4299 4299 remoteopts,
4300 4300 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4301 4301 "locate":
4302 4302 (locate,
4303 4303 [('r', 'rev', '',
4304 4304 _('search the repository as it is in REV'), _('REV')),
4305 4305 ('0', 'print0', None,
4306 4306 _('end filenames with NUL, for use with xargs')),
4307 4307 ('f', 'fullpath', None,
4308 4308 _('print complete paths from the filesystem root')),
4309 4309 ] + walkopts,
4310 4310 _('[OPTION]... [PATTERN]...')),
4311 4311 "^log|history":
4312 4312 (log,
4313 4313 [('f', 'follow', None,
4314 4314 _('follow changeset history,'
4315 4315 ' or file history across copies and renames')),
4316 4316 ('', 'follow-first', None,
4317 4317 _('only follow the first parent of merge changesets')),
4318 4318 ('d', 'date', '',
4319 4319 _('show revisions matching date spec'), _('DATE')),
4320 4320 ('C', 'copies', None, _('show copied files')),
4321 4321 ('k', 'keyword', [],
4322 4322 _('do case-insensitive search for a given text'), _('TEXT')),
4323 4323 ('r', 'rev', [],
4324 4324 _('show the specified revision or range'), _('REV')),
4325 4325 ('', 'removed', None, _('include revisions where files were removed')),
4326 4326 ('m', 'only-merges', None, _('show only merges')),
4327 4327 ('u', 'user', [],
4328 4328 _('revisions committed by user'), _('USER')),
4329 4329 ('', 'only-branch', [],
4330 4330 _('show only changesets within the given named branch (DEPRECATED)'),
4331 4331 _('BRANCH')),
4332 4332 ('b', 'branch', [],
4333 4333 _('show changesets within the given named branch'), _('BRANCH')),
4334 4334 ('P', 'prune', [],
4335 4335 _('do not display revision or any of its ancestors'), _('REV')),
4336 4336 ] + logopts + walkopts,
4337 4337 _('[OPTION]... [FILE]')),
4338 4338 "manifest":
4339 4339 (manifest,
4340 4340 [('r', 'rev', '',
4341 4341 _('revision to display'), _('REV'))],
4342 4342 _('[-r REV]')),
4343 4343 "^merge":
4344 4344 (merge,
4345 4345 [('f', 'force', None, _('force a merge with outstanding changes')),
4346 4346 ('t', 'tool', '', _('specify merge tool')),
4347 4347 ('r', 'rev', '',
4348 4348 _('revision to merge'), _('REV')),
4349 4349 ('P', 'preview', None,
4350 4350 _('review revisions to merge (no merge is performed)'))],
4351 4351 _('[-P] [-f] [[-r] REV]')),
4352 4352 "outgoing|out":
4353 4353 (outgoing,
4354 4354 [('f', 'force', None,
4355 4355 _('run even when the destination is unrelated')),
4356 4356 ('r', 'rev', [],
4357 4357 _('a changeset intended to be included in the destination'),
4358 4358 _('REV')),
4359 4359 ('n', 'newest-first', None, _('show newest record first')),
4360 4360 ('b', 'branch', [],
4361 4361 _('a specific branch you would like to push'), _('BRANCH')),
4362 4362 ] + logopts + remoteopts + subrepoopts,
4363 4363 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4364 4364 "parents":
4365 4365 (parents,
4366 4366 [('r', 'rev', '',
4367 4367 _('show parents of the specified revision'), _('REV')),
4368 4368 ] + templateopts,
4369 4369 _('[-r REV] [FILE]')),
4370 4370 "paths": (paths, [], _('[NAME]')),
4371 4371 "^pull":
4372 4372 (pull,
4373 4373 [('u', 'update', None,
4374 4374 _('update to new branch head if changesets were pulled')),
4375 4375 ('f', 'force', None,
4376 4376 _('run even when remote repository is unrelated')),
4377 4377 ('r', 'rev', [],
4378 4378 _('a remote changeset intended to be added'), _('REV')),
4379 4379 ('b', 'branch', [],
4380 4380 _('a specific branch you would like to pull'), _('BRANCH')),
4381 4381 ] + remoteopts,
4382 4382 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4383 4383 "^push":
4384 4384 (push,
4385 4385 [('f', 'force', None, _('force push')),
4386 4386 ('r', 'rev', [],
4387 4387 _('a changeset intended to be included in the destination'),
4388 4388 _('REV')),
4389 4389 ('b', 'branch', [],
4390 4390 _('a specific branch you would like to push'), _('BRANCH')),
4391 4391 ('', 'new-branch', False, _('allow pushing a new branch')),
4392 4392 ] + remoteopts,
4393 4393 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4394 4394 "recover": (recover, []),
4395 4395 "^remove|rm":
4396 4396 (remove,
4397 4397 [('A', 'after', None, _('record delete for missing files')),
4398 4398 ('f', 'force', None,
4399 4399 _('remove (and delete) file even if added or modified')),
4400 4400 ] + walkopts,
4401 4401 _('[OPTION]... FILE...')),
4402 4402 "rename|move|mv":
4403 4403 (rename,
4404 4404 [('A', 'after', None, _('record a rename that has already occurred')),
4405 4405 ('f', 'force', None,
4406 4406 _('forcibly copy over an existing managed file')),
4407 4407 ] + walkopts + dryrunopts,
4408 4408 _('[OPTION]... SOURCE... DEST')),
4409 4409 "resolve":
4410 4410 (resolve,
4411 4411 [('a', 'all', None, _('select all unresolved files')),
4412 4412 ('l', 'list', None, _('list state of files needing merge')),
4413 4413 ('m', 'mark', None, _('mark files as resolved')),
4414 4414 ('u', 'unmark', None, _('mark files as unresolved')),
4415 4415 ('t', 'tool', '', _('specify merge tool')),
4416 4416 ('n', 'no-status', None, _('hide status prefix'))]
4417 4417 + walkopts,
4418 4418 _('[OPTION]... [FILE]...')),
4419 4419 "revert":
4420 4420 (revert,
4421 4421 [('a', 'all', None, _('revert all changes when no arguments given')),
4422 4422 ('d', 'date', '',
4423 4423 _('tipmost revision matching date'), _('DATE')),
4424 4424 ('r', 'rev', '',
4425 4425 _('revert to the specified revision'), _('REV')),
4426 4426 ('', 'no-backup', None, _('do not save backup copies of files')),
4427 4427 ] + walkopts + dryrunopts,
4428 4428 _('[OPTION]... [-r REV] [NAME]...')),
4429 4429 "rollback": (rollback, dryrunopts),
4430 4430 "root": (root, []),
4431 4431 "^serve":
4432 4432 (serve,
4433 4433 [('A', 'accesslog', '',
4434 4434 _('name of access log file to write to'), _('FILE')),
4435 4435 ('d', 'daemon', None, _('run server in background')),
4436 4436 ('', 'daemon-pipefds', '',
4437 4437 _('used internally by daemon mode'), _('NUM')),
4438 4438 ('E', 'errorlog', '',
4439 4439 _('name of error log file to write to'), _('FILE')),
4440 4440 # use string type, then we can check if something was passed
4441 4441 ('p', 'port', '',
4442 4442 _('port to listen on (default: 8000)'), _('PORT')),
4443 4443 ('a', 'address', '',
4444 4444 _('address to listen on (default: all interfaces)'), _('ADDR')),
4445 4445 ('', 'prefix', '',
4446 4446 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4447 4447 ('n', 'name', '',
4448 4448 _('name to show in web pages (default: working directory)'),
4449 4449 _('NAME')),
4450 4450 ('', 'web-conf', '',
4451 4451 _('name of the hgweb config file (see "hg help hgweb")'),
4452 4452 _('FILE')),
4453 4453 ('', 'webdir-conf', '',
4454 4454 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4455 4455 ('', 'pid-file', '',
4456 4456 _('name of file to write process ID to'), _('FILE')),
4457 4457 ('', 'stdio', None, _('for remote clients')),
4458 4458 ('t', 'templates', '',
4459 4459 _('web templates to use'), _('TEMPLATE')),
4460 4460 ('', 'style', '',
4461 4461 _('template style to use'), _('STYLE')),
4462 4462 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4463 4463 ('', 'certificate', '',
4464 4464 _('SSL certificate file'), _('FILE'))],
4465 4465 _('[OPTION]...')),
4466 4466 "showconfig|debugconfig":
4467 4467 (showconfig,
4468 4468 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4469 4469 _('[-u] [NAME]...')),
4470 4470 "^summary|sum":
4471 4471 (summary,
4472 4472 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4473 4473 "^status|st":
4474 4474 (status,
4475 4475 [('A', 'all', None, _('show status of all files')),
4476 4476 ('m', 'modified', None, _('show only modified files')),
4477 4477 ('a', 'added', None, _('show only added files')),
4478 4478 ('r', 'removed', None, _('show only removed files')),
4479 4479 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4480 4480 ('c', 'clean', None, _('show only files without changes')),
4481 4481 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4482 4482 ('i', 'ignored', None, _('show only ignored files')),
4483 4483 ('n', 'no-status', None, _('hide status prefix')),
4484 4484 ('C', 'copies', None, _('show source of copied files')),
4485 4485 ('0', 'print0', None,
4486 4486 _('end filenames with NUL, for use with xargs')),
4487 4487 ('', 'rev', [],
4488 4488 _('show difference from revision'), _('REV')),
4489 4489 ('', 'change', '',
4490 4490 _('list the changed files of a revision'), _('REV')),
4491 4491 ] + walkopts + subrepoopts,
4492 4492 _('[OPTION]... [FILE]...')),
4493 4493 "tag":
4494 4494 (tag,
4495 4495 [('f', 'force', None, _('force tag')),
4496 4496 ('l', 'local', None, _('make the tag local')),
4497 4497 ('r', 'rev', '',
4498 4498 _('revision to tag'), _('REV')),
4499 4499 ('', 'remove', None, _('remove a tag')),
4500 4500 # -l/--local is already there, commitopts cannot be used
4501 4501 ('e', 'edit', None, _('edit commit message')),
4502 4502 ('m', 'message', '',
4503 4503 _('use <text> as commit message'), _('TEXT')),
4504 4504 ] + commitopts2,
4505 4505 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4506 4506 "tags": (tags, [], ''),
4507 4507 "tip":
4508 4508 (tip,
4509 4509 [('p', 'patch', None, _('show patch')),
4510 4510 ('g', 'git', None, _('use git extended diff format')),
4511 4511 ] + templateopts,
4512 4512 _('[-p] [-g]')),
4513 4513 "unbundle":
4514 4514 (unbundle,
4515 4515 [('u', 'update', None,
4516 4516 _('update to new branch head if changesets were unbundled'))],
4517 4517 _('[-u] FILE...')),
4518 4518 "^update|up|checkout|co":
4519 4519 (update,
4520 4520 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4521 4521 ('c', 'check', None,
4522 4522 _('update across branches if no uncommitted changes')),
4523 4523 ('d', 'date', '',
4524 4524 _('tipmost revision matching date'), _('DATE')),
4525 4525 ('r', 'rev', '',
4526 4526 _('revision'), _('REV'))],
4527 4527 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4528 4528 "verify": (verify, []),
4529 4529 "version": (version_, []),
4530 4530 }
4531 4531
4532 4532 norepo = ("clone init version help debugcommands debugcomplete"
4533 4533 " debugdate debuginstall debugfsinfo debugpushkey")
4534 4534 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4535 4535 " debugdata debugindex debugindexdot")
@@ -1,683 +1,683 b''
1 1 # dirstate.py - working directory tracking 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 nullid
9 9 from i18n import _
10 10 import util, ignore, osutil, parsers, encoding
11 11 import struct, os, stat, errno
12 12 import cStringIO
13 13
14 14 _format = ">cllll"
15 15 propertycache = util.propertycache
16 16
17 17 def _finddirs(path):
18 18 pos = path.rfind('/')
19 19 while pos != -1:
20 20 yield path[:pos]
21 21 pos = path.rfind('/', 0, pos)
22 22
23 23 def _incdirs(dirs, path):
24 24 for base in _finddirs(path):
25 25 if base in dirs:
26 26 dirs[base] += 1
27 27 return
28 28 dirs[base] = 1
29 29
30 30 def _decdirs(dirs, path):
31 31 for base in _finddirs(path):
32 32 if dirs[base] > 1:
33 33 dirs[base] -= 1
34 34 return
35 35 del dirs[base]
36 36
37 37 class dirstate(object):
38 38
39 39 def __init__(self, opener, ui, root, validate):
40 40 '''Create a new dirstate object.
41 41
42 42 opener is an open()-like callable that can be used to open the
43 43 dirstate file; root is the root of the directory tracked by
44 44 the dirstate.
45 45 '''
46 46 self._opener = opener
47 47 self._validate = validate
48 48 self._root = root
49 49 self._rootdir = os.path.join(root, '')
50 50 self._dirty = False
51 51 self._dirtypl = False
52 52 self._ui = ui
53 53
54 54 @propertycache
55 55 def _map(self):
56 56 '''Return the dirstate contents as a map from filename to
57 57 (state, mode, size, time).'''
58 58 self._read()
59 59 return self._map
60 60
61 61 @propertycache
62 62 def _copymap(self):
63 63 self._read()
64 64 return self._copymap
65 65
66 66 @propertycache
67 67 def _foldmap(self):
68 68 f = {}
69 69 for name in self._map:
70 70 f[os.path.normcase(name)] = name
71 71 return f
72 72
73 73 @propertycache
74 74 def _branch(self):
75 75 try:
76 76 return self._opener("branch").read().strip() or "default"
77 77 except IOError:
78 78 return "default"
79 79
80 80 @propertycache
81 81 def _pl(self):
82 82 try:
83 83 st = self._opener("dirstate").read(40)
84 84 l = len(st)
85 85 if l == 40:
86 86 return st[:20], st[20:40]
87 87 elif l > 0 and l < 40:
88 88 raise util.Abort(_('working directory state appears damaged!'))
89 89 except IOError, err:
90 90 if err.errno != errno.ENOENT:
91 91 raise
92 92 return [nullid, nullid]
93 93
94 94 @propertycache
95 95 def _dirs(self):
96 96 dirs = {}
97 97 for f, s in self._map.iteritems():
98 98 if s[0] != 'r':
99 99 _incdirs(dirs, f)
100 100 return dirs
101 101
102 102 @propertycache
103 103 def _ignore(self):
104 104 files = [self._join('.hgignore')]
105 105 for name, path in self._ui.configitems("ui"):
106 106 if name == 'ignore' or name.startswith('ignore.'):
107 107 files.append(util.expandpath(path))
108 108 return ignore.ignore(self._root, files, self._ui.warn)
109 109
110 110 @propertycache
111 111 def _slash(self):
112 112 return self._ui.configbool('ui', 'slash') and os.sep != '/'
113 113
114 114 @propertycache
115 115 def _checklink(self):
116 116 return util.checklink(self._root)
117 117
118 118 @propertycache
119 119 def _checkexec(self):
120 120 return util.checkexec(self._root)
121 121
122 122 @propertycache
123 123 def _checkcase(self):
124 124 return not util.checkcase(self._join('.hg'))
125 125
126 126 def _join(self, f):
127 127 # much faster than os.path.join()
128 128 # it's safe because f is always a relative path
129 129 return self._rootdir + f
130 130
131 131 def flagfunc(self, fallback):
132 132 if self._checklink:
133 133 if self._checkexec:
134 134 def f(x):
135 135 p = self._join(x)
136 136 if os.path.islink(p):
137 137 return 'l'
138 138 if util.is_exec(p):
139 139 return 'x'
140 140 return ''
141 141 return f
142 142 def f(x):
143 143 if os.path.islink(self._join(x)):
144 144 return 'l'
145 145 if 'x' in fallback(x):
146 146 return 'x'
147 147 return ''
148 148 return f
149 149 if self._checkexec:
150 150 def f(x):
151 151 if 'l' in fallback(x):
152 152 return 'l'
153 153 if util.is_exec(self._join(x)):
154 154 return 'x'
155 155 return ''
156 156 return f
157 157 return fallback
158 158
159 159 def getcwd(self):
160 160 cwd = os.getcwd()
161 161 if cwd == self._root:
162 162 return ''
163 163 # self._root ends with a path separator if self._root is '/' or 'C:\'
164 164 rootsep = self._root
165 165 if not util.endswithsep(rootsep):
166 166 rootsep += os.sep
167 167 if cwd.startswith(rootsep):
168 168 return cwd[len(rootsep):]
169 169 else:
170 170 # we're outside the repo. return an absolute path.
171 171 return cwd
172 172
173 173 def pathto(self, f, cwd=None):
174 174 if cwd is None:
175 175 cwd = self.getcwd()
176 176 path = util.pathto(self._root, cwd, f)
177 177 if self._slash:
178 178 return util.normpath(path)
179 179 return path
180 180
181 181 def __getitem__(self, key):
182 182 '''Return the current state of key (a filename) in the dirstate.
183 183
184 184 States are:
185 185 n normal
186 186 m needs merging
187 187 r marked for removal
188 188 a marked for addition
189 189 ? not tracked
190 190 '''
191 191 return self._map.get(key, ("?",))[0]
192 192
193 193 def __contains__(self, key):
194 194 return key in self._map
195 195
196 196 def __iter__(self):
197 197 for x in sorted(self._map):
198 198 yield x
199 199
200 200 def parents(self):
201 201 return [self._validate(p) for p in self._pl]
202 202
203 203 def branch(self):
204 204 return encoding.tolocal(self._branch)
205 205
206 206 def setparents(self, p1, p2=nullid):
207 207 self._dirty = self._dirtypl = True
208 208 self._pl = p1, p2
209 209
210 210 def setbranch(self, branch):
211 211 if branch in ['tip', '.', 'null']:
212 212 raise util.Abort(_('the name \'%s\' is reserved') % branch)
213 213 self._branch = encoding.fromlocal(branch)
214 214 self._opener("branch", "w").write(self._branch + '\n')
215 215
216 216 def _read(self):
217 217 self._map = {}
218 218 self._copymap = {}
219 219 try:
220 220 st = self._opener("dirstate").read()
221 221 except IOError, err:
222 222 if err.errno != errno.ENOENT:
223 223 raise
224 224 return
225 225 if not st:
226 226 return
227 227
228 228 p = parsers.parse_dirstate(self._map, self._copymap, st)
229 229 if not self._dirtypl:
230 230 self._pl = p
231 231
232 232 def invalidate(self):
233 233 for a in ("_map", "_copymap", "_foldmap", "_branch", "_pl", "_dirs",
234 234 "_ignore"):
235 235 if a in self.__dict__:
236 236 delattr(self, a)
237 237 self._dirty = False
238 238
239 239 def copy(self, source, dest):
240 240 """Mark dest as a copy of source. Unmark dest if source is None."""
241 241 if source == dest:
242 242 return
243 243 self._dirty = True
244 244 if source is not None:
245 245 self._copymap[dest] = source
246 246 elif dest in self._copymap:
247 247 del self._copymap[dest]
248 248
249 249 def copied(self, file):
250 250 return self._copymap.get(file, None)
251 251
252 252 def copies(self):
253 253 return self._copymap
254 254
255 255 def _droppath(self, f):
256 256 if self[f] not in "?r" and "_dirs" in self.__dict__:
257 257 _decdirs(self._dirs, f)
258 258
259 259 def _addpath(self, f, check=False):
260 260 oldstate = self[f]
261 261 if check or oldstate == "r":
262 262 if '\r' in f or '\n' in f:
263 263 raise util.Abort(
264 264 _("'\\n' and '\\r' disallowed in filenames: %r") % f)
265 265 if f in self._dirs:
266 266 raise util.Abort(_('directory %r already in dirstate') % f)
267 267 # shadows
268 268 for d in _finddirs(f):
269 269 if d in self._dirs:
270 270 break
271 271 if d in self._map and self[d] != 'r':
272 272 raise util.Abort(
273 273 _('file %r in dirstate clashes with %r') % (d, f))
274 274 if oldstate in "?r" and "_dirs" in self.__dict__:
275 275 _incdirs(self._dirs, f)
276 276
277 277 def normal(self, f):
278 278 '''Mark a file normal and clean.'''
279 279 self._dirty = True
280 280 self._addpath(f)
281 281 s = os.lstat(self._join(f))
282 282 self._map[f] = ('n', s.st_mode, s.st_size, int(s.st_mtime))
283 283 if f in self._copymap:
284 284 del self._copymap[f]
285 285
286 286 def normallookup(self, f):
287 287 '''Mark a file normal, but possibly dirty.'''
288 288 if self._pl[1] != nullid and f in self._map:
289 289 # if there is a merge going on and the file was either
290 290 # in state 'm' (-1) or coming from other parent (-2) before
291 291 # being removed, restore that state.
292 292 entry = self._map[f]
293 293 if entry[0] == 'r' and entry[2] in (-1, -2):
294 294 source = self._copymap.get(f)
295 295 if entry[2] == -1:
296 296 self.merge(f)
297 297 elif entry[2] == -2:
298 298 self.otherparent(f)
299 299 if source:
300 300 self.copy(source, f)
301 301 return
302 302 if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2:
303 303 return
304 304 self._dirty = True
305 305 self._addpath(f)
306 306 self._map[f] = ('n', 0, -1, -1)
307 307 if f in self._copymap:
308 308 del self._copymap[f]
309 309
310 310 def otherparent(self, f):
311 311 '''Mark as coming from the other parent, always dirty.'''
312 312 if self._pl[1] == nullid:
313 313 raise util.Abort(_("setting %r to other parent "
314 314 "only allowed in merges") % f)
315 315 self._dirty = True
316 316 self._addpath(f)
317 317 self._map[f] = ('n', 0, -2, -1)
318 318 if f in self._copymap:
319 319 del self._copymap[f]
320 320
321 321 def add(self, f):
322 322 '''Mark a file added.'''
323 323 self._dirty = True
324 324 self._addpath(f, True)
325 325 self._map[f] = ('a', 0, -1, -1)
326 326 if f in self._copymap:
327 327 del self._copymap[f]
328 328
329 329 def remove(self, f):
330 330 '''Mark a file removed.'''
331 331 self._dirty = True
332 332 self._droppath(f)
333 333 size = 0
334 334 if self._pl[1] != nullid and f in self._map:
335 335 # backup the previous state
336 336 entry = self._map[f]
337 337 if entry[0] == 'm': # merge
338 338 size = -1
339 339 elif entry[0] == 'n' and entry[2] == -2: # other parent
340 340 size = -2
341 341 self._map[f] = ('r', 0, size, 0)
342 342 if size == 0 and f in self._copymap:
343 343 del self._copymap[f]
344 344
345 345 def merge(self, f):
346 346 '''Mark a file merged.'''
347 347 self._dirty = True
348 348 s = os.lstat(self._join(f))
349 349 self._addpath(f)
350 350 self._map[f] = ('m', s.st_mode, s.st_size, int(s.st_mtime))
351 351 if f in self._copymap:
352 352 del self._copymap[f]
353 353
354 354 def forget(self, f):
355 355 '''Forget a file.'''
356 356 self._dirty = True
357 357 try:
358 358 self._droppath(f)
359 359 del self._map[f]
360 360 except KeyError:
361 361 self._ui.warn(_("not in dirstate: %s\n") % f)
362 362
363 363 def _normalize(self, path, knownpath):
364 364 norm_path = os.path.normcase(path)
365 365 fold_path = self._foldmap.get(norm_path, None)
366 366 if fold_path is None:
367 367 if knownpath or not os.path.lexists(os.path.join(self._root, path)):
368 368 fold_path = path
369 369 else:
370 370 fold_path = self._foldmap.setdefault(norm_path,
371 371 util.fspath(path, self._root))
372 372 return fold_path
373 373
374 374 def clear(self):
375 375 self._map = {}
376 376 if "_dirs" in self.__dict__:
377 377 delattr(self, "_dirs")
378 378 self._copymap = {}
379 379 self._pl = [nullid, nullid]
380 380 self._dirty = True
381 381
382 382 def rebuild(self, parent, files):
383 383 self.clear()
384 384 for f in files:
385 385 if 'x' in files.flags(f):
386 386 self._map[f] = ('n', 0777, -1, 0)
387 387 else:
388 388 self._map[f] = ('n', 0666, -1, 0)
389 389 self._pl = (parent, nullid)
390 390 self._dirty = True
391 391
392 392 def write(self):
393 393 if not self._dirty:
394 394 return
395 395 st = self._opener("dirstate", "w", atomictemp=True)
396 396
397 397 # use the modification time of the newly created temporary file as the
398 398 # filesystem's notion of 'now'
399 399 now = int(util.fstat(st).st_mtime)
400 400
401 401 cs = cStringIO.StringIO()
402 402 copymap = self._copymap
403 403 pack = struct.pack
404 404 write = cs.write
405 405 write("".join(self._pl))
406 406 for f, e in self._map.iteritems():
407 407 if e[0] == 'n' and e[3] == now:
408 408 # The file was last modified "simultaneously" with the current
409 409 # write to dirstate (i.e. within the same second for file-
410 410 # systems with a granularity of 1 sec). This commonly happens
411 411 # for at least a couple of files on 'update'.
412 412 # The user could change the file without changing its size
413 413 # within the same second. Invalidate the file's stat data in
414 414 # dirstate, forcing future 'status' calls to compare the
415 415 # contents of the file. This prevents mistakenly treating such
416 416 # files as clean.
417 417 e = (e[0], 0, -1, -1) # mark entry as 'unset'
418 418 self._map[f] = e
419 419
420 420 if f in copymap:
421 421 f = "%s\0%s" % (f, copymap[f])
422 422 e = pack(_format, e[0], e[1], e[2], e[3], len(f))
423 423 write(e)
424 424 write(f)
425 425 st.write(cs.getvalue())
426 426 st.rename()
427 427 self._dirty = self._dirtypl = False
428 428
429 429 def _dirignore(self, f):
430 430 if f == '.':
431 431 return False
432 432 if self._ignore(f):
433 433 return True
434 434 for p in _finddirs(f):
435 435 if self._ignore(p):
436 436 return True
437 437 return False
438 438
439 439 def walk(self, match, subrepos, unknown, ignored):
440 440 '''
441 441 Walk recursively through the directory tree, finding all files
442 442 matched by match.
443 443
444 444 Return a dict mapping filename to stat-like object (either
445 445 mercurial.osutil.stat instance or return value of os.stat()).
446 446 '''
447 447
448 448 def fwarn(f, msg):
449 449 self._ui.warn('%s: %s\n' % (self.pathto(f), msg))
450 450 return False
451 451
452 452 def badtype(mode):
453 453 kind = _('unknown')
454 454 if stat.S_ISCHR(mode):
455 455 kind = _('character device')
456 456 elif stat.S_ISBLK(mode):
457 457 kind = _('block device')
458 458 elif stat.S_ISFIFO(mode):
459 459 kind = _('fifo')
460 460 elif stat.S_ISSOCK(mode):
461 461 kind = _('socket')
462 462 elif stat.S_ISDIR(mode):
463 463 kind = _('directory')
464 464 return _('unsupported file type (type is %s)') % kind
465 465
466 466 ignore = self._ignore
467 467 dirignore = self._dirignore
468 468 if ignored:
469 469 ignore = util.never
470 470 dirignore = util.never
471 471 elif not unknown:
472 472 # if unknown and ignored are False, skip step 2
473 473 ignore = util.always
474 474 dirignore = util.always
475 475
476 476 matchfn = match.matchfn
477 477 badfn = match.bad
478 478 dmap = self._map
479 479 normpath = util.normpath
480 480 listdir = osutil.listdir
481 481 lstat = os.lstat
482 482 getkind = stat.S_IFMT
483 483 dirkind = stat.S_IFDIR
484 484 regkind = stat.S_IFREG
485 485 lnkkind = stat.S_IFLNK
486 486 join = self._join
487 487 work = []
488 488 wadd = work.append
489 489
490 490 exact = skipstep3 = False
491 491 if matchfn == match.exact: # match.exact
492 492 exact = True
493 493 dirignore = util.always # skip step 2
494 494 elif match.files() and not match.anypats(): # match.match, no patterns
495 495 skipstep3 = True
496 496
497 497 if self._checkcase:
498 498 normalize = self._normalize
499 499 skipstep3 = False
500 500 else:
501 501 normalize = lambda x, y: x
502 502
503 503 files = sorted(match.files())
504 504 subrepos.sort()
505 505 i, j = 0, 0
506 506 while i < len(files) and j < len(subrepos):
507 507 subpath = subrepos[j] + "/"
508 if not files[i].startswith(subpath):
508 if files[i] < subpath:
509 509 i += 1
510 510 continue
511 511 while files and files[i].startswith(subpath):
512 512 del files[i]
513 513 j += 1
514 514
515 515 if not files or '.' in files:
516 516 files = ['']
517 517 results = dict.fromkeys(subrepos)
518 518 results['.hg'] = None
519 519
520 520 # step 1: find all explicit files
521 521 for ff in files:
522 522 nf = normalize(normpath(ff), False)
523 523 if nf in results:
524 524 continue
525 525
526 526 try:
527 527 st = lstat(join(nf))
528 528 kind = getkind(st.st_mode)
529 529 if kind == dirkind:
530 530 skipstep3 = False
531 531 if nf in dmap:
532 532 #file deleted on disk but still in dirstate
533 533 results[nf] = None
534 534 match.dir(nf)
535 535 if not dirignore(nf):
536 536 wadd(nf)
537 537 elif kind == regkind or kind == lnkkind:
538 538 results[nf] = st
539 539 else:
540 540 badfn(ff, badtype(kind))
541 541 if nf in dmap:
542 542 results[nf] = None
543 543 except OSError, inst:
544 544 if nf in dmap: # does it exactly match a file?
545 545 results[nf] = None
546 546 else: # does it match a directory?
547 547 prefix = nf + "/"
548 548 for fn in dmap:
549 549 if fn.startswith(prefix):
550 550 match.dir(nf)
551 551 skipstep3 = False
552 552 break
553 553 else:
554 554 badfn(ff, inst.strerror)
555 555
556 556 # step 2: visit subdirectories
557 557 while work:
558 558 nd = work.pop()
559 559 skip = None
560 560 if nd == '.':
561 561 nd = ''
562 562 else:
563 563 skip = '.hg'
564 564 try:
565 565 entries = listdir(join(nd), stat=True, skip=skip)
566 566 except OSError, inst:
567 567 if inst.errno == errno.EACCES:
568 568 fwarn(nd, inst.strerror)
569 569 continue
570 570 raise
571 571 for f, kind, st in entries:
572 572 nf = normalize(nd and (nd + "/" + f) or f, True)
573 573 if nf not in results:
574 574 if kind == dirkind:
575 575 if not ignore(nf):
576 576 match.dir(nf)
577 577 wadd(nf)
578 578 if nf in dmap and matchfn(nf):
579 579 results[nf] = None
580 580 elif kind == regkind or kind == lnkkind:
581 581 if nf in dmap:
582 582 if matchfn(nf):
583 583 results[nf] = st
584 584 elif matchfn(nf) and not ignore(nf):
585 585 results[nf] = st
586 586 elif nf in dmap and matchfn(nf):
587 587 results[nf] = None
588 588
589 589 # step 3: report unseen items in the dmap hash
590 590 if not skipstep3 and not exact:
591 591 visit = sorted([f for f in dmap if f not in results and matchfn(f)])
592 592 for nf, st in zip(visit, util.statfiles([join(i) for i in visit])):
593 593 if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
594 594 st = None
595 595 results[nf] = st
596 596 for s in subrepos:
597 597 del results[s]
598 598 del results['.hg']
599 599 return results
600 600
601 601 def status(self, match, subrepos, ignored, clean, unknown):
602 602 '''Determine the status of the working copy relative to the
603 603 dirstate and return a tuple of lists (unsure, modified, added,
604 604 removed, deleted, unknown, ignored, clean), where:
605 605
606 606 unsure:
607 607 files that might have been modified since the dirstate was
608 608 written, but need to be read to be sure (size is the same
609 609 but mtime differs)
610 610 modified:
611 611 files that have definitely been modified since the dirstate
612 612 was written (different size or mode)
613 613 added:
614 614 files that have been explicitly added with hg add
615 615 removed:
616 616 files that have been explicitly removed with hg remove
617 617 deleted:
618 618 files that have been deleted through other means ("missing")
619 619 unknown:
620 620 files not in the dirstate that are not ignored
621 621 ignored:
622 622 files not in the dirstate that are ignored
623 623 (by _dirignore())
624 624 clean:
625 625 files that have definitely not been modified since the
626 626 dirstate was written
627 627 '''
628 628 listignored, listclean, listunknown = ignored, clean, unknown
629 629 lookup, modified, added, unknown, ignored = [], [], [], [], []
630 630 removed, deleted, clean = [], [], []
631 631
632 632 dmap = self._map
633 633 ladd = lookup.append # aka "unsure"
634 634 madd = modified.append
635 635 aadd = added.append
636 636 uadd = unknown.append
637 637 iadd = ignored.append
638 638 radd = removed.append
639 639 dadd = deleted.append
640 640 cadd = clean.append
641 641
642 642 lnkkind = stat.S_IFLNK
643 643
644 644 for fn, st in self.walk(match, subrepos, listunknown,
645 645 listignored).iteritems():
646 646 if fn not in dmap:
647 647 if (listignored or match.exact(fn)) and self._dirignore(fn):
648 648 if listignored:
649 649 iadd(fn)
650 650 elif listunknown:
651 651 uadd(fn)
652 652 continue
653 653
654 654 state, mode, size, time = dmap[fn]
655 655
656 656 if not st and state in "nma":
657 657 dadd(fn)
658 658 elif state == 'n':
659 659 # The "mode & lnkkind != lnkkind or self._checklink"
660 660 # lines are an expansion of "islink => checklink"
661 661 # where islink means "is this a link?" and checklink
662 662 # means "can we check links?".
663 663 if (size >= 0 and
664 664 (size != st.st_size
665 665 or ((mode ^ st.st_mode) & 0100 and self._checkexec))
666 666 and (mode & lnkkind != lnkkind or self._checklink)
667 667 or size == -2 # other parent
668 668 or fn in self._copymap):
669 669 madd(fn)
670 670 elif (time != int(st.st_mtime)
671 671 and (mode & lnkkind != lnkkind or self._checklink)):
672 672 ladd(fn)
673 673 elif listclean:
674 674 cadd(fn)
675 675 elif state == 'm':
676 676 madd(fn)
677 677 elif state == 'a':
678 678 aadd(fn)
679 679 elif state == 'r':
680 680 radd(fn)
681 681
682 682 return (lookup, modified, added, removed, deleted, unknown, ignored,
683 683 clean)
@@ -1,554 +1,554 b''
1 1 # hg.py - repository classes for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 from i18n import _
10 10 from lock import release
11 11 from node import hex, nullid, nullrev, short
12 12 import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo
13 13 import lock, util, extensions, error, encoding, node
14 14 import cmdutil, discovery, url
15 15 import merge as mergemod
16 16 import verify as verifymod
17 17 import errno, os, shutil
18 18
19 19 def _local(path):
20 20 path = util.expandpath(util.drop_scheme('file', path))
21 21 return (os.path.isfile(path) and bundlerepo or localrepo)
22 22
23 23 def addbranchrevs(lrepo, repo, branches, revs):
24 24 hashbranch, branches = branches
25 25 if not hashbranch and not branches:
26 26 return revs or None, revs and revs[0] or None
27 27 revs = revs and list(revs) or []
28 28 if not repo.capable('branchmap'):
29 29 if branches:
30 30 raise util.Abort(_("remote branch lookup not supported"))
31 31 revs.append(hashbranch)
32 32 return revs, revs[0]
33 33 branchmap = repo.branchmap()
34 34
35 35 def primary(branch):
36 36 if branch == '.':
37 37 if not lrepo or not lrepo.local():
38 38 raise util.Abort(_("dirstate branch not accessible"))
39 39 branch = lrepo.dirstate.branch()
40 40 if branch in branchmap:
41 41 revs.extend(node.hex(r) for r in reversed(branchmap[branch]))
42 42 return True
43 43 else:
44 44 return False
45 45
46 46 for branch in branches:
47 47 if not primary(branch):
48 48 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
49 49 if hashbranch:
50 50 if not primary(hashbranch):
51 51 revs.append(hashbranch)
52 52 return revs, revs[0]
53 53
54 54 def parseurl(url, branches=None):
55 55 '''parse url#branch, returning (url, (branch, branches))'''
56 56
57 57 if '#' not in url:
58 58 return url, (None, branches or [])
59 59 url, branch = url.split('#', 1)
60 60 return url, (branch, branches or [])
61 61
62 62 schemes = {
63 63 'bundle': bundlerepo,
64 64 'file': _local,
65 65 'http': httprepo,
66 66 'https': httprepo,
67 67 'ssh': sshrepo,
68 68 'static-http': statichttprepo,
69 69 }
70 70
71 71 def _lookup(path):
72 72 scheme = 'file'
73 73 if path:
74 74 c = path.find(':')
75 75 if c > 0:
76 76 scheme = path[:c]
77 77 thing = schemes.get(scheme) or schemes['file']
78 78 try:
79 79 return thing(path)
80 80 except TypeError:
81 81 return thing
82 82
83 83 def islocal(repo):
84 84 '''return true if repo or path is local'''
85 85 if isinstance(repo, str):
86 86 try:
87 87 return _lookup(repo).islocal(repo)
88 88 except AttributeError:
89 89 return False
90 90 return repo.local()
91 91
92 92 def repository(ui, path='', create=False):
93 93 """return a repository object for the specified path"""
94 94 repo = _lookup(path).instance(ui, path, create)
95 95 ui = getattr(repo, "ui", ui)
96 96 for name, module in extensions.extensions():
97 97 hook = getattr(module, 'reposetup', None)
98 98 if hook:
99 99 hook(ui, repo)
100 100 return repo
101 101
102 102 def defaultdest(source):
103 103 '''return default destination of clone if none is given'''
104 104 return os.path.basename(os.path.normpath(source))
105 105
106 106 def localpath(path):
107 107 if path.startswith('file://localhost/'):
108 108 return path[16:]
109 109 if path.startswith('file://'):
110 110 return path[7:]
111 111 if path.startswith('file:'):
112 112 return path[5:]
113 113 return path
114 114
115 115 def share(ui, source, dest=None, update=True):
116 116 '''create a shared repository'''
117 117
118 118 if not islocal(source):
119 119 raise util.Abort(_('can only share local repositories'))
120 120
121 121 if not dest:
122 122 dest = defaultdest(source)
123 123 else:
124 124 dest = ui.expandpath(dest)
125 125
126 126 if isinstance(source, str):
127 127 origsource = ui.expandpath(source)
128 128 source, branches = parseurl(origsource)
129 129 srcrepo = repository(ui, source)
130 130 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
131 131 else:
132 132 srcrepo = source
133 133 origsource = source = srcrepo.url()
134 134 checkout = None
135 135
136 136 sharedpath = srcrepo.sharedpath # if our source is already sharing
137 137
138 138 root = os.path.realpath(dest)
139 139 roothg = os.path.join(root, '.hg')
140 140
141 141 if os.path.exists(roothg):
142 142 raise util.Abort(_('destination already exists'))
143 143
144 144 if not os.path.isdir(root):
145 145 os.mkdir(root)
146 146 os.mkdir(roothg)
147 147
148 148 requirements = ''
149 149 try:
150 150 requirements = srcrepo.opener('requires').read()
151 151 except IOError, inst:
152 152 if inst.errno != errno.ENOENT:
153 153 raise
154 154
155 155 requirements += 'shared\n'
156 156 file(os.path.join(roothg, 'requires'), 'w').write(requirements)
157 157 file(os.path.join(roothg, 'sharedpath'), 'w').write(sharedpath)
158 158
159 159 default = srcrepo.ui.config('paths', 'default')
160 160 if default:
161 161 f = file(os.path.join(roothg, 'hgrc'), 'w')
162 162 f.write('[paths]\ndefault = %s\n' % default)
163 163 f.close()
164 164
165 165 r = repository(ui, root)
166 166
167 167 if update:
168 168 r.ui.status(_("updating working directory\n"))
169 169 if update is not True:
170 170 checkout = update
171 171 for test in (checkout, 'default', 'tip'):
172 172 if test is None:
173 173 continue
174 174 try:
175 175 uprev = r.lookup(test)
176 176 break
177 177 except error.RepoLookupError:
178 178 continue
179 179 _update(r, uprev)
180 180
181 181 def clone(ui, source, dest=None, pull=False, rev=None, update=True,
182 182 stream=False, branch=None):
183 183 """Make a copy of an existing repository.
184 184
185 185 Create a copy of an existing repository in a new directory. The
186 186 source and destination are URLs, as passed to the repository
187 187 function. Returns a pair of repository objects, the source and
188 188 newly created destination.
189 189
190 190 The location of the source is added to the new repository's
191 191 .hg/hgrc file, as the default to be used for future pulls and
192 192 pushes.
193 193
194 194 If an exception is raised, the partly cloned/updated destination
195 195 repository will be deleted.
196 196
197 197 Arguments:
198 198
199 199 source: repository object or URL
200 200
201 201 dest: URL of destination repository to create (defaults to base
202 202 name of source repository)
203 203
204 204 pull: always pull from source repository, even in local case
205 205
206 206 stream: stream raw data uncompressed from repository (fast over
207 207 LAN, slow over WAN)
208 208
209 209 rev: revision to clone up to (implies pull=True)
210 210
211 211 update: update working directory after clone completes, if
212 212 destination is local repository (True means update to default rev,
213 213 anything else is treated as a revision)
214 214
215 215 branch: branches to clone
216 216 """
217 217
218 218 if isinstance(source, str):
219 219 origsource = ui.expandpath(source)
220 220 source, branch = parseurl(origsource, branch)
221 221 src_repo = repository(ui, source)
222 222 else:
223 223 src_repo = source
224 224 branch = (None, branch or [])
225 225 origsource = source = src_repo.url()
226 226 rev, checkout = addbranchrevs(src_repo, src_repo, branch, rev)
227 227
228 228 if dest is None:
229 229 dest = defaultdest(source)
230 230 ui.status(_("destination directory: %s\n") % dest)
231 231 else:
232 232 dest = ui.expandpath(dest)
233 233
234 234 dest = localpath(dest)
235 235 source = localpath(source)
236 236
237 237 if os.path.exists(dest):
238 238 if not os.path.isdir(dest):
239 239 raise util.Abort(_("destination '%s' already exists") % dest)
240 240 elif os.listdir(dest):
241 241 raise util.Abort(_("destination '%s' is not empty") % dest)
242 242
243 243 class DirCleanup(object):
244 244 def __init__(self, dir_):
245 245 self.rmtree = shutil.rmtree
246 246 self.dir_ = dir_
247 247 def close(self):
248 248 self.dir_ = None
249 249 def cleanup(self):
250 250 if self.dir_:
251 251 self.rmtree(self.dir_, True)
252 252
253 253 src_lock = dest_lock = dir_cleanup = None
254 254 try:
255 255 if islocal(dest):
256 256 dir_cleanup = DirCleanup(dest)
257 257
258 258 abspath = origsource
259 259 copy = False
260 260 if src_repo.cancopy() and islocal(dest):
261 261 abspath = os.path.abspath(util.drop_scheme('file', origsource))
262 262 copy = not pull and not rev
263 263
264 264 if copy:
265 265 try:
266 266 # we use a lock here because if we race with commit, we
267 267 # can end up with extra data in the cloned revlogs that's
268 268 # not pointed to by changesets, thus causing verify to
269 269 # fail
270 270 src_lock = src_repo.lock(wait=False)
271 271 except error.LockError:
272 272 copy = False
273 273
274 274 if copy:
275 275 src_repo.hook('preoutgoing', throw=True, source='clone')
276 276 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
277 277 if not os.path.exists(dest):
278 278 os.mkdir(dest)
279 279 else:
280 280 # only clean up directories we create ourselves
281 281 dir_cleanup.dir_ = hgdir
282 282 try:
283 283 dest_path = hgdir
284 284 os.mkdir(dest_path)
285 285 except OSError, inst:
286 286 if inst.errno == errno.EEXIST:
287 287 dir_cleanup.close()
288 288 raise util.Abort(_("destination '%s' already exists")
289 289 % dest)
290 290 raise
291 291
292 292 hardlink = None
293 293 num = 0
294 294 for f in src_repo.store.copylist():
295 295 src = os.path.join(src_repo.sharedpath, f)
296 296 dst = os.path.join(dest_path, f)
297 297 dstbase = os.path.dirname(dst)
298 298 if dstbase and not os.path.exists(dstbase):
299 299 os.mkdir(dstbase)
300 300 if os.path.exists(src):
301 301 if dst.endswith('data'):
302 302 # lock to avoid premature writing to the target
303 303 dest_lock = lock.lock(os.path.join(dstbase, "lock"))
304 304 hardlink, n = util.copyfiles(src, dst, hardlink)
305 305 num += n
306 306 if hardlink:
307 307 ui.debug("linked %d files\n" % num)
308 308 else:
309 309 ui.debug("copied %d files\n" % num)
310 310
311 311 # we need to re-init the repo after manually copying the data
312 312 # into it
313 313 dest_repo = repository(ui, dest)
314 314 src_repo.hook('outgoing', source='clone',
315 315 node=node.hex(node.nullid))
316 316 else:
317 317 try:
318 318 dest_repo = repository(ui, dest, create=True)
319 319 except OSError, inst:
320 320 if inst.errno == errno.EEXIST:
321 321 dir_cleanup.close()
322 322 raise util.Abort(_("destination '%s' already exists")
323 323 % dest)
324 324 raise
325 325
326 326 revs = None
327 327 if rev:
328 328 if 'lookup' not in src_repo.capabilities:
329 329 raise util.Abort(_("src repository does not support "
330 330 "revision lookup and so doesn't "
331 331 "support clone by revision"))
332 332 revs = [src_repo.lookup(r) for r in rev]
333 333 checkout = revs[0]
334 334 if dest_repo.local():
335 335 dest_repo.clone(src_repo, heads=revs, stream=stream)
336 336 elif src_repo.local():
337 337 src_repo.push(dest_repo, revs=revs)
338 338 else:
339 339 raise util.Abort(_("clone from remote to remote not supported"))
340 340
341 341 if dir_cleanup:
342 342 dir_cleanup.close()
343 343
344 344 if dest_repo.local():
345 345 fp = dest_repo.opener("hgrc", "w", text=True)
346 346 fp.write("[paths]\n")
347 347 fp.write("default = %s\n" % abspath)
348 348 fp.close()
349 349
350 350 dest_repo.ui.setconfig('paths', 'default', abspath)
351 351
352 352 if update:
353 353 if update is not True:
354 354 checkout = update
355 355 if src_repo.local():
356 356 checkout = src_repo.lookup(update)
357 357 for test in (checkout, 'default', 'tip'):
358 358 if test is None:
359 359 continue
360 360 try:
361 361 uprev = dest_repo.lookup(test)
362 362 break
363 363 except error.RepoLookupError:
364 364 continue
365 365 bn = dest_repo[uprev].branch()
366 366 dest_repo.ui.status(_("updating to branch %s\n") % bn)
367 367 _update(dest_repo, uprev)
368 368
369 369 return src_repo, dest_repo
370 370 finally:
371 371 release(src_lock, dest_lock)
372 372 if dir_cleanup is not None:
373 373 dir_cleanup.cleanup()
374 374
375 375 def _showstats(repo, stats):
376 376 repo.ui.status(_("%d files updated, %d files merged, "
377 377 "%d files removed, %d files unresolved\n") % stats)
378 378
379 379 def update(repo, node):
380 380 """update the working directory to node, merging linear changes"""
381 381 stats = mergemod.update(repo, node, False, False, None)
382 382 _showstats(repo, stats)
383 383 if stats[3]:
384 384 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
385 385 return stats[3] > 0
386 386
387 387 # naming conflict in clone()
388 388 _update = update
389 389
390 390 def clean(repo, node, show_stats=True):
391 391 """forcibly switch the working directory to node, clobbering changes"""
392 392 stats = mergemod.update(repo, node, False, True, None)
393 393 if show_stats:
394 394 _showstats(repo, stats)
395 395 return stats[3] > 0
396 396
397 397 def merge(repo, node, force=None, remind=True):
398 398 """Branch merge with node, resolving changes. Return true if any
399 399 unresolved conflicts."""
400 400 stats = mergemod.update(repo, node, True, force, False)
401 401 _showstats(repo, stats)
402 402 if stats[3]:
403 403 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
404 404 "or 'hg update -C .' to abandon\n"))
405 405 elif remind:
406 406 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
407 407 return stats[3] > 0
408 408
409 409 def _incoming(displaychlist, subreporecurse, ui, repo, source,
410 410 opts, buffered=False):
411 411 """
412 412 Helper for incoming / gincoming.
413 413 displaychlist gets called with
414 414 (remoterepo, incomingchangesetlist, displayer) parameters,
415 415 and is supposed to contain only code that can't be unified.
416 416 """
417 417 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
418 418 other = repository(remoteui(repo, opts), source)
419 419 ui.status(_('comparing with %s\n') % url.hidepassword(source))
420 420 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
421 421
422 422 if revs:
423 423 revs = [other.lookup(rev) for rev in revs]
424 424 other, incoming, bundle = bundlerepo.getremotechanges(ui, repo, other, revs,
425 425 opts["bundle"], opts["force"])
426 426 if incoming is None:
427 427 ui.status(_("no changes found\n"))
428 428 return subreporecurse()
429 429
430 430 try:
431 431 chlist = other.changelog.nodesbetween(incoming, revs)[0]
432 432 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
433 433
434 434 # XXX once graphlog extension makes it into core,
435 435 # should be replaced by a if graph/else
436 436 displaychlist(other, chlist, displayer)
437 437
438 438 displayer.close()
439 439 finally:
440 440 if hasattr(other, 'close'):
441 441 other.close()
442 442 if bundle:
443 443 os.unlink(bundle)
444 444 subreporecurse()
445 445 return 0 # exit code is zero since we found incoming changes
446 446
447 447 def incoming(ui, repo, source, opts):
448 448 def subreporecurse():
449 449 ret = 1
450 450 if opts.get('subrepos'):
451 451 ctx = repo[None]
452 452 for subpath in sorted(ctx.substate):
453 453 sub = ctx.sub(subpath)
454 454 ret = min(ret, sub.incoming(ui, source, opts))
455 455 return ret
456 456
457 457 def display(other, chlist, displayer):
458 458 limit = cmdutil.loglimit(opts)
459 459 if opts.get('newest_first'):
460 460 chlist.reverse()
461 461 count = 0
462 462 for n in chlist:
463 463 if limit is not None and count >= limit:
464 464 break
465 465 parents = [p for p in other.changelog.parents(n) if p != nullid]
466 466 if opts.get('no_merges') and len(parents) == 2:
467 467 continue
468 468 count += 1
469 469 displayer.show(other[n])
470 470 return _incoming(display, subreporecurse, ui, repo, source, opts)
471 471
472 472 def _outgoing(ui, repo, dest, opts):
473 473 dest = ui.expandpath(dest or 'default-push', dest or 'default')
474 474 dest, branches = parseurl(dest, opts.get('branch'))
475 475 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
476 476 if revs:
477 477 revs = [repo.lookup(rev) for rev in revs]
478 478
479 479 other = repository(remoteui(repo, opts), dest)
480 480 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
481 481 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
482 482 if not o:
483 483 ui.status(_("no changes found\n"))
484 484 return None
485 485
486 486 return repo.changelog.nodesbetween(o, revs)[0]
487 487
488 488 def outgoing(ui, repo, dest, opts):
489 489 def recurse():
490 490 ret = 1
491 491 if opts.get('subrepos'):
492 492 ctx = repo[None]
493 493 for subpath in sorted(ctx.substate):
494 494 sub = ctx.sub(subpath)
495 495 ret = min(ret, sub.outgoing(ui, dest, opts))
496 496 return ret
497 497
498 498 limit = cmdutil.loglimit(opts)
499 499 o = _outgoing(ui, repo, dest, opts)
500 500 if o is None:
501 501 return recurse()
502 502
503 503 if opts.get('newest_first'):
504 504 o.reverse()
505 505 displayer = cmdutil.show_changeset(ui, repo, opts)
506 506 count = 0
507 507 for n in o:
508 508 if limit is not None and count >= limit:
509 509 break
510 510 parents = [p for p in repo.changelog.parents(n) if p != nullid]
511 511 if opts.get('no_merges') and len(parents) == 2:
512 512 continue
513 513 count += 1
514 514 displayer.show(repo[n])
515 515 displayer.close()
516 516 recurse()
517 517 return 0 # exit code is zero since we found outgoing changes
518 518
519 519 def revert(repo, node, choose):
520 520 """revert changes to revision in node without updating dirstate"""
521 521 return mergemod.update(repo, node, False, True, choose)[3] > 0
522 522
523 523 def verify(repo):
524 524 """verify the consistency of a repository"""
525 525 return verifymod.verify(repo)
526 526
527 527 def remoteui(src, opts):
528 528 'build a remote ui from ui or repo and opts'
529 529 if hasattr(src, 'baseui'): # looks like a repository
530 530 dst = src.baseui.copy() # drop repo-specific config
531 531 src = src.ui # copy target options from repo
532 532 else: # assume it's a global ui object
533 533 dst = src.copy() # keep all global options
534 534
535 535 # copy ssh-specific options
536 536 for o in 'ssh', 'remotecmd':
537 537 v = opts.get(o) or src.config('ui', o)
538 538 if v:
539 539 dst.setconfig("ui", o, v)
540 540
541 541 # copy bundle-specific options
542 542 r = src.config('bundle', 'mainreporoot')
543 543 if r:
544 544 dst.setconfig('bundle', 'mainreporoot', r)
545 545
546 546 # copy selected local settings to the remote ui
547 547 for sect in ('auth', 'http_proxy'):
548 548 for key, val in src.configitems(sect):
549 549 dst.setconfig(sect, key, val)
550 550 v = src.config('web', 'cacerts')
551 551 if v:
552 dst.setconfig('web', 'cacerts', v)
552 dst.setconfig('web', 'cacerts', util.expandpath(v))
553 553
554 554 return dst
@@ -1,719 +1,721 b''
1 1 # url.py - HTTP handling for mercurial
2 2 #
3 3 # Copyright 2005, 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
4 4 # Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br>
5 5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
6 6 #
7 7 # This software may be used and distributed according to the terms of the
8 8 # GNU General Public License version 2 or any later version.
9 9
10 10 import urllib, urllib2, urlparse, httplib, os, re, socket, cStringIO
11 11 import __builtin__
12 12 from i18n import _
13 13 import keepalive, util
14 14
15 15 def _urlunparse(scheme, netloc, path, params, query, fragment, url):
16 16 '''Handle cases where urlunparse(urlparse(x://)) doesn't preserve the "//"'''
17 17 result = urlparse.urlunparse((scheme, netloc, path, params, query, fragment))
18 18 if (scheme and
19 19 result.startswith(scheme + ':') and
20 20 not result.startswith(scheme + '://') and
21 21 url.startswith(scheme + '://')
22 22 ):
23 23 result = scheme + '://' + result[len(scheme + ':'):]
24 24 return result
25 25
26 26 def hidepassword(url):
27 27 '''hide user credential in a url string'''
28 28 scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
29 29 netloc = re.sub('([^:]*):([^@]*)@(.*)', r'\1:***@\3', netloc)
30 30 return _urlunparse(scheme, netloc, path, params, query, fragment, url)
31 31
32 32 def removeauth(url):
33 33 '''remove all authentication information from a url string'''
34 34 scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
35 35 netloc = netloc[netloc.find('@')+1:]
36 36 return _urlunparse(scheme, netloc, path, params, query, fragment, url)
37 37
38 38 def netlocsplit(netloc):
39 39 '''split [user[:passwd]@]host[:port] into 4-tuple.'''
40 40
41 41 a = netloc.find('@')
42 42 if a == -1:
43 43 user, passwd = None, None
44 44 else:
45 45 userpass, netloc = netloc[:a], netloc[a + 1:]
46 46 c = userpass.find(':')
47 47 if c == -1:
48 48 user, passwd = urllib.unquote(userpass), None
49 49 else:
50 50 user = urllib.unquote(userpass[:c])
51 51 passwd = urllib.unquote(userpass[c + 1:])
52 52 c = netloc.find(':')
53 53 if c == -1:
54 54 host, port = netloc, None
55 55 else:
56 56 host, port = netloc[:c], netloc[c + 1:]
57 57 return host, port, user, passwd
58 58
59 59 def netlocunsplit(host, port, user=None, passwd=None):
60 60 '''turn host, port, user, passwd into [user[:passwd]@]host[:port].'''
61 61 if port:
62 62 hostport = host + ':' + port
63 63 else:
64 64 hostport = host
65 65 if user:
66 66 quote = lambda s: urllib.quote(s, safe='')
67 67 if passwd:
68 68 userpass = quote(user) + ':' + quote(passwd)
69 69 else:
70 70 userpass = quote(user)
71 71 return userpass + '@' + hostport
72 72 return hostport
73 73
74 74 _safe = ('abcdefghijklmnopqrstuvwxyz'
75 75 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
76 76 '0123456789' '_.-/')
77 77 _safeset = None
78 78 _hex = None
79 79 def quotepath(path):
80 80 '''quote the path part of a URL
81 81
82 82 This is similar to urllib.quote, but it also tries to avoid
83 83 quoting things twice (inspired by wget):
84 84
85 85 >>> quotepath('abc def')
86 86 'abc%20def'
87 87 >>> quotepath('abc%20def')
88 88 'abc%20def'
89 89 >>> quotepath('abc%20 def')
90 90 'abc%20%20def'
91 91 >>> quotepath('abc def%20')
92 92 'abc%20def%20'
93 93 >>> quotepath('abc def%2')
94 94 'abc%20def%252'
95 95 >>> quotepath('abc def%')
96 96 'abc%20def%25'
97 97 '''
98 98 global _safeset, _hex
99 99 if _safeset is None:
100 100 _safeset = set(_safe)
101 101 _hex = set('abcdefABCDEF0123456789')
102 102 l = list(path)
103 103 for i in xrange(len(l)):
104 104 c = l[i]
105 105 if (c == '%' and i + 2 < len(l) and
106 106 l[i + 1] in _hex and l[i + 2] in _hex):
107 107 pass
108 108 elif c not in _safeset:
109 109 l[i] = '%%%02X' % ord(c)
110 110 return ''.join(l)
111 111
112 112 class passwordmgr(urllib2.HTTPPasswordMgrWithDefaultRealm):
113 113 def __init__(self, ui):
114 114 urllib2.HTTPPasswordMgrWithDefaultRealm.__init__(self)
115 115 self.ui = ui
116 116
117 117 def find_user_password(self, realm, authuri):
118 118 authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
119 119 self, realm, authuri)
120 120 user, passwd = authinfo
121 121 if user and passwd:
122 122 self._writedebug(user, passwd)
123 123 return (user, passwd)
124 124
125 125 if not user:
126 126 auth = self.readauthtoken(authuri)
127 127 if auth:
128 128 user, passwd = auth.get('username'), auth.get('password')
129 129 if not user or not passwd:
130 130 if not self.ui.interactive():
131 131 raise util.Abort(_('http authorization required'))
132 132
133 133 self.ui.write(_("http authorization required\n"))
134 134 self.ui.write(_("realm: %s\n") % realm)
135 135 if user:
136 136 self.ui.write(_("user: %s\n") % user)
137 137 else:
138 138 user = self.ui.prompt(_("user:"), default=None)
139 139
140 140 if not passwd:
141 141 passwd = self.ui.getpass()
142 142
143 143 self.add_password(realm, authuri, user, passwd)
144 144 self._writedebug(user, passwd)
145 145 return (user, passwd)
146 146
147 147 def _writedebug(self, user, passwd):
148 148 msg = _('http auth: user %s, password %s\n')
149 149 self.ui.debug(msg % (user, passwd and '*' * len(passwd) or 'not set'))
150 150
151 151 def readauthtoken(self, uri):
152 152 # Read configuration
153 153 config = dict()
154 154 for key, val in self.ui.configitems('auth'):
155 155 if '.' not in key:
156 156 self.ui.warn(_("ignoring invalid [auth] key '%s'\n") % key)
157 157 continue
158 158 group, setting = key.split('.', 1)
159 159 gdict = config.setdefault(group, dict())
160 160 if setting in ('username', 'cert', 'key'):
161 161 val = util.expandpath(val)
162 162 gdict[setting] = val
163 163
164 164 # Find the best match
165 165 scheme, hostpath = uri.split('://', 1)
166 166 bestlen = 0
167 167 bestauth = None
168 168 for auth in config.itervalues():
169 169 prefix = auth.get('prefix')
170 170 if not prefix:
171 171 continue
172 172 p = prefix.split('://', 1)
173 173 if len(p) > 1:
174 174 schemes, prefix = [p[0]], p[1]
175 175 else:
176 176 schemes = (auth.get('schemes') or 'https').split()
177 177 if (prefix == '*' or hostpath.startswith(prefix)) and \
178 178 len(prefix) > bestlen and scheme in schemes:
179 179 bestlen = len(prefix)
180 180 bestauth = auth
181 181 return bestauth
182 182
183 183 class proxyhandler(urllib2.ProxyHandler):
184 184 def __init__(self, ui):
185 185 proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
186 186 # XXX proxyauthinfo = None
187 187
188 188 if proxyurl:
189 189 # proxy can be proper url or host[:port]
190 190 if not (proxyurl.startswith('http:') or
191 191 proxyurl.startswith('https:')):
192 192 proxyurl = 'http://' + proxyurl + '/'
193 193 snpqf = urlparse.urlsplit(proxyurl)
194 194 proxyscheme, proxynetloc, proxypath, proxyquery, proxyfrag = snpqf
195 195 hpup = netlocsplit(proxynetloc)
196 196
197 197 proxyhost, proxyport, proxyuser, proxypasswd = hpup
198 198 if not proxyuser:
199 199 proxyuser = ui.config("http_proxy", "user")
200 200 proxypasswd = ui.config("http_proxy", "passwd")
201 201
202 202 # see if we should use a proxy for this url
203 203 no_list = ["localhost", "127.0.0.1"]
204 204 no_list.extend([p.lower() for
205 205 p in ui.configlist("http_proxy", "no")])
206 206 no_list.extend([p.strip().lower() for
207 207 p in os.getenv("no_proxy", '').split(',')
208 208 if p.strip()])
209 209 # "http_proxy.always" config is for running tests on localhost
210 210 if ui.configbool("http_proxy", "always"):
211 211 self.no_list = []
212 212 else:
213 213 self.no_list = no_list
214 214
215 215 proxyurl = urlparse.urlunsplit((
216 216 proxyscheme, netlocunsplit(proxyhost, proxyport,
217 217 proxyuser, proxypasswd or ''),
218 218 proxypath, proxyquery, proxyfrag))
219 219 proxies = {'http': proxyurl, 'https': proxyurl}
220 220 ui.debug('proxying through http://%s:%s\n' %
221 221 (proxyhost, proxyport))
222 222 else:
223 223 proxies = {}
224 224
225 225 # urllib2 takes proxy values from the environment and those
226 226 # will take precedence if found, so drop them
227 227 for env in ["HTTP_PROXY", "http_proxy", "no_proxy"]:
228 228 try:
229 229 if env in os.environ:
230 230 del os.environ[env]
231 231 except OSError:
232 232 pass
233 233
234 234 urllib2.ProxyHandler.__init__(self, proxies)
235 235 self.ui = ui
236 236
237 237 def proxy_open(self, req, proxy, type_):
238 238 host = req.get_host().split(':')[0]
239 239 if host in self.no_list:
240 240 return None
241 241
242 242 # work around a bug in Python < 2.4.2
243 243 # (it leaves a "\n" at the end of Proxy-authorization headers)
244 244 baseclass = req.__class__
245 245 class _request(baseclass):
246 246 def add_header(self, key, val):
247 247 if key.lower() == 'proxy-authorization':
248 248 val = val.strip()
249 249 return baseclass.add_header(self, key, val)
250 250 req.__class__ = _request
251 251
252 252 return urllib2.ProxyHandler.proxy_open(self, req, proxy, type_)
253 253
254 254 class httpsendfile(object):
255 255 """This is a wrapper around the objects returned by python's "open".
256 256
257 257 Its purpose is to send file-like objects via HTTP and, to do so, it
258 258 defines a __len__ attribute to feed the Content-Length header.
259 259 """
260 260
261 261 def __init__(self, ui, *args, **kwargs):
262 262 # We can't just "self._data = open(*args, **kwargs)" here because there
263 263 # is an "open" function defined in this module that shadows the global
264 264 # one
265 265 self.ui = ui
266 266 self._data = __builtin__.open(*args, **kwargs)
267 267 self.seek = self._data.seek
268 268 self.close = self._data.close
269 269 self.write = self._data.write
270 270 self._len = os.fstat(self._data.fileno()).st_size
271 271 self._pos = 0
272 272 self._total = len(self) / 1024 * 2
273 273
274 274 def read(self, *args, **kwargs):
275 275 try:
276 276 ret = self._data.read(*args, **kwargs)
277 277 except EOFError:
278 278 self.ui.progress(_('sending'), None)
279 279 self._pos += len(ret)
280 280 # We pass double the max for total because we currently have
281 281 # to send the bundle twice in the case of a server that
282 282 # requires authentication. Since we can't know until we try
283 283 # once whether authentication will be required, just lie to
284 284 # the user and maybe the push succeeds suddenly at 50%.
285 285 self.ui.progress(_('sending'), self._pos / 1024,
286 286 unit=_('kb'), total=self._total)
287 287 return ret
288 288
289 289 def __len__(self):
290 290 return self._len
291 291
292 292 def _gen_sendfile(connection):
293 293 def _sendfile(self, data):
294 294 # send a file
295 295 if isinstance(data, httpsendfile):
296 296 # if auth required, some data sent twice, so rewind here
297 297 data.seek(0)
298 298 for chunk in util.filechunkiter(data):
299 299 connection.send(self, chunk)
300 300 else:
301 301 connection.send(self, data)
302 302 return _sendfile
303 303
304 304 has_https = hasattr(urllib2, 'HTTPSHandler')
305 305 if has_https:
306 306 try:
307 307 # avoid using deprecated/broken FakeSocket in python 2.6
308 308 import ssl
309 309 _ssl_wrap_socket = ssl.wrap_socket
310 310 CERT_REQUIRED = ssl.CERT_REQUIRED
311 311 except ImportError:
312 312 CERT_REQUIRED = 2
313 313
314 314 def _ssl_wrap_socket(sock, key_file, cert_file,
315 315 cert_reqs=CERT_REQUIRED, ca_certs=None):
316 316 if ca_certs:
317 317 raise util.Abort(_(
318 318 'certificate checking requires Python 2.6'))
319 319
320 320 ssl = socket.ssl(sock, key_file, cert_file)
321 321 return httplib.FakeSocket(sock, ssl)
322 322
323 323 try:
324 324 _create_connection = socket.create_connection
325 325 except AttributeError:
326 326 _GLOBAL_DEFAULT_TIMEOUT = object()
327 327
328 328 def _create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
329 329 source_address=None):
330 330 # lifted from Python 2.6
331 331
332 332 msg = "getaddrinfo returns an empty list"
333 333 host, port = address
334 334 for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
335 335 af, socktype, proto, canonname, sa = res
336 336 sock = None
337 337 try:
338 338 sock = socket.socket(af, socktype, proto)
339 339 if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
340 340 sock.settimeout(timeout)
341 341 if source_address:
342 342 sock.bind(source_address)
343 343 sock.connect(sa)
344 344 return sock
345 345
346 346 except socket.error, msg:
347 347 if sock is not None:
348 348 sock.close()
349 349
350 350 raise socket.error, msg
351 351
352 352 class httpconnection(keepalive.HTTPConnection):
353 353 # must be able to send big bundle as stream.
354 354 send = _gen_sendfile(keepalive.HTTPConnection)
355 355
356 356 def connect(self):
357 357 if has_https and self.realhostport: # use CONNECT proxy
358 358 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
359 359 self.sock.connect((self.host, self.port))
360 360 if _generic_proxytunnel(self):
361 361 # we do not support client x509 certificates
362 362 self.sock = _ssl_wrap_socket(self.sock, None, None)
363 363 else:
364 364 keepalive.HTTPConnection.connect(self)
365 365
366 366 def getresponse(self):
367 367 proxyres = getattr(self, 'proxyres', None)
368 368 if proxyres:
369 369 if proxyres.will_close:
370 370 self.close()
371 371 self.proxyres = None
372 372 return proxyres
373 373 return keepalive.HTTPConnection.getresponse(self)
374 374
375 375 # general transaction handler to support different ways to handle
376 376 # HTTPS proxying before and after Python 2.6.3.
377 377 def _generic_start_transaction(handler, h, req):
378 378 if hasattr(req, '_tunnel_host') and req._tunnel_host:
379 379 tunnel_host = req._tunnel_host
380 380 if tunnel_host[:7] not in ['http://', 'https:/']:
381 381 tunnel_host = 'https://' + tunnel_host
382 382 new_tunnel = True
383 383 else:
384 384 tunnel_host = req.get_selector()
385 385 new_tunnel = False
386 386
387 387 if new_tunnel or tunnel_host == req.get_full_url(): # has proxy
388 388 urlparts = urlparse.urlparse(tunnel_host)
389 389 if new_tunnel or urlparts[0] == 'https': # only use CONNECT for HTTPS
390 390 realhostport = urlparts[1]
391 391 if realhostport[-1] == ']' or ':' not in realhostport:
392 392 realhostport += ':443'
393 393
394 394 h.realhostport = realhostport
395 395 h.headers = req.headers.copy()
396 396 h.headers.update(handler.parent.addheaders)
397 397 return
398 398
399 399 h.realhostport = None
400 400 h.headers = None
401 401
402 402 def _generic_proxytunnel(self):
403 403 proxyheaders = dict(
404 404 [(x, self.headers[x]) for x in self.headers
405 405 if x.lower().startswith('proxy-')])
406 406 self._set_hostport(self.host, self.port)
407 407 self.send('CONNECT %s HTTP/1.0\r\n' % self.realhostport)
408 408 for header in proxyheaders.iteritems():
409 409 self.send('%s: %s\r\n' % header)
410 410 self.send('\r\n')
411 411
412 412 # majority of the following code is duplicated from
413 413 # httplib.HTTPConnection as there are no adequate places to
414 414 # override functions to provide the needed functionality
415 415 res = self.response_class(self.sock,
416 416 strict=self.strict,
417 417 method=self._method)
418 418
419 419 while True:
420 420 version, status, reason = res._read_status()
421 421 if status != httplib.CONTINUE:
422 422 break
423 423 while True:
424 424 skip = res.fp.readline().strip()
425 425 if not skip:
426 426 break
427 427 res.status = status
428 428 res.reason = reason.strip()
429 429
430 430 if res.status == 200:
431 431 while True:
432 432 line = res.fp.readline()
433 433 if line == '\r\n':
434 434 break
435 435 return True
436 436
437 437 if version == 'HTTP/1.0':
438 438 res.version = 10
439 439 elif version.startswith('HTTP/1.'):
440 440 res.version = 11
441 441 elif version == 'HTTP/0.9':
442 442 res.version = 9
443 443 else:
444 444 raise httplib.UnknownProtocol(version)
445 445
446 446 if res.version == 9:
447 447 res.length = None
448 448 res.chunked = 0
449 449 res.will_close = 1
450 450 res.msg = httplib.HTTPMessage(cStringIO.StringIO())
451 451 return False
452 452
453 453 res.msg = httplib.HTTPMessage(res.fp)
454 454 res.msg.fp = None
455 455
456 456 # are we using the chunked-style of transfer encoding?
457 457 trenc = res.msg.getheader('transfer-encoding')
458 458 if trenc and trenc.lower() == "chunked":
459 459 res.chunked = 1
460 460 res.chunk_left = None
461 461 else:
462 462 res.chunked = 0
463 463
464 464 # will the connection close at the end of the response?
465 465 res.will_close = res._check_close()
466 466
467 467 # do we have a Content-Length?
468 468 # NOTE: RFC 2616, S4.4, #3 says we ignore this if tr_enc is "chunked"
469 469 length = res.msg.getheader('content-length')
470 470 if length and not res.chunked:
471 471 try:
472 472 res.length = int(length)
473 473 except ValueError:
474 474 res.length = None
475 475 else:
476 476 if res.length < 0: # ignore nonsensical negative lengths
477 477 res.length = None
478 478 else:
479 479 res.length = None
480 480
481 481 # does the body have a fixed length? (of zero)
482 482 if (status == httplib.NO_CONTENT or status == httplib.NOT_MODIFIED or
483 483 100 <= status < 200 or # 1xx codes
484 484 res._method == 'HEAD'):
485 485 res.length = 0
486 486
487 487 # if the connection remains open, and we aren't using chunked, and
488 488 # a content-length was not provided, then assume that the connection
489 489 # WILL close.
490 490 if (not res.will_close and
491 491 not res.chunked and
492 492 res.length is None):
493 493 res.will_close = 1
494 494
495 495 self.proxyres = res
496 496
497 497 return False
498 498
499 499 class httphandler(keepalive.HTTPHandler):
500 500 def http_open(self, req):
501 501 return self.do_open(httpconnection, req)
502 502
503 503 def _start_transaction(self, h, req):
504 504 _generic_start_transaction(self, h, req)
505 505 return keepalive.HTTPHandler._start_transaction(self, h, req)
506 506
507 507 def _verifycert(cert, hostname):
508 508 '''Verify that cert (in socket.getpeercert() format) matches hostname.
509 509 CRLs and subjectAltName are not handled.
510 510
511 511 Returns error message if any problems are found and None on success.
512 512 '''
513 513 if not cert:
514 514 return _('no certificate received')
515 515 dnsname = hostname.lower()
516 516 for s in cert.get('subject', []):
517 517 key, value = s[0]
518 518 if key == 'commonName':
519 519 certname = value.lower()
520 520 if (certname == dnsname or
521 521 '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1]):
522 522 return None
523 523 return _('certificate is for %s') % certname
524 524 return _('no commonName found in certificate')
525 525
526 526 if has_https:
527 527 class BetterHTTPS(httplib.HTTPSConnection):
528 528 send = keepalive.safesend
529 529
530 530 def connect(self):
531 531 if hasattr(self, 'ui'):
532 532 cacerts = self.ui.config('web', 'cacerts')
533 if cacerts:
534 cacerts = util.expandpath(cacerts)
533 535 else:
534 536 cacerts = None
535 537
536 538 if cacerts:
537 539 sock = _create_connection((self.host, self.port))
538 540 self.sock = _ssl_wrap_socket(sock, self.key_file,
539 541 self.cert_file, cert_reqs=CERT_REQUIRED,
540 542 ca_certs=cacerts)
541 543 msg = _verifycert(self.sock.getpeercert(), self.host)
542 544 if msg:
543 545 raise util.Abort(_('%s certificate error: %s') %
544 546 (self.host, msg))
545 547 self.ui.debug('%s certificate successfully verified\n' %
546 548 self.host)
547 549 else:
548 550 self.ui.warn(_("warning: %s certificate not verified "
549 551 "(check web.cacerts config setting)\n") %
550 552 self.host)
551 553 httplib.HTTPSConnection.connect(self)
552 554
553 555 class httpsconnection(BetterHTTPS):
554 556 response_class = keepalive.HTTPResponse
555 557 # must be able to send big bundle as stream.
556 558 send = _gen_sendfile(BetterHTTPS)
557 559 getresponse = keepalive.wrapgetresponse(httplib.HTTPSConnection)
558 560
559 561 def connect(self):
560 562 if self.realhostport: # use CONNECT proxy
561 563 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
562 564 self.sock.connect((self.host, self.port))
563 565 if _generic_proxytunnel(self):
564 566 self.sock = _ssl_wrap_socket(self.sock, self.key_file,
565 567 self.cert_file)
566 568 else:
567 569 BetterHTTPS.connect(self)
568 570
569 571 class httpshandler(keepalive.KeepAliveHandler, urllib2.HTTPSHandler):
570 572 def __init__(self, ui):
571 573 keepalive.KeepAliveHandler.__init__(self)
572 574 urllib2.HTTPSHandler.__init__(self)
573 575 self.ui = ui
574 576 self.pwmgr = passwordmgr(self.ui)
575 577
576 578 def _start_transaction(self, h, req):
577 579 _generic_start_transaction(self, h, req)
578 580 return keepalive.KeepAliveHandler._start_transaction(self, h, req)
579 581
580 582 def https_open(self, req):
581 583 self.auth = self.pwmgr.readauthtoken(req.get_full_url())
582 584 return self.do_open(self._makeconnection, req)
583 585
584 586 def _makeconnection(self, host, port=None, *args, **kwargs):
585 587 keyfile = None
586 588 certfile = None
587 589
588 590 if len(args) >= 1: # key_file
589 591 keyfile = args[0]
590 592 if len(args) >= 2: # cert_file
591 593 certfile = args[1]
592 594 args = args[2:]
593 595
594 596 # if the user has specified different key/cert files in
595 597 # hgrc, we prefer these
596 598 if self.auth and 'key' in self.auth and 'cert' in self.auth:
597 599 keyfile = self.auth['key']
598 600 certfile = self.auth['cert']
599 601
600 602 conn = httpsconnection(host, port, keyfile, certfile, *args, **kwargs)
601 603 conn.ui = self.ui
602 604 return conn
603 605
604 606 class httpdigestauthhandler(urllib2.HTTPDigestAuthHandler):
605 607 def __init__(self, *args, **kwargs):
606 608 urllib2.HTTPDigestAuthHandler.__init__(self, *args, **kwargs)
607 609 self.retried_req = None
608 610
609 611 def reset_retry_count(self):
610 612 # Python 2.6.5 will call this on 401 or 407 errors and thus loop
611 613 # forever. We disable reset_retry_count completely and reset in
612 614 # http_error_auth_reqed instead.
613 615 pass
614 616
615 617 def http_error_auth_reqed(self, auth_header, host, req, headers):
616 618 # Reset the retry counter once for each request.
617 619 if req is not self.retried_req:
618 620 self.retried_req = req
619 621 self.retried = 0
620 622 # In python < 2.5 AbstractDigestAuthHandler raises a ValueError if
621 623 # it doesn't know about the auth type requested. This can happen if
622 624 # somebody is using BasicAuth and types a bad password.
623 625 try:
624 626 return urllib2.HTTPDigestAuthHandler.http_error_auth_reqed(
625 627 self, auth_header, host, req, headers)
626 628 except ValueError, inst:
627 629 arg = inst.args[0]
628 630 if arg.startswith("AbstractDigestAuthHandler doesn't know "):
629 631 return
630 632 raise
631 633
632 634 class httpbasicauthhandler(urllib2.HTTPBasicAuthHandler):
633 635 def __init__(self, *args, **kwargs):
634 636 urllib2.HTTPBasicAuthHandler.__init__(self, *args, **kwargs)
635 637 self.retried_req = None
636 638
637 639 def reset_retry_count(self):
638 640 # Python 2.6.5 will call this on 401 or 407 errors and thus loop
639 641 # forever. We disable reset_retry_count completely and reset in
640 642 # http_error_auth_reqed instead.
641 643 pass
642 644
643 645 def http_error_auth_reqed(self, auth_header, host, req, headers):
644 646 # Reset the retry counter once for each request.
645 647 if req is not self.retried_req:
646 648 self.retried_req = req
647 649 self.retried = 0
648 650 return urllib2.HTTPBasicAuthHandler.http_error_auth_reqed(
649 651 self, auth_header, host, req, headers)
650 652
651 653 def getauthinfo(path):
652 654 scheme, netloc, urlpath, query, frag = urlparse.urlsplit(path)
653 655 if not urlpath:
654 656 urlpath = '/'
655 657 if scheme != 'file':
656 658 # XXX: why are we quoting the path again with some smart
657 659 # heuristic here? Anyway, it cannot be done with file://
658 660 # urls since path encoding is os/fs dependent (see
659 661 # urllib.pathname2url() for details).
660 662 urlpath = quotepath(urlpath)
661 663 host, port, user, passwd = netlocsplit(netloc)
662 664
663 665 # urllib cannot handle URLs with embedded user or passwd
664 666 url = urlparse.urlunsplit((scheme, netlocunsplit(host, port),
665 667 urlpath, query, frag))
666 668 if user:
667 669 netloc = host
668 670 if port:
669 671 netloc += ':' + port
670 672 # Python < 2.4.3 uses only the netloc to search for a password
671 673 authinfo = (None, (url, netloc), user, passwd or '')
672 674 else:
673 675 authinfo = None
674 676 return url, authinfo
675 677
676 678 handlerfuncs = []
677 679
678 680 def opener(ui, authinfo=None):
679 681 '''
680 682 construct an opener suitable for urllib2
681 683 authinfo will be added to the password manager
682 684 '''
683 685 handlers = [httphandler()]
684 686 if has_https:
685 687 handlers.append(httpshandler(ui))
686 688
687 689 handlers.append(proxyhandler(ui))
688 690
689 691 passmgr = passwordmgr(ui)
690 692 if authinfo is not None:
691 693 passmgr.add_password(*authinfo)
692 694 user, passwd = authinfo[2:4]
693 695 ui.debug('http auth: user %s, password %s\n' %
694 696 (user, passwd and '*' * len(passwd) or 'not set'))
695 697
696 698 handlers.extend((httpbasicauthhandler(passmgr),
697 699 httpdigestauthhandler(passmgr)))
698 700 handlers.extend([h(ui, passmgr) for h in handlerfuncs])
699 701 opener = urllib2.build_opener(*handlers)
700 702
701 703 # 1.0 here is the _protocol_ version
702 704 opener.addheaders = [('User-agent', 'mercurial/proto-1.0')]
703 705 opener.addheaders.append(('Accept', 'application/mercurial-0.1'))
704 706 return opener
705 707
706 708 scheme_re = re.compile(r'^([a-zA-Z0-9+-.]+)://')
707 709
708 710 def open(ui, url, data=None):
709 711 scheme = None
710 712 m = scheme_re.search(url)
711 713 if m:
712 714 scheme = m.group(1).lower()
713 715 if not scheme:
714 716 path = util.normpath(os.path.abspath(url))
715 717 url = 'file://' + urllib.pathname2url(path)
716 718 authinfo = None
717 719 else:
718 720 url, authinfo = getauthinfo(url)
719 721 return opener(ui, authinfo).open(url, data)
@@ -1,429 +1,429 b''
1 1 $ "$TESTDIR/hghave" no-outer-repo || exit 80
2 2
3 3 $ hg init a
4 4 $ cd a
5 5 $ echo a > a
6 6 $ hg ci -A -d'1 0' -m a
7 7 adding a
8 8
9 9 $ cd ..
10 10
11 11 $ hg init b
12 12 $ cd b
13 13 $ echo b > b
14 14 $ hg ci -A -d'1 0' -m b
15 15 adding b
16 16
17 17 $ cd ..
18 18
19 19 $ hg clone a c
20 20 updating to branch default
21 21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 22 $ cd c
23 23 $ cat >> .hg/hgrc <<EOF
24 24 > [paths]
25 25 > relative = ../a
26 26 > EOF
27 27 $ hg pull -f ../b
28 28 pulling from ../b
29 29 searching for changes
30 30 warning: repository is unrelated
31 31 adding changesets
32 32 adding manifests
33 33 adding file changes
34 34 added 1 changesets with 1 changes to 1 files (+1 heads)
35 35 (run 'hg heads' to see heads, 'hg merge' to merge)
36 36 $ hg merge
37 37 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
38 38 (branch merge, don't forget to commit)
39 39
40 40 $ cd ..
41 41
42 42 Testing -R/--repository:
43 43
44 44 $ hg -R a tip
45 45 changeset: 0:8580ff50825a
46 46 tag: tip
47 47 user: test
48 48 date: Thu Jan 01 00:00:01 1970 +0000
49 49 summary: a
50 50
51 51 $ hg --repository b tip
52 52 changeset: 0:b6c483daf290
53 53 tag: tip
54 54 user: test
55 55 date: Thu Jan 01 00:00:01 1970 +0000
56 56 summary: b
57 57
58 58
59 59 -R with a URL:
60 60
61 61 $ hg -R file:a identify
62 62 8580ff50825a tip
63 63 $ hg -R file://localhost/`pwd`/a/ identify
64 64 8580ff50825a tip
65 65
66 66 -R with path aliases:
67 67
68 68 $ cd c
69 69 $ hg -R default identify
70 70 8580ff50825a tip
71 71 $ hg -R relative identify
72 72 8580ff50825a tip
73 73 $ echo '[paths]' >> $HGRCPATH
74 74 $ echo 'relativetohome = a' >> $HGRCPATH
75 75 $ HOME=`pwd`/../ hg -R relativetohome identify
76 76 8580ff50825a tip
77 77 $ cd ..
78 78
79 79 Implicit -R:
80 80
81 81 $ hg ann a/a
82 82 0: a
83 83 $ hg ann a/a a/a
84 84 0: a
85 85 $ hg ann a/a b/b
86 86 abort: There is no Mercurial repository here (.hg not found)!
87 87 [255]
88 88 $ hg -R b ann a/a
89 89 abort: a/a not under root
90 90 [255]
91 91 $ hg log
92 92 abort: There is no Mercurial repository here (.hg not found)!
93 93 [255]
94 94
95 95 Abbreviation of long option:
96 96
97 97 $ hg --repo c tip
98 98 changeset: 1:b6c483daf290
99 99 tag: tip
100 100 parent: -1:000000000000
101 101 user: test
102 102 date: Thu Jan 01 00:00:01 1970 +0000
103 103 summary: b
104 104
105 105
106 106 earlygetopt with duplicate options (36d23de02da1):
107 107
108 108 $ hg --cwd a --cwd b --cwd c tip
109 109 changeset: 1:b6c483daf290
110 110 tag: tip
111 111 parent: -1:000000000000
112 112 user: test
113 113 date: Thu Jan 01 00:00:01 1970 +0000
114 114 summary: b
115 115
116 116 $ hg --repo c --repository b -R a tip
117 117 changeset: 0:8580ff50825a
118 118 tag: tip
119 119 user: test
120 120 date: Thu Jan 01 00:00:01 1970 +0000
121 121 summary: a
122 122
123 123
124 124 earlygetopt short option without following space:
125 125
126 126 $ hg -q -Rb tip
127 127 0:b6c483daf290
128 128
129 129 earlygetopt with illegal abbreviations:
130 130
131 131 $ hg --confi "foo.bar=baz"
132 132 abort: option --config may not be abbreviated!
133 133 [255]
134 134 $ hg --cw a tip
135 135 abort: option --cwd may not be abbreviated!
136 136 [255]
137 137 $ hg --rep a tip
138 138 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
139 139 [255]
140 140 $ hg --repositor a tip
141 141 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
142 142 [255]
143 143 $ hg -qR a tip
144 144 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
145 145 [255]
146 146 $ hg -qRa tip
147 147 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
148 148 [255]
149 149
150 150 Testing --cwd:
151 151
152 152 $ hg --cwd a parents
153 153 changeset: 0:8580ff50825a
154 154 tag: tip
155 155 user: test
156 156 date: Thu Jan 01 00:00:01 1970 +0000
157 157 summary: a
158 158
159 159
160 160 Testing -y/--noninteractive - just be sure it is parsed:
161 161
162 162 $ hg --cwd a tip -q --noninteractive
163 163 0:8580ff50825a
164 164 $ hg --cwd a tip -q -y
165 165 0:8580ff50825a
166 166
167 167 Testing -q/--quiet:
168 168
169 169 $ hg -R a -q tip
170 170 0:8580ff50825a
171 171 $ hg -R b -q tip
172 172 0:b6c483daf290
173 173 $ hg -R c --quiet parents
174 174 0:8580ff50825a
175 175 1:b6c483daf290
176 176
177 177 Testing -v/--verbose:
178 178
179 179 $ hg --cwd c head -v
180 180 changeset: 1:b6c483daf290
181 181 tag: tip
182 182 parent: -1:000000000000
183 183 user: test
184 184 date: Thu Jan 01 00:00:01 1970 +0000
185 185 files: b
186 186 description:
187 187 b
188 188
189 189
190 190 changeset: 0:8580ff50825a
191 191 user: test
192 192 date: Thu Jan 01 00:00:01 1970 +0000
193 193 files: a
194 194 description:
195 195 a
196 196
197 197
198 198 $ hg --cwd b tip --verbose
199 199 changeset: 0:b6c483daf290
200 200 tag: tip
201 201 user: test
202 202 date: Thu Jan 01 00:00:01 1970 +0000
203 203 files: b
204 204 description:
205 205 b
206 206
207 207
208 208
209 209 Testing --config:
210 210
211 211 $ hg --cwd c --config paths.quuxfoo=bar paths | grep quuxfoo > /dev/null && echo quuxfoo
212 212 quuxfoo
213 213 $ hg --cwd c --config '' tip -q
214 214 abort: malformed --config option: '' (use --config section.name=value)
215 215 [255]
216 216 $ hg --cwd c --config a.b tip -q
217 217 abort: malformed --config option: 'a.b' (use --config section.name=value)
218 218 [255]
219 219 $ hg --cwd c --config a tip -q
220 220 abort: malformed --config option: 'a' (use --config section.name=value)
221 221 [255]
222 222 $ hg --cwd c --config a.= tip -q
223 223 abort: malformed --config option: 'a.=' (use --config section.name=value)
224 224 [255]
225 225 $ hg --cwd c --config .b= tip -q
226 226 abort: malformed --config option: '.b=' (use --config section.name=value)
227 227 [255]
228 228
229 229 Testing --debug:
230 230
231 231 $ hg --cwd c log --debug
232 232 changeset: 1:b6c483daf2907ce5825c0bb50f5716226281cc1a
233 233 tag: tip
234 234 parent: -1:0000000000000000000000000000000000000000
235 235 parent: -1:0000000000000000000000000000000000000000
236 236 manifest: 1:23226e7a252cacdc2d99e4fbdc3653441056de49
237 237 user: test
238 238 date: Thu Jan 01 00:00:01 1970 +0000
239 239 files+: b
240 240 extra: branch=default
241 241 description:
242 242 b
243 243
244 244
245 245 changeset: 0:8580ff50825a50c8f716709acdf8de0deddcd6ab
246 246 parent: -1:0000000000000000000000000000000000000000
247 247 parent: -1:0000000000000000000000000000000000000000
248 248 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
249 249 user: test
250 250 date: Thu Jan 01 00:00:01 1970 +0000
251 251 files+: a
252 252 extra: branch=default
253 253 description:
254 254 a
255 255
256 256
257 257
258 258 Testing --traceback:
259 259
260 260 $ hg --cwd c --config x --traceback id 2>&1 | grep -i 'traceback'
261 261 Traceback (most recent call last):
262 262
263 263 Testing --time:
264 264
265 265 $ hg --cwd a --time id
266 266 8580ff50825a tip
267 267 Time: real * (glob)
268 268
269 269 Testing --version:
270 270
271 271 $ hg --version -q
272 272 Mercurial Distributed SCM * (glob)
273 273
274 274 Testing -h/--help:
275 275
276 276 $ hg -h
277 277 Mercurial Distributed SCM
278 278
279 279 list of commands:
280 280
281 281 add add the specified files on the next commit
282 282 addremove add all new files, delete all missing files
283 283 annotate show changeset information by line for each file
284 284 archive create an unversioned archive of a repository revision
285 285 backout reverse effect of earlier changeset
286 286 bisect subdivision search of changesets
287 287 branch set or show the current branch name
288 288 branches list repository named branches
289 289 bundle create a changegroup file
290 290 cat output the current or given revision of files
291 291 clone make a copy of an existing repository
292 292 commit commit the specified files or all outstanding changes
293 293 copy mark files as copied for the next commit
294 294 diff diff repository (or selected files)
295 295 export dump the header and diffs for one or more changesets
296 296 forget forget the specified files on the next commit
297 297 grep search for a pattern in specified files and revisions
298 298 heads show current repository heads or show branch heads
299 299 help show help for a given topic or a help overview
300 300 identify identify the working copy or specified revision
301 301 import import an ordered set of patches
302 302 incoming show new changesets found in source
303 303 init create a new repository in the given directory
304 304 locate locate files matching specific patterns
305 305 log show revision history of entire repository or files
306 306 manifest output the current or given revision of the project manifest
307 307 merge merge working directory with another revision
308 308 outgoing show changesets not found in the destination
309 309 parents show the parents of the working directory or revision
310 310 paths show aliases for remote repositories
311 311 pull pull changes from the specified source
312 312 push push changes to the specified destination
313 313 recover roll back an interrupted transaction
314 314 remove remove the specified files on the next commit
315 315 rename rename files; equivalent of copy + remove
316 316 resolve redo merges or set/view the merge status of files
317 317 revert restore individual files or directories to an earlier state
318 318 rollback roll back the last transaction (dangerous)
319 319 root print the root (top) of the current working directory
320 320 serve start stand-alone webserver
321 321 showconfig show combined config settings from all hgrc files
322 322 status show changed files in the working directory
323 323 summary summarize working directory state
324 324 tag add one or more tags for the current or given revision
325 325 tags list repository tags
326 326 tip show the tip revision
327 327 unbundle apply one or more changegroup files
328 328 update update working directory (or switch revisions)
329 329 verify verify the integrity of the repository
330 330 version output version and copyright information
331 331
332 332 additional help topics:
333 333
334 334 config Configuration Files
335 335 dates Date Formats
336 336 patterns File Name Patterns
337 337 environment Environment Variables
338 338 revisions Specifying Single Revisions
339 339 multirevs Specifying Multiple Revisions
340 340 revsets Specifying Revision Sets
341 341 diffs Diff Formats
342 342 merge-tools Merge Tools
343 343 templating Template Usage
344 344 urls URL Paths
345 345 extensions Using additional features
346 346 subrepos Subrepositories
347 347 hgweb Configuring hgweb
348 348 glossary Glossary
349 349
350 use "hg -v help" to show aliases and global options
350 use "hg -v help" to show builtin aliases and global options
351 351
352 352 $ hg --help
353 353 Mercurial Distributed SCM
354 354
355 355 list of commands:
356 356
357 357 add add the specified files on the next commit
358 358 addremove add all new files, delete all missing files
359 359 annotate show changeset information by line for each file
360 360 archive create an unversioned archive of a repository revision
361 361 backout reverse effect of earlier changeset
362 362 bisect subdivision search of changesets
363 363 branch set or show the current branch name
364 364 branches list repository named branches
365 365 bundle create a changegroup file
366 366 cat output the current or given revision of files
367 367 clone make a copy of an existing repository
368 368 commit commit the specified files or all outstanding changes
369 369 copy mark files as copied for the next commit
370 370 diff diff repository (or selected files)
371 371 export dump the header and diffs for one or more changesets
372 372 forget forget the specified files on the next commit
373 373 grep search for a pattern in specified files and revisions
374 374 heads show current repository heads or show branch heads
375 375 help show help for a given topic or a help overview
376 376 identify identify the working copy or specified revision
377 377 import import an ordered set of patches
378 378 incoming show new changesets found in source
379 379 init create a new repository in the given directory
380 380 locate locate files matching specific patterns
381 381 log show revision history of entire repository or files
382 382 manifest output the current or given revision of the project manifest
383 383 merge merge working directory with another revision
384 384 outgoing show changesets not found in the destination
385 385 parents show the parents of the working directory or revision
386 386 paths show aliases for remote repositories
387 387 pull pull changes from the specified source
388 388 push push changes to the specified destination
389 389 recover roll back an interrupted transaction
390 390 remove remove the specified files on the next commit
391 391 rename rename files; equivalent of copy + remove
392 392 resolve redo merges or set/view the merge status of files
393 393 revert restore individual files or directories to an earlier state
394 394 rollback roll back the last transaction (dangerous)
395 395 root print the root (top) of the current working directory
396 396 serve start stand-alone webserver
397 397 showconfig show combined config settings from all hgrc files
398 398 status show changed files in the working directory
399 399 summary summarize working directory state
400 400 tag add one or more tags for the current or given revision
401 401 tags list repository tags
402 402 tip show the tip revision
403 403 unbundle apply one or more changegroup files
404 404 update update working directory (or switch revisions)
405 405 verify verify the integrity of the repository
406 406 version output version and copyright information
407 407
408 408 additional help topics:
409 409
410 410 config Configuration Files
411 411 dates Date Formats
412 412 patterns File Name Patterns
413 413 environment Environment Variables
414 414 revisions Specifying Single Revisions
415 415 multirevs Specifying Multiple Revisions
416 416 revsets Specifying Revision Sets
417 417 diffs Diff Formats
418 418 merge-tools Merge Tools
419 419 templating Template Usage
420 420 urls URL Paths
421 421 extensions Using additional features
422 422 subrepos Subrepositories
423 423 hgweb Configuring hgweb
424 424 glossary Glossary
425 425
426 use "hg -v help" to show aliases and global options
426 use "hg -v help" to show builtin aliases and global options
427 427
428 428 Not tested: --debugger
429 429
@@ -1,790 +1,790 b''
1 1 Short help:
2 2
3 3 $ hg
4 4 Mercurial Distributed SCM
5 5
6 6 basic commands:
7 7
8 8 add add the specified files on the next commit
9 9 annotate show changeset information by line for each file
10 10 clone make a copy of an existing repository
11 11 commit commit the specified files or all outstanding changes
12 12 diff diff repository (or selected files)
13 13 export dump the header and diffs for one or more changesets
14 14 forget forget the specified files on the next commit
15 15 init create a new repository in the given directory
16 16 log show revision history of entire repository or files
17 17 merge merge working directory with another revision
18 18 pull pull changes from the specified source
19 19 push push changes to the specified destination
20 20 remove remove the specified files on the next commit
21 21 serve start stand-alone webserver
22 22 status show changed files in the working directory
23 23 summary summarize working directory state
24 24 update update working directory (or switch revisions)
25 25
26 26 use "hg help" for the full list of commands or "hg -v" for details
27 27
28 28 $ hg -q
29 29 add add the specified files on the next commit
30 30 annotate show changeset information by line for each file
31 31 clone make a copy of an existing repository
32 32 commit commit the specified files or all outstanding changes
33 33 diff diff repository (or selected files)
34 34 export dump the header and diffs for one or more changesets
35 35 forget forget the specified files on the next commit
36 36 init create a new repository in the given directory
37 37 log show revision history of entire repository or files
38 38 merge merge working directory with another revision
39 39 pull pull changes from the specified source
40 40 push push changes to the specified destination
41 41 remove remove the specified files on the next commit
42 42 serve start stand-alone webserver
43 43 status show changed files in the working directory
44 44 summary summarize working directory state
45 45 update update working directory (or switch revisions)
46 46
47 47 $ hg help
48 48 Mercurial Distributed SCM
49 49
50 50 list of commands:
51 51
52 52 add add the specified files on the next commit
53 53 addremove add all new files, delete all missing files
54 54 annotate show changeset information by line for each file
55 55 archive create an unversioned archive of a repository revision
56 56 backout reverse effect of earlier changeset
57 57 bisect subdivision search of changesets
58 58 branch set or show the current branch name
59 59 branches list repository named branches
60 60 bundle create a changegroup file
61 61 cat output the current or given revision of files
62 62 clone make a copy of an existing repository
63 63 commit commit the specified files or all outstanding changes
64 64 copy mark files as copied for the next commit
65 65 diff diff repository (or selected files)
66 66 export dump the header and diffs for one or more changesets
67 67 forget forget the specified files on the next commit
68 68 grep search for a pattern in specified files and revisions
69 69 heads show current repository heads or show branch heads
70 70 help show help for a given topic or a help overview
71 71 identify identify the working copy or specified revision
72 72 import import an ordered set of patches
73 73 incoming show new changesets found in source
74 74 init create a new repository in the given directory
75 75 locate locate files matching specific patterns
76 76 log show revision history of entire repository or files
77 77 manifest output the current or given revision of the project manifest
78 78 merge merge working directory with another revision
79 79 outgoing show changesets not found in the destination
80 80 parents show the parents of the working directory or revision
81 81 paths show aliases for remote repositories
82 82 pull pull changes from the specified source
83 83 push push changes to the specified destination
84 84 recover roll back an interrupted transaction
85 85 remove remove the specified files on the next commit
86 86 rename rename files; equivalent of copy + remove
87 87 resolve redo merges or set/view the merge status of files
88 88 revert restore individual files or directories to an earlier state
89 89 rollback roll back the last transaction (dangerous)
90 90 root print the root (top) of the current working directory
91 91 serve start stand-alone webserver
92 92 showconfig show combined config settings from all hgrc files
93 93 status show changed files in the working directory
94 94 summary summarize working directory state
95 95 tag add one or more tags for the current or given revision
96 96 tags list repository tags
97 97 tip show the tip revision
98 98 unbundle apply one or more changegroup files
99 99 update update working directory (or switch revisions)
100 100 verify verify the integrity of the repository
101 101 version output version and copyright information
102 102
103 103 additional help topics:
104 104
105 105 config Configuration Files
106 106 dates Date Formats
107 107 patterns File Name Patterns
108 108 environment Environment Variables
109 109 revisions Specifying Single Revisions
110 110 multirevs Specifying Multiple Revisions
111 111 revsets Specifying Revision Sets
112 112 diffs Diff Formats
113 113 merge-tools Merge Tools
114 114 templating Template Usage
115 115 urls URL Paths
116 116 extensions Using additional features
117 117 subrepos Subrepositories
118 118 hgweb Configuring hgweb
119 119 glossary Glossary
120 120
121 use "hg -v help" to show aliases and global options
121 use "hg -v help" to show builtin aliases and global options
122 122
123 123 $ hg -q help
124 124 add add the specified files on the next commit
125 125 addremove add all new files, delete all missing files
126 126 annotate show changeset information by line for each file
127 127 archive create an unversioned archive of a repository revision
128 128 backout reverse effect of earlier changeset
129 129 bisect subdivision search of changesets
130 130 branch set or show the current branch name
131 131 branches list repository named branches
132 132 bundle create a changegroup file
133 133 cat output the current or given revision of files
134 134 clone make a copy of an existing repository
135 135 commit commit the specified files or all outstanding changes
136 136 copy mark files as copied for the next commit
137 137 diff diff repository (or selected files)
138 138 export dump the header and diffs for one or more changesets
139 139 forget forget the specified files on the next commit
140 140 grep search for a pattern in specified files and revisions
141 141 heads show current repository heads or show branch heads
142 142 help show help for a given topic or a help overview
143 143 identify identify the working copy or specified revision
144 144 import import an ordered set of patches
145 145 incoming show new changesets found in source
146 146 init create a new repository in the given directory
147 147 locate locate files matching specific patterns
148 148 log show revision history of entire repository or files
149 149 manifest output the current or given revision of the project manifest
150 150 merge merge working directory with another revision
151 151 outgoing show changesets not found in the destination
152 152 parents show the parents of the working directory or revision
153 153 paths show aliases for remote repositories
154 154 pull pull changes from the specified source
155 155 push push changes to the specified destination
156 156 recover roll back an interrupted transaction
157 157 remove remove the specified files on the next commit
158 158 rename rename files; equivalent of copy + remove
159 159 resolve redo merges or set/view the merge status of files
160 160 revert restore individual files or directories to an earlier state
161 161 rollback roll back the last transaction (dangerous)
162 162 root print the root (top) of the current working directory
163 163 serve start stand-alone webserver
164 164 showconfig show combined config settings from all hgrc files
165 165 status show changed files in the working directory
166 166 summary summarize working directory state
167 167 tag add one or more tags for the current or given revision
168 168 tags list repository tags
169 169 tip show the tip revision
170 170 unbundle apply one or more changegroup files
171 171 update update working directory (or switch revisions)
172 172 verify verify the integrity of the repository
173 173 version output version and copyright information
174 174
175 175 additional help topics:
176 176
177 177 config Configuration Files
178 178 dates Date Formats
179 179 patterns File Name Patterns
180 180 environment Environment Variables
181 181 revisions Specifying Single Revisions
182 182 multirevs Specifying Multiple Revisions
183 183 revsets Specifying Revision Sets
184 184 diffs Diff Formats
185 185 merge-tools Merge Tools
186 186 templating Template Usage
187 187 urls URL Paths
188 188 extensions Using additional features
189 189 subrepos Subrepositories
190 190 hgweb Configuring hgweb
191 191 glossary Glossary
192 192
193 193 Test short command list with verbose option
194 194
195 195 $ hg -v help shortlist
196 196 Mercurial Distributed SCM (version *) (glob)
197 197 (see http://mercurial.selenic.com for more information)
198 198
199 199 Copyright (C) 2005-2010 Matt Mackall and others
200 200 This is free software; see the source for copying conditions. There is NO
201 201 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
202 202
203 203 basic commands:
204 204
205 205 add:
206 206 add the specified files on the next commit
207 207 annotate, blame:
208 208 show changeset information by line for each file
209 209 clone:
210 210 make a copy of an existing repository
211 211 commit, ci:
212 212 commit the specified files or all outstanding changes
213 213 diff:
214 214 diff repository (or selected files)
215 215 export:
216 216 dump the header and diffs for one or more changesets
217 217 forget:
218 218 forget the specified files on the next commit
219 219 init:
220 220 create a new repository in the given directory
221 221 log, history:
222 222 show revision history of entire repository or files
223 223 merge:
224 224 merge working directory with another revision
225 225 pull:
226 226 pull changes from the specified source
227 227 push:
228 228 push changes to the specified destination
229 229 remove, rm:
230 230 remove the specified files on the next commit
231 231 serve:
232 232 start stand-alone webserver
233 233 status, st:
234 234 show changed files in the working directory
235 235 summary, sum:
236 236 summarize working directory state
237 237 update, up, checkout, co:
238 238 update working directory (or switch revisions)
239 239
240 240 global options:
241 241 -R --repository REPO repository root directory or name of overlay bundle
242 242 file
243 243 --cwd DIR change working directory
244 244 -y --noninteractive do not prompt, assume 'yes' for any required answers
245 245 -q --quiet suppress output
246 246 -v --verbose enable additional output
247 247 --config CONFIG [+] set/override config option (use 'section.name=value')
248 248 --debug enable debugging output
249 249 --debugger start debugger
250 250 --encoding ENCODE set the charset encoding (default: ascii)
251 251 --encodingmode MODE set the charset encoding mode (default: strict)
252 252 --traceback always print a traceback on exception
253 253 --time time how long the command takes
254 254 --profile print command execution profile
255 255 --version output version information and exit
256 256 -h --help display help and exit
257 257
258 258 [+] marked option can be specified multiple times
259 259
260 260 use "hg help" for the full list of commands
261 261
262 262 $ hg add -h
263 263 hg add [OPTION]... [FILE]...
264 264
265 265 add the specified files on the next commit
266 266
267 267 Schedule files to be version controlled and added to the repository.
268 268
269 269 The files will be added to the repository at the next commit. To undo an
270 270 add before that, see "hg forget".
271 271
272 272 If no names are given, add all files to the repository.
273 273
274 274 Returns 0 if all files are successfully added.
275 275
276 276 use "hg -v help add" to show verbose help
277 277
278 278 options:
279 279
280 280 -I --include PATTERN [+] include names matching the given patterns
281 281 -X --exclude PATTERN [+] exclude names matching the given patterns
282 282 -S --subrepos recurse into subrepositories
283 283 -n --dry-run do not perform actions, just print output
284 284
285 285 [+] marked option can be specified multiple times
286 286
287 287 use "hg -v help add" to show global options
288 288
289 289 Verbose help for add
290 290
291 291 $ hg add -hv
292 292 hg add [OPTION]... [FILE]...
293 293
294 294 add the specified files on the next commit
295 295
296 296 Schedule files to be version controlled and added to the repository.
297 297
298 298 The files will be added to the repository at the next commit. To undo an
299 299 add before that, see "hg forget".
300 300
301 301 If no names are given, add all files to the repository.
302 302
303 303 An example showing how new (unknown) files are added automatically by "hg
304 304 add":
305 305
306 306 $ ls
307 307 foo.c
308 308 $ hg status
309 309 ? foo.c
310 310 $ hg add
311 311 adding foo.c
312 312 $ hg status
313 313 A foo.c
314 314
315 315 Returns 0 if all files are successfully added.
316 316
317 317 options:
318 318
319 319 -I --include PATTERN [+] include names matching the given patterns
320 320 -X --exclude PATTERN [+] exclude names matching the given patterns
321 321 -S --subrepos recurse into subrepositories
322 322 -n --dry-run do not perform actions, just print output
323 323
324 324 global options:
325 325 -R --repository REPO repository root directory or name of overlay bundle
326 326 file
327 327 --cwd DIR change working directory
328 328 -y --noninteractive do not prompt, assume 'yes' for any required
329 329 answers
330 330 -q --quiet suppress output
331 331 -v --verbose enable additional output
332 332 --config CONFIG [+] set/override config option (use
333 333 'section.name=value')
334 334 --debug enable debugging output
335 335 --debugger start debugger
336 336 --encoding ENCODE set the charset encoding (default: ascii)
337 337 --encodingmode MODE set the charset encoding mode (default: strict)
338 338 --traceback always print a traceback on exception
339 339 --time time how long the command takes
340 340 --profile print command execution profile
341 341 --version output version information and exit
342 342 -h --help display help and exit
343 343
344 344 [+] marked option can be specified multiple times
345 345
346 346 Test help option with version option
347 347
348 348 $ hg add -h --version
349 349 Mercurial Distributed SCM (version *) (glob)
350 350 (see http://mercurial.selenic.com for more information)
351 351
352 352 Copyright (C) 2005-2010 Matt Mackall and others
353 353 This is free software; see the source for copying conditions. There is NO
354 354 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
355 355
356 356 hg add [OPTION]... [FILE]...
357 357
358 358 add the specified files on the next commit
359 359
360 360 Schedule files to be version controlled and added to the repository.
361 361
362 362 The files will be added to the repository at the next commit. To undo an
363 363 add before that, see "hg forget".
364 364
365 365 If no names are given, add all files to the repository.
366 366
367 367 Returns 0 if all files are successfully added.
368 368
369 369 use "hg -v help add" to show verbose help
370 370
371 371 options:
372 372
373 373 -I --include PATTERN [+] include names matching the given patterns
374 374 -X --exclude PATTERN [+] exclude names matching the given patterns
375 375 -S --subrepos recurse into subrepositories
376 376 -n --dry-run do not perform actions, just print output
377 377
378 378 [+] marked option can be specified multiple times
379 379
380 380 use "hg -v help add" to show global options
381 381
382 382 $ hg add --skjdfks
383 383 hg add: option --skjdfks not recognized
384 384 hg add [OPTION]... [FILE]...
385 385
386 386 add the specified files on the next commit
387 387
388 388 Schedule files to be version controlled and added to the repository.
389 389
390 390 The files will be added to the repository at the next commit. To undo an
391 391 add before that, see "hg forget".
392 392
393 393 If no names are given, add all files to the repository.
394 394
395 395 Returns 0 if all files are successfully added.
396 396
397 397 use "hg -v help add" to show verbose help
398 398
399 399 options:
400 400
401 401 -I --include PATTERN [+] include names matching the given patterns
402 402 -X --exclude PATTERN [+] exclude names matching the given patterns
403 403 -S --subrepos recurse into subrepositories
404 404 -n --dry-run do not perform actions, just print output
405 405
406 406 [+] marked option can be specified multiple times
407 407
408 408 use "hg -v help add" to show global options
409 409 [255]
410 410
411 411 Test ambiguous command help
412 412
413 413 $ hg help ad
414 414 list of commands:
415 415
416 416 add add the specified files on the next commit
417 417 addremove add all new files, delete all missing files
418 418
419 use "hg -v help ad" to show aliases and global options
419 use "hg -v help ad" to show builtin aliases and global options
420 420
421 421 Test command without options
422 422
423 423 $ hg help verify
424 424 hg verify
425 425
426 426 verify the integrity of the repository
427 427
428 428 Verify the integrity of the current repository.
429 429
430 430 This will perform an extensive check of the repository's integrity,
431 431 validating the hashes and checksums of each entry in the changelog,
432 432 manifest, and tracked files, as well as the integrity of their crosslinks
433 433 and indices.
434 434
435 435 Returns 0 on success, 1 if errors are encountered.
436 436
437 437 use "hg -v help verify" to show global options
438 438
439 439 $ hg help diff
440 440 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
441 441
442 442 diff repository (or selected files)
443 443
444 444 Show differences between revisions for the specified files.
445 445
446 446 Differences between files are shown using the unified diff format.
447 447
448 448 Note:
449 449 diff may generate unexpected results for merges, as it will default to
450 450 comparing against the working directory's first parent changeset if no
451 451 revisions are specified.
452 452
453 453 When two revision arguments are given, then changes are shown between
454 454 those revisions. If only one revision is specified then that revision is
455 455 compared to the working directory, and, when no revisions are specified,
456 456 the working directory files are compared to its parent.
457 457
458 458 Alternatively you can specify -c/--change with a revision to see the
459 459 changes in that changeset relative to its first parent.
460 460
461 461 Without the -a/--text option, diff will avoid generating diffs of files it
462 462 detects as binary. With -a, diff will generate a diff anyway, probably
463 463 with undesirable results.
464 464
465 465 Use the -g/--git option to generate diffs in the git extended diff format.
466 466 For more information, read "hg help diffs".
467 467
468 468 Returns 0 on success.
469 469
470 470 options:
471 471
472 472 -r --rev REV [+] revision
473 473 -c --change REV change made by revision
474 474 -a --text treat all files as text
475 475 -g --git use git extended diff format
476 476 --nodates omit dates from diff headers
477 477 -p --show-function show which function each change is in
478 478 --reverse produce a diff that undoes the changes
479 479 -w --ignore-all-space ignore white space when comparing lines
480 480 -b --ignore-space-change ignore changes in the amount of white space
481 481 -B --ignore-blank-lines ignore changes whose lines are all blank
482 482 -U --unified NUM number of lines of context to show
483 483 --stat output diffstat-style summary of changes
484 484 -I --include PATTERN [+] include names matching the given patterns
485 485 -X --exclude PATTERN [+] exclude names matching the given patterns
486 486 -S --subrepos recurse into subrepositories
487 487
488 488 [+] marked option can be specified multiple times
489 489
490 490 use "hg -v help diff" to show global options
491 491
492 492 $ hg help status
493 493 hg status [OPTION]... [FILE]...
494 494
495 495 aliases: st
496 496
497 497 show changed files in the working directory
498 498
499 499 Show status of files in the repository. If names are given, only files
500 500 that match are shown. Files that are clean or ignored or the source of a
501 501 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
502 502 -C/--copies or -A/--all are given. Unless options described with "show
503 503 only ..." are given, the options -mardu are used.
504 504
505 505 Option -q/--quiet hides untracked (unknown and ignored) files unless
506 506 explicitly requested with -u/--unknown or -i/--ignored.
507 507
508 508 Note:
509 509 status may appear to disagree with diff if permissions have changed or
510 510 a merge has occurred. The standard diff format does not report
511 511 permission changes and diff only reports changes relative to one merge
512 512 parent.
513 513
514 514 If one revision is given, it is used as the base revision. If two
515 515 revisions are given, the differences between them are shown. The --change
516 516 option can also be used as a shortcut to list the changed files of a
517 517 revision from its first parent.
518 518
519 519 The codes used to show the status of files are:
520 520
521 521 M = modified
522 522 A = added
523 523 R = removed
524 524 C = clean
525 525 ! = missing (deleted by non-hg command, but still tracked)
526 526 ? = not tracked
527 527 I = ignored
528 528 = origin of the previous file listed as A (added)
529 529
530 530 Returns 0 on success.
531 531
532 532 options:
533 533
534 534 -A --all show status of all files
535 535 -m --modified show only modified files
536 536 -a --added show only added files
537 537 -r --removed show only removed files
538 538 -d --deleted show only deleted (but tracked) files
539 539 -c --clean show only files without changes
540 540 -u --unknown show only unknown (not tracked) files
541 541 -i --ignored show only ignored files
542 542 -n --no-status hide status prefix
543 543 -C --copies show source of copied files
544 544 -0 --print0 end filenames with NUL, for use with xargs
545 545 --rev REV [+] show difference from revision
546 546 --change REV list the changed files of a revision
547 547 -I --include PATTERN [+] include names matching the given patterns
548 548 -X --exclude PATTERN [+] exclude names matching the given patterns
549 549 -S --subrepos recurse into subrepositories
550 550
551 551 [+] marked option can be specified multiple times
552 552
553 553 use "hg -v help status" to show global options
554 554
555 555 $ hg -q help status
556 556 hg status [OPTION]... [FILE]...
557 557
558 558 show changed files in the working directory
559 559
560 560 $ hg help foo
561 561 hg: unknown command 'foo'
562 562 Mercurial Distributed SCM
563 563
564 564 basic commands:
565 565
566 566 add add the specified files on the next commit
567 567 annotate show changeset information by line for each file
568 568 clone make a copy of an existing repository
569 569 commit commit the specified files or all outstanding changes
570 570 diff diff repository (or selected files)
571 571 export dump the header and diffs for one or more changesets
572 572 forget forget the specified files on the next commit
573 573 init create a new repository in the given directory
574 574 log show revision history of entire repository or files
575 575 merge merge working directory with another revision
576 576 pull pull changes from the specified source
577 577 push push changes to the specified destination
578 578 remove remove the specified files on the next commit
579 579 serve start stand-alone webserver
580 580 status show changed files in the working directory
581 581 summary summarize working directory state
582 582 update update working directory (or switch revisions)
583 583
584 584 use "hg help" for the full list of commands or "hg -v" for details
585 585 [255]
586 586
587 587 $ hg skjdfks
588 588 hg: unknown command 'skjdfks'
589 589 Mercurial Distributed SCM
590 590
591 591 basic commands:
592 592
593 593 add add the specified files on the next commit
594 594 annotate show changeset information by line for each file
595 595 clone make a copy of an existing repository
596 596 commit commit the specified files or all outstanding changes
597 597 diff diff repository (or selected files)
598 598 export dump the header and diffs for one or more changesets
599 599 forget forget the specified files on the next commit
600 600 init create a new repository in the given directory
601 601 log show revision history of entire repository or files
602 602 merge merge working directory with another revision
603 603 pull pull changes from the specified source
604 604 push push changes to the specified destination
605 605 remove remove the specified files on the next commit
606 606 serve start stand-alone webserver
607 607 status show changed files in the working directory
608 608 summary summarize working directory state
609 609 update update working directory (or switch revisions)
610 610
611 611 use "hg help" for the full list of commands or "hg -v" for details
612 612 [255]
613 613
614 614 $ cat > helpext.py <<EOF
615 615 > import os
616 616 > from mercurial import commands
617 617 >
618 618 > def nohelp(ui, *args, **kwargs):
619 619 > pass
620 620 >
621 621 > cmdtable = {
622 622 > "nohelp": (nohelp, [], "hg nohelp"),
623 623 > }
624 624 >
625 625 > commands.norepo += ' nohelp'
626 626 > EOF
627 627 $ echo '[extensions]' >> $HGRCPATH
628 628 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
629 629
630 630 Test command with no help text
631 631
632 632 $ hg help nohelp
633 633 hg nohelp
634 634
635 635 (no help text available)
636 636
637 637 use "hg -v help nohelp" to show global options
638 638
639 639 Test that default list of commands omits extension commands
640 640
641 641 $ hg help
642 642 Mercurial Distributed SCM
643 643
644 644 list of commands:
645 645
646 646 add add the specified files on the next commit
647 647 addremove add all new files, delete all missing files
648 648 annotate show changeset information by line for each file
649 649 archive create an unversioned archive of a repository revision
650 650 backout reverse effect of earlier changeset
651 651 bisect subdivision search of changesets
652 652 branch set or show the current branch name
653 653 branches list repository named branches
654 654 bundle create a changegroup file
655 655 cat output the current or given revision of files
656 656 clone make a copy of an existing repository
657 657 commit commit the specified files or all outstanding changes
658 658 copy mark files as copied for the next commit
659 659 diff diff repository (or selected files)
660 660 export dump the header and diffs for one or more changesets
661 661 forget forget the specified files on the next commit
662 662 grep search for a pattern in specified files and revisions
663 663 heads show current repository heads or show branch heads
664 664 help show help for a given topic or a help overview
665 665 identify identify the working copy or specified revision
666 666 import import an ordered set of patches
667 667 incoming show new changesets found in source
668 668 init create a new repository in the given directory
669 669 locate locate files matching specific patterns
670 670 log show revision history of entire repository or files
671 671 manifest output the current or given revision of the project manifest
672 672 merge merge working directory with another revision
673 673 outgoing show changesets not found in the destination
674 674 parents show the parents of the working directory or revision
675 675 paths show aliases for remote repositories
676 676 pull pull changes from the specified source
677 677 push push changes to the specified destination
678 678 recover roll back an interrupted transaction
679 679 remove remove the specified files on the next commit
680 680 rename rename files; equivalent of copy + remove
681 681 resolve redo merges or set/view the merge status of files
682 682 revert restore individual files or directories to an earlier state
683 683 rollback roll back the last transaction (dangerous)
684 684 root print the root (top) of the current working directory
685 685 serve start stand-alone webserver
686 686 showconfig show combined config settings from all hgrc files
687 687 status show changed files in the working directory
688 688 summary summarize working directory state
689 689 tag add one or more tags for the current or given revision
690 690 tags list repository tags
691 691 tip show the tip revision
692 692 unbundle apply one or more changegroup files
693 693 update update working directory (or switch revisions)
694 694 verify verify the integrity of the repository
695 695 version output version and copyright information
696 696
697 697 enabled extensions:
698 698
699 699 helpext (no help text available)
700 700
701 701 additional help topics:
702 702
703 703 config Configuration Files
704 704 dates Date Formats
705 705 patterns File Name Patterns
706 706 environment Environment Variables
707 707 revisions Specifying Single Revisions
708 708 multirevs Specifying Multiple Revisions
709 709 revsets Specifying Revision Sets
710 710 diffs Diff Formats
711 711 merge-tools Merge Tools
712 712 templating Template Usage
713 713 urls URL Paths
714 714 extensions Using additional features
715 715 subrepos Subrepositories
716 716 hgweb Configuring hgweb
717 717 glossary Glossary
718 718
719 use "hg -v help" to show aliases and global options
719 use "hg -v help" to show builtin aliases and global options
720 720
721 721 Test list of commands with command with no help text
722 722
723 723 $ hg help helpext
724 724 helpext extension - no help text available
725 725
726 726 list of commands:
727 727
728 728 nohelp (no help text available)
729 729
730 use "hg -v help helpext" to show aliases and global options
730 use "hg -v help helpext" to show builtin aliases and global options
731 731
732 732 Test a help topic
733 733
734 734 $ hg help revs
735 735 Specifying Single Revisions
736 736
737 737 Mercurial supports several ways to specify individual revisions.
738 738
739 739 A plain integer is treated as a revision number. Negative integers are
740 740 treated as sequential offsets from the tip, with -1 denoting the tip, -2
741 741 denoting the revision prior to the tip, and so forth.
742 742
743 743 A 40-digit hexadecimal string is treated as a unique revision identifier.
744 744
745 745 A hexadecimal string less than 40 characters long is treated as a unique
746 746 revision identifier and is referred to as a short-form identifier. A
747 747 short-form identifier is only valid if it is the prefix of exactly one
748 748 full-length identifier.
749 749
750 750 Any other string is treated as a tag or branch name. A tag name is a
751 751 symbolic name associated with a revision identifier. A branch name denotes
752 752 the tipmost revision of that branch. Tag and branch names must not contain
753 753 the ":" character.
754 754
755 755 The reserved name "tip" is a special tag that always identifies the most
756 756 recent revision.
757 757
758 758 The reserved name "null" indicates the null revision. This is the revision
759 759 of an empty repository, and the parent of revision 0.
760 760
761 761 The reserved name "." indicates the working directory parent. If no
762 762 working directory is checked out, it is equivalent to null. If an
763 763 uncommitted merge is in progress, "." is the revision of the first parent.
764 764
765 765 Test help hooks
766 766
767 767 $ cat > helphook1.py <<EOF
768 768 > from mercurial import help
769 769 >
770 770 > def rewrite(topic, doc):
771 771 > return doc + '\nhelphook1\n'
772 772 >
773 773 > def extsetup(ui):
774 774 > help.addtopichook('revsets', rewrite)
775 775 > EOF
776 776 $ cat > helphook2.py <<EOF
777 777 > from mercurial import help
778 778 >
779 779 > def rewrite(topic, doc):
780 780 > return doc + '\nhelphook2\n'
781 781 >
782 782 > def extsetup(ui):
783 783 > help.addtopichook('revsets', rewrite)
784 784 > EOF
785 785 $ echo '[extensions]' >> $HGRCPATH
786 786 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
787 787 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
788 788 $ hg help revsets | grep helphook
789 789 helphook1
790 790 helphook2
@@ -1,189 +1,190 b''
1 1 Proper https client requires the built-in ssl from Python 2.6.
2 2
3 3 $ "$TESTDIR/hghave" ssl || exit 80
4 4
5 5 Certificates created with:
6 6 printf '.\n.\n.\n.\n.\nlocalhost\nhg@localhost\n' | \
7 7 openssl req -newkey rsa:512 -keyout priv.pem -nodes -x509 -days 9000 -out pub.pem
8 8 Can be dumped with:
9 9 openssl x509 -in pub.pem -text
10 10
11 11 $ cat << EOT > priv.pem
12 12 > -----BEGIN PRIVATE KEY-----
13 13 > MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEApjCWeYGrIa/Vo7LH
14 14 > aRF8ou0tbgHKE33Use/whCnKEUm34rDaXQd4lxxX6aDWg06n9tiVStAKTgQAHJY8
15 15 > j/xgSwIDAQABAkBxHC6+Qlf0VJXGlb6NL16yEVVTQxqDS6hA9zqu6TZjrr0YMfzc
16 16 > EGNIiZGt7HCBL0zO+cPDg/LeCZc6HQhf0KrhAiEAzlJq4hWWzvguWFIJWSoBeBUG
17 17 > MF1ACazQO7PYE8M0qfECIQDONHHP0SKZzz/ZwBZcAveC5K61f/v9hONFwbeYulzR
18 18 > +wIgc9SvbtgB/5Yzpp//4ZAEnR7oh5SClCvyB+KSx52K3nECICbhQphhoXmI10wy
19 19 > aMTellaq0bpNMHFDziqH9RsqAHhjAiEAgYGxfzkftt5IUUn/iFK89aaIpyrpuaAh
20 20 > HY8gUVkVRVs=
21 21 > -----END PRIVATE KEY-----
22 22 > EOT
23 23
24 24 $ cat << EOT > pub.pem
25 25 > -----BEGIN CERTIFICATE-----
26 26 > MIIBqzCCAVWgAwIBAgIJANAXFFyWjGnRMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNV
27 27 > BAMMCWxvY2FsaG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTEw
28 28 > MTAxNDIwMzAxNFoXDTM1MDYwNTIwMzAxNFowMTESMBAGA1UEAwwJbG9jYWxob3N0
29 29 > MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhvc3QwXDANBgkqhkiG9w0BAQEFAANL
30 30 > ADBIAkEApjCWeYGrIa/Vo7LHaRF8ou0tbgHKE33Use/whCnKEUm34rDaXQd4lxxX
31 31 > 6aDWg06n9tiVStAKTgQAHJY8j/xgSwIDAQABo1AwTjAdBgNVHQ4EFgQUE6sA+amm
32 32 > r24dGX0kpjxOgO45hzQwHwYDVR0jBBgwFoAUE6sA+ammr24dGX0kpjxOgO45hzQw
33 33 > DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAFArvQFiAZJgQczRsbYlG1xl
34 34 > t+truk37w5B3m3Ick1ntRcQrqs+hf0CO1q6Squ144geYaQ8CDirSR92fICELI1c=
35 35 > -----END CERTIFICATE-----
36 36 > EOT
37 37 $ cat priv.pem pub.pem >> server.pem
38 38 $ PRIV=`pwd`/server.pem
39 39
40 40 $ cat << EOT > pub-other.pem
41 41 > -----BEGIN CERTIFICATE-----
42 42 > MIIBqzCCAVWgAwIBAgIJALwZS731c/ORMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNV
43 43 > BAMMCWxvY2FsaG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTEw
44 44 > MTAxNDIwNDUxNloXDTM1MDYwNTIwNDUxNlowMTESMBAGA1UEAwwJbG9jYWxob3N0
45 45 > MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhvc3QwXDANBgkqhkiG9w0BAQEFAANL
46 46 > ADBIAkEAsxsapLbHrqqUKuQBxdpK4G3m2LjtyrTSdpzzzFlecxd5yhNP6AyWrufo
47 47 > K4VMGo2xlu9xOo88nDSUNSKPuD09MwIDAQABo1AwTjAdBgNVHQ4EFgQUoIB1iMhN
48 48 > y868rpQ2qk9dHnU6ebswHwYDVR0jBBgwFoAUoIB1iMhNy868rpQ2qk9dHnU6ebsw
49 49 > DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAJ544f125CsE7J2t55PdFaF6
50 50 > bBlNBb91FCywBgSjhBjf+GG3TNPwrPdc3yqeq+hzJiuInqbOBv9abmMyq8Wsoig=
51 51 > -----END CERTIFICATE-----
52 52 > EOT
53 53
54 54 pub.pem patched with other notBefore / notAfter:
55 55
56 56 $ cat << EOT > pub-not-yet.pem
57 57 > -----BEGIN CERTIFICATE-----
58 58 > MIIBqzCCAVWgAwIBAgIJANAXFFyWjGnRMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNVBAMMCWxvY2Fs
59 59 > aG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTM1MDYwNTIwMzAxNFoXDTM1MDYw
60 60 > NTIwMzAxNFowMTESMBAGA1UEAwwJbG9jYWxob3N0MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhv
61 61 > c3QwXDANBgkqhkiG9w0BAQEFAANLADBIAkEApjCWeYGrIa/Vo7LHaRF8ou0tbgHKE33Use/whCnK
62 62 > EUm34rDaXQd4lxxX6aDWg06n9tiVStAKTgQAHJY8j/xgSwIDAQABo1AwTjAdBgNVHQ4EFgQUE6sA
63 63 > +ammr24dGX0kpjxOgO45hzQwHwYDVR0jBBgwFoAUE6sA+ammr24dGX0kpjxOgO45hzQwDAYDVR0T
64 64 > BAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAJXV41gWnkgC7jcpPpFRSUSZaxyzrXmD1CIqQf0WgVDb
65 65 > /12E0vR2DuZitgzUYtBaofM81aTtc0a2/YsrmqePGm0=
66 66 > -----END CERTIFICATE-----
67 67 > EOT
68 68 $ cat priv.pem pub-not-yet.pem > server-not-yet.pem
69 69
70 70 $ cat << EOT > pub-expired.pem
71 71 > -----BEGIN CERTIFICATE-----
72 72 > MIIBqzCCAVWgAwIBAgIJANAXFFyWjGnRMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNVBAMMCWxvY2Fs
73 73 > aG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTEwMTAxNDIwMzAxNFoXDTEwMTAx
74 74 > NDIwMzAxNFowMTESMBAGA1UEAwwJbG9jYWxob3N0MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhv
75 75 > c3QwXDANBgkqhkiG9w0BAQEFAANLADBIAkEApjCWeYGrIa/Vo7LHaRF8ou0tbgHKE33Use/whCnK
76 76 > EUm34rDaXQd4lxxX6aDWg06n9tiVStAKTgQAHJY8j/xgSwIDAQABo1AwTjAdBgNVHQ4EFgQUE6sA
77 77 > +ammr24dGX0kpjxOgO45hzQwHwYDVR0jBBgwFoAUE6sA+ammr24dGX0kpjxOgO45hzQwDAYDVR0T
78 78 > BAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAJfk57DTRf2nUbYaMSlVAARxMNbFGOjQhAUtY400GhKt
79 79 > 2uiKCNGKXVXD3AHWe13yHc5KttzbHQStE5Nm/DlWBWQ=
80 80 > -----END CERTIFICATE-----
81 81 > EOT
82 82 $ cat priv.pem pub-expired.pem > server-expired.pem
83 83
84 84 $ hg init test
85 85 $ cd test
86 86 $ echo foo>foo
87 87 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
88 88 $ echo foo>foo.d/foo
89 89 $ echo bar>foo.d/bAr.hg.d/BaR
90 90 $ echo bar>foo.d/baR.d.hg/bAR
91 91 $ hg commit -A -m 1
92 92 adding foo
93 93 adding foo.d/bAr.hg.d/BaR
94 94 adding foo.d/baR.d.hg/bAR
95 95 adding foo.d/foo
96 96 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV
97 97 $ cat ../hg0.pid >> $DAEMON_PIDS
98 98
99 99 Test server address cannot be reused
100 100
101 101 $ hg serve -p $HGPORT --certificate=$PRIV 2>&1
102 102 abort: cannot start server at ':$HGPORT': Address already in use
103 103 [255]
104 104 $ cd ..
105 105
106 106 clone via pull
107 107
108 108 $ hg clone https://localhost:$HGPORT/ copy-pull
109 109 warning: localhost certificate not verified (check web.cacerts config setting)
110 110 requesting all changes
111 111 adding changesets
112 112 adding manifests
113 113 adding file changes
114 114 added 1 changesets with 4 changes to 4 files
115 115 updating to branch default
116 116 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
117 117 $ hg verify -R copy-pull
118 118 checking changesets
119 119 checking manifests
120 120 crosschecking files in changesets and manifests
121 121 checking files
122 122 4 files, 1 changesets, 4 total revisions
123 123 $ cd test
124 124 $ echo bar > bar
125 125 $ hg commit -A -d '1 0' -m 2
126 126 adding bar
127 127 $ cd ..
128 128
129 129 pull without cacert
130 130
131 131 $ cd copy-pull
132 132 $ echo '[hooks]' >> .hg/hgrc
133 133 $ echo "changegroup = python '$TESTDIR'/printenv.py changegroup" >> .hg/hgrc
134 134 $ hg pull
135 135 warning: localhost certificate not verified (check web.cacerts config setting)
136 136 changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_URL=https://localhost:$HGPORT/
137 137 pulling from https://localhost:$HGPORT/
138 138 searching for changes
139 139 adding changesets
140 140 adding manifests
141 141 adding file changes
142 142 added 1 changesets with 1 changes to 1 files
143 143 (run 'hg update' to get a working copy)
144 144 $ cd ..
145 145
146 146 cacert configured in local repo
147 147
148 148 $ cp copy-pull/.hg/hgrc copy-pull/.hg/hgrc.bu
149 149 $ echo "[web]" >> copy-pull/.hg/hgrc
150 150 $ echo "cacerts=`pwd`/pub.pem" >> copy-pull/.hg/hgrc
151 151 $ hg -R copy-pull pull --traceback
152 152 pulling from https://localhost:$HGPORT/
153 153 searching for changes
154 154 no changes found
155 155 $ mv copy-pull/.hg/hgrc.bu copy-pull/.hg/hgrc
156 156
157 cacert configured globally
157 cacert configured globally, also testing expansion of environment
158 variables in the filename
158 159
159 160 $ echo "[web]" >> $HGRCPATH
160 $ echo "cacerts=`pwd`/pub.pem" >> $HGRCPATH
161 $ hg -R copy-pull pull
161 $ echo 'cacerts=$P/pub.pem' >> $HGRCPATH
162 $ P=`pwd` hg -R copy-pull pull
162 163 pulling from https://localhost:$HGPORT/
163 164 searching for changes
164 165 no changes found
165 166
166 167 cacert mismatch
167 168
168 169 $ hg -R copy-pull pull --config web.cacerts=pub.pem https://127.0.0.1:$HGPORT/
169 170 abort: 127.0.0.1 certificate error: certificate is for localhost
170 171 [255]
171 172 $ hg -R copy-pull pull --config web.cacerts=pub-other.pem
172 173 abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
173 174 [255]
174 175
175 176 Test server cert which isn't valid yet
176 177
177 178 $ hg -R test serve -p $HGPORT1 -d --pid-file=hg1.pid --certificate=server-not-yet.pem
178 179 $ cat hg1.pid >> $DAEMON_PIDS
179 180 $ hg -R copy-pull pull --config web.cacerts=pub-not-yet.pem https://localhost:$HGPORT1/
180 181 abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
181 182 [255]
182 183
183 184 Test server cert which no longer is valid
184 185
185 186 $ hg -R test serve -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem
186 187 $ cat hg2.pid >> $DAEMON_PIDS
187 188 $ hg -R copy-pull pull --config web.cacerts=pub-expired.pem https://localhost:$HGPORT2/
188 189 abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
189 190 [255]
@@ -1,1368 +1,1368 b''
1 1 $ checkundo()
2 2 > {
3 3 > if [ -f .hg/store/undo ]; then
4 4 > echo ".hg/store/undo still exists after $1"
5 5 > fi
6 6 > }
7 7
8 8 $ echo "[extensions]" >> $HGRCPATH
9 9 $ echo "mq=" >> $HGRCPATH
10 10
11 11 $ echo "[mq]" >> $HGRCPATH
12 12 $ echo "plain=true" >> $HGRCPATH
13 13
14 14
15 15 help
16 16
17 17 $ hg help mq
18 18 mq extension - manage a stack of patches
19 19
20 20 This extension lets you work with a stack of patches in a Mercurial
21 21 repository. It manages two stacks of patches - all known patches, and applied
22 22 patches (subset of known patches).
23 23
24 24 Known patches are represented as patch files in the .hg/patches directory.
25 25 Applied patches are both patch files and changesets.
26 26
27 27 Common tasks (use "hg help command" for more details):
28 28
29 29 create new patch qnew
30 30 import existing patch qimport
31 31
32 32 print patch series qseries
33 33 print applied patches qapplied
34 34
35 35 add known patch to applied stack qpush
36 36 remove patch from applied stack qpop
37 37 refresh contents of top applied patch qrefresh
38 38
39 39 By default, mq will automatically use git patches when required to avoid
40 40 losing file mode changes, copy records, binary files or empty files creations
41 41 or deletions. This behaviour can be configured with:
42 42
43 43 [mq]
44 44 git = auto/keep/yes/no
45 45
46 46 If set to 'keep', mq will obey the [diff] section configuration while
47 47 preserving existing git patches upon qrefresh. If set to 'yes' or 'no', mq
48 48 will override the [diff] section and always generate git or regular patches,
49 49 possibly losing data in the second case.
50 50
51 51 You will by default be managing a patch queue named "patches". You can create
52 52 other, independent patch queues with the "hg qqueue" command.
53 53
54 54 list of commands:
55 55
56 56 qapplied print the patches already applied
57 57 qclone clone main and patch repository at same time
58 58 qdelete remove patches from queue
59 59 qdiff diff of the current patch and subsequent modifications
60 60 qfinish move applied patches into repository history
61 61 qfold fold the named patches into the current patch
62 62 qgoto push or pop patches until named patch is at top of stack
63 63 qguard set or print guards for a patch
64 64 qheader print the header of the topmost or specified patch
65 65 qimport import a patch
66 66 qnew create a new patch
67 67 qnext print the name of the next patch
68 68 qpop pop the current patch off the stack
69 69 qprev print the name of the previous patch
70 70 qpush push the next patch onto the stack
71 71 qqueue manage multiple patch queues
72 72 qrefresh update the current patch
73 73 qrename rename a patch
74 74 qselect set or print guarded patches to push
75 75 qseries print the entire series file
76 76 qtop print the name of the current patch
77 77 qunapplied print the patches not yet applied
78 78 strip strip changesets and all their descendants from the repository
79 79
80 use "hg -v help mq" to show aliases and global options
80 use "hg -v help mq" to show builtin aliases and global options
81 81
82 82 $ hg init a
83 83 $ cd a
84 84 $ echo a > a
85 85 $ hg ci -Ama
86 86 adding a
87 87
88 88 $ hg clone . ../k
89 89 updating to branch default
90 90 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 91
92 92 $ mkdir b
93 93 $ echo z > b/z
94 94 $ hg ci -Ama
95 95 adding b/z
96 96
97 97
98 98 qinit
99 99
100 100 $ hg qinit
101 101
102 102 $ cd ..
103 103 $ hg init b
104 104
105 105
106 106 -R qinit
107 107
108 108 $ hg -R b qinit
109 109
110 110 $ hg init c
111 111
112 112
113 113 qinit -c
114 114
115 115 $ hg --cwd c qinit -c
116 116 $ hg -R c/.hg/patches st
117 117 A .hgignore
118 118 A series
119 119
120 120
121 121 qinit; qinit -c
122 122
123 123 $ hg init d
124 124 $ cd d
125 125 $ hg qinit
126 126 $ hg qinit -c
127 127
128 128 qinit -c should create both files if they don't exist
129 129
130 130 $ cat .hg/patches/.hgignore
131 131 ^\.hg
132 132 ^\.mq
133 133 syntax: glob
134 134 status
135 135 guards
136 136 $ cat .hg/patches/series
137 137 $ hg qinit -c
138 138 abort: repository $TESTTMP/d/.hg/patches already exists!
139 139 [255]
140 140 $ cd ..
141 141
142 142 $ echo '% qinit; <stuff>; qinit -c'
143 143 % qinit; <stuff>; qinit -c
144 144 $ hg init e
145 145 $ cd e
146 146 $ hg qnew A
147 147 $ checkundo qnew
148 148 $ echo foo > foo
149 149 $ hg add foo
150 150 $ hg qrefresh
151 151 $ hg qnew B
152 152 $ echo >> foo
153 153 $ hg qrefresh
154 154 $ echo status >> .hg/patches/.hgignore
155 155 $ echo bleh >> .hg/patches/.hgignore
156 156 $ hg qinit -c
157 157 adding .hg/patches/A
158 158 adding .hg/patches/B
159 159 $ hg -R .hg/patches status
160 160 A .hgignore
161 161 A A
162 162 A B
163 163 A series
164 164
165 165 qinit -c shouldn't touch these files if they already exist
166 166
167 167 $ cat .hg/patches/.hgignore
168 168 status
169 169 bleh
170 170 $ cat .hg/patches/series
171 171 A
172 172 B
173 173
174 174 add an untracked file
175 175
176 176 $ echo >> .hg/patches/flaf
177 177
178 178 status --mq with color (issue2096)
179 179
180 180 $ hg status --mq --config extensions.color= --color=always
181 181 \x1b[0;32;1mA .hgignore\x1b[0m (esc)
182 182 \x1b[0;32;1mA A\x1b[0m (esc)
183 183 \x1b[0;32;1mA B\x1b[0m (esc)
184 184 \x1b[0;32;1mA series\x1b[0m (esc)
185 185 \x1b[0;35;1;4m? flaf\x1b[0m (esc)
186 186
187 187 try the --mq option on a command provided by an extension
188 188
189 189 $ hg purge --mq --verbose --config extensions.purge=
190 190 Removing file flaf
191 191
192 192 $ cd ..
193 193
194 194 init --mq without repo
195 195
196 196 $ mkdir f
197 197 $ cd f
198 198 $ hg init --mq
199 199 abort: there is no Mercurial repository here (.hg not found)
200 200 [255]
201 201 $ cd ..
202 202
203 203 init --mq with repo path
204 204
205 205 $ hg init g
206 206 $ hg init --mq g
207 207 $ test -d g/.hg/patches/.hg
208 208
209 209 init --mq with nonexistent directory
210 210
211 211 $ hg init --mq nonexistentdir
212 212 abort: repository nonexistentdir not found!
213 213 [255]
214 214
215 215
216 216 init --mq with bundle (non "local")
217 217
218 218 $ hg -R a bundle --all a.bundle >/dev/null
219 219 $ hg init --mq a.bundle
220 220 abort: only a local queue repository may be initialized
221 221 [255]
222 222
223 223 $ cd a
224 224
225 225 $ hg qnew -m 'foo bar' test.patch
226 226
227 227 $ echo '# comment' > .hg/patches/series.tmp
228 228 $ echo >> .hg/patches/series.tmp # empty line
229 229 $ cat .hg/patches/series >> .hg/patches/series.tmp
230 230 $ mv .hg/patches/series.tmp .hg/patches/series
231 231
232 232
233 233 qrefresh
234 234
235 235 $ echo a >> a
236 236 $ hg qrefresh
237 237 $ cat .hg/patches/test.patch
238 238 foo bar
239 239
240 240 diff -r [a-f0-9]* a (re)
241 241 --- a/a\t(?P<date>.*) (re)
242 242 \+\+\+ b/a\t(?P<date2>.*) (re)
243 243 @@ -1,1 +1,2 @@
244 244 a
245 245 +a
246 246
247 247 empty qrefresh
248 248
249 249 $ hg qrefresh -X a
250 250
251 251 revision:
252 252
253 253 $ hg diff -r -2 -r -1
254 254
255 255 patch:
256 256
257 257 $ cat .hg/patches/test.patch
258 258 foo bar
259 259
260 260
261 261 working dir diff:
262 262
263 263 $ hg diff --nodates -q
264 264 --- a/a
265 265 +++ b/a
266 266 @@ -1,1 +1,2 @@
267 267 a
268 268 +a
269 269
270 270 restore things
271 271
272 272 $ hg qrefresh
273 273 $ checkundo qrefresh
274 274
275 275
276 276 qpop
277 277
278 278 $ hg qpop
279 279 popping test.patch
280 280 patch queue now empty
281 281 $ checkundo qpop
282 282
283 283
284 284 qpush with dump of tag cache
285 285 Dump the tag cache to ensure that it has exactly one head after qpush.
286 286
287 287 $ rm -f .hg/tags.cache
288 288 $ hg tags > /dev/null
289 289
290 290 .hg/tags.cache (pre qpush):
291 291
292 292 $ cat .hg/tags.cache
293 293 1 [\da-f]{40} (re)
294 294
295 295 $ hg qpush
296 296 applying test.patch
297 297 now at: test.patch
298 298 $ hg tags > /dev/null
299 299
300 300 .hg/tags.cache (post qpush):
301 301
302 302 $ cat .hg/tags.cache
303 303 2 [\da-f]{40} (re)
304 304
305 305 $ checkundo qpush
306 306 $ cd ..
307 307
308 308
309 309 pop/push outside repo
310 310 $ hg -R a qpop
311 311 popping test.patch
312 312 patch queue now empty
313 313 $ hg -R a qpush
314 314 applying test.patch
315 315 now at: test.patch
316 316
317 317 $ cd a
318 318 $ hg qnew test2.patch
319 319
320 320 qrefresh in subdir
321 321
322 322 $ cd b
323 323 $ echo a > a
324 324 $ hg add a
325 325 $ hg qrefresh
326 326
327 327 pop/push -a in subdir
328 328
329 329 $ hg qpop -a
330 330 popping test2.patch
331 331 popping test.patch
332 332 patch queue now empty
333 333 $ hg --traceback qpush -a
334 334 applying test.patch
335 335 applying test2.patch
336 336 now at: test2.patch
337 337
338 338
339 339 setting columns & formatted tests truncating (issue1912)
340 340
341 341 $ COLUMNS=4 hg qseries --config ui.formatted=true
342 342 test.patch
343 343 test2.patch
344 344 $ COLUMNS=20 hg qseries --config ui.formatted=true -vs
345 345 0 A test.patch: f...
346 346 1 A test2.patch:
347 347 $ hg qpop
348 348 popping test2.patch
349 349 now at: test.patch
350 350 $ hg qseries -vs
351 351 0 A test.patch: foo bar
352 352 1 U test2.patch:
353 353 $ hg sum | grep mq
354 354 mq: 1 applied, 1 unapplied
355 355 $ hg qpush
356 356 applying test2.patch
357 357 now at: test2.patch
358 358 $ hg sum | grep mq
359 359 mq: 2 applied
360 360 $ hg qapplied
361 361 test.patch
362 362 test2.patch
363 363 $ hg qtop
364 364 test2.patch
365 365
366 366
367 367 prev
368 368
369 369 $ hg qapp -1
370 370 test.patch
371 371
372 372 next
373 373
374 374 $ hg qunapp -1
375 375 all patches applied
376 376 [1]
377 377
378 378 $ hg qpop
379 379 popping test2.patch
380 380 now at: test.patch
381 381
382 382 commit should fail
383 383
384 384 $ hg commit
385 385 abort: cannot commit over an applied mq patch
386 386 [255]
387 387
388 388 push should fail
389 389
390 390 $ hg push ../../k
391 391 pushing to ../../k
392 392 abort: source has mq patches applied
393 393 [255]
394 394
395 395
396 396 import should fail
397 397
398 398 $ hg st .
399 399 $ echo foo >> ../a
400 400 $ hg diff > ../../import.diff
401 401 $ hg revert --no-backup ../a
402 402 $ hg import ../../import.diff
403 403 abort: cannot import over an applied patch
404 404 [255]
405 405 $ hg st
406 406
407 407 import --no-commit should succeed
408 408
409 409 $ hg import --no-commit ../../import.diff
410 410 applying ../../import.diff
411 411 $ hg st
412 412 M a
413 413 $ hg revert --no-backup ../a
414 414
415 415
416 416 qunapplied
417 417
418 418 $ hg qunapplied
419 419 test2.patch
420 420
421 421
422 422 qpush/qpop with index
423 423
424 424 $ hg qnew test1b.patch
425 425 $ echo 1b > 1b
426 426 $ hg add 1b
427 427 $ hg qrefresh
428 428 $ hg qpush 2
429 429 applying test2.patch
430 430 now at: test2.patch
431 431 $ hg qpop 0
432 432 popping test2.patch
433 433 popping test1b.patch
434 434 now at: test.patch
435 435 $ hg qpush test.patch+1
436 436 applying test1b.patch
437 437 now at: test1b.patch
438 438 $ hg qpush test.patch+2
439 439 applying test2.patch
440 440 now at: test2.patch
441 441 $ hg qpop test2.patch-1
442 442 popping test2.patch
443 443 now at: test1b.patch
444 444 $ hg qpop test2.patch-2
445 445 popping test1b.patch
446 446 now at: test.patch
447 447 $ hg qpush test1b.patch+1
448 448 applying test1b.patch
449 449 applying test2.patch
450 450 now at: test2.patch
451 451
452 452
453 453 qpush --move
454 454
455 455 $ hg qpop -a
456 456 popping test2.patch
457 457 popping test1b.patch
458 458 popping test.patch
459 459 patch queue now empty
460 460 $ hg qguard test1b.patch -- -negguard
461 461 $ hg qguard test2.patch -- +posguard
462 462 $ hg qpush --move test2.patch # can't move guarded patch
463 463 cannot push 'test2.patch' - guarded by ['+posguard']
464 464 [1]
465 465 $ hg qselect posguard
466 466 number of unguarded, unapplied patches has changed from 2 to 3
467 467 $ hg qpush --move test2.patch # move to front
468 468 applying test2.patch
469 469 now at: test2.patch
470 470 $ hg qpush --move test1b.patch # negative guard unselected
471 471 applying test1b.patch
472 472 now at: test1b.patch
473 473 $ hg qpush --move test.patch # noop move
474 474 applying test.patch
475 475 now at: test.patch
476 476 $ hg qseries -v
477 477 0 A test2.patch
478 478 1 A test1b.patch
479 479 2 A test.patch
480 480 $ hg qpop -a
481 481 popping test.patch
482 482 popping test1b.patch
483 483 popping test2.patch
484 484 patch queue now empty
485 485
486 486 cleaning up
487 487
488 488 $ hg qselect --none
489 489 guards deactivated
490 490 number of unguarded, unapplied patches has changed from 3 to 2
491 491 $ hg qguard --none test1b.patch
492 492 $ hg qguard --none test2.patch
493 493 $ hg qpush --move test.patch
494 494 applying test.patch
495 495 now at: test.patch
496 496 $ hg qpush --move test1b.patch
497 497 applying test1b.patch
498 498 now at: test1b.patch
499 499 $ hg qpush --move bogus # nonexistent patch
500 500 abort: patch bogus not in series
501 501 [255]
502 502 $ hg qpush --move # no patch
503 503 abort: please specify the patch to move
504 504 [255]
505 505 $ hg qpush --move test.patch # already applied
506 506 abort: cannot push to a previous patch: test.patch
507 507 [255]
508 508 $ hg qpush
509 509 applying test2.patch
510 510 now at: test2.patch
511 511
512 512
513 513 series after move
514 514
515 515 $ cat `hg root`/.hg/patches/series
516 516 test.patch
517 517 test1b.patch
518 518 test2.patch
519 519 # comment
520 520
521 521
522 522
523 523 pop, qapplied, qunapplied
524 524
525 525 $ hg qseries -v
526 526 0 A test.patch
527 527 1 A test1b.patch
528 528 2 A test2.patch
529 529
530 530 qapplied -1 test.patch
531 531
532 532 $ hg qapplied -1 test.patch
533 533 only one patch applied
534 534 [1]
535 535
536 536 qapplied -1 test1b.patch
537 537
538 538 $ hg qapplied -1 test1b.patch
539 539 test.patch
540 540
541 541 qapplied -1 test2.patch
542 542
543 543 $ hg qapplied -1 test2.patch
544 544 test1b.patch
545 545
546 546 qapplied -1
547 547
548 548 $ hg qapplied -1
549 549 test1b.patch
550 550
551 551 qapplied
552 552
553 553 $ hg qapplied
554 554 test.patch
555 555 test1b.patch
556 556 test2.patch
557 557
558 558 qapplied test1b.patch
559 559
560 560 $ hg qapplied test1b.patch
561 561 test.patch
562 562 test1b.patch
563 563
564 564 qunapplied -1
565 565
566 566 $ hg qunapplied -1
567 567 all patches applied
568 568 [1]
569 569
570 570 qunapplied
571 571
572 572 $ hg qunapplied
573 573
574 574 popping
575 575
576 576 $ hg qpop
577 577 popping test2.patch
578 578 now at: test1b.patch
579 579
580 580 qunapplied -1
581 581
582 582 $ hg qunapplied -1
583 583 test2.patch
584 584
585 585 qunapplied
586 586
587 587 $ hg qunapplied
588 588 test2.patch
589 589
590 590 qunapplied test2.patch
591 591
592 592 $ hg qunapplied test2.patch
593 593
594 594 qunapplied -1 test2.patch
595 595
596 596 $ hg qunapplied -1 test2.patch
597 597 all patches applied
598 598 [1]
599 599
600 600 popping -a
601 601
602 602 $ hg qpop -a
603 603 popping test1b.patch
604 604 popping test.patch
605 605 patch queue now empty
606 606
607 607 qapplied
608 608
609 609 $ hg qapplied
610 610
611 611 qapplied -1
612 612
613 613 $ hg qapplied -1
614 614 no patches applied
615 615 [1]
616 616 $ hg qpush
617 617 applying test.patch
618 618 now at: test.patch
619 619
620 620
621 621 push should succeed
622 622
623 623 $ hg qpop -a
624 624 popping test.patch
625 625 patch queue now empty
626 626 $ hg push ../../k
627 627 pushing to ../../k
628 628 searching for changes
629 629 adding changesets
630 630 adding manifests
631 631 adding file changes
632 632 added 1 changesets with 1 changes to 1 files
633 633
634 634
635 635 we want to start with some patches applied
636 636
637 637 $ hg qpush -a
638 638 applying test.patch
639 639 applying test1b.patch
640 640 applying test2.patch
641 641 now at: test2.patch
642 642
643 643 % pops all patches and succeeds
644 644
645 645 $ hg qpop -a
646 646 popping test2.patch
647 647 popping test1b.patch
648 648 popping test.patch
649 649 patch queue now empty
650 650
651 651 % does nothing and succeeds
652 652
653 653 $ hg qpop -a
654 654 no patches applied
655 655
656 656 % fails - nothing else to pop
657 657
658 658 $ hg qpop
659 659 no patches applied
660 660 [1]
661 661
662 662 % pushes a patch and succeeds
663 663
664 664 $ hg qpush
665 665 applying test.patch
666 666 now at: test.patch
667 667
668 668 % pops a patch and succeeds
669 669
670 670 $ hg qpop
671 671 popping test.patch
672 672 patch queue now empty
673 673
674 674 % pushes up to test1b.patch and succeeds
675 675
676 676 $ hg qpush test1b.patch
677 677 applying test.patch
678 678 applying test1b.patch
679 679 now at: test1b.patch
680 680
681 681 % does nothing and succeeds
682 682
683 683 $ hg qpush test1b.patch
684 684 qpush: test1b.patch is already at the top
685 685
686 686 % does nothing and succeeds
687 687
688 688 $ hg qpop test1b.patch
689 689 qpop: test1b.patch is already at the top
690 690
691 691 % fails - can't push to this patch
692 692
693 693 $ hg qpush test.patch
694 694 abort: cannot push to a previous patch: test.patch
695 695 [255]
696 696
697 697 % fails - can't pop to this patch
698 698
699 699 $ hg qpop test2.patch
700 700 abort: patch test2.patch is not applied
701 701 [255]
702 702
703 703 % pops up to test.patch and succeeds
704 704
705 705 $ hg qpop test.patch
706 706 popping test1b.patch
707 707 now at: test.patch
708 708
709 709 % pushes all patches and succeeds
710 710
711 711 $ hg qpush -a
712 712 applying test1b.patch
713 713 applying test2.patch
714 714 now at: test2.patch
715 715
716 716 % does nothing and succeeds
717 717
718 718 $ hg qpush -a
719 719 all patches are currently applied
720 720
721 721 % fails - nothing else to push
722 722
723 723 $ hg qpush
724 724 patch series already fully applied
725 725 [1]
726 726
727 727 % does nothing and succeeds
728 728
729 729 $ hg qpush test2.patch
730 730 qpush: test2.patch is already at the top
731 731
732 732 strip
733 733
734 734 $ cd ../../b
735 735 $ echo x>x
736 736 $ hg ci -Ama
737 737 adding x
738 738 $ hg strip tip
739 739 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
740 740 saved backup bundle to $TESTTMP/b/.hg/strip-backup/*-backup.hg (glob)
741 741 $ hg unbundle .hg/strip-backup/*
742 742 adding changesets
743 743 adding manifests
744 744 adding file changes
745 745 added 1 changesets with 1 changes to 1 files
746 746 (run 'hg update' to get a working copy)
747 747
748 748
749 749 strip with local changes, should complain
750 750
751 751 $ hg up
752 752 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
753 753 $ echo y>y
754 754 $ hg add y
755 755 $ hg strip tip
756 756 abort: local changes found
757 757 [255]
758 758
759 759 --force strip with local changes
760 760
761 761 $ hg strip -f tip
762 762 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
763 763 saved backup bundle to $TESTTMP/b/.hg/strip-backup/*-backup.hg (glob)
764 764
765 765
766 766 cd b; hg qrefresh
767 767
768 768 $ hg init refresh
769 769 $ cd refresh
770 770 $ echo a > a
771 771 $ hg ci -Ama
772 772 adding a
773 773 $ hg qnew -mfoo foo
774 774 $ echo a >> a
775 775 $ hg qrefresh
776 776 $ mkdir b
777 777 $ cd b
778 778 $ echo f > f
779 779 $ hg add f
780 780 $ hg qrefresh
781 781 $ cat ../.hg/patches/foo
782 782 foo
783 783
784 784 diff -r cb9a9f314b8b a
785 785 --- a/a\t(?P<date>.*) (re)
786 786 \+\+\+ b/a\t(?P<date>.*) (re)
787 787 @@ -1,1 +1,2 @@
788 788 a
789 789 +a
790 790 diff -r cb9a9f314b8b b/f
791 791 --- /dev/null\t(?P<date>.*) (re)
792 792 \+\+\+ b/b/f\t(?P<date>.*) (re)
793 793 @@ -0,0 +1,1 @@
794 794 +f
795 795
796 796 hg qrefresh .
797 797
798 798 $ hg qrefresh .
799 799 $ cat ../.hg/patches/foo
800 800 foo
801 801
802 802 diff -r cb9a9f314b8b b/f
803 803 --- /dev/null\t(?P<date>.*) (re)
804 804 \+\+\+ b/b/f\t(?P<date>.*) (re)
805 805 @@ -0,0 +1,1 @@
806 806 +f
807 807 $ hg status
808 808 M a
809 809
810 810
811 811 qpush failure
812 812
813 813 $ cd ..
814 814 $ hg qrefresh
815 815 $ hg qnew -mbar bar
816 816 $ echo foo > foo
817 817 $ echo bar > bar
818 818 $ hg add foo bar
819 819 $ hg qrefresh
820 820 $ hg qpop -a
821 821 popping bar
822 822 popping foo
823 823 patch queue now empty
824 824 $ echo bar > foo
825 825 $ hg qpush -a
826 826 applying foo
827 827 applying bar
828 828 file foo already exists
829 829 1 out of 1 hunks FAILED -- saving rejects to file foo.rej
830 830 patch failed, unable to continue (try -v)
831 831 patch failed, rejects left in working dir
832 832 errors during apply, please fix and refresh bar
833 833 [2]
834 834 $ hg st
835 835 ? foo
836 836 ? foo.rej
837 837
838 838
839 839 mq tags
840 840
841 841 $ hg log --template '{rev} {tags}\n' -r qparent:qtip
842 842 0 qparent
843 843 1 foo qbase
844 844 2 bar qtip tip
845 845
846 846
847 847 bad node in status
848 848
849 849 $ hg qpop
850 850 popping bar
851 851 now at: foo
852 852 $ hg strip -qn tip
853 853 $ hg tip
854 854 changeset: 0:cb9a9f314b8b
855 855 tag: tip
856 856 user: test
857 857 date: Thu Jan 01 00:00:00 1970 +0000
858 858 summary: a
859 859
860 860 $ hg branches
861 861 default 0:cb9a9f314b8b
862 862 $ hg qpop
863 863 no patches applied
864 864 [1]
865 865
866 866 $ cat >>$HGRCPATH <<EOF
867 867 > [diff]
868 868 > git = True
869 869 > EOF
870 870 $ cd ..
871 871 $ hg init git
872 872 $ cd git
873 873 $ hg qinit
874 874
875 875 $ hg qnew -m'new file' new
876 876 $ echo foo > new
877 877 $ chmod +x new
878 878 $ hg add new
879 879 $ hg qrefresh
880 880 $ cat .hg/patches/new
881 881 new file
882 882
883 883 diff --git a/new b/new
884 884 new file mode 100755
885 885 --- /dev/null
886 886 +++ b/new
887 887 @@ -0,0 +1,1 @@
888 888 +foo
889 889
890 890 $ hg qnew -m'copy file' copy
891 891 $ hg cp new copy
892 892 $ hg qrefresh
893 893 $ cat .hg/patches/copy
894 894 copy file
895 895
896 896 diff --git a/new b/copy
897 897 copy from new
898 898 copy to copy
899 899
900 900 $ hg qpop
901 901 popping copy
902 902 now at: new
903 903 $ hg qpush
904 904 applying copy
905 905 now at: copy
906 906 $ hg qdiff
907 907 diff --git a/new b/copy
908 908 copy from new
909 909 copy to copy
910 910 $ cat >>$HGRCPATH <<EOF
911 911 > [diff]
912 912 > git = False
913 913 > EOF
914 914 $ hg qdiff --git
915 915 diff --git a/new b/copy
916 916 copy from new
917 917 copy to copy
918 918 $ cd ..
919 919
920 920
921 921 test file addition in slow path
922 922
923 923 $ hg init slow
924 924 $ cd slow
925 925 $ hg qinit
926 926 $ echo foo > foo
927 927 $ hg add foo
928 928 $ hg ci -m 'add foo'
929 929 $ hg qnew bar
930 930 $ echo bar > bar
931 931 $ hg add bar
932 932 $ hg mv foo baz
933 933 $ hg qrefresh --git
934 934 $ hg up -C 0
935 935 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
936 936 $ echo >> foo
937 937 $ hg ci -m 'change foo'
938 938 created new head
939 939 $ hg up -C 1
940 940 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
941 941 $ hg qrefresh --git
942 942 $ cat .hg/patches/bar
943 943 diff --git a/bar b/bar
944 944 new file mode 100644
945 945 --- /dev/null
946 946 +++ b/bar
947 947 @@ -0,0 +1,1 @@
948 948 +bar
949 949 diff --git a/foo b/baz
950 950 rename from foo
951 951 rename to baz
952 952 $ hg log -v --template '{rev} {file_copies}\n' -r .
953 953 2 baz (foo)
954 954 $ hg qrefresh --git
955 955 $ cat .hg/patches/bar
956 956 diff --git a/bar b/bar
957 957 new file mode 100644
958 958 --- /dev/null
959 959 +++ b/bar
960 960 @@ -0,0 +1,1 @@
961 961 +bar
962 962 diff --git a/foo b/baz
963 963 rename from foo
964 964 rename to baz
965 965 $ hg log -v --template '{rev} {file_copies}\n' -r .
966 966 2 baz (foo)
967 967 $ hg qrefresh
968 968 $ grep 'diff --git' .hg/patches/bar
969 969 diff --git a/bar b/bar
970 970 diff --git a/foo b/baz
971 971
972 972
973 973 test file move chains in the slow path
974 974
975 975 $ hg up -C 1
976 976 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
977 977 $ echo >> foo
978 978 $ hg ci -m 'change foo again'
979 979 $ hg up -C 2
980 980 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
981 981 $ hg mv bar quux
982 982 $ hg mv baz bleh
983 983 $ hg qrefresh --git
984 984 $ cat .hg/patches/bar
985 985 diff --git a/foo b/bleh
986 986 rename from foo
987 987 rename to bleh
988 988 diff --git a/quux b/quux
989 989 new file mode 100644
990 990 --- /dev/null
991 991 +++ b/quux
992 992 @@ -0,0 +1,1 @@
993 993 +bar
994 994 $ hg log -v --template '{rev} {file_copies}\n' -r .
995 995 3 bleh (foo)
996 996 $ hg mv quux fred
997 997 $ hg mv bleh barney
998 998 $ hg qrefresh --git
999 999 $ cat .hg/patches/bar
1000 1000 diff --git a/foo b/barney
1001 1001 rename from foo
1002 1002 rename to barney
1003 1003 diff --git a/fred b/fred
1004 1004 new file mode 100644
1005 1005 --- /dev/null
1006 1006 +++ b/fred
1007 1007 @@ -0,0 +1,1 @@
1008 1008 +bar
1009 1009 $ hg log -v --template '{rev} {file_copies}\n' -r .
1010 1010 3 barney (foo)
1011 1011
1012 1012
1013 1013 refresh omitting an added file
1014 1014
1015 1015 $ hg qnew baz
1016 1016 $ echo newfile > newfile
1017 1017 $ hg add newfile
1018 1018 $ hg qrefresh
1019 1019 $ hg st -A newfile
1020 1020 C newfile
1021 1021 $ hg qrefresh -X newfile
1022 1022 $ hg st -A newfile
1023 1023 A newfile
1024 1024 $ hg revert newfile
1025 1025 $ rm newfile
1026 1026 $ hg qpop
1027 1027 popping baz
1028 1028 now at: bar
1029 1029 $ hg qdel baz
1030 1030
1031 1031
1032 1032 create a git patch
1033 1033
1034 1034 $ echo a > alexander
1035 1035 $ hg add alexander
1036 1036 $ hg qnew -f --git addalexander
1037 1037 $ grep diff .hg/patches/addalexander
1038 1038 diff --git a/alexander b/alexander
1039 1039
1040 1040
1041 1041 create a git binary patch
1042 1042
1043 1043 $ cat > writebin.py <<EOF
1044 1044 > import sys
1045 1045 > path = sys.argv[1]
1046 1046 > open(path, 'wb').write('BIN\x00ARY')
1047 1047 > EOF
1048 1048 $ python writebin.py bucephalus
1049 1049
1050 1050 $ python "$TESTDIR/md5sum.py" bucephalus
1051 1051 8ba2a2f3e77b55d03051ff9c24ad65e7 bucephalus
1052 1052 $ hg add bucephalus
1053 1053 $ hg qnew -f --git addbucephalus
1054 1054 $ grep diff .hg/patches/addbucephalus
1055 1055 diff --git a/bucephalus b/bucephalus
1056 1056
1057 1057
1058 1058 check binary patches can be popped and pushed
1059 1059
1060 1060 $ hg qpop
1061 1061 popping addbucephalus
1062 1062 now at: addalexander
1063 1063 $ test -f bucephalus && echo % bucephalus should not be there
1064 1064 [1]
1065 1065 $ hg qpush
1066 1066 applying addbucephalus
1067 1067 now at: addbucephalus
1068 1068 $ test -f bucephalus
1069 1069 $ python "$TESTDIR/md5sum.py" bucephalus
1070 1070 8ba2a2f3e77b55d03051ff9c24ad65e7 bucephalus
1071 1071
1072 1072
1073 1073
1074 1074 strip again
1075 1075
1076 1076 $ cd ..
1077 1077 $ hg init strip
1078 1078 $ cd strip
1079 1079 $ touch foo
1080 1080 $ hg add foo
1081 1081 $ hg ci -m 'add foo'
1082 1082 $ echo >> foo
1083 1083 $ hg ci -m 'change foo 1'
1084 1084 $ hg up -C 0
1085 1085 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1086 1086 $ echo 1 >> foo
1087 1087 $ hg ci -m 'change foo 2'
1088 1088 created new head
1089 1089 $ HGMERGE=true hg merge
1090 1090 merging foo
1091 1091 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1092 1092 (branch merge, don't forget to commit)
1093 1093 $ hg ci -m merge
1094 1094 $ hg log
1095 1095 changeset: 3:99615015637b
1096 1096 tag: tip
1097 1097 parent: 2:20cbbe65cff7
1098 1098 parent: 1:d2871fc282d4
1099 1099 user: test
1100 1100 date: Thu Jan 01 00:00:00 1970 +0000
1101 1101 summary: merge
1102 1102
1103 1103 changeset: 2:20cbbe65cff7
1104 1104 parent: 0:53245c60e682
1105 1105 user: test
1106 1106 date: Thu Jan 01 00:00:00 1970 +0000
1107 1107 summary: change foo 2
1108 1108
1109 1109 changeset: 1:d2871fc282d4
1110 1110 user: test
1111 1111 date: Thu Jan 01 00:00:00 1970 +0000
1112 1112 summary: change foo 1
1113 1113
1114 1114 changeset: 0:53245c60e682
1115 1115 user: test
1116 1116 date: Thu Jan 01 00:00:00 1970 +0000
1117 1117 summary: add foo
1118 1118
1119 1119 $ hg strip 1
1120 1120 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1121 1121 saved backup bundle to $TESTTMP/b/strip/.hg/strip-backup/*-backup.hg (glob)
1122 1122 $ checkundo strip
1123 1123 $ hg log
1124 1124 changeset: 1:20cbbe65cff7
1125 1125 tag: tip
1126 1126 user: test
1127 1127 date: Thu Jan 01 00:00:00 1970 +0000
1128 1128 summary: change foo 2
1129 1129
1130 1130 changeset: 0:53245c60e682
1131 1131 user: test
1132 1132 date: Thu Jan 01 00:00:00 1970 +0000
1133 1133 summary: add foo
1134 1134
1135 1135 $ cd ..
1136 1136
1137 1137
1138 1138 qclone
1139 1139
1140 1140 $ qlog()
1141 1141 > {
1142 1142 > echo 'main repo:'
1143 1143 > hg log --template ' rev {rev}: {desc}\n'
1144 1144 > echo 'patch repo:'
1145 1145 > hg -R .hg/patches log --template ' rev {rev}: {desc}\n'
1146 1146 > }
1147 1147 $ hg init qclonesource
1148 1148 $ cd qclonesource
1149 1149 $ echo foo > foo
1150 1150 $ hg add foo
1151 1151 $ hg ci -m 'add foo'
1152 1152 $ hg qinit
1153 1153 $ hg qnew patch1
1154 1154 $ echo bar >> foo
1155 1155 $ hg qrefresh -m 'change foo'
1156 1156 $ cd ..
1157 1157
1158 1158
1159 1159 repo with unversioned patch dir
1160 1160
1161 1161 $ hg qclone qclonesource failure
1162 1162 abort: versioned patch repository not found (see init --mq)
1163 1163 [255]
1164 1164
1165 1165 $ cd qclonesource
1166 1166 $ hg qinit -c
1167 1167 adding .hg/patches/patch1
1168 1168 $ hg qci -m checkpoint
1169 1169 $ qlog
1170 1170 main repo:
1171 1171 rev 1: change foo
1172 1172 rev 0: add foo
1173 1173 patch repo:
1174 1174 rev 0: checkpoint
1175 1175 $ cd ..
1176 1176
1177 1177
1178 1178 repo with patches applied
1179 1179
1180 1180 $ hg qclone qclonesource qclonedest
1181 1181 updating to branch default
1182 1182 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1183 1183 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1184 1184 $ cd qclonedest
1185 1185 $ qlog
1186 1186 main repo:
1187 1187 rev 0: add foo
1188 1188 patch repo:
1189 1189 rev 0: checkpoint
1190 1190 $ cd ..
1191 1191
1192 1192
1193 1193 repo with patches unapplied
1194 1194
1195 1195 $ cd qclonesource
1196 1196 $ hg qpop -a
1197 1197 popping patch1
1198 1198 patch queue now empty
1199 1199 $ qlog
1200 1200 main repo:
1201 1201 rev 0: add foo
1202 1202 patch repo:
1203 1203 rev 0: checkpoint
1204 1204 $ cd ..
1205 1205 $ hg qclone qclonesource qclonedest2
1206 1206 updating to branch default
1207 1207 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1208 1208 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1209 1209 $ cd qclonedest2
1210 1210 $ qlog
1211 1211 main repo:
1212 1212 rev 0: add foo
1213 1213 patch repo:
1214 1214 rev 0: checkpoint
1215 1215 $ cd ..
1216 1216
1217 1217
1218 1218 Issue1033: test applying on an empty file
1219 1219
1220 1220 $ hg init empty
1221 1221 $ cd empty
1222 1222 $ touch a
1223 1223 $ hg ci -Am addempty
1224 1224 adding a
1225 1225 $ echo a > a
1226 1226 $ hg qnew -f -e changea
1227 1227 $ hg qpop
1228 1228 popping changea
1229 1229 patch queue now empty
1230 1230 $ hg qpush
1231 1231 applying changea
1232 1232 now at: changea
1233 1233 $ cd ..
1234 1234
1235 1235
1236 1236 test qpush with --force, issue1087
1237 1237
1238 1238 $ hg init forcepush
1239 1239 $ cd forcepush
1240 1240 $ echo hello > hello.txt
1241 1241 $ echo bye > bye.txt
1242 1242 $ hg ci -Ama
1243 1243 adding bye.txt
1244 1244 adding hello.txt
1245 1245 $ hg qnew -d '0 0' empty
1246 1246 $ hg qpop
1247 1247 popping empty
1248 1248 patch queue now empty
1249 1249 $ echo world >> hello.txt
1250 1250
1251 1251
1252 1252 qpush should fail, local changes
1253 1253
1254 1254 $ hg qpush
1255 1255 abort: local changes found, refresh first
1256 1256 [255]
1257 1257
1258 1258
1259 1259 apply force, should not discard changes with empty patch
1260 1260
1261 1261 $ hg qpush -f
1262 1262 applying empty
1263 1263 patch empty is empty
1264 1264 now at: empty
1265 1265 $ hg diff --config diff.nodates=True
1266 1266 diff -r bf5fc3f07a0a hello.txt
1267 1267 --- a/hello.txt
1268 1268 +++ b/hello.txt
1269 1269 @@ -1,1 +1,2 @@
1270 1270 hello
1271 1271 +world
1272 1272 $ hg qdiff --config diff.nodates=True
1273 1273 diff -r 9ecee4f634e3 hello.txt
1274 1274 --- a/hello.txt
1275 1275 +++ b/hello.txt
1276 1276 @@ -1,1 +1,2 @@
1277 1277 hello
1278 1278 +world
1279 1279 $ hg log -l1 -p
1280 1280 changeset: 1:bf5fc3f07a0a
1281 1281 tag: empty
1282 1282 tag: qbase
1283 1283 tag: qtip
1284 1284 tag: tip
1285 1285 user: test
1286 1286 date: Thu Jan 01 00:00:00 1970 +0000
1287 1287 summary: imported patch empty
1288 1288
1289 1289
1290 1290 $ hg qref -d '0 0'
1291 1291 $ hg qpop
1292 1292 popping empty
1293 1293 patch queue now empty
1294 1294 $ echo universe >> hello.txt
1295 1295 $ echo universe >> bye.txt
1296 1296
1297 1297
1298 1298 qpush should fail, local changes
1299 1299
1300 1300 $ hg qpush
1301 1301 abort: local changes found, refresh first
1302 1302 [255]
1303 1303
1304 1304
1305 1305 apply force, should discard changes in hello, but not bye
1306 1306
1307 1307 $ hg qpush -f
1308 1308 applying empty
1309 1309 now at: empty
1310 1310 $ hg st
1311 1311 M bye.txt
1312 1312 $ hg diff --config diff.nodates=True
1313 1313 diff -r ba252371dbc1 bye.txt
1314 1314 --- a/bye.txt
1315 1315 +++ b/bye.txt
1316 1316 @@ -1,1 +1,2 @@
1317 1317 bye
1318 1318 +universe
1319 1319 $ hg qdiff --config diff.nodates=True
1320 1320 diff -r 9ecee4f634e3 bye.txt
1321 1321 --- a/bye.txt
1322 1322 +++ b/bye.txt
1323 1323 @@ -1,1 +1,2 @@
1324 1324 bye
1325 1325 +universe
1326 1326 diff -r 9ecee4f634e3 hello.txt
1327 1327 --- a/hello.txt
1328 1328 +++ b/hello.txt
1329 1329 @@ -1,1 +1,3 @@
1330 1330 hello
1331 1331 +world
1332 1332 +universe
1333 1333
1334 1334
1335 1335 test popping revisions not in working dir ancestry
1336 1336
1337 1337 $ hg qseries -v
1338 1338 0 A empty
1339 1339 $ hg up qparent
1340 1340 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1341 1341 $ hg qpop
1342 1342 popping empty
1343 1343 patch queue now empty
1344 1344
1345 1345 $ cd ..
1346 1346 $ hg init deletion-order
1347 1347 $ cd deletion-order
1348 1348
1349 1349 $ touch a
1350 1350 $ hg ci -Aqm0
1351 1351
1352 1352 $ hg qnew rename-dir
1353 1353 $ hg rm a
1354 1354 $ hg qrefresh
1355 1355
1356 1356 $ mkdir a b
1357 1357 $ touch a/a b/b
1358 1358 $ hg add -q a b
1359 1359 $ hg qrefresh
1360 1360
1361 1361
1362 1362 test popping must remove files added in subdirectories first
1363 1363
1364 1364 $ hg qpop
1365 1365 popping rename-dir
1366 1366 patch queue now empty
1367 1367 $ cd ..
1368 1368
@@ -1,658 +1,677 b''
1 1 $ rm -rf sub
2 2 $ mkdir sub
3 3 $ cd sub
4 4 $ hg init t
5 5 $ cd t
6 6
7 7 first revision, no sub
8 8
9 9 $ echo a > a
10 10 $ hg ci -Am0
11 11 adding a
12 12
13 13 add first sub
14 14
15 15 $ echo s = s > .hgsub
16 16 $ hg add .hgsub
17 17 $ hg init s
18 18 $ echo a > s/a
19 19
20 20 Issue2232: committing a subrepo without .hgsub
21 21
22 22 $ hg ci -mbad s
23 23 abort: can't commit subrepos without .hgsub
24 24 [255]
25 25
26 26 $ hg -R s ci -Ams0
27 27 adding a
28 28 $ hg sum
29 29 parent: 0:f7b1eb17ad24 tip
30 30 0
31 31 branch: default
32 32 commit: 1 added, 1 subrepos
33 33 update: (current)
34 34 $ hg ci -m1
35 35 committing subrepository s
36 36
37 37 Issue2022: update -C
38 38
39 39 $ echo b > s/a
40 40 $ hg sum
41 41 parent: 1:7cf8cfea66e4 tip
42 42 1
43 43 branch: default
44 44 commit: 1 subrepos
45 45 update: (current)
46 46 $ hg co -C 1
47 47 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 48 $ hg sum
49 49 parent: 1:7cf8cfea66e4 tip
50 50 1
51 51 branch: default
52 52 commit: (clean)
53 53 update: (current)
54 54
55 55 add sub sub
56 56
57 57 $ echo ss = ss > s/.hgsub
58 58 $ hg init s/ss
59 59 $ echo a > s/ss/a
60 60 $ hg -R s add s/.hgsub
61 61 $ hg -R s/ss add s/ss/a
62 62 $ hg sum
63 63 parent: 1:7cf8cfea66e4 tip
64 64 1
65 65 branch: default
66 66 commit: 1 subrepos
67 67 update: (current)
68 68 $ hg ci -m2
69 69 committing subrepository s
70 70 committing subrepository s/ss
71 71 $ hg sum
72 72 parent: 2:df30734270ae tip
73 73 2
74 74 branch: default
75 75 commit: (clean)
76 76 update: (current)
77 77
78 78 bump sub rev
79 79
80 80 $ echo b > s/a
81 81 $ hg -R s ci -ms1
82 82 $ hg ci -m3
83 83 committing subrepository s
84 84
85 85 leave sub dirty
86 86
87 87 $ echo c > s/a
88 88 $ hg ci -m4
89 89 committing subrepository s
90 90 $ hg tip -R s
91 91 changeset: 3:1c833a7a9e3a
92 92 tag: tip
93 93 user: test
94 94 date: Thu Jan 01 00:00:00 1970 +0000
95 95 summary: 4
96 96
97 97
98 98 check caching
99 99
100 100 $ hg co 0
101 101 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
102 102 $ hg debugsub
103 103
104 104 restore
105 105
106 106 $ hg co
107 107 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
108 108 $ hg debugsub
109 109 path s
110 110 source s
111 111 revision 1c833a7a9e3a4445c711aaf0f012379cd0d4034e
112 112
113 113 new branch for merge tests
114 114
115 115 $ hg co 1
116 116 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
117 117 $ echo t = t >> .hgsub
118 118 $ hg init t
119 119 $ echo t > t/t
120 120 $ hg -R t add t
121 121 adding t/t
122 122
123 123 5
124 124
125 125 $ hg ci -m5 # add sub
126 126 committing subrepository t
127 127 created new head
128 128 $ echo t2 > t/t
129 129
130 130 6
131 131
132 132 $ hg st -R s
133 133 $ hg ci -m6 # change sub
134 134 committing subrepository t
135 135 $ hg debugsub
136 136 path s
137 137 source s
138 138 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
139 139 path t
140 140 source t
141 141 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
142 142 $ echo t3 > t/t
143 143
144 144 7
145 145
146 146 $ hg ci -m7 # change sub again for conflict test
147 147 committing subrepository t
148 148 $ hg rm .hgsub
149 149
150 150 8
151 151
152 152 $ hg ci -m8 # remove sub
153 153
154 154 merge tests
155 155
156 156 $ hg co -C 3
157 157 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
158 158 $ hg merge 5 # test adding
159 159 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 160 (branch merge, don't forget to commit)
161 161 $ hg debugsub
162 162 path s
163 163 source s
164 164 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
165 165 path t
166 166 source t
167 167 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
168 168 $ hg ci -m9
169 169 created new head
170 170 $ hg merge 6 --debug # test change
171 171 searching for copies back to rev 2
172 172 resolving manifests
173 173 overwrite None partial False
174 174 ancestor 1f14a2e2d3ec local f0d2028bf86d+ remote 1831e14459c4
175 175 .hgsubstate: versions differ -> m
176 176 updating: .hgsubstate 1/1 files (100.00%)
177 177 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
178 178 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
179 179 getting subrepo t
180 180 resolving manifests
181 181 overwrite True partial False
182 182 ancestor 60ca1237c194+ local 60ca1237c194+ remote 6747d179aa9a
183 183 t: remote is newer -> g
184 184 updating: t 1/1 files (100.00%)
185 185 getting t
186 186 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
187 187 (branch merge, don't forget to commit)
188 188 $ hg debugsub
189 189 path s
190 190 source s
191 191 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
192 192 path t
193 193 source t
194 194 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
195 195 $ echo conflict > t/t
196 196 $ hg ci -m10
197 197 committing subrepository t
198 198 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
199 199 searching for copies back to rev 2
200 200 resolving manifests
201 201 overwrite None partial False
202 202 ancestor 1831e14459c4 local e45c8b14af55+ remote f94576341bcf
203 203 .hgsubstate: versions differ -> m
204 204 updating: .hgsubstate 1/1 files (100.00%)
205 205 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
206 206 subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
207 207 merging subrepo t
208 208 searching for copies back to rev 2
209 209 resolving manifests
210 210 overwrite None partial False
211 211 ancestor 6747d179aa9a local 20a0db6fbf6c+ remote 7af322bc1198
212 212 t: versions differ -> m
213 213 preserving t for resolve of t
214 214 updating: t 1/1 files (100.00%)
215 215 picked tool 'internal:merge' for t (binary False symlink False)
216 216 merging t
217 217 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
218 218 warning: conflicts during merge.
219 219 merging t failed!
220 220 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
221 221 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
222 222 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
223 223 (branch merge, don't forget to commit)
224 224
225 225 should conflict
226 226
227 227 $ cat t/t
228 228 <<<<<<< local
229 229 conflict
230 230 =======
231 231 t3
232 232 >>>>>>> other
233 233
234 234 clone
235 235
236 236 $ cd ..
237 237 $ hg clone t tc
238 238 updating to branch default
239 239 pulling subrepo s from $TESTTMP/sub/t/s
240 240 requesting all changes
241 241 adding changesets
242 242 adding manifests
243 243 adding file changes
244 244 added 4 changesets with 5 changes to 3 files
245 245 pulling subrepo s/ss from $TESTTMP/sub/t/s/ss
246 246 requesting all changes
247 247 adding changesets
248 248 adding manifests
249 249 adding file changes
250 250 added 1 changesets with 1 changes to 1 files
251 251 pulling subrepo t from $TESTTMP/sub/t/t
252 252 requesting all changes
253 253 adding changesets
254 254 adding manifests
255 255 adding file changes
256 256 added 4 changesets with 4 changes to 1 files (+1 heads)
257 257 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
258 258 $ cd tc
259 259 $ hg debugsub
260 260 path s
261 261 source s
262 262 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
263 263 path t
264 264 source t
265 265 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
266 266
267 267 push
268 268
269 269 $ echo bah > t/t
270 270 $ hg ci -m11
271 271 committing subrepository t
272 272 $ hg push
273 273 pushing to $TESTTMP/sub/t
274 274 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
275 275 searching for changes
276 276 no changes found
277 277 pushing subrepo s to $TESTTMP/sub/t/s
278 278 searching for changes
279 279 no changes found
280 280 pushing subrepo t to $TESTTMP/sub/t/t
281 281 searching for changes
282 282 adding changesets
283 283 adding manifests
284 284 adding file changes
285 285 added 1 changesets with 1 changes to 1 files
286 286 searching for changes
287 287 adding changesets
288 288 adding manifests
289 289 adding file changes
290 290 added 1 changesets with 1 changes to 1 files
291 291
292 292 push -f
293 293
294 294 $ echo bah > s/a
295 295 $ hg ci -m12
296 296 committing subrepository s
297 297 $ hg push
298 298 pushing to $TESTTMP/sub/t
299 299 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
300 300 searching for changes
301 301 no changes found
302 302 pushing subrepo s to $TESTTMP/sub/t/s
303 303 searching for changes
304 304 abort: push creates new remote heads on branch 'default'!
305 305 (did you forget to merge? use push -f to force)
306 306 [255]
307 307 $ hg push -f
308 308 pushing to $TESTTMP/sub/t
309 309 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
310 310 searching for changes
311 311 no changes found
312 312 pushing subrepo s to $TESTTMP/sub/t/s
313 313 searching for changes
314 314 adding changesets
315 315 adding manifests
316 316 adding file changes
317 317 added 1 changesets with 1 changes to 1 files (+1 heads)
318 318 pushing subrepo t to $TESTTMP/sub/t/t
319 319 searching for changes
320 320 no changes found
321 321 searching for changes
322 322 adding changesets
323 323 adding manifests
324 324 adding file changes
325 325 added 1 changesets with 1 changes to 1 files
326 326
327 327 update
328 328
329 329 $ cd ../t
330 330 $ hg up -C # discard our earlier merge
331 331 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
332 332 $ echo blah > t/t
333 333 $ hg ci -m13
334 334 committing subrepository t
335 335
336 336 pull
337 337
338 338 $ cd ../tc
339 339 $ hg pull
340 340 pulling from $TESTTMP/sub/t
341 341 searching for changes
342 342 adding changesets
343 343 adding manifests
344 344 adding file changes
345 345 added 1 changesets with 1 changes to 1 files
346 346 (run 'hg update' to get a working copy)
347 347
348 348 should pull t
349 349
350 350 $ hg up
351 351 pulling subrepo t from $TESTTMP/sub/t/t
352 352 searching for changes
353 353 adding changesets
354 354 adding manifests
355 355 adding file changes
356 356 added 1 changesets with 1 changes to 1 files
357 357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
358 358 $ cat t/t
359 359 blah
360 360
361 361 bogus subrepo path aborts
362 362
363 363 $ echo 'bogus=[boguspath' >> .hgsub
364 364 $ hg ci -m 'bogus subrepo path'
365 365 abort: missing ] in subrepo source
366 366 [255]
367 367
368 368 Issue1986: merge aborts when trying to merge a subrepo that
369 369 shouldn't need merging
370 370
371 371 # subrepo layout
372 372 #
373 373 # o 5 br
374 374 # /|
375 375 # o | 4 default
376 376 # | |
377 377 # | o 3 br
378 378 # |/|
379 379 # o | 2 default
380 380 # | |
381 381 # | o 1 br
382 382 # |/
383 383 # o 0 default
384 384
385 385 $ cd ..
386 386 $ rm -rf sub
387 387 $ hg init main
388 388 $ cd main
389 389 $ hg init s
390 390 $ cd s
391 391 $ echo a > a
392 392 $ hg ci -Am1
393 393 adding a
394 394 $ hg branch br
395 395 marked working directory as branch br
396 396 $ echo a >> a
397 397 $ hg ci -m1
398 398 $ hg up default
399 399 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
400 400 $ echo b > b
401 401 $ hg ci -Am1
402 402 adding b
403 403 $ hg up br
404 404 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
405 405 $ hg merge tip
406 406 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
407 407 (branch merge, don't forget to commit)
408 408 $ hg ci -m1
409 409 $ hg up 2
410 410 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
411 411 $ echo c > c
412 412 $ hg ci -Am1
413 413 adding c
414 414 $ hg up 3
415 415 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
416 416 $ hg merge 4
417 417 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
418 418 (branch merge, don't forget to commit)
419 419 $ hg ci -m1
420 420
421 421 # main repo layout:
422 422 #
423 423 # * <-- try to merge default into br again
424 424 # .`|
425 425 # . o 5 br --> substate = 5
426 426 # . |
427 427 # o | 4 default --> substate = 4
428 428 # | |
429 429 # | o 3 br --> substate = 2
430 430 # |/|
431 431 # o | 2 default --> substate = 2
432 432 # | |
433 433 # | o 1 br --> substate = 3
434 434 # |/
435 435 # o 0 default --> substate = 2
436 436
437 437 $ cd ..
438 438 $ echo 's = s' > .hgsub
439 439 $ hg -R s up 2
440 440 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
441 441 $ hg ci -Am1
442 442 adding .hgsub
443 443 committing subrepository s
444 444 $ hg branch br
445 445 marked working directory as branch br
446 446 $ echo b > b
447 447 $ hg -R s up 3
448 448 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
449 449 $ hg ci -Am1
450 450 adding b
451 451 committing subrepository s
452 452 $ hg up default
453 453 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
454 454 $ echo c > c
455 455 $ hg ci -Am1
456 456 adding c
457 457 $ hg up 1
458 458 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
459 459 $ hg merge 2
460 460 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 461 (branch merge, don't forget to commit)
462 462 $ hg ci -m1
463 463 $ hg up 2
464 464 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
465 465 $ hg -R s up 4
466 466 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
467 467 $ echo d > d
468 468 $ hg ci -Am1
469 469 adding d
470 470 committing subrepository s
471 471 $ hg up 3
472 472 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
473 473 $ hg -R s up 5
474 474 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
475 475 $ echo e > e
476 476 $ hg ci -Am1
477 477 adding e
478 478 committing subrepository s
479 479
480 480 $ hg up 5
481 481 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
482 482 $ hg merge 4 # try to merge default into br again
483 483 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
484 484 (branch merge, don't forget to commit)
485 485 $ cd ..
486 486
487 487 test subrepo delete from .hgsubstate
488 488
489 489 $ hg init testdelete
490 490 $ mkdir testdelete/nested testdelete/nested2
491 491 $ hg init testdelete/nested
492 492 $ hg init testdelete/nested2
493 493 $ echo test > testdelete/nested/foo
494 494 $ echo test > testdelete/nested2/foo
495 495 $ hg -R testdelete/nested add
496 496 adding testdelete/nested/foo
497 497 $ hg -R testdelete/nested2 add
498 498 adding testdelete/nested2/foo
499 499 $ hg -R testdelete/nested ci -m test
500 500 $ hg -R testdelete/nested2 ci -m test
501 501 $ echo nested = nested > testdelete/.hgsub
502 502 $ echo nested2 = nested2 >> testdelete/.hgsub
503 503 $ hg -R testdelete add
504 504 adding testdelete/.hgsub
505 505 $ hg -R testdelete ci -m "nested 1 & 2 added"
506 506 committing subrepository nested
507 507 committing subrepository nested2
508 508 $ echo nested = nested > testdelete/.hgsub
509 509 $ hg -R testdelete ci -m "nested 2 deleted"
510 510 $ cat testdelete/.hgsubstate
511 511 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
512 512 $ hg -R testdelete remove testdelete/.hgsub
513 513 $ hg -R testdelete ci -m ".hgsub deleted"
514 514 $ cat testdelete/.hgsubstate
515 515
516 516 test repository cloning
517 517
518 518 $ mkdir mercurial mercurial2
519 519 $ hg init nested_absolute
520 520 $ echo test > nested_absolute/foo
521 521 $ hg -R nested_absolute add
522 522 adding nested_absolute/foo
523 523 $ hg -R nested_absolute ci -mtest
524 524 $ cd mercurial
525 525 $ hg init nested_relative
526 526 $ echo test2 > nested_relative/foo2
527 527 $ hg -R nested_relative add
528 528 adding nested_relative/foo2
529 529 $ hg -R nested_relative ci -mtest2
530 530 $ hg init main
531 531 $ echo "nested_relative = ../nested_relative" > main/.hgsub
532 532 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
533 533 $ hg -R main add
534 534 adding main/.hgsub
535 535 $ hg -R main ci -m "add subrepos"
536 536 committing subrepository nested_absolute
537 537 committing subrepository nested_relative
538 538 $ cd ..
539 539 $ hg clone mercurial/main mercurial2/main
540 540 updating to branch default
541 541 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
542 542 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
543 543 > mercurial2/main/nested_relative/.hg/hgrc
544 544 [paths]
545 545 default = $TESTTMP/sub/mercurial/nested_absolute
546 546 [paths]
547 547 default = $TESTTMP/sub/mercurial/nested_relative
548 548 $ rm -rf mercurial mercurial2
549 549
550 550 Issue1977: multirepo push should fail if subrepo push fails
551 551
552 552 $ hg init repo
553 553 $ hg init repo/s
554 554 $ echo a > repo/s/a
555 555 $ hg -R repo/s ci -Am0
556 556 adding a
557 557 $ echo s = s > repo/.hgsub
558 558 $ hg -R repo ci -Am1
559 559 adding .hgsub
560 560 committing subrepository s
561 561 $ hg clone repo repo2
562 562 updating to branch default
563 563 pulling subrepo s from $TESTTMP/sub/repo/s
564 564 requesting all changes
565 565 adding changesets
566 566 adding manifests
567 567 adding file changes
568 568 added 1 changesets with 1 changes to 1 files
569 569 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
570 570 $ hg -q -R repo2 pull -u
571 571 $ echo 1 > repo2/s/a
572 572 $ hg -R repo2/s ci -m2
573 573 $ hg -q -R repo2/s push
574 574 $ hg -R repo2/s up -C 0
575 575 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
576 576 $ echo 2 > repo2/s/a
577 577 $ hg -R repo2/s ci -m3
578 578 created new head
579 579 $ hg -R repo2 ci -m3
580 580 committing subrepository s
581 581 $ hg -q -R repo2 push
582 582 abort: push creates new remote heads on branch 'default'!
583 583 (did you forget to merge? use push -f to force)
584 584 [255]
585 585 $ hg -R repo update
586 586 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
587 587 $ rm -rf repo2 repo
588 588
589 589
590 590 Issue1852 subrepos with relative paths always push/pull relative to default
591 591
592 592 Prepare a repo with subrepo
593 593
594 594 $ hg init issue1852a
595 595 $ cd issue1852a
596 596 $ hg init sub/repo
597 597 $ echo test > sub/repo/foo
598 598 $ hg -R sub/repo add sub/repo/foo
599 599 $ echo sub/repo = sub/repo > .hgsub
600 600 $ hg add .hgsub
601 601 $ hg ci -mtest
602 602 committing subrepository sub/repo
603 603 $ echo test >> sub/repo/foo
604 604 $ hg ci -mtest
605 605 committing subrepository sub/repo
606 606 $ cd ..
607 607
608 608 Create repo without default path, pull top repo, and see what happens on update
609 609
610 610 $ hg init issue1852b
611 611 $ hg -R issue1852b pull issue1852a
612 612 pulling from issue1852a
613 613 requesting all changes
614 614 adding changesets
615 615 adding manifests
616 616 adding file changes
617 617 added 2 changesets with 3 changes to 2 files
618 618 (run 'hg update' to get a working copy)
619 619 $ hg -R issue1852b update
620 620 abort: default path for subrepository sub/repo not found
621 621 [255]
622 622
623 623 Pull -u now doesn't help
624 624
625 625 $ hg -R issue1852b pull -u issue1852a
626 626 pulling from issue1852a
627 627 searching for changes
628 628 no changes found
629 629
630 630 Try the same, but with pull -u
631 631
632 632 $ hg init issue1852c
633 633 $ hg -R issue1852c pull -r0 -u issue1852a
634 634 pulling from issue1852a
635 635 adding changesets
636 636 adding manifests
637 637 adding file changes
638 638 added 1 changesets with 2 changes to 2 files
639 639 pulling subrepo sub/repo from issue1852a/sub/repo
640 640 requesting all changes
641 641 adding changesets
642 642 adding manifests
643 643 adding file changes
644 644 added 2 changesets with 2 changes to 1 files
645 645 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
646 646
647 647 Try to push from the other side
648 648
649 649 $ hg -R issue1852a push `pwd`/issue1852c
650 650 pushing to $TESTTMP/sub/issue1852c
651 651 pushing subrepo sub/repo to $TESTTMP/sub/issue1852c/sub/repo
652 652 searching for changes
653 653 no changes found
654 654 searching for changes
655 655 adding changesets
656 656 adding manifests
657 657 adding file changes
658 658 added 1 changesets with 1 changes to 1 files
659
660 Check status of files when none of them belong to the first
661 subrepository:
662
663 $ hg init subrepo-status
664 $ cd subrepo-status
665 $ hg init subrepo-1
666 $ hg init subrepo-2
667 $ cd subrepo-2
668 $ touch file
669 $ hg add file
670 $ cd ..
671 $ echo subrepo-1 = subrepo-1 > .hgsub
672 $ echo subrepo-2 = subrepo-2 >> .hgsub
673 $ hg add .hgsub
674 $ hg ci -m 'Added subrepos'
675 committing subrepository subrepo-1
676 committing subrepository subrepo-2
677 $ hg st subrepo-2/file
General Comments 0
You need to be logged in to leave comments. Login now