##// END OF EJS Templates
serve: rename --daemon-pipefds to --daemon-postexec (BC)...
Jun Wu -
r28194:7623ba92 default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,466 +1,466 b''
1 1 /*
2 2 * A fast client for Mercurial command server
3 3 *
4 4 * Copyright (c) 2011 Yuya Nishihara <yuya@tcha.org>
5 5 *
6 6 * This software may be used and distributed according to the terms of the
7 7 * GNU General Public License version 2 or any later version.
8 8 */
9 9
10 10 #include <assert.h>
11 11 #include <errno.h>
12 12 #include <fcntl.h>
13 13 #include <signal.h>
14 14 #include <stdio.h>
15 15 #include <stdlib.h>
16 16 #include <string.h>
17 17 #include <sys/stat.h>
18 18 #include <sys/types.h>
19 19 #include <sys/un.h>
20 20 #include <sys/wait.h>
21 21 #include <time.h>
22 22 #include <unistd.h>
23 23
24 24 #include "hgclient.h"
25 25 #include "util.h"
26 26
27 27 #ifndef UNIX_PATH_MAX
28 28 #define UNIX_PATH_MAX (sizeof(((struct sockaddr_un *)NULL)->sun_path))
29 29 #endif
30 30
31 31 struct cmdserveropts {
32 32 char sockname[UNIX_PATH_MAX];
33 33 char lockfile[UNIX_PATH_MAX];
34 34 char pidfile[UNIX_PATH_MAX];
35 35 size_t argsize;
36 36 const char **args;
37 37 };
38 38
39 39 static void initcmdserveropts(struct cmdserveropts *opts) {
40 40 memset(opts, 0, sizeof(struct cmdserveropts));
41 41 }
42 42
43 43 static void freecmdserveropts(struct cmdserveropts *opts) {
44 44 free(opts->args);
45 45 opts->args = NULL;
46 46 opts->argsize = 0;
47 47 }
48 48
49 49 /*
50 50 * Test if an argument is a sensitive flag that should be passed to the server.
51 51 * Return 0 if not, otherwise the number of arguments starting from the current
52 52 * one that should be passed to the server.
53 53 */
54 54 static size_t testsensitiveflag(const char *arg)
55 55 {
56 56 static const struct {
57 57 const char *name;
58 58 size_t narg;
59 59 } flags[] = {
60 60 {"--config", 1},
61 61 {"--cwd", 1},
62 62 {"--repo", 1},
63 63 {"--repository", 1},
64 64 {"--traceback", 0},
65 65 {"-R", 1},
66 66 };
67 67 size_t i;
68 68 for (i = 0; i < sizeof(flags) / sizeof(flags[0]); ++i) {
69 69 size_t len = strlen(flags[i].name);
70 70 size_t narg = flags[i].narg;
71 71 if (memcmp(arg, flags[i].name, len) == 0) {
72 72 if (arg[len] == '\0') { /* --flag (value) */
73 73 return narg + 1;
74 74 } else if (arg[len] == '=' && narg > 0) { /* --flag=value */
75 75 return 1;
76 76 } else if (flags[i].name[1] != '-') { /* short flag */
77 77 return 1;
78 78 }
79 79 }
80 80 }
81 81 return 0;
82 82 }
83 83
84 84 /*
85 85 * Parse argv[] and put sensitive flags to opts->args
86 86 */
87 87 static void setcmdserverargs(struct cmdserveropts *opts,
88 88 int argc, const char *argv[])
89 89 {
90 90 size_t i, step;
91 91 opts->argsize = 0;
92 92 for (i = 0, step = 1; i < (size_t)argc; i += step, step = 1) {
93 93 if (!argv[i])
94 94 continue; /* pass clang-analyse */
95 95 if (strcmp(argv[i], "--") == 0)
96 96 break;
97 97 size_t n = testsensitiveflag(argv[i]);
98 98 if (n == 0 || i + n > (size_t)argc)
99 99 continue;
100 100 opts->args = reallocx(opts->args,
101 101 (n + opts->argsize) * sizeof(char *));
102 102 memcpy(opts->args + opts->argsize, argv + i,
103 103 sizeof(char *) * n);
104 104 opts->argsize += n;
105 105 step = n;
106 106 }
107 107 }
108 108
109 109 static void preparesockdir(const char *sockdir)
110 110 {
111 111 int r;
112 112 r = mkdir(sockdir, 0700);
113 113 if (r < 0 && errno != EEXIST)
114 114 abortmsg("cannot create sockdir %s (errno = %d)",
115 115 sockdir, errno);
116 116
117 117 struct stat st;
118 118 r = lstat(sockdir, &st);
119 119 if (r < 0)
120 120 abortmsg("cannot stat %s (errno = %d)", sockdir, errno);
121 121 if (!S_ISDIR(st.st_mode))
122 122 abortmsg("cannot create sockdir %s (file exists)", sockdir);
123 123 if (st.st_uid != geteuid() || st.st_mode & 0077)
124 124 abortmsg("insecure sockdir %s", sockdir);
125 125 }
126 126
127 127 static void setcmdserveropts(struct cmdserveropts *opts)
128 128 {
129 129 int r;
130 130 char sockdir[UNIX_PATH_MAX];
131 131 const char *envsockname = getenv("CHGSOCKNAME");
132 132 if (!envsockname) {
133 133 /* by default, put socket file in secure directory
134 134 * (permission of socket file may be ignored on some Unices) */
135 135 const char *tmpdir = getenv("TMPDIR");
136 136 if (!tmpdir)
137 137 tmpdir = "/tmp";
138 138 r = snprintf(sockdir, sizeof(sockdir), "%s/chg%d",
139 139 tmpdir, geteuid());
140 140 if (r < 0 || (size_t)r >= sizeof(sockdir))
141 141 abortmsg("too long TMPDIR (r = %d)", r);
142 142 preparesockdir(sockdir);
143 143 }
144 144
145 145 const char *basename = (envsockname) ? envsockname : sockdir;
146 146 const char *sockfmt = (envsockname) ? "%s" : "%s/server";
147 147 const char *lockfmt = (envsockname) ? "%s.lock" : "%s/lock";
148 148 const char *pidfmt = (envsockname) ? "%s.pid" : "%s/pid";
149 149 r = snprintf(opts->sockname, sizeof(opts->sockname), sockfmt, basename);
150 150 if (r < 0 || (size_t)r >= sizeof(opts->sockname))
151 151 abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
152 152 r = snprintf(opts->lockfile, sizeof(opts->lockfile), lockfmt, basename);
153 153 if (r < 0 || (size_t)r >= sizeof(opts->lockfile))
154 154 abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
155 155 r = snprintf(opts->pidfile, sizeof(opts->pidfile), pidfmt, basename);
156 156 if (r < 0 || (size_t)r >= sizeof(opts->pidfile))
157 157 abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
158 158 }
159 159
160 160 /*
161 161 * Make lock file that indicates cmdserver process is about to start. Created
162 162 * lock file will be deleted by server. (0: success, -1: lock exists)
163 163 */
164 164 static int lockcmdserver(const struct cmdserveropts *opts)
165 165 {
166 166 int r;
167 167 char info[32];
168 168 r = snprintf(info, sizeof(info), "%d", getpid());
169 169 if (r < 0 || (size_t)r >= sizeof(info))
170 170 abortmsg("failed to format lock info");
171 171 r = symlink(info, opts->lockfile);
172 172 if (r < 0 && errno != EEXIST)
173 173 abortmsg("failed to make lock %s (errno = %d)",
174 174 opts->lockfile, errno);
175 175 return r;
176 176 }
177 177
178 178 static void execcmdserver(const struct cmdserveropts *opts)
179 179 {
180 180 const char *hgcmd = getenv("CHGHG");
181 181 if (!hgcmd || hgcmd[0] == '\0')
182 182 hgcmd = getenv("HG");
183 183 if (!hgcmd || hgcmd[0] == '\0')
184 184 hgcmd = "hg";
185 185
186 186 const char *baseargv[] = {
187 187 hgcmd,
188 188 "serve",
189 189 "--cwd", "/",
190 190 "--cmdserver", "chgunix",
191 191 "--address", opts->sockname,
192 "--daemon-pipefds", opts->lockfile,
192 "--daemon-postexec", opts->lockfile,
193 193 "--pid-file", opts->pidfile,
194 194 "--config", "extensions.chgserver=",
195 195 /* wrap root ui so that it can be disabled/enabled by config */
196 196 "--config", "progress.assume-tty=1",
197 197 };
198 198 size_t baseargvsize = sizeof(baseargv) / sizeof(baseargv[0]);
199 199 size_t argsize = baseargvsize + opts->argsize + 1;
200 200
201 201 const char **argv = mallocx(sizeof(char *) * argsize);
202 202 memcpy(argv, baseargv, sizeof(baseargv));
203 203 memcpy(argv + baseargvsize, opts->args, sizeof(char *) * opts->argsize);
204 204 argv[argsize - 1] = NULL;
205 205
206 206 if (execvp(hgcmd, (char **)argv) < 0)
207 207 abortmsg("failed to exec cmdserver (errno = %d)", errno);
208 208 free(argv);
209 209 }
210 210
211 211 /*
212 212 * Sleep until lock file is deleted, i.e. cmdserver process starts listening.
213 213 * If pid is given, it also checks if the child process fails to start.
214 214 */
215 215 static void waitcmdserver(const struct cmdserveropts *opts, pid_t pid)
216 216 {
217 217 static const struct timespec sleepreq = {0, 10 * 1000000};
218 218 int pst = 0;
219 219
220 220 for (unsigned int i = 0; i < 10 * 100; i++) {
221 221 int r;
222 222 struct stat lst;
223 223
224 224 r = lstat(opts->lockfile, &lst);
225 225 if (r < 0 && errno == ENOENT)
226 226 return; /* lock file deleted by server */
227 227 if (r < 0)
228 228 goto cleanup;
229 229
230 230 if (pid > 0) {
231 231 /* collect zombie if child process fails to start */
232 232 r = waitpid(pid, &pst, WNOHANG);
233 233 if (r != 0)
234 234 goto cleanup;
235 235 }
236 236
237 237 nanosleep(&sleepreq, NULL);
238 238 }
239 239
240 240 abortmsg("timed out waiting for cmdserver %s", opts->lockfile);
241 241 return;
242 242
243 243 cleanup:
244 244 if (pid > 0)
245 245 /* lockfile should be made by this process */
246 246 unlink(opts->lockfile);
247 247 if (WIFEXITED(pst)) {
248 248 abortmsg("cmdserver exited with status %d", WEXITSTATUS(pst));
249 249 } else if (WIFSIGNALED(pst)) {
250 250 abortmsg("cmdserver killed by signal %d", WTERMSIG(pst));
251 251 } else {
252 252 abortmsg("error white waiting cmdserver");
253 253 }
254 254 }
255 255
256 256 /* Spawn new background cmdserver */
257 257 static void startcmdserver(const struct cmdserveropts *opts)
258 258 {
259 259 debugmsg("start cmdserver at %s", opts->sockname);
260 260
261 261 if (lockcmdserver(opts) < 0) {
262 262 debugmsg("lock file exists, waiting...");
263 263 waitcmdserver(opts, 0);
264 264 return;
265 265 }
266 266
267 267 /* remove dead cmdserver socket if any */
268 268 unlink(opts->sockname);
269 269
270 270 pid_t pid = fork();
271 271 if (pid < 0)
272 272 abortmsg("failed to fork cmdserver process");
273 273 if (pid == 0) {
274 274 /* bypass uisetup() of pager extension */
275 275 int nullfd = open("/dev/null", O_WRONLY);
276 276 if (nullfd >= 0) {
277 277 dup2(nullfd, fileno(stdout));
278 278 close(nullfd);
279 279 }
280 280 execcmdserver(opts);
281 281 } else {
282 282 waitcmdserver(opts, pid);
283 283 }
284 284 }
285 285
286 286 static void killcmdserver(const struct cmdserveropts *opts, int sig)
287 287 {
288 288 FILE *fp = fopen(opts->pidfile, "r");
289 289 if (!fp)
290 290 abortmsg("cannot open %s (errno = %d)", opts->pidfile, errno);
291 291 int pid = 0;
292 292 int n = fscanf(fp, "%d", &pid);
293 293 fclose(fp);
294 294 if (n != 1 || pid <= 0)
295 295 abortmsg("cannot read pid from %s", opts->pidfile);
296 296
297 297 if (kill((pid_t)pid, sig) < 0) {
298 298 if (errno == ESRCH)
299 299 return;
300 300 abortmsg("cannot kill %d (errno = %d)", pid, errno);
301 301 }
302 302 }
303 303
304 304 static pid_t peerpid = 0;
305 305
306 306 static void forwardsignal(int sig)
307 307 {
308 308 assert(peerpid > 0);
309 309 if (kill(peerpid, sig) < 0)
310 310 abortmsg("cannot kill %d (errno = %d)", peerpid, errno);
311 311 debugmsg("forward signal %d", sig);
312 312 }
313 313
314 314 static void handlestopsignal(int sig)
315 315 {
316 316 sigset_t unblockset, oldset;
317 317 struct sigaction sa, oldsa;
318 318 if (sigemptyset(&unblockset) < 0)
319 319 goto error;
320 320 if (sigaddset(&unblockset, sig) < 0)
321 321 goto error;
322 322 memset(&sa, 0, sizeof(sa));
323 323 sa.sa_handler = SIG_DFL;
324 324 sa.sa_flags = SA_RESTART;
325 325 if (sigemptyset(&sa.sa_mask) < 0)
326 326 goto error;
327 327
328 328 forwardsignal(sig);
329 329 if (raise(sig) < 0) /* resend to self */
330 330 goto error;
331 331 if (sigaction(sig, &sa, &oldsa) < 0)
332 332 goto error;
333 333 if (sigprocmask(SIG_UNBLOCK, &unblockset, &oldset) < 0)
334 334 goto error;
335 335 /* resent signal will be handled before sigprocmask() returns */
336 336 if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0)
337 337 goto error;
338 338 if (sigaction(sig, &oldsa, NULL) < 0)
339 339 goto error;
340 340 return;
341 341
342 342 error:
343 343 abortmsg("failed to handle stop signal (errno = %d)", errno);
344 344 }
345 345
346 346 static void setupsignalhandler(pid_t pid)
347 347 {
348 348 if (pid <= 0)
349 349 return;
350 350 peerpid = pid;
351 351
352 352 struct sigaction sa;
353 353 memset(&sa, 0, sizeof(sa));
354 354 sa.sa_handler = forwardsignal;
355 355 sa.sa_flags = SA_RESTART;
356 356 if (sigemptyset(&sa.sa_mask) < 0)
357 357 goto error;
358 358
359 359 if (sigaction(SIGHUP, &sa, NULL) < 0)
360 360 goto error;
361 361 if (sigaction(SIGINT, &sa, NULL) < 0)
362 362 goto error;
363 363
364 364 /* terminate frontend by double SIGTERM in case of server freeze */
365 365 sa.sa_flags |= SA_RESETHAND;
366 366 if (sigaction(SIGTERM, &sa, NULL) < 0)
367 367 goto error;
368 368
369 369 /* propagate job control requests to worker */
370 370 sa.sa_handler = forwardsignal;
371 371 sa.sa_flags = SA_RESTART;
372 372 if (sigaction(SIGCONT, &sa, NULL) < 0)
373 373 goto error;
374 374 sa.sa_handler = handlestopsignal;
375 375 sa.sa_flags = SA_RESTART;
376 376 if (sigaction(SIGTSTP, &sa, NULL) < 0)
377 377 goto error;
378 378
379 379 return;
380 380
381 381 error:
382 382 abortmsg("failed to set up signal handlers (errno = %d)", errno);
383 383 }
384 384
385 385 /* This implementation is based on hgext/pager.py (pre 369741ef7253) */
386 386 static void setuppager(hgclient_t *hgc, const char *const args[],
387 387 size_t argsize)
388 388 {
389 389 const char *pagercmd = hgc_getpager(hgc, args, argsize);
390 390 if (!pagercmd)
391 391 return;
392 392
393 393 int pipefds[2];
394 394 if (pipe(pipefds) < 0)
395 395 return;
396 396 pid_t pid = fork();
397 397 if (pid < 0)
398 398 goto error;
399 399 if (pid == 0) {
400 400 close(pipefds[0]);
401 401 if (dup2(pipefds[1], fileno(stdout)) < 0)
402 402 goto error;
403 403 if (isatty(fileno(stderr))) {
404 404 if (dup2(pipefds[1], fileno(stderr)) < 0)
405 405 goto error;
406 406 }
407 407 close(pipefds[1]);
408 408 hgc_attachio(hgc); /* reattach to pager */
409 409 return;
410 410 } else {
411 411 dup2(pipefds[0], fileno(stdin));
412 412 close(pipefds[0]);
413 413 close(pipefds[1]);
414 414
415 415 int r = execlp("/bin/sh", "/bin/sh", "-c", pagercmd, NULL);
416 416 if (r < 0) {
417 417 abortmsg("cannot start pager '%s' (errno = %d)",
418 418 pagercmd, errno);
419 419 }
420 420 return;
421 421 }
422 422
423 423 error:
424 424 close(pipefds[0]);
425 425 close(pipefds[1]);
426 426 abortmsg("failed to prepare pager (errno = %d)", errno);
427 427 }
428 428
429 429 int main(int argc, const char *argv[], const char *envp[])
430 430 {
431 431 if (getenv("CHGDEBUG"))
432 432 enabledebugmsg();
433 433
434 434 struct cmdserveropts opts;
435 435 initcmdserveropts(&opts);
436 436 setcmdserveropts(&opts);
437 437 setcmdserverargs(&opts, argc, argv);
438 438
439 439 if (argc == 2) {
440 440 int sig = 0;
441 441 if (strcmp(argv[1], "--kill-chg-daemon") == 0)
442 442 sig = SIGTERM;
443 443 if (strcmp(argv[1], "--reload-chg-daemon") == 0)
444 444 sig = SIGHUP;
445 445 if (sig > 0) {
446 446 killcmdserver(&opts, sig);
447 447 return 0;
448 448 }
449 449 }
450 450
451 451 hgclient_t *hgc = hgc_open(opts.sockname);
452 452 if (!hgc) {
453 453 startcmdserver(&opts);
454 454 hgc = hgc_open(opts.sockname);
455 455 }
456 456 if (!hgc)
457 457 abortmsg("cannot open hg client");
458 458
459 459 setupsignalhandler(hgc_peerpid(hgc));
460 460 hgc_setenv(hgc, envp);
461 461 setuppager(hgc, argv + 1, argc - 1);
462 462 int exitcode = hgc_runcommand(hgc, argv + 1, argc - 1);
463 463 hgc_close(hgc);
464 464 freecmdserveropts(&opts);
465 465 return exitcode;
466 466 }
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,55 +1,55 b''
1 1 #!/usr/bin/env python
2 2
3 3 from __future__ import absolute_import
4 4
5 5 """
6 6 Small and dumb HTTP server for use in tests.
7 7 """
8 8
9 9 import optparse
10 10 import BaseHTTPServer
11 11 import signal
12 12 import SimpleHTTPServer
13 13 import sys
14 14
15 15 from mercurial import (
16 16 cmdutil,
17 17 )
18 18
19 19 OptionParser = optparse.OptionParser
20 20
21 21 class simplehttpservice(object):
22 22 def __init__(self, host, port):
23 23 self.address = (host, port)
24 24 def init(self):
25 25 self.httpd = BaseHTTPServer.HTTPServer(
26 26 self.address, SimpleHTTPServer.SimpleHTTPRequestHandler)
27 27 def run(self):
28 28 self.httpd.serve_forever()
29 29
30 30 if __name__ == '__main__':
31 31 parser = OptionParser()
32 32 parser.add_option('-p', '--port', dest='port', type='int', default=8000,
33 33 help='TCP port to listen on', metavar='PORT')
34 34 parser.add_option('-H', '--host', dest='host', default='localhost',
35 35 help='hostname or IP to listen on', metavar='HOST')
36 36 parser.add_option('--pid', dest='pid',
37 37 help='file name where the PID of the server is stored')
38 38 parser.add_option('-f', '--foreground', dest='foreground',
39 39 action='store_true',
40 40 help='do not start the HTTP server in the background')
41 parser.add_option('--daemon-pipefds')
41 parser.add_option('--daemon-postexec')
42 42
43 43 (options, args) = parser.parse_args()
44 44
45 45 signal.signal(signal.SIGTERM, lambda x, y: sys.exit(0))
46 46
47 47 if options.foreground and options.pid:
48 48 parser.error("options --pid and --foreground are mutually exclusive")
49 49
50 50 opts = {'pid_file': options.pid,
51 51 'daemon': not options.foreground,
52 'daemon_pipefds': options.daemon_pipefds}
52 'daemon_postexec': options.daemon_postexec}
53 53 service = simplehttpservice(options.host, options.port)
54 54 cmdutil.service(opts, initfn=service.init, runfn=service.run,
55 55 runargs=[sys.executable, __file__] + sys.argv[1:])
@@ -1,350 +1,350 b''
1 1 Show all commands except debug commands
2 2 $ hg debugcomplete
3 3 add
4 4 addremove
5 5 annotate
6 6 archive
7 7 backout
8 8 bisect
9 9 bookmarks
10 10 branch
11 11 branches
12 12 bundle
13 13 cat
14 14 clone
15 15 commit
16 16 config
17 17 copy
18 18 diff
19 19 export
20 20 files
21 21 forget
22 22 graft
23 23 grep
24 24 heads
25 25 help
26 26 identify
27 27 import
28 28 incoming
29 29 init
30 30 locate
31 31 log
32 32 manifest
33 33 merge
34 34 outgoing
35 35 parents
36 36 paths
37 37 phase
38 38 pull
39 39 push
40 40 recover
41 41 remove
42 42 rename
43 43 resolve
44 44 revert
45 45 rollback
46 46 root
47 47 serve
48 48 status
49 49 summary
50 50 tag
51 51 tags
52 52 tip
53 53 unbundle
54 54 update
55 55 verify
56 56 version
57 57
58 58 Show all commands that start with "a"
59 59 $ hg debugcomplete a
60 60 add
61 61 addremove
62 62 annotate
63 63 archive
64 64
65 65 Do not show debug commands if there are other candidates
66 66 $ hg debugcomplete d
67 67 diff
68 68
69 69 Show debug commands if there are no other candidates
70 70 $ hg debugcomplete debug
71 71 debugancestor
72 72 debugapplystreamclonebundle
73 73 debugbuilddag
74 74 debugbundle
75 75 debugcheckstate
76 76 debugcommands
77 77 debugcomplete
78 78 debugconfig
79 79 debugcreatestreamclonebundle
80 80 debugdag
81 81 debugdata
82 82 debugdate
83 83 debugdeltachain
84 84 debugdirstate
85 85 debugdiscovery
86 86 debugextensions
87 87 debugfileset
88 88 debugfsinfo
89 89 debuggetbundle
90 90 debugignore
91 91 debugindex
92 92 debugindexdot
93 93 debuginstall
94 94 debugknown
95 95 debuglabelcomplete
96 96 debuglocks
97 97 debugmergestate
98 98 debugnamecomplete
99 99 debugobsolete
100 100 debugpathcomplete
101 101 debugpushkey
102 102 debugpvec
103 103 debugrebuilddirstate
104 104 debugrebuildfncache
105 105 debugrename
106 106 debugrevlog
107 107 debugrevspec
108 108 debugsetparents
109 109 debugsub
110 110 debugsuccessorssets
111 111 debugwalk
112 112 debugwireargs
113 113
114 114 Do not show the alias of a debug command if there are other candidates
115 115 (this should hide rawcommit)
116 116 $ hg debugcomplete r
117 117 recover
118 118 remove
119 119 rename
120 120 resolve
121 121 revert
122 122 rollback
123 123 root
124 124 Show the alias of a debug command if there are no other candidates
125 125 $ hg debugcomplete rawc
126 126
127 127
128 128 Show the global options
129 129 $ hg debugcomplete --options | sort
130 130 --config
131 131 --cwd
132 132 --debug
133 133 --debugger
134 134 --encoding
135 135 --encodingmode
136 136 --help
137 137 --hidden
138 138 --noninteractive
139 139 --profile
140 140 --quiet
141 141 --repository
142 142 --time
143 143 --traceback
144 144 --verbose
145 145 --version
146 146 -R
147 147 -h
148 148 -q
149 149 -v
150 150 -y
151 151
152 152 Show the options for the "serve" command
153 153 $ hg debugcomplete --options serve | sort
154 154 --accesslog
155 155 --address
156 156 --certificate
157 157 --cmdserver
158 158 --config
159 159 --cwd
160 160 --daemon
161 --daemon-pipefds
161 --daemon-postexec
162 162 --debug
163 163 --debugger
164 164 --encoding
165 165 --encodingmode
166 166 --errorlog
167 167 --help
168 168 --hidden
169 169 --ipv6
170 170 --name
171 171 --noninteractive
172 172 --pid-file
173 173 --port
174 174 --prefix
175 175 --profile
176 176 --quiet
177 177 --repository
178 178 --stdio
179 179 --style
180 180 --templates
181 181 --time
182 182 --traceback
183 183 --verbose
184 184 --version
185 185 --web-conf
186 186 -6
187 187 -A
188 188 -E
189 189 -R
190 190 -a
191 191 -d
192 192 -h
193 193 -n
194 194 -p
195 195 -q
196 196 -t
197 197 -v
198 198 -y
199 199
200 200 Show an error if we use --options with an ambiguous abbreviation
201 201 $ hg debugcomplete --options s
202 202 hg: command 's' is ambiguous:
203 203 serve showconfig status summary
204 204 [255]
205 205
206 206 Show all commands + options
207 207 $ hg debugcommands
208 208 add: include, exclude, subrepos, dry-run
209 209 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude, template
210 210 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
211 211 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
212 212 diff: rev, change, text, git, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, root, include, exclude, subrepos
213 213 export: output, switch-parent, rev, text, git, nodates
214 214 forget: include, exclude
215 215 init: ssh, remotecmd, insecure
216 216 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
217 217 merge: force, rev, preview, tool
218 218 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
219 219 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
220 220 remove: after, force, subrepos, include, exclude
221 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
221 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
222 222 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template
223 223 summary: remote
224 224 update: clean, check, date, rev, tool
225 225 addremove: similarity, subrepos, include, exclude, dry-run
226 226 archive: no-decode, prefix, rev, type, subrepos, include, exclude
227 227 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
228 228 bisect: reset, good, bad, skip, extend, command, noupdate
229 229 bookmarks: force, rev, delete, rename, inactive, template
230 230 branch: force, clean
231 231 branches: active, closed, template
232 232 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
233 233 cat: output, rev, decode, include, exclude
234 234 config: untrusted, edit, local, global
235 235 copy: after, force, include, exclude, dry-run
236 236 debugancestor:
237 237 debugapplystreamclonebundle:
238 238 debugbuilddag: mergeable-file, overwritten-file, new-file
239 239 debugbundle: all, spec
240 240 debugcheckstate:
241 241 debugcommands:
242 242 debugcomplete: options
243 243 debugcreatestreamclonebundle:
244 244 debugdag: tags, branches, dots, spaces
245 245 debugdata: changelog, manifest, dir
246 246 debugdate: extended
247 247 debugdeltachain: changelog, manifest, dir, template
248 248 debugdirstate: nodates, datesort
249 249 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
250 250 debugextensions: template
251 251 debugfileset: rev
252 252 debugfsinfo:
253 253 debuggetbundle: head, common, type
254 254 debugignore:
255 255 debugindex: changelog, manifest, dir, format
256 256 debugindexdot: changelog, manifest, dir
257 257 debuginstall:
258 258 debugknown:
259 259 debuglabelcomplete:
260 260 debuglocks: force-lock, force-wlock
261 261 debugmergestate:
262 262 debugnamecomplete:
263 263 debugobsolete: flags, record-parents, rev, date, user
264 264 debugpathcomplete: full, normal, added, removed
265 265 debugpushkey:
266 266 debugpvec:
267 267 debugrebuilddirstate: rev, minimal
268 268 debugrebuildfncache:
269 269 debugrename: rev
270 270 debugrevlog: changelog, manifest, dir, dump
271 271 debugrevspec: optimize
272 272 debugsetparents:
273 273 debugsub: rev
274 274 debugsuccessorssets:
275 275 debugwalk: include, exclude
276 276 debugwireargs: three, four, five, ssh, remotecmd, insecure
277 277 files: rev, print0, include, exclude, template, subrepos
278 278 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
279 279 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
280 280 heads: rev, topo, active, closed, style, template
281 281 help: extension, command, keyword, system
282 282 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
283 283 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
284 284 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
285 285 locate: rev, print0, fullpath, include, exclude
286 286 manifest: rev, all, template
287 287 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
288 288 parents: rev, style, template
289 289 paths: template
290 290 phase: public, draft, secret, force, rev
291 291 recover:
292 292 rename: after, force, include, exclude, dry-run
293 293 resolve: all, list, mark, unmark, no-status, tool, include, exclude, template
294 294 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
295 295 rollback: dry-run, force
296 296 root:
297 297 tag: force, local, rev, remove, edit, message, date, user
298 298 tags: template
299 299 tip: patch, git, style, template
300 300 unbundle: update
301 301 verify:
302 302 version:
303 303
304 304 $ hg init a
305 305 $ cd a
306 306 $ echo fee > fee
307 307 $ hg ci -q -Amfee
308 308 $ hg tag fee
309 309 $ mkdir fie
310 310 $ echo dead > fie/dead
311 311 $ echo live > fie/live
312 312 $ hg bookmark fo
313 313 $ hg branch -q fie
314 314 $ hg ci -q -Amfie
315 315 $ echo fo > fo
316 316 $ hg branch -qf default
317 317 $ hg ci -q -Amfo
318 318 $ echo Fum > Fum
319 319 $ hg ci -q -AmFum
320 320 $ hg bookmark Fum
321 321
322 322 Test debugpathcomplete
323 323
324 324 $ hg debugpathcomplete f
325 325 fee
326 326 fie
327 327 fo
328 328 $ hg debugpathcomplete -f f
329 329 fee
330 330 fie/dead
331 331 fie/live
332 332 fo
333 333
334 334 $ hg rm Fum
335 335 $ hg debugpathcomplete -r F
336 336 Fum
337 337
338 338 Test debugnamecomplete
339 339
340 340 $ hg debugnamecomplete
341 341 Fum
342 342 default
343 343 fee
344 344 fie
345 345 fo
346 346 tip
347 347 $ hg debugnamecomplete f
348 348 fee
349 349 fie
350 350 fo
General Comments 0
You need to be logged in to leave comments. Login now