Mercurial > hg
comparison contrib/chg/chg.c @ 28535:aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
In some rare cases (next patch), we may want validate to do "unlink" without
forcing the client reconnect. This patch addes a new "reconnect" instruction
and makes "unlink" not to reconnect by default.
author | Jun Wu <quark@fb.com> |
---|---|
date | Mon, 14 Mar 2016 13:48:33 +0000 |
parents | 3bf2892f685f |
children | 1435a8e9b5fe |
comparison
equal
deleted
inserted
replaced
28534:293adbaa14a7 | 28535:aa082a8125da |
---|---|
442 close(pipefds[0]); | 442 close(pipefds[0]); |
443 close(pipefds[1]); | 443 close(pipefds[1]); |
444 abortmsg("failed to prepare pager (errno = %d)", errno); | 444 abortmsg("failed to prepare pager (errno = %d)", errno); |
445 } | 445 } |
446 | 446 |
447 /* Run instructions sent from the server like unlink and set redirect path */ | 447 /* Run instructions sent from the server like unlink and set redirect path |
448 static void runinstructions(struct cmdserveropts *opts, const char **insts) | 448 * Return 1 if reconnect is needed, otherwise 0 */ |
449 { | 449 static int runinstructions(struct cmdserveropts *opts, const char **insts) |
450 { | |
451 int needreconnect = 0; | |
452 if (!insts) | |
453 return needreconnect; | |
454 | |
450 assert(insts); | 455 assert(insts); |
451 opts->redirectsockname[0] = '\0'; | 456 opts->redirectsockname[0] = '\0'; |
452 const char **pinst; | 457 const char **pinst; |
453 for (pinst = insts; *pinst; pinst++) { | 458 for (pinst = insts; *pinst; pinst++) { |
454 debugmsg("instruction: %s", *pinst); | 459 debugmsg("instruction: %s", *pinst); |
458 int r = snprintf(opts->redirectsockname, | 463 int r = snprintf(opts->redirectsockname, |
459 sizeof(opts->redirectsockname), | 464 sizeof(opts->redirectsockname), |
460 "%s", *pinst + 9); | 465 "%s", *pinst + 9); |
461 if (r < 0 || r >= (int)sizeof(opts->redirectsockname)) | 466 if (r < 0 || r >= (int)sizeof(opts->redirectsockname)) |
462 abortmsg("redirect path is too long (%d)", r); | 467 abortmsg("redirect path is too long (%d)", r); |
468 needreconnect = 1; | |
463 } else if (strncmp(*pinst, "exit ", 5) == 0) { | 469 } else if (strncmp(*pinst, "exit ", 5) == 0) { |
464 int n = 0; | 470 int n = 0; |
465 if (sscanf(*pinst + 5, "%d", &n) != 1) | 471 if (sscanf(*pinst + 5, "%d", &n) != 1) |
466 abortmsg("cannot read the exit code"); | 472 abortmsg("cannot read the exit code"); |
467 exit(n); | 473 exit(n); |
474 } else if (strcmp(*pinst, "reconnect") == 0) { | |
475 needreconnect = 1; | |
468 } else { | 476 } else { |
469 abortmsg("unknown instruction: %s", *pinst); | 477 abortmsg("unknown instruction: %s", *pinst); |
470 } | 478 } |
471 } | 479 } |
480 return needreconnect; | |
472 } | 481 } |
473 | 482 |
474 /* | 483 /* |
475 * Test whether the command is unsupported or not. This is not designed to | 484 * Test whether the command is unsupported or not. This is not designed to |
476 * cover all cases. But it's fast, does not depend on the server and does | 485 * cover all cases. But it's fast, does not depend on the server and does |
540 hgc = connectcmdserver(&opts); | 549 hgc = connectcmdserver(&opts); |
541 if (!hgc) | 550 if (!hgc) |
542 abortmsg("cannot open hg client"); | 551 abortmsg("cannot open hg client"); |
543 hgc_setenv(hgc, envp); | 552 hgc_setenv(hgc, envp); |
544 const char **insts = hgc_validate(hgc, argv + 1, argc - 1); | 553 const char **insts = hgc_validate(hgc, argv + 1, argc - 1); |
545 if (insts == NULL) | 554 int needreconnect = runinstructions(&opts, insts); |
555 free(insts); | |
556 if (!needreconnect) | |
546 break; | 557 break; |
547 runinstructions(&opts, insts); | |
548 free(insts); | |
549 hgc_close(hgc); | 558 hgc_close(hgc); |
550 if (++retry > 10) | 559 if (++retry > 10) |
551 abortmsg("too many redirections.\n" | 560 abortmsg("too many redirections.\n" |
552 "Please make sure %s is not a wrapper which " | 561 "Please make sure %s is not a wrapper which " |
553 "changes sensitive environment variables " | 562 "changes sensitive environment variables " |