# HG changeset patch # User Jun Wu # Date 2016-02-26 14:17:59 # Node ID 0a17cfbe54294998efbcd85e7e4a4d21c592b0c0 # Parent 7829d0ba7459e107e60377f62e41bedca515d67a chg: fallback to original hg for some unsupported commands or flags There are some known unsupported commands or flags for chg, such as hg serve -d and hg foo --time. This patch detects these situations and transparently fall back to the original hg. So the users won't bother remembering what chg can and cannot do by themselves. The current detection is not 100% accurate since we do not have an equivalent command line parser in C. But it tries not to cause false positives that prevents people from using chg for legit cases. In the future we may want to implement a more accurate "unsupported" check server-side. diff --git a/contrib/chg/chg.c b/contrib/chg/chg.c --- a/contrib/chg/chg.c +++ b/contrib/chg/chg.c @@ -448,11 +448,51 @@ error: abortmsg("failed to prepare pager (errno = %d)", errno); } +/* + * Test whether the command is unsupported or not. This is not designed to + * cover all cases. But it's fast, does not depend on the server and does + * not return false positives. + */ +static int isunsupported(int argc, const char *argv[]) +{ + enum { + SERVE = 1, + DAEMON = 2, + SERVEDAEMON = SERVE | DAEMON, + TIME = 4, + }; + unsigned int state = 0; + int i; + for (i = 0; i < argc; ++i) { + if (strcmp(argv[i], "--") == 0) + break; + if (i == 0 && strcmp("serve", argv[i]) == 0) + state |= SERVE; + else if (strcmp("-d", argv[i]) == 0 || + strcmp("--daemon", argv[i]) == 0) + state |= DAEMON; + else if (strcmp("--time", argv[i]) == 0) + state |= TIME; + } + return (state & TIME) == TIME || + (state & SERVEDAEMON) == SERVEDAEMON; +} + +static void execoriginalhg(const char *argv[]) +{ + debugmsg("execute original hg"); + if (execvp(gethgcmd(), (char **)argv) < 0) + abortmsg("failed to exec original hg (errno = %d)", errno); +} + int main(int argc, const char *argv[], const char *envp[]) { if (getenv("CHGDEBUG")) enabledebugmsg(); + if (isunsupported(argc - 1, argv + 1)) + execoriginalhg(argv); + struct cmdserveropts opts; initcmdserveropts(&opts); setcmdserveropts(&opts);