exec_cmd.con commit Propagate --exec-path setting to external commands via GIT_EXEC_PATH (c90d565)
   1#include "cache.h"
   2#include "exec_cmd.h"
   3#include "quote.h"
   4#define MAX_ARGS        32
   5
   6extern char **environ;
   7static const char *argv_exec_path;
   8static const char *argv0_path;
   9
  10const char *system_path(const char *path)
  11{
  12        if (!is_absolute_path(path) && argv0_path) {
  13                struct strbuf d = STRBUF_INIT;
  14                strbuf_addf(&d, "%s/%s", argv0_path, path);
  15                path = strbuf_detach(&d, NULL);
  16        }
  17        return path;
  18}
  19
  20void git_set_argv0_path(const char *path)
  21{
  22        argv0_path = path;
  23}
  24
  25void git_set_argv_exec_path(const char *exec_path)
  26{
  27        argv_exec_path = exec_path;
  28        /*
  29         * Propagate this setting to external programs.
  30         */
  31        setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
  32}
  33
  34
  35/* Returns the highest-priority, location to look for git programs. */
  36const char *git_exec_path(void)
  37{
  38        const char *env;
  39
  40        if (argv_exec_path)
  41                return argv_exec_path;
  42
  43        env = getenv(EXEC_PATH_ENVIRONMENT);
  44        if (env && *env) {
  45                return env;
  46        }
  47
  48        return system_path(GIT_EXEC_PATH);
  49}
  50
  51static void add_path(struct strbuf *out, const char *path)
  52{
  53        if (path && *path) {
  54                if (is_absolute_path(path))
  55                        strbuf_addstr(out, path);
  56                else
  57                        strbuf_addstr(out, make_nonrelative_path(path));
  58
  59                strbuf_addch(out, PATH_SEP);
  60        }
  61}
  62
  63void setup_path(void)
  64{
  65        const char *old_path = getenv("PATH");
  66        struct strbuf new_path;
  67
  68        strbuf_init(&new_path, 0);
  69
  70        add_path(&new_path, argv_exec_path);
  71        add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));
  72        add_path(&new_path, system_path(GIT_EXEC_PATH));
  73        add_path(&new_path, argv0_path);
  74
  75        if (old_path)
  76                strbuf_addstr(&new_path, old_path);
  77        else
  78                strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
  79
  80        setenv("PATH", new_path.buf, 1);
  81
  82        strbuf_release(&new_path);
  83}
  84
  85const char **prepare_git_cmd(const char **argv)
  86{
  87        int argc;
  88        const char **nargv;
  89
  90        for (argc = 0; argv[argc]; argc++)
  91                ; /* just counting */
  92        nargv = xmalloc(sizeof(*nargv) * (argc + 2));
  93
  94        nargv[0] = "git";
  95        for (argc = 0; argv[argc]; argc++)
  96                nargv[argc + 1] = argv[argc];
  97        nargv[argc + 1] = NULL;
  98        return nargv;
  99}
 100
 101int execv_git_cmd(const char **argv) {
 102        const char **nargv = prepare_git_cmd(argv);
 103        trace_argv_printf(nargv, "trace: exec:");
 104
 105        /* execvp() can only ever return if it fails */
 106        execvp("git", (char **)nargv);
 107
 108        trace_printf("trace: exec failed: %s\n", strerror(errno));
 109
 110        free(nargv);
 111        return -1;
 112}
 113
 114
 115int execl_git_cmd(const char *cmd,...)
 116{
 117        int argc;
 118        const char *argv[MAX_ARGS + 1];
 119        const char *arg;
 120        va_list param;
 121
 122        va_start(param, cmd);
 123        argv[0] = cmd;
 124        argc = 1;
 125        while (argc < MAX_ARGS) {
 126                arg = argv[argc++] = va_arg(param, char *);
 127                if (!arg)
 128                        break;
 129        }
 130        va_end(param);
 131        if (MAX_ARGS <= argc)
 132                return error("too many args to run %s", cmd);
 133
 134        argv[argc] = NULL;
 135        return execv_git_cmd(argv);
 136}