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 "