receive-pack: Send hook output over side band #2
[git/dscho.git] / builtin-receive-pack.c
blobda1c26b6be14f7aaee99806017cef9554fa65e6d
1 #include "cache.h"
2 #include "pack.h"
3 #include "refs.h"
4 #include "pkt-line.h"
5 #include "sideband.h"
6 #include "run-command.h"
7 #include "exec_cmd.h"
8 #include "commit.h"
9 #include "object.h"
10 #include "remote.h"
11 #include "transport.h"
13 static const char receive_pack_usage[] = "git receive-pack <git-dir>";
15 enum deny_action {
16 DENY_UNCONFIGURED,
17 DENY_IGNORE,
18 DENY_WARN,
19 DENY_REFUSE,
22 static int deny_deletes;
23 static int deny_non_fast_forwards;
24 static enum deny_action deny_current_branch = DENY_UNCONFIGURED;
25 static enum deny_action deny_delete_current = DENY_UNCONFIGURED;
26 static int receive_fsck_objects;
27 static int receive_unpack_limit = -1;
28 static int transfer_unpack_limit = -1;
29 static int unpack_limit = 100;
30 static int report_status;
31 static int use_sideband;
32 static int prefer_ofs_delta = 1;
33 static int auto_update_server_info;
34 static int auto_gc = 1;
35 static const char *head_name;
36 static int sent_capabilities;
38 static enum deny_action parse_deny_action(const char *var, const char *value)
40 if (value) {
41 if (!strcasecmp(value, "ignore"))
42 return DENY_IGNORE;
43 if (!strcasecmp(value, "warn"))
44 return DENY_WARN;
45 if (!strcasecmp(value, "refuse"))
46 return DENY_REFUSE;
48 if (git_config_bool(var, value))
49 return DENY_REFUSE;
50 return DENY_IGNORE;
53 static int receive_pack_config(const char *var, const char *value, void *cb)
55 if (strcmp(var, "receive.denydeletes") == 0) {
56 deny_deletes = git_config_bool(var, value);
57 return 0;
60 if (strcmp(var, "receive.denynonfastforwards") == 0) {
61 deny_non_fast_forwards = git_config_bool(var, value);
62 return 0;
65 if (strcmp(var, "receive.unpacklimit") == 0) {
66 receive_unpack_limit = git_config_int(var, value);
67 return 0;
70 if (strcmp(var, "transfer.unpacklimit") == 0) {
71 transfer_unpack_limit = git_config_int(var, value);
72 return 0;
75 if (strcmp(var, "receive.fsckobjects") == 0) {
76 receive_fsck_objects = git_config_bool(var, value);
77 return 0;
80 if (!strcmp(var, "receive.denycurrentbranch")) {
81 deny_current_branch = parse_deny_action(var, value);
82 return 0;
85 if (strcmp(var, "receive.denydeletecurrent") == 0) {
86 deny_delete_current = parse_deny_action(var, value);
87 return 0;
90 if (strcmp(var, "repack.usedeltabaseoffset") == 0) {
91 prefer_ofs_delta = git_config_bool(var, value);
92 return 0;
95 if (strcmp(var, "receive.updateserverinfo") == 0) {
96 auto_update_server_info = git_config_bool(var, value);
97 return 0;
100 if (strcmp(var, "receive.autogc") == 0) {
101 auto_gc = git_config_bool(var, value);
102 return 0;
105 return git_default_config(var, value, cb);
108 static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
110 if (sent_capabilities)
111 packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
112 else
113 packet_write(1, "%s %s%c%s%s\n",
114 sha1_to_hex(sha1), path, 0,
115 " report-status delete-refs side-band-64k",
116 prefer_ofs_delta ? " ofs-delta" : "");
117 sent_capabilities = 1;
118 return 0;
121 static void write_head_info(void)
123 for_each_ref(show_ref, NULL);
124 if (!sent_capabilities)
125 show_ref("capabilities^{}", null_sha1, 0, NULL);
129 struct command {
130 struct command *next;
131 const char *error_string;
132 unsigned char old_sha1[20];
133 unsigned char new_sha1[20];
134 char ref_name[FLEX_ARRAY]; /* more */
137 static struct command *commands;
139 static const char pre_receive_hook[] = "hooks/pre-receive";
140 static const char post_receive_hook[] = "hooks/post-receive";
142 static int copy_to_sideband(int in, int out, void *arg)
144 char data[128];
145 while (1) {
146 ssize_t sz = xread(in, data, sizeof(data));
147 if (sz <= 0)
148 break;
149 send_sideband(1, 2, data, sz, use_sideband);
151 close(in);
152 return 0;
155 static int run_receive_hook(const char *hook_name)
157 static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
158 struct command *cmd;
159 struct child_process proc;
160 struct async muxer;
161 const char *argv[2];
162 int have_input = 0, code;
164 for (cmd = commands; !have_input && cmd; cmd = cmd->next) {
165 if (!cmd->error_string)
166 have_input = 1;
169 if (!have_input || access(hook_name, X_OK) < 0)
170 return 0;
172 argv[0] = hook_name;
173 argv[1] = NULL;
175 memset(&proc, 0, sizeof(proc));
176 proc.argv = argv;
177 proc.in = -1;
178 proc.stdout_to_stderr = 1;
180 if (use_sideband) {
181 memset(&muxer, 0, sizeof(muxer));
182 muxer.proc = copy_to_sideband;
183 muxer.in = -1;
184 code = start_async(&muxer);
185 if (code)
186 return code;
187 proc.err = muxer.in;
190 code = start_command(&proc);
191 if (code) {
192 if (use_sideband)
193 finish_async(&muxer);
194 return code;
197 for (cmd = commands; cmd; cmd = cmd->next) {
198 if (!cmd->error_string) {
199 size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
200 sha1_to_hex(cmd->old_sha1),
201 sha1_to_hex(cmd->new_sha1),
202 cmd->ref_name);
203 if (write_in_full(proc.in, buf, n) != n)
204 break;
207 close(proc.in);
208 if (use_sideband)
209 finish_async(&muxer);
210 return finish_command(&proc);
213 static int run_update_hook(struct command *cmd)
215 static const char update_hook[] = "hooks/update";
216 const char *argv[5];
217 struct child_process proc;
218 int code;
220 if (access(update_hook, X_OK) < 0)
221 return 0;
223 argv[0] = update_hook;
224 argv[1] = cmd->ref_name;
225 argv[2] = sha1_to_hex(cmd->old_sha1);
226 argv[3] = sha1_to_hex(cmd->new_sha1);
227 argv[4] = NULL;
229 memset(&proc, 0, sizeof(proc));
230 proc.no_stdin = 1;
231 proc.stdout_to_stderr = 1;
232 proc.err = use_sideband ? -1 : 0;
233 proc.argv = argv;
235 code = start_command(&proc);
236 if (code)
237 return code;
238 if (use_sideband)
239 copy_to_sideband(proc.err, -1, NULL);
240 return finish_command(&proc);
243 static int is_ref_checked_out(const char *ref)
245 if (is_bare_repository())
246 return 0;
248 if (!head_name)
249 return 0;
250 return !strcmp(head_name, ref);
253 static char *warn_unconfigured_deny_msg[] = {
254 "Updating the currently checked out branch may cause confusion,",
255 "as the index and work tree do not reflect changes that are in HEAD.",
256 "As a result, you may see the changes you just pushed into it",
257 "reverted when you run 'git diff' over there, and you may want",
258 "to run 'git reset --hard' before starting to work to recover.",
260 "You can set 'receive.denyCurrentBranch' configuration variable to",
261 "'refuse' in the remote repository to forbid pushing into its",
262 "current branch."
264 "To allow pushing into the current branch, you can set it to 'ignore';",
265 "but this is not recommended unless you arranged to update its work",
266 "tree to match what you pushed in some other way.",
268 "To squelch this message, you can set it to 'warn'.",
270 "Note that the default will change in a future version of git",
271 "to refuse updating the current branch unless you have the",
272 "configuration variable set to either 'ignore' or 'warn'."
275 static void warn_unconfigured_deny(void)
277 int i;
278 for (i = 0; i < ARRAY_SIZE(warn_unconfigured_deny_msg); i++)
279 warning("%s", warn_unconfigured_deny_msg[i]);
282 static char *warn_unconfigured_deny_delete_current_msg[] = {
283 "Deleting the current branch can cause confusion by making the next",
284 "'git clone' not check out any file.",
286 "You can set 'receive.denyDeleteCurrent' configuration variable to",
287 "'refuse' in the remote repository to disallow deleting the current",
288 "branch.",
290 "You can set it to 'ignore' to allow such a delete without a warning.",
292 "To make this warning message less loud, you can set it to 'warn'.",
294 "Note that the default will change in a future version of git",
295 "to refuse deleting the current branch unless you have the",
296 "configuration variable set to either 'ignore' or 'warn'."
299 static void warn_unconfigured_deny_delete_current(void)
301 int i;
302 for (i = 0;
303 i < ARRAY_SIZE(warn_unconfigured_deny_delete_current_msg);
304 i++)
305 warning("%s", warn_unconfigured_deny_delete_current_msg[i]);
308 static const char *update(struct command *cmd)
310 const char *name = cmd->ref_name;
311 unsigned char *old_sha1 = cmd->old_sha1;
312 unsigned char *new_sha1 = cmd->new_sha1;
313 struct ref_lock *lock;
315 /* only refs/... are allowed */
316 if (prefixcmp(name, "refs/") || check_ref_format(name + 5)) {
317 error("refusing to create funny ref '%s' remotely", name);
318 return "funny refname";
321 if (is_ref_checked_out(name)) {
322 switch (deny_current_branch) {
323 case DENY_IGNORE:
324 break;
325 case DENY_UNCONFIGURED:
326 case DENY_WARN:
327 warning("updating the current branch");
328 if (deny_current_branch == DENY_UNCONFIGURED)
329 warn_unconfigured_deny();
330 break;
331 case DENY_REFUSE:
332 error("refusing to update checked out branch: %s", name);
333 return "branch is currently checked out";
337 if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
338 error("unpack should have generated %s, "
339 "but I can't find it!", sha1_to_hex(new_sha1));
340 return "bad pack";
343 if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) {
344 if (deny_deletes && !prefixcmp(name, "refs/heads/")) {
345 error("denying ref deletion for %s", name);
346 return "deletion prohibited";
349 if (!strcmp(name, head_name)) {
350 switch (deny_delete_current) {
351 case DENY_IGNORE:
352 break;
353 case DENY_WARN:
354 case DENY_UNCONFIGURED:
355 if (deny_delete_current == DENY_UNCONFIGURED)
356 warn_unconfigured_deny_delete_current();
357 warning("deleting the current branch");
358 break;
359 case DENY_REFUSE:
360 error("refusing to delete the current branch: %s", name);
361 return "deletion of the current branch prohibited";
366 if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
367 !is_null_sha1(old_sha1) &&
368 !prefixcmp(name, "refs/heads/")) {
369 struct object *old_object, *new_object;
370 struct commit *old_commit, *new_commit;
371 struct commit_list *bases, *ent;
373 old_object = parse_object(old_sha1);
374 new_object = parse_object(new_sha1);
376 if (!old_object || !new_object ||
377 old_object->type != OBJ_COMMIT ||
378 new_object->type != OBJ_COMMIT) {
379 error("bad sha1 objects for %s", name);
380 return "bad ref";
382 old_commit = (struct commit *)old_object;
383 new_commit = (struct commit *)new_object;
384 bases = get_merge_bases(old_commit, new_commit, 1);
385 for (ent = bases; ent; ent = ent->next)
386 if (!hashcmp(old_sha1, ent->item->object.sha1))
387 break;
388 free_commit_list(bases);
389 if (!ent) {
390 error("denying non-fast-forward %s"
391 " (you should pull first)", name);
392 return "non-fast-forward";
395 if (run_update_hook(cmd)) {
396 error("hook declined to update %s", name);
397 return "hook declined";
400 if (is_null_sha1(new_sha1)) {
401 if (!parse_object(old_sha1)) {
402 warning ("Allowing deletion of corrupt ref.");
403 old_sha1 = NULL;
405 if (delete_ref(name, old_sha1, 0)) {
406 error("failed to delete %s", name);
407 return "failed to delete";
409 return NULL; /* good */
411 else {
412 lock = lock_any_ref_for_update(name, old_sha1, 0);
413 if (!lock) {
414 error("failed to lock %s", name);
415 return "failed to lock";
417 if (write_ref_sha1(lock, new_sha1, "push")) {
418 return "failed to write"; /* error() already called */
420 return NULL; /* good */
424 static char update_post_hook[] = "hooks/post-update";
426 static void run_update_post_hook(struct command *cmd)
428 struct command *cmd_p;
429 int argc;
430 const char **argv;
431 struct child_process proc;
433 for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
434 if (cmd_p->error_string)
435 continue;
436 argc++;
438 if (!argc || access(update_post_hook, X_OK) < 0)
439 return;
440 argv = xmalloc(sizeof(*argv) * (2 + argc));
441 argv[0] = update_post_hook;
443 for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
444 char *p;
445 if (cmd_p->error_string)
446 continue;
447 p = xmalloc(strlen(cmd_p->ref_name) + 1);
448 strcpy(p, cmd_p->ref_name);
449 argv[argc] = p;
450 argc++;
452 argv[argc] = NULL;
454 memset(&proc, 0, sizeof(proc));
455 proc.no_stdin = 1;
456 proc.stdout_to_stderr = 1;
457 proc.err = use_sideband ? -1 : 0;
458 proc.argv = argv;
460 if (!start_command(&proc)) {
461 if (use_sideband)
462 copy_to_sideband(proc.err, -1, NULL);
463 finish_command(&proc);
467 static void execute_commands(const char *unpacker_error)
469 struct command *cmd = commands;
470 unsigned char sha1[20];
472 if (unpacker_error) {
473 while (cmd) {
474 cmd->error_string = "n/a (unpacker error)";
475 cmd = cmd->next;
477 return;
480 if (run_receive_hook(pre_receive_hook)) {
481 while (cmd) {
482 cmd->error_string = "pre-receive hook declined";
483 cmd = cmd->next;
485 return;
488 head_name = resolve_ref("HEAD", sha1, 0, NULL);
490 while (cmd) {
491 cmd->error_string = update(cmd);
492 cmd = cmd->next;
496 static void read_head_info(void)
498 struct command **p = &commands;
499 for (;;) {
500 static char line[1000];
501 unsigned char old_sha1[20], new_sha1[20];
502 struct command *cmd;
503 char *refname;
504 int len, reflen;
506 len = packet_read_line(0, line, sizeof(line));
507 if (!len)
508 break;
509 if (line[len-1] == '\n')
510 line[--len] = 0;
511 if (len < 83 ||
512 line[40] != ' ' ||
513 line[81] != ' ' ||
514 get_sha1_hex(line, old_sha1) ||
515 get_sha1_hex(line + 41, new_sha1))
516 die("protocol error: expected old/new/ref, got '%s'",
517 line);
519 refname = line + 82;
520 reflen = strlen(refname);
521 if (reflen + 82 < len) {
522 if (strstr(refname + reflen + 1, "report-status"))
523 report_status = 1;
524 if (strstr(refname + reflen + 1, "side-band-64k"))
525 use_sideband = LARGE_PACKET_MAX;
527 cmd = xmalloc(sizeof(struct command) + len - 80);
528 hashcpy(cmd->old_sha1, old_sha1);
529 hashcpy(cmd->new_sha1, new_sha1);
530 memcpy(cmd->ref_name, line + 82, len - 81);
531 cmd->error_string = NULL;
532 cmd->next = NULL;
533 *p = cmd;
534 p = &cmd->next;
538 static const char *parse_pack_header(struct pack_header *hdr)
540 switch (read_pack_header(0, hdr)) {
541 case PH_ERROR_EOF:
542 return "eof before pack header was fully read";
544 case PH_ERROR_PACK_SIGNATURE:
545 return "protocol error (pack signature mismatch detected)";
547 case PH_ERROR_PROTOCOL:
548 return "protocol error (pack version unsupported)";
550 default:
551 return "unknown error in parse_pack_header";
553 case 0:
554 return NULL;
558 static const char *pack_lockfile;
560 static const char *unpack(void)
562 struct pack_header hdr;
563 const char *hdr_err;
564 char hdr_arg[38];
566 hdr_err = parse_pack_header(&hdr);
567 if (hdr_err)
568 return hdr_err;
569 snprintf(hdr_arg, sizeof(hdr_arg),
570 "--pack_header=%"PRIu32",%"PRIu32,
571 ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
573 if (ntohl(hdr.hdr_entries) < unpack_limit) {
574 int code, i = 0;
575 const char *unpacker[4];
576 unpacker[i++] = "unpack-objects";
577 if (receive_fsck_objects)
578 unpacker[i++] = "--strict";
579 unpacker[i++] = hdr_arg;
580 unpacker[i++] = NULL;
581 code = run_command_v_opt(unpacker, RUN_GIT_CMD);
582 if (!code)
583 return NULL;
584 return "unpack-objects abnormal exit";
585 } else {
586 const char *keeper[7];
587 int s, status, i = 0;
588 char keep_arg[256];
589 struct child_process ip;
591 s = sprintf(keep_arg, "--keep=receive-pack %"PRIuMAX" on ", (uintmax_t) getpid());
592 if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
593 strcpy(keep_arg + s, "localhost");
595 keeper[i++] = "index-pack";
596 keeper[i++] = "--stdin";
597 if (receive_fsck_objects)
598 keeper[i++] = "--strict";
599 keeper[i++] = "--fix-thin";
600 keeper[i++] = hdr_arg;
601 keeper[i++] = keep_arg;
602 keeper[i++] = NULL;
603 memset(&ip, 0, sizeof(ip));
604 ip.argv = keeper;
605 ip.out = -1;
606 ip.git_cmd = 1;
607 status = start_command(&ip);
608 if (status) {
609 return "index-pack fork failed";
611 pack_lockfile = index_pack_lockfile(ip.out);
612 close(ip.out);
613 status = finish_command(&ip);
614 if (!status) {
615 reprepare_packed_git();
616 return NULL;
618 return "index-pack abnormal exit";
622 static void report(const char *unpack_status)
624 struct command *cmd;
625 struct strbuf buf = STRBUF_INIT;
627 packet_buf_write(&buf, "unpack %s\n",
628 unpack_status ? unpack_status : "ok");
629 for (cmd = commands; cmd; cmd = cmd->next) {
630 if (!cmd->error_string)
631 packet_buf_write(&buf, "ok %s\n",
632 cmd->ref_name);
633 else
634 packet_buf_write(&buf, "ng %s %s\n",
635 cmd->ref_name, cmd->error_string);
637 packet_buf_flush(&buf);
639 if (use_sideband)
640 send_sideband(1, 1, buf.buf, buf.len, use_sideband);
641 else
642 safe_write(1, buf.buf, buf.len);
643 strbuf_release(&buf);
646 static int delete_only(struct command *cmd)
648 while (cmd) {
649 if (!is_null_sha1(cmd->new_sha1))
650 return 0;
651 cmd = cmd->next;
653 return 1;
656 static int add_refs_from_alternate(struct alternate_object_database *e, void *unused)
658 char *other;
659 size_t len;
660 struct remote *remote;
661 struct transport *transport;
662 const struct ref *extra;
664 e->name[-1] = '\0';
665 other = xstrdup(make_absolute_path(e->base));
666 e->name[-1] = '/';
667 len = strlen(other);
669 while (other[len-1] == '/')
670 other[--len] = '\0';
671 if (len < 8 || memcmp(other + len - 8, "/objects", 8))
672 return 0;
673 /* Is this a git repository with refs? */
674 memcpy(other + len - 8, "/refs", 6);
675 if (!is_directory(other))
676 return 0;
677 other[len - 8] = '\0';
678 remote = remote_get(other);
679 transport = transport_get(remote, other);
680 for (extra = transport_get_remote_refs(transport);
681 extra;
682 extra = extra->next) {
683 add_extra_ref(".have", extra->old_sha1, 0);
685 transport_disconnect(transport);
686 free(other);
687 return 0;
690 static void add_alternate_refs(void)
692 foreach_alt_odb(add_refs_from_alternate, NULL);
695 int cmd_receive_pack(int argc, const char **argv, const char *prefix)
697 int advertise_refs = 0;
698 int stateless_rpc = 0;
699 int i;
700 char *dir = NULL;
702 argv++;
703 for (i = 1; i < argc; i++) {
704 const char *arg = *argv++;
706 if (*arg == '-') {
707 if (!strcmp(arg, "--advertise-refs")) {
708 advertise_refs = 1;
709 continue;
711 if (!strcmp(arg, "--stateless-rpc")) {
712 stateless_rpc = 1;
713 continue;
716 usage(receive_pack_usage);
718 if (dir)
719 usage(receive_pack_usage);
720 dir = xstrdup(arg);
722 if (!dir)
723 usage(receive_pack_usage);
725 setup_path();
727 if (!enter_repo(dir, 0))
728 die("'%s' does not appear to be a git repository", dir);
730 if (is_repository_shallow())
731 die("attempt to push into a shallow repository");
733 git_config(receive_pack_config, NULL);
735 if (0 <= transfer_unpack_limit)
736 unpack_limit = transfer_unpack_limit;
737 else if (0 <= receive_unpack_limit)
738 unpack_limit = receive_unpack_limit;
740 if (advertise_refs || !stateless_rpc) {
741 add_alternate_refs();
742 write_head_info();
743 clear_extra_refs();
745 /* EOF */
746 packet_flush(1);
748 if (advertise_refs)
749 return 0;
751 read_head_info();
752 if (commands) {
753 const char *unpack_status = NULL;
755 if (!delete_only(commands))
756 unpack_status = unpack();
757 execute_commands(unpack_status);
758 if (pack_lockfile)
759 unlink_or_warn(pack_lockfile);
760 if (report_status)
761 report(unpack_status);
762 run_receive_hook(post_receive_hook);
763 run_update_post_hook(commands);
764 if (auto_gc) {
765 const char *argv_gc_auto[] = {
766 "gc", "--auto", "--quiet", NULL,
768 run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
770 if (auto_update_server_info)
771 update_server_info(0);
773 if (use_sideband)
774 packet_flush(1);
775 return 0;