blob: ce6741eb682b59ad638c7bee6ca31e2fcd53f281 [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
6extern char **environ;
Scott R Parish384df832007-10-27 01:36:51 -07007static const char *argv_exec_path;
Johannes Sixte1464ca2008-07-21 21:19:52 +02008static const char *argv0_path;
Michal Ostrowski77cb17e2006-01-10 21:12:17 -05009
Steffen Prohaska2de9de52008-07-13 22:31:18 +020010const char *system_path(const char *path)
11{
Johannes Sixt966c6ed2008-07-21 21:19:53 +020012 if (!is_absolute_path(path) && argv0_path) {
Steffen Prohaska2de9de52008-07-13 22:31:18 +020013 struct strbuf d = STRBUF_INIT;
Johannes Sixt966c6ed2008-07-21 21:19:53 +020014 strbuf_addf(&d, "%s/%s", argv0_path, path);
Steffen Prohaska2de9de52008-07-13 22:31:18 +020015 path = strbuf_detach(&d, NULL);
16 }
17 return path;
18}
19
Johannes Sixte1464ca2008-07-21 21:19:52 +020020void git_set_argv0_path(const char *path)
21{
22 argv0_path = path;
23}
24
Scott R Parish384df832007-10-27 01:36:51 -070025void git_set_argv_exec_path(const char *exec_path)
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050026{
Scott R Parish384df832007-10-27 01:36:51 -070027 argv_exec_path = exec_path;
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050028}
29
30
31/* Returns the highest-priority, location to look for git programs. */
Timo Hirvonen962554c2006-02-26 17:13:46 +020032const char *git_exec_path(void)
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050033{
34 const char *env;
35
Scott R Parish384df832007-10-27 01:36:51 -070036 if (argv_exec_path)
37 return argv_exec_path;
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050038
Junio C Hamanod4ebc362006-12-19 01:28:15 -080039 env = getenv(EXEC_PATH_ENVIRONMENT);
Dmitry V. Levin2b601622006-05-29 04:34:34 +040040 if (env && *env) {
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050041 return env;
42 }
43
Johannes Sixt49fa65a2008-07-23 21:12:18 +020044 return system_path(GIT_EXEC_PATH);
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050045}
46
Scott R Parish511707d2007-10-28 04:17:20 -070047static void add_path(struct strbuf *out, const char *path)
48{
49 if (path && *path) {
50 if (is_absolute_path(path))
51 strbuf_addstr(out, path);
52 else
Johannes Sixt10c4c882008-07-21 21:19:55 +020053 strbuf_addstr(out, make_nonrelative_path(path));
Scott R Parish511707d2007-10-28 04:17:20 -070054
Johannes Sixt80ba0742007-12-03 21:55:57 +010055 strbuf_addch(out, PATH_SEP);
Scott R Parish511707d2007-10-28 04:17:20 -070056 }
57}
58
Johannes Sixte1464ca2008-07-21 21:19:52 +020059void setup_path(void)
Scott R Parish511707d2007-10-28 04:17:20 -070060{
61 const char *old_path = getenv("PATH");
62 struct strbuf new_path;
63
64 strbuf_init(&new_path, 0);
65
66 add_path(&new_path, argv_exec_path);
67 add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));
Johannes Sixt49fa65a2008-07-23 21:12:18 +020068 add_path(&new_path, system_path(GIT_EXEC_PATH));
Johannes Sixte1464ca2008-07-21 21:19:52 +020069 add_path(&new_path, argv0_path);
Scott R Parish511707d2007-10-28 04:17:20 -070070
71 if (old_path)
72 strbuf_addstr(&new_path, old_path);
73 else
74 strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
75
76 setenv("PATH", new_path.buf, 1);
77
78 strbuf_release(&new_path);
79}
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050080
Steffen Prohaska4933e5e2008-07-28 07:50:27 +020081const char **prepare_git_cmd(const char **argv)
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050082{
Junio C Hamano7550be02007-12-01 22:09:22 -080083 int argc;
84 const char **nargv;
Michal Ostrowski77cb17e2006-01-10 21:12:17 -050085
Junio C Hamano7550be02007-12-01 22:09:22 -080086 for (argc = 0; argv[argc]; argc++)
87 ; /* just counting */
88 nargv = xmalloc(sizeof(*nargv) * (argc + 2));
Junio C Hamano9201c702006-03-05 02:47:29 -080089
Junio C Hamano7550be02007-12-01 22:09:22 -080090 nargv[0] = "git";
91 for (argc = 0; argv[argc]; argc++)
92 nargv[argc + 1] = argv[argc];
93 nargv[argc + 1] = NULL;
Steffen Prohaska4933e5e2008-07-28 07:50:27 +020094 return nargv;
95}
96
97int execv_git_cmd(const char **argv) {
98 const char **nargv = prepare_git_cmd(argv);
Junio C Hamano7550be02007-12-01 22:09:22 -080099 trace_argv_printf(nargv, "trace: exec:");
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500100
Scott R Parish511707d2007-10-28 04:17:20 -0700101 /* execvp() can only ever return if it fails */
Junio C Hamano7550be02007-12-01 22:09:22 -0800102 execvp("git", (char **)nargv);
Dmitry V. Levind6859902006-05-30 18:58:52 +0400103
Scott R Parish511707d2007-10-28 04:17:20 -0700104 trace_printf("trace: exec failed: %s\n", strerror(errno));
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500105
Junio C Hamano7550be02007-12-01 22:09:22 -0800106 free(nargv);
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500107 return -1;
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500108}
109
110
Junio C Hamano9201c702006-03-05 02:47:29 -0800111int execl_git_cmd(const char *cmd,...)
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500112{
113 int argc;
Junio C Hamano9201c702006-03-05 02:47:29 -0800114 const char *argv[MAX_ARGS + 1];
115 const char *arg;
Michal Ostrowski77cb17e2006-01-10 21:12:17 -0500116 va_list param;
117
118 va_start(param, cmd);
119 argv[0] = cmd;
120 argc = 1;
121 while (argc < MAX_ARGS) {
122 arg = argv[argc++] = va_arg(param, char *);
123 if (!arg)
124 break;
125 }
126 va_end(param);
127 if (MAX_ARGS <= argc)
128 return error("too many args to run %s", cmd);
129
130 argv[argc] = NULL;
131 return execv_git_cmd(argv);
132}