diff --git a/contrib/chg/chg.c b/contrib/chg/chg.c --- a/contrib/chg/chg.c +++ b/contrib/chg/chg.c @@ -203,6 +203,39 @@ return hgcmd; } +static void putsidechannelenv(const char *envname) +{ + char *buf, *bufp; + const char *existing_val = getenv(envname); + size_t existing_val_len = 0; + size_t envname_len = strlen(envname); + size_t buf_len; + + if (existing_val != NULL) { + existing_val_len = strlen(existing_val); + } + + /* 11: 8 for CHGORIG_, 1 for the =, 1 for the "exists" flag, 1 for the + * nul */ + buf_len = envname_len + existing_val_len + 11; + bufp = buf = mallocx(buf_len); + strlcpy(bufp, "CHGORIG_", 8); + bufp += 8; /* strlen("CHGORIG_") */ + strlcpy(bufp, envname, envname_len); + bufp += envname_len; + *bufp++ = '='; + *bufp++ = (existing_val == NULL) ? '0' : '1'; + if (existing_val != NULL && existing_val_len > 0) { + strlcpy(bufp, existing_val, existing_val_len); + bufp += existing_val_len; + } + *bufp = '\0'; + if (putenv(buf) != 0) { + abortmsgerrno("failed to putenv for stored vars"); + } + /* don't free `buf`, putenv does NOT copy the string! */ +} + static void execcmdserver(const struct cmdserveropts *opts) { const char *hgcmd = gethgcmd(); @@ -410,6 +443,14 @@ "wrapper to chg. Alternatively, set $CHGHG to the " "path of real hg."); + char *coerce = getenv("PYTHONCOERCECLOCALE"); + if (coerce == NULL || coerce[0] != '0') { + /* Py3 modifies the environment on execution, we need a side + * channel to get an unmodified environment to `hg serve` for + * some variables */ + putsidechannelenv("LC_CTYPE"); + } + if (isunsupported(argc - 1, argv + 1)) execoriginalhg(argv);