##// END OF EJS Templates
add -l,--limit to log command.
Vadim Gelfer -
r1756:f29857aa default
parent child Browse files
Show More
@@ -1,829 +1,830 b''
1 HG(1)
1 HG(1)
2 =====
2 =====
3 Matt Mackall <mpm@selenic.com>
3 Matt Mackall <mpm@selenic.com>
4
4
5 NAME
5 NAME
6 ----
6 ----
7 hg - Mercurial source code management system
7 hg - Mercurial source code management system
8
8
9 SYNOPSIS
9 SYNOPSIS
10 --------
10 --------
11 'hg' [-v -d -q -y] <command> [command options] [files]
11 'hg' [-v -d -q -y] <command> [command options] [files]
12
12
13 DESCRIPTION
13 DESCRIPTION
14 -----------
14 -----------
15 The hg(1) command provides a command line interface to the Mercurial system.
15 The hg(1) command provides a command line interface to the Mercurial system.
16
16
17 OPTIONS
17 OPTIONS
18 -------
18 -------
19
19
20 -R, --repository::
20 -R, --repository::
21 repository root directory
21 repository root directory
22
22
23 --cwd::
23 --cwd::
24 change working directory
24 change working directory
25
25
26 -y, --noninteractive::
26 -y, --noninteractive::
27 do not prompt, assume 'yes' for any required answers
27 do not prompt, assume 'yes' for any required answers
28
28
29 -q, --quiet::
29 -q, --quiet::
30 suppress output
30 suppress output
31
31
32 -v, --verbose::
32 -v, --verbose::
33 enable additional output
33 enable additional output
34
34
35 --debug::
35 --debug::
36 enable debugging output
36 enable debugging output
37
37
38 --traceback::
38 --traceback::
39 print traceback on exception
39 print traceback on exception
40
40
41 --time::
41 --time::
42 time how long the command takes
42 time how long the command takes
43
43
44 --profile::
44 --profile::
45 print command execution profile
45 print command execution profile
46
46
47 --version::
47 --version::
48 output version information and exit
48 output version information and exit
49
49
50 -h, --help::
50 -h, --help::
51 display help and exit
51 display help and exit
52
52
53 COMMAND ELEMENTS
53 COMMAND ELEMENTS
54 ----------------
54 ----------------
55
55
56 files ...::
56 files ...::
57 indicates one or more filename or relative path filenames; see
57 indicates one or more filename or relative path filenames; see
58 "FILE NAME PATTERNS" for information on pattern matching
58 "FILE NAME PATTERNS" for information on pattern matching
59
59
60 path::
60 path::
61 indicates a path on the local machine
61 indicates a path on the local machine
62
62
63 revision::
63 revision::
64 indicates a changeset which can be specified as a changeset revision
64 indicates a changeset which can be specified as a changeset revision
65 number, a tag, or a unique substring of the changeset hash value
65 number, a tag, or a unique substring of the changeset hash value
66
66
67 repository path::
67 repository path::
68 either the pathname of a local repository or the URI of a remote
68 either the pathname of a local repository or the URI of a remote
69 repository. There are two available URI protocols, http:// which is
69 repository. There are two available URI protocols, http:// which is
70 fast and the old-http:// protocol which is much slower but does not
70 fast and the old-http:// protocol which is much slower but does not
71 require a special server on the web host.
71 require a special server on the web host.
72
72
73 COMMANDS
73 COMMANDS
74 --------
74 --------
75
75
76 add [options] [files ...]::
76 add [options] [files ...]::
77 Schedule files to be version controlled and added to the repository.
77 Schedule files to be version controlled and added to the repository.
78
78
79 The files will be added to the repository at the next commit.
79 The files will be added to the repository at the next commit.
80
80
81 If no names are given, add all files in the current directory and
81 If no names are given, add all files in the current directory and
82 its subdirectories.
82 its subdirectories.
83
83
84 addremove [options] [files ...]::
84 addremove [options] [files ...]::
85 Add all new files and remove all missing files from the repository.
85 Add all new files and remove all missing files from the repository.
86
86
87 New files are ignored if they match any of the patterns in .hgignore. As
87 New files are ignored if they match any of the patterns in .hgignore. As
88 with add, these changes take effect at the next commit.
88 with add, these changes take effect at the next commit.
89
89
90 annotate [-r <rev> -u -n -c -d] [files ...]::
90 annotate [-r <rev> -u -n -c -d] [files ...]::
91 List changes in files, showing the revision id responsible for each line
91 List changes in files, showing the revision id responsible for each line
92
92
93 This command is useful to discover who did a change or when a change took
93 This command is useful to discover who did a change or when a change took
94 place.
94 place.
95
95
96 Without the -a option, annotate will avoid processing files it
96 Without the -a option, annotate will avoid processing files it
97 detects as binary. With -a, annotate will generate an annotation
97 detects as binary. With -a, annotate will generate an annotation
98 anyway, probably with undesirable results.
98 anyway, probably with undesirable results.
99
99
100 options:
100 options:
101 -a, --text treat all files as text
101 -a, --text treat all files as text
102 -I, --include <pat> include names matching the given patterns
102 -I, --include <pat> include names matching the given patterns
103 -X, --exclude <pat> exclude names matching the given patterns
103 -X, --exclude <pat> exclude names matching the given patterns
104 -r, --revision <rev> annotate the specified revision
104 -r, --revision <rev> annotate the specified revision
105 -u, --user list the author
105 -u, --user list the author
106 -d, --date list the commit date
106 -d, --date list the commit date
107 -c, --changeset list the changeset
107 -c, --changeset list the changeset
108 -n, --number list the revision number (default)
108 -n, --number list the revision number (default)
109
109
110 bundle <file> <other>::
110 bundle <file> <other>::
111 (EXPERIMENTAL)
111 (EXPERIMENTAL)
112
112
113 Generate a compressed changegroup file collecting all changesets
113 Generate a compressed changegroup file collecting all changesets
114 not found in the other repository.
114 not found in the other repository.
115
115
116 This file can then be transferred using conventional means and
116 This file can then be transferred using conventional means and
117 applied to another repository with the unbundle command. This is
117 applied to another repository with the unbundle command. This is
118 useful when native push and pull are not available or when
118 useful when native push and pull are not available or when
119 exporting an entire repository is undesirable. The standard file
119 exporting an entire repository is undesirable. The standard file
120 extension is ".hg".
120 extension is ".hg".
121
121
122 Unlike import/export, this exactly preserves all changeset
122 Unlike import/export, this exactly preserves all changeset
123 contents including permissions, rename data, and revision history.
123 contents including permissions, rename data, and revision history.
124
124
125 cat [options] <file ...>::
125 cat [options] <file ...>::
126 Print the specified files as they were at the given revision.
126 Print the specified files as they were at the given revision.
127 If no revision is given then the tip is used.
127 If no revision is given then the tip is used.
128
128
129 Output may be to a file, in which case the name of the file is
129 Output may be to a file, in which case the name of the file is
130 given using a format string. The formatting rules are the same as
130 given using a format string. The formatting rules are the same as
131 for the export command, with the following additions:
131 for the export command, with the following additions:
132
132
133 %s basename of file being printed
133 %s basename of file being printed
134 %d dirname of file being printed, or '.' if in repo root
134 %d dirname of file being printed, or '.' if in repo root
135 %p root-relative path name of file being printed
135 %p root-relative path name of file being printed
136
136
137 options:
137 options:
138 -I, --include <pat> include names matching the given patterns
138 -I, --include <pat> include names matching the given patterns
139 -X, --exclude <pat> exclude names matching the given patterns
139 -X, --exclude <pat> exclude names matching the given patterns
140 -o, --output <filespec> print output to file with formatted name
140 -o, --output <filespec> print output to file with formatted name
141 -r, --rev <rev> print the given revision
141 -r, --rev <rev> print the given revision
142
142
143 clone [options] <source> [dest]::
143 clone [options] <source> [dest]::
144 Create a copy of an existing repository in a new directory.
144 Create a copy of an existing repository in a new directory.
145
145
146 If no destination directory name is specified, it defaults to the
146 If no destination directory name is specified, it defaults to the
147 basename of the source.
147 basename of the source.
148
148
149 The location of the source is added to the new repository's
149 The location of the source is added to the new repository's
150 .hg/hgrc file, as the default to be used for future pulls.
150 .hg/hgrc file, as the default to be used for future pulls.
151
151
152 For efficiency, hardlinks are used for cloning whenever the source
152 For efficiency, hardlinks are used for cloning whenever the source
153 and destination are on the same filesystem. Some filesystems,
153 and destination are on the same filesystem. Some filesystems,
154 such as AFS, implement hardlinking incorrectly, but do not report
154 such as AFS, implement hardlinking incorrectly, but do not report
155 errors. In these cases, use the --pull option to avoid
155 errors. In these cases, use the --pull option to avoid
156 hardlinking.
156 hardlinking.
157
157
158 See pull for valid source format details.
158 See pull for valid source format details.
159
159
160 options:
160 options:
161 -U, --noupdate do not update the new working directory
161 -U, --noupdate do not update the new working directory
162 --pull use pull protocol to copy metadata
162 --pull use pull protocol to copy metadata
163 -e, --ssh specify ssh command to use
163 -e, --ssh specify ssh command to use
164 --remotecmd specify hg command to run on the remote side
164 --remotecmd specify hg command to run on the remote side
165
165
166 commit [options] [files...]::
166 commit [options] [files...]::
167 Commit changes to the given files into the repository.
167 Commit changes to the given files into the repository.
168
168
169 If a list of files is omitted, all changes reported by "hg status"
169 If a list of files is omitted, all changes reported by "hg status"
170 from the root of the repository will be commited.
170 from the root of the repository will be commited.
171
171
172 The HGEDITOR or EDITOR environment variables are used to start an
172 The HGEDITOR or EDITOR environment variables are used to start an
173 editor to add a commit comment.
173 editor to add a commit comment.
174
174
175 Options:
175 Options:
176
176
177 -A, --addremove run addremove during commit
177 -A, --addremove run addremove during commit
178 -I, --include <pat> include names matching the given patterns
178 -I, --include <pat> include names matching the given patterns
179 -X, --exclude <pat> exclude names matching the given patterns
179 -X, --exclude <pat> exclude names matching the given patterns
180 -m, --message <text> use <text> as commit message
180 -m, --message <text> use <text> as commit message
181 -l, --logfile <file> read the commit message from <file>
181 -l, --logfile <file> read the commit message from <file>
182 -d, --date <datecode> record datecode as commit date
182 -d, --date <datecode> record datecode as commit date
183 -u, --user <user> record user as commiter
183 -u, --user <user> record user as commiter
184
184
185 aliases: ci
185 aliases: ci
186
186
187 copy <source ...> <dest>::
187 copy <source ...> <dest>::
188 Mark dest as having copies of source files. If dest is a
188 Mark dest as having copies of source files. If dest is a
189 directory, copies are put in that directory. If dest is a file,
189 directory, copies are put in that directory. If dest is a file,
190 there can only be one source.
190 there can only be one source.
191
191
192 By default, this command copies the contents of files as they
192 By default, this command copies the contents of files as they
193 stand in the working directory. If invoked with --after, the
193 stand in the working directory. If invoked with --after, the
194 operation is recorded, but no copying is performed.
194 operation is recorded, but no copying is performed.
195
195
196 This command takes effect in the next commit.
196 This command takes effect in the next commit.
197
197
198 NOTE: This command should be treated as experimental. While it
198 NOTE: This command should be treated as experimental. While it
199 should properly record copied files, this information is not yet
199 should properly record copied files, this information is not yet
200 fully used by merge, nor fully reported by log.
200 fully used by merge, nor fully reported by log.
201
201
202 Options:
202 Options:
203 -A, --after record a copy that has already occurred
203 -A, --after record a copy that has already occurred
204 -I, --include <pat> include names matching the given patterns
204 -I, --include <pat> include names matching the given patterns
205 -X, --exclude <pat> exclude names matching the given patterns
205 -X, --exclude <pat> exclude names matching the given patterns
206 -f, --force forcibly copy over an existing managed file
206 -f, --force forcibly copy over an existing managed file
207
207
208 aliases: cp
208 aliases: cp
209
209
210 diff [-a] [-r revision] [-r revision] [files ...]::
210 diff [-a] [-r revision] [-r revision] [files ...]::
211 Show differences between revisions for the specified files.
211 Show differences between revisions for the specified files.
212
212
213 Differences between files are shown using the unified diff format.
213 Differences between files are shown using the unified diff format.
214
214
215 When two revision arguments are given, then changes are shown
215 When two revision arguments are given, then changes are shown
216 between those revisions. If only one revision is specified then
216 between those revisions. If only one revision is specified then
217 that revision is compared to the working directory, and, when no
217 that revision is compared to the working directory, and, when no
218 revisions are specified, the working directory files are compared
218 revisions are specified, the working directory files are compared
219 to its parent.
219 to its parent.
220
220
221 Without the -a option, diff will avoid generating diffs of files
221 Without the -a option, diff will avoid generating diffs of files
222 it detects as binary. With -a, diff will generate a diff anyway,
222 it detects as binary. With -a, diff will generate a diff anyway,
223 probably with undesirable results.
223 probably with undesirable results.
224
224
225 options:
225 options:
226 -a, --text treat all files as text
226 -a, --text treat all files as text
227 -I, --include <pat> include names matching the given patterns
227 -I, --include <pat> include names matching the given patterns
228 -p, --show-function show which function each change is in
228 -p, --show-function show which function each change is in
229 -X, --exclude <pat> exclude names matching the given patterns
229 -X, --exclude <pat> exclude names matching the given patterns
230 -w, --ignore-all-space ignore white space when comparing lines
230 -w, --ignore-all-space ignore white space when comparing lines
231
231
232 export [-o filespec] [revision] ...::
232 export [-o filespec] [revision] ...::
233 Print the changeset header and diffs for one or more revisions.
233 Print the changeset header and diffs for one or more revisions.
234
234
235 The information shown in the changeset header is: author,
235 The information shown in the changeset header is: author,
236 changeset hash, parent and commit comment.
236 changeset hash, parent and commit comment.
237
237
238 Output may be to a file, in which case the name of the file is
238 Output may be to a file, in which case the name of the file is
239 given using a format string. The formatting rules are as follows:
239 given using a format string. The formatting rules are as follows:
240
240
241 %% literal "%" character
241 %% literal "%" character
242 %H changeset hash (40 bytes of hexadecimal)
242 %H changeset hash (40 bytes of hexadecimal)
243 %N number of patches being generated
243 %N number of patches being generated
244 %R changeset revision number
244 %R changeset revision number
245 %b basename of the exporting repository
245 %b basename of the exporting repository
246 %h short-form changeset hash (12 bytes of hexadecimal)
246 %h short-form changeset hash (12 bytes of hexadecimal)
247 %n zero-padded sequence number, starting at 1
247 %n zero-padded sequence number, starting at 1
248 %r zero-padded changeset revision number
248 %r zero-padded changeset revision number
249
249
250 Without the -a option, export will avoid generating diffs of files
250 Without the -a option, export will avoid generating diffs of files
251 it detects as binary. With -a, export will generate a diff anyway,
251 it detects as binary. With -a, export will generate a diff anyway,
252 probably with undesirable results.
252 probably with undesirable results.
253
253
254 options:
254 options:
255 -a, --text treat all files as text
255 -a, --text treat all files as text
256 -o, --output <filespec> print output to file with formatted name
256 -o, --output <filespec> print output to file with formatted name
257
257
258 forget [options] [files]::
258 forget [options] [files]::
259 Undo an 'hg add' scheduled for the next commit.
259 Undo an 'hg add' scheduled for the next commit.
260
260
261 options:
261 options:
262 -I, --include <pat> include names matching the given patterns
262 -I, --include <pat> include names matching the given patterns
263 -X, --exclude <pat> exclude names matching the given patterns
263 -X, --exclude <pat> exclude names matching the given patterns
264
264
265 grep [options] pattern [files]::
265 grep [options] pattern [files]::
266 Search revisions of files for a regular expression.
266 Search revisions of files for a regular expression.
267
267
268 This command behaves differently than Unix grep. It only accepts
268 This command behaves differently than Unix grep. It only accepts
269 Python/Perl regexps. It searches repository history, not the
269 Python/Perl regexps. It searches repository history, not the
270 working directory. It always prints the revision number in which
270 working directory. It always prints the revision number in which
271 a match appears.
271 a match appears.
272
272
273 By default, grep only prints output for the first revision of a
273 By default, grep only prints output for the first revision of a
274 file in which it finds a match. To get it to print every revision
274 file in which it finds a match. To get it to print every revision
275 that contains a change in match status ("-" for a match that
275 that contains a change in match status ("-" for a match that
276 becomes a non-match, or "+" for a non-match that becomes a match),
276 becomes a non-match, or "+" for a non-match that becomes a match),
277 use the --all flag.
277 use the --all flag.
278
278
279 options:
279 options:
280 -0, --print0 end fields with NUL
280 -0, --print0 end fields with NUL
281 -I, --include <pat> include names matching the given patterns
281 -I, --include <pat> include names matching the given patterns
282 -X, --exclude <pat> exclude names matching the given patterns
282 -X, --exclude <pat> exclude names matching the given patterns
283 --all print all revisions that match
283 --all print all revisions that match
284 -i, --ignore-case ignore case when matching
284 -i, --ignore-case ignore case when matching
285 -l, --files-with-matches print only filenames and revs that match
285 -l, --files-with-matches print only filenames and revs that match
286 -n, --line-number print matching line numbers
286 -n, --line-number print matching line numbers
287 -r <rev>, --rev <rev> search in given revision range
287 -r <rev>, --rev <rev> search in given revision range
288 -u, --user print user who committed change
288 -u, --user print user who committed change
289
289
290 heads::
290 heads::
291 Show all repository head changesets.
291 Show all repository head changesets.
292
292
293 Repository "heads" are changesets that don't have children
293 Repository "heads" are changesets that don't have children
294 changesets. They are where development generally takes place and
294 changesets. They are where development generally takes place and
295 are the usual targets for update and merge operations.
295 are the usual targets for update and merge operations.
296
296
297 identify::
297 identify::
298 Print a short summary of the current state of the repo.
298 Print a short summary of the current state of the repo.
299
299
300 This summary identifies the repository state using one or two parent
300 This summary identifies the repository state using one or two parent
301 hash identifiers, followed by a "+" if there are uncommitted changes
301 hash identifiers, followed by a "+" if there are uncommitted changes
302 in the working directory, followed by a list of tags for this revision.
302 in the working directory, followed by a list of tags for this revision.
303
303
304 aliases: id
304 aliases: id
305
305
306 import [-p <n> -b <base> -f] <patches>::
306 import [-p <n> -b <base> -f] <patches>::
307 Import a list of patches and commit them individually.
307 Import a list of patches and commit them individually.
308
308
309 If there are outstanding changes in the working directory, import
309 If there are outstanding changes in the working directory, import
310 will abort unless given the -f flag.
310 will abort unless given the -f flag.
311
311
312 If a patch looks like a mail message (its first line starts with
312 If a patch looks like a mail message (its first line starts with
313 "From " or looks like an RFC822 header), it will not be applied
313 "From " or looks like an RFC822 header), it will not be applied
314 unless the -f option is used. The importer neither parses nor
314 unless the -f option is used. The importer neither parses nor
315 discards mail headers, so use -f only to override the "mailness"
315 discards mail headers, so use -f only to override the "mailness"
316 safety check, not to import a real mail message.
316 safety check, not to import a real mail message.
317
317
318 options:
318 options:
319 -p, --strip <n> directory strip option for patch. This has the same
319 -p, --strip <n> directory strip option for patch. This has the same
320 meaning as the corresponding patch option
320 meaning as the corresponding patch option
321 -b <path> base directory to read patches from
321 -b <path> base directory to read patches from
322 -f, --force skip check for outstanding uncommitted changes
322 -f, --force skip check for outstanding uncommitted changes
323
323
324 aliases: patch
324 aliases: patch
325
325
326 incoming [-p] [source]::
326 incoming [-p] [source]::
327 Show new changesets found in the specified repo or the default
327 Show new changesets found in the specified repo or the default
328 pull repo. These are the changesets that would be pulled if a pull
328 pull repo. These are the changesets that would be pulled if a pull
329 was requested.
329 was requested.
330
330
331 Currently only local repositories are supported.
331 Currently only local repositories are supported.
332
332
333 options:
333 options:
334 -p, --patch show patch
334 -p, --patch show patch
335
335
336 aliases: in
336 aliases: in
337
337
338 init [dest]::
338 init [dest]::
339 Initialize a new repository in the given directory. If the given
339 Initialize a new repository in the given directory. If the given
340 directory does not exist, it is created.
340 directory does not exist, it is created.
341
341
342 If no directory is given, the current directory is used.
342 If no directory is given, the current directory is used.
343
343
344 locate [options] [files]::
344 locate [options] [files]::
345 Print all files under Mercurial control whose names match the
345 Print all files under Mercurial control whose names match the
346 given patterns.
346 given patterns.
347
347
348 This command searches the current directory and its
348 This command searches the current directory and its
349 subdirectories. To search an entire repository, move to the root
349 subdirectories. To search an entire repository, move to the root
350 of the repository.
350 of the repository.
351
351
352 If no patterns are given to match, this command prints all file
352 If no patterns are given to match, this command prints all file
353 names.
353 names.
354
354
355 If you want to feed the output of this command into the "xargs"
355 If you want to feed the output of this command into the "xargs"
356 command, use the "-0" option to both this command and "xargs".
356 command, use the "-0" option to both this command and "xargs".
357 This will avoid the problem of "xargs" treating single filenames
357 This will avoid the problem of "xargs" treating single filenames
358 that contain white space as multiple filenames.
358 that contain white space as multiple filenames.
359
359
360 options:
360 options:
361
361
362 -0, --print0 end filenames with NUL, for use with xargs
362 -0, --print0 end filenames with NUL, for use with xargs
363 -f, --fullpath print complete paths from the filesystem root
363 -f, --fullpath print complete paths from the filesystem root
364 -I, --include <pat> include names matching the given patterns
364 -I, --include <pat> include names matching the given patterns
365 -r, --rev <rev> search the repository as it stood at rev
365 -r, --rev <rev> search the repository as it stood at rev
366 -X, --exclude <pat> exclude names matching the given patterns
366 -X, --exclude <pat> exclude names matching the given patterns
367
367
368 log [-r revision ...] [-p] [files]::
368 log [-r revision ...] [-p] [files]::
369 Print the revision history of the specified files or the entire project.
369 Print the revision history of the specified files or the entire project.
370
370
371 By default this command outputs: changeset id and hash, tags,
371 By default this command outputs: changeset id and hash, tags,
372 parents, user, date and time, and a summary for each commit. The
372 parents, user, date and time, and a summary for each commit. The
373 -v switch adds some more detail, such as changed files, manifest
373 -v switch adds some more detail, such as changed files, manifest
374 hashes or message signatures.
374 hashes or message signatures.
375
375
376 options:
376 options:
377 -I, --include <pat> include names matching the given patterns
377 -I, --include <pat> include names matching the given patterns
378 -X, --exclude <pat> exclude names matching the given patterns
378 -X, --exclude <pat> exclude names matching the given patterns
379 -l, --limit <num> print no more than this many changes
379 -r, --rev <A> show the specified revision or range
380 -r, --rev <A> show the specified revision or range
380 -p, --patch show patch
381 -p, --patch show patch
381
382
382 aliases: history
383 aliases: history
383
384
384 manifest [revision]::
385 manifest [revision]::
385 Print a list of version controlled files for the given revision.
386 Print a list of version controlled files for the given revision.
386
387
387 The manifest is the list of files being version controlled. If no revision
388 The manifest is the list of files being version controlled. If no revision
388 is given then the tip is used.
389 is given then the tip is used.
389
390
390 outgoing [-p] [dest]::
391 outgoing [-p] [dest]::
391 Show changesets not found in the specified destination repo or the
392 Show changesets not found in the specified destination repo or the
392 default push repo. These are the changesets that would be pushed
393 default push repo. These are the changesets that would be pushed
393 if a push was requested.
394 if a push was requested.
394
395
395 See pull for valid source format details.
396 See pull for valid source format details.
396
397
397 options:
398 options:
398 -p, --patch show patch
399 -p, --patch show patch
399
400
400 aliases: out
401 aliases: out
401
402
402 parents::
403 parents::
403 Print the working directory's parent revisions.
404 Print the working directory's parent revisions.
404
405
405 paths [NAME]::
406 paths [NAME]::
406 Show definition of symbolic path name NAME. If no name is given, show
407 Show definition of symbolic path name NAME. If no name is given, show
407 definition of available names.
408 definition of available names.
408
409
409 Path names are defined in the [paths] section of /etc/mercurial/hgrc
410 Path names are defined in the [paths] section of /etc/mercurial/hgrc
410 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
411 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
411
412
412 pull <repository path>::
413 pull <repository path>::
413 Pull changes from a remote repository to a local one.
414 Pull changes from a remote repository to a local one.
414
415
415 This finds all changes from the repository at the specified path
416 This finds all changes from the repository at the specified path
416 or URL and adds them to the local repository. By default, this
417 or URL and adds them to the local repository. By default, this
417 does not update the copy of the project in the working directory.
418 does not update the copy of the project in the working directory.
418
419
419 Valid URLs are of the form:
420 Valid URLs are of the form:
420
421
421 local/filesystem/path
422 local/filesystem/path
422 http://[user@]host[:port][/path]
423 http://[user@]host[:port][/path]
423 https://[user@]host[:port][/path]
424 https://[user@]host[:port][/path]
424 ssh://[user@]host[:port][/path]
425 ssh://[user@]host[:port][/path]
425
426
426 SSH requires an accessible shell account on the destination machine
427 SSH requires an accessible shell account on the destination machine
427 and a copy of hg in the remote path. With SSH, paths are relative
428 and a copy of hg in the remote path. With SSH, paths are relative
428 to the remote user's home directory by default; use two slashes at
429 to the remote user's home directory by default; use two slashes at
429 the start of a path to specify it as relative to the filesystem root.
430 the start of a path to specify it as relative to the filesystem root.
430
431
431 options:
432 options:
432 -u, --update update the working directory to tip after pull
433 -u, --update update the working directory to tip after pull
433 -e, --ssh specify ssh command to use
434 -e, --ssh specify ssh command to use
434 --remotecmd specify hg command to run on the remote side
435 --remotecmd specify hg command to run on the remote side
435
436
436 push <destination>::
437 push <destination>::
437 Push changes from the local repository to the given destination.
438 Push changes from the local repository to the given destination.
438
439
439 This is the symmetrical operation for pull. It helps to move
440 This is the symmetrical operation for pull. It helps to move
440 changes from the current repository to a different one. If the
441 changes from the current repository to a different one. If the
441 destination is local this is identical to a pull in that directory
442 destination is local this is identical to a pull in that directory
442 from the current one.
443 from the current one.
443
444
444 By default, push will refuse to run if it detects the result would
445 By default, push will refuse to run if it detects the result would
445 increase the number of remote heads. This generally indicates the
446 increase the number of remote heads. This generally indicates the
446 the client has forgotten to sync and merge before pushing.
447 the client has forgotten to sync and merge before pushing.
447
448
448 Valid URLs are of the form:
449 Valid URLs are of the form:
449
450
450 local/filesystem/path
451 local/filesystem/path
451 ssh://[user@]host[:port][/path]
452 ssh://[user@]host[:port][/path]
452
453
453 SSH requires an accessible shell account on the destination
454 SSH requires an accessible shell account on the destination
454 machine and a copy of hg in the remote path.
455 machine and a copy of hg in the remote path.
455
456
456 options:
457 options:
457
458
458 -f, --force force update
459 -f, --force force update
459 -e, --ssh specify ssh command to use
460 -e, --ssh specify ssh command to use
460 --remotecmd specify hg command to run on the remote side
461 --remotecmd specify hg command to run on the remote side
461
462
462 rawcommit [-p -d -u -F -m -l]::
463 rawcommit [-p -d -u -F -m -l]::
463 Lowlevel commit, for use in helper scripts. (DEPRECATED)
464 Lowlevel commit, for use in helper scripts. (DEPRECATED)
464
465
465 This command is not intended to be used by normal users, as it is
466 This command is not intended to be used by normal users, as it is
466 primarily useful for importing from other SCMs.
467 primarily useful for importing from other SCMs.
467
468
468 This command is now deprecated and will be removed in a future
469 This command is now deprecated and will be removed in a future
469 release, please use debugsetparents and commit instead.
470 release, please use debugsetparents and commit instead.
470
471
471 recover::
472 recover::
472 Recover from an interrupted commit or pull.
473 Recover from an interrupted commit or pull.
473
474
474 This command tries to fix the repository status after an interrupted
475 This command tries to fix the repository status after an interrupted
475 operation. It should only be necessary when Mercurial suggests it.
476 operation. It should only be necessary when Mercurial suggests it.
476
477
477 remove [options] [files ...]::
478 remove [options] [files ...]::
478 Schedule the indicated files for removal from the repository.
479 Schedule the indicated files for removal from the repository.
479
480
480 This command schedules the files to be removed at the next commit.
481 This command schedules the files to be removed at the next commit.
481 This only removes files from the current branch, not from the
482 This only removes files from the current branch, not from the
482 entire project history. If the files still exist in the working
483 entire project history. If the files still exist in the working
483 directory, they will be deleted from it.
484 directory, they will be deleted from it.
484
485
485 aliases: rm
486 aliases: rm
486
487
487 rename <source ...> <dest>::
488 rename <source ...> <dest>::
488 Mark dest as copies of sources; mark sources for deletion. If
489 Mark dest as copies of sources; mark sources for deletion. If
489 dest is a directory, copies are put in that directory. If dest is
490 dest is a directory, copies are put in that directory. If dest is
490 a file, there can only be one source.
491 a file, there can only be one source.
491
492
492 By default, this command copies the contents of files as they
493 By default, this command copies the contents of files as they
493 stand in the working directory. If invoked with --after, the
494 stand in the working directory. If invoked with --after, the
494 operation is recorded, but no copying is performed.
495 operation is recorded, but no copying is performed.
495
496
496 This command takes effect in the next commit.
497 This command takes effect in the next commit.
497
498
498 NOTE: This command should be treated as experimental. While it
499 NOTE: This command should be treated as experimental. While it
499 should properly record rename files, this information is not yet
500 should properly record rename files, this information is not yet
500 fully used by merge, nor fully reported by log.
501 fully used by merge, nor fully reported by log.
501
502
502 Options:
503 Options:
503 -A, --after record a rename that has already occurred
504 -A, --after record a rename that has already occurred
504 -f, --force forcibly copy over an existing managed file
505 -f, --force forcibly copy over an existing managed file
505
506
506 aliases: mv
507 aliases: mv
507
508
508 revert [names ...]::
509 revert [names ...]::
509 The revert command has two modes of operation.
510 The revert command has two modes of operation.
510
511
511 In its default mode, it reverts any uncommitted modifications made
512 In its default mode, it reverts any uncommitted modifications made
512 to the named files or directories. This restores the contents of
513 to the named files or directories. This restores the contents of
513 the affected files to an unmodified state.
514 the affected files to an unmodified state.
514
515
515 Using the -r option, it reverts the given files or directories to
516 Using the -r option, it reverts the given files or directories to
516 their state as of an earlier revision. This can be helpful to "roll
517 their state as of an earlier revision. This can be helpful to "roll
517 back" some or all of a change that should not have been committed.
518 back" some or all of a change that should not have been committed.
518
519
519 Revert modifies the working directory. It does not commit any
520 Revert modifies the working directory. It does not commit any
520 changes, or change the parent of the current working directory.
521 changes, or change the parent of the current working directory.
521
522
522 If a file has been deleted, it is recreated. If the executable
523 If a file has been deleted, it is recreated. If the executable
523 mode of a file was changed, it is reset.
524 mode of a file was changed, it is reset.
524
525
525 If a directory is given, all files in that directory and its
526 If a directory is given, all files in that directory and its
526 subdirectories are reverted.
527 subdirectories are reverted.
527
528
528 If no arguments are given, all files in the current directory and
529 If no arguments are given, all files in the current directory and
529 its subdirectories are reverted.
530 its subdirectories are reverted.
530
531
531 options:
532 options:
532 -r, --rev <rev> revision to revert to
533 -r, --rev <rev> revision to revert to
533 -n, --nonrecursive do not recurse into subdirectories
534 -n, --nonrecursive do not recurse into subdirectories
534
535
535 root::
536 root::
536 Print the root directory of the current repository.
537 Print the root directory of the current repository.
537
538
538 serve [options]::
539 serve [options]::
539 Start a local HTTP repository browser and pull server.
540 Start a local HTTP repository browser and pull server.
540
541
541 By default, the server logs accesses to stdout and errors to
542 By default, the server logs accesses to stdout and errors to
542 stderr. Use the "-A" and "-E" options to log to files.
543 stderr. Use the "-A" and "-E" options to log to files.
543
544
544 options:
545 options:
545 -A, --accesslog <file> name of access log file to write to
546 -A, --accesslog <file> name of access log file to write to
546 -d, --daemon run server in background, as a daemon
547 -d, --daemon run server in background, as a daemon
547 -E, --errorlog <file> name of error log file to write to
548 -E, --errorlog <file> name of error log file to write to
548 -a, --address <addr> address to use
549 -a, --address <addr> address to use
549 -p, --port <n> port to use (default: 8000)
550 -p, --port <n> port to use (default: 8000)
550 -n, --name <name> name to show in web pages (default: working dir)
551 -n, --name <name> name to show in web pages (default: working dir)
551 --pid-file <file> write server process ID to given file
552 --pid-file <file> write server process ID to given file
552 -t, --templatedir <path> web templates to use
553 -t, --templatedir <path> web templates to use
553 -6, --ipv6 use IPv6 in addition to IPv4
554 -6, --ipv6 use IPv6 in addition to IPv4
554
555
555 status [options] [files]::
556 status [options] [files]::
556 Show changed files in the working directory. If no names are
557 Show changed files in the working directory. If no names are
557 given, all files are shown. Otherwise, only files matching the
558 given, all files are shown. Otherwise, only files matching the
558 given names are shown.
559 given names are shown.
559
560
560 The codes used to show the status of files are:
561 The codes used to show the status of files are:
561
562
562 M = changed
563 M = changed
563 A = added
564 A = added
564 R = removed
565 R = removed
565 ? = not tracked
566 ? = not tracked
566
567
567 options:
568 options:
568
569
569 -m, --modified show only modified files
570 -m, --modified show only modified files
570 -a, --added show only added files
571 -a, --added show only added files
571 -r, --removed show only removed files
572 -r, --removed show only removed files
572 -u, --unknown show only unknown (not tracked) files
573 -u, --unknown show only unknown (not tracked) files
573 -n, --no-status hide status prefix
574 -n, --no-status hide status prefix
574 -0, --print0 end filenames with NUL, for use with xargs
575 -0, --print0 end filenames with NUL, for use with xargs
575 -I, --include <pat> include names matching the given patterns
576 -I, --include <pat> include names matching the given patterns
576 -X, --exclude <pat> exclude names matching the given patterns
577 -X, --exclude <pat> exclude names matching the given patterns
577
578
578 tag [-l -m <text> -d <datecode> -u <user>] <name> [revision]::
579 tag [-l -m <text> -d <datecode> -u <user>] <name> [revision]::
579 Name a particular revision using <name>.
580 Name a particular revision using <name>.
580
581
581 Tags are used to name particular revisions of the repository and are
582 Tags are used to name particular revisions of the repository and are
582 very useful to compare different revision, to go back to significant
583 very useful to compare different revision, to go back to significant
583 earlier versions or to mark branch points as releases, etc.
584 earlier versions or to mark branch points as releases, etc.
584
585
585 If no revision is given, the tip is used.
586 If no revision is given, the tip is used.
586
587
587 To facilitate version control, distribution, and merging of tags,
588 To facilitate version control, distribution, and merging of tags,
588 they are stored as a file named ".hgtags" which is managed
589 they are stored as a file named ".hgtags" which is managed
589 similarly to other project files and can be hand-edited if
590 similarly to other project files and can be hand-edited if
590 necessary.
591 necessary.
591
592
592 options:
593 options:
593 -l, --local make the tag local
594 -l, --local make the tag local
594 -m, --message <text> message for tag commit log entry
595 -m, --message <text> message for tag commit log entry
595 -d, --date <datecode> datecode for commit
596 -d, --date <datecode> datecode for commit
596 -u, --user <user> user for commit
597 -u, --user <user> user for commit
597
598
598 Note: Local tags are not version-controlled or distributed and are
599 Note: Local tags are not version-controlled or distributed and are
599 stored in the .hg/localtags file. If there exists a local tag and
600 stored in the .hg/localtags file. If there exists a local tag and
600 a public tag with the same name, local tag is used.
601 a public tag with the same name, local tag is used.
601
602
602 tags::
603 tags::
603 List the repository tags.
604 List the repository tags.
604
605
605 This lists both regular and local tags.
606 This lists both regular and local tags.
606
607
607 tip [-p]::
608 tip [-p]::
608 Show the tip revision.
609 Show the tip revision.
609
610
610 options:
611 options:
611 -p, --patch show patch
612 -p, --patch show patch
612
613
613 unbundle <file>::
614 unbundle <file>::
614 (EXPERIMENTAL)
615 (EXPERIMENTAL)
615
616
616 Apply a compressed changegroup file generated by the bundle
617 Apply a compressed changegroup file generated by the bundle
617 command.
618 command.
618
619
619 undo::
620 undo::
620 Undo the last commit or pull transaction.
621 Undo the last commit or pull transaction.
621
622
622 Roll back the last pull or commit transaction on the
623 Roll back the last pull or commit transaction on the
623 repository, restoring the project to its earlier state.
624 repository, restoring the project to its earlier state.
624
625
625 This command should be used with care. There is only one level of
626 This command should be used with care. There is only one level of
626 undo and there is no redo.
627 undo and there is no redo.
627
628
628 This command is not intended for use on public repositories. Once
629 This command is not intended for use on public repositories. Once
629 a change is visible for pull by other users, undoing it locally is
630 a change is visible for pull by other users, undoing it locally is
630 ineffective.
631 ineffective.
631
632
632 update [-m -C] [revision]::
633 update [-m -C] [revision]::
633 Update the working directory to the specified revision.
634 Update the working directory to the specified revision.
634
635
635 By default, update will refuse to run if doing so would require
636 By default, update will refuse to run if doing so would require
636 merging or discarding local changes.
637 merging or discarding local changes.
637
638
638 With the -m option, a merge will be performed.
639 With the -m option, a merge will be performed.
639
640
640 With the -C option, local changes will be lost.
641 With the -C option, local changes will be lost.
641
642
642 options:
643 options:
643 -m, --merge allow merging of branches
644 -m, --merge allow merging of branches
644 -C, --clean overwrite locally modified files
645 -C, --clean overwrite locally modified files
645
646
646 aliases: up checkout co
647 aliases: up checkout co
647
648
648 verify::
649 verify::
649 Verify the integrity of the current repository.
650 Verify the integrity of the current repository.
650
651
651 This will perform an extensive check of the repository's
652 This will perform an extensive check of the repository's
652 integrity, validating the hashes and checksums of each entry in
653 integrity, validating the hashes and checksums of each entry in
653 the changelog, manifest, and tracked files, as well as the
654 the changelog, manifest, and tracked files, as well as the
654 integrity of their crosslinks and indices.
655 integrity of their crosslinks and indices.
655
656
656 FILE NAME PATTERNS
657 FILE NAME PATTERNS
657 ------------------
658 ------------------
658
659
659 Mercurial accepts several notations for identifying one or more
660 Mercurial accepts several notations for identifying one or more
660 files at a time.
661 files at a time.
661
662
662 By default, Mercurial treats filenames as shell-style extended
663 By default, Mercurial treats filenames as shell-style extended
663 glob patterns.
664 glob patterns.
664
665
665 Alternate pattern notations must be specified explicitly.
666 Alternate pattern notations must be specified explicitly.
666
667
667 To use a plain path name without any pattern matching, start a
668 To use a plain path name without any pattern matching, start a
668 name with "path:". These path names must match completely, from
669 name with "path:". These path names must match completely, from
669 the root of the current repository.
670 the root of the current repository.
670
671
671 To use an extended glob, start a name with "glob:". Globs are
672 To use an extended glob, start a name with "glob:". Globs are
672 rooted at the current directory; a glob such as "*.c" will match
673 rooted at the current directory; a glob such as "*.c" will match
673 files ending in ".c" in the current directory only.
674 files ending in ".c" in the current directory only.
674
675
675 The supported glob syntax extensions are "**" to match any string
676 The supported glob syntax extensions are "**" to match any string
676 across path separators, and "{a,b}" to mean "a or b".
677 across path separators, and "{a,b}" to mean "a or b".
677
678
678 To use a Perl/Python regular expression, start a name with "re:".
679 To use a Perl/Python regular expression, start a name with "re:".
679 Regexp pattern matching is anchored at the root of the repository.
680 Regexp pattern matching is anchored at the root of the repository.
680
681
681 Plain examples:
682 Plain examples:
682
683
683 path:foo/bar a name bar in a directory named foo in the root of
684 path:foo/bar a name bar in a directory named foo in the root of
684 the repository
685 the repository
685 path:path:name a file or directory named "path:name"
686 path:path:name a file or directory named "path:name"
686
687
687 Glob examples:
688 Glob examples:
688
689
689 glob:*.c any name ending in ".c" in the current directory
690 glob:*.c any name ending in ".c" in the current directory
690 *.c any name ending in ".c" in the current directory
691 *.c any name ending in ".c" in the current directory
691 **.c any name ending in ".c" in the current directory, or
692 **.c any name ending in ".c" in the current directory, or
692 any subdirectory
693 any subdirectory
693 foo/*.c any name ending in ".c" in the directory foo
694 foo/*.c any name ending in ".c" in the directory foo
694 foo/**.c any name ending in ".c" in the directory foo, or any
695 foo/**.c any name ending in ".c" in the directory foo, or any
695 subdirectory
696 subdirectory
696
697
697 Regexp examples:
698 Regexp examples:
698
699
699 re:.*\.c$ any name ending in ".c", anywhere in the repository
700 re:.*\.c$ any name ending in ".c", anywhere in the repository
700
701
701
702
702 SPECIFYING SINGLE REVISIONS
703 SPECIFYING SINGLE REVISIONS
703 ---------------------------
704 ---------------------------
704
705
705 Mercurial accepts several notations for identifying individual
706 Mercurial accepts several notations for identifying individual
706 revisions.
707 revisions.
707
708
708 A plain integer is treated as a revision number. Negative
709 A plain integer is treated as a revision number. Negative
709 integers are treated as offsets from the tip, with -1 denoting the
710 integers are treated as offsets from the tip, with -1 denoting the
710 tip.
711 tip.
711
712
712 A 40-digit hexadecimal string is treated as a unique revision
713 A 40-digit hexadecimal string is treated as a unique revision
713 identifier.
714 identifier.
714
715
715 A hexadecimal string less than 40 characters long is treated as a
716 A hexadecimal string less than 40 characters long is treated as a
716 unique revision identifier, and referred to as a short-form
717 unique revision identifier, and referred to as a short-form
717 identifier. A short-form identifier is only valid if it is the
718 identifier. A short-form identifier is only valid if it is the
718 prefix of one full-length identifier.
719 prefix of one full-length identifier.
719
720
720 Any other string is treated as a tag name, which is a symbolic
721 Any other string is treated as a tag name, which is a symbolic
721 name associated with a revision identifier. Tag names may not
722 name associated with a revision identifier. Tag names may not
722 contain the ":" character.
723 contain the ":" character.
723
724
724 The reserved name "tip" is a special tag that always identifies
725 The reserved name "tip" is a special tag that always identifies
725 the most recent revision.
726 the most recent revision.
726
727
727 SPECIFYING MULTIPLE REVISIONS
728 SPECIFYING MULTIPLE REVISIONS
728 -----------------------------
729 -----------------------------
729
730
730 When Mercurial accepts more than one revision, they may be
731 When Mercurial accepts more than one revision, they may be
731 specified individually, or provided as a continuous range,
732 specified individually, or provided as a continuous range,
732 separated by the ":" character.
733 separated by the ":" character.
733
734
734 The syntax of range notation is [BEGIN]:[END], where BEGIN and END
735 The syntax of range notation is [BEGIN]:[END], where BEGIN and END
735 are revision identifiers. Both BEGIN and END are optional. If
736 are revision identifiers. Both BEGIN and END are optional. If
736 BEGIN is not specified, it defaults to revision number 0. If END
737 BEGIN is not specified, it defaults to revision number 0. If END
737 is not specified, it defaults to the tip. The range ":" thus
738 is not specified, it defaults to the tip. The range ":" thus
738 means "all revisions".
739 means "all revisions".
739
740
740 If BEGIN is greater than END, revisions are treated in reverse
741 If BEGIN is greater than END, revisions are treated in reverse
741 order.
742 order.
742
743
743 A range acts as a closed interval. This means that a range of 3:5
744 A range acts as a closed interval. This means that a range of 3:5
744 gives 3, 4 and 5. Similarly, a range of 4:2 gives 4, 3, and 2.
745 gives 3, 4 and 5. Similarly, a range of 4:2 gives 4, 3, and 2.
745
746
746 ENVIRONMENT VARIABLES
747 ENVIRONMENT VARIABLES
747 ---------------------
748 ---------------------
748
749
749 HGEDITOR::
750 HGEDITOR::
750 This is the name of the editor to use when committing. Defaults to the
751 This is the name of the editor to use when committing. Defaults to the
751 value of EDITOR.
752 value of EDITOR.
752
753
753 (deprecated, use .hgrc)
754 (deprecated, use .hgrc)
754
755
755 HGMERGE::
756 HGMERGE::
756 An executable to use for resolving merge conflicts. The program
757 An executable to use for resolving merge conflicts. The program
757 will be executed with three arguments: local file, remote file,
758 will be executed with three arguments: local file, remote file,
758 ancestor file.
759 ancestor file.
759
760
760 The default program is "hgmerge", which is a shell script provided
761 The default program is "hgmerge", which is a shell script provided
761 by Mercurial with some sensible defaults.
762 by Mercurial with some sensible defaults.
762
763
763 (deprecated, use .hgrc)
764 (deprecated, use .hgrc)
764
765
765 HGUSER::
766 HGUSER::
766 This is the string used for the author of a commit.
767 This is the string used for the author of a commit.
767
768
768 (deprecated, use .hgrc)
769 (deprecated, use .hgrc)
769
770
770 EMAIL::
771 EMAIL::
771 If HGUSER is not set, this will be used as the author for a commit.
772 If HGUSER is not set, this will be used as the author for a commit.
772
773
773 LOGNAME::
774 LOGNAME::
774 If neither HGUSER nor EMAIL is set, LOGNAME will be used (with
775 If neither HGUSER nor EMAIL is set, LOGNAME will be used (with
775 '@hostname' appended) as the author value for a commit.
776 '@hostname' appended) as the author value for a commit.
776
777
777 EDITOR::
778 EDITOR::
778 This is the name of the editor used in the hgmerge script. It will be
779 This is the name of the editor used in the hgmerge script. It will be
779 used for commit messages if HGEDITOR isn't set. Defaults to 'vi'.
780 used for commit messages if HGEDITOR isn't set. Defaults to 'vi'.
780
781
781 PYTHONPATH::
782 PYTHONPATH::
782 This is used by Python to find imported modules and may need to be set
783 This is used by Python to find imported modules and may need to be set
783 appropriately if Mercurial is not installed system-wide.
784 appropriately if Mercurial is not installed system-wide.
784
785
785 FILES
786 FILES
786 -----
787 -----
787 .hgignore::
788 .hgignore::
788 This file contains regular expressions (one per line) that describe file
789 This file contains regular expressions (one per line) that describe file
789 names that should be ignored by hg.
790 names that should be ignored by hg.
790
791
791 .hgtags::
792 .hgtags::
792 This file contains changeset hash values and text tag names (one of each
793 This file contains changeset hash values and text tag names (one of each
793 separated by spaces) that correspond to tagged versions of the repository
794 separated by spaces) that correspond to tagged versions of the repository
794 contents.
795 contents.
795
796
796 /etc/mercurial/hgrc, $HOME/.hgrc, .hg/hgrc::
797 /etc/mercurial/hgrc, $HOME/.hgrc, .hg/hgrc::
797 This file contains defaults and configuration. Values in .hg/hgrc
798 This file contains defaults and configuration. Values in .hg/hgrc
798 override those in $HOME/.hgrc, and these override settings made in the
799 override those in $HOME/.hgrc, and these override settings made in the
799 global /etc/mercurial/hgrc configuration. See hgrc(5) for details of
800 global /etc/mercurial/hgrc configuration. See hgrc(5) for details of
800 the contents and format of these files.
801 the contents and format of these files.
801
802
802 BUGS
803 BUGS
803 ----
804 ----
804 Probably lots, please post them to the mailing list (See Resources below)
805 Probably lots, please post them to the mailing list (See Resources below)
805 when you find them.
806 when you find them.
806
807
807 SEE ALSO
808 SEE ALSO
808 --------
809 --------
809 hgrc(5)
810 hgrc(5)
810
811
811 AUTHOR
812 AUTHOR
812 ------
813 ------
813 Written by Matt Mackall <mpm@selenic.com>
814 Written by Matt Mackall <mpm@selenic.com>
814
815
815 RESOURCES
816 RESOURCES
816 ---------
817 ---------
817 http://selenic.com/mercurial[Main Web Site]
818 http://selenic.com/mercurial[Main Web Site]
818
819
819 http://www.serpentine.com/mercurial[Wiki site]
820 http://www.serpentine.com/mercurial[Wiki site]
820
821
821 http://selenic.com/hg[Source code repository]
822 http://selenic.com/hg[Source code repository]
822
823
823 http://selenic.com/mailman/listinfo/mercurial[Mailing list]
824 http://selenic.com/mailman/listinfo/mercurial[Mailing list]
824
825
825 COPYING
826 COPYING
826 -------
827 -------
827 Copyright \(C) 2005 Matt Mackall.
828 Copyright \(C) 2005 Matt Mackall.
828 Free use of this software is granted under the terms of the GNU General
829 Free use of this software is granted under the terms of the GNU General
829 Public License (GPL).
830 Public License (GPL).
@@ -1,2853 +1,2868 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from demandload import demandload
8 from demandload import demandload
9 from node import *
9 from node import *
10 from i18n import gettext as _
10 from i18n import gettext as _
11 demandload(globals(), "os re sys signal shutil imp urllib pdb")
11 demandload(globals(), "os re sys signal shutil imp urllib pdb")
12 demandload(globals(), "fancyopts ui hg util lock revlog")
12 demandload(globals(), "fancyopts ui hg util lock revlog")
13 demandload(globals(), "fnmatch hgweb mdiff random signal time traceback")
13 demandload(globals(), "fnmatch hgweb mdiff random signal time traceback")
14 demandload(globals(), "errno socket version struct atexit sets bz2")
14 demandload(globals(), "errno socket version struct atexit sets bz2")
15
15
16 class UnknownCommand(Exception):
16 class UnknownCommand(Exception):
17 """Exception raised if command is not in the command table."""
17 """Exception raised if command is not in the command table."""
18 class AmbiguousCommand(Exception):
18 class AmbiguousCommand(Exception):
19 """Exception raised if command shortcut matches more than one command."""
19 """Exception raised if command shortcut matches more than one command."""
20
20
21 def filterfiles(filters, files):
21 def filterfiles(filters, files):
22 l = [x for x in files if x in filters]
22 l = [x for x in files if x in filters]
23
23
24 for t in filters:
24 for t in filters:
25 if t and t[-1] != "/":
25 if t and t[-1] != "/":
26 t += "/"
26 t += "/"
27 l += [x for x in files if x.startswith(t)]
27 l += [x for x in files if x.startswith(t)]
28 return l
28 return l
29
29
30 def relpath(repo, args):
30 def relpath(repo, args):
31 cwd = repo.getcwd()
31 cwd = repo.getcwd()
32 if cwd:
32 if cwd:
33 return [util.normpath(os.path.join(cwd, x)) for x in args]
33 return [util.normpath(os.path.join(cwd, x)) for x in args]
34 return args
34 return args
35
35
36 def matchpats(repo, pats=[], opts={}, head=''):
36 def matchpats(repo, pats=[], opts={}, head=''):
37 cwd = repo.getcwd()
37 cwd = repo.getcwd()
38 if not pats and cwd:
38 if not pats and cwd:
39 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
39 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
40 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
40 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
41 cwd = ''
41 cwd = ''
42 return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'),
42 return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'),
43 opts.get('exclude'), head)
43 opts.get('exclude'), head)
44
44
45 def makewalk(repo, pats, opts, node=None, head=''):
45 def makewalk(repo, pats, opts, node=None, head=''):
46 files, matchfn, anypats = matchpats(repo, pats, opts, head)
46 files, matchfn, anypats = matchpats(repo, pats, opts, head)
47 exact = dict(zip(files, files))
47 exact = dict(zip(files, files))
48 def walk():
48 def walk():
49 for src, fn in repo.walk(node=node, files=files, match=matchfn):
49 for src, fn in repo.walk(node=node, files=files, match=matchfn):
50 yield src, fn, util.pathto(repo.getcwd(), fn), fn in exact
50 yield src, fn, util.pathto(repo.getcwd(), fn), fn in exact
51 return files, matchfn, walk()
51 return files, matchfn, walk()
52
52
53 def walk(repo, pats, opts, node=None, head=''):
53 def walk(repo, pats, opts, node=None, head=''):
54 files, matchfn, results = makewalk(repo, pats, opts, node, head)
54 files, matchfn, results = makewalk(repo, pats, opts, node, head)
55 for r in results:
55 for r in results:
56 yield r
56 yield r
57
57
58 def walkchangerevs(ui, repo, pats, opts):
58 def walkchangerevs(ui, repo, pats, opts):
59 '''Iterate over files and the revs they changed in.
59 '''Iterate over files and the revs they changed in.
60
60
61 Callers most commonly need to iterate backwards over the history
61 Callers most commonly need to iterate backwards over the history
62 it is interested in. Doing so has awful (quadratic-looking)
62 it is interested in. Doing so has awful (quadratic-looking)
63 performance, so we use iterators in a "windowed" way.
63 performance, so we use iterators in a "windowed" way.
64
64
65 We walk a window of revisions in the desired order. Within the
65 We walk a window of revisions in the desired order. Within the
66 window, we first walk forwards to gather data, then in the desired
66 window, we first walk forwards to gather data, then in the desired
67 order (usually backwards) to display it.
67 order (usually backwards) to display it.
68
68
69 This function returns an (iterator, getchange, matchfn) tuple. The
69 This function returns an (iterator, getchange, matchfn) tuple. The
70 getchange function returns the changelog entry for a numeric
70 getchange function returns the changelog entry for a numeric
71 revision. The iterator yields 3-tuples. They will be of one of
71 revision. The iterator yields 3-tuples. They will be of one of
72 the following forms:
72 the following forms:
73
73
74 "window", incrementing, lastrev: stepping through a window,
74 "window", incrementing, lastrev: stepping through a window,
75 positive if walking forwards through revs, last rev in the
75 positive if walking forwards through revs, last rev in the
76 sequence iterated over - use to reset state for the current window
76 sequence iterated over - use to reset state for the current window
77
77
78 "add", rev, fns: out-of-order traversal of the given file names
78 "add", rev, fns: out-of-order traversal of the given file names
79 fns, which changed during revision rev - use to gather data for
79 fns, which changed during revision rev - use to gather data for
80 possible display
80 possible display
81
81
82 "iter", rev, None: in-order traversal of the revs earlier iterated
82 "iter", rev, None: in-order traversal of the revs earlier iterated
83 over with "add" - use to display data'''
83 over with "add" - use to display data'''
84
84
85 files, matchfn, anypats = matchpats(repo, pats, opts)
85 files, matchfn, anypats = matchpats(repo, pats, opts)
86
86
87 if repo.changelog.count() == 0:
87 if repo.changelog.count() == 0:
88 return [], False, matchfn
88 return [], False, matchfn
89
89
90 revs = map(int, revrange(ui, repo, opts['rev'] or ['tip:0']))
90 revs = map(int, revrange(ui, repo, opts['rev'] or ['tip:0']))
91 wanted = {}
91 wanted = {}
92 slowpath = anypats
92 slowpath = anypats
93 window = 300
93 window = 300
94 fncache = {}
94 fncache = {}
95
95
96 chcache = {}
96 chcache = {}
97 def getchange(rev):
97 def getchange(rev):
98 ch = chcache.get(rev)
98 ch = chcache.get(rev)
99 if ch is None:
99 if ch is None:
100 chcache[rev] = ch = repo.changelog.read(repo.lookup(str(rev)))
100 chcache[rev] = ch = repo.changelog.read(repo.lookup(str(rev)))
101 return ch
101 return ch
102
102
103 if not slowpath and not files:
103 if not slowpath and not files:
104 # No files, no patterns. Display all revs.
104 # No files, no patterns. Display all revs.
105 wanted = dict(zip(revs, revs))
105 wanted = dict(zip(revs, revs))
106 if not slowpath:
106 if not slowpath:
107 # Only files, no patterns. Check the history of each file.
107 # Only files, no patterns. Check the history of each file.
108 def filerevgen(filelog):
108 def filerevgen(filelog):
109 for i in xrange(filelog.count() - 1, -1, -window):
109 for i in xrange(filelog.count() - 1, -1, -window):
110 revs = []
110 revs = []
111 for j in xrange(max(0, i - window), i + 1):
111 for j in xrange(max(0, i - window), i + 1):
112 revs.append(filelog.linkrev(filelog.node(j)))
112 revs.append(filelog.linkrev(filelog.node(j)))
113 revs.reverse()
113 revs.reverse()
114 for rev in revs:
114 for rev in revs:
115 yield rev
115 yield rev
116
116
117 minrev, maxrev = min(revs), max(revs)
117 minrev, maxrev = min(revs), max(revs)
118 for file in files:
118 for file in files:
119 filelog = repo.file(file)
119 filelog = repo.file(file)
120 # A zero count may be a directory or deleted file, so
120 # A zero count may be a directory or deleted file, so
121 # try to find matching entries on the slow path.
121 # try to find matching entries on the slow path.
122 if filelog.count() == 0:
122 if filelog.count() == 0:
123 slowpath = True
123 slowpath = True
124 break
124 break
125 for rev in filerevgen(filelog):
125 for rev in filerevgen(filelog):
126 if rev <= maxrev:
126 if rev <= maxrev:
127 if rev < minrev:
127 if rev < minrev:
128 break
128 break
129 fncache.setdefault(rev, [])
129 fncache.setdefault(rev, [])
130 fncache[rev].append(file)
130 fncache[rev].append(file)
131 wanted[rev] = 1
131 wanted[rev] = 1
132 if slowpath:
132 if slowpath:
133 # The slow path checks files modified in every changeset.
133 # The slow path checks files modified in every changeset.
134 def changerevgen():
134 def changerevgen():
135 for i in xrange(repo.changelog.count() - 1, -1, -window):
135 for i in xrange(repo.changelog.count() - 1, -1, -window):
136 for j in xrange(max(0, i - window), i + 1):
136 for j in xrange(max(0, i - window), i + 1):
137 yield j, getchange(j)[3]
137 yield j, getchange(j)[3]
138
138
139 for rev, changefiles in changerevgen():
139 for rev, changefiles in changerevgen():
140 matches = filter(matchfn, changefiles)
140 matches = filter(matchfn, changefiles)
141 if matches:
141 if matches:
142 fncache[rev] = matches
142 fncache[rev] = matches
143 wanted[rev] = 1
143 wanted[rev] = 1
144
144
145 def iterate():
145 def iterate():
146 for i in xrange(0, len(revs), window):
146 for i in xrange(0, len(revs), window):
147 yield 'window', revs[0] < revs[-1], revs[-1]
147 yield 'window', revs[0] < revs[-1], revs[-1]
148 nrevs = [rev for rev in revs[i:min(i+window, len(revs))]
148 nrevs = [rev for rev in revs[i:min(i+window, len(revs))]
149 if rev in wanted]
149 if rev in wanted]
150 srevs = list(nrevs)
150 srevs = list(nrevs)
151 srevs.sort()
151 srevs.sort()
152 for rev in srevs:
152 for rev in srevs:
153 fns = fncache.get(rev) or filter(matchfn, getchange(rev)[3])
153 fns = fncache.get(rev) or filter(matchfn, getchange(rev)[3])
154 yield 'add', rev, fns
154 yield 'add', rev, fns
155 for rev in nrevs:
155 for rev in nrevs:
156 yield 'iter', rev, None
156 yield 'iter', rev, None
157 return iterate(), getchange, matchfn
157 return iterate(), getchange, matchfn
158
158
159 revrangesep = ':'
159 revrangesep = ':'
160
160
161 def revrange(ui, repo, revs, revlog=None):
161 def revrange(ui, repo, revs, revlog=None):
162 """Yield revision as strings from a list of revision specifications."""
162 """Yield revision as strings from a list of revision specifications."""
163 if revlog is None:
163 if revlog is None:
164 revlog = repo.changelog
164 revlog = repo.changelog
165 revcount = revlog.count()
165 revcount = revlog.count()
166 def fix(val, defval):
166 def fix(val, defval):
167 if not val:
167 if not val:
168 return defval
168 return defval
169 try:
169 try:
170 num = int(val)
170 num = int(val)
171 if str(num) != val:
171 if str(num) != val:
172 raise ValueError
172 raise ValueError
173 if num < 0:
173 if num < 0:
174 num += revcount
174 num += revcount
175 if num < 0:
175 if num < 0:
176 num = 0
176 num = 0
177 elif num >= revcount:
177 elif num >= revcount:
178 raise ValueError
178 raise ValueError
179 except ValueError:
179 except ValueError:
180 try:
180 try:
181 num = repo.changelog.rev(repo.lookup(val))
181 num = repo.changelog.rev(repo.lookup(val))
182 except KeyError:
182 except KeyError:
183 try:
183 try:
184 num = revlog.rev(revlog.lookup(val))
184 num = revlog.rev(revlog.lookup(val))
185 except KeyError:
185 except KeyError:
186 raise util.Abort(_('invalid revision identifier %s'), val)
186 raise util.Abort(_('invalid revision identifier %s'), val)
187 return num
187 return num
188 seen = {}
188 seen = {}
189 for spec in revs:
189 for spec in revs:
190 if spec.find(revrangesep) >= 0:
190 if spec.find(revrangesep) >= 0:
191 start, end = spec.split(revrangesep, 1)
191 start, end = spec.split(revrangesep, 1)
192 start = fix(start, 0)
192 start = fix(start, 0)
193 end = fix(end, revcount - 1)
193 end = fix(end, revcount - 1)
194 step = start > end and -1 or 1
194 step = start > end and -1 or 1
195 for rev in xrange(start, end+step, step):
195 for rev in xrange(start, end+step, step):
196 if rev in seen:
196 if rev in seen:
197 continue
197 continue
198 seen[rev] = 1
198 seen[rev] = 1
199 yield str(rev)
199 yield str(rev)
200 else:
200 else:
201 rev = fix(spec, None)
201 rev = fix(spec, None)
202 if rev in seen:
202 if rev in seen:
203 continue
203 continue
204 seen[rev] = 1
204 seen[rev] = 1
205 yield str(rev)
205 yield str(rev)
206
206
207 def make_filename(repo, r, pat, node=None,
207 def make_filename(repo, r, pat, node=None,
208 total=None, seqno=None, revwidth=None, pathname=None):
208 total=None, seqno=None, revwidth=None, pathname=None):
209 node_expander = {
209 node_expander = {
210 'H': lambda: hex(node),
210 'H': lambda: hex(node),
211 'R': lambda: str(r.rev(node)),
211 'R': lambda: str(r.rev(node)),
212 'h': lambda: short(node),
212 'h': lambda: short(node),
213 }
213 }
214 expander = {
214 expander = {
215 '%': lambda: '%',
215 '%': lambda: '%',
216 'b': lambda: os.path.basename(repo.root),
216 'b': lambda: os.path.basename(repo.root),
217 }
217 }
218
218
219 try:
219 try:
220 if node:
220 if node:
221 expander.update(node_expander)
221 expander.update(node_expander)
222 if node and revwidth is not None:
222 if node and revwidth is not None:
223 expander['r'] = lambda: str(r.rev(node)).zfill(revwidth)
223 expander['r'] = lambda: str(r.rev(node)).zfill(revwidth)
224 if total is not None:
224 if total is not None:
225 expander['N'] = lambda: str(total)
225 expander['N'] = lambda: str(total)
226 if seqno is not None:
226 if seqno is not None:
227 expander['n'] = lambda: str(seqno)
227 expander['n'] = lambda: str(seqno)
228 if total is not None and seqno is not None:
228 if total is not None and seqno is not None:
229 expander['n'] = lambda:str(seqno).zfill(len(str(total)))
229 expander['n'] = lambda:str(seqno).zfill(len(str(total)))
230 if pathname is not None:
230 if pathname is not None:
231 expander['s'] = lambda: os.path.basename(pathname)
231 expander['s'] = lambda: os.path.basename(pathname)
232 expander['d'] = lambda: os.path.dirname(pathname) or '.'
232 expander['d'] = lambda: os.path.dirname(pathname) or '.'
233 expander['p'] = lambda: pathname
233 expander['p'] = lambda: pathname
234
234
235 newname = []
235 newname = []
236 patlen = len(pat)
236 patlen = len(pat)
237 i = 0
237 i = 0
238 while i < patlen:
238 while i < patlen:
239 c = pat[i]
239 c = pat[i]
240 if c == '%':
240 if c == '%':
241 i += 1
241 i += 1
242 c = pat[i]
242 c = pat[i]
243 c = expander[c]()
243 c = expander[c]()
244 newname.append(c)
244 newname.append(c)
245 i += 1
245 i += 1
246 return ''.join(newname)
246 return ''.join(newname)
247 except KeyError, inst:
247 except KeyError, inst:
248 raise util.Abort(_("invalid format spec '%%%s' in output file name"),
248 raise util.Abort(_("invalid format spec '%%%s' in output file name"),
249 inst.args[0])
249 inst.args[0])
250
250
251 def make_file(repo, r, pat, node=None,
251 def make_file(repo, r, pat, node=None,
252 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
252 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
253 if not pat or pat == '-':
253 if not pat or pat == '-':
254 return 'w' in mode and sys.stdout or sys.stdin
254 return 'w' in mode and sys.stdout or sys.stdin
255 if hasattr(pat, 'write') and 'w' in mode:
255 if hasattr(pat, 'write') and 'w' in mode:
256 return pat
256 return pat
257 if hasattr(pat, 'read') and 'r' in mode:
257 if hasattr(pat, 'read') and 'r' in mode:
258 return pat
258 return pat
259 return open(make_filename(repo, r, pat, node, total, seqno, revwidth,
259 return open(make_filename(repo, r, pat, node, total, seqno, revwidth,
260 pathname),
260 pathname),
261 mode)
261 mode)
262
262
263 def dodiff(fp, ui, repo, node1, node2, files=None, match=util.always,
263 def dodiff(fp, ui, repo, node1, node2, files=None, match=util.always,
264 changes=None, text=False, opts={}):
264 changes=None, text=False, opts={}):
265 if not changes:
265 if not changes:
266 changes = repo.changes(node1, node2, files, match=match)
266 changes = repo.changes(node1, node2, files, match=match)
267 modified, added, removed, deleted, unknown = changes
267 modified, added, removed, deleted, unknown = changes
268 if files:
268 if files:
269 modified, added, removed = map(lambda x: filterfiles(files, x),
269 modified, added, removed = map(lambda x: filterfiles(files, x),
270 (modified, added, removed))
270 (modified, added, removed))
271
271
272 if not modified and not added and not removed:
272 if not modified and not added and not removed:
273 return
273 return
274
274
275 if node2:
275 if node2:
276 change = repo.changelog.read(node2)
276 change = repo.changelog.read(node2)
277 mmap2 = repo.manifest.read(change[0])
277 mmap2 = repo.manifest.read(change[0])
278 date2 = util.datestr(change[2])
278 date2 = util.datestr(change[2])
279 def read(f):
279 def read(f):
280 return repo.file(f).read(mmap2[f])
280 return repo.file(f).read(mmap2[f])
281 else:
281 else:
282 date2 = util.datestr()
282 date2 = util.datestr()
283 if not node1:
283 if not node1:
284 node1 = repo.dirstate.parents()[0]
284 node1 = repo.dirstate.parents()[0]
285 def read(f):
285 def read(f):
286 return repo.wread(f)
286 return repo.wread(f)
287
287
288 if ui.quiet:
288 if ui.quiet:
289 r = None
289 r = None
290 else:
290 else:
291 hexfunc = ui.verbose and hex or short
291 hexfunc = ui.verbose and hex or short
292 r = [hexfunc(node) for node in [node1, node2] if node]
292 r = [hexfunc(node) for node in [node1, node2] if node]
293
293
294 change = repo.changelog.read(node1)
294 change = repo.changelog.read(node1)
295 mmap = repo.manifest.read(change[0])
295 mmap = repo.manifest.read(change[0])
296 date1 = util.datestr(change[2])
296 date1 = util.datestr(change[2])
297
297
298 diffopts = ui.diffopts()
298 diffopts = ui.diffopts()
299 showfunc = opts.get('show_function') or diffopts['showfunc']
299 showfunc = opts.get('show_function') or diffopts['showfunc']
300 ignorews = opts.get('ignore_all_space') or diffopts['ignorews']
300 ignorews = opts.get('ignore_all_space') or diffopts['ignorews']
301 for f in modified:
301 for f in modified:
302 to = None
302 to = None
303 if f in mmap:
303 if f in mmap:
304 to = repo.file(f).read(mmap[f])
304 to = repo.file(f).read(mmap[f])
305 tn = read(f)
305 tn = read(f)
306 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text,
306 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text,
307 showfunc=showfunc, ignorews=ignorews))
307 showfunc=showfunc, ignorews=ignorews))
308 for f in added:
308 for f in added:
309 to = None
309 to = None
310 tn = read(f)
310 tn = read(f)
311 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text,
311 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text,
312 showfunc=showfunc, ignorews=ignorews))
312 showfunc=showfunc, ignorews=ignorews))
313 for f in removed:
313 for f in removed:
314 to = repo.file(f).read(mmap[f])
314 to = repo.file(f).read(mmap[f])
315 tn = None
315 tn = None
316 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text,
316 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text,
317 showfunc=showfunc, ignorews=ignorews))
317 showfunc=showfunc, ignorews=ignorews))
318
318
319 def trimuser(ui, name, rev, revcache):
319 def trimuser(ui, name, rev, revcache):
320 """trim the name of the user who committed a change"""
320 """trim the name of the user who committed a change"""
321 user = revcache.get(rev)
321 user = revcache.get(rev)
322 if user is None:
322 if user is None:
323 user = revcache[rev] = ui.shortuser(name)
323 user = revcache[rev] = ui.shortuser(name)
324 return user
324 return user
325
325
326 def show_changeset(ui, repo, rev=0, changenode=None, brinfo=None):
326 def show_changeset(ui, repo, rev=0, changenode=None, brinfo=None):
327 """show a single changeset or file revision"""
327 """show a single changeset or file revision"""
328 log = repo.changelog
328 log = repo.changelog
329 if changenode is None:
329 if changenode is None:
330 changenode = log.node(rev)
330 changenode = log.node(rev)
331 elif not rev:
331 elif not rev:
332 rev = log.rev(changenode)
332 rev = log.rev(changenode)
333
333
334 if ui.quiet:
334 if ui.quiet:
335 ui.write("%d:%s\n" % (rev, short(changenode)))
335 ui.write("%d:%s\n" % (rev, short(changenode)))
336 return
336 return
337
337
338 changes = log.read(changenode)
338 changes = log.read(changenode)
339 date = util.datestr(changes[2])
339 date = util.datestr(changes[2])
340
340
341 parents = [(log.rev(p), ui.verbose and hex(p) or short(p))
341 parents = [(log.rev(p), ui.verbose and hex(p) or short(p))
342 for p in log.parents(changenode)
342 for p in log.parents(changenode)
343 if ui.debugflag or p != nullid]
343 if ui.debugflag or p != nullid]
344 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
344 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
345 parents = []
345 parents = []
346
346
347 if ui.verbose:
347 if ui.verbose:
348 ui.write(_("changeset: %d:%s\n") % (rev, hex(changenode)))
348 ui.write(_("changeset: %d:%s\n") % (rev, hex(changenode)))
349 else:
349 else:
350 ui.write(_("changeset: %d:%s\n") % (rev, short(changenode)))
350 ui.write(_("changeset: %d:%s\n") % (rev, short(changenode)))
351
351
352 for tag in repo.nodetags(changenode):
352 for tag in repo.nodetags(changenode):
353 ui.status(_("tag: %s\n") % tag)
353 ui.status(_("tag: %s\n") % tag)
354 for parent in parents:
354 for parent in parents:
355 ui.write(_("parent: %d:%s\n") % parent)
355 ui.write(_("parent: %d:%s\n") % parent)
356
356
357 if brinfo and changenode in brinfo:
357 if brinfo and changenode in brinfo:
358 br = brinfo[changenode]
358 br = brinfo[changenode]
359 ui.write(_("branch: %s\n") % " ".join(br))
359 ui.write(_("branch: %s\n") % " ".join(br))
360
360
361 ui.debug(_("manifest: %d:%s\n") % (repo.manifest.rev(changes[0]),
361 ui.debug(_("manifest: %d:%s\n") % (repo.manifest.rev(changes[0]),
362 hex(changes[0])))
362 hex(changes[0])))
363 ui.status(_("user: %s\n") % changes[1])
363 ui.status(_("user: %s\n") % changes[1])
364 ui.status(_("date: %s\n") % date)
364 ui.status(_("date: %s\n") % date)
365
365
366 if ui.debugflag:
366 if ui.debugflag:
367 files = repo.changes(log.parents(changenode)[0], changenode)
367 files = repo.changes(log.parents(changenode)[0], changenode)
368 for key, value in zip([_("files:"), _("files+:"), _("files-:")], files):
368 for key, value in zip([_("files:"), _("files+:"), _("files-:")], files):
369 if value:
369 if value:
370 ui.note("%-12s %s\n" % (key, " ".join(value)))
370 ui.note("%-12s %s\n" % (key, " ".join(value)))
371 else:
371 else:
372 ui.note(_("files: %s\n") % " ".join(changes[3]))
372 ui.note(_("files: %s\n") % " ".join(changes[3]))
373
373
374 description = changes[4].strip()
374 description = changes[4].strip()
375 if description:
375 if description:
376 if ui.verbose:
376 if ui.verbose:
377 ui.status(_("description:\n"))
377 ui.status(_("description:\n"))
378 ui.status(description)
378 ui.status(description)
379 ui.status("\n\n")
379 ui.status("\n\n")
380 else:
380 else:
381 ui.status(_("summary: %s\n") % description.splitlines()[0])
381 ui.status(_("summary: %s\n") % description.splitlines()[0])
382 ui.status("\n")
382 ui.status("\n")
383
383
384 def show_version(ui):
384 def show_version(ui):
385 """output version and copyright information"""
385 """output version and copyright information"""
386 ui.write(_("Mercurial Distributed SCM (version %s)\n")
386 ui.write(_("Mercurial Distributed SCM (version %s)\n")
387 % version.get_version())
387 % version.get_version())
388 ui.status(_(
388 ui.status(_(
389 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
389 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
390 "This is free software; see the source for copying conditions. "
390 "This is free software; see the source for copying conditions. "
391 "There is NO\nwarranty; "
391 "There is NO\nwarranty; "
392 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
392 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
393 ))
393 ))
394
394
395 def help_(ui, cmd=None, with_version=False):
395 def help_(ui, cmd=None, with_version=False):
396 """show help for a given command or all commands"""
396 """show help for a given command or all commands"""
397 option_lists = []
397 option_lists = []
398 if cmd and cmd != 'shortlist':
398 if cmd and cmd != 'shortlist':
399 if with_version:
399 if with_version:
400 show_version(ui)
400 show_version(ui)
401 ui.write('\n')
401 ui.write('\n')
402 aliases, i = find(cmd)
402 aliases, i = find(cmd)
403 # synopsis
403 # synopsis
404 ui.write("%s\n\n" % i[2])
404 ui.write("%s\n\n" % i[2])
405
405
406 # description
406 # description
407 doc = i[0].__doc__
407 doc = i[0].__doc__
408 if not doc:
408 if not doc:
409 doc = _("(No help text available)")
409 doc = _("(No help text available)")
410 if ui.quiet:
410 if ui.quiet:
411 doc = doc.splitlines(0)[0]
411 doc = doc.splitlines(0)[0]
412 ui.write("%s\n" % doc.rstrip())
412 ui.write("%s\n" % doc.rstrip())
413
413
414 if not ui.quiet:
414 if not ui.quiet:
415 # aliases
415 # aliases
416 if len(aliases) > 1:
416 if len(aliases) > 1:
417 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
417 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
418
418
419 # options
419 # options
420 if i[1]:
420 if i[1]:
421 option_lists.append(("options", i[1]))
421 option_lists.append(("options", i[1]))
422
422
423 else:
423 else:
424 # program name
424 # program name
425 if ui.verbose or with_version:
425 if ui.verbose or with_version:
426 show_version(ui)
426 show_version(ui)
427 else:
427 else:
428 ui.status(_("Mercurial Distributed SCM\n"))
428 ui.status(_("Mercurial Distributed SCM\n"))
429 ui.status('\n')
429 ui.status('\n')
430
430
431 # list of commands
431 # list of commands
432 if cmd == "shortlist":
432 if cmd == "shortlist":
433 ui.status(_('basic commands (use "hg help" '
433 ui.status(_('basic commands (use "hg help" '
434 'for the full list or option "-v" for details):\n\n'))
434 'for the full list or option "-v" for details):\n\n'))
435 elif ui.verbose:
435 elif ui.verbose:
436 ui.status(_('list of commands:\n\n'))
436 ui.status(_('list of commands:\n\n'))
437 else:
437 else:
438 ui.status(_('list of commands (use "hg help -v" '
438 ui.status(_('list of commands (use "hg help -v" '
439 'to show aliases and global options):\n\n'))
439 'to show aliases and global options):\n\n'))
440
440
441 h = {}
441 h = {}
442 cmds = {}
442 cmds = {}
443 for c, e in table.items():
443 for c, e in table.items():
444 f = c.split("|")[0]
444 f = c.split("|")[0]
445 if cmd == "shortlist" and not f.startswith("^"):
445 if cmd == "shortlist" and not f.startswith("^"):
446 continue
446 continue
447 f = f.lstrip("^")
447 f = f.lstrip("^")
448 if not ui.debugflag and f.startswith("debug"):
448 if not ui.debugflag and f.startswith("debug"):
449 continue
449 continue
450 d = ""
450 d = ""
451 doc = e[0].__doc__
451 doc = e[0].__doc__
452 if not doc:
452 if not doc:
453 doc = _("(No help text available)")
453 doc = _("(No help text available)")
454 h[f] = doc.splitlines(0)[0].rstrip()
454 h[f] = doc.splitlines(0)[0].rstrip()
455 cmds[f] = c.lstrip("^")
455 cmds[f] = c.lstrip("^")
456
456
457 fns = h.keys()
457 fns = h.keys()
458 fns.sort()
458 fns.sort()
459 m = max(map(len, fns))
459 m = max(map(len, fns))
460 for f in fns:
460 for f in fns:
461 if ui.verbose:
461 if ui.verbose:
462 commands = cmds[f].replace("|",", ")
462 commands = cmds[f].replace("|",", ")
463 ui.write(" %s:\n %s\n"%(commands, h[f]))
463 ui.write(" %s:\n %s\n"%(commands, h[f]))
464 else:
464 else:
465 ui.write(' %-*s %s\n' % (m, f, h[f]))
465 ui.write(' %-*s %s\n' % (m, f, h[f]))
466
466
467 # global options
467 # global options
468 if ui.verbose:
468 if ui.verbose:
469 option_lists.append(("global options", globalopts))
469 option_lists.append(("global options", globalopts))
470
470
471 # list all option lists
471 # list all option lists
472 opt_output = []
472 opt_output = []
473 for title, options in option_lists:
473 for title, options in option_lists:
474 opt_output.append(("\n%s:\n" % title, None))
474 opt_output.append(("\n%s:\n" % title, None))
475 for shortopt, longopt, default, desc in options:
475 for shortopt, longopt, default, desc in options:
476 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
476 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
477 longopt and " --%s" % longopt),
477 longopt and " --%s" % longopt),
478 "%s%s" % (desc,
478 "%s%s" % (desc,
479 default
479 default
480 and _(" (default: %s)") % default
480 and _(" (default: %s)") % default
481 or "")))
481 or "")))
482
482
483 if opt_output:
483 if opt_output:
484 opts_len = max([len(line[0]) for line in opt_output if line[1]])
484 opts_len = max([len(line[0]) for line in opt_output if line[1]])
485 for first, second in opt_output:
485 for first, second in opt_output:
486 if second:
486 if second:
487 ui.write(" %-*s %s\n" % (opts_len, first, second))
487 ui.write(" %-*s %s\n" % (opts_len, first, second))
488 else:
488 else:
489 ui.write("%s\n" % first)
489 ui.write("%s\n" % first)
490
490
491 # Commands start here, listed alphabetically
491 # Commands start here, listed alphabetically
492
492
493 def add(ui, repo, *pats, **opts):
493 def add(ui, repo, *pats, **opts):
494 """add the specified files on the next commit
494 """add the specified files on the next commit
495
495
496 Schedule files to be version controlled and added to the repository.
496 Schedule files to be version controlled and added to the repository.
497
497
498 The files will be added to the repository at the next commit.
498 The files will be added to the repository at the next commit.
499
499
500 If no names are given, add all files in the repository.
500 If no names are given, add all files in the repository.
501 """
501 """
502
502
503 names = []
503 names = []
504 for src, abs, rel, exact in walk(repo, pats, opts):
504 for src, abs, rel, exact in walk(repo, pats, opts):
505 if exact:
505 if exact:
506 if ui.verbose:
506 if ui.verbose:
507 ui.status(_('adding %s\n') % rel)
507 ui.status(_('adding %s\n') % rel)
508 names.append(abs)
508 names.append(abs)
509 elif repo.dirstate.state(abs) == '?':
509 elif repo.dirstate.state(abs) == '?':
510 ui.status(_('adding %s\n') % rel)
510 ui.status(_('adding %s\n') % rel)
511 names.append(abs)
511 names.append(abs)
512 repo.add(names)
512 repo.add(names)
513
513
514 def addremove(ui, repo, *pats, **opts):
514 def addremove(ui, repo, *pats, **opts):
515 """add all new files, delete all missing files
515 """add all new files, delete all missing files
516
516
517 Add all new files and remove all missing files from the repository.
517 Add all new files and remove all missing files from the repository.
518
518
519 New files are ignored if they match any of the patterns in .hgignore. As
519 New files are ignored if they match any of the patterns in .hgignore. As
520 with add, these changes take effect at the next commit.
520 with add, these changes take effect at the next commit.
521 """
521 """
522 return addremove_lock(ui, repo, pats, opts)
522 return addremove_lock(ui, repo, pats, opts)
523
523
524 def addremove_lock(ui, repo, pats, opts, wlock=None):
524 def addremove_lock(ui, repo, pats, opts, wlock=None):
525 add, remove = [], []
525 add, remove = [], []
526 for src, abs, rel, exact in walk(repo, pats, opts):
526 for src, abs, rel, exact in walk(repo, pats, opts):
527 if src == 'f' and repo.dirstate.state(abs) == '?':
527 if src == 'f' and repo.dirstate.state(abs) == '?':
528 add.append(abs)
528 add.append(abs)
529 if ui.verbose or not exact:
529 if ui.verbose or not exact:
530 ui.status(_('adding %s\n') % ((pats and rel) or abs))
530 ui.status(_('adding %s\n') % ((pats and rel) or abs))
531 if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
531 if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
532 remove.append(abs)
532 remove.append(abs)
533 if ui.verbose or not exact:
533 if ui.verbose or not exact:
534 ui.status(_('removing %s\n') % ((pats and rel) or abs))
534 ui.status(_('removing %s\n') % ((pats and rel) or abs))
535 repo.add(add, wlock=wlock)
535 repo.add(add, wlock=wlock)
536 repo.remove(remove, wlock=wlock)
536 repo.remove(remove, wlock=wlock)
537
537
538 def annotate(ui, repo, *pats, **opts):
538 def annotate(ui, repo, *pats, **opts):
539 """show changeset information per file line
539 """show changeset information per file line
540
540
541 List changes in files, showing the revision id responsible for each line
541 List changes in files, showing the revision id responsible for each line
542
542
543 This command is useful to discover who did a change or when a change took
543 This command is useful to discover who did a change or when a change took
544 place.
544 place.
545
545
546 Without the -a option, annotate will avoid processing files it
546 Without the -a option, annotate will avoid processing files it
547 detects as binary. With -a, annotate will generate an annotation
547 detects as binary. With -a, annotate will generate an annotation
548 anyway, probably with undesirable results.
548 anyway, probably with undesirable results.
549 """
549 """
550 def getnode(rev):
550 def getnode(rev):
551 return short(repo.changelog.node(rev))
551 return short(repo.changelog.node(rev))
552
552
553 ucache = {}
553 ucache = {}
554 def getname(rev):
554 def getname(rev):
555 cl = repo.changelog.read(repo.changelog.node(rev))
555 cl = repo.changelog.read(repo.changelog.node(rev))
556 return trimuser(ui, cl[1], rev, ucache)
556 return trimuser(ui, cl[1], rev, ucache)
557
557
558 dcache = {}
558 dcache = {}
559 def getdate(rev):
559 def getdate(rev):
560 datestr = dcache.get(rev)
560 datestr = dcache.get(rev)
561 if datestr is None:
561 if datestr is None:
562 cl = repo.changelog.read(repo.changelog.node(rev))
562 cl = repo.changelog.read(repo.changelog.node(rev))
563 datestr = dcache[rev] = util.datestr(cl[2])
563 datestr = dcache[rev] = util.datestr(cl[2])
564 return datestr
564 return datestr
565
565
566 if not pats:
566 if not pats:
567 raise util.Abort(_('at least one file name or pattern required'))
567 raise util.Abort(_('at least one file name or pattern required'))
568
568
569 opmap = [['user', getname], ['number', str], ['changeset', getnode],
569 opmap = [['user', getname], ['number', str], ['changeset', getnode],
570 ['date', getdate]]
570 ['date', getdate]]
571 if not opts['user'] and not opts['changeset'] and not opts['date']:
571 if not opts['user'] and not opts['changeset'] and not opts['date']:
572 opts['number'] = 1
572 opts['number'] = 1
573
573
574 if opts['rev']:
574 if opts['rev']:
575 node = repo.changelog.lookup(opts['rev'])
575 node = repo.changelog.lookup(opts['rev'])
576 else:
576 else:
577 node = repo.dirstate.parents()[0]
577 node = repo.dirstate.parents()[0]
578 change = repo.changelog.read(node)
578 change = repo.changelog.read(node)
579 mmap = repo.manifest.read(change[0])
579 mmap = repo.manifest.read(change[0])
580
580
581 for src, abs, rel, exact in walk(repo, pats, opts):
581 for src, abs, rel, exact in walk(repo, pats, opts):
582 if abs not in mmap:
582 if abs not in mmap:
583 ui.warn(_("warning: %s is not in the repository!\n") %
583 ui.warn(_("warning: %s is not in the repository!\n") %
584 ((pats and rel) or abs))
584 ((pats and rel) or abs))
585 continue
585 continue
586
586
587 f = repo.file(abs)
587 f = repo.file(abs)
588 if not opts['text'] and util.binary(f.read(mmap[abs])):
588 if not opts['text'] and util.binary(f.read(mmap[abs])):
589 ui.write(_("%s: binary file\n") % ((pats and rel) or abs))
589 ui.write(_("%s: binary file\n") % ((pats and rel) or abs))
590 continue
590 continue
591
591
592 lines = f.annotate(mmap[abs])
592 lines = f.annotate(mmap[abs])
593 pieces = []
593 pieces = []
594
594
595 for o, f in opmap:
595 for o, f in opmap:
596 if opts[o]:
596 if opts[o]:
597 l = [f(n) for n, dummy in lines]
597 l = [f(n) for n, dummy in lines]
598 if l:
598 if l:
599 m = max(map(len, l))
599 m = max(map(len, l))
600 pieces.append(["%*s" % (m, x) for x in l])
600 pieces.append(["%*s" % (m, x) for x in l])
601
601
602 if pieces:
602 if pieces:
603 for p, l in zip(zip(*pieces), lines):
603 for p, l in zip(zip(*pieces), lines):
604 ui.write("%s: %s" % (" ".join(p), l[1]))
604 ui.write("%s: %s" % (" ".join(p), l[1]))
605
605
606 def bundle(ui, repo, fname, dest="default-push", **opts):
606 def bundle(ui, repo, fname, dest="default-push", **opts):
607 """create a changegroup file
607 """create a changegroup file
608
608
609 Generate a compressed changegroup file collecting all changesets
609 Generate a compressed changegroup file collecting all changesets
610 not found in the other repository.
610 not found in the other repository.
611
611
612 This file can then be transferred using conventional means and
612 This file can then be transferred using conventional means and
613 applied to another repository with the unbundle command. This is
613 applied to another repository with the unbundle command. This is
614 useful when native push and pull are not available or when
614 useful when native push and pull are not available or when
615 exporting an entire repository is undesirable. The standard file
615 exporting an entire repository is undesirable. The standard file
616 extension is ".hg".
616 extension is ".hg".
617
617
618 Unlike import/export, this exactly preserves all changeset
618 Unlike import/export, this exactly preserves all changeset
619 contents including permissions, rename data, and revision history.
619 contents including permissions, rename data, and revision history.
620 """
620 """
621 f = open(fname, "wb")
621 f = open(fname, "wb")
622 dest = ui.expandpath(dest, repo.root)
622 dest = ui.expandpath(dest, repo.root)
623 other = hg.repository(ui, dest)
623 other = hg.repository(ui, dest)
624 o = repo.findoutgoing(other)
624 o = repo.findoutgoing(other)
625 cg = repo.changegroup(o, 'bundle')
625 cg = repo.changegroup(o, 'bundle')
626
626
627 try:
627 try:
628 f.write("HG10")
628 f.write("HG10")
629 z = bz2.BZ2Compressor(9)
629 z = bz2.BZ2Compressor(9)
630 while 1:
630 while 1:
631 chunk = cg.read(4096)
631 chunk = cg.read(4096)
632 if not chunk:
632 if not chunk:
633 break
633 break
634 f.write(z.compress(chunk))
634 f.write(z.compress(chunk))
635 f.write(z.flush())
635 f.write(z.flush())
636 except:
636 except:
637 os.unlink(fname)
637 os.unlink(fname)
638 raise
638 raise
639
639
640 def cat(ui, repo, file1, *pats, **opts):
640 def cat(ui, repo, file1, *pats, **opts):
641 """output the latest or given revisions of files
641 """output the latest or given revisions of files
642
642
643 Print the specified files as they were at the given revision.
643 Print the specified files as they were at the given revision.
644 If no revision is given then the tip is used.
644 If no revision is given then the tip is used.
645
645
646 Output may be to a file, in which case the name of the file is
646 Output may be to a file, in which case the name of the file is
647 given using a format string. The formatting rules are the same as
647 given using a format string. The formatting rules are the same as
648 for the export command, with the following additions:
648 for the export command, with the following additions:
649
649
650 %s basename of file being printed
650 %s basename of file being printed
651 %d dirname of file being printed, or '.' if in repo root
651 %d dirname of file being printed, or '.' if in repo root
652 %p root-relative path name of file being printed
652 %p root-relative path name of file being printed
653 """
653 """
654 mf = {}
654 mf = {}
655 rev = opts['rev']
655 rev = opts['rev']
656 if rev:
656 if rev:
657 node = repo.lookup(rev)
657 node = repo.lookup(rev)
658 else:
658 else:
659 node = repo.changelog.tip()
659 node = repo.changelog.tip()
660 change = repo.changelog.read(node)
660 change = repo.changelog.read(node)
661 mf = repo.manifest.read(change[0])
661 mf = repo.manifest.read(change[0])
662 for src, abs, rel, exact in walk(repo, (file1,) + pats, opts, node):
662 for src, abs, rel, exact in walk(repo, (file1,) + pats, opts, node):
663 r = repo.file(abs)
663 r = repo.file(abs)
664 n = mf[abs]
664 n = mf[abs]
665 fp = make_file(repo, r, opts['output'], node=n, pathname=abs)
665 fp = make_file(repo, r, opts['output'], node=n, pathname=abs)
666 fp.write(r.read(n))
666 fp.write(r.read(n))
667
667
668 def clone(ui, source, dest=None, **opts):
668 def clone(ui, source, dest=None, **opts):
669 """make a copy of an existing repository
669 """make a copy of an existing repository
670
670
671 Create a copy of an existing repository in a new directory.
671 Create a copy of an existing repository in a new directory.
672
672
673 If no destination directory name is specified, it defaults to the
673 If no destination directory name is specified, it defaults to the
674 basename of the source.
674 basename of the source.
675
675
676 The location of the source is added to the new repository's
676 The location of the source is added to the new repository's
677 .hg/hgrc file, as the default to be used for future pulls.
677 .hg/hgrc file, as the default to be used for future pulls.
678
678
679 For efficiency, hardlinks are used for cloning whenever the source
679 For efficiency, hardlinks are used for cloning whenever the source
680 and destination are on the same filesystem. Some filesystems,
680 and destination are on the same filesystem. Some filesystems,
681 such as AFS, implement hardlinking incorrectly, but do not report
681 such as AFS, implement hardlinking incorrectly, but do not report
682 errors. In these cases, use the --pull option to avoid
682 errors. In these cases, use the --pull option to avoid
683 hardlinking.
683 hardlinking.
684 """
684 """
685 if dest is None:
685 if dest is None:
686 dest = os.path.basename(os.path.normpath(source))
686 dest = os.path.basename(os.path.normpath(source))
687
687
688 if os.path.exists(dest):
688 if os.path.exists(dest):
689 raise util.Abort(_("destination '%s' already exists"), dest)
689 raise util.Abort(_("destination '%s' already exists"), dest)
690
690
691 dest = os.path.realpath(dest)
691 dest = os.path.realpath(dest)
692
692
693 class Dircleanup(object):
693 class Dircleanup(object):
694 def __init__(self, dir_):
694 def __init__(self, dir_):
695 self.rmtree = shutil.rmtree
695 self.rmtree = shutil.rmtree
696 self.dir_ = dir_
696 self.dir_ = dir_
697 os.mkdir(dir_)
697 os.mkdir(dir_)
698 def close(self):
698 def close(self):
699 self.dir_ = None
699 self.dir_ = None
700 def __del__(self):
700 def __del__(self):
701 if self.dir_:
701 if self.dir_:
702 self.rmtree(self.dir_, True)
702 self.rmtree(self.dir_, True)
703
703
704 if opts['ssh']:
704 if opts['ssh']:
705 ui.setconfig("ui", "ssh", opts['ssh'])
705 ui.setconfig("ui", "ssh", opts['ssh'])
706 if opts['remotecmd']:
706 if opts['remotecmd']:
707 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
707 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
708
708
709 if not os.path.exists(source):
709 if not os.path.exists(source):
710 source = ui.expandpath(source)
710 source = ui.expandpath(source)
711
711
712 d = Dircleanup(dest)
712 d = Dircleanup(dest)
713 abspath = source
713 abspath = source
714 other = hg.repository(ui, source)
714 other = hg.repository(ui, source)
715
715
716 copy = False
716 copy = False
717 if other.dev() != -1:
717 if other.dev() != -1:
718 abspath = os.path.abspath(source)
718 abspath = os.path.abspath(source)
719 if not opts['pull'] and not opts['rev']:
719 if not opts['pull'] and not opts['rev']:
720 copy = True
720 copy = True
721
721
722 if copy:
722 if copy:
723 try:
723 try:
724 # we use a lock here because if we race with commit, we
724 # we use a lock here because if we race with commit, we
725 # can end up with extra data in the cloned revlogs that's
725 # can end up with extra data in the cloned revlogs that's
726 # not pointed to by changesets, thus causing verify to
726 # not pointed to by changesets, thus causing verify to
727 # fail
727 # fail
728 l1 = lock.lock(os.path.join(source, ".hg", "lock"))
728 l1 = lock.lock(os.path.join(source, ".hg", "lock"))
729 except OSError:
729 except OSError:
730 copy = False
730 copy = False
731
731
732 if copy:
732 if copy:
733 # we lock here to avoid premature writing to the target
733 # we lock here to avoid premature writing to the target
734 os.mkdir(os.path.join(dest, ".hg"))
734 os.mkdir(os.path.join(dest, ".hg"))
735 l2 = lock.lock(os.path.join(dest, ".hg", "lock"))
735 l2 = lock.lock(os.path.join(dest, ".hg", "lock"))
736
736
737 files = "data 00manifest.d 00manifest.i 00changelog.d 00changelog.i"
737 files = "data 00manifest.d 00manifest.i 00changelog.d 00changelog.i"
738 for f in files.split():
738 for f in files.split():
739 src = os.path.join(source, ".hg", f)
739 src = os.path.join(source, ".hg", f)
740 dst = os.path.join(dest, ".hg", f)
740 dst = os.path.join(dest, ".hg", f)
741 try:
741 try:
742 util.copyfiles(src, dst)
742 util.copyfiles(src, dst)
743 except OSError, inst:
743 except OSError, inst:
744 if inst.errno != errno.ENOENT:
744 if inst.errno != errno.ENOENT:
745 raise
745 raise
746
746
747 repo = hg.repository(ui, dest)
747 repo = hg.repository(ui, dest)
748
748
749 else:
749 else:
750 revs = None
750 revs = None
751 if opts['rev']:
751 if opts['rev']:
752 if not other.local():
752 if not other.local():
753 error = _("clone -r not supported yet for remote repositories.")
753 error = _("clone -r not supported yet for remote repositories.")
754 raise util.Abort(error)
754 raise util.Abort(error)
755 else:
755 else:
756 revs = [other.lookup(rev) for rev in opts['rev']]
756 revs = [other.lookup(rev) for rev in opts['rev']]
757 repo = hg.repository(ui, dest, create=1)
757 repo = hg.repository(ui, dest, create=1)
758 repo.pull(other, heads = revs)
758 repo.pull(other, heads = revs)
759
759
760 f = repo.opener("hgrc", "w", text=True)
760 f = repo.opener("hgrc", "w", text=True)
761 f.write("[paths]\n")
761 f.write("[paths]\n")
762 f.write("default = %s\n" % abspath)
762 f.write("default = %s\n" % abspath)
763 f.close()
763 f.close()
764
764
765 if not opts['noupdate']:
765 if not opts['noupdate']:
766 update(ui, repo)
766 update(ui, repo)
767
767
768 d.close()
768 d.close()
769
769
770 def commit(ui, repo, *pats, **opts):
770 def commit(ui, repo, *pats, **opts):
771 """commit the specified files or all outstanding changes
771 """commit the specified files or all outstanding changes
772
772
773 Commit changes to the given files into the repository.
773 Commit changes to the given files into the repository.
774
774
775 If a list of files is omitted, all changes reported by "hg status"
775 If a list of files is omitted, all changes reported by "hg status"
776 will be commited.
776 will be commited.
777
777
778 The HGEDITOR or EDITOR environment variables are used to start an
778 The HGEDITOR or EDITOR environment variables are used to start an
779 editor to add a commit comment.
779 editor to add a commit comment.
780 """
780 """
781 message = opts['message']
781 message = opts['message']
782 logfile = opts['logfile']
782 logfile = opts['logfile']
783
783
784 if message and logfile:
784 if message and logfile:
785 raise util.Abort(_('options --message and --logfile are mutually '
785 raise util.Abort(_('options --message and --logfile are mutually '
786 'exclusive'))
786 'exclusive'))
787 if not message and logfile:
787 if not message and logfile:
788 try:
788 try:
789 if logfile == '-':
789 if logfile == '-':
790 message = sys.stdin.read()
790 message = sys.stdin.read()
791 else:
791 else:
792 message = open(logfile).read()
792 message = open(logfile).read()
793 except IOError, inst:
793 except IOError, inst:
794 raise util.Abort(_("can't read commit message '%s': %s") %
794 raise util.Abort(_("can't read commit message '%s': %s") %
795 (logfile, inst.strerror))
795 (logfile, inst.strerror))
796
796
797 if opts['addremove']:
797 if opts['addremove']:
798 addremove(ui, repo, *pats, **opts)
798 addremove(ui, repo, *pats, **opts)
799 fns, match, anypats = matchpats(repo, pats, opts)
799 fns, match, anypats = matchpats(repo, pats, opts)
800 if pats:
800 if pats:
801 modified, added, removed, deleted, unknown = (
801 modified, added, removed, deleted, unknown = (
802 repo.changes(files=fns, match=match))
802 repo.changes(files=fns, match=match))
803 files = modified + added + removed
803 files = modified + added + removed
804 else:
804 else:
805 files = []
805 files = []
806 try:
806 try:
807 repo.commit(files, message, opts['user'], opts['date'], match)
807 repo.commit(files, message, opts['user'], opts['date'], match)
808 except ValueError, inst:
808 except ValueError, inst:
809 raise util.Abort(str(inst))
809 raise util.Abort(str(inst))
810
810
811 def docopy(ui, repo, pats, opts):
811 def docopy(ui, repo, pats, opts):
812 cwd = repo.getcwd()
812 cwd = repo.getcwd()
813 errors = 0
813 errors = 0
814 copied = []
814 copied = []
815 targets = {}
815 targets = {}
816
816
817 def okaytocopy(abs, rel, exact):
817 def okaytocopy(abs, rel, exact):
818 reasons = {'?': _('is not managed'),
818 reasons = {'?': _('is not managed'),
819 'a': _('has been marked for add'),
819 'a': _('has been marked for add'),
820 'r': _('has been marked for remove')}
820 'r': _('has been marked for remove')}
821 state = repo.dirstate.state(abs)
821 state = repo.dirstate.state(abs)
822 reason = reasons.get(state)
822 reason = reasons.get(state)
823 if reason:
823 if reason:
824 if state == 'a':
824 if state == 'a':
825 origsrc = repo.dirstate.copied(abs)
825 origsrc = repo.dirstate.copied(abs)
826 if origsrc is not None:
826 if origsrc is not None:
827 return origsrc
827 return origsrc
828 if exact:
828 if exact:
829 ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
829 ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
830 else:
830 else:
831 return abs
831 return abs
832
832
833 def copy(origsrc, abssrc, relsrc, target, exact):
833 def copy(origsrc, abssrc, relsrc, target, exact):
834 abstarget = util.canonpath(repo.root, cwd, target)
834 abstarget = util.canonpath(repo.root, cwd, target)
835 reltarget = util.pathto(cwd, abstarget)
835 reltarget = util.pathto(cwd, abstarget)
836 prevsrc = targets.get(abstarget)
836 prevsrc = targets.get(abstarget)
837 if prevsrc is not None:
837 if prevsrc is not None:
838 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
838 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
839 (reltarget, abssrc, prevsrc))
839 (reltarget, abssrc, prevsrc))
840 return
840 return
841 if (not opts['after'] and os.path.exists(reltarget) or
841 if (not opts['after'] and os.path.exists(reltarget) or
842 opts['after'] and repo.dirstate.state(abstarget) not in '?r'):
842 opts['after'] and repo.dirstate.state(abstarget) not in '?r'):
843 if not opts['force']:
843 if not opts['force']:
844 ui.warn(_('%s: not overwriting - file exists\n') %
844 ui.warn(_('%s: not overwriting - file exists\n') %
845 reltarget)
845 reltarget)
846 return
846 return
847 if not opts['after']:
847 if not opts['after']:
848 os.unlink(reltarget)
848 os.unlink(reltarget)
849 if opts['after']:
849 if opts['after']:
850 if not os.path.exists(reltarget):
850 if not os.path.exists(reltarget):
851 return
851 return
852 else:
852 else:
853 targetdir = os.path.dirname(reltarget) or '.'
853 targetdir = os.path.dirname(reltarget) or '.'
854 if not os.path.isdir(targetdir):
854 if not os.path.isdir(targetdir):
855 os.makedirs(targetdir)
855 os.makedirs(targetdir)
856 try:
856 try:
857 shutil.copyfile(relsrc, reltarget)
857 shutil.copyfile(relsrc, reltarget)
858 shutil.copymode(relsrc, reltarget)
858 shutil.copymode(relsrc, reltarget)
859 except shutil.Error, inst:
859 except shutil.Error, inst:
860 raise util.Abort(str(inst))
860 raise util.Abort(str(inst))
861 except IOError, inst:
861 except IOError, inst:
862 if inst.errno == errno.ENOENT:
862 if inst.errno == errno.ENOENT:
863 ui.warn(_('%s: deleted in working copy\n') % relsrc)
863 ui.warn(_('%s: deleted in working copy\n') % relsrc)
864 else:
864 else:
865 ui.warn(_('%s: cannot copy - %s\n') %
865 ui.warn(_('%s: cannot copy - %s\n') %
866 (relsrc, inst.strerror))
866 (relsrc, inst.strerror))
867 errors += 1
867 errors += 1
868 return
868 return
869 if ui.verbose or not exact:
869 if ui.verbose or not exact:
870 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
870 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
871 targets[abstarget] = abssrc
871 targets[abstarget] = abssrc
872 repo.copy(origsrc, abstarget)
872 repo.copy(origsrc, abstarget)
873 copied.append((abssrc, relsrc, exact))
873 copied.append((abssrc, relsrc, exact))
874
874
875 def targetpathfn(pat, dest, srcs):
875 def targetpathfn(pat, dest, srcs):
876 if os.path.isdir(pat):
876 if os.path.isdir(pat):
877 abspfx = util.canonpath(repo.root, cwd, pat)
877 abspfx = util.canonpath(repo.root, cwd, pat)
878 if destdirexists:
878 if destdirexists:
879 striplen = len(os.path.split(abspfx)[0])
879 striplen = len(os.path.split(abspfx)[0])
880 else:
880 else:
881 striplen = len(abspfx)
881 striplen = len(abspfx)
882 if striplen:
882 if striplen:
883 striplen += len(os.sep)
883 striplen += len(os.sep)
884 res = lambda p: os.path.join(dest, p[striplen:])
884 res = lambda p: os.path.join(dest, p[striplen:])
885 elif destdirexists:
885 elif destdirexists:
886 res = lambda p: os.path.join(dest, os.path.basename(p))
886 res = lambda p: os.path.join(dest, os.path.basename(p))
887 else:
887 else:
888 res = lambda p: dest
888 res = lambda p: dest
889 return res
889 return res
890
890
891 def targetpathafterfn(pat, dest, srcs):
891 def targetpathafterfn(pat, dest, srcs):
892 if util.patkind(pat, None)[0]:
892 if util.patkind(pat, None)[0]:
893 # a mercurial pattern
893 # a mercurial pattern
894 res = lambda p: os.path.join(dest, os.path.basename(p))
894 res = lambda p: os.path.join(dest, os.path.basename(p))
895 else:
895 else:
896 abspfx = util.canonpath(repo.root, cwd, pat)
896 abspfx = util.canonpath(repo.root, cwd, pat)
897 if len(abspfx) < len(srcs[0][0]):
897 if len(abspfx) < len(srcs[0][0]):
898 # A directory. Either the target path contains the last
898 # A directory. Either the target path contains the last
899 # component of the source path or it does not.
899 # component of the source path or it does not.
900 def evalpath(striplen):
900 def evalpath(striplen):
901 score = 0
901 score = 0
902 for s in srcs:
902 for s in srcs:
903 t = os.path.join(dest, s[0][striplen:])
903 t = os.path.join(dest, s[0][striplen:])
904 if os.path.exists(t):
904 if os.path.exists(t):
905 score += 1
905 score += 1
906 return score
906 return score
907
907
908 striplen = len(abspfx)
908 striplen = len(abspfx)
909 if striplen:
909 if striplen:
910 striplen += len(os.sep)
910 striplen += len(os.sep)
911 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
911 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
912 score = evalpath(striplen)
912 score = evalpath(striplen)
913 striplen1 = len(os.path.split(abspfx)[0])
913 striplen1 = len(os.path.split(abspfx)[0])
914 if striplen1:
914 if striplen1:
915 striplen1 += len(os.sep)
915 striplen1 += len(os.sep)
916 if evalpath(striplen1) > score:
916 if evalpath(striplen1) > score:
917 striplen = striplen1
917 striplen = striplen1
918 res = lambda p: os.path.join(dest, p[striplen:])
918 res = lambda p: os.path.join(dest, p[striplen:])
919 else:
919 else:
920 # a file
920 # a file
921 if destdirexists:
921 if destdirexists:
922 res = lambda p: os.path.join(dest, os.path.basename(p))
922 res = lambda p: os.path.join(dest, os.path.basename(p))
923 else:
923 else:
924 res = lambda p: dest
924 res = lambda p: dest
925 return res
925 return res
926
926
927
927
928 pats = list(pats)
928 pats = list(pats)
929 if not pats:
929 if not pats:
930 raise util.Abort(_('no source or destination specified'))
930 raise util.Abort(_('no source or destination specified'))
931 if len(pats) == 1:
931 if len(pats) == 1:
932 raise util.Abort(_('no destination specified'))
932 raise util.Abort(_('no destination specified'))
933 dest = pats.pop()
933 dest = pats.pop()
934 destdirexists = os.path.isdir(dest)
934 destdirexists = os.path.isdir(dest)
935 if (len(pats) > 1 or util.patkind(pats[0], None)[0]) and not destdirexists:
935 if (len(pats) > 1 or util.patkind(pats[0], None)[0]) and not destdirexists:
936 raise util.Abort(_('with multiple sources, destination must be an '
936 raise util.Abort(_('with multiple sources, destination must be an '
937 'existing directory'))
937 'existing directory'))
938 if opts['after']:
938 if opts['after']:
939 tfn = targetpathafterfn
939 tfn = targetpathafterfn
940 else:
940 else:
941 tfn = targetpathfn
941 tfn = targetpathfn
942 copylist = []
942 copylist = []
943 for pat in pats:
943 for pat in pats:
944 srcs = []
944 srcs = []
945 for tag, abssrc, relsrc, exact in walk(repo, [pat], opts):
945 for tag, abssrc, relsrc, exact in walk(repo, [pat], opts):
946 origsrc = okaytocopy(abssrc, relsrc, exact)
946 origsrc = okaytocopy(abssrc, relsrc, exact)
947 if origsrc:
947 if origsrc:
948 srcs.append((origsrc, abssrc, relsrc, exact))
948 srcs.append((origsrc, abssrc, relsrc, exact))
949 if not srcs:
949 if not srcs:
950 continue
950 continue
951 copylist.append((tfn(pat, dest, srcs), srcs))
951 copylist.append((tfn(pat, dest, srcs), srcs))
952 if not copylist:
952 if not copylist:
953 raise util.Abort(_('no files to copy'))
953 raise util.Abort(_('no files to copy'))
954
954
955 for targetpath, srcs in copylist:
955 for targetpath, srcs in copylist:
956 for origsrc, abssrc, relsrc, exact in srcs:
956 for origsrc, abssrc, relsrc, exact in srcs:
957 copy(origsrc, abssrc, relsrc, targetpath(abssrc), exact)
957 copy(origsrc, abssrc, relsrc, targetpath(abssrc), exact)
958
958
959 if errors:
959 if errors:
960 ui.warn(_('(consider using --after)\n'))
960 ui.warn(_('(consider using --after)\n'))
961 return errors, copied
961 return errors, copied
962
962
963 def copy(ui, repo, *pats, **opts):
963 def copy(ui, repo, *pats, **opts):
964 """mark files as copied for the next commit
964 """mark files as copied for the next commit
965
965
966 Mark dest as having copies of source files. If dest is a
966 Mark dest as having copies of source files. If dest is a
967 directory, copies are put in that directory. If dest is a file,
967 directory, copies are put in that directory. If dest is a file,
968 there can only be one source.
968 there can only be one source.
969
969
970 By default, this command copies the contents of files as they
970 By default, this command copies the contents of files as they
971 stand in the working directory. If invoked with --after, the
971 stand in the working directory. If invoked with --after, the
972 operation is recorded, but no copying is performed.
972 operation is recorded, but no copying is performed.
973
973
974 This command takes effect in the next commit.
974 This command takes effect in the next commit.
975
975
976 NOTE: This command should be treated as experimental. While it
976 NOTE: This command should be treated as experimental. While it
977 should properly record copied files, this information is not yet
977 should properly record copied files, this information is not yet
978 fully used by merge, nor fully reported by log.
978 fully used by merge, nor fully reported by log.
979 """
979 """
980 errs, copied = docopy(ui, repo, pats, opts)
980 errs, copied = docopy(ui, repo, pats, opts)
981 return errs
981 return errs
982
982
983 def debugancestor(ui, index, rev1, rev2):
983 def debugancestor(ui, index, rev1, rev2):
984 """find the ancestor revision of two revisions in a given index"""
984 """find the ancestor revision of two revisions in a given index"""
985 r = revlog.revlog(util.opener(os.getcwd()), index, "")
985 r = revlog.revlog(util.opener(os.getcwd()), index, "")
986 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
986 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
987 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
987 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
988
988
989 def debugcheckstate(ui, repo):
989 def debugcheckstate(ui, repo):
990 """validate the correctness of the current dirstate"""
990 """validate the correctness of the current dirstate"""
991 parent1, parent2 = repo.dirstate.parents()
991 parent1, parent2 = repo.dirstate.parents()
992 repo.dirstate.read()
992 repo.dirstate.read()
993 dc = repo.dirstate.map
993 dc = repo.dirstate.map
994 keys = dc.keys()
994 keys = dc.keys()
995 keys.sort()
995 keys.sort()
996 m1n = repo.changelog.read(parent1)[0]
996 m1n = repo.changelog.read(parent1)[0]
997 m2n = repo.changelog.read(parent2)[0]
997 m2n = repo.changelog.read(parent2)[0]
998 m1 = repo.manifest.read(m1n)
998 m1 = repo.manifest.read(m1n)
999 m2 = repo.manifest.read(m2n)
999 m2 = repo.manifest.read(m2n)
1000 errors = 0
1000 errors = 0
1001 for f in dc:
1001 for f in dc:
1002 state = repo.dirstate.state(f)
1002 state = repo.dirstate.state(f)
1003 if state in "nr" and f not in m1:
1003 if state in "nr" and f not in m1:
1004 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1004 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1005 errors += 1
1005 errors += 1
1006 if state in "a" and f in m1:
1006 if state in "a" and f in m1:
1007 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1007 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1008 errors += 1
1008 errors += 1
1009 if state in "m" and f not in m1 and f not in m2:
1009 if state in "m" and f not in m1 and f not in m2:
1010 ui.warn(_("%s in state %s, but not in either manifest\n") %
1010 ui.warn(_("%s in state %s, but not in either manifest\n") %
1011 (f, state))
1011 (f, state))
1012 errors += 1
1012 errors += 1
1013 for f in m1:
1013 for f in m1:
1014 state = repo.dirstate.state(f)
1014 state = repo.dirstate.state(f)
1015 if state not in "nrm":
1015 if state not in "nrm":
1016 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1016 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1017 errors += 1
1017 errors += 1
1018 if errors:
1018 if errors:
1019 error = _(".hg/dirstate inconsistent with current parent's manifest")
1019 error = _(".hg/dirstate inconsistent with current parent's manifest")
1020 raise util.Abort(error)
1020 raise util.Abort(error)
1021
1021
1022 def debugconfig(ui):
1022 def debugconfig(ui):
1023 """show combined config settings from all hgrc files"""
1023 """show combined config settings from all hgrc files"""
1024 try:
1024 try:
1025 repo = hg.repository(ui)
1025 repo = hg.repository(ui)
1026 except hg.RepoError:
1026 except hg.RepoError:
1027 pass
1027 pass
1028 for section, name, value in ui.walkconfig():
1028 for section, name, value in ui.walkconfig():
1029 ui.write('%s.%s=%s\n' % (section, name, value))
1029 ui.write('%s.%s=%s\n' % (section, name, value))
1030
1030
1031 def debugsetparents(ui, repo, rev1, rev2=None):
1031 def debugsetparents(ui, repo, rev1, rev2=None):
1032 """manually set the parents of the current working directory
1032 """manually set the parents of the current working directory
1033
1033
1034 This is useful for writing repository conversion tools, but should
1034 This is useful for writing repository conversion tools, but should
1035 be used with care.
1035 be used with care.
1036 """
1036 """
1037
1037
1038 if not rev2:
1038 if not rev2:
1039 rev2 = hex(nullid)
1039 rev2 = hex(nullid)
1040
1040
1041 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1041 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1042
1042
1043 def debugstate(ui, repo):
1043 def debugstate(ui, repo):
1044 """show the contents of the current dirstate"""
1044 """show the contents of the current dirstate"""
1045 repo.dirstate.read()
1045 repo.dirstate.read()
1046 dc = repo.dirstate.map
1046 dc = repo.dirstate.map
1047 keys = dc.keys()
1047 keys = dc.keys()
1048 keys.sort()
1048 keys.sort()
1049 for file_ in keys:
1049 for file_ in keys:
1050 ui.write("%c %3o %10d %s %s\n"
1050 ui.write("%c %3o %10d %s %s\n"
1051 % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
1051 % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
1052 time.strftime("%x %X",
1052 time.strftime("%x %X",
1053 time.localtime(dc[file_][3])), file_))
1053 time.localtime(dc[file_][3])), file_))
1054 for f in repo.dirstate.copies:
1054 for f in repo.dirstate.copies:
1055 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copies[f], f))
1055 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copies[f], f))
1056
1056
1057 def debugdata(ui, file_, rev):
1057 def debugdata(ui, file_, rev):
1058 """dump the contents of an data file revision"""
1058 """dump the contents of an data file revision"""
1059 r = revlog.revlog(util.opener(os.getcwd()), file_[:-2] + ".i", file_)
1059 r = revlog.revlog(util.opener(os.getcwd()), file_[:-2] + ".i", file_)
1060 try:
1060 try:
1061 ui.write(r.revision(r.lookup(rev)))
1061 ui.write(r.revision(r.lookup(rev)))
1062 except KeyError:
1062 except KeyError:
1063 raise util.Abort(_('invalid revision identifier %s'), rev)
1063 raise util.Abort(_('invalid revision identifier %s'), rev)
1064
1064
1065 def debugindex(ui, file_):
1065 def debugindex(ui, file_):
1066 """dump the contents of an index file"""
1066 """dump the contents of an index file"""
1067 r = revlog.revlog(util.opener(os.getcwd()), file_, "")
1067 r = revlog.revlog(util.opener(os.getcwd()), file_, "")
1068 ui.write(" rev offset length base linkrev" +
1068 ui.write(" rev offset length base linkrev" +
1069 " nodeid p1 p2\n")
1069 " nodeid p1 p2\n")
1070 for i in range(r.count()):
1070 for i in range(r.count()):
1071 e = r.index[i]
1071 e = r.index[i]
1072 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1072 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1073 i, e[0], e[1], e[2], e[3],
1073 i, e[0], e[1], e[2], e[3],
1074 short(e[6]), short(e[4]), short(e[5])))
1074 short(e[6]), short(e[4]), short(e[5])))
1075
1075
1076 def debugindexdot(ui, file_):
1076 def debugindexdot(ui, file_):
1077 """dump an index DAG as a .dot file"""
1077 """dump an index DAG as a .dot file"""
1078 r = revlog.revlog(util.opener(os.getcwd()), file_, "")
1078 r = revlog.revlog(util.opener(os.getcwd()), file_, "")
1079 ui.write("digraph G {\n")
1079 ui.write("digraph G {\n")
1080 for i in range(r.count()):
1080 for i in range(r.count()):
1081 e = r.index[i]
1081 e = r.index[i]
1082 ui.write("\t%d -> %d\n" % (r.rev(e[4]), i))
1082 ui.write("\t%d -> %d\n" % (r.rev(e[4]), i))
1083 if e[5] != nullid:
1083 if e[5] != nullid:
1084 ui.write("\t%d -> %d\n" % (r.rev(e[5]), i))
1084 ui.write("\t%d -> %d\n" % (r.rev(e[5]), i))
1085 ui.write("}\n")
1085 ui.write("}\n")
1086
1086
1087 def debugrename(ui, repo, file, rev=None):
1087 def debugrename(ui, repo, file, rev=None):
1088 """dump rename information"""
1088 """dump rename information"""
1089 r = repo.file(relpath(repo, [file])[0])
1089 r = repo.file(relpath(repo, [file])[0])
1090 if rev:
1090 if rev:
1091 try:
1091 try:
1092 # assume all revision numbers are for changesets
1092 # assume all revision numbers are for changesets
1093 n = repo.lookup(rev)
1093 n = repo.lookup(rev)
1094 change = repo.changelog.read(n)
1094 change = repo.changelog.read(n)
1095 m = repo.manifest.read(change[0])
1095 m = repo.manifest.read(change[0])
1096 n = m[relpath(repo, [file])[0]]
1096 n = m[relpath(repo, [file])[0]]
1097 except (hg.RepoError, KeyError):
1097 except (hg.RepoError, KeyError):
1098 n = r.lookup(rev)
1098 n = r.lookup(rev)
1099 else:
1099 else:
1100 n = r.tip()
1100 n = r.tip()
1101 m = r.renamed(n)
1101 m = r.renamed(n)
1102 if m:
1102 if m:
1103 ui.write(_("renamed from %s:%s\n") % (m[0], hex(m[1])))
1103 ui.write(_("renamed from %s:%s\n") % (m[0], hex(m[1])))
1104 else:
1104 else:
1105 ui.write(_("not renamed\n"))
1105 ui.write(_("not renamed\n"))
1106
1106
1107 def debugwalk(ui, repo, *pats, **opts):
1107 def debugwalk(ui, repo, *pats, **opts):
1108 """show how files match on given patterns"""
1108 """show how files match on given patterns"""
1109 items = list(walk(repo, pats, opts))
1109 items = list(walk(repo, pats, opts))
1110 if not items:
1110 if not items:
1111 return
1111 return
1112 fmt = '%%s %%-%ds %%-%ds %%s' % (
1112 fmt = '%%s %%-%ds %%-%ds %%s' % (
1113 max([len(abs) for (src, abs, rel, exact) in items]),
1113 max([len(abs) for (src, abs, rel, exact) in items]),
1114 max([len(rel) for (src, abs, rel, exact) in items]))
1114 max([len(rel) for (src, abs, rel, exact) in items]))
1115 for src, abs, rel, exact in items:
1115 for src, abs, rel, exact in items:
1116 line = fmt % (src, abs, rel, exact and 'exact' or '')
1116 line = fmt % (src, abs, rel, exact and 'exact' or '')
1117 ui.write("%s\n" % line.rstrip())
1117 ui.write("%s\n" % line.rstrip())
1118
1118
1119 def diff(ui, repo, *pats, **opts):
1119 def diff(ui, repo, *pats, **opts):
1120 """diff repository (or selected files)
1120 """diff repository (or selected files)
1121
1121
1122 Show differences between revisions for the specified files.
1122 Show differences between revisions for the specified files.
1123
1123
1124 Differences between files are shown using the unified diff format.
1124 Differences between files are shown using the unified diff format.
1125
1125
1126 When two revision arguments are given, then changes are shown
1126 When two revision arguments are given, then changes are shown
1127 between those revisions. If only one revision is specified then
1127 between those revisions. If only one revision is specified then
1128 that revision is compared to the working directory, and, when no
1128 that revision is compared to the working directory, and, when no
1129 revisions are specified, the working directory files are compared
1129 revisions are specified, the working directory files are compared
1130 to its parent.
1130 to its parent.
1131
1131
1132 Without the -a option, diff will avoid generating diffs of files
1132 Without the -a option, diff will avoid generating diffs of files
1133 it detects as binary. With -a, diff will generate a diff anyway,
1133 it detects as binary. With -a, diff will generate a diff anyway,
1134 probably with undesirable results.
1134 probably with undesirable results.
1135 """
1135 """
1136 node1, node2 = None, None
1136 node1, node2 = None, None
1137 revs = [repo.lookup(x) for x in opts['rev']]
1137 revs = [repo.lookup(x) for x in opts['rev']]
1138
1138
1139 if len(revs) > 0:
1139 if len(revs) > 0:
1140 node1 = revs[0]
1140 node1 = revs[0]
1141 if len(revs) > 1:
1141 if len(revs) > 1:
1142 node2 = revs[1]
1142 node2 = revs[1]
1143 if len(revs) > 2:
1143 if len(revs) > 2:
1144 raise util.Abort(_("too many revisions to diff"))
1144 raise util.Abort(_("too many revisions to diff"))
1145
1145
1146 fns, matchfn, anypats = matchpats(repo, pats, opts)
1146 fns, matchfn, anypats = matchpats(repo, pats, opts)
1147
1147
1148 dodiff(sys.stdout, ui, repo, node1, node2, fns, match=matchfn,
1148 dodiff(sys.stdout, ui, repo, node1, node2, fns, match=matchfn,
1149 text=opts['text'], opts=opts)
1149 text=opts['text'], opts=opts)
1150
1150
1151 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
1151 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
1152 node = repo.lookup(changeset)
1152 node = repo.lookup(changeset)
1153 parents = [p for p in repo.changelog.parents(node) if p != nullid]
1153 parents = [p for p in repo.changelog.parents(node) if p != nullid]
1154 if opts['switch_parent']:
1154 if opts['switch_parent']:
1155 parents.reverse()
1155 parents.reverse()
1156 prev = (parents and parents[0]) or nullid
1156 prev = (parents and parents[0]) or nullid
1157 change = repo.changelog.read(node)
1157 change = repo.changelog.read(node)
1158
1158
1159 fp = make_file(repo, repo.changelog, opts['output'],
1159 fp = make_file(repo, repo.changelog, opts['output'],
1160 node=node, total=total, seqno=seqno,
1160 node=node, total=total, seqno=seqno,
1161 revwidth=revwidth)
1161 revwidth=revwidth)
1162 if fp != sys.stdout:
1162 if fp != sys.stdout:
1163 ui.note("%s\n" % fp.name)
1163 ui.note("%s\n" % fp.name)
1164
1164
1165 fp.write("# HG changeset patch\n")
1165 fp.write("# HG changeset patch\n")
1166 fp.write("# User %s\n" % change[1])
1166 fp.write("# User %s\n" % change[1])
1167 fp.write("# Node ID %s\n" % hex(node))
1167 fp.write("# Node ID %s\n" % hex(node))
1168 fp.write("# Parent %s\n" % hex(prev))
1168 fp.write("# Parent %s\n" % hex(prev))
1169 if len(parents) > 1:
1169 if len(parents) > 1:
1170 fp.write("# Parent %s\n" % hex(parents[1]))
1170 fp.write("# Parent %s\n" % hex(parents[1]))
1171 fp.write(change[4].rstrip())
1171 fp.write(change[4].rstrip())
1172 fp.write("\n\n")
1172 fp.write("\n\n")
1173
1173
1174 dodiff(fp, ui, repo, prev, node, text=opts['text'])
1174 dodiff(fp, ui, repo, prev, node, text=opts['text'])
1175 if fp != sys.stdout:
1175 if fp != sys.stdout:
1176 fp.close()
1176 fp.close()
1177
1177
1178 def export(ui, repo, *changesets, **opts):
1178 def export(ui, repo, *changesets, **opts):
1179 """dump the header and diffs for one or more changesets
1179 """dump the header and diffs for one or more changesets
1180
1180
1181 Print the changeset header and diffs for one or more revisions.
1181 Print the changeset header and diffs for one or more revisions.
1182
1182
1183 The information shown in the changeset header is: author,
1183 The information shown in the changeset header is: author,
1184 changeset hash, parent and commit comment.
1184 changeset hash, parent and commit comment.
1185
1185
1186 Output may be to a file, in which case the name of the file is
1186 Output may be to a file, in which case the name of the file is
1187 given using a format string. The formatting rules are as follows:
1187 given using a format string. The formatting rules are as follows:
1188
1188
1189 %% literal "%" character
1189 %% literal "%" character
1190 %H changeset hash (40 bytes of hexadecimal)
1190 %H changeset hash (40 bytes of hexadecimal)
1191 %N number of patches being generated
1191 %N number of patches being generated
1192 %R changeset revision number
1192 %R changeset revision number
1193 %b basename of the exporting repository
1193 %b basename of the exporting repository
1194 %h short-form changeset hash (12 bytes of hexadecimal)
1194 %h short-form changeset hash (12 bytes of hexadecimal)
1195 %n zero-padded sequence number, starting at 1
1195 %n zero-padded sequence number, starting at 1
1196 %r zero-padded changeset revision number
1196 %r zero-padded changeset revision number
1197
1197
1198 Without the -a option, export will avoid generating diffs of files
1198 Without the -a option, export will avoid generating diffs of files
1199 it detects as binary. With -a, export will generate a diff anyway,
1199 it detects as binary. With -a, export will generate a diff anyway,
1200 probably with undesirable results.
1200 probably with undesirable results.
1201
1201
1202 With the --switch-parent option, the diff will be against the second
1202 With the --switch-parent option, the diff will be against the second
1203 parent. It can be useful to review a merge.
1203 parent. It can be useful to review a merge.
1204 """
1204 """
1205 if not changesets:
1205 if not changesets:
1206 raise util.Abort(_("export requires at least one changeset"))
1206 raise util.Abort(_("export requires at least one changeset"))
1207 seqno = 0
1207 seqno = 0
1208 revs = list(revrange(ui, repo, changesets))
1208 revs = list(revrange(ui, repo, changesets))
1209 total = len(revs)
1209 total = len(revs)
1210 revwidth = max(map(len, revs))
1210 revwidth = max(map(len, revs))
1211 msg = len(revs) > 1 and _("Exporting patches:\n") or _("Exporting patch:\n")
1211 msg = len(revs) > 1 and _("Exporting patches:\n") or _("Exporting patch:\n")
1212 ui.note(msg)
1212 ui.note(msg)
1213 for cset in revs:
1213 for cset in revs:
1214 seqno += 1
1214 seqno += 1
1215 doexport(ui, repo, cset, seqno, total, revwidth, opts)
1215 doexport(ui, repo, cset, seqno, total, revwidth, opts)
1216
1216
1217 def forget(ui, repo, *pats, **opts):
1217 def forget(ui, repo, *pats, **opts):
1218 """don't add the specified files on the next commit
1218 """don't add the specified files on the next commit
1219
1219
1220 Undo an 'hg add' scheduled for the next commit.
1220 Undo an 'hg add' scheduled for the next commit.
1221 """
1221 """
1222 forget = []
1222 forget = []
1223 for src, abs, rel, exact in walk(repo, pats, opts):
1223 for src, abs, rel, exact in walk(repo, pats, opts):
1224 if repo.dirstate.state(abs) == 'a':
1224 if repo.dirstate.state(abs) == 'a':
1225 forget.append(abs)
1225 forget.append(abs)
1226 if ui.verbose or not exact:
1226 if ui.verbose or not exact:
1227 ui.status(_('forgetting %s\n') % ((pats and rel) or abs))
1227 ui.status(_('forgetting %s\n') % ((pats and rel) or abs))
1228 repo.forget(forget)
1228 repo.forget(forget)
1229
1229
1230 def grep(ui, repo, pattern, *pats, **opts):
1230 def grep(ui, repo, pattern, *pats, **opts):
1231 """search for a pattern in specified files and revisions
1231 """search for a pattern in specified files and revisions
1232
1232
1233 Search revisions of files for a regular expression.
1233 Search revisions of files for a regular expression.
1234
1234
1235 This command behaves differently than Unix grep. It only accepts
1235 This command behaves differently than Unix grep. It only accepts
1236 Python/Perl regexps. It searches repository history, not the
1236 Python/Perl regexps. It searches repository history, not the
1237 working directory. It always prints the revision number in which
1237 working directory. It always prints the revision number in which
1238 a match appears.
1238 a match appears.
1239
1239
1240 By default, grep only prints output for the first revision of a
1240 By default, grep only prints output for the first revision of a
1241 file in which it finds a match. To get it to print every revision
1241 file in which it finds a match. To get it to print every revision
1242 that contains a change in match status ("-" for a match that
1242 that contains a change in match status ("-" for a match that
1243 becomes a non-match, or "+" for a non-match that becomes a match),
1243 becomes a non-match, or "+" for a non-match that becomes a match),
1244 use the --all flag.
1244 use the --all flag.
1245 """
1245 """
1246 reflags = 0
1246 reflags = 0
1247 if opts['ignore_case']:
1247 if opts['ignore_case']:
1248 reflags |= re.I
1248 reflags |= re.I
1249 regexp = re.compile(pattern, reflags)
1249 regexp = re.compile(pattern, reflags)
1250 sep, eol = ':', '\n'
1250 sep, eol = ':', '\n'
1251 if opts['print0']:
1251 if opts['print0']:
1252 sep = eol = '\0'
1252 sep = eol = '\0'
1253
1253
1254 fcache = {}
1254 fcache = {}
1255 def getfile(fn):
1255 def getfile(fn):
1256 if fn not in fcache:
1256 if fn not in fcache:
1257 fcache[fn] = repo.file(fn)
1257 fcache[fn] = repo.file(fn)
1258 return fcache[fn]
1258 return fcache[fn]
1259
1259
1260 def matchlines(body):
1260 def matchlines(body):
1261 begin = 0
1261 begin = 0
1262 linenum = 0
1262 linenum = 0
1263 while True:
1263 while True:
1264 match = regexp.search(body, begin)
1264 match = regexp.search(body, begin)
1265 if not match:
1265 if not match:
1266 break
1266 break
1267 mstart, mend = match.span()
1267 mstart, mend = match.span()
1268 linenum += body.count('\n', begin, mstart) + 1
1268 linenum += body.count('\n', begin, mstart) + 1
1269 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1269 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1270 lend = body.find('\n', mend)
1270 lend = body.find('\n', mend)
1271 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1271 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1272 begin = lend + 1
1272 begin = lend + 1
1273
1273
1274 class linestate(object):
1274 class linestate(object):
1275 def __init__(self, line, linenum, colstart, colend):
1275 def __init__(self, line, linenum, colstart, colend):
1276 self.line = line
1276 self.line = line
1277 self.linenum = linenum
1277 self.linenum = linenum
1278 self.colstart = colstart
1278 self.colstart = colstart
1279 self.colend = colend
1279 self.colend = colend
1280 def __eq__(self, other):
1280 def __eq__(self, other):
1281 return self.line == other.line
1281 return self.line == other.line
1282 def __hash__(self):
1282 def __hash__(self):
1283 return hash(self.line)
1283 return hash(self.line)
1284
1284
1285 matches = {}
1285 matches = {}
1286 def grepbody(fn, rev, body):
1286 def grepbody(fn, rev, body):
1287 matches[rev].setdefault(fn, {})
1287 matches[rev].setdefault(fn, {})
1288 m = matches[rev][fn]
1288 m = matches[rev][fn]
1289 for lnum, cstart, cend, line in matchlines(body):
1289 for lnum, cstart, cend, line in matchlines(body):
1290 s = linestate(line, lnum, cstart, cend)
1290 s = linestate(line, lnum, cstart, cend)
1291 m[s] = s
1291 m[s] = s
1292
1292
1293 prev = {}
1293 prev = {}
1294 ucache = {}
1294 ucache = {}
1295 def display(fn, rev, states, prevstates):
1295 def display(fn, rev, states, prevstates):
1296 diff = list(sets.Set(states).symmetric_difference(sets.Set(prevstates)))
1296 diff = list(sets.Set(states).symmetric_difference(sets.Set(prevstates)))
1297 diff.sort(lambda x, y: cmp(x.linenum, y.linenum))
1297 diff.sort(lambda x, y: cmp(x.linenum, y.linenum))
1298 counts = {'-': 0, '+': 0}
1298 counts = {'-': 0, '+': 0}
1299 filerevmatches = {}
1299 filerevmatches = {}
1300 for l in diff:
1300 for l in diff:
1301 if incrementing or not opts['all']:
1301 if incrementing or not opts['all']:
1302 change = ((l in prevstates) and '-') or '+'
1302 change = ((l in prevstates) and '-') or '+'
1303 r = rev
1303 r = rev
1304 else:
1304 else:
1305 change = ((l in states) and '-') or '+'
1305 change = ((l in states) and '-') or '+'
1306 r = prev[fn]
1306 r = prev[fn]
1307 cols = [fn, str(rev)]
1307 cols = [fn, str(rev)]
1308 if opts['line_number']:
1308 if opts['line_number']:
1309 cols.append(str(l.linenum))
1309 cols.append(str(l.linenum))
1310 if opts['all']:
1310 if opts['all']:
1311 cols.append(change)
1311 cols.append(change)
1312 if opts['user']:
1312 if opts['user']:
1313 cols.append(trimuser(ui, getchange(rev)[1], rev,
1313 cols.append(trimuser(ui, getchange(rev)[1], rev,
1314 ucache))
1314 ucache))
1315 if opts['files_with_matches']:
1315 if opts['files_with_matches']:
1316 c = (fn, rev)
1316 c = (fn, rev)
1317 if c in filerevmatches:
1317 if c in filerevmatches:
1318 continue
1318 continue
1319 filerevmatches[c] = 1
1319 filerevmatches[c] = 1
1320 else:
1320 else:
1321 cols.append(l.line)
1321 cols.append(l.line)
1322 ui.write(sep.join(cols), eol)
1322 ui.write(sep.join(cols), eol)
1323 counts[change] += 1
1323 counts[change] += 1
1324 return counts['+'], counts['-']
1324 return counts['+'], counts['-']
1325
1325
1326 fstate = {}
1326 fstate = {}
1327 skip = {}
1327 skip = {}
1328 changeiter, getchange, matchfn = walkchangerevs(ui, repo, pats, opts)
1328 changeiter, getchange, matchfn = walkchangerevs(ui, repo, pats, opts)
1329 count = 0
1329 count = 0
1330 incrementing = False
1330 incrementing = False
1331 for st, rev, fns in changeiter:
1331 for st, rev, fns in changeiter:
1332 if st == 'window':
1332 if st == 'window':
1333 incrementing = rev
1333 incrementing = rev
1334 matches.clear()
1334 matches.clear()
1335 elif st == 'add':
1335 elif st == 'add':
1336 change = repo.changelog.read(repo.lookup(str(rev)))
1336 change = repo.changelog.read(repo.lookup(str(rev)))
1337 mf = repo.manifest.read(change[0])
1337 mf = repo.manifest.read(change[0])
1338 matches[rev] = {}
1338 matches[rev] = {}
1339 for fn in fns:
1339 for fn in fns:
1340 if fn in skip:
1340 if fn in skip:
1341 continue
1341 continue
1342 fstate.setdefault(fn, {})
1342 fstate.setdefault(fn, {})
1343 try:
1343 try:
1344 grepbody(fn, rev, getfile(fn).read(mf[fn]))
1344 grepbody(fn, rev, getfile(fn).read(mf[fn]))
1345 except KeyError:
1345 except KeyError:
1346 pass
1346 pass
1347 elif st == 'iter':
1347 elif st == 'iter':
1348 states = matches[rev].items()
1348 states = matches[rev].items()
1349 states.sort()
1349 states.sort()
1350 for fn, m in states:
1350 for fn, m in states:
1351 if fn in skip:
1351 if fn in skip:
1352 continue
1352 continue
1353 if incrementing or not opts['all'] or fstate[fn]:
1353 if incrementing or not opts['all'] or fstate[fn]:
1354 pos, neg = display(fn, rev, m, fstate[fn])
1354 pos, neg = display(fn, rev, m, fstate[fn])
1355 count += pos + neg
1355 count += pos + neg
1356 if pos and not opts['all']:
1356 if pos and not opts['all']:
1357 skip[fn] = True
1357 skip[fn] = True
1358 fstate[fn] = m
1358 fstate[fn] = m
1359 prev[fn] = rev
1359 prev[fn] = rev
1360
1360
1361 if not incrementing:
1361 if not incrementing:
1362 fstate = fstate.items()
1362 fstate = fstate.items()
1363 fstate.sort()
1363 fstate.sort()
1364 for fn, state in fstate:
1364 for fn, state in fstate:
1365 if fn in skip:
1365 if fn in skip:
1366 continue
1366 continue
1367 display(fn, rev, {}, state)
1367 display(fn, rev, {}, state)
1368 return (count == 0 and 1) or 0
1368 return (count == 0 and 1) or 0
1369
1369
1370 def heads(ui, repo, **opts):
1370 def heads(ui, repo, **opts):
1371 """show current repository heads
1371 """show current repository heads
1372
1372
1373 Show all repository head changesets.
1373 Show all repository head changesets.
1374
1374
1375 Repository "heads" are changesets that don't have children
1375 Repository "heads" are changesets that don't have children
1376 changesets. They are where development generally takes place and
1376 changesets. They are where development generally takes place and
1377 are the usual targets for update and merge operations.
1377 are the usual targets for update and merge operations.
1378 """
1378 """
1379 if opts['rev']:
1379 if opts['rev']:
1380 heads = repo.heads(repo.lookup(opts['rev']))
1380 heads = repo.heads(repo.lookup(opts['rev']))
1381 else:
1381 else:
1382 heads = repo.heads()
1382 heads = repo.heads()
1383 br = None
1383 br = None
1384 if opts['branches']:
1384 if opts['branches']:
1385 br = repo.branchlookup(heads)
1385 br = repo.branchlookup(heads)
1386 for n in heads:
1386 for n in heads:
1387 show_changeset(ui, repo, changenode=n, brinfo=br)
1387 show_changeset(ui, repo, changenode=n, brinfo=br)
1388
1388
1389 def identify(ui, repo):
1389 def identify(ui, repo):
1390 """print information about the working copy
1390 """print information about the working copy
1391
1391
1392 Print a short summary of the current state of the repo.
1392 Print a short summary of the current state of the repo.
1393
1393
1394 This summary identifies the repository state using one or two parent
1394 This summary identifies the repository state using one or two parent
1395 hash identifiers, followed by a "+" if there are uncommitted changes
1395 hash identifiers, followed by a "+" if there are uncommitted changes
1396 in the working directory, followed by a list of tags for this revision.
1396 in the working directory, followed by a list of tags for this revision.
1397 """
1397 """
1398 parents = [p for p in repo.dirstate.parents() if p != nullid]
1398 parents = [p for p in repo.dirstate.parents() if p != nullid]
1399 if not parents:
1399 if not parents:
1400 ui.write(_("unknown\n"))
1400 ui.write(_("unknown\n"))
1401 return
1401 return
1402
1402
1403 hexfunc = ui.verbose and hex or short
1403 hexfunc = ui.verbose and hex or short
1404 modified, added, removed, deleted, unknown = repo.changes()
1404 modified, added, removed, deleted, unknown = repo.changes()
1405 output = ["%s%s" %
1405 output = ["%s%s" %
1406 ('+'.join([hexfunc(parent) for parent in parents]),
1406 ('+'.join([hexfunc(parent) for parent in parents]),
1407 (modified or added or removed or deleted) and "+" or "")]
1407 (modified or added or removed or deleted) and "+" or "")]
1408
1408
1409 if not ui.quiet:
1409 if not ui.quiet:
1410 # multiple tags for a single parent separated by '/'
1410 # multiple tags for a single parent separated by '/'
1411 parenttags = ['/'.join(tags)
1411 parenttags = ['/'.join(tags)
1412 for tags in map(repo.nodetags, parents) if tags]
1412 for tags in map(repo.nodetags, parents) if tags]
1413 # tags for multiple parents separated by ' + '
1413 # tags for multiple parents separated by ' + '
1414 if parenttags:
1414 if parenttags:
1415 output.append(' + '.join(parenttags))
1415 output.append(' + '.join(parenttags))
1416
1416
1417 ui.write("%s\n" % ' '.join(output))
1417 ui.write("%s\n" % ' '.join(output))
1418
1418
1419 def import_(ui, repo, patch1, *patches, **opts):
1419 def import_(ui, repo, patch1, *patches, **opts):
1420 """import an ordered set of patches
1420 """import an ordered set of patches
1421
1421
1422 Import a list of patches and commit them individually.
1422 Import a list of patches and commit them individually.
1423
1423
1424 If there are outstanding changes in the working directory, import
1424 If there are outstanding changes in the working directory, import
1425 will abort unless given the -f flag.
1425 will abort unless given the -f flag.
1426
1426
1427 If a patch looks like a mail message (its first line starts with
1427 If a patch looks like a mail message (its first line starts with
1428 "From " or looks like an RFC822 header), it will not be applied
1428 "From " or looks like an RFC822 header), it will not be applied
1429 unless the -f option is used. The importer neither parses nor
1429 unless the -f option is used. The importer neither parses nor
1430 discards mail headers, so use -f only to override the "mailness"
1430 discards mail headers, so use -f only to override the "mailness"
1431 safety check, not to import a real mail message.
1431 safety check, not to import a real mail message.
1432 """
1432 """
1433 patches = (patch1,) + patches
1433 patches = (patch1,) + patches
1434
1434
1435 if not opts['force']:
1435 if not opts['force']:
1436 modified, added, removed, deleted, unknown = repo.changes()
1436 modified, added, removed, deleted, unknown = repo.changes()
1437 if modified or added or removed or deleted:
1437 if modified or added or removed or deleted:
1438 raise util.Abort(_("outstanding uncommitted changes"))
1438 raise util.Abort(_("outstanding uncommitted changes"))
1439
1439
1440 d = opts["base"]
1440 d = opts["base"]
1441 strip = opts["strip"]
1441 strip = opts["strip"]
1442
1442
1443 mailre = re.compile(r'(?:From |[\w-]+:)')
1443 mailre = re.compile(r'(?:From |[\w-]+:)')
1444
1444
1445 # attempt to detect the start of a patch
1445 # attempt to detect the start of a patch
1446 # (this heuristic is borrowed from quilt)
1446 # (this heuristic is borrowed from quilt)
1447 diffre = re.compile(r'(?:Index:[ \t]|diff[ \t]|RCS file: |' +
1447 diffre = re.compile(r'(?:Index:[ \t]|diff[ \t]|RCS file: |' +
1448 'retrieving revision [0-9]+(\.[0-9]+)*$|' +
1448 'retrieving revision [0-9]+(\.[0-9]+)*$|' +
1449 '(---|\*\*\*)[ \t])')
1449 '(---|\*\*\*)[ \t])')
1450
1450
1451 for patch in patches:
1451 for patch in patches:
1452 ui.status(_("applying %s\n") % patch)
1452 ui.status(_("applying %s\n") % patch)
1453 pf = os.path.join(d, patch)
1453 pf = os.path.join(d, patch)
1454
1454
1455 message = []
1455 message = []
1456 user = None
1456 user = None
1457 hgpatch = False
1457 hgpatch = False
1458 for line in file(pf):
1458 for line in file(pf):
1459 line = line.rstrip()
1459 line = line.rstrip()
1460 if (not message and not hgpatch and
1460 if (not message and not hgpatch and
1461 mailre.match(line) and not opts['force']):
1461 mailre.match(line) and not opts['force']):
1462 if len(line) > 35:
1462 if len(line) > 35:
1463 line = line[:32] + '...'
1463 line = line[:32] + '...'
1464 raise util.Abort(_('first line looks like a '
1464 raise util.Abort(_('first line looks like a '
1465 'mail header: ') + line)
1465 'mail header: ') + line)
1466 if diffre.match(line):
1466 if diffre.match(line):
1467 break
1467 break
1468 elif hgpatch:
1468 elif hgpatch:
1469 # parse values when importing the result of an hg export
1469 # parse values when importing the result of an hg export
1470 if line.startswith("# User "):
1470 if line.startswith("# User "):
1471 user = line[7:]
1471 user = line[7:]
1472 ui.debug(_('User: %s\n') % user)
1472 ui.debug(_('User: %s\n') % user)
1473 elif not line.startswith("# ") and line:
1473 elif not line.startswith("# ") and line:
1474 message.append(line)
1474 message.append(line)
1475 hgpatch = False
1475 hgpatch = False
1476 elif line == '# HG changeset patch':
1476 elif line == '# HG changeset patch':
1477 hgpatch = True
1477 hgpatch = True
1478 message = [] # We may have collected garbage
1478 message = [] # We may have collected garbage
1479 else:
1479 else:
1480 message.append(line)
1480 message.append(line)
1481
1481
1482 # make sure message isn't empty
1482 # make sure message isn't empty
1483 if not message:
1483 if not message:
1484 message = _("imported patch %s\n") % patch
1484 message = _("imported patch %s\n") % patch
1485 else:
1485 else:
1486 message = "%s\n" % '\n'.join(message)
1486 message = "%s\n" % '\n'.join(message)
1487 ui.debug(_('message:\n%s\n') % message)
1487 ui.debug(_('message:\n%s\n') % message)
1488
1488
1489 files = util.patch(strip, pf, ui)
1489 files = util.patch(strip, pf, ui)
1490
1490
1491 if len(files) > 0:
1491 if len(files) > 0:
1492 addremove(ui, repo, *files)
1492 addremove(ui, repo, *files)
1493 repo.commit(files, message, user)
1493 repo.commit(files, message, user)
1494
1494
1495 def incoming(ui, repo, source="default", **opts):
1495 def incoming(ui, repo, source="default", **opts):
1496 """show new changesets found in source
1496 """show new changesets found in source
1497
1497
1498 Show new changesets found in the specified repo or the default
1498 Show new changesets found in the specified repo or the default
1499 pull repo. These are the changesets that would be pulled if a pull
1499 pull repo. These are the changesets that would be pulled if a pull
1500 was requested.
1500 was requested.
1501
1501
1502 Currently only local repositories are supported.
1502 Currently only local repositories are supported.
1503 """
1503 """
1504 source = ui.expandpath(source, repo.root)
1504 source = ui.expandpath(source, repo.root)
1505 other = hg.repository(ui, source)
1505 other = hg.repository(ui, source)
1506 if not other.local():
1506 if not other.local():
1507 raise util.Abort(_("incoming doesn't work for remote repositories yet"))
1507 raise util.Abort(_("incoming doesn't work for remote repositories yet"))
1508 o = repo.findincoming(other)
1508 o = repo.findincoming(other)
1509 if not o:
1509 if not o:
1510 return
1510 return
1511 o = other.changelog.nodesbetween(o)[0]
1511 o = other.changelog.nodesbetween(o)[0]
1512 if opts['newest_first']:
1512 if opts['newest_first']:
1513 o.reverse()
1513 o.reverse()
1514 for n in o:
1514 for n in o:
1515 parents = [p for p in other.changelog.parents(n) if p != nullid]
1515 parents = [p for p in other.changelog.parents(n) if p != nullid]
1516 if opts['no_merges'] and len(parents) == 2:
1516 if opts['no_merges'] and len(parents) == 2:
1517 continue
1517 continue
1518 show_changeset(ui, other, changenode=n)
1518 show_changeset(ui, other, changenode=n)
1519 if opts['patch']:
1519 if opts['patch']:
1520 prev = (parents and parents[0]) or nullid
1520 prev = (parents and parents[0]) or nullid
1521 dodiff(ui, ui, other, prev, n)
1521 dodiff(ui, ui, other, prev, n)
1522 ui.write("\n")
1522 ui.write("\n")
1523
1523
1524 def init(ui, dest="."):
1524 def init(ui, dest="."):
1525 """create a new repository in the given directory
1525 """create a new repository in the given directory
1526
1526
1527 Initialize a new repository in the given directory. If the given
1527 Initialize a new repository in the given directory. If the given
1528 directory does not exist, it is created.
1528 directory does not exist, it is created.
1529
1529
1530 If no directory is given, the current directory is used.
1530 If no directory is given, the current directory is used.
1531 """
1531 """
1532 if not os.path.exists(dest):
1532 if not os.path.exists(dest):
1533 os.mkdir(dest)
1533 os.mkdir(dest)
1534 hg.repository(ui, dest, create=1)
1534 hg.repository(ui, dest, create=1)
1535
1535
1536 def locate(ui, repo, *pats, **opts):
1536 def locate(ui, repo, *pats, **opts):
1537 """locate files matching specific patterns
1537 """locate files matching specific patterns
1538
1538
1539 Print all files under Mercurial control whose names match the
1539 Print all files under Mercurial control whose names match the
1540 given patterns.
1540 given patterns.
1541
1541
1542 This command searches the current directory and its
1542 This command searches the current directory and its
1543 subdirectories. To search an entire repository, move to the root
1543 subdirectories. To search an entire repository, move to the root
1544 of the repository.
1544 of the repository.
1545
1545
1546 If no patterns are given to match, this command prints all file
1546 If no patterns are given to match, this command prints all file
1547 names.
1547 names.
1548
1548
1549 If you want to feed the output of this command into the "xargs"
1549 If you want to feed the output of this command into the "xargs"
1550 command, use the "-0" option to both this command and "xargs".
1550 command, use the "-0" option to both this command and "xargs".
1551 This will avoid the problem of "xargs" treating single filenames
1551 This will avoid the problem of "xargs" treating single filenames
1552 that contain white space as multiple filenames.
1552 that contain white space as multiple filenames.
1553 """
1553 """
1554 end = opts['print0'] and '\0' or '\n'
1554 end = opts['print0'] and '\0' or '\n'
1555 rev = opts['rev']
1555 rev = opts['rev']
1556 if rev:
1556 if rev:
1557 node = repo.lookup(rev)
1557 node = repo.lookup(rev)
1558 else:
1558 else:
1559 node = None
1559 node = None
1560
1560
1561 for src, abs, rel, exact in walk(repo, pats, opts, node=node,
1561 for src, abs, rel, exact in walk(repo, pats, opts, node=node,
1562 head='(?:.*/|)'):
1562 head='(?:.*/|)'):
1563 if not node and repo.dirstate.state(abs) == '?':
1563 if not node and repo.dirstate.state(abs) == '?':
1564 continue
1564 continue
1565 if opts['fullpath']:
1565 if opts['fullpath']:
1566 ui.write(os.path.join(repo.root, abs), end)
1566 ui.write(os.path.join(repo.root, abs), end)
1567 else:
1567 else:
1568 ui.write(((pats and rel) or abs), end)
1568 ui.write(((pats and rel) or abs), end)
1569
1569
1570 def log(ui, repo, *pats, **opts):
1570 def log(ui, repo, *pats, **opts):
1571 """show revision history of entire repository or files
1571 """show revision history of entire repository or files
1572
1572
1573 Print the revision history of the specified files or the entire project.
1573 Print the revision history of the specified files or the entire project.
1574
1574
1575 By default this command outputs: changeset id and hash, tags,
1575 By default this command outputs: changeset id and hash, tags,
1576 non-trivial parents, user, date and time, and a summary for each
1576 non-trivial parents, user, date and time, and a summary for each
1577 commit. When the -v/--verbose switch is used, the list of changed
1577 commit. When the -v/--verbose switch is used, the list of changed
1578 files and full commit message is shown.
1578 files and full commit message is shown.
1579 """
1579 """
1580 class dui(object):
1580 class dui(object):
1581 # Implement and delegate some ui protocol. Save hunks of
1581 # Implement and delegate some ui protocol. Save hunks of
1582 # output for later display in the desired order.
1582 # output for later display in the desired order.
1583 def __init__(self, ui):
1583 def __init__(self, ui):
1584 self.ui = ui
1584 self.ui = ui
1585 self.hunk = {}
1585 self.hunk = {}
1586 def bump(self, rev):
1586 def bump(self, rev):
1587 self.rev = rev
1587 self.rev = rev
1588 self.hunk[rev] = []
1588 self.hunk[rev] = []
1589 def note(self, *args):
1589 def note(self, *args):
1590 if self.verbose:
1590 if self.verbose:
1591 self.write(*args)
1591 self.write(*args)
1592 def status(self, *args):
1592 def status(self, *args):
1593 if not self.quiet:
1593 if not self.quiet:
1594 self.write(*args)
1594 self.write(*args)
1595 def write(self, *args):
1595 def write(self, *args):
1596 self.hunk[self.rev].append(args)
1596 self.hunk[self.rev].append(args)
1597 def debug(self, *args):
1597 def debug(self, *args):
1598 if self.debugflag:
1598 if self.debugflag:
1599 self.write(*args)
1599 self.write(*args)
1600 def __getattr__(self, key):
1600 def __getattr__(self, key):
1601 return getattr(self.ui, key)
1601 return getattr(self.ui, key)
1602
1602 changeiter, getchange, matchfn = walkchangerevs(ui, repo, pats, opts)
1603 changeiter, getchange, matchfn = walkchangerevs(ui, repo, pats, opts)
1604
1605 if opts['limit']:
1606 try:
1607 limit = int(opts['limit'])
1608 except ValueError:
1609 raise util.Abort(_('limit must be a positive integer'))
1610 if limit <= 0: raise util.Abort(_('limit must be positive'))
1611 else:
1612 limit = sys.maxint
1613 count = 0
1614
1603 for st, rev, fns in changeiter:
1615 for st, rev, fns in changeiter:
1604 if st == 'window':
1616 if st == 'window':
1605 du = dui(ui)
1617 du = dui(ui)
1606 elif st == 'add':
1618 elif st == 'add':
1607 du.bump(rev)
1619 du.bump(rev)
1608 changenode = repo.changelog.node(rev)
1620 changenode = repo.changelog.node(rev)
1609 parents = [p for p in repo.changelog.parents(changenode)
1621 parents = [p for p in repo.changelog.parents(changenode)
1610 if p != nullid]
1622 if p != nullid]
1611 if opts['no_merges'] and len(parents) == 2:
1623 if opts['no_merges'] and len(parents) == 2:
1612 continue
1624 continue
1613 if opts['only_merges'] and len(parents) != 2:
1625 if opts['only_merges'] and len(parents) != 2:
1614 continue
1626 continue
1615
1627
1616 br = None
1628 br = None
1617 if opts['keyword']:
1629 if opts['keyword']:
1618 changes = getchange(rev)
1630 changes = getchange(rev)
1619 miss = 0
1631 miss = 0
1620 for k in [kw.lower() for kw in opts['keyword']]:
1632 for k in [kw.lower() for kw in opts['keyword']]:
1621 if not (k in changes[1].lower() or
1633 if not (k in changes[1].lower() or
1622 k in changes[4].lower() or
1634 k in changes[4].lower() or
1623 k in " ".join(changes[3][:20]).lower()):
1635 k in " ".join(changes[3][:20]).lower()):
1624 miss = 1
1636 miss = 1
1625 break
1637 break
1626 if miss:
1638 if miss:
1627 continue
1639 continue
1628
1640
1629 if opts['branch']:
1641 if opts['branch']:
1630 br = repo.branchlookup([repo.changelog.node(rev)])
1642 br = repo.branchlookup([repo.changelog.node(rev)])
1631
1643
1632 show_changeset(du, repo, rev, brinfo=br)
1644 show_changeset(du, repo, rev, brinfo=br)
1633 if opts['patch']:
1645 if opts['patch']:
1634 prev = (parents and parents[0]) or nullid
1646 prev = (parents and parents[0]) or nullid
1635 dodiff(du, du, repo, prev, changenode, match=matchfn)
1647 dodiff(du, du, repo, prev, changenode, match=matchfn)
1636 du.write("\n\n")
1648 du.write("\n\n")
1637 elif st == 'iter':
1649 elif st == 'iter':
1650 if count == limit: break
1651 count += 1
1638 for args in du.hunk[rev]:
1652 for args in du.hunk[rev]:
1639 ui.write(*args)
1653 ui.write(*args)
1640
1654
1641 def manifest(ui, repo, rev=None):
1655 def manifest(ui, repo, rev=None):
1642 """output the latest or given revision of the project manifest
1656 """output the latest or given revision of the project manifest
1643
1657
1644 Print a list of version controlled files for the given revision.
1658 Print a list of version controlled files for the given revision.
1645
1659
1646 The manifest is the list of files being version controlled. If no revision
1660 The manifest is the list of files being version controlled. If no revision
1647 is given then the tip is used.
1661 is given then the tip is used.
1648 """
1662 """
1649 if rev:
1663 if rev:
1650 try:
1664 try:
1651 # assume all revision numbers are for changesets
1665 # assume all revision numbers are for changesets
1652 n = repo.lookup(rev)
1666 n = repo.lookup(rev)
1653 change = repo.changelog.read(n)
1667 change = repo.changelog.read(n)
1654 n = change[0]
1668 n = change[0]
1655 except hg.RepoError:
1669 except hg.RepoError:
1656 n = repo.manifest.lookup(rev)
1670 n = repo.manifest.lookup(rev)
1657 else:
1671 else:
1658 n = repo.manifest.tip()
1672 n = repo.manifest.tip()
1659 m = repo.manifest.read(n)
1673 m = repo.manifest.read(n)
1660 mf = repo.manifest.readflags(n)
1674 mf = repo.manifest.readflags(n)
1661 files = m.keys()
1675 files = m.keys()
1662 files.sort()
1676 files.sort()
1663
1677
1664 for f in files:
1678 for f in files:
1665 ui.write("%40s %3s %s\n" % (hex(m[f]), mf[f] and "755" or "644", f))
1679 ui.write("%40s %3s %s\n" % (hex(m[f]), mf[f] and "755" or "644", f))
1666
1680
1667 def outgoing(ui, repo, dest="default-push", **opts):
1681 def outgoing(ui, repo, dest="default-push", **opts):
1668 """show changesets not found in destination
1682 """show changesets not found in destination
1669
1683
1670 Show changesets not found in the specified destination repo or the
1684 Show changesets not found in the specified destination repo or the
1671 default push repo. These are the changesets that would be pushed
1685 default push repo. These are the changesets that would be pushed
1672 if a push was requested.
1686 if a push was requested.
1673 """
1687 """
1674 dest = ui.expandpath(dest, repo.root)
1688 dest = ui.expandpath(dest, repo.root)
1675 other = hg.repository(ui, dest)
1689 other = hg.repository(ui, dest)
1676 o = repo.findoutgoing(other)
1690 o = repo.findoutgoing(other)
1677 o = repo.changelog.nodesbetween(o)[0]
1691 o = repo.changelog.nodesbetween(o)[0]
1678 if opts['newest_first']:
1692 if opts['newest_first']:
1679 o.reverse()
1693 o.reverse()
1680 for n in o:
1694 for n in o:
1681 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1695 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1682 if opts['no_merges'] and len(parents) == 2:
1696 if opts['no_merges'] and len(parents) == 2:
1683 continue
1697 continue
1684 show_changeset(ui, repo, changenode=n)
1698 show_changeset(ui, repo, changenode=n)
1685 if opts['patch']:
1699 if opts['patch']:
1686 prev = (parents and parents[0]) or nullid
1700 prev = (parents and parents[0]) or nullid
1687 dodiff(ui, ui, repo, prev, n)
1701 dodiff(ui, ui, repo, prev, n)
1688 ui.write("\n")
1702 ui.write("\n")
1689
1703
1690 def parents(ui, repo, rev=None, branch=None):
1704 def parents(ui, repo, rev=None, branch=None):
1691 """show the parents of the working dir or revision
1705 """show the parents of the working dir or revision
1692
1706
1693 Print the working directory's parent revisions.
1707 Print the working directory's parent revisions.
1694 """
1708 """
1695 if rev:
1709 if rev:
1696 p = repo.changelog.parents(repo.lookup(rev))
1710 p = repo.changelog.parents(repo.lookup(rev))
1697 else:
1711 else:
1698 p = repo.dirstate.parents()
1712 p = repo.dirstate.parents()
1699
1713
1700 br = None
1714 br = None
1701 if branch is not None:
1715 if branch is not None:
1702 br = repo.branchlookup(p)
1716 br = repo.branchlookup(p)
1703 for n in p:
1717 for n in p:
1704 if n != nullid:
1718 if n != nullid:
1705 show_changeset(ui, repo, changenode=n, brinfo=br)
1719 show_changeset(ui, repo, changenode=n, brinfo=br)
1706
1720
1707 def paths(ui, search=None):
1721 def paths(ui, search=None):
1708 """show definition of symbolic path names
1722 """show definition of symbolic path names
1709
1723
1710 Show definition of symbolic path name NAME. If no name is given, show
1724 Show definition of symbolic path name NAME. If no name is given, show
1711 definition of available names.
1725 definition of available names.
1712
1726
1713 Path names are defined in the [paths] section of /etc/mercurial/hgrc
1727 Path names are defined in the [paths] section of /etc/mercurial/hgrc
1714 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
1728 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
1715 """
1729 """
1716 try:
1730 try:
1717 repo = hg.repository(ui=ui)
1731 repo = hg.repository(ui=ui)
1718 except hg.RepoError:
1732 except hg.RepoError:
1719 pass
1733 pass
1720
1734
1721 if search:
1735 if search:
1722 for name, path in ui.configitems("paths"):
1736 for name, path in ui.configitems("paths"):
1723 if name == search:
1737 if name == search:
1724 ui.write("%s\n" % path)
1738 ui.write("%s\n" % path)
1725 return
1739 return
1726 ui.warn(_("not found!\n"))
1740 ui.warn(_("not found!\n"))
1727 return 1
1741 return 1
1728 else:
1742 else:
1729 for name, path in ui.configitems("paths"):
1743 for name, path in ui.configitems("paths"):
1730 ui.write("%s = %s\n" % (name, path))
1744 ui.write("%s = %s\n" % (name, path))
1731
1745
1732 def pull(ui, repo, source="default", **opts):
1746 def pull(ui, repo, source="default", **opts):
1733 """pull changes from the specified source
1747 """pull changes from the specified source
1734
1748
1735 Pull changes from a remote repository to a local one.
1749 Pull changes from a remote repository to a local one.
1736
1750
1737 This finds all changes from the repository at the specified path
1751 This finds all changes from the repository at the specified path
1738 or URL and adds them to the local repository. By default, this
1752 or URL and adds them to the local repository. By default, this
1739 does not update the copy of the project in the working directory.
1753 does not update the copy of the project in the working directory.
1740
1754
1741 Valid URLs are of the form:
1755 Valid URLs are of the form:
1742
1756
1743 local/filesystem/path
1757 local/filesystem/path
1744 http://[user@]host[:port][/path]
1758 http://[user@]host[:port][/path]
1745 https://[user@]host[:port][/path]
1759 https://[user@]host[:port][/path]
1746 ssh://[user@]host[:port][/path]
1760 ssh://[user@]host[:port][/path]
1747
1761
1748 SSH requires an accessible shell account on the destination machine
1762 SSH requires an accessible shell account on the destination machine
1749 and a copy of hg in the remote path. With SSH, paths are relative
1763 and a copy of hg in the remote path. With SSH, paths are relative
1750 to the remote user's home directory by default; use two slashes at
1764 to the remote user's home directory by default; use two slashes at
1751 the start of a path to specify it as relative to the filesystem root.
1765 the start of a path to specify it as relative to the filesystem root.
1752 """
1766 """
1753 source = ui.expandpath(source, repo.root)
1767 source = ui.expandpath(source, repo.root)
1754 ui.status(_('pulling from %s\n') % (source))
1768 ui.status(_('pulling from %s\n') % (source))
1755
1769
1756 if opts['ssh']:
1770 if opts['ssh']:
1757 ui.setconfig("ui", "ssh", opts['ssh'])
1771 ui.setconfig("ui", "ssh", opts['ssh'])
1758 if opts['remotecmd']:
1772 if opts['remotecmd']:
1759 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
1773 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
1760
1774
1761 other = hg.repository(ui, source)
1775 other = hg.repository(ui, source)
1762 revs = None
1776 revs = None
1763 if opts['rev'] and not other.local():
1777 if opts['rev'] and not other.local():
1764 raise util.Abort(_("pull -r doesn't work for remote repositories yet"))
1778 raise util.Abort(_("pull -r doesn't work for remote repositories yet"))
1765 elif opts['rev']:
1779 elif opts['rev']:
1766 revs = [other.lookup(rev) for rev in opts['rev']]
1780 revs = [other.lookup(rev) for rev in opts['rev']]
1767 r = repo.pull(other, heads=revs)
1781 r = repo.pull(other, heads=revs)
1768 if not r:
1782 if not r:
1769 if opts['update']:
1783 if opts['update']:
1770 return update(ui, repo)
1784 return update(ui, repo)
1771 else:
1785 else:
1772 ui.status(_("(run 'hg update' to get a working copy)\n"))
1786 ui.status(_("(run 'hg update' to get a working copy)\n"))
1773
1787
1774 return r
1788 return r
1775
1789
1776 def push(ui, repo, dest="default-push", force=False, ssh=None, remotecmd=None):
1790 def push(ui, repo, dest="default-push", force=False, ssh=None, remotecmd=None):
1777 """push changes to the specified destination
1791 """push changes to the specified destination
1778
1792
1779 Push changes from the local repository to the given destination.
1793 Push changes from the local repository to the given destination.
1780
1794
1781 This is the symmetrical operation for pull. It helps to move
1795 This is the symmetrical operation for pull. It helps to move
1782 changes from the current repository to a different one. If the
1796 changes from the current repository to a different one. If the
1783 destination is local this is identical to a pull in that directory
1797 destination is local this is identical to a pull in that directory
1784 from the current one.
1798 from the current one.
1785
1799
1786 By default, push will refuse to run if it detects the result would
1800 By default, push will refuse to run if it detects the result would
1787 increase the number of remote heads. This generally indicates the
1801 increase the number of remote heads. This generally indicates the
1788 the client has forgotten to sync and merge before pushing.
1802 the client has forgotten to sync and merge before pushing.
1789
1803
1790 Valid URLs are of the form:
1804 Valid URLs are of the form:
1791
1805
1792 local/filesystem/path
1806 local/filesystem/path
1793 ssh://[user@]host[:port][/path]
1807 ssh://[user@]host[:port][/path]
1794
1808
1795 SSH requires an accessible shell account on the destination
1809 SSH requires an accessible shell account on the destination
1796 machine and a copy of hg in the remote path.
1810 machine and a copy of hg in the remote path.
1797 """
1811 """
1798 dest = ui.expandpath(dest, repo.root)
1812 dest = ui.expandpath(dest, repo.root)
1799 ui.status('pushing to %s\n' % (dest))
1813 ui.status('pushing to %s\n' % (dest))
1800
1814
1801 if ssh:
1815 if ssh:
1802 ui.setconfig("ui", "ssh", ssh)
1816 ui.setconfig("ui", "ssh", ssh)
1803 if remotecmd:
1817 if remotecmd:
1804 ui.setconfig("ui", "remotecmd", remotecmd)
1818 ui.setconfig("ui", "remotecmd", remotecmd)
1805
1819
1806 other = hg.repository(ui, dest)
1820 other = hg.repository(ui, dest)
1807 r = repo.push(other, force)
1821 r = repo.push(other, force)
1808 return r
1822 return r
1809
1823
1810 def rawcommit(ui, repo, *flist, **rc):
1824 def rawcommit(ui, repo, *flist, **rc):
1811 """raw commit interface (DEPRECATED)
1825 """raw commit interface (DEPRECATED)
1812
1826
1813 Lowlevel commit, for use in helper scripts.
1827 Lowlevel commit, for use in helper scripts.
1814
1828
1815 This command is not intended to be used by normal users, as it is
1829 This command is not intended to be used by normal users, as it is
1816 primarily useful for importing from other SCMs.
1830 primarily useful for importing from other SCMs.
1817
1831
1818 This command is now deprecated and will be removed in a future
1832 This command is now deprecated and will be removed in a future
1819 release, please use debugsetparents and commit instead.
1833 release, please use debugsetparents and commit instead.
1820 """
1834 """
1821
1835
1822 ui.warn(_("(the rawcommit command is deprecated)\n"))
1836 ui.warn(_("(the rawcommit command is deprecated)\n"))
1823
1837
1824 message = rc['message']
1838 message = rc['message']
1825 if not message and rc['logfile']:
1839 if not message and rc['logfile']:
1826 try:
1840 try:
1827 message = open(rc['logfile']).read()
1841 message = open(rc['logfile']).read()
1828 except IOError:
1842 except IOError:
1829 pass
1843 pass
1830 if not message and not rc['logfile']:
1844 if not message and not rc['logfile']:
1831 raise util.Abort(_("missing commit message"))
1845 raise util.Abort(_("missing commit message"))
1832
1846
1833 files = relpath(repo, list(flist))
1847 files = relpath(repo, list(flist))
1834 if rc['files']:
1848 if rc['files']:
1835 files += open(rc['files']).read().splitlines()
1849 files += open(rc['files']).read().splitlines()
1836
1850
1837 rc['parent'] = map(repo.lookup, rc['parent'])
1851 rc['parent'] = map(repo.lookup, rc['parent'])
1838
1852
1839 try:
1853 try:
1840 repo.rawcommit(files, message, rc['user'], rc['date'], *rc['parent'])
1854 repo.rawcommit(files, message, rc['user'], rc['date'], *rc['parent'])
1841 except ValueError, inst:
1855 except ValueError, inst:
1842 raise util.Abort(str(inst))
1856 raise util.Abort(str(inst))
1843
1857
1844 def recover(ui, repo):
1858 def recover(ui, repo):
1845 """roll back an interrupted transaction
1859 """roll back an interrupted transaction
1846
1860
1847 Recover from an interrupted commit or pull.
1861 Recover from an interrupted commit or pull.
1848
1862
1849 This command tries to fix the repository status after an interrupted
1863 This command tries to fix the repository status after an interrupted
1850 operation. It should only be necessary when Mercurial suggests it.
1864 operation. It should only be necessary when Mercurial suggests it.
1851 """
1865 """
1852 if repo.recover():
1866 if repo.recover():
1853 return repo.verify()
1867 return repo.verify()
1854 return False
1868 return False
1855
1869
1856 def remove(ui, repo, pat, *pats, **opts):
1870 def remove(ui, repo, pat, *pats, **opts):
1857 """remove the specified files on the next commit
1871 """remove the specified files on the next commit
1858
1872
1859 Schedule the indicated files for removal from the repository.
1873 Schedule the indicated files for removal from the repository.
1860
1874
1861 This command schedules the files to be removed at the next commit.
1875 This command schedules the files to be removed at the next commit.
1862 This only removes files from the current branch, not from the
1876 This only removes files from the current branch, not from the
1863 entire project history. If the files still exist in the working
1877 entire project history. If the files still exist in the working
1864 directory, they will be deleted from it.
1878 directory, they will be deleted from it.
1865 """
1879 """
1866 names = []
1880 names = []
1867 def okaytoremove(abs, rel, exact):
1881 def okaytoremove(abs, rel, exact):
1868 modified, added, removed, deleted, unknown = repo.changes(files=[abs])
1882 modified, added, removed, deleted, unknown = repo.changes(files=[abs])
1869 reason = None
1883 reason = None
1870 if modified:
1884 if modified:
1871 reason = _('is modified')
1885 reason = _('is modified')
1872 elif added:
1886 elif added:
1873 reason = _('has been marked for add')
1887 reason = _('has been marked for add')
1874 elif unknown:
1888 elif unknown:
1875 reason = _('is not managed')
1889 reason = _('is not managed')
1876 if reason:
1890 if reason:
1877 if exact:
1891 if exact:
1878 ui.warn(_('not removing %s: file %s\n') % (rel, reason))
1892 ui.warn(_('not removing %s: file %s\n') % (rel, reason))
1879 else:
1893 else:
1880 return True
1894 return True
1881 for src, abs, rel, exact in walk(repo, (pat,) + pats, opts):
1895 for src, abs, rel, exact in walk(repo, (pat,) + pats, opts):
1882 if okaytoremove(abs, rel, exact):
1896 if okaytoremove(abs, rel, exact):
1883 if ui.verbose or not exact:
1897 if ui.verbose or not exact:
1884 ui.status(_('removing %s\n') % rel)
1898 ui.status(_('removing %s\n') % rel)
1885 names.append(abs)
1899 names.append(abs)
1886 repo.remove(names, unlink=True)
1900 repo.remove(names, unlink=True)
1887
1901
1888 def rename(ui, repo, *pats, **opts):
1902 def rename(ui, repo, *pats, **opts):
1889 """rename files; equivalent of copy + remove
1903 """rename files; equivalent of copy + remove
1890
1904
1891 Mark dest as copies of sources; mark sources for deletion. If
1905 Mark dest as copies of sources; mark sources for deletion. If
1892 dest is a directory, copies are put in that directory. If dest is
1906 dest is a directory, copies are put in that directory. If dest is
1893 a file, there can only be one source.
1907 a file, there can only be one source.
1894
1908
1895 By default, this command copies the contents of files as they
1909 By default, this command copies the contents of files as they
1896 stand in the working directory. If invoked with --after, the
1910 stand in the working directory. If invoked with --after, the
1897 operation is recorded, but no copying is performed.
1911 operation is recorded, but no copying is performed.
1898
1912
1899 This command takes effect in the next commit.
1913 This command takes effect in the next commit.
1900
1914
1901 NOTE: This command should be treated as experimental. While it
1915 NOTE: This command should be treated as experimental. While it
1902 should properly record rename files, this information is not yet
1916 should properly record rename files, this information is not yet
1903 fully used by merge, nor fully reported by log.
1917 fully used by merge, nor fully reported by log.
1904 """
1918 """
1905 errs, copied = docopy(ui, repo, pats, opts)
1919 errs, copied = docopy(ui, repo, pats, opts)
1906 names = []
1920 names = []
1907 for abs, rel, exact in copied:
1921 for abs, rel, exact in copied:
1908 if ui.verbose or not exact:
1922 if ui.verbose or not exact:
1909 ui.status(_('removing %s\n') % rel)
1923 ui.status(_('removing %s\n') % rel)
1910 names.append(abs)
1924 names.append(abs)
1911 repo.remove(names, unlink=True)
1925 repo.remove(names, unlink=True)
1912 return errs
1926 return errs
1913
1927
1914 def revert(ui, repo, *pats, **opts):
1928 def revert(ui, repo, *pats, **opts):
1915 """revert modified files or dirs back to their unmodified states
1929 """revert modified files or dirs back to their unmodified states
1916
1930
1917 Revert any uncommitted modifications made to the named files or
1931 Revert any uncommitted modifications made to the named files or
1918 directories. This restores the contents of the affected files to
1932 directories. This restores the contents of the affected files to
1919 an unmodified state.
1933 an unmodified state.
1920
1934
1921 If a file has been deleted, it is recreated. If the executable
1935 If a file has been deleted, it is recreated. If the executable
1922 mode of a file was changed, it is reset.
1936 mode of a file was changed, it is reset.
1923
1937
1924 If names are given, all files matching the names are reverted.
1938 If names are given, all files matching the names are reverted.
1925
1939
1926 If no arguments are given, all files in the repository are reverted.
1940 If no arguments are given, all files in the repository are reverted.
1927 """
1941 """
1928 node = opts['rev'] and repo.lookup(opts['rev']) or \
1942 node = opts['rev'] and repo.lookup(opts['rev']) or \
1929 repo.dirstate.parents()[0]
1943 repo.dirstate.parents()[0]
1930
1944
1931 files, choose, anypats = matchpats(repo, pats, opts)
1945 files, choose, anypats = matchpats(repo, pats, opts)
1932 modified, added, removed, deleted, unknown = repo.changes(match=choose)
1946 modified, added, removed, deleted, unknown = repo.changes(match=choose)
1933 repo.forget(added)
1947 repo.forget(added)
1934 repo.undelete(removed + deleted)
1948 repo.undelete(removed + deleted)
1935
1949
1936 return repo.update(node, False, True, choose, False)
1950 return repo.update(node, False, True, choose, False)
1937
1951
1938 def root(ui, repo):
1952 def root(ui, repo):
1939 """print the root (top) of the current working dir
1953 """print the root (top) of the current working dir
1940
1954
1941 Print the root directory of the current repository.
1955 Print the root directory of the current repository.
1942 """
1956 """
1943 ui.write(repo.root + "\n")
1957 ui.write(repo.root + "\n")
1944
1958
1945 def serve(ui, repo, **opts):
1959 def serve(ui, repo, **opts):
1946 """export the repository via HTTP
1960 """export the repository via HTTP
1947
1961
1948 Start a local HTTP repository browser and pull server.
1962 Start a local HTTP repository browser and pull server.
1949
1963
1950 By default, the server logs accesses to stdout and errors to
1964 By default, the server logs accesses to stdout and errors to
1951 stderr. Use the "-A" and "-E" options to log to files.
1965 stderr. Use the "-A" and "-E" options to log to files.
1952 """
1966 """
1953
1967
1954 if opts["stdio"]:
1968 if opts["stdio"]:
1955 fin, fout = sys.stdin, sys.stdout
1969 fin, fout = sys.stdin, sys.stdout
1956 sys.stdout = sys.stderr
1970 sys.stdout = sys.stderr
1957
1971
1958 # Prevent insertion/deletion of CRs
1972 # Prevent insertion/deletion of CRs
1959 util.set_binary(fin)
1973 util.set_binary(fin)
1960 util.set_binary(fout)
1974 util.set_binary(fout)
1961
1975
1962 def getarg():
1976 def getarg():
1963 argline = fin.readline()[:-1]
1977 argline = fin.readline()[:-1]
1964 arg, l = argline.split()
1978 arg, l = argline.split()
1965 val = fin.read(int(l))
1979 val = fin.read(int(l))
1966 return arg, val
1980 return arg, val
1967 def respond(v):
1981 def respond(v):
1968 fout.write("%d\n" % len(v))
1982 fout.write("%d\n" % len(v))
1969 fout.write(v)
1983 fout.write(v)
1970 fout.flush()
1984 fout.flush()
1971
1985
1972 lock = None
1986 lock = None
1973
1987
1974 while 1:
1988 while 1:
1975 cmd = fin.readline()[:-1]
1989 cmd = fin.readline()[:-1]
1976 if cmd == '':
1990 if cmd == '':
1977 return
1991 return
1978 if cmd == "heads":
1992 if cmd == "heads":
1979 h = repo.heads()
1993 h = repo.heads()
1980 respond(" ".join(map(hex, h)) + "\n")
1994 respond(" ".join(map(hex, h)) + "\n")
1981 if cmd == "lock":
1995 if cmd == "lock":
1982 lock = repo.lock()
1996 lock = repo.lock()
1983 respond("")
1997 respond("")
1984 if cmd == "unlock":
1998 if cmd == "unlock":
1985 if lock:
1999 if lock:
1986 lock.release()
2000 lock.release()
1987 lock = None
2001 lock = None
1988 respond("")
2002 respond("")
1989 elif cmd == "branches":
2003 elif cmd == "branches":
1990 arg, nodes = getarg()
2004 arg, nodes = getarg()
1991 nodes = map(bin, nodes.split(" "))
2005 nodes = map(bin, nodes.split(" "))
1992 r = []
2006 r = []
1993 for b in repo.branches(nodes):
2007 for b in repo.branches(nodes):
1994 r.append(" ".join(map(hex, b)) + "\n")
2008 r.append(" ".join(map(hex, b)) + "\n")
1995 respond("".join(r))
2009 respond("".join(r))
1996 elif cmd == "between":
2010 elif cmd == "between":
1997 arg, pairs = getarg()
2011 arg, pairs = getarg()
1998 pairs = [map(bin, p.split("-")) for p in pairs.split(" ")]
2012 pairs = [map(bin, p.split("-")) for p in pairs.split(" ")]
1999 r = []
2013 r = []
2000 for b in repo.between(pairs):
2014 for b in repo.between(pairs):
2001 r.append(" ".join(map(hex, b)) + "\n")
2015 r.append(" ".join(map(hex, b)) + "\n")
2002 respond("".join(r))
2016 respond("".join(r))
2003 elif cmd == "changegroup":
2017 elif cmd == "changegroup":
2004 nodes = []
2018 nodes = []
2005 arg, roots = getarg()
2019 arg, roots = getarg()
2006 nodes = map(bin, roots.split(" "))
2020 nodes = map(bin, roots.split(" "))
2007
2021
2008 cg = repo.changegroup(nodes, 'serve')
2022 cg = repo.changegroup(nodes, 'serve')
2009 while 1:
2023 while 1:
2010 d = cg.read(4096)
2024 d = cg.read(4096)
2011 if not d:
2025 if not d:
2012 break
2026 break
2013 fout.write(d)
2027 fout.write(d)
2014
2028
2015 fout.flush()
2029 fout.flush()
2016
2030
2017 elif cmd == "addchangegroup":
2031 elif cmd == "addchangegroup":
2018 if not lock:
2032 if not lock:
2019 respond("not locked")
2033 respond("not locked")
2020 continue
2034 continue
2021 respond("")
2035 respond("")
2022
2036
2023 r = repo.addchangegroup(fin)
2037 r = repo.addchangegroup(fin)
2024 respond("")
2038 respond("")
2025
2039
2026 optlist = "name templates style address port ipv6 accesslog errorlog"
2040 optlist = "name templates style address port ipv6 accesslog errorlog"
2027 for o in optlist.split():
2041 for o in optlist.split():
2028 if opts[o]:
2042 if opts[o]:
2029 ui.setconfig("web", o, opts[o])
2043 ui.setconfig("web", o, opts[o])
2030
2044
2031 if opts['daemon'] and not opts['daemon_pipefds']:
2045 if opts['daemon'] and not opts['daemon_pipefds']:
2032 rfd, wfd = os.pipe()
2046 rfd, wfd = os.pipe()
2033 args = sys.argv[:]
2047 args = sys.argv[:]
2034 args.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
2048 args.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
2035 pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
2049 pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
2036 args[0], args)
2050 args[0], args)
2037 os.close(wfd)
2051 os.close(wfd)
2038 os.read(rfd, 1)
2052 os.read(rfd, 1)
2039 os._exit(0)
2053 os._exit(0)
2040
2054
2041 try:
2055 try:
2042 httpd = hgweb.create_server(repo)
2056 httpd = hgweb.create_server(repo)
2043 except socket.error, inst:
2057 except socket.error, inst:
2044 raise util.Abort(_('cannot start server: ') + inst.args[1])
2058 raise util.Abort(_('cannot start server: ') + inst.args[1])
2045
2059
2046 if ui.verbose:
2060 if ui.verbose:
2047 addr, port = httpd.socket.getsockname()
2061 addr, port = httpd.socket.getsockname()
2048 if addr == '0.0.0.0':
2062 if addr == '0.0.0.0':
2049 addr = socket.gethostname()
2063 addr = socket.gethostname()
2050 else:
2064 else:
2051 try:
2065 try:
2052 addr = socket.gethostbyaddr(addr)[0]
2066 addr = socket.gethostbyaddr(addr)[0]
2053 except socket.error:
2067 except socket.error:
2054 pass
2068 pass
2055 if port != 80:
2069 if port != 80:
2056 ui.status(_('listening at http://%s:%d/\n') % (addr, port))
2070 ui.status(_('listening at http://%s:%d/\n') % (addr, port))
2057 else:
2071 else:
2058 ui.status(_('listening at http://%s/\n') % addr)
2072 ui.status(_('listening at http://%s/\n') % addr)
2059
2073
2060 if opts['pid_file']:
2074 if opts['pid_file']:
2061 fp = open(opts['pid_file'], 'w')
2075 fp = open(opts['pid_file'], 'w')
2062 fp.write(str(os.getpid()))
2076 fp.write(str(os.getpid()))
2063 fp.close()
2077 fp.close()
2064
2078
2065 if opts['daemon_pipefds']:
2079 if opts['daemon_pipefds']:
2066 rfd, wfd = [int(x) for x in opts['daemon_pipefds'].split(',')]
2080 rfd, wfd = [int(x) for x in opts['daemon_pipefds'].split(',')]
2067 os.close(rfd)
2081 os.close(rfd)
2068 os.write(wfd, 'y')
2082 os.write(wfd, 'y')
2069 os.close(wfd)
2083 os.close(wfd)
2070 sys.stdout.flush()
2084 sys.stdout.flush()
2071 sys.stderr.flush()
2085 sys.stderr.flush()
2072 fd = os.open(util.nulldev, os.O_RDWR)
2086 fd = os.open(util.nulldev, os.O_RDWR)
2073 if fd != 0: os.dup2(fd, 0)
2087 if fd != 0: os.dup2(fd, 0)
2074 if fd != 1: os.dup2(fd, 1)
2088 if fd != 1: os.dup2(fd, 1)
2075 if fd != 2: os.dup2(fd, 2)
2089 if fd != 2: os.dup2(fd, 2)
2076 if fd not in (0, 1, 2): os.close(fd)
2090 if fd not in (0, 1, 2): os.close(fd)
2077
2091
2078 httpd.serve_forever()
2092 httpd.serve_forever()
2079
2093
2080 def status(ui, repo, *pats, **opts):
2094 def status(ui, repo, *pats, **opts):
2081 """show changed files in the working directory
2095 """show changed files in the working directory
2082
2096
2083 Show changed files in the repository. If names are
2097 Show changed files in the repository. If names are
2084 given, only files that match are shown.
2098 given, only files that match are shown.
2085
2099
2086 The codes used to show the status of files are:
2100 The codes used to show the status of files are:
2087 M = modified
2101 M = modified
2088 A = added
2102 A = added
2089 R = removed
2103 R = removed
2090 ! = deleted, but still tracked
2104 ! = deleted, but still tracked
2091 ? = not tracked
2105 ? = not tracked
2092 """
2106 """
2093
2107
2094 files, matchfn, anypats = matchpats(repo, pats, opts)
2108 files, matchfn, anypats = matchpats(repo, pats, opts)
2095 cwd = (pats and repo.getcwd()) or ''
2109 cwd = (pats and repo.getcwd()) or ''
2096 modified, added, removed, deleted, unknown = [
2110 modified, added, removed, deleted, unknown = [
2097 [util.pathto(cwd, x) for x in n]
2111 [util.pathto(cwd, x) for x in n]
2098 for n in repo.changes(files=files, match=matchfn)]
2112 for n in repo.changes(files=files, match=matchfn)]
2099
2113
2100 changetypes = [(_('modified'), 'M', modified),
2114 changetypes = [(_('modified'), 'M', modified),
2101 (_('added'), 'A', added),
2115 (_('added'), 'A', added),
2102 (_('removed'), 'R', removed),
2116 (_('removed'), 'R', removed),
2103 (_('deleted'), '!', deleted),
2117 (_('deleted'), '!', deleted),
2104 (_('unknown'), '?', unknown)]
2118 (_('unknown'), '?', unknown)]
2105
2119
2106 end = opts['print0'] and '\0' or '\n'
2120 end = opts['print0'] and '\0' or '\n'
2107
2121
2108 for opt, char, changes in ([ct for ct in changetypes if opts[ct[0]]]
2122 for opt, char, changes in ([ct for ct in changetypes if opts[ct[0]]]
2109 or changetypes):
2123 or changetypes):
2110 if opts['no_status']:
2124 if opts['no_status']:
2111 format = "%%s%s" % end
2125 format = "%%s%s" % end
2112 else:
2126 else:
2113 format = "%s %%s%s" % (char, end);
2127 format = "%s %%s%s" % (char, end);
2114
2128
2115 for f in changes:
2129 for f in changes:
2116 ui.write(format % f)
2130 ui.write(format % f)
2117
2131
2118 def tag(ui, repo, name, rev_=None, **opts):
2132 def tag(ui, repo, name, rev_=None, **opts):
2119 """add a tag for the current tip or a given revision
2133 """add a tag for the current tip or a given revision
2120
2134
2121 Name a particular revision using <name>.
2135 Name a particular revision using <name>.
2122
2136
2123 Tags are used to name particular revisions of the repository and are
2137 Tags are used to name particular revisions of the repository and are
2124 very useful to compare different revision, to go back to significant
2138 very useful to compare different revision, to go back to significant
2125 earlier versions or to mark branch points as releases, etc.
2139 earlier versions or to mark branch points as releases, etc.
2126
2140
2127 If no revision is given, the tip is used.
2141 If no revision is given, the tip is used.
2128
2142
2129 To facilitate version control, distribution, and merging of tags,
2143 To facilitate version control, distribution, and merging of tags,
2130 they are stored as a file named ".hgtags" which is managed
2144 they are stored as a file named ".hgtags" which is managed
2131 similarly to other project files and can be hand-edited if
2145 similarly to other project files and can be hand-edited if
2132 necessary. The file '.hg/localtags' is used for local tags (not
2146 necessary. The file '.hg/localtags' is used for local tags (not
2133 shared among repositories).
2147 shared among repositories).
2134 """
2148 """
2135 if name == "tip":
2149 if name == "tip":
2136 raise util.Abort(_("the name 'tip' is reserved"))
2150 raise util.Abort(_("the name 'tip' is reserved"))
2137 if rev_ is not None:
2151 if rev_ is not None:
2138 ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, "
2152 ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, "
2139 "please use 'hg tag [-r REV] NAME' instead\n"))
2153 "please use 'hg tag [-r REV] NAME' instead\n"))
2140 if opts['rev']:
2154 if opts['rev']:
2141 raise util.Abort(_("use only one form to specify the revision"))
2155 raise util.Abort(_("use only one form to specify the revision"))
2142 if opts['rev']:
2156 if opts['rev']:
2143 rev_ = opts['rev']
2157 rev_ = opts['rev']
2144 if rev_:
2158 if rev_:
2145 r = hex(repo.lookup(rev_))
2159 r = hex(repo.lookup(rev_))
2146 else:
2160 else:
2147 r = hex(repo.changelog.tip())
2161 r = hex(repo.changelog.tip())
2148
2162
2149 disallowed = (revrangesep, '\r', '\n')
2163 disallowed = (revrangesep, '\r', '\n')
2150 for c in disallowed:
2164 for c in disallowed:
2151 if name.find(c) >= 0:
2165 if name.find(c) >= 0:
2152 raise util.Abort(_("%s cannot be used in a tag name") % repr(c))
2166 raise util.Abort(_("%s cannot be used in a tag name") % repr(c))
2153
2167
2154 repo.hook('pretag', throw=True, node=r, tag=name,
2168 repo.hook('pretag', throw=True, node=r, tag=name,
2155 local=int(not not opts['local']))
2169 local=int(not not opts['local']))
2156
2170
2157 if opts['local']:
2171 if opts['local']:
2158 repo.opener("localtags", "a").write("%s %s\n" % (r, name))
2172 repo.opener("localtags", "a").write("%s %s\n" % (r, name))
2159 repo.hook('tag', node=r, tag=name, local=1)
2173 repo.hook('tag', node=r, tag=name, local=1)
2160 return
2174 return
2161
2175
2162 for x in repo.changes():
2176 for x in repo.changes():
2163 if ".hgtags" in x:
2177 if ".hgtags" in x:
2164 raise util.Abort(_("working copy of .hgtags is changed "
2178 raise util.Abort(_("working copy of .hgtags is changed "
2165 "(please commit .hgtags manually)"))
2179 "(please commit .hgtags manually)"))
2166
2180
2167 repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name))
2181 repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name))
2168 if repo.dirstate.state(".hgtags") == '?':
2182 if repo.dirstate.state(".hgtags") == '?':
2169 repo.add([".hgtags"])
2183 repo.add([".hgtags"])
2170
2184
2171 message = (opts['message'] or
2185 message = (opts['message'] or
2172 _("Added tag %s for changeset %s") % (name, r))
2186 _("Added tag %s for changeset %s") % (name, r))
2173 try:
2187 try:
2174 repo.commit([".hgtags"], message, opts['user'], opts['date'])
2188 repo.commit([".hgtags"], message, opts['user'], opts['date'])
2175 repo.hook('tag', node=r, tag=name, local=0)
2189 repo.hook('tag', node=r, tag=name, local=0)
2176 except ValueError, inst:
2190 except ValueError, inst:
2177 raise util.Abort(str(inst))
2191 raise util.Abort(str(inst))
2178
2192
2179 def tags(ui, repo):
2193 def tags(ui, repo):
2180 """list repository tags
2194 """list repository tags
2181
2195
2182 List the repository tags.
2196 List the repository tags.
2183
2197
2184 This lists both regular and local tags.
2198 This lists both regular and local tags.
2185 """
2199 """
2186
2200
2187 l = repo.tagslist()
2201 l = repo.tagslist()
2188 l.reverse()
2202 l.reverse()
2189 for t, n in l:
2203 for t, n in l:
2190 try:
2204 try:
2191 r = "%5d:%s" % (repo.changelog.rev(n), hex(n))
2205 r = "%5d:%s" % (repo.changelog.rev(n), hex(n))
2192 except KeyError:
2206 except KeyError:
2193 r = " ?:?"
2207 r = " ?:?"
2194 ui.write("%-30s %s\n" % (t, r))
2208 ui.write("%-30s %s\n" % (t, r))
2195
2209
2196 def tip(ui, repo, **opts):
2210 def tip(ui, repo, **opts):
2197 """show the tip revision
2211 """show the tip revision
2198
2212
2199 Show the tip revision.
2213 Show the tip revision.
2200 """
2214 """
2201 n = repo.changelog.tip()
2215 n = repo.changelog.tip()
2202 show_changeset(ui, repo, changenode=n)
2216 show_changeset(ui, repo, changenode=n)
2203 if opts['patch']:
2217 if opts['patch']:
2204 dodiff(ui, ui, repo, repo.changelog.parents(n)[0], n)
2218 dodiff(ui, ui, repo, repo.changelog.parents(n)[0], n)
2205
2219
2206 def unbundle(ui, repo, fname, **opts):
2220 def unbundle(ui, repo, fname, **opts):
2207 """apply a changegroup file
2221 """apply a changegroup file
2208
2222
2209 Apply a compressed changegroup file generated by the bundle
2223 Apply a compressed changegroup file generated by the bundle
2210 command.
2224 command.
2211 """
2225 """
2212 f = urllib.urlopen(fname)
2226 f = urllib.urlopen(fname)
2213
2227
2214 if f.read(4) != "HG10":
2228 if f.read(4) != "HG10":
2215 raise util.Abort(_("%s: not a Mercurial bundle file") % fname)
2229 raise util.Abort(_("%s: not a Mercurial bundle file") % fname)
2216
2230
2217 def bzgenerator(f):
2231 def bzgenerator(f):
2218 zd = bz2.BZ2Decompressor()
2232 zd = bz2.BZ2Decompressor()
2219 for chunk in f:
2233 for chunk in f:
2220 yield zd.decompress(chunk)
2234 yield zd.decompress(chunk)
2221
2235
2222 bzgen = bzgenerator(util.filechunkiter(f, 4096))
2236 bzgen = bzgenerator(util.filechunkiter(f, 4096))
2223 if repo.addchangegroup(util.chunkbuffer(bzgen)):
2237 if repo.addchangegroup(util.chunkbuffer(bzgen)):
2224 return 1
2238 return 1
2225
2239
2226 if opts['update']:
2240 if opts['update']:
2227 return update(ui, repo)
2241 return update(ui, repo)
2228 else:
2242 else:
2229 ui.status(_("(run 'hg update' to get a working copy)\n"))
2243 ui.status(_("(run 'hg update' to get a working copy)\n"))
2230
2244
2231 def undo(ui, repo):
2245 def undo(ui, repo):
2232 """undo the last commit or pull
2246 """undo the last commit or pull
2233
2247
2234 Roll back the last pull or commit transaction on the
2248 Roll back the last pull or commit transaction on the
2235 repository, restoring the project to its earlier state.
2249 repository, restoring the project to its earlier state.
2236
2250
2237 This command should be used with care. There is only one level of
2251 This command should be used with care. There is only one level of
2238 undo and there is no redo.
2252 undo and there is no redo.
2239
2253
2240 This command is not intended for use on public repositories. Once
2254 This command is not intended for use on public repositories. Once
2241 a change is visible for pull by other users, undoing it locally is
2255 a change is visible for pull by other users, undoing it locally is
2242 ineffective.
2256 ineffective.
2243 """
2257 """
2244 repo.undo()
2258 repo.undo()
2245
2259
2246 def update(ui, repo, node=None, merge=False, clean=False, force=None,
2260 def update(ui, repo, node=None, merge=False, clean=False, force=None,
2247 branch=None):
2261 branch=None):
2248 """update or merge working directory
2262 """update or merge working directory
2249
2263
2250 Update the working directory to the specified revision.
2264 Update the working directory to the specified revision.
2251
2265
2252 If there are no outstanding changes in the working directory and
2266 If there are no outstanding changes in the working directory and
2253 there is a linear relationship between the current version and the
2267 there is a linear relationship between the current version and the
2254 requested version, the result is the requested version.
2268 requested version, the result is the requested version.
2255
2269
2256 Otherwise the result is a merge between the contents of the
2270 Otherwise the result is a merge between the contents of the
2257 current working directory and the requested version. Files that
2271 current working directory and the requested version. Files that
2258 changed between either parent are marked as changed for the next
2272 changed between either parent are marked as changed for the next
2259 commit and a commit must be performed before any further updates
2273 commit and a commit must be performed before any further updates
2260 are allowed.
2274 are allowed.
2261
2275
2262 By default, update will refuse to run if doing so would require
2276 By default, update will refuse to run if doing so would require
2263 merging or discarding local changes.
2277 merging or discarding local changes.
2264 """
2278 """
2265 if branch:
2279 if branch:
2266 br = repo.branchlookup(branch=branch)
2280 br = repo.branchlookup(branch=branch)
2267 found = []
2281 found = []
2268 for x in br:
2282 for x in br:
2269 if branch in br[x]:
2283 if branch in br[x]:
2270 found.append(x)
2284 found.append(x)
2271 if len(found) > 1:
2285 if len(found) > 1:
2272 ui.warn(_("Found multiple heads for %s\n") % branch)
2286 ui.warn(_("Found multiple heads for %s\n") % branch)
2273 for x in found:
2287 for x in found:
2274 show_changeset(ui, repo, changenode=x, brinfo=br)
2288 show_changeset(ui, repo, changenode=x, brinfo=br)
2275 return 1
2289 return 1
2276 if len(found) == 1:
2290 if len(found) == 1:
2277 node = found[0]
2291 node = found[0]
2278 ui.warn(_("Using head %s for branch %s\n") % (short(node), branch))
2292 ui.warn(_("Using head %s for branch %s\n") % (short(node), branch))
2279 else:
2293 else:
2280 ui.warn(_("branch %s not found\n") % (branch))
2294 ui.warn(_("branch %s not found\n") % (branch))
2281 return 1
2295 return 1
2282 else:
2296 else:
2283 node = node and repo.lookup(node) or repo.changelog.tip()
2297 node = node and repo.lookup(node) or repo.changelog.tip()
2284 return repo.update(node, allow=merge, force=clean, forcemerge=force)
2298 return repo.update(node, allow=merge, force=clean, forcemerge=force)
2285
2299
2286 def verify(ui, repo):
2300 def verify(ui, repo):
2287 """verify the integrity of the repository
2301 """verify the integrity of the repository
2288
2302
2289 Verify the integrity of the current repository.
2303 Verify the integrity of the current repository.
2290
2304
2291 This will perform an extensive check of the repository's
2305 This will perform an extensive check of the repository's
2292 integrity, validating the hashes and checksums of each entry in
2306 integrity, validating the hashes and checksums of each entry in
2293 the changelog, manifest, and tracked files, as well as the
2307 the changelog, manifest, and tracked files, as well as the
2294 integrity of their crosslinks and indices.
2308 integrity of their crosslinks and indices.
2295 """
2309 """
2296 return repo.verify()
2310 return repo.verify()
2297
2311
2298 # Command options and aliases are listed here, alphabetically
2312 # Command options and aliases are listed here, alphabetically
2299
2313
2300 table = {
2314 table = {
2301 "^add":
2315 "^add":
2302 (add,
2316 (add,
2303 [('I', 'include', [], _('include names matching the given patterns')),
2317 [('I', 'include', [], _('include names matching the given patterns')),
2304 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2318 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2305 _('hg add [OPTION]... [FILE]...')),
2319 _('hg add [OPTION]... [FILE]...')),
2306 "addremove":
2320 "addremove":
2307 (addremove,
2321 (addremove,
2308 [('I', 'include', [], _('include names matching the given patterns')),
2322 [('I', 'include', [], _('include names matching the given patterns')),
2309 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2323 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2310 _('hg addremove [OPTION]... [FILE]...')),
2324 _('hg addremove [OPTION]... [FILE]...')),
2311 "^annotate":
2325 "^annotate":
2312 (annotate,
2326 (annotate,
2313 [('r', 'rev', '', _('annotate the specified revision')),
2327 [('r', 'rev', '', _('annotate the specified revision')),
2314 ('a', 'text', None, _('treat all files as text')),
2328 ('a', 'text', None, _('treat all files as text')),
2315 ('u', 'user', None, _('list the author')),
2329 ('u', 'user', None, _('list the author')),
2316 ('d', 'date', None, _('list the date')),
2330 ('d', 'date', None, _('list the date')),
2317 ('n', 'number', None, _('list the revision number (default)')),
2331 ('n', 'number', None, _('list the revision number (default)')),
2318 ('c', 'changeset', None, _('list the changeset')),
2332 ('c', 'changeset', None, _('list the changeset')),
2319 ('I', 'include', [], _('include names matching the given patterns')),
2333 ('I', 'include', [], _('include names matching the given patterns')),
2320 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2334 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2321 _('hg annotate [OPTION]... FILE...')),
2335 _('hg annotate [OPTION]... FILE...')),
2322 "bundle":
2336 "bundle":
2323 (bundle,
2337 (bundle,
2324 [],
2338 [],
2325 _('hg bundle FILE DEST')),
2339 _('hg bundle FILE DEST')),
2326 "cat":
2340 "cat":
2327 (cat,
2341 (cat,
2328 [('I', 'include', [], _('include names matching the given patterns')),
2342 [('I', 'include', [], _('include names matching the given patterns')),
2329 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2343 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2330 ('o', 'output', '', _('print output to file with formatted name')),
2344 ('o', 'output', '', _('print output to file with formatted name')),
2331 ('r', 'rev', '', _('print the given revision'))],
2345 ('r', 'rev', '', _('print the given revision'))],
2332 _('hg cat [OPTION]... FILE...')),
2346 _('hg cat [OPTION]... FILE...')),
2333 "^clone":
2347 "^clone":
2334 (clone,
2348 (clone,
2335 [('U', 'noupdate', None, _('do not update the new working directory')),
2349 [('U', 'noupdate', None, _('do not update the new working directory')),
2336 ('e', 'ssh', '', _('specify ssh command to use')),
2350 ('e', 'ssh', '', _('specify ssh command to use')),
2337 ('', 'pull', None, _('use pull protocol to copy metadata')),
2351 ('', 'pull', None, _('use pull protocol to copy metadata')),
2338 ('r', 'rev', [],
2352 ('r', 'rev', [],
2339 _('a changeset you would like to have after cloning')),
2353 _('a changeset you would like to have after cloning')),
2340 ('', 'remotecmd', '',
2354 ('', 'remotecmd', '',
2341 _('specify hg command to run on the remote side'))],
2355 _('specify hg command to run on the remote side'))],
2342 _('hg clone [OPTION]... SOURCE [DEST]')),
2356 _('hg clone [OPTION]... SOURCE [DEST]')),
2343 "^commit|ci":
2357 "^commit|ci":
2344 (commit,
2358 (commit,
2345 [('A', 'addremove', None, _('run addremove during commit')),
2359 [('A', 'addremove', None, _('run addremove during commit')),
2346 ('I', 'include', [], _('include names matching the given patterns')),
2360 ('I', 'include', [], _('include names matching the given patterns')),
2347 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2361 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2348 ('m', 'message', '', _('use <text> as commit message')),
2362 ('m', 'message', '', _('use <text> as commit message')),
2349 ('l', 'logfile', '', _('read the commit message from <file>')),
2363 ('l', 'logfile', '', _('read the commit message from <file>')),
2350 ('d', 'date', '', _('record datecode as commit date')),
2364 ('d', 'date', '', _('record datecode as commit date')),
2351 ('u', 'user', '', _('record user as commiter'))],
2365 ('u', 'user', '', _('record user as commiter'))],
2352 _('hg commit [OPTION]... [FILE]...')),
2366 _('hg commit [OPTION]... [FILE]...')),
2353 "copy|cp":
2367 "copy|cp":
2354 (copy,
2368 (copy,
2355 [('I', 'include', [], _('include names matching the given patterns')),
2369 [('I', 'include', [], _('include names matching the given patterns')),
2356 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2370 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2357 ('A', 'after', None, _('record a copy that has already occurred')),
2371 ('A', 'after', None, _('record a copy that has already occurred')),
2358 ('f', 'force', None,
2372 ('f', 'force', None,
2359 _('forcibly copy over an existing managed file'))],
2373 _('forcibly copy over an existing managed file'))],
2360 _('hg copy [OPTION]... [SOURCE]... DEST')),
2374 _('hg copy [OPTION]... [SOURCE]... DEST')),
2361 "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
2375 "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
2362 "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')),
2376 "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')),
2363 "debugconfig": (debugconfig, [], _('debugconfig')),
2377 "debugconfig": (debugconfig, [], _('debugconfig')),
2364 "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')),
2378 "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')),
2365 "debugstate": (debugstate, [], _('debugstate')),
2379 "debugstate": (debugstate, [], _('debugstate')),
2366 "debugdata": (debugdata, [], _('debugdata FILE REV')),
2380 "debugdata": (debugdata, [], _('debugdata FILE REV')),
2367 "debugindex": (debugindex, [], _('debugindex FILE')),
2381 "debugindex": (debugindex, [], _('debugindex FILE')),
2368 "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')),
2382 "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')),
2369 "debugrename": (debugrename, [], _('debugrename FILE [REV]')),
2383 "debugrename": (debugrename, [], _('debugrename FILE [REV]')),
2370 "debugwalk":
2384 "debugwalk":
2371 (debugwalk,
2385 (debugwalk,
2372 [('I', 'include', [], _('include names matching the given patterns')),
2386 [('I', 'include', [], _('include names matching the given patterns')),
2373 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2387 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2374 _('debugwalk [OPTION]... [FILE]...')),
2388 _('debugwalk [OPTION]... [FILE]...')),
2375 "^diff":
2389 "^diff":
2376 (diff,
2390 (diff,
2377 [('r', 'rev', [], _('revision')),
2391 [('r', 'rev', [], _('revision')),
2378 ('a', 'text', None, _('treat all files as text')),
2392 ('a', 'text', None, _('treat all files as text')),
2379 ('I', 'include', [], _('include names matching the given patterns')),
2393 ('I', 'include', [], _('include names matching the given patterns')),
2380 ('p', 'show-function', None,
2394 ('p', 'show-function', None,
2381 _('show which function each change is in')),
2395 _('show which function each change is in')),
2382 ('w', 'ignore-all-space', None,
2396 ('w', 'ignore-all-space', None,
2383 _('ignore white space when comparing lines')),
2397 _('ignore white space when comparing lines')),
2384 ('X', 'exclude', [],
2398 ('X', 'exclude', [],
2385 _('exclude names matching the given patterns'))],
2399 _('exclude names matching the given patterns'))],
2386 _('hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...')),
2400 _('hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...')),
2387 "^export":
2401 "^export":
2388 (export,
2402 (export,
2389 [('o', 'output', '', _('print output to file with formatted name')),
2403 [('o', 'output', '', _('print output to file with formatted name')),
2390 ('a', 'text', None, _('treat all files as text')),
2404 ('a', 'text', None, _('treat all files as text')),
2391 ('', 'switch-parent', None, _('diff against the second parent'))],
2405 ('', 'switch-parent', None, _('diff against the second parent'))],
2392 _('hg export [-a] [-o OUTFILE] REV...')),
2406 _('hg export [-a] [-o OUTFILE] REV...')),
2393 "forget":
2407 "forget":
2394 (forget,
2408 (forget,
2395 [('I', 'include', [], _('include names matching the given patterns')),
2409 [('I', 'include', [], _('include names matching the given patterns')),
2396 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2410 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2397 _('hg forget [OPTION]... FILE...')),
2411 _('hg forget [OPTION]... FILE...')),
2398 "grep":
2412 "grep":
2399 (grep,
2413 (grep,
2400 [('0', 'print0', None, _('end fields with NUL')),
2414 [('0', 'print0', None, _('end fields with NUL')),
2401 ('I', 'include', [], _('include names matching the given patterns')),
2415 ('I', 'include', [], _('include names matching the given patterns')),
2402 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2416 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2403 ('', 'all', None, _('print all revisions that match')),
2417 ('', 'all', None, _('print all revisions that match')),
2404 ('i', 'ignore-case', None, _('ignore case when matching')),
2418 ('i', 'ignore-case', None, _('ignore case when matching')),
2405 ('l', 'files-with-matches', None,
2419 ('l', 'files-with-matches', None,
2406 _('print only filenames and revs that match')),
2420 _('print only filenames and revs that match')),
2407 ('n', 'line-number', None, _('print matching line numbers')),
2421 ('n', 'line-number', None, _('print matching line numbers')),
2408 ('r', 'rev', [], _('search in given revision range')),
2422 ('r', 'rev', [], _('search in given revision range')),
2409 ('u', 'user', None, _('print user who committed change'))],
2423 ('u', 'user', None, _('print user who committed change'))],
2410 _('hg grep [OPTION]... PATTERN [FILE]...')),
2424 _('hg grep [OPTION]... PATTERN [FILE]...')),
2411 "heads":
2425 "heads":
2412 (heads,
2426 (heads,
2413 [('b', 'branches', None, _('find branch info')),
2427 [('b', 'branches', None, _('find branch info')),
2414 ('r', 'rev', '', _('show only heads which are descendants of rev'))],
2428 ('r', 'rev', '', _('show only heads which are descendants of rev'))],
2415 _('hg heads [-b] [-r <rev>]')),
2429 _('hg heads [-b] [-r <rev>]')),
2416 "help": (help_, [], _('hg help [COMMAND]')),
2430 "help": (help_, [], _('hg help [COMMAND]')),
2417 "identify|id": (identify, [], _('hg identify')),
2431 "identify|id": (identify, [], _('hg identify')),
2418 "import|patch":
2432 "import|patch":
2419 (import_,
2433 (import_,
2420 [('p', 'strip', 1,
2434 [('p', 'strip', 1,
2421 _('directory strip option for patch. This has the same\n') +
2435 _('directory strip option for patch. This has the same\n') +
2422 _('meaning as the corresponding patch option')),
2436 _('meaning as the corresponding patch option')),
2423 ('f', 'force', None,
2437 ('f', 'force', None,
2424 _('skip check for outstanding uncommitted changes')),
2438 _('skip check for outstanding uncommitted changes')),
2425 ('b', 'base', '', _('base path'))],
2439 ('b', 'base', '', _('base path'))],
2426 _('hg import [-f] [-p NUM] [-b BASE] PATCH...')),
2440 _('hg import [-f] [-p NUM] [-b BASE] PATCH...')),
2427 "incoming|in": (incoming,
2441 "incoming|in": (incoming,
2428 [('M', 'no-merges', None, _('do not show merges')),
2442 [('M', 'no-merges', None, _('do not show merges')),
2429 ('p', 'patch', None, _('show patch')),
2443 ('p', 'patch', None, _('show patch')),
2430 ('n', 'newest-first', None, _('show newest record first'))],
2444 ('n', 'newest-first', None, _('show newest record first'))],
2431 _('hg incoming [-p] [-n] [-M] [SOURCE]')),
2445 _('hg incoming [-p] [-n] [-M] [SOURCE]')),
2432 "^init": (init, [], _('hg init [DEST]')),
2446 "^init": (init, [], _('hg init [DEST]')),
2433 "locate":
2447 "locate":
2434 (locate,
2448 (locate,
2435 [('r', 'rev', '', _('search the repository as it stood at rev')),
2449 [('r', 'rev', '', _('search the repository as it stood at rev')),
2436 ('0', 'print0', None,
2450 ('0', 'print0', None,
2437 _('end filenames with NUL, for use with xargs')),
2451 _('end filenames with NUL, for use with xargs')),
2438 ('f', 'fullpath', None,
2452 ('f', 'fullpath', None,
2439 _('print complete paths from the filesystem root')),
2453 _('print complete paths from the filesystem root')),
2440 ('I', 'include', [], _('include names matching the given patterns')),
2454 ('I', 'include', [], _('include names matching the given patterns')),
2441 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2455 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2442 _('hg locate [OPTION]... [PATTERN]...')),
2456 _('hg locate [OPTION]... [PATTERN]...')),
2443 "^log|history":
2457 "^log|history":
2444 (log,
2458 (log,
2445 [('I', 'include', [], _('include names matching the given patterns')),
2459 [('I', 'include', [], _('include names matching the given patterns')),
2446 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2460 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2447 ('b', 'branch', None, _('show branches')),
2461 ('b', 'branch', None, _('show branches')),
2448 ('k', 'keyword', [], _('search for a keyword')),
2462 ('k', 'keyword', [], _('search for a keyword')),
2463 ('l', 'limit', '', _('limit number of changes displayed')),
2449 ('r', 'rev', [], _('show the specified revision or range')),
2464 ('r', 'rev', [], _('show the specified revision or range')),
2450 ('M', 'no-merges', None, _('do not show merges')),
2465 ('M', 'no-merges', None, _('do not show merges')),
2451 ('m', 'only-merges', None, _('show only merges')),
2466 ('m', 'only-merges', None, _('show only merges')),
2452 ('p', 'patch', None, _('show patch'))],
2467 ('p', 'patch', None, _('show patch'))],
2453 _('hg log [-I] [-X] [-r REV]... [-p] [FILE]')),
2468 _('hg log [-I] [-X] [-r REV]... [-p] [FILE]')),
2454 "manifest": (manifest, [], _('hg manifest [REV]')),
2469 "manifest": (manifest, [], _('hg manifest [REV]')),
2455 "outgoing|out": (outgoing,
2470 "outgoing|out": (outgoing,
2456 [('M', 'no-merges', None, _('do not show merges')),
2471 [('M', 'no-merges', None, _('do not show merges')),
2457 ('p', 'patch', None, _('show patch')),
2472 ('p', 'patch', None, _('show patch')),
2458 ('n', 'newest-first', None, _('show newest record first'))],
2473 ('n', 'newest-first', None, _('show newest record first'))],
2459 _('hg outgoing [-p] [-n] [-M] [DEST]')),
2474 _('hg outgoing [-p] [-n] [-M] [DEST]')),
2460 "^parents":
2475 "^parents":
2461 (parents,
2476 (parents,
2462 [('b', 'branch', None, _('show branches'))],
2477 [('b', 'branch', None, _('show branches'))],
2463 _('hg parents [-b] [REV]')),
2478 _('hg parents [-b] [REV]')),
2464 "paths": (paths, [], _('hg paths [NAME]')),
2479 "paths": (paths, [], _('hg paths [NAME]')),
2465 "^pull":
2480 "^pull":
2466 (pull,
2481 (pull,
2467 [('u', 'update', None,
2482 [('u', 'update', None,
2468 _('update the working directory to tip after pull')),
2483 _('update the working directory to tip after pull')),
2469 ('e', 'ssh', '', _('specify ssh command to use')),
2484 ('e', 'ssh', '', _('specify ssh command to use')),
2470 ('r', 'rev', [], _('a specific revision you would like to pull')),
2485 ('r', 'rev', [], _('a specific revision you would like to pull')),
2471 ('', 'remotecmd', '',
2486 ('', 'remotecmd', '',
2472 _('specify hg command to run on the remote side'))],
2487 _('specify hg command to run on the remote side'))],
2473 _('hg pull [-u] [-e FILE] [-r rev] [--remotecmd FILE] [SOURCE]')),
2488 _('hg pull [-u] [-e FILE] [-r rev] [--remotecmd FILE] [SOURCE]')),
2474 "^push":
2489 "^push":
2475 (push,
2490 (push,
2476 [('f', 'force', None, _('force push')),
2491 [('f', 'force', None, _('force push')),
2477 ('e', 'ssh', '', _('specify ssh command to use')),
2492 ('e', 'ssh', '', _('specify ssh command to use')),
2478 ('', 'remotecmd', '',
2493 ('', 'remotecmd', '',
2479 _('specify hg command to run on the remote side'))],
2494 _('specify hg command to run on the remote side'))],
2480 _('hg push [-f] [-e FILE] [--remotecmd FILE] [DEST]')),
2495 _('hg push [-f] [-e FILE] [--remotecmd FILE] [DEST]')),
2481 "rawcommit":
2496 "rawcommit":
2482 (rawcommit,
2497 (rawcommit,
2483 [('p', 'parent', [], _('parent')),
2498 [('p', 'parent', [], _('parent')),
2484 ('d', 'date', '', _('date code')),
2499 ('d', 'date', '', _('date code')),
2485 ('u', 'user', '', _('user')),
2500 ('u', 'user', '', _('user')),
2486 ('F', 'files', '', _('file list')),
2501 ('F', 'files', '', _('file list')),
2487 ('m', 'message', '', _('commit message')),
2502 ('m', 'message', '', _('commit message')),
2488 ('l', 'logfile', '', _('commit message file'))],
2503 ('l', 'logfile', '', _('commit message file'))],
2489 _('hg rawcommit [OPTION]... [FILE]...')),
2504 _('hg rawcommit [OPTION]... [FILE]...')),
2490 "recover": (recover, [], _('hg recover')),
2505 "recover": (recover, [], _('hg recover')),
2491 "^remove|rm":
2506 "^remove|rm":
2492 (remove,
2507 (remove,
2493 [('I', 'include', [], _('include names matching the given patterns')),
2508 [('I', 'include', [], _('include names matching the given patterns')),
2494 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2509 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2495 _('hg remove [OPTION]... FILE...')),
2510 _('hg remove [OPTION]... FILE...')),
2496 "rename|mv":
2511 "rename|mv":
2497 (rename,
2512 (rename,
2498 [('I', 'include', [], _('include names matching the given patterns')),
2513 [('I', 'include', [], _('include names matching the given patterns')),
2499 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2514 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2500 ('A', 'after', None, _('record a rename that has already occurred')),
2515 ('A', 'after', None, _('record a rename that has already occurred')),
2501 ('f', 'force', None,
2516 ('f', 'force', None,
2502 _('forcibly copy over an existing managed file'))],
2517 _('forcibly copy over an existing managed file'))],
2503 _('hg rename [OPTION]... [SOURCE]... DEST')),
2518 _('hg rename [OPTION]... [SOURCE]... DEST')),
2504 "^revert":
2519 "^revert":
2505 (revert,
2520 (revert,
2506 [('I', 'include', [], _('include names matching the given patterns')),
2521 [('I', 'include', [], _('include names matching the given patterns')),
2507 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2522 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2508 ('r', 'rev', '', _('revision to revert to'))],
2523 ('r', 'rev', '', _('revision to revert to'))],
2509 _('hg revert [-n] [-r REV] [NAME]...')),
2524 _('hg revert [-n] [-r REV] [NAME]...')),
2510 "root": (root, [], _('hg root')),
2525 "root": (root, [], _('hg root')),
2511 "^serve":
2526 "^serve":
2512 (serve,
2527 (serve,
2513 [('A', 'accesslog', '', _('name of access log file to write to')),
2528 [('A', 'accesslog', '', _('name of access log file to write to')),
2514 ('d', 'daemon', None, _('run server in background')),
2529 ('d', 'daemon', None, _('run server in background')),
2515 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
2530 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
2516 ('E', 'errorlog', '', _('name of error log file to write to')),
2531 ('E', 'errorlog', '', _('name of error log file to write to')),
2517 ('p', 'port', 0, _('port to use (default: 8000)')),
2532 ('p', 'port', 0, _('port to use (default: 8000)')),
2518 ('a', 'address', '', _('address to use')),
2533 ('a', 'address', '', _('address to use')),
2519 ('n', 'name', '',
2534 ('n', 'name', '',
2520 _('name to show in web pages (default: working dir)')),
2535 _('name to show in web pages (default: working dir)')),
2521 ('', 'pid-file', '', _('name of file to write process ID to')),
2536 ('', 'pid-file', '', _('name of file to write process ID to')),
2522 ('', 'stdio', None, _('for remote clients')),
2537 ('', 'stdio', None, _('for remote clients')),
2523 ('t', 'templates', '', _('web templates to use')),
2538 ('t', 'templates', '', _('web templates to use')),
2524 ('', 'style', '', _('template style to use')),
2539 ('', 'style', '', _('template style to use')),
2525 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4'))],
2540 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4'))],
2526 _('hg serve [OPTION]...')),
2541 _('hg serve [OPTION]...')),
2527 "^status|st":
2542 "^status|st":
2528 (status,
2543 (status,
2529 [('m', 'modified', None, _('show only modified files')),
2544 [('m', 'modified', None, _('show only modified files')),
2530 ('a', 'added', None, _('show only added files')),
2545 ('a', 'added', None, _('show only added files')),
2531 ('r', 'removed', None, _('show only removed files')),
2546 ('r', 'removed', None, _('show only removed files')),
2532 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
2547 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
2533 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
2548 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
2534 ('n', 'no-status', None, _('hide status prefix')),
2549 ('n', 'no-status', None, _('hide status prefix')),
2535 ('0', 'print0', None,
2550 ('0', 'print0', None,
2536 _('end filenames with NUL, for use with xargs')),
2551 _('end filenames with NUL, for use with xargs')),
2537 ('I', 'include', [], _('include names matching the given patterns')),
2552 ('I', 'include', [], _('include names matching the given patterns')),
2538 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2553 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2539 _('hg status [OPTION]... [FILE]...')),
2554 _('hg status [OPTION]... [FILE]...')),
2540 "tag":
2555 "tag":
2541 (tag,
2556 (tag,
2542 [('l', 'local', None, _('make the tag local')),
2557 [('l', 'local', None, _('make the tag local')),
2543 ('m', 'message', '', _('message for tag commit log entry')),
2558 ('m', 'message', '', _('message for tag commit log entry')),
2544 ('d', 'date', '', _('record datecode as commit date')),
2559 ('d', 'date', '', _('record datecode as commit date')),
2545 ('u', 'user', '', _('record user as commiter')),
2560 ('u', 'user', '', _('record user as commiter')),
2546 ('r', 'rev', '', _('revision to tag'))],
2561 ('r', 'rev', '', _('revision to tag'))],
2547 _('hg tag [-r REV] [OPTION]... NAME')),
2562 _('hg tag [-r REV] [OPTION]... NAME')),
2548 "tags": (tags, [], _('hg tags')),
2563 "tags": (tags, [], _('hg tags')),
2549 "tip": (tip, [('p', 'patch', None, _('show patch'))], _('hg tip')),
2564 "tip": (tip, [('p', 'patch', None, _('show patch'))], _('hg tip')),
2550 "unbundle":
2565 "unbundle":
2551 (unbundle,
2566 (unbundle,
2552 [('u', 'update', None,
2567 [('u', 'update', None,
2553 _('update the working directory to tip after unbundle'))],
2568 _('update the working directory to tip after unbundle'))],
2554 _('hg unbundle [-u] FILE')),
2569 _('hg unbundle [-u] FILE')),
2555 "undo": (undo, [], _('hg undo')),
2570 "undo": (undo, [], _('hg undo')),
2556 "^update|up|checkout|co":
2571 "^update|up|checkout|co":
2557 (update,
2572 (update,
2558 [('b', 'branch', '', _('checkout the head of a specific branch')),
2573 [('b', 'branch', '', _('checkout the head of a specific branch')),
2559 ('m', 'merge', None, _('allow merging of branches')),
2574 ('m', 'merge', None, _('allow merging of branches')),
2560 ('C', 'clean', None, _('overwrite locally modified files')),
2575 ('C', 'clean', None, _('overwrite locally modified files')),
2561 ('f', 'force', None, _('force a merge with outstanding changes'))],
2576 ('f', 'force', None, _('force a merge with outstanding changes'))],
2562 _('hg update [-b TAG] [-m] [-C] [-f] [REV]')),
2577 _('hg update [-b TAG] [-m] [-C] [-f] [REV]')),
2563 "verify": (verify, [], _('hg verify')),
2578 "verify": (verify, [], _('hg verify')),
2564 "version": (show_version, [], _('hg version')),
2579 "version": (show_version, [], _('hg version')),
2565 }
2580 }
2566
2581
2567 globalopts = [
2582 globalopts = [
2568 ('R', 'repository', '', _('repository root directory')),
2583 ('R', 'repository', '', _('repository root directory')),
2569 ('', 'cwd', '', _('change working directory')),
2584 ('', 'cwd', '', _('change working directory')),
2570 ('y', 'noninteractive', None,
2585 ('y', 'noninteractive', None,
2571 _('do not prompt, assume \'yes\' for any required answers')),
2586 _('do not prompt, assume \'yes\' for any required answers')),
2572 ('q', 'quiet', None, _('suppress output')),
2587 ('q', 'quiet', None, _('suppress output')),
2573 ('v', 'verbose', None, _('enable additional output')),
2588 ('v', 'verbose', None, _('enable additional output')),
2574 ('', 'debug', None, _('enable debugging output')),
2589 ('', 'debug', None, _('enable debugging output')),
2575 ('', 'debugger', None, _('start debugger')),
2590 ('', 'debugger', None, _('start debugger')),
2576 ('', 'traceback', None, _('print traceback on exception')),
2591 ('', 'traceback', None, _('print traceback on exception')),
2577 ('', 'time', None, _('time how long the command takes')),
2592 ('', 'time', None, _('time how long the command takes')),
2578 ('', 'profile', None, _('print command execution profile')),
2593 ('', 'profile', None, _('print command execution profile')),
2579 ('', 'version', None, _('output version information and exit')),
2594 ('', 'version', None, _('output version information and exit')),
2580 ('h', 'help', None, _('display help and exit')),
2595 ('h', 'help', None, _('display help and exit')),
2581 ]
2596 ]
2582
2597
2583 norepo = ("clone init version help debugancestor debugconfig debugdata"
2598 norepo = ("clone init version help debugancestor debugconfig debugdata"
2584 " debugindex debugindexdot paths")
2599 " debugindex debugindexdot paths")
2585
2600
2586 def find(cmd):
2601 def find(cmd):
2587 """Return (aliases, command table entry) for command string."""
2602 """Return (aliases, command table entry) for command string."""
2588 choice = None
2603 choice = None
2589 count = 0
2604 count = 0
2590 for e in table.keys():
2605 for e in table.keys():
2591 aliases = e.lstrip("^").split("|")
2606 aliases = e.lstrip("^").split("|")
2592 if cmd in aliases:
2607 if cmd in aliases:
2593 return aliases, table[e]
2608 return aliases, table[e]
2594 for a in aliases:
2609 for a in aliases:
2595 if a.startswith(cmd):
2610 if a.startswith(cmd):
2596 count += 1
2611 count += 1
2597 choice = aliases, table[e]
2612 choice = aliases, table[e]
2598 break
2613 break
2599
2614
2600 if count > 1:
2615 if count > 1:
2601 raise AmbiguousCommand(cmd)
2616 raise AmbiguousCommand(cmd)
2602
2617
2603 if choice:
2618 if choice:
2604 return choice
2619 return choice
2605
2620
2606 raise UnknownCommand(cmd)
2621 raise UnknownCommand(cmd)
2607
2622
2608 class SignalInterrupt(Exception):
2623 class SignalInterrupt(Exception):
2609 """Exception raised on SIGTERM and SIGHUP."""
2624 """Exception raised on SIGTERM and SIGHUP."""
2610
2625
2611 def catchterm(*args):
2626 def catchterm(*args):
2612 raise SignalInterrupt
2627 raise SignalInterrupt
2613
2628
2614 def run():
2629 def run():
2615 sys.exit(dispatch(sys.argv[1:]))
2630 sys.exit(dispatch(sys.argv[1:]))
2616
2631
2617 class ParseError(Exception):
2632 class ParseError(Exception):
2618 """Exception raised on errors in parsing the command line."""
2633 """Exception raised on errors in parsing the command line."""
2619
2634
2620 def parse(ui, args):
2635 def parse(ui, args):
2621 options = {}
2636 options = {}
2622 cmdoptions = {}
2637 cmdoptions = {}
2623
2638
2624 try:
2639 try:
2625 args = fancyopts.fancyopts(args, globalopts, options)
2640 args = fancyopts.fancyopts(args, globalopts, options)
2626 except fancyopts.getopt.GetoptError, inst:
2641 except fancyopts.getopt.GetoptError, inst:
2627 raise ParseError(None, inst)
2642 raise ParseError(None, inst)
2628
2643
2629 if args:
2644 if args:
2630 cmd, args = args[0], args[1:]
2645 cmd, args = args[0], args[1:]
2631 aliases, i = find(cmd)
2646 aliases, i = find(cmd)
2632 cmd = aliases[0]
2647 cmd = aliases[0]
2633 defaults = ui.config("defaults", cmd)
2648 defaults = ui.config("defaults", cmd)
2634 if defaults:
2649 if defaults:
2635 args = defaults.split() + args
2650 args = defaults.split() + args
2636 c = list(i[1])
2651 c = list(i[1])
2637 else:
2652 else:
2638 cmd = None
2653 cmd = None
2639 c = []
2654 c = []
2640
2655
2641 # combine global options into local
2656 # combine global options into local
2642 for o in globalopts:
2657 for o in globalopts:
2643 c.append((o[0], o[1], options[o[1]], o[3]))
2658 c.append((o[0], o[1], options[o[1]], o[3]))
2644
2659
2645 try:
2660 try:
2646 args = fancyopts.fancyopts(args, c, cmdoptions)
2661 args = fancyopts.fancyopts(args, c, cmdoptions)
2647 except fancyopts.getopt.GetoptError, inst:
2662 except fancyopts.getopt.GetoptError, inst:
2648 raise ParseError(cmd, inst)
2663 raise ParseError(cmd, inst)
2649
2664
2650 # separate global options back out
2665 # separate global options back out
2651 for o in globalopts:
2666 for o in globalopts:
2652 n = o[1]
2667 n = o[1]
2653 options[n] = cmdoptions[n]
2668 options[n] = cmdoptions[n]
2654 del cmdoptions[n]
2669 del cmdoptions[n]
2655
2670
2656 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
2671 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
2657
2672
2658 def dispatch(args):
2673 def dispatch(args):
2659 signal.signal(signal.SIGTERM, catchterm)
2674 signal.signal(signal.SIGTERM, catchterm)
2660 try:
2675 try:
2661 signal.signal(signal.SIGHUP, catchterm)
2676 signal.signal(signal.SIGHUP, catchterm)
2662 except AttributeError:
2677 except AttributeError:
2663 pass
2678 pass
2664
2679
2665 try:
2680 try:
2666 u = ui.ui()
2681 u = ui.ui()
2667 except util.Abort, inst:
2682 except util.Abort, inst:
2668 sys.stderr.write(_("abort: %s\n") % inst)
2683 sys.stderr.write(_("abort: %s\n") % inst)
2669 sys.exit(1)
2684 sys.exit(1)
2670
2685
2671 external = []
2686 external = []
2672 for x in u.extensions():
2687 for x in u.extensions():
2673 def on_exception(exc, inst):
2688 def on_exception(exc, inst):
2674 u.warn(_("*** failed to import extension %s\n") % x[1])
2689 u.warn(_("*** failed to import extension %s\n") % x[1])
2675 u.warn("%s\n" % inst)
2690 u.warn("%s\n" % inst)
2676 if "--traceback" in sys.argv[1:]:
2691 if "--traceback" in sys.argv[1:]:
2677 traceback.print_exc()
2692 traceback.print_exc()
2678 if x[1]:
2693 if x[1]:
2679 try:
2694 try:
2680 mod = imp.load_source(x[0], x[1])
2695 mod = imp.load_source(x[0], x[1])
2681 except Exception, inst:
2696 except Exception, inst:
2682 on_exception(Exception, inst)
2697 on_exception(Exception, inst)
2683 continue
2698 continue
2684 else:
2699 else:
2685 def importh(name):
2700 def importh(name):
2686 mod = __import__(name)
2701 mod = __import__(name)
2687 components = name.split('.')
2702 components = name.split('.')
2688 for comp in components[1:]:
2703 for comp in components[1:]:
2689 mod = getattr(mod, comp)
2704 mod = getattr(mod, comp)
2690 return mod
2705 return mod
2691 try:
2706 try:
2692 mod = importh(x[0])
2707 mod = importh(x[0])
2693 except Exception, inst:
2708 except Exception, inst:
2694 on_exception(Exception, inst)
2709 on_exception(Exception, inst)
2695 continue
2710 continue
2696
2711
2697 external.append(mod)
2712 external.append(mod)
2698 for x in external:
2713 for x in external:
2699 cmdtable = getattr(x, 'cmdtable', {})
2714 cmdtable = getattr(x, 'cmdtable', {})
2700 for t in cmdtable:
2715 for t in cmdtable:
2701 if t in table:
2716 if t in table:
2702 u.warn(_("module %s overrides %s\n") % (x.__name__, t))
2717 u.warn(_("module %s overrides %s\n") % (x.__name__, t))
2703 table.update(cmdtable)
2718 table.update(cmdtable)
2704
2719
2705 try:
2720 try:
2706 cmd, func, args, options, cmdoptions = parse(u, args)
2721 cmd, func, args, options, cmdoptions = parse(u, args)
2707 except ParseError, inst:
2722 except ParseError, inst:
2708 if inst.args[0]:
2723 if inst.args[0]:
2709 u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
2724 u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
2710 help_(u, inst.args[0])
2725 help_(u, inst.args[0])
2711 else:
2726 else:
2712 u.warn(_("hg: %s\n") % inst.args[1])
2727 u.warn(_("hg: %s\n") % inst.args[1])
2713 help_(u, 'shortlist')
2728 help_(u, 'shortlist')
2714 sys.exit(-1)
2729 sys.exit(-1)
2715 except AmbiguousCommand, inst:
2730 except AmbiguousCommand, inst:
2716 u.warn(_("hg: command '%s' is ambiguous.\n") % inst.args[0])
2731 u.warn(_("hg: command '%s' is ambiguous.\n") % inst.args[0])
2717 sys.exit(1)
2732 sys.exit(1)
2718 except UnknownCommand, inst:
2733 except UnknownCommand, inst:
2719 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2734 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2720 help_(u, 'shortlist')
2735 help_(u, 'shortlist')
2721 sys.exit(1)
2736 sys.exit(1)
2722
2737
2723 if options["time"]:
2738 if options["time"]:
2724 def get_times():
2739 def get_times():
2725 t = os.times()
2740 t = os.times()
2726 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
2741 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
2727 t = (t[0], t[1], t[2], t[3], time.clock())
2742 t = (t[0], t[1], t[2], t[3], time.clock())
2728 return t
2743 return t
2729 s = get_times()
2744 s = get_times()
2730 def print_time():
2745 def print_time():
2731 t = get_times()
2746 t = get_times()
2732 u.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
2747 u.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
2733 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
2748 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
2734 atexit.register(print_time)
2749 atexit.register(print_time)
2735
2750
2736 u.updateopts(options["verbose"], options["debug"], options["quiet"],
2751 u.updateopts(options["verbose"], options["debug"], options["quiet"],
2737 not options["noninteractive"])
2752 not options["noninteractive"])
2738
2753
2739 # enter the debugger before command execution
2754 # enter the debugger before command execution
2740 if options['debugger']:
2755 if options['debugger']:
2741 pdb.set_trace()
2756 pdb.set_trace()
2742
2757
2743 try:
2758 try:
2744 try:
2759 try:
2745 if options['help']:
2760 if options['help']:
2746 help_(u, cmd, options['version'])
2761 help_(u, cmd, options['version'])
2747 sys.exit(0)
2762 sys.exit(0)
2748 elif options['version']:
2763 elif options['version']:
2749 show_version(u)
2764 show_version(u)
2750 sys.exit(0)
2765 sys.exit(0)
2751 elif not cmd:
2766 elif not cmd:
2752 help_(u, 'shortlist')
2767 help_(u, 'shortlist')
2753 sys.exit(0)
2768 sys.exit(0)
2754
2769
2755 if options['cwd']:
2770 if options['cwd']:
2756 try:
2771 try:
2757 os.chdir(options['cwd'])
2772 os.chdir(options['cwd'])
2758 except OSError, inst:
2773 except OSError, inst:
2759 raise util.Abort('%s: %s' %
2774 raise util.Abort('%s: %s' %
2760 (options['cwd'], inst.strerror))
2775 (options['cwd'], inst.strerror))
2761
2776
2762 if cmd not in norepo.split():
2777 if cmd not in norepo.split():
2763 path = options["repository"] or ""
2778 path = options["repository"] or ""
2764 repo = hg.repository(ui=u, path=path)
2779 repo = hg.repository(ui=u, path=path)
2765 for x in external:
2780 for x in external:
2766 if hasattr(x, 'reposetup'):
2781 if hasattr(x, 'reposetup'):
2767 x.reposetup(u, repo)
2782 x.reposetup(u, repo)
2768 d = lambda: func(u, repo, *args, **cmdoptions)
2783 d = lambda: func(u, repo, *args, **cmdoptions)
2769 else:
2784 else:
2770 d = lambda: func(u, *args, **cmdoptions)
2785 d = lambda: func(u, *args, **cmdoptions)
2771
2786
2772 if options['profile']:
2787 if options['profile']:
2773 import hotshot, hotshot.stats
2788 import hotshot, hotshot.stats
2774 prof = hotshot.Profile("hg.prof")
2789 prof = hotshot.Profile("hg.prof")
2775 r = prof.runcall(d)
2790 r = prof.runcall(d)
2776 prof.close()
2791 prof.close()
2777 stats = hotshot.stats.load("hg.prof")
2792 stats = hotshot.stats.load("hg.prof")
2778 stats.strip_dirs()
2793 stats.strip_dirs()
2779 stats.sort_stats('time', 'calls')
2794 stats.sort_stats('time', 'calls')
2780 stats.print_stats(40)
2795 stats.print_stats(40)
2781 return r
2796 return r
2782 else:
2797 else:
2783 return d()
2798 return d()
2784 except:
2799 except:
2785 # enter the debugger when we hit an exception
2800 # enter the debugger when we hit an exception
2786 if options['debugger']:
2801 if options['debugger']:
2787 pdb.post_mortem(sys.exc_info()[2])
2802 pdb.post_mortem(sys.exc_info()[2])
2788 if options['traceback']:
2803 if options['traceback']:
2789 traceback.print_exc()
2804 traceback.print_exc()
2790 raise
2805 raise
2791 except hg.RepoError, inst:
2806 except hg.RepoError, inst:
2792 u.warn(_("abort: "), inst, "!\n")
2807 u.warn(_("abort: "), inst, "!\n")
2793 except revlog.RevlogError, inst:
2808 except revlog.RevlogError, inst:
2794 u.warn(_("abort: "), inst, "!\n")
2809 u.warn(_("abort: "), inst, "!\n")
2795 except SignalInterrupt:
2810 except SignalInterrupt:
2796 u.warn(_("killed!\n"))
2811 u.warn(_("killed!\n"))
2797 except KeyboardInterrupt:
2812 except KeyboardInterrupt:
2798 try:
2813 try:
2799 u.warn(_("interrupted!\n"))
2814 u.warn(_("interrupted!\n"))
2800 except IOError, inst:
2815 except IOError, inst:
2801 if inst.errno == errno.EPIPE:
2816 if inst.errno == errno.EPIPE:
2802 if u.debugflag:
2817 if u.debugflag:
2803 u.warn(_("\nbroken pipe\n"))
2818 u.warn(_("\nbroken pipe\n"))
2804 else:
2819 else:
2805 raise
2820 raise
2806 except IOError, inst:
2821 except IOError, inst:
2807 if hasattr(inst, "code"):
2822 if hasattr(inst, "code"):
2808 u.warn(_("abort: %s\n") % inst)
2823 u.warn(_("abort: %s\n") % inst)
2809 elif hasattr(inst, "reason"):
2824 elif hasattr(inst, "reason"):
2810 u.warn(_("abort: error: %s\n") % inst.reason[1])
2825 u.warn(_("abort: error: %s\n") % inst.reason[1])
2811 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
2826 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
2812 if u.debugflag:
2827 if u.debugflag:
2813 u.warn(_("broken pipe\n"))
2828 u.warn(_("broken pipe\n"))
2814 elif getattr(inst, "strerror", None):
2829 elif getattr(inst, "strerror", None):
2815 if getattr(inst, "filename", None):
2830 if getattr(inst, "filename", None):
2816 u.warn(_("abort: %s - %s\n") % (inst.strerror, inst.filename))
2831 u.warn(_("abort: %s - %s\n") % (inst.strerror, inst.filename))
2817 else:
2832 else:
2818 u.warn(_("abort: %s\n") % inst.strerror)
2833 u.warn(_("abort: %s\n") % inst.strerror)
2819 else:
2834 else:
2820 raise
2835 raise
2821 except OSError, inst:
2836 except OSError, inst:
2822 if hasattr(inst, "filename"):
2837 if hasattr(inst, "filename"):
2823 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
2838 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
2824 else:
2839 else:
2825 u.warn(_("abort: %s\n") % inst.strerror)
2840 u.warn(_("abort: %s\n") % inst.strerror)
2826 except util.Abort, inst:
2841 except util.Abort, inst:
2827 u.warn(_('abort: '), inst.args[0] % inst.args[1:], '\n')
2842 u.warn(_('abort: '), inst.args[0] % inst.args[1:], '\n')
2828 sys.exit(1)
2843 sys.exit(1)
2829 except TypeError, inst:
2844 except TypeError, inst:
2830 # was this an argument error?
2845 # was this an argument error?
2831 tb = traceback.extract_tb(sys.exc_info()[2])
2846 tb = traceback.extract_tb(sys.exc_info()[2])
2832 if len(tb) > 2: # no
2847 if len(tb) > 2: # no
2833 raise
2848 raise
2834 u.debug(inst, "\n")
2849 u.debug(inst, "\n")
2835 u.warn(_("%s: invalid arguments\n") % cmd)
2850 u.warn(_("%s: invalid arguments\n") % cmd)
2836 help_(u, cmd)
2851 help_(u, cmd)
2837 except AmbiguousCommand, inst:
2852 except AmbiguousCommand, inst:
2838 u.warn(_("hg: command '%s' is ambiguous.\n") % inst.args[0])
2853 u.warn(_("hg: command '%s' is ambiguous.\n") % inst.args[0])
2839 help_(u, 'shortlist')
2854 help_(u, 'shortlist')
2840 except UnknownCommand, inst:
2855 except UnknownCommand, inst:
2841 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2856 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2842 help_(u, 'shortlist')
2857 help_(u, 'shortlist')
2843 except SystemExit:
2858 except SystemExit:
2844 # don't catch this in the catch-all below
2859 # don't catch this in the catch-all below
2845 raise
2860 raise
2846 except:
2861 except:
2847 u.warn(_("** unknown exception encountered, details follow\n"))
2862 u.warn(_("** unknown exception encountered, details follow\n"))
2848 u.warn(_("** report bug details to mercurial@selenic.com\n"))
2863 u.warn(_("** report bug details to mercurial@selenic.com\n"))
2849 u.warn(_("** Mercurial Distributed SCM (version %s)\n")
2864 u.warn(_("** Mercurial Distributed SCM (version %s)\n")
2850 % version.get_version())
2865 % version.get_version())
2851 raise
2866 raise
2852
2867
2853 sys.exit(-1)
2868 sys.exit(-1)
General Comments 0
You need to be logged in to leave comments. Login now