Code

Merge branch 'maint'
[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 = 5000;
15 static int report_status;
17 static char capabilities[] = "report-status";
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));
116         if (!has_sha1_file(new_sha1)) {
117                 cmd->error_string = "bad pack";
118                 return error("unpack should have generated %s, "
119                              "but I can't find it!", new_hex);
120         }
121         if (deny_non_fast_forwards && !is_null_sha1(old_sha1)) {
122                 struct commit *old_commit, *new_commit;
123                 struct commit_list *bases, *ent;
125                 old_commit = (struct commit *)parse_object(old_sha1);
126                 new_commit = (struct commit *)parse_object(new_sha1);
127                 bases = get_merge_bases(old_commit, new_commit, 1);
128                 for (ent = bases; ent; ent = ent->next)
129                         if (!hashcmp(old_sha1, ent->item->object.sha1))
130                                 break;
131                 free_commit_list(bases);
132                 if (!ent)
133                         return error("denying non-fast forward;"
134                                      " you should pull first");
135         }
136         if (run_update_hook(name, old_hex, new_hex)) {
137                 cmd->error_string = "hook declined";
138                 return error("hook declined to update %s", name);
139         }
141         lock = lock_any_ref_for_update(name, old_sha1);
142         if (!lock) {
143                 cmd->error_string = "failed to lock";
144                 return error("failed to lock %s", name);
145         }
146         write_ref_sha1(lock, new_sha1, "push");
148         fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex);
149         return 0;
152 static char update_post_hook[] = "hooks/post-update";
154 static void run_update_post_hook(struct command *cmd)
156         struct command *cmd_p;
157         int argc;
158         const char **argv;
160         if (access(update_post_hook, X_OK) < 0)
161                 return;
162         for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
163                 if (cmd_p->error_string)
164                         continue;
165                 argc++;
166         }
167         argv = xmalloc(sizeof(*argv) * (1 + argc));
168         argv[0] = update_post_hook;
170         for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
171                 char *p;
172                 if (cmd_p->error_string)
173                         continue;
174                 p = xmalloc(strlen(cmd_p->ref_name) + 1);
175                 strcpy(p, cmd_p->ref_name);
176                 argv[argc] = p;
177                 argc++;
178         }
179         argv[argc] = NULL;
180         run_command_v_opt(argc, argv, RUN_COMMAND_NO_STDIO);
183 /*
184  * This gets called after(if) we've successfully
185  * unpacked the data payload.
186  */
187 static void execute_commands(void)
189         struct command *cmd = commands;
191         while (cmd) {
192                 update(cmd);
193                 cmd = cmd->next;
194         }
195         run_update_post_hook(commands);
198 static void read_head_info(void)
200         struct command **p = &commands;
201         for (;;) {
202                 static char line[1000];
203                 unsigned char old_sha1[20], new_sha1[20];
204                 struct command *cmd;
205                 char *refname;
206                 int len, reflen;
208                 len = packet_read_line(0, line, sizeof(line));
209                 if (!len)
210                         break;
211                 if (line[len-1] == '\n')
212                         line[--len] = 0;
213                 if (len < 83 ||
214                     line[40] != ' ' ||
215                     line[81] != ' ' ||
216                     get_sha1_hex(line, old_sha1) ||
217                     get_sha1_hex(line + 41, new_sha1))
218                         die("protocol error: expected old/new/ref, got '%s'",
219                             line);
221                 refname = line + 82;
222                 reflen = strlen(refname);
223                 if (reflen + 82 < len) {
224                         if (strstr(refname + reflen + 1, "report-status"))
225                                 report_status = 1;
226                 }
227                 cmd = xmalloc(sizeof(struct command) + len - 80);
228                 hashcpy(cmd->old_sha1, old_sha1);
229                 hashcpy(cmd->new_sha1, new_sha1);
230                 memcpy(cmd->ref_name, line + 82, len - 81);
231                 cmd->error_string = "n/a (unpacker error)";
232                 cmd->next = NULL;
233                 *p = cmd;
234                 p = &cmd->next;
235         }
238 static const char *parse_pack_header(struct pack_header *hdr)
240         char *c = (char*)hdr;
241         ssize_t remaining = sizeof(struct pack_header);
242         do {
243                 ssize_t r = xread(0, c, remaining);
244                 if (r <= 0)
245                         return "eof before pack header was fully read";
246                 remaining -= r;
247                 c += r;
248         } while (remaining > 0);
249         if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
250                 return "protocol error (pack signature mismatch detected)";
251         if (!pack_version_ok(hdr->hdr_version))
252                 return "protocol error (pack version unsupported)";
253         return NULL;
256 static const char *pack_lockfile;
258 static const char *unpack(void)
260         struct pack_header hdr;
261         const char *hdr_err;
262         char hdr_arg[38];
264         hdr_err = parse_pack_header(&hdr);
265         if (hdr_err)
266                 return hdr_err;
267         snprintf(hdr_arg, sizeof(hdr_arg), "--pack_header=%u,%u",
268                         ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
270         if (ntohl(hdr.hdr_entries) < unpack_limit) {
271                 int code;
272                 const char *unpacker[3];
273                 unpacker[0] = "unpack-objects";
274                 unpacker[1] = hdr_arg;
275                 unpacker[2] = NULL;
276                 code = run_command_v_opt(1, unpacker, RUN_GIT_CMD);
277                 switch (code) {
278                 case 0:
279                         return NULL;
280                 case -ERR_RUN_COMMAND_FORK:
281                         return "unpack fork failed";
282                 case -ERR_RUN_COMMAND_EXEC:
283                         return "unpack execute failed";
284                 case -ERR_RUN_COMMAND_WAITPID:
285                         return "waitpid failed";
286                 case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
287                         return "waitpid is confused";
288                 case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
289                         return "unpacker died of signal";
290                 case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
291                         return "unpacker died strangely";
292                 default:
293                         return "unpacker exited with error code";
294                 }
295         } else {
296                 const char *keeper[6];
297                 int fd[2], s, len, status;
298                 pid_t pid;
299                 char keep_arg[256];
300                 char packname[46];
302                 s = sprintf(keep_arg, "--keep=receive-pack %i on ", getpid());
303                 if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
304                         strcpy(keep_arg + s, "localhost");
306                 keeper[0] = "index-pack";
307                 keeper[1] = "--stdin";
308                 keeper[2] = "--fix-thin";
309                 keeper[3] = hdr_arg;
310                 keeper[4] = keep_arg;
311                 keeper[5] = NULL;
313                 if (pipe(fd) < 0)
314                         return "index-pack pipe failed";
315                 pid = fork();
316                 if (pid < 0)
317                         return "index-pack fork failed";
318                 if (!pid) {
319                         dup2(fd[1], 1);
320                         close(fd[1]);
321                         close(fd[0]);
322                         execv_git_cmd(keeper);
323                         die("execv of index-pack failed");
324                 }
325                 close(fd[1]);
327                 /*
328                  * The first thing we expects from index-pack's output
329                  * is "pack\t%40s\n" or "keep\t%40s\n" (46 bytes) where
330                  * %40s is the newly created pack SHA1 name.  In the "keep"
331                  * case, we need it to remove the corresponding .keep file
332                  * later on.  If we don't get that then tough luck with it.
333                  */
334                 for (len = 0;
335                      len < 46 && (s = xread(fd[0], packname+len, 46-len)) > 0;
336                      len += s);
337                 close(fd[0]);
338                 if (len == 46 && packname[45] == '\n' &&
339                     memcmp(packname, "keep\t", 5) == 0) {
340                         char path[PATH_MAX];
341                         packname[45] = 0;
342                         snprintf(path, sizeof(path), "%s/pack/pack-%s.keep",
343                                  get_object_directory(), packname + 5);
344                         pack_lockfile = xstrdup(path);
345                 }
347                 /* Then wrap our index-pack process. */
348                 while (waitpid(pid, &status, 0) < 0)
349                         if (errno != EINTR)
350                                 return "waitpid failed";
351                 if (WIFEXITED(status)) {
352                         int code = WEXITSTATUS(status);
353                         if (code)
354                                 return "index-pack exited with error code";
355                         reprepare_packed_git();
356                         return NULL;
357                 }
358                 return "index-pack abnormal exit";
359         }
362 static void report(const char *unpack_status)
364         struct command *cmd;
365         packet_write(1, "unpack %s\n",
366                      unpack_status ? unpack_status : "ok");
367         for (cmd = commands; cmd; cmd = cmd->next) {
368                 if (!cmd->error_string)
369                         packet_write(1, "ok %s\n",
370                                      cmd->ref_name);
371                 else
372                         packet_write(1, "ng %s %s\n",
373                                      cmd->ref_name, cmd->error_string);
374         }
375         packet_flush(1);
378 int main(int argc, char **argv)
380         int i;
381         char *dir = NULL;
383         argv++;
384         for (i = 1; i < argc; i++) {
385                 char *arg = *argv++;
387                 if (*arg == '-') {
388                         /* Do flag handling here */
389                         usage(receive_pack_usage);
390                 }
391                 if (dir)
392                         usage(receive_pack_usage);
393                 dir = arg;
394         }
395         if (!dir)
396                 usage(receive_pack_usage);
398         if (!enter_repo(dir, 0))
399                 die("'%s': unable to chdir or not a git archive", dir);
401         setup_ident();
402         git_config(receive_pack_config);
404         write_head_info();
406         /* EOF */
407         packet_flush(1);
409         read_head_info();
410         if (commands) {
411                 const char *unpack_status = unpack();
412                 if (!unpack_status)
413                         execute_commands();
414                 if (pack_lockfile)
415                         unlink(pack_lockfile);
416                 if (report_status)
417                         report(unpack_status);
418         }
419         return 0;