Code

Merge branch 'js/branch-config'
[git.git] / 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 <sys/wait.h>
11 static const char receive_pack_usage[] = "git-receive-pack <git-dir>";
13 static int deny_non_fast_forwards = 0;
14 static int unpack_limit = 100;
15 static int report_status;
17 static char capabilities[] = " report-status delete-refs ";
18 static int capabilities_sent;
20 static int receive_pack_config(const char *var, const char *value)
21 {
22         git_default_config(var, value);
24         if (strcmp(var, "receive.denynonfastforwards") == 0)
25         {
26                 deny_non_fast_forwards = git_config_bool(var, value);
27                 return 0;
28         }
30         if (strcmp(var, "receive.unpacklimit") == 0)
31         {
32                 unpack_limit = git_config_int(var, value);
33                 return 0;
34         }
36         return 0;
37 }
39 static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
40 {
41         if (capabilities_sent)
42                 packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
43         else
44                 packet_write(1, "%s %s%c%s\n",
45                              sha1_to_hex(sha1), path, 0, capabilities);
46         capabilities_sent = 1;
47         return 0;
48 }
50 static void write_head_info(void)
51 {
52         for_each_ref(show_ref, NULL);
53         if (!capabilities_sent)
54                 show_ref("capabilities^{}", null_sha1, 0, NULL);
56 }
58 struct command {
59         struct command *next;
60         const char *error_string;
61         unsigned char old_sha1[20];
62         unsigned char new_sha1[20];
63         char ref_name[FLEX_ARRAY]; /* more */
64 };
66 static struct command *commands;
68 static char update_hook[] = "hooks/update";
70 static int run_update_hook(const char *refname,
71                            char *old_hex, char *new_hex)
72 {
73         int code;
75         if (access(update_hook, X_OK) < 0)
76                 return 0;
77         code = run_command(update_hook, refname, old_hex, new_hex, NULL);
78         switch (code) {
79         case 0:
80                 return 0;
81         case -ERR_RUN_COMMAND_FORK:
82                 return error("hook fork failed");
83         case -ERR_RUN_COMMAND_EXEC:
84                 return error("hook execute failed");
85         case -ERR_RUN_COMMAND_WAITPID:
86                 return error("waitpid failed");
87         case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
88                 return error("waitpid is confused");
89         case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
90                 return error("%s died of signal", update_hook);
91         case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
92                 return error("%s died strangely", update_hook);
93         default:
94                 error("%s exited with error code %d", update_hook, -code);
95                 return -code;
96         }
97 }
99 static int update(struct command *cmd)
101         const char *name = cmd->ref_name;
102         unsigned char *old_sha1 = cmd->old_sha1;
103         unsigned char *new_sha1 = cmd->new_sha1;
104         char new_hex[41], old_hex[41];
105         struct ref_lock *lock;
107         cmd->error_string = NULL;
108         if (!strncmp(name, "refs/", 5) && check_ref_format(name + 5)) {
109                 cmd->error_string = "funny refname";
110                 return error("refusing to create funny ref '%s' locally",
111                              name);
112         }
114         strcpy(new_hex, sha1_to_hex(new_sha1));
115         strcpy(old_hex, sha1_to_hex(old_sha1));
117         if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
118                 cmd->error_string = "bad pack";
119                 return error("unpack should have generated %s, "
120                              "but I can't find it!", new_hex);
121         }
122         if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
123             !is_null_sha1(old_sha1) &&
124             !strncmp(name, "refs/heads/", 11)) {
125                 struct commit *old_commit, *new_commit;
126                 struct commit_list *bases, *ent;
128                 old_commit = (struct commit *)parse_object(old_sha1);
129                 new_commit = (struct commit *)parse_object(new_sha1);
130                 bases = get_merge_bases(old_commit, new_commit, 1);
131                 for (ent = bases; ent; ent = ent->next)
132                         if (!hashcmp(old_sha1, ent->item->object.sha1))
133                                 break;
134                 free_commit_list(bases);
135                 if (!ent)
136                         return error("denying non-fast forward;"
137                                      " you should pull first");
138         }
139         if (run_update_hook(name, old_hex, new_hex)) {
140                 cmd->error_string = "hook declined";
141                 return error("hook declined to update %s", name);
142         }
144         if (is_null_sha1(new_sha1)) {
145                 if (delete_ref(name, old_sha1)) {
146                         cmd->error_string = "failed to delete";
147                         return error("failed to delete %s", name);
148                 }
149                 fprintf(stderr, "%s: %s -> deleted\n", name, old_hex);
150         }
151         else {
152                 lock = lock_any_ref_for_update(name, old_sha1);
153                 if (!lock) {
154                         cmd->error_string = "failed to lock";
155                         return error("failed to lock %s", name);
156                 }
157                 write_ref_sha1(lock, new_sha1, "push");
158                 fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex);
159         }
160         return 0;
163 static char update_post_hook[] = "hooks/post-update";
165 static void run_update_post_hook(struct command *cmd)
167         struct command *cmd_p;
168         int argc;
169         const char **argv;
171         if (access(update_post_hook, X_OK) < 0)
172                 return;
173         for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
174                 if (cmd_p->error_string)
175                         continue;
176                 argc++;
177         }
178         argv = xmalloc(sizeof(*argv) * (1 + argc));
179         argv[0] = update_post_hook;
181         for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
182                 char *p;
183                 if (cmd_p->error_string)
184                         continue;
185                 p = xmalloc(strlen(cmd_p->ref_name) + 1);
186                 strcpy(p, cmd_p->ref_name);
187                 argv[argc] = p;
188                 argc++;
189         }
190         argv[argc] = NULL;
191         run_command_v_opt(argc, argv, RUN_COMMAND_NO_STDIO);
194 /*
195  * This gets called after(if) we've successfully
196  * unpacked the data payload.
197  */
198 static void execute_commands(void)
200         struct command *cmd = commands;
202         while (cmd) {
203                 update(cmd);
204                 cmd = cmd->next;
205         }
206         run_update_post_hook(commands);
209 static void read_head_info(void)
211         struct command **p = &commands;
212         for (;;) {
213                 static char line[1000];
214                 unsigned char old_sha1[20], new_sha1[20];
215                 struct command *cmd;
216                 char *refname;
217                 int len, reflen;
219                 len = packet_read_line(0, line, sizeof(line));
220                 if (!len)
221                         break;
222                 if (line[len-1] == '\n')
223                         line[--len] = 0;
224                 if (len < 83 ||
225                     line[40] != ' ' ||
226                     line[81] != ' ' ||
227                     get_sha1_hex(line, old_sha1) ||
228                     get_sha1_hex(line + 41, new_sha1))
229                         die("protocol error: expected old/new/ref, got '%s'",
230                             line);
232                 refname = line + 82;
233                 reflen = strlen(refname);
234                 if (reflen + 82 < len) {
235                         if (strstr(refname + reflen + 1, "report-status"))
236                                 report_status = 1;
237                 }
238                 cmd = xmalloc(sizeof(struct command) + len - 80);
239                 hashcpy(cmd->old_sha1, old_sha1);
240                 hashcpy(cmd->new_sha1, new_sha1);
241                 memcpy(cmd->ref_name, line + 82, len - 81);
242                 cmd->error_string = "n/a (unpacker error)";
243                 cmd->next = NULL;
244                 *p = cmd;
245                 p = &cmd->next;
246         }
249 static const char *parse_pack_header(struct pack_header *hdr)
251         char *c = (char*)hdr;
252         ssize_t remaining = sizeof(struct pack_header);
253         do {
254                 ssize_t r = xread(0, c, remaining);
255                 if (r <= 0)
256                         return "eof before pack header was fully read";
257                 remaining -= r;
258                 c += r;
259         } while (remaining > 0);
260         if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
261                 return "protocol error (pack signature mismatch detected)";
262         if (!pack_version_ok(hdr->hdr_version))
263                 return "protocol error (pack version unsupported)";
264         return NULL;
267 static const char *pack_lockfile;
269 static const char *unpack(void)
271         struct pack_header hdr;
272         const char *hdr_err;
273         char hdr_arg[38];
275         hdr_err = parse_pack_header(&hdr);
276         if (hdr_err)
277                 return hdr_err;
278         snprintf(hdr_arg, sizeof(hdr_arg), "--pack_header=%u,%u",
279                         ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
281         if (ntohl(hdr.hdr_entries) < unpack_limit) {
282                 int code;
283                 const char *unpacker[3];
284                 unpacker[0] = "unpack-objects";
285                 unpacker[1] = hdr_arg;
286                 unpacker[2] = NULL;
287                 code = run_command_v_opt(1, unpacker, RUN_GIT_CMD);
288                 switch (code) {
289                 case 0:
290                         return NULL;
291                 case -ERR_RUN_COMMAND_FORK:
292                         return "unpack fork failed";
293                 case -ERR_RUN_COMMAND_EXEC:
294                         return "unpack execute failed";
295                 case -ERR_RUN_COMMAND_WAITPID:
296                         return "waitpid failed";
297                 case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
298                         return "waitpid is confused";
299                 case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
300                         return "unpacker died of signal";
301                 case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
302                         return "unpacker died strangely";
303                 default:
304                         return "unpacker exited with error code";
305                 }
306         } else {
307                 const char *keeper[6];
308                 int fd[2], s, len, status;
309                 pid_t pid;
310                 char keep_arg[256];
311                 char packname[46];
313                 s = sprintf(keep_arg, "--keep=receive-pack %i on ", getpid());
314                 if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
315                         strcpy(keep_arg + s, "localhost");
317                 keeper[0] = "index-pack";
318                 keeper[1] = "--stdin";
319                 keeper[2] = "--fix-thin";
320                 keeper[3] = hdr_arg;
321                 keeper[4] = keep_arg;
322                 keeper[5] = NULL;
324                 if (pipe(fd) < 0)
325                         return "index-pack pipe failed";
326                 pid = fork();
327                 if (pid < 0)
328                         return "index-pack fork failed";
329                 if (!pid) {
330                         dup2(fd[1], 1);
331                         close(fd[1]);
332                         close(fd[0]);
333                         execv_git_cmd(keeper);
334                         die("execv of index-pack failed");
335                 }
336                 close(fd[1]);
338                 /*
339                  * The first thing we expects from index-pack's output
340                  * is "pack\t%40s\n" or "keep\t%40s\n" (46 bytes) where
341                  * %40s is the newly created pack SHA1 name.  In the "keep"
342                  * case, we need it to remove the corresponding .keep file
343                  * later on.  If we don't get that then tough luck with it.
344                  */
345                 for (len = 0;
346                      len < 46 && (s = xread(fd[0], packname+len, 46-len)) > 0;
347                      len += s);
348                 close(fd[0]);
349                 if (len == 46 && packname[45] == '\n' &&
350                     memcmp(packname, "keep\t", 5) == 0) {
351                         char path[PATH_MAX];
352                         packname[45] = 0;
353                         snprintf(path, sizeof(path), "%s/pack/pack-%s.keep",
354                                  get_object_directory(), packname + 5);
355                         pack_lockfile = xstrdup(path);
356                 }
358                 /* Then wrap our index-pack process. */
359                 while (waitpid(pid, &status, 0) < 0)
360                         if (errno != EINTR)
361                                 return "waitpid failed";
362                 if (WIFEXITED(status)) {
363                         int code = WEXITSTATUS(status);
364                         if (code)
365                                 return "index-pack exited with error code";
366                         reprepare_packed_git();
367                         return NULL;
368                 }
369                 return "index-pack abnormal exit";
370         }
373 static void report(const char *unpack_status)
375         struct command *cmd;
376         packet_write(1, "unpack %s\n",
377                      unpack_status ? unpack_status : "ok");
378         for (cmd = commands; cmd; cmd = cmd->next) {
379                 if (!cmd->error_string)
380                         packet_write(1, "ok %s\n",
381                                      cmd->ref_name);
382                 else
383                         packet_write(1, "ng %s %s\n",
384                                      cmd->ref_name, cmd->error_string);
385         }
386         packet_flush(1);
389 static int delete_only(struct command *cmd)
391         while (cmd) {
392                 if (!is_null_sha1(cmd->new_sha1))
393                         return 0;
394                 cmd = cmd->next;
395         }
396         return 1;
399 int main(int argc, char **argv)
401         int i;
402         char *dir = NULL;
404         argv++;
405         for (i = 1; i < argc; i++) {
406                 char *arg = *argv++;
408                 if (*arg == '-') {
409                         /* Do flag handling here */
410                         usage(receive_pack_usage);
411                 }
412                 if (dir)
413                         usage(receive_pack_usage);
414                 dir = arg;
415         }
416         if (!dir)
417                 usage(receive_pack_usage);
419         if (!enter_repo(dir, 0))
420                 die("'%s': unable to chdir or not a git archive", dir);
422         setup_ident();
423         /* don't die if gecos is empty */
424         ignore_missing_committer_name();
425         git_config(receive_pack_config);
427         write_head_info();
429         /* EOF */
430         packet_flush(1);
432         read_head_info();
433         if (commands) {
434                 const char *unpack_status = NULL;
436                 if (!delete_only(commands))
437                         unpack_status = unpack();
438                 if (!unpack_status)
439                         execute_commands();
440                 if (pack_lockfile)
441                         unlink(pack_lockfile);
442                 if (report_status)
443                         report(unpack_status);
444         }
445         return 0;