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