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"
11
12static const char receive_pack_usage[] = "git receive-pack <git-dir>";
13
14enum deny_action {
15 DENY_UNCONFIGURED,
16 DENY_IGNORE,
17 DENY_WARN,
18 DENY_REFUSE,
19};
20
21static int deny_deletes;
22static int deny_non_fast_forwards;
23static enum deny_action deny_current_branch = DENY_UNCONFIGURED;
24static enum deny_action deny_delete_current = DENY_UNCONFIGURED;
25static int receive_fsck_objects;
26static int receive_unpack_limit = -1;
27static int transfer_unpack_limit = -1;
28static int unpack_limit = 100;
29static int report_status;
30static const char *head_name;
31
32static char capabilities[] = " report-status delete-refs ";
33static int capabilities_sent;
34
35static enum deny_action parse_deny_action(const char *var, const char *value)
36{
37 if (value) {
38 if (!strcasecmp(value, "ignore"))
39 return DENY_IGNORE;
40 if (!strcasecmp(value, "warn"))
41 return DENY_WARN;
42 if (!strcasecmp(value, "refuse"))
43 return DENY_REFUSE;
44 }
45 if (git_config_bool(var, value))
46 return DENY_REFUSE;
47 return DENY_IGNORE;
48}
49
50static int receive_pack_config(const char *var, const char *value, void *cb)
51{
52 if (strcmp(var, "receive.denydeletes") == 0) {
53 deny_deletes = git_config_bool(var, value);
54 return 0;
55 }
56
57 if (strcmp(var, "receive.denynonfastforwards") == 0) {
58 deny_non_fast_forwards = git_config_bool(var, value);
59 return 0;
60 }
61
62 if (strcmp(var, "receive.unpacklimit") == 0) {
63 receive_unpack_limit = git_config_int(var, value);
64 return 0;
65 }
66
67 if (strcmp(var, "transfer.unpacklimit") == 0) {
68 transfer_unpack_limit = git_config_int(var, value);
69 return 0;
70 }
71
72 if (strcmp(var, "receive.fsckobjects") == 0) {
73 receive_fsck_objects = git_config_bool(var, value);
74 return 0;
75 }
76
77 if (!strcmp(var, "receive.denycurrentbranch")) {
78 deny_current_branch = parse_deny_action(var, value);
79 return 0;
80 }
81
82 if (strcmp(var, "receive.denydeletecurrent") == 0) {
83 deny_delete_current = parse_deny_action(var, value);
84 return 0;
85 }
86
87 return git_default_config(var, value, cb);
88}
89
90static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
91{
92 if (capabilities_sent)
93 packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
94 else
95 packet_write(1, "%s %s%c%s\n",
96 sha1_to_hex(sha1), path, 0, capabilities);
97 capabilities_sent = 1;
98 return 0;
99}
100
101static void write_head_info(void)
102{
103 for_each_ref(show_ref, NULL);
104 if (!capabilities_sent)
105 show_ref("capabilities^{}", null_sha1, 0, NULL);
106
107}
108
109struct command {
110 struct command *next;
111 const char *error_string;
112 unsigned char old_sha1[20];
113 unsigned char new_sha1[20];
114 char ref_name[FLEX_ARRAY]; /* more */
115};
116
117static struct command *commands;
118
119static const char pre_receive_hook[] = "hooks/pre-receive";
120static const char post_receive_hook[] = "hooks/post-receive";
121
122static int hook_status(int code, const char *hook_name)
123{
124 switch (code) {
125 case 0:
126 return 0;
127 case -ERR_RUN_COMMAND_FORK:
128 return error("hook fork failed");
129 case -ERR_RUN_COMMAND_EXEC:
130 return error("hook execute failed");
131 case -ERR_RUN_COMMAND_PIPE:
132 return error("hook pipe failed");
133 case -ERR_RUN_COMMAND_WAITPID:
134 return error("waitpid failed");
135 case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
136 return error("waitpid is confused");
137 case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
138 return error("%s died of signal", hook_name);
139 case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
140 return error("%s died strangely", hook_name);
141 default:
142 error("%s exited with error code %d", hook_name, -code);
143 return -code;
144 }
145}
146
147static int run_receive_hook(const char *hook_name)
148{
149 static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
150 struct command *cmd;
151 struct child_process proc;
152 const char *argv[2];
153 int have_input = 0, code;
154
155 for (cmd = commands; !have_input && cmd; cmd = cmd->next) {
156 if (!cmd->error_string)
157 have_input = 1;
158 }
159
160 if (!have_input || access(hook_name, X_OK) < 0)
161 return 0;
162
163 argv[0] = hook_name;
164 argv[1] = NULL;
165
166 memset(&proc, 0, sizeof(proc));
167 proc.argv = argv;
168 proc.in = -1;
169 proc.stdout_to_stderr = 1;
170
171 code = start_command(&proc);
172 if (code)
173 return hook_status(code, hook_name);
174 for (cmd = commands; cmd; cmd = cmd->next) {
175 if (!cmd->error_string) {
176 size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
177 sha1_to_hex(cmd->old_sha1),
178 sha1_to_hex(cmd->new_sha1),
179 cmd->ref_name);
180 if (write_in_full(proc.in, buf, n) != n)
181 break;
182 }
183 }
184 close(proc.in);
185 return hook_status(finish_command(&proc), hook_name);
186}
187
188static int run_update_hook(struct command *cmd)
189{
190 static const char update_hook[] = "hooks/update";
191 struct child_process proc;
192 const char *argv[5];
193
194 if (access(update_hook, X_OK) < 0)
195 return 0;
196
197 argv[0] = update_hook;
198 argv[1] = cmd->ref_name;
199 argv[2] = sha1_to_hex(cmd->old_sha1);
200 argv[3] = sha1_to_hex(cmd->new_sha1);
201 argv[4] = NULL;
202
203 memset(&proc, 0, sizeof(proc));
204 proc.argv = argv;
205 proc.no_stdin = 1;
206 proc.stdout_to_stderr = 1;
207
208 return hook_status(run_command(&proc), update_hook);
209}
210
211static int is_ref_checked_out(const char *ref)
212{
213 if (is_bare_repository())
214 return 0;
215
216 if (!head_name)
217 return 0;
218 return !strcmp(head_name, ref);
219}
220
221static 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.",
227 "",
228 "You can set 'receive.denyCurrentBranch' configuration variable to",
229 "'refuse' in the remote repository to forbid pushing into its",
230 "current branch."
231 "",
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.",
235 "",
236 "To squelch this message, you can set it to 'warn'.",
237 "",
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'."
241};
242
243static void warn_unconfigured_deny(void)
244{
245 int i;
246 for (i = 0; i < ARRAY_SIZE(warn_unconfigured_deny_msg); i++)
247 warning("%s", warn_unconfigured_deny_msg[i]);
248}
249
250static 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.",
253 "",
254 "You can set 'receive.denyDeleteCurrent' configuration variable to",
255 "'refuse' in the remote repository to disallow deleting the current",
256 "branch.",
257 "",
258 "You can set it to 'ignore' to allow such a delete without a warning.",
259 "",
260 "To make this warning message less loud, you can set it to 'warn'.",
261 "",
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'."
265};
266
267static void warn_unconfigured_deny_delete_current(void)
268{
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]);
274}
275
276static const char *update(struct command *cmd)
277{
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;
282
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";
287 }
288
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";
302 }
303 }
304
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";
309 }
310
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";
315 }
316
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";
330 }
331 }
332 }
333
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;
340
341 old_object = parse_object(old_sha1);
342 new_object = parse_object(new_sha1);
343
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";
349 }
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";
361 }
362 }
363 if (run_update_hook(cmd)) {
364 error("hook declined to update %s", name);
365 return "hook declined";
366 }
367
368 if (is_null_sha1(new_sha1)) {
369 if (!parse_object(old_sha1)) {
370 warning ("Allowing deletion of corrupt ref.");
371 old_sha1 = NULL;
372 }
373 if (delete_ref(name, old_sha1, 0)) {
374 error("failed to delete %s", name);
375 return "failed to delete";
376 }
377 return NULL; /* good */
378 }
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";
384 }
385 if (write_ref_sha1(lock, new_sha1, "push")) {
386 return "failed to write"; /* error() already called */
387 }
388 return NULL; /* good */
389 }
390}
391
392static char update_post_hook[] = "hooks/post-update";
393
394static void run_update_post_hook(struct command *cmd)
395{
396 struct command *cmd_p;
397 int argc;
398 const char **argv;
399
400 for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
401 if (cmd_p->error_string)
402 continue;
403 argc++;
404 }
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;
409
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++;
418 }
419 argv[argc] = NULL;
420 run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
421 | RUN_COMMAND_STDOUT_TO_STDERR);
422}
423
424static void execute_commands(const char *unpacker_error)
425{
426 struct command *cmd = commands;
427 unsigned char sha1[20];
428
429 if (unpacker_error) {
430 while (cmd) {
431 cmd->error_string = "n/a (unpacker error)";
432 cmd = cmd->next;
433 }
434 return;
435 }
436
437 if (run_receive_hook(pre_receive_hook)) {
438 while (cmd) {
439 cmd->error_string = "pre-receive hook declined";
440 cmd = cmd->next;
441 }
442 return;
443 }
444
445 head_name = resolve_ref("HEAD", sha1, 0, NULL);
446
447 while (cmd) {
448 cmd->error_string = update(cmd);
449 cmd = cmd->next;
450 }
451}
452
453static void read_head_info(void)
454{
455 struct command **p = &commands;
456 for (;;) {
457 static char line[1000];
458 unsigned char old_sha1[20], new_sha1[20];
459 struct command *cmd;
460 char *refname;
461 int len, reflen;
462
463 len = packet_read_line(0, line, sizeof(line));
464 if (!len)
465 break;
466 if (line[len-1] == '\n')
467 line[--len] = 0;
468 if (len < 83 ||
469 line[40] != ' ' ||
470 line[81] != ' ' ||
471 get_sha1_hex(line, old_sha1) ||
472 get_sha1_hex(line + 41, new_sha1))
473 die("protocol error: expected old/new/ref, got '%s'",
474 line);
475
476 refname = line + 82;
477 reflen = strlen(refname);
478 if (reflen + 82 < len) {
479 if (strstr(refname + reflen + 1, "report-status"))
480 report_status = 1;
481 }
482 cmd = xmalloc(sizeof(struct command) + len - 80);
483 hashcpy(cmd->old_sha1, old_sha1);
484 hashcpy(cmd->new_sha1, new_sha1);
485 memcpy(cmd->ref_name, line + 82, len - 81);
486 cmd->error_string = NULL;
487 cmd->next = NULL;
488 *p = cmd;
489 p = &cmd->next;
490 }
491}
492
493static const char *parse_pack_header(struct pack_header *hdr)
494{
495 switch (read_pack_header(0, hdr)) {
496 case PH_ERROR_EOF:
497 return "eof before pack header was fully read";
498
499 case PH_ERROR_PACK_SIGNATURE:
500 return "protocol error (pack signature mismatch detected)";
501
502 case PH_ERROR_PROTOCOL:
503 return "protocol error (pack version unsupported)";
504
505 default:
506 return "unknown error in parse_pack_header";
507
508 case 0:
509 return NULL;
510 }
511}
512
513static const char *pack_lockfile;
514
515static const char *unpack(void)
516{
517 struct pack_header hdr;
518 const char *hdr_err;
519 char hdr_arg[38];
520
521 hdr_err = parse_pack_header(&hdr);
522 if (hdr_err)
523 return hdr_err;
524 snprintf(hdr_arg, sizeof(hdr_arg),
525 "--pack_header=%"PRIu32",%"PRIu32,
526 ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
527
528 if (ntohl(hdr.hdr_entries) < unpack_limit) {
529 int code, i = 0;
530 const char *unpacker[4];
531 unpacker[i++] = "unpack-objects";
532 if (receive_fsck_objects)
533 unpacker[i++] = "--strict";
534 unpacker[i++] = hdr_arg;
535 unpacker[i++] = NULL;
536 code = run_command_v_opt(unpacker, RUN_GIT_CMD);
537 switch (code) {
538 case 0:
539 return NULL;
540 case -ERR_RUN_COMMAND_FORK:
541 return "unpack fork failed";
542 case -ERR_RUN_COMMAND_EXEC:
543 return "unpack execute failed";
544 case -ERR_RUN_COMMAND_WAITPID:
545 return "waitpid failed";
546 case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
547 return "waitpid is confused";
548 case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
549 return "unpacker died of signal";
550 case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
551 return "unpacker died strangely";
552 default:
553 return "unpacker exited with error code";
554 }
555 } else {
556 const char *keeper[7];
557 int s, status, i = 0;
558 char keep_arg[256];
559 struct child_process ip;
560
561 s = sprintf(keep_arg, "--keep=receive-pack %"PRIuMAX" on ", (uintmax_t) getpid());
562 if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
563 strcpy(keep_arg + s, "localhost");
564
565 keeper[i++] = "index-pack";
566 keeper[i++] = "--stdin";
567 if (receive_fsck_objects)
568 keeper[i++] = "--strict";
569 keeper[i++] = "--fix-thin";
570 keeper[i++] = hdr_arg;
571 keeper[i++] = keep_arg;
572 keeper[i++] = NULL;
573 memset(&ip, 0, sizeof(ip));
574 ip.argv = keeper;
575 ip.out = -1;
576 ip.git_cmd = 1;
577 if (start_command(&ip))
578 return "index-pack fork failed";
579 pack_lockfile = index_pack_lockfile(ip.out);
580 close(ip.out);
581 status = finish_command(&ip);
582 if (!status) {
583 reprepare_packed_git();
584 return NULL;
585 }
586 return "index-pack abnormal exit";
587 }
588}
589
590static void report(const char *unpack_status)
591{
592 struct command *cmd;
593 packet_write(1, "unpack %s\n",
594 unpack_status ? unpack_status : "ok");
595 for (cmd = commands; cmd; cmd = cmd->next) {
596 if (!cmd->error_string)
597 packet_write(1, "ok %s\n",
598 cmd->ref_name);
599 else
600 packet_write(1, "ng %s %s\n",
601 cmd->ref_name, cmd->error_string);
602 }
603 packet_flush(1);
604}
605
606static int delete_only(struct command *cmd)
607{
608 while (cmd) {
609 if (!is_null_sha1(cmd->new_sha1))
610 return 0;
611 cmd = cmd->next;
612 }
613 return 1;
614}
615
616static int add_refs_from_alternate(struct alternate_object_database *e, void *unused)
617{
618 char *other;
619 size_t len;
620 struct remote *remote;
621 struct transport *transport;
622 const struct ref *extra;
623
624 e->name[-1] = '\0';
625 other = xstrdup(make_absolute_path(e->base));
626 e->name[-1] = '/';
627 len = strlen(other);
628
629 while (other[len-1] == '/')
630 other[--len] = '\0';
631 if (len < 8 || memcmp(other + len - 8, "/objects", 8))
632 return 0;
633 /* Is this a git repository with refs? */
634 memcpy(other + len - 8, "/refs", 6);
635 if (!is_directory(other))
636 return 0;
637 other[len - 8] = '\0';
638 remote = remote_get(other);
639 transport = transport_get(remote, other);
640 for (extra = transport_get_remote_refs(transport);
641 extra;
642 extra = extra->next) {
643 add_extra_ref(".have", extra->old_sha1, 0);
644 }
645 transport_disconnect(transport);
646 free(other);
647 return 0;
648}
649
650static void add_alternate_refs(void)
651{
652 foreach_alt_odb(add_refs_from_alternate, NULL);
653}
654
655int cmd_receive_pack(int argc, const char **argv, const char *prefix)
656{
657 int i;
658 char *dir = NULL;
659
660 argv++;
661 for (i = 1; i < argc; i++) {
662 const char *arg = *argv++;
663
664 if (*arg == '-') {
665 /* Do flag handling here */
666 usage(receive_pack_usage);
667 }
668 if (dir)
669 usage(receive_pack_usage);
670 dir = xstrdup(arg);
671 }
672 if (!dir)
673 usage(receive_pack_usage);
674
675 setup_path();
676
677 if (!enter_repo(dir, 0))
678 die("'%s' does not appear to be a git repository", dir);
679
680 if (is_repository_shallow())
681 die("attempt to push into a shallow repository");
682
683 git_config(receive_pack_config, NULL);
684
685 if (0 <= transfer_unpack_limit)
686 unpack_limit = transfer_unpack_limit;
687 else if (0 <= receive_unpack_limit)
688 unpack_limit = receive_unpack_limit;
689
690 add_alternate_refs();
691 write_head_info();
692 clear_extra_refs();
693
694 /* EOF */
695 packet_flush(1);
696
697 read_head_info();
698 if (commands) {
699 const char *unpack_status = NULL;
700
701 if (!delete_only(commands))
702 unpack_status = unpack();
703 execute_commands(unpack_status);
704 if (pack_lockfile)
705 unlink(pack_lockfile);
706 if (report_status)
707 report(unpack_status);
708 run_receive_hook(post_receive_hook);
709 run_update_post_hook(commands);
710 }
711 return 0;
712}