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.
--- a/contrib/chg/chg.c Wed Feb 24 13:20:06 2016 +0000
+++ b/contrib/chg/chg.c Fri Feb 26 14:17:59 2016 +0000
@@ -448,11 +448,51 @@
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);