blob: 125fa6fabf503d29cb82b2ccbc92359abf95b0e8 [file] [log] [blame]
Michal Ostrowski77cb17e2006-01-10 21:12:17 -05001#include "cache.h"
2#include "exec_cmd.h"
Matthias Lederhofer575ba9d2006-06-25 15:56:18 +02003#include "quote.h"
Michal Ostrowski77cb17e2006-01-10 21:12:17 -05004#define MAX_ARGS 32
5
Scott R Parish384df832007-10-27 01:36:51 -07006static const char *argv_exec_path;
Johannes Sixte1464ca2008-07-21 21:19:52 +02007static const char *argv0_path;
Michal Ostrowski77cb17e2006-01-10 21:12:17 -05008
Steffen Prohaska2de9de52008-07-13 22:31:18 +02009const char *system_path(const char *path)
10{
Steffen Prohaska35fb0e862009-01-18 13:00:14 +010011#ifdef RUNTIME_PREFIX
12 static const char *prefix;
13#else
Steffen Prohaska026fa0d2009-01-18 13:00:09 +010014 static const char *prefix = PREFIX;
Steffen Prohaska35fb0e862009-01-18 13:00:14 +010015#endif
Steffen Prohaska026fa0d2009-01-18 13:00:09 +010016 struct strbuf d = STRBUF_INIT;
17
18 if (is_absolute_path(path))
19 return path;
20
Steffen Prohaska35fb0e862009-01-18 13:00:14 +010021#ifdef RUNTIME_PREFIX
22 assert(argv0_path);
23 assert(is_absolute_path(argv0_path));
24
Johannes Schindelin024aa7d2009-02-19 20:10:53 +010025 if (!prefix &&
26 !(prefix = strip_path_suffix(argv0_path, GIT_EXEC_PATH)) &&
27 !(prefix = strip_path_suffix(argv0_path, BINDIR)) &&
28 !(prefix = strip_path_suffix(argv0_path, "git"))) {
Steffen Prohaska35fb0e862009-01-18 13:00:14 +010029 prefix = PREFIX;
Johannes Sixtaa094572010-02-23 12:42:56 +010030 trace_printf("RUNTIME_PREFIX requested, "
Steffen Prohaska35fb0e862009-01-18 13:00:14 +010031 "but prefix computation failed. "
32 "Using static fallback '%s'.\n", prefix);
33 }
34#endif
35
Steffen Prohaska026fa0d2009-01-18 13:00:09 +010036 strbuf_addf(&d, "%s/%s", prefix, path);
37 path = strbuf_detach(&d, NULL);
Steffen Prohaska2de9de52008-07-13 22:31:18 +020038 return path;
39}
40
Steve Haslam4dd47c32009-01-18 13:00:10 +010041const char *git_extract_argv0_path(const char *argv0)
Johannes Sixte1464ca2008-07-21 21:19:52 +020042{
Steffen Prohaska2cd72b02009-01-18 13:00:11 +010043 const char *slash;
44
45 if (!argv0 || !*argv0)
46 return NULL;
47 slash = argv0 + strlen(argv0);
Steve Haslam4dd47c32009-01-18 13:00:10 +010048
49 while (argv0 <= slash && !is_dir_sep(*slash))
50 slash--;
51
52 if (slash >= argv0) {
53 argv0_path = xstrndup(argv0, slash - argv0);
54 return slash + 1;
55 }
56
57 return argv0;
Johannes Sixte1464ca2008-07-21 21:19:52 +020058}
59
Scott R Parish384df832007-10-27 01:36:51 -070060void git_set_argv_exec_path(const char *exec_path)
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050061{
Scott R Parish384df832007-10-27 01:36:51 -070062 argv_exec_path = exec_path;
Johannes Sixtc90d5652009-03-21 23:21:18 +010063 /*
64 * Propagate this setting to external programs.
65 */
66 setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050067}
68
69
70/* Returns the highest-priority, location to look for git programs. */
Timo Hirvonen962554c2006-02-26 17:13:46 +020071const char *git_exec_path(void)
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050072{
73 const char *env;
74
Scott R Parish384df832007-10-27 01:36:51 -070075 if (argv_exec_path)
76 return argv_exec_path;
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050077
Junio C Hamanod4ebc362006-12-19 01:28:15 -080078 env = getenv(EXEC_PATH_ENVIRONMENT);
Dmitry V. Levin2b601622006-05-29 04:34:34 +040079 if (env && *env) {
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050080 return env;
81 }
82
Johannes Sixt49fa65a2008-07-23 21:12:18 +020083 return system_path(GIT_EXEC_PATH);
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050084}
85
Scott R Parish511707d2007-10-28 04:17:20 -070086static void add_path(struct strbuf *out, const char *path)
87{
88 if (path && *path) {
89 if (is_absolute_path(path))
90 strbuf_addstr(out, path);
91 else
Carlos Martín Nietoe2a57aa2011-03-17 12:26:46 +010092 strbuf_addstr(out, absolute_path(path));
Scott R Parish511707d2007-10-28 04:17:20 -070093
Johannes Sixt80ba0742007-12-03 21:55:57 +010094 strbuf_addch(out, PATH_SEP);
Scott R Parish511707d2007-10-28 04:17:20 -070095 }
96}
97
Johannes Sixte1464ca2008-07-21 21:19:52 +020098void setup_path(void)
Scott R Parish511707d2007-10-28 04:17:20 -070099{
100 const char *old_path = getenv("PATH");
Brandon Caseyf285a2d2008-10-09 14:12:12 -0500101 struct strbuf new_path = STRBUF_INIT;
Scott R Parish511707d2007-10-28 04:17:20 -0700102
Steffen Prohaska8e346282009-01-18 13:00:13 +0100103 add_path(&new_path, git_exec_path());
Johannes Sixte1464ca2008-07-21 21:19:52 +0200104 add_path(&new_path, argv0_path);
Scott R Parish511707d2007-10-28 04:17:20 -0700105
106 if (old_path)
107 strbuf_addstr(&new_path, old_path);
108 else
Chris Webbcb6a22c2010-04-13 10:07:13 +0100109 strbuf_addstr(&new_path, _PATH_DEFPATH);
Scott R Parish511707d2007-10-28 04:17:20 -0700110
111 setenv("PATH", new_path.buf, 1);
112
113 strbuf_release(&new_path);
114}
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500115
Steffen Prohaska4933e5e2008-07-28 07:50:27 +0200116const char **prepare_git_cmd(const char **argv)
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500117{
Junio C Hamano7550be02007-12-01 22:09:22 -0800118 int argc;
119 const char **nargv;
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500120
Junio C Hamano7550be02007-12-01 22:09:22 -0800121 for (argc = 0; argv[argc]; argc++)
122 ; /* just counting */
123 nargv = xmalloc(sizeof(*nargv) * (argc + 2));
Junio C Hamano9201c702006-03-05 02:47:29 -0800124
Junio C Hamano7550be02007-12-01 22:09:22 -0800125 nargv[0] = "git";
126 for (argc = 0; argv[argc]; argc++)
127 nargv[argc + 1] = argv[argc];
128 nargv[argc + 1] = NULL;
Steffen Prohaska4933e5e2008-07-28 07:50:27 +0200129 return nargv;
130}
131
132int execv_git_cmd(const char **argv) {
133 const char **nargv = prepare_git_cmd(argv);
Junio C Hamano7550be02007-12-01 22:09:22 -0800134 trace_argv_printf(nargv, "trace: exec:");
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500135
Scott R Parish511707d2007-10-28 04:17:20 -0700136 /* execvp() can only ever return if it fails */
Jeff King38f865c2012-03-30 03:52:18 -0400137 sane_execvp("git", (char **)nargv);
Dmitry V. Levind6859902006-05-30 18:58:52 +0400138
Scott R Parish511707d2007-10-28 04:17:20 -0700139 trace_printf("trace: exec failed: %s\n", strerror(errno));
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500140
Junio C Hamano7550be02007-12-01 22:09:22 -0800141 free(nargv);
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500142 return -1;
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500143}
144
145
Junio C Hamano9201c702006-03-05 02:47:29 -0800146int execl_git_cmd(const char *cmd,...)
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500147{
148 int argc;
Junio C Hamano9201c702006-03-05 02:47:29 -0800149 const char *argv[MAX_ARGS + 1];
150 const char *arg;
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500151 va_list param;
152
153 va_start(param, cmd);
154 argv[0] = cmd;
155 argc = 1;
156 while (argc < MAX_ARGS) {
157 arg = argv[argc++] = va_arg(param, char *);
158 if (!arg)
159 break;
160 }
161 va_end(param);
162 if (MAX_ARGS <= argc)
163 return error("too many args to run %s", cmd);
164
165 argv[argc] = NULL;
166 return execv_git_cmd(argv);
167}