exec_cmd.con commit Fix behavior with non-commit upstream references (57ffc5f)
   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#ifdef RUNTIME_PREFIX
  13        static const char *prefix;
  14#else
  15        static const char *prefix = PREFIX;
  16#endif
  17        struct strbuf d = STRBUF_INIT;
  18
  19        if (is_absolute_path(path))
  20                return path;
  21
  22#ifdef RUNTIME_PREFIX
  23        assert(argv0_path);
  24        assert(is_absolute_path(argv0_path));
  25
  26        if (!prefix &&
  27            !(prefix = strip_path_suffix(argv0_path, GIT_EXEC_PATH)) &&
  28            !(prefix = strip_path_suffix(argv0_path, BINDIR)) &&
  29            !(prefix = strip_path_suffix(argv0_path, "git"))) {
  30                prefix = PREFIX;
  31                fprintf(stderr, "RUNTIME_PREFIX requested, "
  32                                "but prefix computation failed.  "
  33                                "Using static fallback '%s'.\n", prefix);
  34        }
  35#endif
  36
  37        strbuf_addf(&d, "%s/%s", prefix, path);
  38        path = strbuf_detach(&d, NULL);
  39        return path;
  40}
  41
  42const char *git_extract_argv0_path(const char *argv0)
  43{
  44        const char *slash;
  45
  46        if (!argv0 || !*argv0)
  47                return NULL;
  48        slash = argv0 + strlen(argv0);
  49
  50        while (argv0 <= slash && !is_dir_sep(*slash))
  51                slash--;
  52
  53        if (slash >= argv0) {
  54                argv0_path = xstrndup(argv0, slash - argv0);
  55                return slash + 1;
  56        }
  57
  58        return argv0;
  59}
  60
  61void git_set_argv_exec_path(const char *exec_path)
  62{
  63        argv_exec_path = exec_path;
  64}
  65
  66
  67/* Returns the highest-priority, location to look for git programs. */
  68const char *git_exec_path(void)
  69{
  70        const char *env;
  71
  72        if (argv_exec_path)
  73                return argv_exec_path;
  74
  75        env = getenv(EXEC_PATH_ENVIRONMENT);
  76        if (env && *env) {
  77                return env;
  78        }
  79
  80        return system_path(GIT_EXEC_PATH);
  81}
  82
  83static void add_path(struct strbuf *out, const char *path)
  84{
  85        if (path && *path) {
  86                if (is_absolute_path(path))
  87                        strbuf_addstr(out, path);
  88                else
  89                        strbuf_addstr(out, make_nonrelative_path(path));
  90
  91                strbuf_addch(out, PATH_SEP);
  92        }
  93}
  94
  95void setup_path(void)
  96{
  97        const char *old_path = getenv("PATH");
  98        struct strbuf new_path = STRBUF_INIT;
  99
 100        add_path(&new_path, git_exec_path());
 101        add_path(&new_path, argv0_path);
 102
 103        if (old_path)
 104                strbuf_addstr(&new_path, old_path);
 105        else
 106                strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
 107
 108        setenv("PATH", new_path.buf, 1);
 109
 110        strbuf_release(&new_path);
 111}
 112
 113const char **prepare_git_cmd(const char **argv)
 114{
 115        int argc;
 116        const char **nargv;
 117
 118        for (argc = 0; argv[argc]; argc++)
 119                ; /* just counting */
 120        nargv = xmalloc(sizeof(*nargv) * (argc + 2));
 121
 122        nargv[0] = "git";
 123        for (argc = 0; argv[argc]; argc++)
 124                nargv[argc + 1] = argv[argc];
 125        nargv[argc + 1] = NULL;
 126        return nargv;
 127}
 128
 129int execv_git_cmd(const char **argv) {
 130        const char **nargv = prepare_git_cmd(argv);
 131        trace_argv_printf(nargv, "trace: exec:");
 132
 133        /* execvp() can only ever return if it fails */
 134        execvp("git", (char **)nargv);
 135
 136        trace_printf("trace: exec failed: %s\n", strerror(errno));
 137
 138        free(nargv);
 139        return -1;
 140}
 141
 142
 143int execl_git_cmd(const char *cmd,...)
 144{
 145        int argc;
 146        const char *argv[MAX_ARGS + 1];
 147        const char *arg;
 148        va_list param;
 149
 150        va_start(param, cmd);
 151        argv[0] = cmd;
 152        argc = 1;
 153        while (argc < MAX_ARGS) {
 154                arg = argv[argc++] = va_arg(param, char *);
 155                if (!arg)
 156                        break;
 157        }
 158        va_end(param);
 159        if (MAX_ARGS <= argc)
 160                return error("too many args to run %s", cmd);
 161
 162        argv[argc] = NULL;
 163        return execv_git_cmd(argv);
 164}