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