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