run_command: report system call errors instead of returning error codes
[git/ericb.git] / builtin-receive-pack.c
blob1dcdb1a514780cc80ae84b5a9f4aa6bc78c0df14
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_UNCONFIGURED,
16 DENY_IGNORE,
17 DENY_WARN,
18 DENY_REFUSE,
21 static int deny_deletes;
22 static int deny_non_fast_forwards;
23 static enum deny_action deny_current_branch = DENY_UNCONFIGURED;
24 static enum deny_action deny_delete_current = DENY_UNCONFIGURED;
25 static int receive_fsck_objects;
26 static int receive_unpack_limit = -1;
27 static int transfer_unpack_limit = -1;
28 static int unpack_limit = 100;
29 static int report_status;
30 static int prefer_ofs_delta = 1;
31 static const char *head_name;
32 static char *capabilities_to_send;
34 static enum deny_action parse_deny_action(const char *var, const char *value)
36 if (value) {
37 if (!strcasecmp(value, "ignore"))
38 return DENY_IGNORE;
39 if (!strcasecmp(value, "warn"))
40 return DENY_WARN;
41 if (!strcasecmp(value, "refuse"))
42 return DENY_REFUSE;
44 if (git_config_bool(var, value))
45 return DENY_REFUSE;
46 return DENY_IGNORE;
49 static int receive_pack_config(const char *var, const char *value, void *cb)
51 if (strcmp(var, "receive.denydeletes") == 0) {
52 deny_deletes = git_config_bool(var, value);
53 return 0;
56 if (strcmp(var, "receive.denynonfastforwards") == 0) {
57 deny_non_fast_forwards = git_config_bool(var, value);
58 return 0;
61 if (strcmp(var, "receive.unpacklimit") == 0) {
62 receive_unpack_limit = git_config_int(var, value);
63 return 0;
66 if (strcmp(var, "transfer.unpacklimit") == 0) {
67 transfer_unpack_limit = git_config_int(var, value);
68 return 0;
71 if (strcmp(var, "receive.fsckobjects") == 0) {
72 receive_fsck_objects = git_config_bool(var, value);
73 return 0;
76 if (!strcmp(var, "receive.denycurrentbranch")) {
77 deny_current_branch = parse_deny_action(var, value);
78 return 0;
81 if (strcmp(var, "receive.denydeletecurrent") == 0) {
82 deny_delete_current = parse_deny_action(var, value);
83 return 0;
86 if (strcmp(var, "repack.usedeltabaseoffset") == 0) {
87 prefer_ofs_delta = git_config_bool(var, value);
88 return 0;
91 return git_default_config(var, value, cb);
94 static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
96 if (!capabilities_to_send)
97 packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
98 else
99 packet_write(1, "%s %s%c%s\n",
100 sha1_to_hex(sha1), path, 0, capabilities_to_send);
101 capabilities_to_send = NULL;
102 return 0;
105 static void write_head_info(void)
107 for_each_ref(show_ref, NULL);
108 if (capabilities_to_send)
109 show_ref("capabilities^{}", null_sha1, 0, NULL);
113 struct command {
114 struct command *next;
115 const char *error_string;
116 unsigned char old_sha1[20];
117 unsigned char new_sha1[20];
118 char ref_name[FLEX_ARRAY]; /* more */
121 static struct command *commands;
123 static const char pre_receive_hook[] = "hooks/pre-receive";
124 static const char post_receive_hook[] = "hooks/post-receive";
126 static int run_status(int code, const char *cmd_name)
128 if (code < 0 && errno == ENOENT)
129 return error("execute of %s failed", cmd_name);
130 else if (code > 0)
131 error("%s exited with error code %d", cmd_name, code);
132 return code;
135 static int run_receive_hook(const char *hook_name)
137 static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
138 struct command *cmd;
139 struct child_process proc;
140 const char *argv[2];
141 int have_input = 0, code;
143 for (cmd = commands; !have_input && cmd; cmd = cmd->next) {
144 if (!cmd->error_string)
145 have_input = 1;
148 if (!have_input || access(hook_name, X_OK) < 0)
149 return 0;
151 argv[0] = hook_name;
152 argv[1] = NULL;
154 memset(&proc, 0, sizeof(proc));
155 proc.argv = argv;
156 proc.in = -1;
157 proc.stdout_to_stderr = 1;
159 code = start_command(&proc);
160 if (code)
161 return run_status(code, hook_name);
162 for (cmd = commands; cmd; cmd = cmd->next) {
163 if (!cmd->error_string) {
164 size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
165 sha1_to_hex(cmd->old_sha1),
166 sha1_to_hex(cmd->new_sha1),
167 cmd->ref_name);
168 if (write_in_full(proc.in, buf, n) != n)
169 break;
172 close(proc.in);
173 return run_status(finish_command(&proc), hook_name);
176 static int run_update_hook(struct command *cmd)
178 static const char update_hook[] = "hooks/update";
179 const char *argv[5];
181 if (access(update_hook, X_OK) < 0)
182 return 0;
184 argv[0] = update_hook;
185 argv[1] = cmd->ref_name;
186 argv[2] = sha1_to_hex(cmd->old_sha1);
187 argv[3] = sha1_to_hex(cmd->new_sha1);
188 argv[4] = NULL;
190 return run_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
191 RUN_COMMAND_STDOUT_TO_STDERR),
192 update_hook);
195 static int is_ref_checked_out(const char *ref)
197 if (is_bare_repository())
198 return 0;
200 if (!head_name)
201 return 0;
202 return !strcmp(head_name, ref);
205 static char *warn_unconfigured_deny_msg[] = {
206 "Updating the currently checked out branch may cause confusion,",
207 "as the index and work tree do not reflect changes that are in HEAD.",
208 "As a result, you may see the changes you just pushed into it",
209 "reverted when you run 'git diff' over there, and you may want",
210 "to run 'git reset --hard' before starting to work to recover.",
212 "You can set 'receive.denyCurrentBranch' configuration variable to",
213 "'refuse' in the remote repository to forbid pushing into its",
214 "current branch."
216 "To allow pushing into the current branch, you can set it to 'ignore';",
217 "but this is not recommended unless you arranged to update its work",
218 "tree to match what you pushed in some other way.",
220 "To squelch this message, you can set it to 'warn'.",
222 "Note that the default will change in a future version of git",
223 "to refuse updating the current branch unless you have the",
224 "configuration variable set to either 'ignore' or 'warn'."
227 static void warn_unconfigured_deny(void)
229 int i;
230 for (i = 0; i < ARRAY_SIZE(warn_unconfigured_deny_msg); i++)
231 warning("%s", warn_unconfigured_deny_msg[i]);
234 static char *warn_unconfigured_deny_delete_current_msg[] = {
235 "Deleting the current branch can cause confusion by making the next",
236 "'git clone' not check out any file.",
238 "You can set 'receive.denyDeleteCurrent' configuration variable to",
239 "'refuse' in the remote repository to disallow deleting the current",
240 "branch.",
242 "You can set it to 'ignore' to allow such a delete without a warning.",
244 "To make this warning message less loud, you can set it to 'warn'.",
246 "Note that the default will change in a future version of git",
247 "to refuse deleting the current branch unless you have the",
248 "configuration variable set to either 'ignore' or 'warn'."
251 static void warn_unconfigured_deny_delete_current(void)
253 int i;
254 for (i = 0;
255 i < ARRAY_SIZE(warn_unconfigured_deny_delete_current_msg);
256 i++)
257 warning("%s", warn_unconfigured_deny_delete_current_msg[i]);
260 static const char *update(struct command *cmd)
262 const char *name = cmd->ref_name;
263 unsigned char *old_sha1 = cmd->old_sha1;
264 unsigned char *new_sha1 = cmd->new_sha1;
265 struct ref_lock *lock;
267 /* only refs/... are allowed */
268 if (prefixcmp(name, "refs/") || check_ref_format(name + 5)) {
269 error("refusing to create funny ref '%s' remotely", name);
270 return "funny refname";
273 if (is_ref_checked_out(name)) {
274 switch (deny_current_branch) {
275 case DENY_IGNORE:
276 break;
277 case DENY_UNCONFIGURED:
278 case DENY_WARN:
279 warning("updating the current branch");
280 if (deny_current_branch == DENY_UNCONFIGURED)
281 warn_unconfigured_deny();
282 break;
283 case DENY_REFUSE:
284 error("refusing to update checked out branch: %s", name);
285 return "branch is currently checked out";
289 if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
290 error("unpack should have generated %s, "
291 "but I can't find it!", sha1_to_hex(new_sha1));
292 return "bad pack";
295 if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) {
296 if (deny_deletes && !prefixcmp(name, "refs/heads/")) {
297 error("denying ref deletion for %s", name);
298 return "deletion prohibited";
301 if (!strcmp(name, head_name)) {
302 switch (deny_delete_current) {
303 case DENY_IGNORE:
304 break;
305 case DENY_WARN:
306 case DENY_UNCONFIGURED:
307 if (deny_delete_current == DENY_UNCONFIGURED)
308 warn_unconfigured_deny_delete_current();
309 warning("deleting the current branch");
310 break;
311 case DENY_REFUSE:
312 error("refusing to delete the current branch: %s", name);
313 return "deletion of the current branch prohibited";
318 if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
319 !is_null_sha1(old_sha1) &&
320 !prefixcmp(name, "refs/heads/")) {
321 struct object *old_object, *new_object;
322 struct commit *old_commit, *new_commit;
323 struct commit_list *bases, *ent;
325 old_object = parse_object(old_sha1);
326 new_object = parse_object(new_sha1);
328 if (!old_object || !new_object ||
329 old_object->type != OBJ_COMMIT ||
330 new_object->type != OBJ_COMMIT) {
331 error("bad sha1 objects for %s", name);
332 return "bad ref";
334 old_commit = (struct commit *)old_object;
335 new_commit = (struct commit *)new_object;
336 bases = get_merge_bases(old_commit, new_commit, 1);
337 for (ent = bases; ent; ent = ent->next)
338 if (!hashcmp(old_sha1, ent->item->object.sha1))
339 break;
340 free_commit_list(bases);
341 if (!ent) {
342 error("denying non-fast forward %s"
343 " (you should pull first)", name);
344 return "non-fast forward";
347 if (run_update_hook(cmd)) {
348 error("hook declined to update %s", name);
349 return "hook declined";
352 if (is_null_sha1(new_sha1)) {
353 if (!parse_object(old_sha1)) {
354 warning ("Allowing deletion of corrupt ref.");
355 old_sha1 = NULL;
357 if (delete_ref(name, old_sha1, 0)) {
358 error("failed to delete %s", name);
359 return "failed to delete";
361 return NULL; /* good */
363 else {
364 lock = lock_any_ref_for_update(name, old_sha1, 0);
365 if (!lock) {
366 error("failed to lock %s", name);
367 return "failed to lock";
369 if (write_ref_sha1(lock, new_sha1, "push")) {
370 return "failed to write"; /* error() already called */
372 return NULL; /* good */
376 static char update_post_hook[] = "hooks/post-update";
378 static void run_update_post_hook(struct command *cmd)
380 struct command *cmd_p;
381 int argc, status;
382 const char **argv;
384 for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
385 if (cmd_p->error_string)
386 continue;
387 argc++;
389 if (!argc || access(update_post_hook, X_OK) < 0)
390 return;
391 argv = xmalloc(sizeof(*argv) * (2 + argc));
392 argv[0] = update_post_hook;
394 for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
395 char *p;
396 if (cmd_p->error_string)
397 continue;
398 p = xmalloc(strlen(cmd_p->ref_name) + 1);
399 strcpy(p, cmd_p->ref_name);
400 argv[argc] = p;
401 argc++;
403 argv[argc] = NULL;
404 status = run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
405 | RUN_COMMAND_STDOUT_TO_STDERR);
406 run_status(status, update_post_hook);
409 static void execute_commands(const char *unpacker_error)
411 struct command *cmd = commands;
412 unsigned char sha1[20];
414 if (unpacker_error) {
415 while (cmd) {
416 cmd->error_string = "n/a (unpacker error)";
417 cmd = cmd->next;
419 return;
422 if (run_receive_hook(pre_receive_hook)) {
423 while (cmd) {
424 cmd->error_string = "pre-receive hook declined";
425 cmd = cmd->next;
427 return;
430 head_name = resolve_ref("HEAD", sha1, 0, NULL);
432 while (cmd) {
433 cmd->error_string = update(cmd);
434 cmd = cmd->next;
438 static void read_head_info(void)
440 struct command **p = &commands;
441 for (;;) {
442 static char line[1000];
443 unsigned char old_sha1[20], new_sha1[20];
444 struct command *cmd;
445 char *refname;
446 int len, reflen;
448 len = packet_read_line(0, line, sizeof(line));
449 if (!len)
450 break;
451 if (line[len-1] == '\n')
452 line[--len] = 0;
453 if (len < 83 ||
454 line[40] != ' ' ||
455 line[81] != ' ' ||
456 get_sha1_hex(line, old_sha1) ||
457 get_sha1_hex(line + 41, new_sha1))
458 die("protocol error: expected old/new/ref, got '%s'",
459 line);
461 refname = line + 82;
462 reflen = strlen(refname);
463 if (reflen + 82 < len) {
464 if (strstr(refname + reflen + 1, "report-status"))
465 report_status = 1;
467 cmd = xmalloc(sizeof(struct command) + len - 80);
468 hashcpy(cmd->old_sha1, old_sha1);
469 hashcpy(cmd->new_sha1, new_sha1);
470 memcpy(cmd->ref_name, line + 82, len - 81);
471 cmd->error_string = NULL;
472 cmd->next = NULL;
473 *p = cmd;
474 p = &cmd->next;
478 static const char *parse_pack_header(struct pack_header *hdr)
480 switch (read_pack_header(0, hdr)) {
481 case PH_ERROR_EOF:
482 return "eof before pack header was fully read";
484 case PH_ERROR_PACK_SIGNATURE:
485 return "protocol error (pack signature mismatch detected)";
487 case PH_ERROR_PROTOCOL:
488 return "protocol error (pack version unsupported)";
490 default:
491 return "unknown error in parse_pack_header";
493 case 0:
494 return NULL;
498 static const char *pack_lockfile;
500 static const char *unpack(void)
502 struct pack_header hdr;
503 const char *hdr_err;
504 char hdr_arg[38];
506 hdr_err = parse_pack_header(&hdr);
507 if (hdr_err)
508 return hdr_err;
509 snprintf(hdr_arg, sizeof(hdr_arg),
510 "--pack_header=%"PRIu32",%"PRIu32,
511 ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
513 if (ntohl(hdr.hdr_entries) < unpack_limit) {
514 int code, i = 0;
515 const char *unpacker[4];
516 unpacker[i++] = "unpack-objects";
517 if (receive_fsck_objects)
518 unpacker[i++] = "--strict";
519 unpacker[i++] = hdr_arg;
520 unpacker[i++] = NULL;
521 code = run_command_v_opt(unpacker, RUN_GIT_CMD);
522 if (!code)
523 return NULL;
524 run_status(code, unpacker[0]);
525 return "unpack-objects abnormal exit";
526 } else {
527 const char *keeper[7];
528 int s, status, i = 0;
529 char keep_arg[256];
530 struct child_process ip;
532 s = sprintf(keep_arg, "--keep=receive-pack %"PRIuMAX" on ", (uintmax_t) getpid());
533 if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
534 strcpy(keep_arg + s, "localhost");
536 keeper[i++] = "index-pack";
537 keeper[i++] = "--stdin";
538 if (receive_fsck_objects)
539 keeper[i++] = "--strict";
540 keeper[i++] = "--fix-thin";
541 keeper[i++] = hdr_arg;
542 keeper[i++] = keep_arg;
543 keeper[i++] = NULL;
544 memset(&ip, 0, sizeof(ip));
545 ip.argv = keeper;
546 ip.out = -1;
547 ip.git_cmd = 1;
548 status = start_command(&ip);
549 if (status) {
550 run_status(status, keeper[0]);
551 return "index-pack fork failed";
553 pack_lockfile = index_pack_lockfile(ip.out);
554 close(ip.out);
555 status = finish_command(&ip);
556 if (!status) {
557 reprepare_packed_git();
558 return NULL;
560 run_status(status, keeper[0]);
561 return "index-pack abnormal exit";
565 static void report(const char *unpack_status)
567 struct command *cmd;
568 packet_write(1, "unpack %s\n",
569 unpack_status ? unpack_status : "ok");
570 for (cmd = commands; cmd; cmd = cmd->next) {
571 if (!cmd->error_string)
572 packet_write(1, "ok %s\n",
573 cmd->ref_name);
574 else
575 packet_write(1, "ng %s %s\n",
576 cmd->ref_name, cmd->error_string);
578 packet_flush(1);
581 static int delete_only(struct command *cmd)
583 while (cmd) {
584 if (!is_null_sha1(cmd->new_sha1))
585 return 0;
586 cmd = cmd->next;
588 return 1;
591 static int add_refs_from_alternate(struct alternate_object_database *e, void *unused)
593 char *other;
594 size_t len;
595 struct remote *remote;
596 struct transport *transport;
597 const struct ref *extra;
599 e->name[-1] = '\0';
600 other = xstrdup(make_absolute_path(e->base));
601 e->name[-1] = '/';
602 len = strlen(other);
604 while (other[len-1] == '/')
605 other[--len] = '\0';
606 if (len < 8 || memcmp(other + len - 8, "/objects", 8))
607 return 0;
608 /* Is this a git repository with refs? */
609 memcpy(other + len - 8, "/refs", 6);
610 if (!is_directory(other))
611 return 0;
612 other[len - 8] = '\0';
613 remote = remote_get(other);
614 transport = transport_get(remote, other);
615 for (extra = transport_get_remote_refs(transport);
616 extra;
617 extra = extra->next) {
618 add_extra_ref(".have", extra->old_sha1, 0);
620 transport_disconnect(transport);
621 free(other);
622 return 0;
625 static void add_alternate_refs(void)
627 foreach_alt_odb(add_refs_from_alternate, NULL);
630 int cmd_receive_pack(int argc, const char **argv, const char *prefix)
632 int i;
633 char *dir = NULL;
635 argv++;
636 for (i = 1; i < argc; i++) {
637 const char *arg = *argv++;
639 if (*arg == '-') {
640 /* Do flag handling here */
641 usage(receive_pack_usage);
643 if (dir)
644 usage(receive_pack_usage);
645 dir = xstrdup(arg);
647 if (!dir)
648 usage(receive_pack_usage);
650 setup_path();
652 if (!enter_repo(dir, 0))
653 die("'%s' does not appear to be a git repository", dir);
655 if (is_repository_shallow())
656 die("attempt to push into a shallow repository");
658 git_config(receive_pack_config, NULL);
660 if (0 <= transfer_unpack_limit)
661 unpack_limit = transfer_unpack_limit;
662 else if (0 <= receive_unpack_limit)
663 unpack_limit = receive_unpack_limit;
665 capabilities_to_send = (prefer_ofs_delta) ?
666 " report-status delete-refs ofs-delta " :
667 " report-status delete-refs ";
669 add_alternate_refs();
670 write_head_info();
671 clear_extra_refs();
673 /* EOF */
674 packet_flush(1);
676 read_head_info();
677 if (commands) {
678 const char *unpack_status = NULL;
680 if (!delete_only(commands))
681 unpack_status = unpack();
682 execute_commands(unpack_status);
683 if (pack_lockfile)
684 unlink_or_warn(pack_lockfile);
685 if (report_status)
686 report(unpack_status);
687 run_receive_hook(post_receive_hook);
688 run_update_post_hook(commands);
690 return 0;