##// END OF EJS Templates
[PATCH] Fix "no-update" option to clone...
mpm@selenic.com -
r505:dc1f735d default
parent child Browse files
Show More
@@ -1,449 +1,449 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 --debug, -d::
20 --debug, -d::
21 enable debugging output
21 enable debugging output
22
22
23 --quiet, -q::
23 --quiet, -q::
24 suppress output
24 suppress output
25
25
26 --verbose, -v::
26 --verbose, -v::
27 enable additional output
27 enable additional output
28
28
29 --noninteractive, -y::
29 --noninteractive, -y::
30 do not prompt, assume 'yes' for any required answers
30 do not prompt, assume 'yes' for any required answers
31
31
32 COMMAND ELEMENTS
32 COMMAND ELEMENTS
33 ----------------
33 ----------------
34
34
35 files ...::
35 files ...::
36 indicates one or more filename or relative path filenames
36 indicates one or more filename or relative path filenames
37
37
38 path::
38 path::
39 indicates a path on the local machine
39 indicates a path on the local machine
40
40
41 revision::
41 revision::
42 indicates a changeset which can be specified as a changeset revision
42 indicates a changeset which can be specified as a changeset revision
43 number, a tag, or a unique substring of the changeset hash value
43 number, a tag, or a unique substring of the changeset hash value
44
44
45 repository path::
45 repository path::
46 either the pathname of a local repository or the URI of a remote
46 either the pathname of a local repository or the URI of a remote
47 repository. There are two available URI protocols, http:// which is
47 repository. There are two available URI protocols, http:// which is
48 fast and the old-http:// protocol which is much slower but does not
48 fast and the old-http:// protocol which is much slower but does not
49 require a special server on the web host.
49 require a special server on the web host.
50
50
51 COMMANDS
51 COMMANDS
52 --------
52 --------
53
53
54 add [files ...]::
54 add [files ...]::
55 Schedule files to be version controlled and added to the repository.
55 Schedule files to be version controlled and added to the repository.
56
56
57 The files will be added to the repository at the next commit.
57 The files will be added to the repository at the next commit.
58
58
59 addremove::
59 addremove::
60 Add all new files and remove all missing files from the repository.
60 Add all new files and remove all missing files from the repository.
61
61
62 New files are ignored if they match any of the patterns in .hgignore. As
62 New files are ignored if they match any of the patterns in .hgignore. As
63 with add, these changes take effect at the next commit.
63 with add, these changes take effect at the next commit.
64
64
65 annotate [-r <rev> -u -n -c] [files ...]::
65 annotate [-r <rev> -u -n -c] [files ...]::
66 List changes in files, showing the revision id responsible for each line
66 List changes in files, showing the revision id responsible for each line
67
67
68 This command is useful to discover who did a change or when a change took
68 This command is useful to discover who did a change or when a change took
69 place.
69 place.
70
70
71 options:
71 options:
72 -r, --revision <rev> annotate the specified revision
72 -r, --revision <rev> annotate the specified revision
73 -u, --user list the author
73 -u, --user list the author
74 -c, --changeset list the changeset
74 -c, --changeset list the changeset
75 -n, --number list the revision number (default)
75 -n, --number list the revision number (default)
76
76
77 cat <file> [revision]::
77 cat <file> [revision]::
78 Output to stdout the given revision for the specified file.
78 Output to stdout the given revision for the specified file.
79
79
80 If no revision is given then the tip is used.
80 If no revision is given then the tip is used.
81
81
82 clone [-U] <source> [dest]::
82 clone [-U] <source> [dest]::
83 Create a copy of an existing repository in a new directory.
83 Create a copy of an existing repository in a new directory.
84
84
85 If the destination directory is specified but doesn't exist, it is
85 If the destination directory is specified but doesn't exist, it is
86 created. If no destination directory is specified, it defaults to the
86 created. If no destination directory is specified, it defaults to the
87 current directory.
87 current directory.
88
88
89 The source is added to the new repository's .hg/hgrc file to be used in
89 The source is added to the new repository's .hg/hgrc file to be used in
90 future pulls.
90 future pulls.
91
91
92 For efficiency, hardlinks are used for cloning whenever the
92 For efficiency, hardlinks are used for cloning whenever the
93 source and destination are on the same filesystem.
93 source and destination are on the same filesystem.
94
94
95 options:
95 options:
96 -U, --no-update do not update the new working directory
96 -U, --noupdate do not update the new working directory
97
97
98 commit [-A -t -l <file> -t <text> -u <user> -d <datecode>] [files...]::
98 commit [-A -t -l <file> -t <text> -u <user> -d <datecode>] [files...]::
99 Commit changes to the given files into the repository.
99 Commit changes to the given files into the repository.
100
100
101 If a list of files is omitted, all changes reported by "hg status"
101 If a list of files is omitted, all changes reported by "hg status"
102 will be commited.
102 will be commited.
103
103
104 The HGEDITOR or EDITOR environment variables are used to start an
104 The HGEDITOR or EDITOR environment variables are used to start an
105 editor to add a commit comment.
105 editor to add a commit comment.
106
106
107 Options:
107 Options:
108
108
109 -A, --addremove run addremove during commit
109 -A, --addremove run addremove during commit
110 -t, --text <text> use <text> as commit message
110 -t, --text <text> use <text> as commit message
111 -l, --logfile <file> show the commit message for the given file
111 -l, --logfile <file> show the commit message for the given file
112 -d, --date <datecode> record datecode as commit date
112 -d, --date <datecode> record datecode as commit date
113 -u, --user <user> record user as commiter
113 -u, --user <user> record user as commiter
114
114
115 aliases: ci
115 aliases: ci
116
116
117 copy <source> <dest>::
117 copy <source> <dest>::
118 Mark <dest> file as a copy or rename of a <source> one
118 Mark <dest> file as a copy or rename of a <source> one
119
119
120 This command takes effect for the next commit.
120 This command takes effect for the next commit.
121
121
122 diff [-r revision] [-r revision] [files ...]::
122 diff [-r revision] [-r revision] [files ...]::
123 Show differences between revisions for the specified files.
123 Show differences between revisions for the specified files.
124
124
125 Differences between files are shown using the unified diff format.
125 Differences between files are shown using the unified diff format.
126
126
127 When two revision arguments are given, then changes are shown
127 When two revision arguments are given, then changes are shown
128 between those revisions. If only one revision is specified then
128 between those revisions. If only one revision is specified then
129 that revision is compared to the working directory, and, when no
129 that revision is compared to the working directory, and, when no
130 revisions are specified, the working directory files are compared
130 revisions are specified, the working directory files are compared
131 to its parent.
131 to its parent.
132
132
133 export [revision]::
133 export [revision]::
134 Print the changeset header and diffs for a particular revision.
134 Print the changeset header and diffs for a particular revision.
135
135
136 The information shown in the changeset header is: author, changeset hash,
136 The information shown in the changeset header is: author, changeset hash,
137 parent and commit comment.
137 parent and commit comment.
138
138
139 forget [files]::
139 forget [files]::
140 Undo an 'hg add' scheduled for the next commit.
140 Undo an 'hg add' scheduled for the next commit.
141
141
142 heads::
142 heads::
143 Show all repository head changesets.
143 Show all repository head changesets.
144
144
145 Repository "heads" are changesets that don't have children
145 Repository "heads" are changesets that don't have children
146 changesets. They are where development generally takes place and
146 changesets. They are where development generally takes place and
147 are the usual targets for update and merge operations.
147 are the usual targets for update and merge operations.
148
148
149 history::
149 history::
150 Print a log of the revision history of the repository.
150 Print a log of the revision history of the repository.
151
151
152 By default this command outputs: changeset id and hash, tags,
152 By default this command outputs: changeset id and hash, tags,
153 parents, user, date and time, and a summary for each commit. The
153 parents, user, date and time, and a summary for each commit. The
154 -v switch adds some more detail, such as changed files, manifest
154 -v switch adds some more detail, such as changed files, manifest
155 hashes or message signatures.
155 hashes or message signatures.
156
156
157 To display the history of a given file, see the log command.
157 To display the history of a given file, see the log command.
158
158
159 identify::
159 identify::
160 Print a short summary of the current state of the repo.
160 Print a short summary of the current state of the repo.
161
161
162 This summary identifies the repository state using one or two parent
162 This summary identifies the repository state using one or two parent
163 hash identifiers, followed by a "+" if there are uncommitted changes
163 hash identifiers, followed by a "+" if there are uncommitted changes
164 in the working directory, followed by a list of tags for this revision.
164 in the working directory, followed by a list of tags for this revision.
165
165
166 aliases: id
166 aliases: id
167
167
168 import [-p <n> -b <base> -q] <patches>::
168 import [-p <n> -b <base> -q] <patches>::
169 Import a list of patches and commit them individually.
169 Import a list of patches and commit them individually.
170
170
171 options:
171 options:
172 -p, --strip <n> directory strip option for patch. This has the same
172 -p, --strip <n> directory strip option for patch. This has the same
173 meaning as the correnponding patch option
173 meaning as the correnponding patch option
174 -b <path> base directory to read patches from
174 -b <path> base directory to read patches from
175
175
176 aliases: patch
176 aliases: patch
177
177
178 init::
178 init::
179 Initialize a new repository in the current directory.
179 Initialize a new repository in the current directory.
180
180
181 log <file>::
181 log <file>::
182 Print the revision history of the specified file.
182 Print the revision history of the specified file.
183
183
184 To display the revision history for the whole repository, use the history
184 To display the revision history for the whole repository, use the history
185 command.
185 command.
186
186
187 manifest [revision]::
187 manifest [revision]::
188 Print a list of version controlled files for the given revision.
188 Print a list of version controlled files for the given revision.
189
189
190 The manifest is the list of files being version controlled. If no revision
190 The manifest is the list of files being version controlled. If no revision
191 is given then the tip is used.
191 is given then the tip is used.
192
192
193 parents::
193 parents::
194 Print the working directory's parent revisions.
194 Print the working directory's parent revisions.
195
195
196 pull <repository path>::
196 pull <repository path>::
197 Pull changes from a remote repository to a local one.
197 Pull changes from a remote repository to a local one.
198
198
199 This finds all changes from the repository at the specified path
199 This finds all changes from the repository at the specified path
200 or URL and adds them to the local repository. By default, this
200 or URL and adds them to the local repository. By default, this
201 does not update the copy of the project in the working directory.
201 does not update the copy of the project in the working directory.
202
202
203 options:
203 options:
204 -u, --update update the working directory to tip after pull
204 -u, --update update the working directory to tip after pull
205
205
206 push <destination>::
206 push <destination>::
207 Push changes from the local repository to the given destination.
207 Push changes from the local repository to the given destination.
208
208
209 This is the symmetrical operation for pull. It helps to move
209 This is the symmetrical operation for pull. It helps to move
210 changes from the current repository to a different one. If the
210 changes from the current repository to a different one. If the
211 destination is local this is identical to a pull in that directory
211 destination is local this is identical to a pull in that directory
212 from the current one.
212 from the current one.
213
213
214 The other currently available push method is SSH. This requires an
214 The other currently available push method is SSH. This requires an
215 accessible shell account on the destination machine and a copy of
215 accessible shell account on the destination machine and a copy of
216 hg in the remote path. Destinations are specified in the following
216 hg in the remote path. Destinations are specified in the following
217 form:
217 form:
218
218
219 ssh://[user@]host[:port]/path
219 ssh://[user@]host[:port]/path
220
220
221 rawcommit [-p -d -u -F -t -l]::
221 rawcommit [-p -d -u -F -t -l]::
222 Lowlevel commit, for use in helper scripts.
222 Lowlevel commit, for use in helper scripts.
223
223
224 This command is not intended to be used by normal users, as it is
224 This command is not intended to be used by normal users, as it is
225 primarily useful for importing from other SCMs.
225 primarily useful for importing from other SCMs.
226
226
227 recover::
227 recover::
228 Recover from an interrupted commit or pull.
228 Recover from an interrupted commit or pull.
229
229
230 This command tries to fix the repository status after an interrupted
230 This command tries to fix the repository status after an interrupted
231 operation. It should only be necessary when Mercurial suggests it.
231 operation. It should only be necessary when Mercurial suggests it.
232
232
233 remove [files ...]::
233 remove [files ...]::
234 Schedule the indicated files for removal from the repository.
234 Schedule the indicated files for removal from the repository.
235
235
236 This command shedules the files to be removed at the next commit.
236 This command shedules the files to be removed at the next commit.
237 This only removes files from the current branch, not from the
237 This only removes files from the current branch, not from the
238 entire project history.
238 entire project history.
239
239
240 aliases: rm
240 aliases: rm
241
241
242 root::
242 root::
243 Print the root directory of the current repository.
243 Print the root directory of the current repository.
244
244
245 serve [-a addr -n name -p port -t templatedir]::
245 serve [-a addr -n name -p port -t templatedir]::
246 Start a local HTTP repository browser and pull server.
246 Start a local HTTP repository browser and pull server.
247
247
248 options:
248 options:
249 -a, --address <addr> address to use
249 -a, --address <addr> address to use
250 -p, --port <n> port to use (default: 8000)
250 -p, --port <n> port to use (default: 8000)
251 -n, --name <name> name to show in web pages (default: working dir)
251 -n, --name <name> name to show in web pages (default: working dir)
252 -t, --templatedir <path> web templates to use
252 -t, --templatedir <path> web templates to use
253
253
254 status::
254 status::
255 Show changed files in the working directory.
255 Show changed files in the working directory.
256
256
257 The codes used to show the status of files are:
257 The codes used to show the status of files are:
258
258
259 C = changed
259 C = changed
260 A = added
260 A = added
261 R = removed
261 R = removed
262 ? = not tracked
262 ? = not tracked
263
263
264 tag [-t <text> -d <datecode> -u <user>] <name> [revision]::
264 tag [-t <text> -d <datecode> -u <user>] <name> [revision]::
265 Name a particular revision using <name>.
265 Name a particular revision using <name>.
266
266
267 Tags are used to name particular revisions of the repository and are
267 Tags are used to name particular revisions of the repository and are
268 very useful to compare different revision, to go back to significant
268 very useful to compare different revision, to go back to significant
269 earlier versions or to mark branch points as releases, etc.
269 earlier versions or to mark branch points as releases, etc.
270
270
271 If no revision is given, the tip is used.
271 If no revision is given, the tip is used.
272
272
273 To facilitate version control, distribution, and merging of tags,
273 To facilitate version control, distribution, and merging of tags,
274 they are stored as a file named ".hgtags" which is managed
274 they are stored as a file named ".hgtags" which is managed
275 similarly to other project files and can be hand-edited if
275 similarly to other project files and can be hand-edited if
276 necessary.
276 necessary.
277
277
278 options:
278 options:
279 -t, --text <text> message for tag commit log entry
279 -t, --text <text> message for tag commit log entry
280 -d, --date <datecode> datecode for commit
280 -d, --date <datecode> datecode for commit
281 -u, --user <user> user for commit
281 -u, --user <user> user for commit
282
282
283 Note: Mercurial also has support for "local tags" that are not
283 Note: Mercurial also has support for "local tags" that are not
284 version-controlled or distributed which are stored in the .hg/hgrc
284 version-controlled or distributed which are stored in the .hg/hgrc
285 file.
285 file.
286
286
287 tags::
287 tags::
288 List the repository tags.
288 List the repository tags.
289
289
290 This lists both regular and local tags.
290 This lists both regular and local tags.
291
291
292 tip::
292 tip::
293 Show the tip revision.
293 Show the tip revision.
294
294
295 undo::
295 undo::
296 Undo the last commit or pull transaction.
296 Undo the last commit or pull transaction.
297
297
298 update [-m -C] [revision]::
298 update [-m -C] [revision]::
299 Update the working directory to the specified revision.
299 Update the working directory to the specified revision.
300
300
301 By default, update will refuse to run if doing so would require
301 By default, update will refuse to run if doing so would require
302 merging or discarding local changes.
302 merging or discarding local changes.
303
303
304 With the -m option, a merge will be performed.
304 With the -m option, a merge will be performed.
305
305
306 With the -C option, local changes will be lost.
306 With the -C option, local changes will be lost.
307
307
308 options:
308 options:
309 -m, --merge allow merging of branches
309 -m, --merge allow merging of branches
310 -C, --clean overwrite locally modified files
310 -C, --clean overwrite locally modified files
311
311
312 aliases: up checkout co
312 aliases: up checkout co
313
313
314 verify::
314 verify::
315 Verify the integrity of the current repository.
315 Verify the integrity of the current repository.
316
316
317 This will perform an extensive check of the repository's
317 This will perform an extensive check of the repository's
318 integrity, validating the hashes and checksums of each entry in
318 integrity, validating the hashes and checksums of each entry in
319 the changelog, manifest, and tracked files, as well as the
319 the changelog, manifest, and tracked files, as well as the
320 integrity of their crosslinks and indices.
320 integrity of their crosslinks and indices.
321
321
322
322
323 ENVIRONMENT VARIABLES
323 ENVIRONMENT VARIABLES
324 ---------------------
324 ---------------------
325
325
326 HGEDITOR::
326 HGEDITOR::
327 This is the name of the editor to use when committing. Defaults to the
327 This is the name of the editor to use when committing. Defaults to the
328 value of EDITOR.
328 value of EDITOR.
329
329
330 HGMERGE::
330 HGMERGE::
331 An executable to use for resolving merge conflicts. The program
331 An executable to use for resolving merge conflicts. The program
332 will be executed with three arguments: local file, remote file,
332 will be executed with three arguments: local file, remote file,
333 ancestor file.
333 ancestor file.
334
334
335 The default program is "hgmerge", which is a shell script provided
335 The default program is "hgmerge", which is a shell script provided
336 by Mercurial with some sensible defaults.
336 by Mercurial with some sensible defaults.
337
337
338 HGUSER::
338 HGUSER::
339 This is the string used for the author of a commit.
339 This is the string used for the author of a commit.
340
340
341 EMAIL::
341 EMAIL::
342 If HGUSER is not set, this will be used as the author for a commit.
342 If HGUSER is not set, this will be used as the author for a commit.
343
343
344 LOGNAME::
344 LOGNAME::
345 If neither HGUSER nor EMAIL is set, LOGNAME will be used (with
345 If neither HGUSER nor EMAIL is set, LOGNAME will be used (with
346 '@hostname' appended) as the author value for a commit.
346 '@hostname' appended) as the author value for a commit.
347
347
348 EDITOR::
348 EDITOR::
349 This is the name of the editor used in the hgmerge script. It will be
349 This is the name of the editor used in the hgmerge script. It will be
350 used for commit messages if HGEDITOR isn't set. Defaults to 'vi'.
350 used for commit messages if HGEDITOR isn't set. Defaults to 'vi'.
351
351
352 PYTHONPATH::
352 PYTHONPATH::
353 This is used by Python to find imported modules and may need to be set
353 This is used by Python to find imported modules and may need to be set
354 appropriately if Mercurial is not installed system-wide.
354 appropriately if Mercurial is not installed system-wide.
355
355
356 FILES
356 FILES
357 -----
357 -----
358 .hgignore::
358 .hgignore::
359 This file contains regular expressions (one per line) that describe file
359 This file contains regular expressions (one per line) that describe file
360 names that should be ignored by hg.
360 names that should be ignored by hg.
361
361
362 .hgtags::
362 .hgtags::
363 This file contains changeset hash values and text tag names (one of each
363 This file contains changeset hash values and text tag names (one of each
364 seperated by spaces) that correspond to tagged versions of the repository
364 seperated by spaces) that correspond to tagged versions of the repository
365 contents.
365 contents.
366
366
367 $HOME/.hgrc, .hg/hgrc::
367 $HOME/.hgrc, .hg/hgrc::
368 This file contains defaults and configuration. Values in .hg/hgrc
368 This file contains defaults and configuration. Values in .hg/hgrc
369 override those in .hgrc.
369 override those in .hgrc.
370
370
371 NAMED REPOSITORIES
371 NAMED REPOSITORIES
372 ------------------
372 ------------------
373
373
374 To give symbolic names to a repository, create a section in .hgrc
374 To give symbolic names to a repository, create a section in .hgrc
375 or .hg/hgrc containing assignments of names to paths. Example:
375 or .hg/hgrc containing assignments of names to paths. Example:
376
376
377 -----------------
377 -----------------
378 [paths]
378 [paths]
379 hg = http://selenic.com/hg
379 hg = http://selenic.com/hg
380 tah = http://hg.intevation.org/mercurial-tah/
380 tah = http://hg.intevation.org/mercurial-tah/
381 -----------------
381 -----------------
382
382
383
383
384 LOCAL TAGS
384 LOCAL TAGS
385 ----------
385 ----------
386
386
387 To create tags that are local to the repository and not distributed or
387 To create tags that are local to the repository and not distributed or
388 version-controlled, create an hgrc section like the following:
388 version-controlled, create an hgrc section like the following:
389
389
390 ----------------
390 ----------------
391 [tags]
391 [tags]
392 working = 2dcced388cab3677a8f543c3c47a0ad34ac9d435
392 working = 2dcced388cab3677a8f543c3c47a0ad34ac9d435
393 tested = 12e0fdbc57a0be78f0e817fd1d170a3615cd35da
393 tested = 12e0fdbc57a0be78f0e817fd1d170a3615cd35da
394 ----------------
394 ----------------
395
395
396
396
397 HOOKS
397 HOOKS
398 -----
398 -----
399
399
400 Mercurial supports a set of 'hook', commands that get automatically
400 Mercurial supports a set of 'hook', commands that get automatically
401 executed by various actions such as starting or finishing a commit. To
401 executed by various actions such as starting or finishing a commit. To
402 specify a hook, simply create an hgrc section like the following:
402 specify a hook, simply create an hgrc section like the following:
403
403
404 -----------------
404 -----------------
405 [hooks]
405 [hooks]
406 precommit = echo "this hook gets executed immediately before a commit"
406 precommit = echo "this hook gets executed immediately before a commit"
407 commit = hg export $NODE | mail -s "new commit $NODE" commit-list
407 commit = hg export $NODE | mail -s "new commit $NODE" commit-list
408 -----------------
408 -----------------
409
409
410
410
411 NON_TRANSPARENT PROXY SUPPORT
411 NON_TRANSPARENT PROXY SUPPORT
412 -----------------------------
412 -----------------------------
413
413
414 To access a Mercurial repository through a proxy, create a file
414 To access a Mercurial repository through a proxy, create a file
415 $HOME/.hgrc in the following format:
415 $HOME/.hgrc in the following format:
416
416
417 --------------
417 --------------
418 [http_proxy]
418 [http_proxy]
419 host=myproxy:8080
419 host=myproxy:8080
420 user=<username>
420 user=<username>
421 passwd=<password>
421 passwd=<password>
422 no=<localhost1>,<localhost2>,<localhost3>,...
422 no=<localhost1>,<localhost2>,<localhost3>,...
423 --------------
423 --------------
424
424
425 "user" and "passwd" fields are used for authenticating proxies, "no" is a
425 "user" and "passwd" fields are used for authenticating proxies, "no" is a
426 comma-separated list of local host names to not proxy.
426 comma-separated list of local host names to not proxy.
427
427
428 BUGS
428 BUGS
429 ----
429 ----
430 Probably lots, please post them to the mailing list (See Resources below)
430 Probably lots, please post them to the mailing list (See Resources below)
431 when you find them.
431 when you find them.
432
432
433 AUTHOR
433 AUTHOR
434 ------
434 ------
435 Written by Matt Mackall <mpm@selenic.com>
435 Written by Matt Mackall <mpm@selenic.com>
436
436
437 RESOURCES
437 RESOURCES
438 ---------
438 ---------
439 http://selenic.com/mercurial[Main Web Site]
439 http://selenic.com/mercurial[Main Web Site]
440
440
441 http://selenic.com/hg[Source code repository]
441 http://selenic.com/hg[Source code repository]
442
442
443 http://selenic.com/mailman/listinfo/mercurial[Mailing list]
443 http://selenic.com/mailman/listinfo/mercurial[Mailing list]
444
444
445 COPYING
445 COPYING
446 -------
446 -------
447 Copyright (C) 2005 Matt Mackall.
447 Copyright (C) 2005 Matt Mackall.
448 Free use of this software is granted under the terms of the GNU General
448 Free use of this software is granted under the terms of the GNU General
449 Public License (GPL).
449 Public License (GPL).
@@ -1,912 +1,912 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 import os, re, sys, signal
8 import os, re, sys, signal
9 import fancyopts, ui, hg, util
9 import fancyopts, ui, hg, util
10 from demandload import *
10 from demandload import *
11 demandload(globals(), "mdiff time hgweb traceback random signal errno version")
11 demandload(globals(), "mdiff time hgweb traceback random signal errno version")
12
12
13 class UnknownCommand(Exception): pass
13 class UnknownCommand(Exception): pass
14
14
15 def filterfiles(filters, files):
15 def filterfiles(filters, files):
16 l = [ x for x in files if x in filters ]
16 l = [ x for x in files if x in filters ]
17
17
18 for t in filters:
18 for t in filters:
19 if t and t[-1] != "/": t += "/"
19 if t and t[-1] != "/": t += "/"
20 l += [ x for x in files if x.startswith(t) ]
20 l += [ x for x in files if x.startswith(t) ]
21 return l
21 return l
22
22
23 def relfilter(repo, files):
23 def relfilter(repo, files):
24 if os.getcwd() != repo.root:
24 if os.getcwd() != repo.root:
25 p = os.getcwd()[len(repo.root) + 1: ]
25 p = os.getcwd()[len(repo.root) + 1: ]
26 return filterfiles([util.pconvert(p)], files)
26 return filterfiles([util.pconvert(p)], files)
27 return files
27 return files
28
28
29 def relpath(repo, args):
29 def relpath(repo, args):
30 if os.getcwd() != repo.root:
30 if os.getcwd() != repo.root:
31 p = os.getcwd()[len(repo.root) + 1: ]
31 p = os.getcwd()[len(repo.root) + 1: ]
32 return [ util.pconvert(os.path.normpath(os.path.join(p, x))) for x in args ]
32 return [ util.pconvert(os.path.normpath(os.path.join(p, x))) for x in args ]
33 return args
33 return args
34
34
35 def dodiff(ui, repo, path, files = None, node1 = None, node2 = None):
35 def dodiff(ui, repo, path, files = None, node1 = None, node2 = None):
36 def date(c):
36 def date(c):
37 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
37 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
38
38
39 if node2:
39 if node2:
40 change = repo.changelog.read(node2)
40 change = repo.changelog.read(node2)
41 mmap2 = repo.manifest.read(change[0])
41 mmap2 = repo.manifest.read(change[0])
42 (c, a, d) = repo.diffrevs(node1, node2)
42 (c, a, d) = repo.diffrevs(node1, node2)
43 def read(f): return repo.file(f).read(mmap2[f])
43 def read(f): return repo.file(f).read(mmap2[f])
44 date2 = date(change)
44 date2 = date(change)
45 else:
45 else:
46 date2 = time.asctime()
46 date2 = time.asctime()
47 (c, a, d, u) = repo.diffdir(path, node1)
47 (c, a, d, u) = repo.diffdir(path, node1)
48 if not node1:
48 if not node1:
49 node1 = repo.dirstate.parents()[0]
49 node1 = repo.dirstate.parents()[0]
50 def read(f): return repo.wfile(f).read()
50 def read(f): return repo.wfile(f).read()
51
51
52 if ui.quiet:
52 if ui.quiet:
53 r = None
53 r = None
54 else:
54 else:
55 hexfunc = ui.verbose and hg.hex or hg.short
55 hexfunc = ui.verbose and hg.hex or hg.short
56 r = [hexfunc(node) for node in [node1, node2] if node]
56 r = [hexfunc(node) for node in [node1, node2] if node]
57
57
58 change = repo.changelog.read(node1)
58 change = repo.changelog.read(node1)
59 mmap = repo.manifest.read(change[0])
59 mmap = repo.manifest.read(change[0])
60 date1 = date(change)
60 date1 = date(change)
61
61
62 if files:
62 if files:
63 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
63 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
64
64
65 for f in c:
65 for f in c:
66 to = None
66 to = None
67 if f in mmap:
67 if f in mmap:
68 to = repo.file(f).read(mmap[f])
68 to = repo.file(f).read(mmap[f])
69 tn = read(f)
69 tn = read(f)
70 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
70 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
71 for f in a:
71 for f in a:
72 to = None
72 to = None
73 tn = read(f)
73 tn = read(f)
74 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
74 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
75 for f in d:
75 for f in d:
76 to = repo.file(f).read(mmap[f])
76 to = repo.file(f).read(mmap[f])
77 tn = None
77 tn = None
78 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
78 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
79
79
80 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None):
80 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None):
81 """show a single changeset or file revision"""
81 """show a single changeset or file revision"""
82 changelog = repo.changelog
82 changelog = repo.changelog
83 if filelog:
83 if filelog:
84 log = filelog
84 log = filelog
85 filerev = rev
85 filerev = rev
86 node = filenode = filelog.node(filerev)
86 node = filenode = filelog.node(filerev)
87 changerev = filelog.linkrev(filenode)
87 changerev = filelog.linkrev(filenode)
88 changenode = changenode or changelog.node(changerev)
88 changenode = changenode or changelog.node(changerev)
89 else:
89 else:
90 log = changelog
90 log = changelog
91 changerev = rev
91 changerev = rev
92 if changenode is None:
92 if changenode is None:
93 changenode = changelog.node(changerev)
93 changenode = changelog.node(changerev)
94 elif not changerev:
94 elif not changerev:
95 rev = changerev = changelog.rev(changenode)
95 rev = changerev = changelog.rev(changenode)
96 node = changenode
96 node = changenode
97
97
98 if ui.quiet:
98 if ui.quiet:
99 ui.write("%d:%s\n" % (rev, hg.hex(node)))
99 ui.write("%d:%s\n" % (rev, hg.hex(node)))
100 return
100 return
101
101
102 changes = changelog.read(changenode)
102 changes = changelog.read(changenode)
103
103
104 parents = [(log.rev(parent), hg.hex(parent))
104 parents = [(log.rev(parent), hg.hex(parent))
105 for parent in log.parents(node)
105 for parent in log.parents(node)
106 if ui.debugflag or parent != hg.nullid]
106 if ui.debugflag or parent != hg.nullid]
107 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
107 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
108 parents = []
108 parents = []
109
109
110 if filelog:
110 if filelog:
111 ui.write("revision: %d:%s\n" % (filerev, hg.hex(filenode)))
111 ui.write("revision: %d:%s\n" % (filerev, hg.hex(filenode)))
112 for parent in parents:
112 for parent in parents:
113 ui.write("parent: %d:%s\n" % parent)
113 ui.write("parent: %d:%s\n" % parent)
114 ui.status("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
114 ui.status("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
115 else:
115 else:
116 ui.write("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
116 ui.write("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
117 for tag in repo.nodetags(changenode):
117 for tag in repo.nodetags(changenode):
118 ui.status("tag: %s\n" % tag)
118 ui.status("tag: %s\n" % tag)
119 for parent in parents:
119 for parent in parents:
120 ui.write("parent: %d:%s\n" % parent)
120 ui.write("parent: %d:%s\n" % parent)
121 ui.note("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]),
121 ui.note("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]),
122 hg.hex(changes[0])))
122 hg.hex(changes[0])))
123 ui.status("user: %s\n" % changes[1])
123 ui.status("user: %s\n" % changes[1])
124 ui.status("date: %s\n" % time.asctime(
124 ui.status("date: %s\n" % time.asctime(
125 time.localtime(float(changes[2].split(' ')[0]))))
125 time.localtime(float(changes[2].split(' ')[0]))))
126 if ui.debugflag:
126 if ui.debugflag:
127 files = repo.diffrevs(changelog.parents(changenode)[0], changenode)
127 files = repo.diffrevs(changelog.parents(changenode)[0], changenode)
128 for key, value in zip(["files:", "files+:", "files-:"], files):
128 for key, value in zip(["files:", "files+:", "files-:"], files):
129 if value:
129 if value:
130 ui.note("%-12s %s\n" % (key, " ".join(value)))
130 ui.note("%-12s %s\n" % (key, " ".join(value)))
131 else:
131 else:
132 ui.note("files: %s\n" % " ".join(changes[3]))
132 ui.note("files: %s\n" % " ".join(changes[3]))
133 description = changes[4].strip()
133 description = changes[4].strip()
134 if description:
134 if description:
135 if ui.verbose:
135 if ui.verbose:
136 ui.status("description:\n")
136 ui.status("description:\n")
137 ui.status(description)
137 ui.status(description)
138 ui.status("\n")
138 ui.status("\n")
139 else:
139 else:
140 ui.status("summary: %s\n" % description.splitlines()[0])
140 ui.status("summary: %s\n" % description.splitlines()[0])
141 ui.status("\n")
141 ui.status("\n")
142
142
143 def show_version(ui):
143 def show_version(ui):
144 """output version and copyright information"""
144 """output version and copyright information"""
145 ui.write("Mercurial version %s\n" % version.get_version())
145 ui.write("Mercurial version %s\n" % version.get_version())
146 ui.status(
146 ui.status(
147 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
147 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
148 "This is free software; see the source for copying conditions. "
148 "This is free software; see the source for copying conditions. "
149 "There is NO\nwarranty; "
149 "There is NO\nwarranty; "
150 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
150 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
151 )
151 )
152
152
153 def help(ui, cmd=None):
153 def help(ui, cmd=None):
154 '''show help for a given command or all commands'''
154 '''show help for a given command or all commands'''
155 if cmd:
155 if cmd:
156 try:
156 try:
157 i = find(cmd)
157 i = find(cmd)
158 ui.write("%s\n\n" % i[2])
158 ui.write("%s\n\n" % i[2])
159
159
160 if i[1]:
160 if i[1]:
161 for s, l, d, c in i[1]:
161 for s, l, d, c in i[1]:
162 opt=' '
162 opt=' '
163 if s: opt = opt + '-' + s + ' '
163 if s: opt = opt + '-' + s + ' '
164 if l: opt = opt + '--' + l + ' '
164 if l: opt = opt + '--' + l + ' '
165 if d: opt = opt + '(' + str(d) + ')'
165 if d: opt = opt + '(' + str(d) + ')'
166 ui.write(opt, "\n")
166 ui.write(opt, "\n")
167 if c: ui.write(' %s\n' % c)
167 if c: ui.write(' %s\n' % c)
168 ui.write("\n")
168 ui.write("\n")
169
169
170 ui.write(i[0].__doc__, "\n")
170 ui.write(i[0].__doc__, "\n")
171 except UnknownCommand:
171 except UnknownCommand:
172 ui.warn("hg: unknown command %s\n" % cmd)
172 ui.warn("hg: unknown command %s\n" % cmd)
173 sys.exit(0)
173 sys.exit(0)
174 else:
174 else:
175 if not ui.quiet:
175 if not ui.quiet:
176 show_version(ui)
176 show_version(ui)
177 ui.write('\n')
177 ui.write('\n')
178 ui.write('hg commands:\n\n')
178 ui.write('hg commands:\n\n')
179
179
180 h = {}
180 h = {}
181 for c, e in table.items():
181 for c, e in table.items():
182 f = c.split("|")[0]
182 f = c.split("|")[0]
183 if f.startswith("debug"):
183 if f.startswith("debug"):
184 continue
184 continue
185 d = ""
185 d = ""
186 if e[0].__doc__:
186 if e[0].__doc__:
187 d = e[0].__doc__.splitlines(0)[0].rstrip()
187 d = e[0].__doc__.splitlines(0)[0].rstrip()
188 h[f] = d
188 h[f] = d
189
189
190 fns = h.keys()
190 fns = h.keys()
191 fns.sort()
191 fns.sort()
192 m = max(map(len, fns))
192 m = max(map(len, fns))
193 for f in fns:
193 for f in fns:
194 ui.write(' %-*s %s\n' % (m, f, h[f]))
194 ui.write(' %-*s %s\n' % (m, f, h[f]))
195
195
196 # Commands start here, listed alphabetically
196 # Commands start here, listed alphabetically
197
197
198 def add(ui, repo, file, *files):
198 def add(ui, repo, file, *files):
199 '''add the specified files on the next commit'''
199 '''add the specified files on the next commit'''
200 repo.add(relpath(repo, (file,) + files))
200 repo.add(relpath(repo, (file,) + files))
201
201
202 def addremove(ui, repo, *files):
202 def addremove(ui, repo, *files):
203 """add all new files, delete all missing files"""
203 """add all new files, delete all missing files"""
204 if files:
204 if files:
205 files = relpath(repo, files)
205 files = relpath(repo, files)
206 d = []
206 d = []
207 u = []
207 u = []
208 for f in files:
208 for f in files:
209 p = repo.wjoin(f)
209 p = repo.wjoin(f)
210 s = repo.dirstate.state(f)
210 s = repo.dirstate.state(f)
211 isfile = os.path.isfile(p)
211 isfile = os.path.isfile(p)
212 if s != 'r' and not isfile:
212 if s != 'r' and not isfile:
213 d.append(f)
213 d.append(f)
214 elif s not in 'nmai' and isfile:
214 elif s not in 'nmai' and isfile:
215 u.append(f)
215 u.append(f)
216 else:
216 else:
217 (c, a, d, u) = repo.diffdir(repo.root)
217 (c, a, d, u) = repo.diffdir(repo.root)
218 repo.add(u)
218 repo.add(u)
219 repo.remove(d)
219 repo.remove(d)
220
220
221 def annotate(u, repo, file, *files, **ops):
221 def annotate(u, repo, file, *files, **ops):
222 """show changeset information per file line"""
222 """show changeset information per file line"""
223 def getnode(rev):
223 def getnode(rev):
224 return hg.short(repo.changelog.node(rev))
224 return hg.short(repo.changelog.node(rev))
225
225
226 def getname(rev):
226 def getname(rev):
227 try:
227 try:
228 return bcache[rev]
228 return bcache[rev]
229 except KeyError:
229 except KeyError:
230 cl = repo.changelog.read(repo.changelog.node(rev))
230 cl = repo.changelog.read(repo.changelog.node(rev))
231 name = cl[1]
231 name = cl[1]
232 f = name.find('@')
232 f = name.find('@')
233 if f >= 0:
233 if f >= 0:
234 name = name[:f]
234 name = name[:f]
235 bcache[rev] = name
235 bcache[rev] = name
236 return name
236 return name
237
237
238 bcache = {}
238 bcache = {}
239 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
239 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
240 if not ops['user'] and not ops['changeset']:
240 if not ops['user'] and not ops['changeset']:
241 ops['number'] = 1
241 ops['number'] = 1
242
242
243 node = repo.dirstate.parents()[0]
243 node = repo.dirstate.parents()[0]
244 if ops['revision']:
244 if ops['revision']:
245 node = repo.changelog.lookup(ops['revision'])
245 node = repo.changelog.lookup(ops['revision'])
246 change = repo.changelog.read(node)
246 change = repo.changelog.read(node)
247 mmap = repo.manifest.read(change[0])
247 mmap = repo.manifest.read(change[0])
248 for f in relpath(repo, (file,) + files):
248 for f in relpath(repo, (file,) + files):
249 lines = repo.file(f).annotate(mmap[f])
249 lines = repo.file(f).annotate(mmap[f])
250 pieces = []
250 pieces = []
251
251
252 for o, f in opmap:
252 for o, f in opmap:
253 if ops[o]:
253 if ops[o]:
254 l = [ f(n) for n,t in lines ]
254 l = [ f(n) for n,t in lines ]
255 m = max(map(len, l))
255 m = max(map(len, l))
256 pieces.append([ "%*s" % (m, x) for x in l])
256 pieces.append([ "%*s" % (m, x) for x in l])
257
257
258 for p,l in zip(zip(*pieces), lines):
258 for p,l in zip(zip(*pieces), lines):
259 u.write(" ".join(p) + ": " + l[1])
259 u.write(" ".join(p) + ": " + l[1])
260
260
261 def cat(ui, repo, file, rev = []):
261 def cat(ui, repo, file, rev = []):
262 """output the latest or given revision of a file"""
262 """output the latest or given revision of a file"""
263 r = repo.file(relpath(repo, [file])[0])
263 r = repo.file(relpath(repo, [file])[0])
264 n = r.tip()
264 n = r.tip()
265 if rev: n = r.lookup(rev)
265 if rev: n = r.lookup(rev)
266 sys.stdout.write(r.read(n))
266 sys.stdout.write(r.read(n))
267
267
268 def clone(ui, source, dest = None, **opts):
268 def clone(ui, source, dest = None, **opts):
269 """make a copy of an existing repository"""
269 """make a copy of an existing repository"""
270 paths = {}
270 paths = {}
271 for name, path in ui.configitems("paths"):
271 for name, path in ui.configitems("paths"):
272 paths[name] = path
272 paths[name] = path
273
273
274 if source in paths: source = paths[source]
274 if source in paths: source = paths[source]
275
275
276 created = success = False
276 created = success = False
277
277
278 if dest is None:
278 if dest is None:
279 dest = os.getcwd()
279 dest = os.getcwd()
280 elif not os.path.exists(dest):
280 elif not os.path.exists(dest):
281 os.mkdir(dest)
281 os.mkdir(dest)
282 created = True
282 created = True
283
283
284 try:
284 try:
285 dest = os.path.realpath(dest)
285 dest = os.path.realpath(dest)
286
286
287 link = 0
287 link = 0
288 if not source.startswith("http://"):
288 if not source.startswith("http://"):
289 source = os.path.realpath(source)
289 source = os.path.realpath(source)
290 d1 = os.stat(dest).st_dev
290 d1 = os.stat(dest).st_dev
291 d2 = os.stat(source).st_dev
291 d2 = os.stat(source).st_dev
292 if d1 == d2: link = 1
292 if d1 == d2: link = 1
293
293
294 os.chdir(dest)
294 os.chdir(dest)
295
295
296 if link:
296 if link:
297 ui.debug("copying by hardlink\n")
297 ui.debug("copying by hardlink\n")
298 os.system("cp -al %s/.hg .hg" % source)
298 os.system("cp -al %s/.hg .hg" % source)
299 try:
299 try:
300 os.remove(".hg/dirstate")
300 os.remove(".hg/dirstate")
301 except: pass
301 except: pass
302
302
303 repo = hg.repository(ui, ".")
303 repo = hg.repository(ui, ".")
304
304
305 else:
305 else:
306 repo = hg.repository(ui, ".", create=1)
306 repo = hg.repository(ui, ".", create=1)
307 other = hg.repository(ui, source)
307 other = hg.repository(ui, source)
308 cg = repo.getchangegroup(other)
308 cg = repo.getchangegroup(other)
309 repo.addchangegroup(cg)
309 repo.addchangegroup(cg)
310
310
311 f = repo.opener("hgrc", "w")
311 f = repo.opener("hgrc", "w")
312 f.write("[paths]\n")
312 f.write("[paths]\n")
313 f.write("default = %s\n" % source)
313 f.write("default = %s\n" % source)
314
314
315 if not opts['no-update']:
315 if not opts['noupdate']:
316 update(ui, repo)
316 update(ui, repo)
317
317
318 success = True
318 success = True
319
319
320 finally:
320 finally:
321 if not success:
321 if not success:
322 del repo
322 del repo
323 import shutil
323 import shutil
324 shutil.rmtree(dest, True)
324 shutil.rmtree(dest, True)
325
325
326 def commit(ui, repo, *files, **opts):
326 def commit(ui, repo, *files, **opts):
327 """commit the specified files or all outstanding changes"""
327 """commit the specified files or all outstanding changes"""
328 text = opts['text']
328 text = opts['text']
329 if not text and opts['logfile']:
329 if not text and opts['logfile']:
330 try: text = open(opts['logfile']).read()
330 try: text = open(opts['logfile']).read()
331 except IOError: pass
331 except IOError: pass
332
332
333 if opts['addremove']:
333 if opts['addremove']:
334 addremove(ui, repo, *files)
334 addremove(ui, repo, *files)
335 repo.commit(relpath(repo, files), text, opts['user'], opts['date'])
335 repo.commit(relpath(repo, files), text, opts['user'], opts['date'])
336
336
337 def copy(ui, repo, source, dest):
337 def copy(ui, repo, source, dest):
338 """mark a file as copied or renamed for the next commit"""
338 """mark a file as copied or renamed for the next commit"""
339 return repo.copy(*relpath(repo, (source, dest)))
339 return repo.copy(*relpath(repo, (source, dest)))
340
340
341 def debugcheckdirstate(ui, repo):
341 def debugcheckdirstate(ui, repo):
342 parent1, parent2 = repo.dirstate.parents()
342 parent1, parent2 = repo.dirstate.parents()
343 dc = repo.dirstate.dup()
343 dc = repo.dirstate.dup()
344 keys = dc.keys()
344 keys = dc.keys()
345 keys.sort()
345 keys.sort()
346 m1n = repo.changelog.read(parent1)[0]
346 m1n = repo.changelog.read(parent1)[0]
347 m2n = repo.changelog.read(parent2)[0]
347 m2n = repo.changelog.read(parent2)[0]
348 m1 = repo.manifest.read(m1n)
348 m1 = repo.manifest.read(m1n)
349 m2 = repo.manifest.read(m2n)
349 m2 = repo.manifest.read(m2n)
350 errors = 0
350 errors = 0
351 for f in dc:
351 for f in dc:
352 state = repo.dirstate.state(f)
352 state = repo.dirstate.state(f)
353 if state in "nr" and f not in m1:
353 if state in "nr" and f not in m1:
354 print "%s in state %s, but not listed in manifest1" % (f, state)
354 print "%s in state %s, but not listed in manifest1" % (f, state)
355 errors += 1
355 errors += 1
356 if state in "a" and f in m1:
356 if state in "a" and f in m1:
357 print "%s in state %s, but also listed in manifest1" % (f, state)
357 print "%s in state %s, but also listed in manifest1" % (f, state)
358 errors += 1
358 errors += 1
359 if state in "m" and f not in m1 and f not in m2:
359 if state in "m" and f not in m1 and f not in m2:
360 print "%s in state %s, but not listed in either manifest" % (f, state)
360 print "%s in state %s, but not listed in either manifest" % (f, state)
361 errors += 1
361 errors += 1
362 for f in m1:
362 for f in m1:
363 state = repo.dirstate.state(f)
363 state = repo.dirstate.state(f)
364 if state not in "nrm":
364 if state not in "nrm":
365 print "%s in manifest1, but listed as state %s" % (f, state)
365 print "%s in manifest1, but listed as state %s" % (f, state)
366 errors += 1
366 errors += 1
367 if errors:
367 if errors:
368 print ".hg/dirstate inconsistent with current parent's manifest, aborting"
368 print ".hg/dirstate inconsistent with current parent's manifest, aborting"
369 sys.exit(1)
369 sys.exit(1)
370
370
371 def debugdumpdirstate(ui, repo):
371 def debugdumpdirstate(ui, repo):
372 dc = repo.dirstate.dup()
372 dc = repo.dirstate.dup()
373 keys = dc.keys()
373 keys = dc.keys()
374 keys.sort()
374 keys.sort()
375 for file in keys:
375 for file in keys:
376 print "%s => %c" % (file, dc[file][0])
376 print "%s => %c" % (file, dc[file][0])
377
377
378 def debugindex(ui, file):
378 def debugindex(ui, file):
379 r = hg.revlog(hg.opener(""), file, "")
379 r = hg.revlog(hg.opener(""), file, "")
380 print " rev offset length base linkrev"+\
380 print " rev offset length base linkrev"+\
381 " p1 p2 nodeid"
381 " p1 p2 nodeid"
382 for i in range(r.count()):
382 for i in range(r.count()):
383 e = r.index[i]
383 e = r.index[i]
384 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
384 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
385 i, e[0], e[1], e[2], e[3],
385 i, e[0], e[1], e[2], e[3],
386 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
386 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
387
387
388 def debugindexdot(ui, file):
388 def debugindexdot(ui, file):
389 r = hg.revlog(hg.opener(""), file, "")
389 r = hg.revlog(hg.opener(""), file, "")
390 print "digraph G {"
390 print "digraph G {"
391 for i in range(r.count()):
391 for i in range(r.count()):
392 e = r.index[i]
392 e = r.index[i]
393 print "\t%d -> %d" % (r.rev(e[4]), i)
393 print "\t%d -> %d" % (r.rev(e[4]), i)
394 if e[5] != hg.nullid:
394 if e[5] != hg.nullid:
395 print "\t%d -> %d" % (r.rev(e[5]), i)
395 print "\t%d -> %d" % (r.rev(e[5]), i)
396 print "}"
396 print "}"
397
397
398 def diff(ui, repo, *files, **opts):
398 def diff(ui, repo, *files, **opts):
399 """diff working directory (or selected files)"""
399 """diff working directory (or selected files)"""
400 revs = []
400 revs = []
401 if opts['rev']:
401 if opts['rev']:
402 revs = map(lambda x: repo.lookup(x), opts['rev'])
402 revs = map(lambda x: repo.lookup(x), opts['rev'])
403
403
404 if len(revs) > 2:
404 if len(revs) > 2:
405 ui.warn("too many revisions to diff\n")
405 ui.warn("too many revisions to diff\n")
406 sys.exit(1)
406 sys.exit(1)
407
407
408 if files:
408 if files:
409 files = relpath(repo, files)
409 files = relpath(repo, files)
410 else:
410 else:
411 files = relpath(repo, [""])
411 files = relpath(repo, [""])
412
412
413 dodiff(ui, repo, os.getcwd(), files, *revs)
413 dodiff(ui, repo, os.getcwd(), files, *revs)
414
414
415 def export(ui, repo, changeset):
415 def export(ui, repo, changeset):
416 """dump the changeset header and diffs for a revision"""
416 """dump the changeset header and diffs for a revision"""
417 node = repo.lookup(changeset)
417 node = repo.lookup(changeset)
418 prev, other = repo.changelog.parents(node)
418 prev, other = repo.changelog.parents(node)
419 change = repo.changelog.read(node)
419 change = repo.changelog.read(node)
420 print "# HG changeset patch"
420 print "# HG changeset patch"
421 print "# User %s" % change[1]
421 print "# User %s" % change[1]
422 print "# Node ID %s" % hg.hex(node)
422 print "# Node ID %s" % hg.hex(node)
423 print "# Parent %s" % hg.hex(prev)
423 print "# Parent %s" % hg.hex(prev)
424 print
424 print
425 if other != hg.nullid:
425 if other != hg.nullid:
426 print "# Parent %s" % hg.hex(other)
426 print "# Parent %s" % hg.hex(other)
427 print change[4].rstrip()
427 print change[4].rstrip()
428 print
428 print
429
429
430 dodiff(ui, repo, "", None, prev, node)
430 dodiff(ui, repo, "", None, prev, node)
431
431
432 def forget(ui, repo, file, *files):
432 def forget(ui, repo, file, *files):
433 """don't add the specified files on the next commit"""
433 """don't add the specified files on the next commit"""
434 repo.forget(relpath(repo, (file,) + files))
434 repo.forget(relpath(repo, (file,) + files))
435
435
436 def heads(ui, repo):
436 def heads(ui, repo):
437 """show current repository heads"""
437 """show current repository heads"""
438 for n in repo.changelog.heads():
438 for n in repo.changelog.heads():
439 show_changeset(ui, repo, changenode=n)
439 show_changeset(ui, repo, changenode=n)
440
440
441 def history(ui, repo):
441 def history(ui, repo):
442 """show the changelog history"""
442 """show the changelog history"""
443 for i in range(repo.changelog.count() - 1, -1, -1):
443 for i in range(repo.changelog.count() - 1, -1, -1):
444 show_changeset(ui, repo, rev=i)
444 show_changeset(ui, repo, rev=i)
445
445
446 def identify(ui, repo):
446 def identify(ui, repo):
447 """print information about the working copy"""
447 """print information about the working copy"""
448 parents = [p for p in repo.dirstate.parents() if p != hg.nullid]
448 parents = [p for p in repo.dirstate.parents() if p != hg.nullid]
449 if not parents:
449 if not parents:
450 ui.write("unknown\n")
450 ui.write("unknown\n")
451 return
451 return
452
452
453 hexfunc = ui.verbose and hg.hex or hg.short
453 hexfunc = ui.verbose and hg.hex or hg.short
454 (c, a, d, u) = repo.diffdir(repo.root)
454 (c, a, d, u) = repo.diffdir(repo.root)
455 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
455 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
456 (c or a or d) and "+" or "")]
456 (c or a or d) and "+" or "")]
457
457
458 if not ui.quiet:
458 if not ui.quiet:
459 # multiple tags for a single parent separated by '/'
459 # multiple tags for a single parent separated by '/'
460 parenttags = ['/'.join(tags)
460 parenttags = ['/'.join(tags)
461 for tags in map(repo.nodetags, parents) if tags]
461 for tags in map(repo.nodetags, parents) if tags]
462 # tags for multiple parents separated by ' + '
462 # tags for multiple parents separated by ' + '
463 output.append(' + '.join(parenttags))
463 output.append(' + '.join(parenttags))
464
464
465 ui.write("%s\n" % ' '.join(output))
465 ui.write("%s\n" % ' '.join(output))
466
466
467 def import_(ui, repo, patch1, *patches, **opts):
467 def import_(ui, repo, patch1, *patches, **opts):
468 """import an ordered set of patches"""
468 """import an ordered set of patches"""
469 try:
469 try:
470 import psyco
470 import psyco
471 psyco.full()
471 psyco.full()
472 except:
472 except:
473 pass
473 pass
474
474
475 patches = (patch1,) + patches
475 patches = (patch1,) + patches
476
476
477 d = opts["base"]
477 d = opts["base"]
478 strip = opts["strip"]
478 strip = opts["strip"]
479
479
480 for patch in patches:
480 for patch in patches:
481 ui.status("applying %s\n" % patch)
481 ui.status("applying %s\n" % patch)
482 pf = os.path.join(d, patch)
482 pf = os.path.join(d, patch)
483
483
484 text = ""
484 text = ""
485 for l in file(pf):
485 for l in file(pf):
486 if l[:4] == "--- ": break
486 if l[:4] == "--- ": break
487 text += l
487 text += l
488
488
489 # make sure text isn't empty
489 # make sure text isn't empty
490 if not text: text = "imported patch %s\n" % patch
490 if not text: text = "imported patch %s\n" % patch
491
491
492 f = os.popen("patch -p%d < %s" % (strip, pf))
492 f = os.popen("patch -p%d < %s" % (strip, pf))
493 files = []
493 files = []
494 for l in f.read().splitlines():
494 for l in f.read().splitlines():
495 l.rstrip('\r\n');
495 l.rstrip('\r\n');
496 ui.status("%s\n" % l)
496 ui.status("%s\n" % l)
497 if l[:14] == 'patching file ':
497 if l[:14] == 'patching file ':
498 pf = l[14:]
498 pf = l[14:]
499 if pf not in files:
499 if pf not in files:
500 files.append(pf)
500 files.append(pf)
501 patcherr = f.close()
501 patcherr = f.close()
502 if patcherr:
502 if patcherr:
503 sys.stderr.write("patch failed")
503 sys.stderr.write("patch failed")
504 sys.exit(1)
504 sys.exit(1)
505
505
506 if len(files) > 0:
506 if len(files) > 0:
507 addremove(ui, repo, *files)
507 addremove(ui, repo, *files)
508 repo.commit(files, text)
508 repo.commit(files, text)
509
509
510 def init(ui, source=None):
510 def init(ui, source=None):
511 """create a new repository in the current directory"""
511 """create a new repository in the current directory"""
512
512
513 if source:
513 if source:
514 ui.warn("no longer supported: use \"hg clone\" instead\n")
514 ui.warn("no longer supported: use \"hg clone\" instead\n")
515 sys.exit(1)
515 sys.exit(1)
516 repo = hg.repository(ui, ".", create=1)
516 repo = hg.repository(ui, ".", create=1)
517
517
518 def log(ui, repo, f):
518 def log(ui, repo, f):
519 """show the revision history of a single file"""
519 """show the revision history of a single file"""
520 f = relpath(repo, [f])[0]
520 f = relpath(repo, [f])[0]
521
521
522 r = repo.file(f)
522 r = repo.file(f)
523 for i in range(r.count() - 1, -1, -1):
523 for i in range(r.count() - 1, -1, -1):
524 show_changeset(ui, repo, filelog=r, rev=i)
524 show_changeset(ui, repo, filelog=r, rev=i)
525
525
526 def manifest(ui, repo, rev = []):
526 def manifest(ui, repo, rev = []):
527 """output the latest or given revision of the project manifest"""
527 """output the latest or given revision of the project manifest"""
528 n = repo.manifest.tip()
528 n = repo.manifest.tip()
529 if rev:
529 if rev:
530 n = repo.manifest.lookup(rev)
530 n = repo.manifest.lookup(rev)
531 m = repo.manifest.read(n)
531 m = repo.manifest.read(n)
532 mf = repo.manifest.readflags(n)
532 mf = repo.manifest.readflags(n)
533 files = m.keys()
533 files = m.keys()
534 files.sort()
534 files.sort()
535
535
536 for f in files:
536 for f in files:
537 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
537 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
538
538
539 def parents(ui, repo, node = None):
539 def parents(ui, repo, node = None):
540 '''show the parents of the current working dir'''
540 '''show the parents of the current working dir'''
541 if node:
541 if node:
542 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
542 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
543 else:
543 else:
544 p = repo.dirstate.parents()
544 p = repo.dirstate.parents()
545
545
546 for n in p:
546 for n in p:
547 if n != hg.nullid:
547 if n != hg.nullid:
548 show_changeset(ui, repo, changenode=n)
548 show_changeset(ui, repo, changenode=n)
549
549
550 def pull(ui, repo, source="default", **opts):
550 def pull(ui, repo, source="default", **opts):
551 """pull changes from the specified source"""
551 """pull changes from the specified source"""
552 paths = {}
552 paths = {}
553 for name, path in ui.configitems("paths"):
553 for name, path in ui.configitems("paths"):
554 paths[name] = path
554 paths[name] = path
555
555
556 if source in paths:
556 if source in paths:
557 source = paths[source]
557 source = paths[source]
558
558
559 ui.status('pulling from %s\n' % (source))
559 ui.status('pulling from %s\n' % (source))
560
560
561 other = hg.repository(ui, source)
561 other = hg.repository(ui, source)
562 cg = repo.getchangegroup(other)
562 cg = repo.getchangegroup(other)
563 r = repo.addchangegroup(cg)
563 r = repo.addchangegroup(cg)
564 if cg and not r:
564 if cg and not r:
565 if opts['update']:
565 if opts['update']:
566 return update(ui, repo)
566 return update(ui, repo)
567 else:
567 else:
568 ui.status("(run 'hg update' to get a working copy)\n")
568 ui.status("(run 'hg update' to get a working copy)\n")
569
569
570 return r
570 return r
571
571
572 def push(ui, repo, dest="default-push"):
572 def push(ui, repo, dest="default-push"):
573 """push changes to the specified destination"""
573 """push changes to the specified destination"""
574 paths = {}
574 paths = {}
575 for name, path in ui.configitems("paths"):
575 for name, path in ui.configitems("paths"):
576 paths[name] = path
576 paths[name] = path
577
577
578 if dest in paths: dest = paths[dest]
578 if dest in paths: dest = paths[dest]
579
579
580 if not dest.startswith("ssh://"):
580 if not dest.startswith("ssh://"):
581 ui.warn("abort: can only push to ssh:// destinations currently\n")
581 ui.warn("abort: can only push to ssh:// destinations currently\n")
582 return 1
582 return 1
583
583
584 m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', dest)
584 m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', dest)
585 if not m:
585 if not m:
586 ui.warn("abort: couldn't parse destination %s\n" % dest)
586 ui.warn("abort: couldn't parse destination %s\n" % dest)
587 return 1
587 return 1
588
588
589 user, host, port, path = map(m.group, (2, 3, 5, 7))
589 user, host, port, path = map(m.group, (2, 3, 5, 7))
590 host = user and ("%s@%s" % (user, host)) or host
590 host = user and ("%s@%s" % (user, host)) or host
591 port = port and (" -p %s") % port or ""
591 port = port and (" -p %s") % port or ""
592 path = path or ""
592 path = path or ""
593
593
594 sport = random.randrange(30000, 60000)
594 sport = random.randrange(30000, 60000)
595 cmd = "ssh %s%s -R %d:localhost:%d 'cd %s; hg pull http://localhost:%d/'"
595 cmd = "ssh %s%s -R %d:localhost:%d 'cd %s; hg pull http://localhost:%d/'"
596 cmd = cmd % (host, port, sport+1, sport, path, sport+1)
596 cmd = cmd % (host, port, sport+1, sport, path, sport+1)
597
597
598 child = os.fork()
598 child = os.fork()
599 if not child:
599 if not child:
600 sys.stdout = file("/dev/null", "w")
600 sys.stdout = file("/dev/null", "w")
601 sys.stderr = sys.stdout
601 sys.stderr = sys.stdout
602 hgweb.server(repo.root, "pull", "", "localhost", sport)
602 hgweb.server(repo.root, "pull", "", "localhost", sport)
603 else:
603 else:
604 r = os.system(cmd)
604 r = os.system(cmd)
605 os.kill(child, signal.SIGTERM)
605 os.kill(child, signal.SIGTERM)
606 return r
606 return r
607
607
608 def rawcommit(ui, repo, *flist, **rc):
608 def rawcommit(ui, repo, *flist, **rc):
609 "raw commit interface"
609 "raw commit interface"
610
610
611 text = rc['text']
611 text = rc['text']
612 if not text and rc['logfile']:
612 if not text and rc['logfile']:
613 try: text = open(rc['logfile']).read()
613 try: text = open(rc['logfile']).read()
614 except IOError: pass
614 except IOError: pass
615 if not text and not rc['logfile']:
615 if not text and not rc['logfile']:
616 print "missing commit text"
616 print "missing commit text"
617 return 1
617 return 1
618
618
619 files = relpath(repo, list(flist))
619 files = relpath(repo, list(flist))
620 if rc['files']:
620 if rc['files']:
621 files += open(rc['files']).read().splitlines()
621 files += open(rc['files']).read().splitlines()
622
622
623 rc['parent'] = map(repo.lookup, rc['parent'])
623 rc['parent'] = map(repo.lookup, rc['parent'])
624
624
625 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
625 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
626
626
627 def recover(ui, repo):
627 def recover(ui, repo):
628 """roll back an interrupted transaction"""
628 """roll back an interrupted transaction"""
629 repo.recover()
629 repo.recover()
630
630
631 def remove(ui, repo, file, *files):
631 def remove(ui, repo, file, *files):
632 """remove the specified files on the next commit"""
632 """remove the specified files on the next commit"""
633 repo.remove(relpath(repo, (file,) + files))
633 repo.remove(relpath(repo, (file,) + files))
634
634
635 def root(ui, repo):
635 def root(ui, repo):
636 """print the root (top) of the current working dir"""
636 """print the root (top) of the current working dir"""
637 ui.write(repo.root + "\n")
637 ui.write(repo.root + "\n")
638
638
639 def serve(ui, repo, **opts):
639 def serve(ui, repo, **opts):
640 """export the repository via HTTP"""
640 """export the repository via HTTP"""
641 hgweb.server(repo.root, opts["name"], opts["templates"],
641 hgweb.server(repo.root, opts["name"], opts["templates"],
642 opts["address"], opts["port"])
642 opts["address"], opts["port"])
643
643
644 def status(ui, repo):
644 def status(ui, repo):
645 '''show changed files in the working directory
645 '''show changed files in the working directory
646
646
647 C = changed
647 C = changed
648 A = added
648 A = added
649 R = removed
649 R = removed
650 ? = not tracked'''
650 ? = not tracked'''
651
651
652 (c, a, d, u) = repo.diffdir(os.getcwd())
652 (c, a, d, u) = repo.diffdir(os.getcwd())
653 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
653 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
654
654
655 for f in c: print "C", f
655 for f in c: print "C", f
656 for f in a: print "A", f
656 for f in a: print "A", f
657 for f in d: print "R", f
657 for f in d: print "R", f
658 for f in u: print "?", f
658 for f in u: print "?", f
659
659
660 def tag(ui, repo, name, rev = None, **opts):
660 def tag(ui, repo, name, rev = None, **opts):
661 """add a tag for the current tip or a given revision"""
661 """add a tag for the current tip or a given revision"""
662
662
663 if name == "tip":
663 if name == "tip":
664 ui.warn("abort: 'tip' is a reserved name!\n")
664 ui.warn("abort: 'tip' is a reserved name!\n")
665 return -1
665 return -1
666
666
667 (c, a, d, u) = repo.diffdir(repo.root)
667 (c, a, d, u) = repo.diffdir(repo.root)
668 for x in (c, a, d, u):
668 for x in (c, a, d, u):
669 if ".hgtags" in x:
669 if ".hgtags" in x:
670 ui.warn("abort: working copy of .hgtags is changed!\n")
670 ui.warn("abort: working copy of .hgtags is changed!\n")
671 ui.status("(please commit .hgtags manually)\n")
671 ui.status("(please commit .hgtags manually)\n")
672 return -1
672 return -1
673
673
674 if rev:
674 if rev:
675 r = hg.hex(repo.lookup(rev))
675 r = hg.hex(repo.lookup(rev))
676 else:
676 else:
677 r = hg.hex(repo.changelog.tip())
677 r = hg.hex(repo.changelog.tip())
678
678
679 add = 0
679 add = 0
680 if not os.path.exists(repo.wjoin(".hgtags")): add = 1
680 if not os.path.exists(repo.wjoin(".hgtags")): add = 1
681 repo.wfile(".hgtags", "a").write("%s %s\n" % (r, name))
681 repo.wfile(".hgtags", "a").write("%s %s\n" % (r, name))
682 if add: repo.add([".hgtags"])
682 if add: repo.add([".hgtags"])
683
683
684 if not opts['text']:
684 if not opts['text']:
685 opts['text'] = "Added tag %s for changeset %s" % (name, r)
685 opts['text'] = "Added tag %s for changeset %s" % (name, r)
686
686
687 repo.commit([".hgtags"], opts['text'], opts['user'], opts['date'])
687 repo.commit([".hgtags"], opts['text'], opts['user'], opts['date'])
688
688
689 def tags(ui, repo):
689 def tags(ui, repo):
690 """list repository tags"""
690 """list repository tags"""
691
691
692 l = repo.tagslist()
692 l = repo.tagslist()
693 l.reverse()
693 l.reverse()
694 for t, n in l:
694 for t, n in l:
695 try:
695 try:
696 r = "%5d:%s" % (repo.changelog.rev(n), hg.hex(n))
696 r = "%5d:%s" % (repo.changelog.rev(n), hg.hex(n))
697 except KeyError:
697 except KeyError:
698 r = " ?:?"
698 r = " ?:?"
699 ui.write("%-30s %s\n" % (t, r))
699 ui.write("%-30s %s\n" % (t, r))
700
700
701 def tip(ui, repo):
701 def tip(ui, repo):
702 """show the tip revision"""
702 """show the tip revision"""
703 n = repo.changelog.tip()
703 n = repo.changelog.tip()
704 show_changeset(ui, repo, changenode=n)
704 show_changeset(ui, repo, changenode=n)
705
705
706 def undo(ui, repo):
706 def undo(ui, repo):
707 """undo the last transaction"""
707 """undo the last transaction"""
708 repo.undo()
708 repo.undo()
709
709
710 def update(ui, repo, node=None, merge=False, clean=False):
710 def update(ui, repo, node=None, merge=False, clean=False):
711 '''update or merge working directory
711 '''update or merge working directory
712
712
713 If there are no outstanding changes in the working directory and
713 If there are no outstanding changes in the working directory and
714 there is a linear relationship between the current version and the
714 there is a linear relationship between the current version and the
715 requested version, the result is the requested version.
715 requested version, the result is the requested version.
716
716
717 Otherwise the result is a merge between the contents of the
717 Otherwise the result is a merge between the contents of the
718 current working directory and the requested version. Files that
718 current working directory and the requested version. Files that
719 changed between either parent are marked as changed for the next
719 changed between either parent are marked as changed for the next
720 commit and a commit must be performed before any further updates
720 commit and a commit must be performed before any further updates
721 are allowed.
721 are allowed.
722 '''
722 '''
723 node = node and repo.lookup(node) or repo.changelog.tip()
723 node = node and repo.lookup(node) or repo.changelog.tip()
724 return repo.update(node, allow=merge, force=clean)
724 return repo.update(node, allow=merge, force=clean)
725
725
726 def verify(ui, repo):
726 def verify(ui, repo):
727 """verify the integrity of the repository"""
727 """verify the integrity of the repository"""
728 return repo.verify()
728 return repo.verify()
729
729
730 # Command options and aliases are listed here, alphabetically
730 # Command options and aliases are listed here, alphabetically
731
731
732 table = {
732 table = {
733 "add": (add, [], "hg add [files]"),
733 "add": (add, [], "hg add [files]"),
734 "addremove": (addremove, [], "hg addremove [files]"),
734 "addremove": (addremove, [], "hg addremove [files]"),
735 "annotate": (annotate,
735 "annotate": (annotate,
736 [('r', 'revision', '', 'revision'),
736 [('r', 'revision', '', 'revision'),
737 ('u', 'user', None, 'show user'),
737 ('u', 'user', None, 'show user'),
738 ('n', 'number', None, 'show revision number'),
738 ('n', 'number', None, 'show revision number'),
739 ('c', 'changeset', None, 'show changeset')],
739 ('c', 'changeset', None, 'show changeset')],
740 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
740 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
741 "cat": (cat, [], 'hg cat <file> [rev]'),
741 "cat": (cat, [], 'hg cat <file> [rev]'),
742 "clone": (clone, [('U', 'no-update', None, 'skip update after cloning')],
742 "clone": (clone, [('U', 'noupdate', None, 'skip update after cloning')],
743 'hg clone [options] <source> [dest]'),
743 'hg clone [options] <source> [dest]'),
744 "commit|ci": (commit,
744 "commit|ci": (commit,
745 [('t', 'text', "", 'commit text'),
745 [('t', 'text', "", 'commit text'),
746 ('A', 'addremove', None, 'run add/remove during commit'),
746 ('A', 'addremove', None, 'run add/remove during commit'),
747 ('l', 'logfile', "", 'commit text file'),
747 ('l', 'logfile', "", 'commit text file'),
748 ('d', 'date', "", 'data'),
748 ('d', 'date', "", 'data'),
749 ('u', 'user', "", 'user')],
749 ('u', 'user', "", 'user')],
750 'hg commit [files]'),
750 'hg commit [files]'),
751 "copy": (copy, [], 'hg copy <source> <dest>'),
751 "copy": (copy, [], 'hg copy <source> <dest>'),
752 "debugcheckdirstate": (debugcheckdirstate, [], 'debugcheckdirstate'),
752 "debugcheckdirstate": (debugcheckdirstate, [], 'debugcheckdirstate'),
753 "debugdumpdirstate": (debugdumpdirstate, [], 'debugdumpdirstate'),
753 "debugdumpdirstate": (debugdumpdirstate, [], 'debugdumpdirstate'),
754 "debugindex": (debugindex, [], 'debugindex <file>'),
754 "debugindex": (debugindex, [], 'debugindex <file>'),
755 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
755 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
756 "diff": (diff, [('r', 'rev', [], 'revision')],
756 "diff": (diff, [('r', 'rev', [], 'revision')],
757 'hg diff [-r A] [-r B] [files]'),
757 'hg diff [-r A] [-r B] [files]'),
758 "export": (export, [], "hg export <changeset>"),
758 "export": (export, [], "hg export <changeset>"),
759 "forget": (forget, [], "hg forget [files]"),
759 "forget": (forget, [], "hg forget [files]"),
760 "heads": (heads, [], 'hg heads'),
760 "heads": (heads, [], 'hg heads'),
761 "history": (history, [], 'hg history'),
761 "history": (history, [], 'hg history'),
762 "help": (help, [], 'hg help [command]'),
762 "help": (help, [], 'hg help [command]'),
763 "identify|id": (identify, [], 'hg identify'),
763 "identify|id": (identify, [], 'hg identify'),
764 "import|patch": (import_,
764 "import|patch": (import_,
765 [('p', 'strip', 1, 'path strip'),
765 [('p', 'strip', 1, 'path strip'),
766 ('b', 'base', "", 'base path')],
766 ('b', 'base', "", 'base path')],
767 "hg import [options] <patches>"),
767 "hg import [options] <patches>"),
768 "init": (init, [], 'hg init'),
768 "init": (init, [], 'hg init'),
769 "log": (log, [], 'hg log <file>'),
769 "log": (log, [], 'hg log <file>'),
770 "manifest": (manifest, [], 'hg manifest [rev]'),
770 "manifest": (manifest, [], 'hg manifest [rev]'),
771 "parents": (parents, [], 'hg parents [node]'),
771 "parents": (parents, [], 'hg parents [node]'),
772 "pull": (pull,
772 "pull": (pull,
773 [('u', 'update', None, 'update working directory')],
773 [('u', 'update', None, 'update working directory')],
774 'hg pull [options] [source]'),
774 'hg pull [options] [source]'),
775 "push": (push, [], 'hg push <destination>'),
775 "push": (push, [], 'hg push <destination>'),
776 "rawcommit": (rawcommit,
776 "rawcommit": (rawcommit,
777 [('p', 'parent', [], 'parent'),
777 [('p', 'parent', [], 'parent'),
778 ('d', 'date', "", 'data'),
778 ('d', 'date', "", 'data'),
779 ('u', 'user', "", 'user'),
779 ('u', 'user', "", 'user'),
780 ('F', 'files', "", 'file list'),
780 ('F', 'files', "", 'file list'),
781 ('t', 'text', "", 'commit text'),
781 ('t', 'text', "", 'commit text'),
782 ('l', 'logfile', "", 'commit text file')],
782 ('l', 'logfile', "", 'commit text file')],
783 'hg rawcommit [options] [files]'),
783 'hg rawcommit [options] [files]'),
784 "recover": (recover, [], "hg recover"),
784 "recover": (recover, [], "hg recover"),
785 "remove|rm": (remove, [], "hg remove [files]"),
785 "remove|rm": (remove, [], "hg remove [files]"),
786 "root": (root, [], "hg root"),
786 "root": (root, [], "hg root"),
787 "serve": (serve, [('p', 'port', 8000, 'listen port'),
787 "serve": (serve, [('p', 'port', 8000, 'listen port'),
788 ('a', 'address', '', 'interface address'),
788 ('a', 'address', '', 'interface address'),
789 ('n', 'name', os.getcwd(), 'repository name'),
789 ('n', 'name', os.getcwd(), 'repository name'),
790 ('t', 'templates', "", 'template map')],
790 ('t', 'templates', "", 'template map')],
791 "hg serve [options]"),
791 "hg serve [options]"),
792 "status": (status, [], 'hg status'),
792 "status": (status, [], 'hg status'),
793 "tag": (tag, [('t', 'text', "", 'commit text'),
793 "tag": (tag, [('t', 'text', "", 'commit text'),
794 ('d', 'date', "", 'date'),
794 ('d', 'date', "", 'date'),
795 ('u', 'user', "", 'user')],
795 ('u', 'user', "", 'user')],
796 'hg tag [options] <name> [rev]'),
796 'hg tag [options] <name> [rev]'),
797 "tags": (tags, [], 'hg tags'),
797 "tags": (tags, [], 'hg tags'),
798 "tip": (tip, [], 'hg tip'),
798 "tip": (tip, [], 'hg tip'),
799 "undo": (undo, [], 'hg undo'),
799 "undo": (undo, [], 'hg undo'),
800 "update|up|checkout|co":
800 "update|up|checkout|co":
801 (update,
801 (update,
802 [('m', 'merge', None, 'allow merging of conflicts'),
802 [('m', 'merge', None, 'allow merging of conflicts'),
803 ('C', 'clean', None, 'overwrite locally modified files')],
803 ('C', 'clean', None, 'overwrite locally modified files')],
804 'hg update [options] [node]'),
804 'hg update [options] [node]'),
805 "verify": (verify, [], 'hg verify'),
805 "verify": (verify, [], 'hg verify'),
806 "version": (show_version, [], 'hg version'),
806 "version": (show_version, [], 'hg version'),
807 }
807 }
808
808
809 norepo = "clone init version help debugindex debugindexdot"
809 norepo = "clone init version help debugindex debugindexdot"
810
810
811 def find(cmd):
811 def find(cmd):
812 for e in table.keys():
812 for e in table.keys():
813 if re.match("(%s)$" % e, cmd):
813 if re.match("(%s)$" % e, cmd):
814 return table[e]
814 return table[e]
815
815
816 raise UnknownCommand(cmd)
816 raise UnknownCommand(cmd)
817
817
818 class SignalInterrupt(Exception): pass
818 class SignalInterrupt(Exception): pass
819
819
820 def catchterm(*args):
820 def catchterm(*args):
821 raise SignalInterrupt
821 raise SignalInterrupt
822
822
823 def run():
823 def run():
824 sys.exit(dispatch(sys.argv[1:]))
824 sys.exit(dispatch(sys.argv[1:]))
825
825
826 def dispatch(args):
826 def dispatch(args):
827 options = {}
827 options = {}
828 opts = [('v', 'verbose', None, 'verbose'),
828 opts = [('v', 'verbose', None, 'verbose'),
829 ('d', 'debug', None, 'debug'),
829 ('d', 'debug', None, 'debug'),
830 ('q', 'quiet', None, 'quiet'),
830 ('q', 'quiet', None, 'quiet'),
831 ('p', 'profile', None, 'profile'),
831 ('p', 'profile', None, 'profile'),
832 ('y', 'noninteractive', None, 'run non-interactively'),
832 ('y', 'noninteractive', None, 'run non-interactively'),
833 ('', 'version', None, 'output version information and exit'),
833 ('', 'version', None, 'output version information and exit'),
834 ]
834 ]
835
835
836 args = fancyopts.fancyopts(args, opts, options,
836 args = fancyopts.fancyopts(args, opts, options,
837 'hg [options] <command> [options] [files]')
837 'hg [options] <command> [options] [files]')
838
838
839 if not args:
839 if not args:
840 cmd = "help"
840 cmd = "help"
841 else:
841 else:
842 cmd, args = args[0], args[1:]
842 cmd, args = args[0], args[1:]
843
843
844 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
844 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
845 not options["noninteractive"])
845 not options["noninteractive"])
846
846
847 if options["version"]:
847 if options["version"]:
848 show_version(u)
848 show_version(u)
849 sys.exit(0)
849 sys.exit(0)
850
850
851 try:
851 try:
852 i = find(cmd)
852 i = find(cmd)
853 except UnknownCommand:
853 except UnknownCommand:
854 u.warn("hg: unknown command '%s'\n" % cmd)
854 u.warn("hg: unknown command '%s'\n" % cmd)
855 help(u)
855 help(u)
856 sys.exit(1)
856 sys.exit(1)
857
857
858 signal.signal(signal.SIGTERM, catchterm)
858 signal.signal(signal.SIGTERM, catchterm)
859
859
860 cmdoptions = {}
860 cmdoptions = {}
861 try:
861 try:
862 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
862 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
863 except fancyopts.getopt.GetoptError, inst:
863 except fancyopts.getopt.GetoptError, inst:
864 u.warn("hg %s: %s\n" % (cmd, inst))
864 u.warn("hg %s: %s\n" % (cmd, inst))
865 help(u, cmd)
865 help(u, cmd)
866 sys.exit(-1)
866 sys.exit(-1)
867
867
868 try:
868 try:
869 if cmd not in norepo.split():
869 if cmd not in norepo.split():
870 repo = hg.repository(ui = u)
870 repo = hg.repository(ui = u)
871 d = lambda: i[0](u, repo, *args, **cmdoptions)
871 d = lambda: i[0](u, repo, *args, **cmdoptions)
872 else:
872 else:
873 d = lambda: i[0](u, *args, **cmdoptions)
873 d = lambda: i[0](u, *args, **cmdoptions)
874
874
875 if options['profile']:
875 if options['profile']:
876 import hotshot, hotshot.stats
876 import hotshot, hotshot.stats
877 prof = hotshot.Profile("hg.prof")
877 prof = hotshot.Profile("hg.prof")
878 r = prof.runcall(d)
878 r = prof.runcall(d)
879 prof.close()
879 prof.close()
880 stats = hotshot.stats.load("hg.prof")
880 stats = hotshot.stats.load("hg.prof")
881 stats.strip_dirs()
881 stats.strip_dirs()
882 stats.sort_stats('time', 'calls')
882 stats.sort_stats('time', 'calls')
883 stats.print_stats(40)
883 stats.print_stats(40)
884 return r
884 return r
885 else:
885 else:
886 return d()
886 return d()
887 except hg.RepoError, inst:
887 except hg.RepoError, inst:
888 u.warn("abort: ", inst, "!\n")
888 u.warn("abort: ", inst, "!\n")
889 except SignalInterrupt:
889 except SignalInterrupt:
890 u.warn("killed!\n")
890 u.warn("killed!\n")
891 except KeyboardInterrupt:
891 except KeyboardInterrupt:
892 u.warn("interrupted!\n")
892 u.warn("interrupted!\n")
893 except IOError, inst:
893 except IOError, inst:
894 if hasattr(inst, "code"):
894 if hasattr(inst, "code"):
895 u.warn("abort: %s\n" % inst)
895 u.warn("abort: %s\n" % inst)
896 elif hasattr(inst, "reason"):
896 elif hasattr(inst, "reason"):
897 u.warn("abort: error %d: %s\n" % (inst.reason[0], inst.reason[1]))
897 u.warn("abort: error %d: %s\n" % (inst.reason[0], inst.reason[1]))
898 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
898 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
899 u.warn("broken pipe\n")
899 u.warn("broken pipe\n")
900 else:
900 else:
901 raise
901 raise
902 except TypeError, inst:
902 except TypeError, inst:
903 # was this an argument error?
903 # was this an argument error?
904 tb = traceback.extract_tb(sys.exc_info()[2])
904 tb = traceback.extract_tb(sys.exc_info()[2])
905 if len(tb) > 2: # no
905 if len(tb) > 2: # no
906 raise
906 raise
907 u.debug(inst, "\n")
907 u.debug(inst, "\n")
908 u.warn("%s: invalid arguments\n" % i[0].__name__)
908 u.warn("%s: invalid arguments\n" % i[0].__name__)
909 help(u, cmd)
909 help(u, cmd)
910
910
911 sys.exit(-1)
911 sys.exit(-1)
912
912
General Comments 0
You need to be logged in to leave comments. Login now