Exec git programs without using PATH.
[git/git.git] / receive-pack.c
CommitLineData
575f4974 1#include "cache.h"
8a65ff76 2#include "refs.h"
f3a3214e 3#include "pkt-line.h"
b1bf95bb 4#include "run-command.h"
575f4974
LT
5#include <sys/wait.h>
6
d0efc8a7 7static const char receive_pack_usage[] = "git-receive-pack <git-dir>";
575f4974 8
77cb17e9 9static char *unpacker[] = { "unpack-objects", NULL };
575f4974 10
cfee10a7
JH
11static int report_status = 0;
12
13static char capabilities[] = "report-status";
14static int capabilities_sent = 0;
15
944d8589 16static int show_ref(const char *path, const unsigned char *sha1)
575f4974 17{
cfee10a7
JH
18 if (capabilities_sent)
19 packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
20 else
21 packet_write(1, "%s %s%c%s\n",
22 sha1_to_hex(sha1), path, 0, capabilities);
23 capabilities_sent = 1;
8a65ff76 24 return 0;
575f4974
LT
25}
26
8a65ff76 27static void write_head_info(void)
575f4974 28{
8a65ff76 29 for_each_ref(show_ref);
cfee10a7
JH
30 if (!capabilities_sent)
31 show_ref("capabilities^{}", null_sha1);
32
575f4974
LT
33}
34
eb1af2df
LT
35struct command {
36 struct command *next;
cfee10a7 37 const char *error_string;
eb1af2df
LT
38 unsigned char old_sha1[20];
39 unsigned char new_sha1[20];
8f1d2e6f 40 char ref_name[FLEX_ARRAY]; /* more */
575f4974
LT
41};
42
6da4016a 43static struct command *commands = NULL;
575f4974 44
f65fdf04
LT
45static int is_all_zeroes(const char *hex)
46{
47 int i;
48 for (i = 0; i < 40; i++)
49 if (*hex++ != '0')
50 return 0;
51 return 1;
52}
53
2eca23da
LT
54static int verify_old_ref(const char *name, char *hex_contents)
55{
56 int fd, ret;
57 char buffer[60];
58
f65fdf04
LT
59 if (is_all_zeroes(hex_contents))
60 return 0;
2eca23da
LT
61 fd = open(name, O_RDONLY);
62 if (fd < 0)
63 return -1;
64 ret = read(fd, buffer, 40);
65 close(fd);
66 if (ret != 40)
67 return -1;
68 if (memcmp(buffer, hex_contents, 40))
69 return -1;
70 return 0;
71}
72
b1bf95bb
JW
73static char update_hook[] = "hooks/update";
74
75static int run_update_hook(const char *refname,
76 char *old_hex, char *new_hex)
77{
78 int code;
79
80 if (access(update_hook, X_OK) < 0)
81 return 0;
82 code = run_command(update_hook, refname, old_hex, new_hex, NULL);
83 switch (code) {
84 case 0:
85 return 0;
86 case -ERR_RUN_COMMAND_FORK:
cfee10a7 87 return error("hook fork failed");
b1bf95bb 88 case -ERR_RUN_COMMAND_EXEC:
cfee10a7 89 return error("hook execute failed");
b1bf95bb 90 case -ERR_RUN_COMMAND_WAITPID:
cfee10a7 91 return error("waitpid failed");
b1bf95bb 92 case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
cfee10a7 93 return error("waitpid is confused");
b1bf95bb 94 case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
cfee10a7 95 return error("%s died of signal\n", update_hook);
b1bf95bb 96 case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
cfee10a7 97 return error("%s died strangely", update_hook);
b1bf95bb
JW
98 default:
99 error("%s exited with error code %d", update_hook, -code);
100 return -code;
101 }
102}
103
cfee10a7 104static int update(struct command *cmd)
2eca23da 105{
cfee10a7
JH
106 const char *name = cmd->ref_name;
107 unsigned char *old_sha1 = cmd->old_sha1;
108 unsigned char *new_sha1 = cmd->new_sha1;
2eca23da
LT
109 char new_hex[60], *old_hex, *lock_name;
110 int newfd, namelen, written;
111
cfee10a7
JH
112 cmd->error_string = NULL;
113 if (!strncmp(name, "refs/", 5) && check_ref_format(name + 5)) {
114 cmd->error_string = "funny refname";
d8a1deec
JH
115 return error("refusing to create funny ref '%s' locally",
116 name);
cfee10a7 117 }
d8a1deec 118
2eca23da
LT
119 namelen = strlen(name);
120 lock_name = xmalloc(namelen + 10);
121 memcpy(lock_name, name, namelen);
122 memcpy(lock_name + namelen, ".lock", 6);
123
124 strcpy(new_hex, sha1_to_hex(new_sha1));
2eca23da 125 old_hex = sha1_to_hex(old_sha1);
cfee10a7
JH
126 if (!has_sha1_file(new_sha1)) {
127 cmd->error_string = "bad pack";
19614330
JH
128 return error("unpack should have generated %s, "
129 "but I can't find it!", new_hex);
cfee10a7 130 }
29f3b3de
JH
131 safe_create_leading_directories(lock_name);
132
f312de01 133 newfd = open(lock_name, O_CREAT | O_EXCL | O_WRONLY, 0666);
cfee10a7
JH
134 if (newfd < 0) {
135 cmd->error_string = "can't lock";
19614330
JH
136 return error("unable to create %s (%s)",
137 lock_name, strerror(errno));
cfee10a7 138 }
f65fdf04
LT
139
140 /* Write the ref with an ending '\n' */
141 new_hex[40] = '\n';
142 new_hex[41] = 0;
2eca23da 143 written = write(newfd, new_hex, 41);
f65fdf04
LT
144 /* Remove the '\n' again */
145 new_hex[40] = 0;
146
2eca23da
LT
147 close(newfd);
148 if (written != 41) {
149 unlink(lock_name);
cfee10a7 150 cmd->error_string = "can't write";
19614330 151 return error("unable to write %s", lock_name);
2eca23da
LT
152 }
153 if (verify_old_ref(name, old_hex) < 0) {
154 unlink(lock_name);
cfee10a7 155 cmd->error_string = "raced";
19614330 156 return error("%s changed during push", name);
2eca23da 157 }
b1bf95bb
JW
158 if (run_update_hook(name, old_hex, new_hex)) {
159 unlink(lock_name);
cfee10a7 160 cmd->error_string = "hook declined";
19614330 161 return error("hook declined to update %s\n", name);
b1bf95bb
JW
162 }
163 else if (rename(lock_name, name) < 0) {
2eca23da 164 unlink(lock_name);
cfee10a7 165 cmd->error_string = "can't rename";
19614330 166 return error("unable to replace %s", name);
2eca23da 167 }
19614330 168 else {
b1bf95bb 169 fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex);
19614330
JH
170 return 0;
171 }
2eca23da
LT
172}
173
19614330
JH
174static char update_post_hook[] = "hooks/post-update";
175
176static void run_update_post_hook(struct command *cmd)
177{
178 struct command *cmd_p;
179 int argc;
180 char **argv;
181
182 if (access(update_post_hook, X_OK) < 0)
183 return;
184 for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
cfee10a7 185 if (cmd_p->error_string)
19614330
JH
186 continue;
187 argc++;
188 }
189 argv = xmalloc(sizeof(*argv) * (1 + argc));
190 argv[0] = update_post_hook;
191
192 for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
cfee10a7 193 if (cmd_p->error_string)
19614330
JH
194 continue;
195 argv[argc] = xmalloc(strlen(cmd_p->ref_name) + 1);
196 strcpy(argv[argc], cmd_p->ref_name);
197 argc++;
198 }
199 argv[argc] = NULL;
128aed68 200 run_command_v_opt(argc, argv, RUN_COMMAND_NO_STDIO);
19614330 201}
2eca23da 202
575f4974
LT
203/*
204 * This gets called after(if) we've successfully
205 * unpacked the data payload.
206 */
207static void execute_commands(void)
208{
eb1af2df
LT
209 struct command *cmd = commands;
210
211 while (cmd) {
cfee10a7 212 update(cmd);
eb1af2df 213 cmd = cmd->next;
575f4974 214 }
19614330 215 run_update_post_hook(commands);
575f4974
LT
216}
217
218static void read_head_info(void)
219{
eb1af2df 220 struct command **p = &commands;
575f4974
LT
221 for (;;) {
222 static char line[1000];
eb1af2df
LT
223 unsigned char old_sha1[20], new_sha1[20];
224 struct command *cmd;
cfee10a7
JH
225 char *refname;
226 int len, reflen;
eb1af2df
LT
227
228 len = packet_read_line(0, line, sizeof(line));
575f4974
LT
229 if (!len)
230 break;
eb1af2df
LT
231 if (line[len-1] == '\n')
232 line[--len] = 0;
233 if (len < 83 ||
234 line[40] != ' ' ||
235 line[81] != ' ' ||
236 get_sha1_hex(line, old_sha1) ||
237 get_sha1_hex(line + 41, new_sha1))
cfee10a7
JH
238 die("protocol error: expected old/new/ref, got '%s'",
239 line);
240
241 refname = line + 82;
242 reflen = strlen(refname);
243 if (reflen + 82 < len) {
244 if (strstr(refname + reflen + 1, "report-status"))
245 report_status = 1;
246 }
eb1af2df
LT
247 cmd = xmalloc(sizeof(struct command) + len - 80);
248 memcpy(cmd->old_sha1, old_sha1, 20);
249 memcpy(cmd->new_sha1, new_sha1, 20);
250 memcpy(cmd->ref_name, line + 82, len - 81);
cfee10a7 251 cmd->error_string = "n/a (unpacker error)";
eb1af2df
LT
252 cmd->next = NULL;
253 *p = cmd;
254 p = &cmd->next;
575f4974
LT
255 }
256}
257
cfee10a7 258static const char *unpack(int *error_code)
575f4974 259{
77cb17e9 260 int code = run_command_v_opt(1, unpacker, RUN_GIT_CMD);
cfee10a7
JH
261
262 *error_code = 0;
b1bf95bb
JW
263 switch (code) {
264 case 0:
cfee10a7 265 return NULL;
b1bf95bb 266 case -ERR_RUN_COMMAND_FORK:
cfee10a7 267 return "unpack fork failed";
b1bf95bb 268 case -ERR_RUN_COMMAND_EXEC:
cfee10a7 269 return "unpack execute failed";
b1bf95bb 270 case -ERR_RUN_COMMAND_WAITPID:
cfee10a7 271 return "waitpid failed";
b1bf95bb 272 case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
cfee10a7 273 return "waitpid is confused";
b1bf95bb 274 case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
cfee10a7 275 return "unpacker died of signal";
b1bf95bb 276 case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
cfee10a7 277 return "unpacker died strangely";
b1bf95bb 278 default:
cfee10a7
JH
279 *error_code = -code;
280 return "unpacker exited with error code";
281 }
282}
283
284static void report(const char *unpack_status)
285{
286 struct command *cmd;
287 packet_write(1, "unpack %s\n",
288 unpack_status ? unpack_status : "ok");
289 for (cmd = commands; cmd; cmd = cmd->next) {
290 if (!cmd->error_string)
291 packet_write(1, "ok %s\n",
292 cmd->ref_name);
293 else
294 packet_write(1, "ng %s %s\n",
295 cmd->ref_name, cmd->error_string);
575f4974 296 }
cfee10a7 297 packet_flush(1);
575f4974
LT
298}
299
300int main(int argc, char **argv)
301{
d0efc8a7 302 int i;
8d630132 303 char *dir = NULL;
575f4974
LT
304
305 argv++;
306 for (i = 1; i < argc; i++) {
8d630132 307 char *arg = *argv++;
575f4974
LT
308
309 if (*arg == '-') {
575f4974
LT
310 /* Do flag handling here */
311 usage(receive_pack_usage);
312 }
d0efc8a7
LT
313 if (dir)
314 usage(receive_pack_usage);
575f4974 315 dir = arg;
575f4974
LT
316 }
317 if (!dir)
318 usage(receive_pack_usage);
319
8d630132
AE
320 if(!enter_repo(dir, 0))
321 die("'%s': unable to chdir or not a git archive", dir);
575f4974 322
8a65ff76 323 write_head_info();
575f4974
LT
324
325 /* EOF */
f3a3214e 326 packet_flush(1);
575f4974
LT
327
328 read_head_info();
7f8e9828 329 if (commands) {
cfee10a7
JH
330 int code;
331 const char *unpack_status = unpack(&code);
332 if (!unpack_status)
333 execute_commands();
334 if (report_status)
335 report(unpack_status);
7f8e9828 336 }
575f4974
LT
337 return 0;
338}