status: refactor format option parsing
[git/ericb.git] / builtin-receive-pack.c
blob6ec1d056e6fa24bf6008d9114df5d5cdacd837af
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 switch (code) {
129 case 0:
130 return 0;
131 case -ERR_RUN_COMMAND_FORK:
132 return error("fork of %s failed", cmd_name);
133 case -ERR_RUN_COMMAND_EXEC:
134 return error("execute of %s failed", cmd_name);
135 case -ERR_RUN_COMMAND_PIPE:
136 return error("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", cmd_name);
143 case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
144 return error("%s died strangely", cmd_name);
145 default:
146 error("%s exited with error code %d", cmd_name, -code);
147 return -code;
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;
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 run_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;
188 close(proc.in);
189 return run_status(finish_command(&proc), hook_name);
192 static int run_update_hook(struct command *cmd)
194 static const char update_hook[] = "hooks/update";
195 const char *argv[5];
197 if (access(update_hook, X_OK) < 0)
198 return 0;
200 argv[0] = update_hook;
201 argv[1] = cmd->ref_name;
202 argv[2] = sha1_to_hex(cmd->old_sha1);
203 argv[3] = sha1_to_hex(cmd->new_sha1);
204 argv[4] = NULL;
206 return run_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
207 RUN_COMMAND_STDOUT_TO_STDERR),
208 update_hook);
211 static int is_ref_checked_out(const char *ref)
213 if (is_bare_repository())
214 return 0;
216 if (!head_name)
217 return 0;
218 return !strcmp(head_name, ref);
221 static char *warn_unconfigured_deny_msg[] = {
222 "Updating the currently checked out branch may cause confusion,",
223 "as the index and work tree do not reflect changes that are in HEAD.",
224 "As a result, you may see the changes you just pushed into it",
225 "reverted when you run 'git diff' over there, and you may want",
226 "to run 'git reset --hard' before starting to work to recover.",
228 "You can set 'receive.denyCurrentBranch' configuration variable to",
229 "'refuse' in the remote repository to forbid pushing into its",
230 "current branch."
232 "To allow pushing into the current branch, you can set it to 'ignore';",
233 "but this is not recommended unless you arranged to update its work",
234 "tree to match what you pushed in some other way.",
236 "To squelch this message, you can set it to 'warn'.",
238 "Note that the default will change in a future version of git",
239 "to refuse updating the current branch unless you have the",
240 "configuration variable set to either 'ignore' or 'warn'."
243 static void warn_unconfigured_deny(void)
245 int i;
246 for (i = 0; i < ARRAY_SIZE(warn_unconfigured_deny_msg); i++)
247 warning("%s", warn_unconfigured_deny_msg[i]);
250 static char *warn_unconfigured_deny_delete_current_msg[] = {
251 "Deleting the current branch can cause confusion by making the next",
252 "'git clone' not check out any file.",
254 "You can set 'receive.denyDeleteCurrent' configuration variable to",
255 "'refuse' in the remote repository to disallow deleting the current",
256 "branch.",
258 "You can set it to 'ignore' to allow such a delete without a warning.",
260 "To make this warning message less loud, you can set it to 'warn'.",
262 "Note that the default will change in a future version of git",
263 "to refuse deleting the current branch unless you have the",
264 "configuration variable set to either 'ignore' or 'warn'."
267 static void warn_unconfigured_deny_delete_current(void)
269 int i;
270 for (i = 0;
271 i < ARRAY_SIZE(warn_unconfigured_deny_delete_current_msg);
272 i++)
273 warning("%s", warn_unconfigured_deny_delete_current_msg[i]);
276 static const char *update(struct command *cmd)
278 const char *name = cmd->ref_name;
279 unsigned char *old_sha1 = cmd->old_sha1;
280 unsigned char *new_sha1 = cmd->new_sha1;
281 struct ref_lock *lock;
283 /* only refs/... are allowed */
284 if (prefixcmp(name, "refs/") || check_ref_format(name + 5)) {
285 error("refusing to create funny ref '%s' remotely", name);
286 return "funny refname";
289 if (is_ref_checked_out(name)) {
290 switch (deny_current_branch) {
291 case DENY_IGNORE:
292 break;
293 case DENY_UNCONFIGURED:
294 case DENY_WARN:
295 warning("updating the current branch");
296 if (deny_current_branch == DENY_UNCONFIGURED)
297 warn_unconfigured_deny();
298 break;
299 case DENY_REFUSE:
300 error("refusing to update checked out branch: %s", name);
301 return "branch is currently checked out";
305 if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
306 error("unpack should have generated %s, "
307 "but I can't find it!", sha1_to_hex(new_sha1));
308 return "bad pack";
311 if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) {
312 if (deny_deletes && !prefixcmp(name, "refs/heads/")) {
313 error("denying ref deletion for %s", name);
314 return "deletion prohibited";
317 if (!strcmp(name, head_name)) {
318 switch (deny_delete_current) {
319 case DENY_IGNORE:
320 break;
321 case DENY_WARN:
322 case DENY_UNCONFIGURED:
323 if (deny_delete_current == DENY_UNCONFIGURED)
324 warn_unconfigured_deny_delete_current();
325 warning("deleting the current branch");
326 break;
327 case DENY_REFUSE:
328 error("refusing to delete the current branch: %s", name);
329 return "deletion of the current branch prohibited";
334 if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
335 !is_null_sha1(old_sha1) &&
336 !prefixcmp(name, "refs/heads/")) {
337 struct object *old_object, *new_object;
338 struct commit *old_commit, *new_commit;
339 struct commit_list *bases, *ent;
341 old_object = parse_object(old_sha1);
342 new_object = parse_object(new_sha1);
344 if (!old_object || !new_object ||
345 old_object->type != OBJ_COMMIT ||
346 new_object->type != OBJ_COMMIT) {
347 error("bad sha1 objects for %s", name);
348 return "bad ref";
350 old_commit = (struct commit *)old_object;
351 new_commit = (struct commit *)new_object;
352 bases = get_merge_bases(old_commit, new_commit, 1);
353 for (ent = bases; ent; ent = ent->next)
354 if (!hashcmp(old_sha1, ent->item->object.sha1))
355 break;
356 free_commit_list(bases);
357 if (!ent) {
358 error("denying non-fast forward %s"
359 " (you should pull first)", name);
360 return "non-fast forward";
363 if (run_update_hook(cmd)) {
364 error("hook declined to update %s", name);
365 return "hook declined";
368 if (is_null_sha1(new_sha1)) {
369 if (!parse_object(old_sha1)) {
370 warning ("Allowing deletion of corrupt ref.");
371 old_sha1 = NULL;
373 if (delete_ref(name, old_sha1, 0)) {
374 error("failed to delete %s", name);
375 return "failed to delete";
377 return NULL; /* good */
379 else {
380 lock = lock_any_ref_for_update(name, old_sha1, 0);
381 if (!lock) {
382 error("failed to lock %s", name);
383 return "failed to lock";
385 if (write_ref_sha1(lock, new_sha1, "push")) {
386 return "failed to write"; /* error() already called */
388 return NULL; /* good */
392 static char update_post_hook[] = "hooks/post-update";
394 static void run_update_post_hook(struct command *cmd)
396 struct command *cmd_p;
397 int argc, status;
398 const char **argv;
400 for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
401 if (cmd_p->error_string)
402 continue;
403 argc++;
405 if (!argc || access(update_post_hook, X_OK) < 0)
406 return;
407 argv = xmalloc(sizeof(*argv) * (2 + argc));
408 argv[0] = update_post_hook;
410 for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
411 char *p;
412 if (cmd_p->error_string)
413 continue;
414 p = xmalloc(strlen(cmd_p->ref_name) + 1);
415 strcpy(p, cmd_p->ref_name);
416 argv[argc] = p;
417 argc++;
419 argv[argc] = NULL;
420 status = run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
421 | RUN_COMMAND_STDOUT_TO_STDERR);
422 run_status(status, update_post_hook);
425 static void execute_commands(const char *unpacker_error)
427 struct command *cmd = commands;
428 unsigned char sha1[20];
430 if (unpacker_error) {
431 while (cmd) {
432 cmd->error_string = "n/a (unpacker error)";
433 cmd = cmd->next;
435 return;
438 if (run_receive_hook(pre_receive_hook)) {
439 while (cmd) {
440 cmd->error_string = "pre-receive hook declined";
441 cmd = cmd->next;
443 return;
446 head_name = resolve_ref("HEAD", sha1, 0, NULL);
448 while (cmd) {
449 cmd->error_string = update(cmd);
450 cmd = cmd->next;
454 static void read_head_info(void)
456 struct command **p = &commands;
457 for (;;) {
458 static char line[1000];
459 unsigned char old_sha1[20], new_sha1[20];
460 struct command *cmd;
461 char *refname;
462 int len, reflen;
464 len = packet_read_line(0, line, sizeof(line));
465 if (!len)
466 break;
467 if (line[len-1] == '\n')
468 line[--len] = 0;
469 if (len < 83 ||
470 line[40] != ' ' ||
471 line[81] != ' ' ||
472 get_sha1_hex(line, old_sha1) ||
473 get_sha1_hex(line + 41, new_sha1))
474 die("protocol error: expected old/new/ref, got '%s'",
475 line);
477 refname = line + 82;
478 reflen = strlen(refname);
479 if (reflen + 82 < len) {
480 if (strstr(refname + reflen + 1, "report-status"))
481 report_status = 1;
483 cmd = xmalloc(sizeof(struct command) + len - 80);
484 hashcpy(cmd->old_sha1, old_sha1);
485 hashcpy(cmd->new_sha1, new_sha1);
486 memcpy(cmd->ref_name, line + 82, len - 81);
487 cmd->error_string = NULL;
488 cmd->next = NULL;
489 *p = cmd;
490 p = &cmd->next;
494 static const char *parse_pack_header(struct pack_header *hdr)
496 switch (read_pack_header(0, hdr)) {
497 case PH_ERROR_EOF:
498 return "eof before pack header was fully read";
500 case PH_ERROR_PACK_SIGNATURE:
501 return "protocol error (pack signature mismatch detected)";
503 case PH_ERROR_PROTOCOL:
504 return "protocol error (pack version unsupported)";
506 default:
507 return "unknown error in parse_pack_header";
509 case 0:
510 return NULL;
514 static const char *pack_lockfile;
516 static const char *unpack(void)
518 struct pack_header hdr;
519 const char *hdr_err;
520 char hdr_arg[38];
522 hdr_err = parse_pack_header(&hdr);
523 if (hdr_err)
524 return hdr_err;
525 snprintf(hdr_arg, sizeof(hdr_arg),
526 "--pack_header=%"PRIu32",%"PRIu32,
527 ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
529 if (ntohl(hdr.hdr_entries) < unpack_limit) {
530 int code, i = 0;
531 const char *unpacker[4];
532 unpacker[i++] = "unpack-objects";
533 if (receive_fsck_objects)
534 unpacker[i++] = "--strict";
535 unpacker[i++] = hdr_arg;
536 unpacker[i++] = NULL;
537 code = run_command_v_opt(unpacker, RUN_GIT_CMD);
538 if (!code)
539 return NULL;
540 run_status(code, unpacker[0]);
541 return "unpack-objects abnormal exit";
542 } else {
543 const char *keeper[7];
544 int s, status, i = 0;
545 char keep_arg[256];
546 struct child_process ip;
548 s = sprintf(keep_arg, "--keep=receive-pack %"PRIuMAX" on ", (uintmax_t) getpid());
549 if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
550 strcpy(keep_arg + s, "localhost");
552 keeper[i++] = "index-pack";
553 keeper[i++] = "--stdin";
554 if (receive_fsck_objects)
555 keeper[i++] = "--strict";
556 keeper[i++] = "--fix-thin";
557 keeper[i++] = hdr_arg;
558 keeper[i++] = keep_arg;
559 keeper[i++] = NULL;
560 memset(&ip, 0, sizeof(ip));
561 ip.argv = keeper;
562 ip.out = -1;
563 ip.git_cmd = 1;
564 status = start_command(&ip);
565 if (status) {
566 run_status(status, keeper[0]);
567 return "index-pack fork failed";
569 pack_lockfile = index_pack_lockfile(ip.out);
570 close(ip.out);
571 status = finish_command(&ip);
572 if (!status) {
573 reprepare_packed_git();
574 return NULL;
576 run_status(status, keeper[0]);
577 return "index-pack abnormal exit";
581 static void report(const char *unpack_status)
583 struct command *cmd;
584 packet_write(1, "unpack %s\n",
585 unpack_status ? unpack_status : "ok");
586 for (cmd = commands; cmd; cmd = cmd->next) {
587 if (!cmd->error_string)
588 packet_write(1, "ok %s\n",
589 cmd->ref_name);
590 else
591 packet_write(1, "ng %s %s\n",
592 cmd->ref_name, cmd->error_string);
594 packet_flush(1);
597 static int delete_only(struct command *cmd)
599 while (cmd) {
600 if (!is_null_sha1(cmd->new_sha1))
601 return 0;
602 cmd = cmd->next;
604 return 1;
607 static int add_refs_from_alternate(struct alternate_object_database *e, void *unused)
609 char *other;
610 size_t len;
611 struct remote *remote;
612 struct transport *transport;
613 const struct ref *extra;
615 e->name[-1] = '\0';
616 other = xstrdup(make_absolute_path(e->base));
617 e->name[-1] = '/';
618 len = strlen(other);
620 while (other[len-1] == '/')
621 other[--len] = '\0';
622 if (len < 8 || memcmp(other + len - 8, "/objects", 8))
623 return 0;
624 /* Is this a git repository with refs? */
625 memcpy(other + len - 8, "/refs", 6);
626 if (!is_directory(other))
627 return 0;
628 other[len - 8] = '\0';
629 remote = remote_get(other);
630 transport = transport_get(remote, other);
631 for (extra = transport_get_remote_refs(transport);
632 extra;
633 extra = extra->next) {
634 add_extra_ref(".have", extra->old_sha1, 0);
636 transport_disconnect(transport);
637 free(other);
638 return 0;
641 static void add_alternate_refs(void)
643 foreach_alt_odb(add_refs_from_alternate, NULL);
646 int cmd_receive_pack(int argc, const char **argv, const char *prefix)
648 int i;
649 char *dir = NULL;
651 argv++;
652 for (i = 1; i < argc; i++) {
653 const char *arg = *argv++;
655 if (*arg == '-') {
656 /* Do flag handling here */
657 usage(receive_pack_usage);
659 if (dir)
660 usage(receive_pack_usage);
661 dir = xstrdup(arg);
663 if (!dir)
664 usage(receive_pack_usage);
666 setup_path();
668 if (!enter_repo(dir, 0))
669 die("'%s' does not appear to be a git repository", dir);
671 if (is_repository_shallow())
672 die("attempt to push into a shallow repository");
674 git_config(receive_pack_config, NULL);
676 if (0 <= transfer_unpack_limit)
677 unpack_limit = transfer_unpack_limit;
678 else if (0 <= receive_unpack_limit)
679 unpack_limit = receive_unpack_limit;
681 capabilities_to_send = (prefer_ofs_delta) ?
682 " report-status delete-refs ofs-delta " :
683 " report-status delete-refs ";
685 add_alternate_refs();
686 write_head_info();
687 clear_extra_refs();
689 /* EOF */
690 packet_flush(1);
692 read_head_info();
693 if (commands) {
694 const char *unpack_status = NULL;
696 if (!delete_only(commands))
697 unpack_status = unpack();
698 execute_commands(unpack_status);
699 if (pack_lockfile)
700 unlink_or_warn(pack_lockfile);
701 if (report_status)
702 report(unpack_status);
703 run_receive_hook(post_receive_hook);
704 run_update_post_hook(commands);
706 return 0;