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