receive-pack: Refactor how capabilities are shown to the client
[git/gitweb.git] / builtin-receive-pack.c
blob325ec6e2c409992e9feba5b2d871835b372c609a
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 int auto_update_server_info;
32 static int auto_gc = 1;
33 static const char *head_name;
34 static int sent_capabilities;
36 static enum deny_action parse_deny_action(const char *var, const char *value)
38 if (value) {
39 if (!strcasecmp(value, "ignore"))
40 return DENY_IGNORE;
41 if (!strcasecmp(value, "warn"))
42 return DENY_WARN;
43 if (!strcasecmp(value, "refuse"))
44 return DENY_REFUSE;
46 if (git_config_bool(var, value))
47 return DENY_REFUSE;
48 return DENY_IGNORE;
51 static int receive_pack_config(const char *var, const char *value, void *cb)
53 if (strcmp(var, "receive.denydeletes") == 0) {
54 deny_deletes = git_config_bool(var, value);
55 return 0;
58 if (strcmp(var, "receive.denynonfastforwards") == 0) {
59 deny_non_fast_forwards = git_config_bool(var, value);
60 return 0;
63 if (strcmp(var, "receive.unpacklimit") == 0) {
64 receive_unpack_limit = git_config_int(var, value);
65 return 0;
68 if (strcmp(var, "transfer.unpacklimit") == 0) {
69 transfer_unpack_limit = git_config_int(var, value);
70 return 0;
73 if (strcmp(var, "receive.fsckobjects") == 0) {
74 receive_fsck_objects = git_config_bool(var, value);
75 return 0;
78 if (!strcmp(var, "receive.denycurrentbranch")) {
79 deny_current_branch = parse_deny_action(var, value);
80 return 0;
83 if (strcmp(var, "receive.denydeletecurrent") == 0) {
84 deny_delete_current = parse_deny_action(var, value);
85 return 0;
88 if (strcmp(var, "repack.usedeltabaseoffset") == 0) {
89 prefer_ofs_delta = git_config_bool(var, value);
90 return 0;
93 if (strcmp(var, "receive.updateserverinfo") == 0) {
94 auto_update_server_info = git_config_bool(var, value);
95 return 0;
98 if (strcmp(var, "receive.autogc") == 0) {
99 auto_gc = git_config_bool(var, value);
100 return 0;
103 return git_default_config(var, value, cb);
106 static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
108 if (sent_capabilities)
109 packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
110 else
111 packet_write(1, "%s %s%c%s%s\n",
112 sha1_to_hex(sha1), path, 0,
113 " report-status delete-refs",
114 prefer_ofs_delta ? " ofs-delta" : "");
115 sent_capabilities = 1;
116 return 0;
119 static void write_head_info(void)
121 for_each_ref(show_ref, NULL);
122 if (!sent_capabilities)
123 show_ref("capabilities^{}", null_sha1, 0, NULL);
127 struct command {
128 struct command *next;
129 const char *error_string;
130 unsigned char old_sha1[20];
131 unsigned char new_sha1[20];
132 char ref_name[FLEX_ARRAY]; /* more */
135 static struct command *commands;
137 static const char pre_receive_hook[] = "hooks/pre-receive";
138 static const char post_receive_hook[] = "hooks/post-receive";
140 static int run_receive_hook(const char *hook_name)
142 static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
143 struct command *cmd;
144 struct child_process proc;
145 const char *argv[2];
146 int have_input = 0, code;
148 for (cmd = commands; !have_input && cmd; cmd = cmd->next) {
149 if (!cmd->error_string)
150 have_input = 1;
153 if (!have_input || access(hook_name, X_OK) < 0)
154 return 0;
156 argv[0] = hook_name;
157 argv[1] = NULL;
159 memset(&proc, 0, sizeof(proc));
160 proc.argv = argv;
161 proc.in = -1;
162 proc.stdout_to_stderr = 1;
164 code = start_command(&proc);
165 if (code)
166 return code;
167 for (cmd = commands; cmd; cmd = cmd->next) {
168 if (!cmd->error_string) {
169 size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
170 sha1_to_hex(cmd->old_sha1),
171 sha1_to_hex(cmd->new_sha1),
172 cmd->ref_name);
173 if (write_in_full(proc.in, buf, n) != n)
174 break;
177 close(proc.in);
178 return finish_command(&proc);
181 static int run_update_hook(struct command *cmd)
183 static const char update_hook[] = "hooks/update";
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 return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
196 RUN_COMMAND_STDOUT_TO_STDERR);
199 static int is_ref_checked_out(const char *ref)
201 if (is_bare_repository())
202 return 0;
204 if (!head_name)
205 return 0;
206 return !strcmp(head_name, ref);
209 static char *warn_unconfigured_deny_msg[] = {
210 "Updating the currently checked out branch may cause confusion,",
211 "as the index and work tree do not reflect changes that are in HEAD.",
212 "As a result, you may see the changes you just pushed into it",
213 "reverted when you run 'git diff' over there, and you may want",
214 "to run 'git reset --hard' before starting to work to recover.",
216 "You can set 'receive.denyCurrentBranch' configuration variable to",
217 "'refuse' in the remote repository to forbid pushing into its",
218 "current branch."
220 "To allow pushing into the current branch, you can set it to 'ignore';",
221 "but this is not recommended unless you arranged to update its work",
222 "tree to match what you pushed in some other way.",
224 "To squelch this message, you can set it to 'warn'.",
226 "Note that the default will change in a future version of git",
227 "to refuse updating the current branch unless you have the",
228 "configuration variable set to either 'ignore' or 'warn'."
231 static void warn_unconfigured_deny(void)
233 int i;
234 for (i = 0; i < ARRAY_SIZE(warn_unconfigured_deny_msg); i++)
235 warning("%s", warn_unconfigured_deny_msg[i]);
238 static char *warn_unconfigured_deny_delete_current_msg[] = {
239 "Deleting the current branch can cause confusion by making the next",
240 "'git clone' not check out any file.",
242 "You can set 'receive.denyDeleteCurrent' configuration variable to",
243 "'refuse' in the remote repository to disallow deleting the current",
244 "branch.",
246 "You can set it to 'ignore' to allow such a delete without a warning.",
248 "To make this warning message less loud, you can set it to 'warn'.",
250 "Note that the default will change in a future version of git",
251 "to refuse deleting the current branch unless you have the",
252 "configuration variable set to either 'ignore' or 'warn'."
255 static void warn_unconfigured_deny_delete_current(void)
257 int i;
258 for (i = 0;
259 i < ARRAY_SIZE(warn_unconfigured_deny_delete_current_msg);
260 i++)
261 warning("%s", warn_unconfigured_deny_delete_current_msg[i]);
264 static const char *update(struct command *cmd)
266 const char *name = cmd->ref_name;
267 unsigned char *old_sha1 = cmd->old_sha1;
268 unsigned char *new_sha1 = cmd->new_sha1;
269 struct ref_lock *lock;
271 /* only refs/... are allowed */
272 if (prefixcmp(name, "refs/") || check_ref_format(name + 5)) {
273 error("refusing to create funny ref '%s' remotely", name);
274 return "funny refname";
277 if (is_ref_checked_out(name)) {
278 switch (deny_current_branch) {
279 case DENY_IGNORE:
280 break;
281 case DENY_UNCONFIGURED:
282 case DENY_WARN:
283 warning("updating the current branch");
284 if (deny_current_branch == DENY_UNCONFIGURED)
285 warn_unconfigured_deny();
286 break;
287 case DENY_REFUSE:
288 error("refusing to update checked out branch: %s", name);
289 return "branch is currently checked out";
293 if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
294 error("unpack should have generated %s, "
295 "but I can't find it!", sha1_to_hex(new_sha1));
296 return "bad pack";
299 if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) {
300 if (deny_deletes && !prefixcmp(name, "refs/heads/")) {
301 error("denying ref deletion for %s", name);
302 return "deletion prohibited";
305 if (!strcmp(name, head_name)) {
306 switch (deny_delete_current) {
307 case DENY_IGNORE:
308 break;
309 case DENY_WARN:
310 case DENY_UNCONFIGURED:
311 if (deny_delete_current == DENY_UNCONFIGURED)
312 warn_unconfigured_deny_delete_current();
313 warning("deleting the current branch");
314 break;
315 case DENY_REFUSE:
316 error("refusing to delete the current branch: %s", name);
317 return "deletion of the current branch prohibited";
322 if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
323 !is_null_sha1(old_sha1) &&
324 !prefixcmp(name, "refs/heads/")) {
325 struct object *old_object, *new_object;
326 struct commit *old_commit, *new_commit;
327 struct commit_list *bases, *ent;
329 old_object = parse_object(old_sha1);
330 new_object = parse_object(new_sha1);
332 if (!old_object || !new_object ||
333 old_object->type != OBJ_COMMIT ||
334 new_object->type != OBJ_COMMIT) {
335 error("bad sha1 objects for %s", name);
336 return "bad ref";
338 old_commit = (struct commit *)old_object;
339 new_commit = (struct commit *)new_object;
340 bases = get_merge_bases(old_commit, new_commit, 1);
341 for (ent = bases; ent; ent = ent->next)
342 if (!hashcmp(old_sha1, ent->item->object.sha1))
343 break;
344 free_commit_list(bases);
345 if (!ent) {
346 error("denying non-fast-forward %s"
347 " (you should pull first)", name);
348 return "non-fast-forward";
351 if (run_update_hook(cmd)) {
352 error("hook declined to update %s", name);
353 return "hook declined";
356 if (is_null_sha1(new_sha1)) {
357 if (!parse_object(old_sha1)) {
358 warning ("Allowing deletion of corrupt ref.");
359 old_sha1 = NULL;
361 if (delete_ref(name, old_sha1, 0)) {
362 error("failed to delete %s", name);
363 return "failed to delete";
365 return NULL; /* good */
367 else {
368 lock = lock_any_ref_for_update(name, old_sha1, 0);
369 if (!lock) {
370 error("failed to lock %s", name);
371 return "failed to lock";
373 if (write_ref_sha1(lock, new_sha1, "push")) {
374 return "failed to write"; /* error() already called */
376 return NULL; /* good */
380 static char update_post_hook[] = "hooks/post-update";
382 static void run_update_post_hook(struct command *cmd)
384 struct command *cmd_p;
385 int argc, status;
386 const char **argv;
388 for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
389 if (cmd_p->error_string)
390 continue;
391 argc++;
393 if (!argc || access(update_post_hook, X_OK) < 0)
394 return;
395 argv = xmalloc(sizeof(*argv) * (2 + argc));
396 argv[0] = update_post_hook;
398 for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
399 char *p;
400 if (cmd_p->error_string)
401 continue;
402 p = xmalloc(strlen(cmd_p->ref_name) + 1);
403 strcpy(p, cmd_p->ref_name);
404 argv[argc] = p;
405 argc++;
407 argv[argc] = NULL;
408 status = run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
409 | RUN_COMMAND_STDOUT_TO_STDERR);
412 static void execute_commands(const char *unpacker_error)
414 struct command *cmd = commands;
415 unsigned char sha1[20];
417 if (unpacker_error) {
418 while (cmd) {
419 cmd->error_string = "n/a (unpacker error)";
420 cmd = cmd->next;
422 return;
425 if (run_receive_hook(pre_receive_hook)) {
426 while (cmd) {
427 cmd->error_string = "pre-receive hook declined";
428 cmd = cmd->next;
430 return;
433 head_name = resolve_ref("HEAD", sha1, 0, NULL);
435 while (cmd) {
436 cmd->error_string = update(cmd);
437 cmd = cmd->next;
441 static void read_head_info(void)
443 struct command **p = &commands;
444 for (;;) {
445 static char line[1000];
446 unsigned char old_sha1[20], new_sha1[20];
447 struct command *cmd;
448 char *refname;
449 int len, reflen;
451 len = packet_read_line(0, line, sizeof(line));
452 if (!len)
453 break;
454 if (line[len-1] == '\n')
455 line[--len] = 0;
456 if (len < 83 ||
457 line[40] != ' ' ||
458 line[81] != ' ' ||
459 get_sha1_hex(line, old_sha1) ||
460 get_sha1_hex(line + 41, new_sha1))
461 die("protocol error: expected old/new/ref, got '%s'",
462 line);
464 refname = line + 82;
465 reflen = strlen(refname);
466 if (reflen + 82 < len) {
467 if (strstr(refname + reflen + 1, "report-status"))
468 report_status = 1;
470 cmd = xmalloc(sizeof(struct command) + len - 80);
471 hashcpy(cmd->old_sha1, old_sha1);
472 hashcpy(cmd->new_sha1, new_sha1);
473 memcpy(cmd->ref_name, line + 82, len - 81);
474 cmd->error_string = NULL;
475 cmd->next = NULL;
476 *p = cmd;
477 p = &cmd->next;
481 static const char *parse_pack_header(struct pack_header *hdr)
483 switch (read_pack_header(0, hdr)) {
484 case PH_ERROR_EOF:
485 return "eof before pack header was fully read";
487 case PH_ERROR_PACK_SIGNATURE:
488 return "protocol error (pack signature mismatch detected)";
490 case PH_ERROR_PROTOCOL:
491 return "protocol error (pack version unsupported)";
493 default:
494 return "unknown error in parse_pack_header";
496 case 0:
497 return NULL;
501 static const char *pack_lockfile;
503 static const char *unpack(void)
505 struct pack_header hdr;
506 const char *hdr_err;
507 char hdr_arg[38];
509 hdr_err = parse_pack_header(&hdr);
510 if (hdr_err)
511 return hdr_err;
512 snprintf(hdr_arg, sizeof(hdr_arg),
513 "--pack_header=%"PRIu32",%"PRIu32,
514 ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
516 if (ntohl(hdr.hdr_entries) < unpack_limit) {
517 int code, i = 0;
518 const char *unpacker[4];
519 unpacker[i++] = "unpack-objects";
520 if (receive_fsck_objects)
521 unpacker[i++] = "--strict";
522 unpacker[i++] = hdr_arg;
523 unpacker[i++] = NULL;
524 code = run_command_v_opt(unpacker, RUN_GIT_CMD);
525 if (!code)
526 return NULL;
527 return "unpack-objects abnormal exit";
528 } else {
529 const char *keeper[7];
530 int s, status, i = 0;
531 char keep_arg[256];
532 struct child_process ip;
534 s = sprintf(keep_arg, "--keep=receive-pack %"PRIuMAX" on ", (uintmax_t) getpid());
535 if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
536 strcpy(keep_arg + s, "localhost");
538 keeper[i++] = "index-pack";
539 keeper[i++] = "--stdin";
540 if (receive_fsck_objects)
541 keeper[i++] = "--strict";
542 keeper[i++] = "--fix-thin";
543 keeper[i++] = hdr_arg;
544 keeper[i++] = keep_arg;
545 keeper[i++] = NULL;
546 memset(&ip, 0, sizeof(ip));
547 ip.argv = keeper;
548 ip.out = -1;
549 ip.git_cmd = 1;
550 status = start_command(&ip);
551 if (status) {
552 return "index-pack fork failed";
554 pack_lockfile = index_pack_lockfile(ip.out);
555 close(ip.out);
556 status = finish_command(&ip);
557 if (!status) {
558 reprepare_packed_git();
559 return NULL;
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 advertise_refs = 0;
633 int stateless_rpc = 0;
634 int i;
635 char *dir = NULL;
637 argv++;
638 for (i = 1; i < argc; i++) {
639 const char *arg = *argv++;
641 if (*arg == '-') {
642 if (!strcmp(arg, "--advertise-refs")) {
643 advertise_refs = 1;
644 continue;
646 if (!strcmp(arg, "--stateless-rpc")) {
647 stateless_rpc = 1;
648 continue;
651 usage(receive_pack_usage);
653 if (dir)
654 usage(receive_pack_usage);
655 dir = xstrdup(arg);
657 if (!dir)
658 usage(receive_pack_usage);
660 setup_path();
662 if (!enter_repo(dir, 0))
663 die("'%s' does not appear to be a git repository", dir);
665 if (is_repository_shallow())
666 die("attempt to push into a shallow repository");
668 git_config(receive_pack_config, NULL);
670 if (0 <= transfer_unpack_limit)
671 unpack_limit = transfer_unpack_limit;
672 else if (0 <= receive_unpack_limit)
673 unpack_limit = receive_unpack_limit;
675 if (advertise_refs || !stateless_rpc) {
676 add_alternate_refs();
677 write_head_info();
678 clear_extra_refs();
680 /* EOF */
681 packet_flush(1);
683 if (advertise_refs)
684 return 0;
686 read_head_info();
687 if (commands) {
688 const char *unpack_status = NULL;
690 if (!delete_only(commands))
691 unpack_status = unpack();
692 execute_commands(unpack_status);
693 if (pack_lockfile)
694 unlink_or_warn(pack_lockfile);
695 if (report_status)
696 report(unpack_status);
697 run_receive_hook(post_receive_hook);
698 run_update_post_hook(commands);
699 if (auto_gc) {
700 const char *argv_gc_auto[] = {
701 "gc", "--auto", "--quiet", NULL,
703 run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
705 if (auto_update_server_info)
706 update_server_info(0);
708 return 0;