Code

test-lib: fix http exit codes
[git.git] / builtin-receive-pack.c
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,
19 };
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)
35 {
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;
43         }
44         if (git_config_bool(var, value))
45                 return DENY_REFUSE;
46         return DENY_IGNORE;
47 }
49 static int receive_pack_config(const char *var, const char *value, void *cb)
50 {
51         if (strcmp(var, "receive.denydeletes") == 0) {
52                 deny_deletes = git_config_bool(var, value);
53                 return 0;
54         }
56         if (strcmp(var, "receive.denynonfastforwards") == 0) {
57                 deny_non_fast_forwards = git_config_bool(var, value);
58                 return 0;
59         }
61         if (strcmp(var, "receive.unpacklimit") == 0) {
62                 receive_unpack_limit = git_config_int(var, value);
63                 return 0;
64         }
66         if (strcmp(var, "transfer.unpacklimit") == 0) {
67                 transfer_unpack_limit = git_config_int(var, value);
68                 return 0;
69         }
71         if (strcmp(var, "receive.fsckobjects") == 0) {
72                 receive_fsck_objects = git_config_bool(var, value);
73                 return 0;
74         }
76         if (!strcmp(var, "receive.denycurrentbranch")) {
77                 deny_current_branch = parse_deny_action(var, value);
78                 return 0;
79         }
81         if (strcmp(var, "receive.denydeletecurrent") == 0) {
82                 deny_delete_current = parse_deny_action(var, value);
83                 return 0;
84         }
86         if (strcmp(var, "repack.usedeltabaseoffset") == 0) {
87                 prefer_ofs_delta = git_config_bool(var, value);
88                 return 0;
89         }
91         return git_default_config(var, value, cb);
92 }
94 static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
95 {
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 */
119 };
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 hook_status(int code, const char *hook_name)
128         switch (code) {
129         case 0:
130                 return 0;
131         case -ERR_RUN_COMMAND_FORK:
132                 return error("hook fork failed");
133         case -ERR_RUN_COMMAND_EXEC:
134                 return error("hook execute failed");
135         case -ERR_RUN_COMMAND_PIPE:
136                 return error("hook pipe failed");
137         case -ERR_RUN_COMMAND_WAITPID:
138                 return error("waitpid failed");
139         case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
140                 return error("waitpid is confused");
141         case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
142                 return error("%s died of signal", hook_name);
143         case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
144                 return error("%s died strangely", hook_name);
145         default:
146                 error("%s exited with error code %d", hook_name, -code);
147                 return -code;
148         }
151 static int run_receive_hook(const char *hook_name)
153         static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
154         struct command *cmd;
155         struct child_process proc;
156         const char *argv[2];
157         int have_input = 0, code;
159         for (cmd = commands; !have_input && cmd; cmd = cmd->next) {
160                 if (!cmd->error_string)
161                         have_input = 1;
162         }
164         if (!have_input || access(hook_name, X_OK) < 0)
165                 return 0;
167         argv[0] = hook_name;
168         argv[1] = NULL;
170         memset(&proc, 0, sizeof(proc));
171         proc.argv = argv;
172         proc.in = -1;
173         proc.stdout_to_stderr = 1;
175         code = start_command(&proc);
176         if (code)
177                 return hook_status(code, hook_name);
178         for (cmd = commands; cmd; cmd = cmd->next) {
179                 if (!cmd->error_string) {
180                         size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
181                                 sha1_to_hex(cmd->old_sha1),
182                                 sha1_to_hex(cmd->new_sha1),
183                                 cmd->ref_name);
184                         if (write_in_full(proc.in, buf, n) != n)
185                                 break;
186                 }
187         }
188         close(proc.in);
189         return hook_status(finish_command(&proc), hook_name);
192 static int run_update_hook(struct command *cmd)
194         static const char update_hook[] = "hooks/update";
195         struct child_process proc;
196         const char *argv[5];
198         if (access(update_hook, X_OK) < 0)
199                 return 0;
201         argv[0] = update_hook;
202         argv[1] = cmd->ref_name;
203         argv[2] = sha1_to_hex(cmd->old_sha1);
204         argv[3] = sha1_to_hex(cmd->new_sha1);
205         argv[4] = NULL;
207         memset(&proc, 0, sizeof(proc));
208         proc.argv = argv;
209         proc.no_stdin = 1;
210         proc.stdout_to_stderr = 1;
212         return hook_status(run_command(&proc), update_hook);
215 static int is_ref_checked_out(const char *ref)
217         if (is_bare_repository())
218                 return 0;
220         if (!head_name)
221                 return 0;
222         return !strcmp(head_name, ref);
225 static char *warn_unconfigured_deny_msg[] = {
226         "Updating the currently checked out branch may cause confusion,",
227         "as the index and work tree do not reflect changes that are in HEAD.",
228         "As a result, you may see the changes you just pushed into it",
229         "reverted when you run 'git diff' over there, and you may want",
230         "to run 'git reset --hard' before starting to work to recover.",
231         "",
232         "You can set 'receive.denyCurrentBranch' configuration variable to",
233         "'refuse' in the remote repository to forbid pushing into its",
234         "current branch."
235         "",
236         "To allow pushing into the current branch, you can set it to 'ignore';",
237         "but this is not recommended unless you arranged to update its work",
238         "tree to match what you pushed in some other way.",
239         "",
240         "To squelch this message, you can set it to 'warn'.",
241         "",
242         "Note that the default will change in a future version of git",
243         "to refuse updating the current branch unless you have the",
244         "configuration variable set to either 'ignore' or 'warn'."
245 };
247 static void warn_unconfigured_deny(void)
249         int i;
250         for (i = 0; i < ARRAY_SIZE(warn_unconfigured_deny_msg); i++)
251                 warning("%s", warn_unconfigured_deny_msg[i]);
254 static char *warn_unconfigured_deny_delete_current_msg[] = {
255         "Deleting the current branch can cause confusion by making the next",
256         "'git clone' not check out any file.",
257         "",
258         "You can set 'receive.denyDeleteCurrent' configuration variable to",
259         "'refuse' in the remote repository to disallow deleting the current",
260         "branch.",
261         "",
262         "You can set it to 'ignore' to allow such a delete without a warning.",
263         "",
264         "To make this warning message less loud, you can set it to 'warn'.",
265         "",
266         "Note that the default will change in a future version of git",
267         "to refuse deleting the current branch unless you have the",
268         "configuration variable set to either 'ignore' or 'warn'."
269 };
271 static void warn_unconfigured_deny_delete_current(void)
273         int i;
274         for (i = 0;
275              i < ARRAY_SIZE(warn_unconfigured_deny_delete_current_msg);
276              i++)
277                 warning("%s", warn_unconfigured_deny_delete_current_msg[i]);
280 static const char *update(struct command *cmd)
282         const char *name = cmd->ref_name;
283         unsigned char *old_sha1 = cmd->old_sha1;
284         unsigned char *new_sha1 = cmd->new_sha1;
285         struct ref_lock *lock;
287         /* only refs/... are allowed */
288         if (prefixcmp(name, "refs/") || check_ref_format(name + 5)) {
289                 error("refusing to create funny ref '%s' remotely", name);
290                 return "funny refname";
291         }
293         if (is_ref_checked_out(name)) {
294                 switch (deny_current_branch) {
295                 case DENY_IGNORE:
296                         break;
297                 case DENY_UNCONFIGURED:
298                 case DENY_WARN:
299                         warning("updating the current branch");
300                         if (deny_current_branch == DENY_UNCONFIGURED)
301                                 warn_unconfigured_deny();
302                         break;
303                 case DENY_REFUSE:
304                         error("refusing to update checked out branch: %s", name);
305                         return "branch is currently checked out";
306                 }
307         }
309         if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
310                 error("unpack should have generated %s, "
311                       "but I can't find it!", sha1_to_hex(new_sha1));
312                 return "bad pack";
313         }
315         if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) {
316                 if (deny_deletes && !prefixcmp(name, "refs/heads/")) {
317                         error("denying ref deletion for %s", name);
318                         return "deletion prohibited";
319                 }
321                 if (!strcmp(name, head_name)) {
322                         switch (deny_delete_current) {
323                         case DENY_IGNORE:
324                                 break;
325                         case DENY_WARN:
326                         case DENY_UNCONFIGURED:
327                                 if (deny_delete_current == DENY_UNCONFIGURED)
328                                         warn_unconfigured_deny_delete_current();
329                                 warning("deleting the current branch");
330                                 break;
331                         case DENY_REFUSE:
332                                 error("refusing to delete the current branch: %s", name);
333                                 return "deletion of the current branch prohibited";
334                         }
335                 }
336         }
338         if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
339             !is_null_sha1(old_sha1) &&
340             !prefixcmp(name, "refs/heads/")) {
341                 struct object *old_object, *new_object;
342                 struct commit *old_commit, *new_commit;
343                 struct commit_list *bases, *ent;
345                 old_object = parse_object(old_sha1);
346                 new_object = parse_object(new_sha1);
348                 if (!old_object || !new_object ||
349                     old_object->type != OBJ_COMMIT ||
350                     new_object->type != OBJ_COMMIT) {
351                         error("bad sha1 objects for %s", name);
352                         return "bad ref";
353                 }
354                 old_commit = (struct commit *)old_object;
355                 new_commit = (struct commit *)new_object;
356                 bases = get_merge_bases(old_commit, new_commit, 1);
357                 for (ent = bases; ent; ent = ent->next)
358                         if (!hashcmp(old_sha1, ent->item->object.sha1))
359                                 break;
360                 free_commit_list(bases);
361                 if (!ent) {
362                         error("denying non-fast forward %s"
363                               " (you should pull first)", name);
364                         return "non-fast forward";
365                 }
366         }
367         if (run_update_hook(cmd)) {
368                 error("hook declined to update %s", name);
369                 return "hook declined";
370         }
372         if (is_null_sha1(new_sha1)) {
373                 if (!parse_object(old_sha1)) {
374                         warning ("Allowing deletion of corrupt ref.");
375                         old_sha1 = NULL;
376                 }
377                 if (delete_ref(name, old_sha1, 0)) {
378                         error("failed to delete %s", name);
379                         return "failed to delete";
380                 }
381                 return NULL; /* good */
382         }
383         else {
384                 lock = lock_any_ref_for_update(name, old_sha1, 0);
385                 if (!lock) {
386                         error("failed to lock %s", name);
387                         return "failed to lock";
388                 }
389                 if (write_ref_sha1(lock, new_sha1, "push")) {
390                         return "failed to write"; /* error() already called */
391                 }
392                 return NULL; /* good */
393         }
396 static char update_post_hook[] = "hooks/post-update";
398 static void run_update_post_hook(struct command *cmd)
400         struct command *cmd_p;
401         int argc;
402         const char **argv;
404         for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
405                 if (cmd_p->error_string)
406                         continue;
407                 argc++;
408         }
409         if (!argc || access(update_post_hook, X_OK) < 0)
410                 return;
411         argv = xmalloc(sizeof(*argv) * (2 + argc));
412         argv[0] = update_post_hook;
414         for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
415                 char *p;
416                 if (cmd_p->error_string)
417                         continue;
418                 p = xmalloc(strlen(cmd_p->ref_name) + 1);
419                 strcpy(p, cmd_p->ref_name);
420                 argv[argc] = p;
421                 argc++;
422         }
423         argv[argc] = NULL;
424         run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
425                 | RUN_COMMAND_STDOUT_TO_STDERR);
428 static void execute_commands(const char *unpacker_error)
430         struct command *cmd = commands;
431         unsigned char sha1[20];
433         if (unpacker_error) {
434                 while (cmd) {
435                         cmd->error_string = "n/a (unpacker error)";
436                         cmd = cmd->next;
437                 }
438                 return;
439         }
441         if (run_receive_hook(pre_receive_hook)) {
442                 while (cmd) {
443                         cmd->error_string = "pre-receive hook declined";
444                         cmd = cmd->next;
445                 }
446                 return;
447         }
449         head_name = resolve_ref("HEAD", sha1, 0, NULL);
451         while (cmd) {
452                 cmd->error_string = update(cmd);
453                 cmd = cmd->next;
454         }
457 static void read_head_info(void)
459         struct command **p = &commands;
460         for (;;) {
461                 static char line[1000];
462                 unsigned char old_sha1[20], new_sha1[20];
463                 struct command *cmd;
464                 char *refname;
465                 int len, reflen;
467                 len = packet_read_line(0, line, sizeof(line));
468                 if (!len)
469                         break;
470                 if (line[len-1] == '\n')
471                         line[--len] = 0;
472                 if (len < 83 ||
473                     line[40] != ' ' ||
474                     line[81] != ' ' ||
475                     get_sha1_hex(line, old_sha1) ||
476                     get_sha1_hex(line + 41, new_sha1))
477                         die("protocol error: expected old/new/ref, got '%s'",
478                             line);
480                 refname = line + 82;
481                 reflen = strlen(refname);
482                 if (reflen + 82 < len) {
483                         if (strstr(refname + reflen + 1, "report-status"))
484                                 report_status = 1;
485                 }
486                 cmd = xmalloc(sizeof(struct command) + len - 80);
487                 hashcpy(cmd->old_sha1, old_sha1);
488                 hashcpy(cmd->new_sha1, new_sha1);
489                 memcpy(cmd->ref_name, line + 82, len - 81);
490                 cmd->error_string = NULL;
491                 cmd->next = NULL;
492                 *p = cmd;
493                 p = &cmd->next;
494         }
497 static const char *parse_pack_header(struct pack_header *hdr)
499         switch (read_pack_header(0, hdr)) {
500         case PH_ERROR_EOF:
501                 return "eof before pack header was fully read";
503         case PH_ERROR_PACK_SIGNATURE:
504                 return "protocol error (pack signature mismatch detected)";
506         case PH_ERROR_PROTOCOL:
507                 return "protocol error (pack version unsupported)";
509         default:
510                 return "unknown error in parse_pack_header";
512         case 0:
513                 return NULL;
514         }
517 static const char *pack_lockfile;
519 static const char *unpack(void)
521         struct pack_header hdr;
522         const char *hdr_err;
523         char hdr_arg[38];
525         hdr_err = parse_pack_header(&hdr);
526         if (hdr_err)
527                 return hdr_err;
528         snprintf(hdr_arg, sizeof(hdr_arg),
529                         "--pack_header=%"PRIu32",%"PRIu32,
530                         ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
532         if (ntohl(hdr.hdr_entries) < unpack_limit) {
533                 int code, i = 0;
534                 const char *unpacker[4];
535                 unpacker[i++] = "unpack-objects";
536                 if (receive_fsck_objects)
537                         unpacker[i++] = "--strict";
538                 unpacker[i++] = hdr_arg;
539                 unpacker[i++] = NULL;
540                 code = run_command_v_opt(unpacker, RUN_GIT_CMD);
541                 switch (code) {
542                 case 0:
543                         return NULL;
544                 case -ERR_RUN_COMMAND_FORK:
545                         return "unpack fork failed";
546                 case -ERR_RUN_COMMAND_EXEC:
547                         return "unpack execute failed";
548                 case -ERR_RUN_COMMAND_WAITPID:
549                         return "waitpid failed";
550                 case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
551                         return "waitpid is confused";
552                 case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
553                         return "unpacker died of signal";
554                 case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
555                         return "unpacker died strangely";
556                 default:
557                         return "unpacker exited with error code";
558                 }
559         } else {
560                 const char *keeper[7];
561                 int s, status, i = 0;
562                 char keep_arg[256];
563                 struct child_process ip;
565                 s = sprintf(keep_arg, "--keep=receive-pack %"PRIuMAX" on ", (uintmax_t) getpid());
566                 if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
567                         strcpy(keep_arg + s, "localhost");
569                 keeper[i++] = "index-pack";
570                 keeper[i++] = "--stdin";
571                 if (receive_fsck_objects)
572                         keeper[i++] = "--strict";
573                 keeper[i++] = "--fix-thin";
574                 keeper[i++] = hdr_arg;
575                 keeper[i++] = keep_arg;
576                 keeper[i++] = NULL;
577                 memset(&ip, 0, sizeof(ip));
578                 ip.argv = keeper;
579                 ip.out = -1;
580                 ip.git_cmd = 1;
581                 if (start_command(&ip))
582                         return "index-pack fork failed";
583                 pack_lockfile = index_pack_lockfile(ip.out);
584                 close(ip.out);
585                 status = finish_command(&ip);
586                 if (!status) {
587                         reprepare_packed_git();
588                         return NULL;
589                 }
590                 return "index-pack abnormal exit";
591         }
594 static void report(const char *unpack_status)
596         struct command *cmd;
597         packet_write(1, "unpack %s\n",
598                      unpack_status ? unpack_status : "ok");
599         for (cmd = commands; cmd; cmd = cmd->next) {
600                 if (!cmd->error_string)
601                         packet_write(1, "ok %s\n",
602                                      cmd->ref_name);
603                 else
604                         packet_write(1, "ng %s %s\n",
605                                      cmd->ref_name, cmd->error_string);
606         }
607         packet_flush(1);
610 static int delete_only(struct command *cmd)
612         while (cmd) {
613                 if (!is_null_sha1(cmd->new_sha1))
614                         return 0;
615                 cmd = cmd->next;
616         }
617         return 1;
620 static int add_refs_from_alternate(struct alternate_object_database *e, void *unused)
622         char *other;
623         size_t len;
624         struct remote *remote;
625         struct transport *transport;
626         const struct ref *extra;
628         e->name[-1] = '\0';
629         other = xstrdup(make_absolute_path(e->base));
630         e->name[-1] = '/';
631         len = strlen(other);
633         while (other[len-1] == '/')
634                 other[--len] = '\0';
635         if (len < 8 || memcmp(other + len - 8, "/objects", 8))
636                 return 0;
637         /* Is this a git repository with refs? */
638         memcpy(other + len - 8, "/refs", 6);
639         if (!is_directory(other))
640                 return 0;
641         other[len - 8] = '\0';
642         remote = remote_get(other);
643         transport = transport_get(remote, other);
644         for (extra = transport_get_remote_refs(transport);
645              extra;
646              extra = extra->next) {
647                 add_extra_ref(".have", extra->old_sha1, 0);
648         }
649         transport_disconnect(transport);
650         free(other);
651         return 0;
654 static void add_alternate_refs(void)
656         foreach_alt_odb(add_refs_from_alternate, NULL);
659 int cmd_receive_pack(int argc, const char **argv, const char *prefix)
661         int i;
662         char *dir = NULL;
664         argv++;
665         for (i = 1; i < argc; i++) {
666                 const char *arg = *argv++;
668                 if (*arg == '-') {
669                         /* Do flag handling here */
670                         usage(receive_pack_usage);
671                 }
672                 if (dir)
673                         usage(receive_pack_usage);
674                 dir = xstrdup(arg);
675         }
676         if (!dir)
677                 usage(receive_pack_usage);
679         setup_path();
681         if (!enter_repo(dir, 0))
682                 die("'%s' does not appear to be a git repository", dir);
684         if (is_repository_shallow())
685                 die("attempt to push into a shallow repository");
687         git_config(receive_pack_config, NULL);
689         if (0 <= transfer_unpack_limit)
690                 unpack_limit = transfer_unpack_limit;
691         else if (0 <= receive_unpack_limit)
692                 unpack_limit = receive_unpack_limit;
694         capabilities_to_send = (prefer_ofs_delta) ?
695                 " report-status delete-refs ofs-delta " :
696                 " report-status delete-refs ";
698         add_alternate_refs();
699         write_head_info();
700         clear_extra_refs();
702         /* EOF */
703         packet_flush(1);
705         read_head_info();
706         if (commands) {
707                 const char *unpack_status = NULL;
709                 if (!delete_only(commands))
710                         unpack_status = unpack();
711                 execute_commands(unpack_status);
712                 if (pack_lockfile)
713                         unlink_or_warn(pack_lockfile);
714                 if (report_status)
715                         report(unpack_status);
716                 run_receive_hook(post_receive_hook);
717                 run_update_post_hook(commands);
718         }
719         return 0;