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