git wrapper: Make while loop more reader-friendly
[git/platforms.git] / builtin-receive-pack.c
blobdb67c3162c6b8ffaba793fd6082324aeae158f86
1 #include "cache.h"
2 #include "pack.h"
3 #include "refs.h"
4 #include "pkt-line.h"
5 #include "run-command.h"
6 #include "exec_cmd.h"
7 #include "commit.h"
8 #include "object.h"
9 #include "remote.h"
10 #include "transport.h"
12 static const char receive_pack_usage[] = "git-receive-pack <git-dir>";
14 enum deny_action {
15 DENY_IGNORE,
16 DENY_WARN,
17 DENY_REFUSE,
20 static int deny_deletes = 0;
21 static int deny_non_fast_forwards = 0;
22 static enum deny_action deny_current_branch = DENY_WARN;
23 static int receive_fsck_objects;
24 static int receive_unpack_limit = -1;
25 static int transfer_unpack_limit = -1;
26 static int unpack_limit = 100;
27 static int report_status;
29 static char capabilities[] = " report-status delete-refs ";
30 static int capabilities_sent;
32 static enum deny_action parse_deny_action(const char *var, const char *value)
34 if (value) {
35 if (!strcasecmp(value, "ignore"))
36 return DENY_IGNORE;
37 if (!strcasecmp(value, "warn"))
38 return DENY_WARN;
39 if (!strcasecmp(value, "refuse"))
40 return DENY_REFUSE;
42 if (git_config_bool(var, value))
43 return DENY_REFUSE;
44 return DENY_IGNORE;
47 static int receive_pack_config(const char *var, const char *value, void *cb)
49 if (strcmp(var, "receive.denydeletes") == 0) {
50 deny_deletes = git_config_bool(var, value);
51 return 0;
54 if (strcmp(var, "receive.denynonfastforwards") == 0) {
55 deny_non_fast_forwards = git_config_bool(var, value);
56 return 0;
59 if (strcmp(var, "receive.unpacklimit") == 0) {
60 receive_unpack_limit = git_config_int(var, value);
61 return 0;
64 if (strcmp(var, "transfer.unpacklimit") == 0) {
65 transfer_unpack_limit = git_config_int(var, value);
66 return 0;
69 if (strcmp(var, "receive.fsckobjects") == 0) {
70 receive_fsck_objects = git_config_bool(var, value);
71 return 0;
74 if (!strcmp(var, "receive.denycurrentbranch")) {
75 deny_current_branch = parse_deny_action(var, value);
76 return 0;
79 return git_default_config(var, value, cb);
82 static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
84 if (capabilities_sent)
85 packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
86 else
87 packet_write(1, "%s %s%c%s\n",
88 sha1_to_hex(sha1), path, 0, capabilities);
89 capabilities_sent = 1;
90 return 0;
93 static void write_head_info(void)
95 for_each_ref(show_ref, NULL);
96 if (!capabilities_sent)
97 show_ref("capabilities^{}", null_sha1, 0, NULL);
101 struct command {
102 struct command *next;
103 const char *error_string;
104 unsigned char old_sha1[20];
105 unsigned char new_sha1[20];
106 char ref_name[FLEX_ARRAY]; /* more */
109 static struct command *commands;
111 static const char pre_receive_hook[] = "hooks/pre-receive";
112 static const char post_receive_hook[] = "hooks/post-receive";
114 static int hook_status(int code, const char *hook_name)
116 switch (code) {
117 case 0:
118 return 0;
119 case -ERR_RUN_COMMAND_FORK:
120 return error("hook fork failed");
121 case -ERR_RUN_COMMAND_EXEC:
122 return error("hook execute failed");
123 case -ERR_RUN_COMMAND_PIPE:
124 return error("hook pipe failed");
125 case -ERR_RUN_COMMAND_WAITPID:
126 return error("waitpid failed");
127 case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
128 return error("waitpid is confused");
129 case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
130 return error("%s died of signal", hook_name);
131 case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
132 return error("%s died strangely", hook_name);
133 default:
134 error("%s exited with error code %d", hook_name, -code);
135 return -code;
139 static int run_hook(const char *hook_name)
141 static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
142 struct command *cmd;
143 struct child_process proc;
144 const char *argv[2];
145 int have_input = 0, code;
147 for (cmd = commands; !have_input && cmd; cmd = cmd->next) {
148 if (!cmd->error_string)
149 have_input = 1;
152 if (!have_input || access(hook_name, X_OK) < 0)
153 return 0;
155 argv[0] = hook_name;
156 argv[1] = NULL;
158 memset(&proc, 0, sizeof(proc));
159 proc.argv = argv;
160 proc.in = -1;
161 proc.stdout_to_stderr = 1;
163 code = start_command(&proc);
164 if (code)
165 return hook_status(code, hook_name);
166 for (cmd = commands; cmd; cmd = cmd->next) {
167 if (!cmd->error_string) {
168 size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
169 sha1_to_hex(cmd->old_sha1),
170 sha1_to_hex(cmd->new_sha1),
171 cmd->ref_name);
172 if (write_in_full(proc.in, buf, n) != n)
173 break;
176 close(proc.in);
177 return hook_status(finish_command(&proc), hook_name);
180 static int run_update_hook(struct command *cmd)
182 static const char update_hook[] = "hooks/update";
183 struct child_process proc;
184 const char *argv[5];
186 if (access(update_hook, X_OK) < 0)
187 return 0;
189 argv[0] = update_hook;
190 argv[1] = cmd->ref_name;
191 argv[2] = sha1_to_hex(cmd->old_sha1);
192 argv[3] = sha1_to_hex(cmd->new_sha1);
193 argv[4] = NULL;
195 memset(&proc, 0, sizeof(proc));
196 proc.argv = argv;
197 proc.no_stdin = 1;
198 proc.stdout_to_stderr = 1;
200 return hook_status(run_command(&proc), update_hook);
203 static int is_ref_checked_out(const char *ref)
205 unsigned char sha1[20];
206 const char *head;
208 if (is_bare_repository())
209 return 0;
211 head = resolve_ref("HEAD", sha1, 0, NULL);
212 if (!head)
213 return 0;
214 return !strcmp(head, ref);
217 static const char *update(struct command *cmd)
219 const char *name = cmd->ref_name;
220 unsigned char *old_sha1 = cmd->old_sha1;
221 unsigned char *new_sha1 = cmd->new_sha1;
222 struct ref_lock *lock;
224 /* only refs/... are allowed */
225 if (prefixcmp(name, "refs/") || check_ref_format(name + 5)) {
226 error("refusing to create funny ref '%s' remotely", name);
227 return "funny refname";
230 switch (deny_current_branch) {
231 case DENY_IGNORE:
232 break;
233 case DENY_WARN:
234 if (!is_ref_checked_out(name))
235 break;
236 warning("updating the currently checked out branch; this may"
237 " cause confusion,\n"
238 "as the index and working tree do not reflect changes"
239 " that are now in HEAD.");
240 break;
241 case DENY_REFUSE:
242 if (!is_ref_checked_out(name))
243 break;
244 error("refusing to update checked out branch: %s", name);
245 return "branch is currently checked out";
248 if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
249 error("unpack should have generated %s, "
250 "but I can't find it!", sha1_to_hex(new_sha1));
251 return "bad pack";
253 if (deny_deletes && is_null_sha1(new_sha1) &&
254 !is_null_sha1(old_sha1) &&
255 !prefixcmp(name, "refs/heads/")) {
256 error("denying ref deletion for %s", name);
257 return "deletion prohibited";
259 if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
260 !is_null_sha1(old_sha1) &&
261 !prefixcmp(name, "refs/heads/")) {
262 struct object *old_object, *new_object;
263 struct commit *old_commit, *new_commit;
264 struct commit_list *bases, *ent;
266 old_object = parse_object(old_sha1);
267 new_object = parse_object(new_sha1);
269 if (!old_object || !new_object ||
270 old_object->type != OBJ_COMMIT ||
271 new_object->type != OBJ_COMMIT) {
272 error("bad sha1 objects for %s", name);
273 return "bad ref";
275 old_commit = (struct commit *)old_object;
276 new_commit = (struct commit *)new_object;
277 bases = get_merge_bases(old_commit, new_commit, 1);
278 for (ent = bases; ent; ent = ent->next)
279 if (!hashcmp(old_sha1, ent->item->object.sha1))
280 break;
281 free_commit_list(bases);
282 if (!ent) {
283 error("denying non-fast forward %s"
284 " (you should pull first)", name);
285 return "non-fast forward";
288 if (run_update_hook(cmd)) {
289 error("hook declined to update %s", name);
290 return "hook declined";
293 if (is_null_sha1(new_sha1)) {
294 if (!parse_object(old_sha1)) {
295 warning ("Allowing deletion of corrupt ref.");
296 old_sha1 = NULL;
298 if (delete_ref(name, old_sha1, 0)) {
299 error("failed to delete %s", name);
300 return "failed to delete";
302 return NULL; /* good */
304 else {
305 lock = lock_any_ref_for_update(name, old_sha1, 0);
306 if (!lock) {
307 error("failed to lock %s", name);
308 return "failed to lock";
310 if (write_ref_sha1(lock, new_sha1, "push")) {
311 return "failed to write"; /* error() already called */
313 return NULL; /* good */
317 static char update_post_hook[] = "hooks/post-update";
319 static void run_update_post_hook(struct command *cmd)
321 struct command *cmd_p;
322 int argc;
323 const char **argv;
325 for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
326 if (cmd_p->error_string)
327 continue;
328 argc++;
330 if (!argc || access(update_post_hook, X_OK) < 0)
331 return;
332 argv = xmalloc(sizeof(*argv) * (2 + argc));
333 argv[0] = update_post_hook;
335 for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
336 char *p;
337 if (cmd_p->error_string)
338 continue;
339 p = xmalloc(strlen(cmd_p->ref_name) + 1);
340 strcpy(p, cmd_p->ref_name);
341 argv[argc] = p;
342 argc++;
344 argv[argc] = NULL;
345 run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
346 | RUN_COMMAND_STDOUT_TO_STDERR);
349 static void execute_commands(const char *unpacker_error)
351 struct command *cmd = commands;
353 if (unpacker_error) {
354 while (cmd) {
355 cmd->error_string = "n/a (unpacker error)";
356 cmd = cmd->next;
358 return;
361 if (run_hook(pre_receive_hook)) {
362 while (cmd) {
363 cmd->error_string = "pre-receive hook declined";
364 cmd = cmd->next;
366 return;
369 while (cmd) {
370 cmd->error_string = update(cmd);
371 cmd = cmd->next;
375 static void read_head_info(void)
377 struct command **p = &commands;
378 for (;;) {
379 static char line[1000];
380 unsigned char old_sha1[20], new_sha1[20];
381 struct command *cmd;
382 char *refname;
383 int len, reflen;
385 len = packet_read_line(0, line, sizeof(line));
386 if (!len)
387 break;
388 if (line[len-1] == '\n')
389 line[--len] = 0;
390 if (len < 83 ||
391 line[40] != ' ' ||
392 line[81] != ' ' ||
393 get_sha1_hex(line, old_sha1) ||
394 get_sha1_hex(line + 41, new_sha1))
395 die("protocol error: expected old/new/ref, got '%s'",
396 line);
398 refname = line + 82;
399 reflen = strlen(refname);
400 if (reflen + 82 < len) {
401 if (strstr(refname + reflen + 1, "report-status"))
402 report_status = 1;
404 cmd = xmalloc(sizeof(struct command) + len - 80);
405 hashcpy(cmd->old_sha1, old_sha1);
406 hashcpy(cmd->new_sha1, new_sha1);
407 memcpy(cmd->ref_name, line + 82, len - 81);
408 cmd->error_string = NULL;
409 cmd->next = NULL;
410 *p = cmd;
411 p = &cmd->next;
415 static const char *parse_pack_header(struct pack_header *hdr)
417 switch (read_pack_header(0, hdr)) {
418 case PH_ERROR_EOF:
419 return "eof before pack header was fully read";
421 case PH_ERROR_PACK_SIGNATURE:
422 return "protocol error (pack signature mismatch detected)";
424 case PH_ERROR_PROTOCOL:
425 return "protocol error (pack version unsupported)";
427 default:
428 return "unknown error in parse_pack_header";
430 case 0:
431 return NULL;
435 static const char *pack_lockfile;
437 static const char *unpack(void)
439 struct pack_header hdr;
440 const char *hdr_err;
441 char hdr_arg[38];
443 hdr_err = parse_pack_header(&hdr);
444 if (hdr_err)
445 return hdr_err;
446 snprintf(hdr_arg, sizeof(hdr_arg),
447 "--pack_header=%"PRIu32",%"PRIu32,
448 ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
450 if (ntohl(hdr.hdr_entries) < unpack_limit) {
451 int code, i = 0;
452 const char *unpacker[4];
453 unpacker[i++] = "unpack-objects";
454 if (receive_fsck_objects)
455 unpacker[i++] = "--strict";
456 unpacker[i++] = hdr_arg;
457 unpacker[i++] = NULL;
458 code = run_command_v_opt(unpacker, RUN_GIT_CMD);
459 switch (code) {
460 case 0:
461 return NULL;
462 case -ERR_RUN_COMMAND_FORK:
463 return "unpack fork failed";
464 case -ERR_RUN_COMMAND_EXEC:
465 return "unpack execute failed";
466 case -ERR_RUN_COMMAND_WAITPID:
467 return "waitpid failed";
468 case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
469 return "waitpid is confused";
470 case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
471 return "unpacker died of signal";
472 case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
473 return "unpacker died strangely";
474 default:
475 return "unpacker exited with error code";
477 } else {
478 const char *keeper[7];
479 int s, status, i = 0;
480 char keep_arg[256];
481 struct child_process ip;
483 s = sprintf(keep_arg, "--keep=receive-pack %"PRIuMAX" on ", (uintmax_t) getpid());
484 if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
485 strcpy(keep_arg + s, "localhost");
487 keeper[i++] = "index-pack";
488 keeper[i++] = "--stdin";
489 if (receive_fsck_objects)
490 keeper[i++] = "--strict";
491 keeper[i++] = "--fix-thin";
492 keeper[i++] = hdr_arg;
493 keeper[i++] = keep_arg;
494 keeper[i++] = NULL;
495 memset(&ip, 0, sizeof(ip));
496 ip.argv = keeper;
497 ip.out = -1;
498 ip.git_cmd = 1;
499 if (start_command(&ip))
500 return "index-pack fork failed";
501 pack_lockfile = index_pack_lockfile(ip.out);
502 close(ip.out);
503 status = finish_command(&ip);
504 if (!status) {
505 reprepare_packed_git();
506 return NULL;
508 return "index-pack abnormal exit";
512 static void report(const char *unpack_status)
514 struct command *cmd;
515 packet_write(1, "unpack %s\n",
516 unpack_status ? unpack_status : "ok");
517 for (cmd = commands; cmd; cmd = cmd->next) {
518 if (!cmd->error_string)
519 packet_write(1, "ok %s\n",
520 cmd->ref_name);
521 else
522 packet_write(1, "ng %s %s\n",
523 cmd->ref_name, cmd->error_string);
525 packet_flush(1);
528 static int delete_only(struct command *cmd)
530 while (cmd) {
531 if (!is_null_sha1(cmd->new_sha1))
532 return 0;
533 cmd = cmd->next;
535 return 1;
538 static int add_refs_from_alternate(struct alternate_object_database *e, void *unused)
540 char *other;
541 size_t len;
542 struct remote *remote;
543 struct transport *transport;
544 const struct ref *extra;
546 e->name[-1] = '\0';
547 other = xstrdup(make_absolute_path(e->base));
548 e->name[-1] = '/';
549 len = strlen(other);
551 while (other[len-1] == '/')
552 other[--len] = '\0';
553 if (len < 8 || memcmp(other + len - 8, "/objects", 8))
554 return 0;
555 /* Is this a git repository with refs? */
556 memcpy(other + len - 8, "/refs", 6);
557 if (!is_directory(other))
558 return 0;
559 other[len - 8] = '\0';
560 remote = remote_get(other);
561 transport = transport_get(remote, other);
562 for (extra = transport_get_remote_refs(transport);
563 extra;
564 extra = extra->next) {
565 add_extra_ref(".have", extra->old_sha1, 0);
567 transport_disconnect(transport);
568 free(other);
569 return 0;
572 static void add_alternate_refs(void)
574 foreach_alt_odb(add_refs_from_alternate, NULL);
577 int cmd_receive_pack(int argc, const char **argv, const char *prefix)
579 int i;
580 char *dir = NULL;
582 argv++;
583 for (i = 1; i < argc; i++) {
584 const char *arg = *argv++;
586 if (*arg == '-') {
587 /* Do flag handling here */
588 usage(receive_pack_usage);
590 if (dir)
591 usage(receive_pack_usage);
592 dir = xstrdup(arg);
594 if (!dir)
595 usage(receive_pack_usage);
597 setup_path();
599 if (!enter_repo(dir, 0))
600 die("'%s': unable to chdir or not a git archive", dir);
602 if (is_repository_shallow())
603 die("attempt to push into a shallow repository");
605 git_config(receive_pack_config, NULL);
607 if (0 <= transfer_unpack_limit)
608 unpack_limit = transfer_unpack_limit;
609 else if (0 <= receive_unpack_limit)
610 unpack_limit = receive_unpack_limit;
612 add_alternate_refs();
613 write_head_info();
614 clear_extra_refs();
616 /* EOF */
617 packet_flush(1);
619 read_head_info();
620 if (commands) {
621 const char *unpack_status = NULL;
623 if (!delete_only(commands))
624 unpack_status = unpack();
625 execute_commands(unpack_status);
626 if (pack_lockfile)
627 unlink(pack_lockfile);
628 if (report_status)
629 report(unpack_status);
630 run_hook(post_receive_hook);
631 run_update_post_hook(commands);
633 return 0;