Code

Uncomment test case: git branch c/d should barf if branch c exists.
[git.git] / receive-pack.c
1 #include "cache.h"
2 #include "refs.h"
3 #include "pkt-line.h"
4 #include "run-command.h"
5 #include "commit.h"
6 #include "object.h"
8 static const char receive_pack_usage[] = "git-receive-pack <git-dir>";
10 static const char *unpacker[] = { "unpack-objects", NULL };
12 static int report_status;
14 static char capabilities[] = "report-status";
15 static int capabilities_sent;
17 static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
18 {
19         if (capabilities_sent)
20                 packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
21         else
22                 packet_write(1, "%s %s%c%s\n",
23                              sha1_to_hex(sha1), path, 0, capabilities);
24         capabilities_sent = 1;
25         return 0;
26 }
28 static void write_head_info(void)
29 {
30         for_each_ref(show_ref, NULL);
31         if (!capabilities_sent)
32                 show_ref("capabilities^{}", null_sha1, 0, NULL);
34 }
36 struct command {
37         struct command *next;
38         const char *error_string;
39         unsigned char old_sha1[20];
40         unsigned char new_sha1[20];
41         char ref_name[FLEX_ARRAY]; /* more */
42 };
44 static struct command *commands;
46 static char update_hook[] = "hooks/update";
48 static int run_update_hook(const char *refname,
49                            char *old_hex, char *new_hex)
50 {
51         int code;
53         if (access(update_hook, X_OK) < 0)
54                 return 0;
55         code = run_command(update_hook, refname, old_hex, new_hex, NULL);
56         switch (code) {
57         case 0:
58                 return 0;
59         case -ERR_RUN_COMMAND_FORK:
60                 return error("hook fork failed");
61         case -ERR_RUN_COMMAND_EXEC:
62                 return error("hook execute failed");
63         case -ERR_RUN_COMMAND_WAITPID:
64                 return error("waitpid failed");
65         case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
66                 return error("waitpid is confused");
67         case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
68                 return error("%s died of signal", update_hook);
69         case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
70                 return error("%s died strangely", update_hook);
71         default:
72                 error("%s exited with error code %d", update_hook, -code);
73                 return -code;
74         }
75 }
77 static int update(struct command *cmd)
78 {
79         const char *name = cmd->ref_name;
80         unsigned char *old_sha1 = cmd->old_sha1;
81         unsigned char *new_sha1 = cmd->new_sha1;
82         char new_hex[41], old_hex[41];
83         struct ref_lock *lock;
85         cmd->error_string = NULL;
86         if (!strncmp(name, "refs/", 5) && check_ref_format(name + 5)) {
87                 cmd->error_string = "funny refname";
88                 return error("refusing to create funny ref '%s' locally",
89                              name);
90         }
92         strcpy(new_hex, sha1_to_hex(new_sha1));
93         strcpy(old_hex, sha1_to_hex(old_sha1));
94         if (!has_sha1_file(new_sha1)) {
95                 cmd->error_string = "bad pack";
96                 return error("unpack should have generated %s, "
97                              "but I can't find it!", new_hex);
98         }
99         if (deny_non_fast_forwards && !is_null_sha1(old_sha1)) {
100                 struct commit *old_commit, *new_commit;
101                 struct commit_list *bases, *ent;
103                 old_commit = (struct commit *)parse_object(old_sha1);
104                 new_commit = (struct commit *)parse_object(new_sha1);
105                 bases = get_merge_bases(old_commit, new_commit, 1);
106                 for (ent = bases; ent; ent = ent->next)
107                         if (!hashcmp(old_sha1, ent->item->object.sha1))
108                                 break;
109                 free_commit_list(bases);
110                 if (!ent)
111                         return error("denying non-fast forward;"
112                                      " you should pull first");
113         }
114         if (run_update_hook(name, old_hex, new_hex)) {
115                 cmd->error_string = "hook declined";
116                 return error("hook declined to update %s", name);
117         }
119         lock = lock_any_ref_for_update(name, old_sha1);
120         if (!lock) {
121                 cmd->error_string = "failed to lock";
122                 return error("failed to lock %s", name);
123         }
124         write_ref_sha1(lock, new_sha1, "push");
126         fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex);
127         return 0;
130 static char update_post_hook[] = "hooks/post-update";
132 static void run_update_post_hook(struct command *cmd)
134         struct command *cmd_p;
135         int argc;
136         const char **argv;
138         if (access(update_post_hook, X_OK) < 0)
139                 return;
140         for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
141                 if (cmd_p->error_string)
142                         continue;
143                 argc++;
144         }
145         argv = xmalloc(sizeof(*argv) * (1 + argc));
146         argv[0] = update_post_hook;
148         for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
149                 char *p;
150                 if (cmd_p->error_string)
151                         continue;
152                 p = xmalloc(strlen(cmd_p->ref_name) + 1);
153                 strcpy(p, cmd_p->ref_name);
154                 argv[argc] = p;
155                 argc++;
156         }
157         argv[argc] = NULL;
158         run_command_v_opt(argc, argv, RUN_COMMAND_NO_STDIO);
161 /*
162  * This gets called after(if) we've successfully
163  * unpacked the data payload.
164  */
165 static void execute_commands(void)
167         struct command *cmd = commands;
169         while (cmd) {
170                 update(cmd);
171                 cmd = cmd->next;
172         }
173         run_update_post_hook(commands);
176 static void read_head_info(void)
178         struct command **p = &commands;
179         for (;;) {
180                 static char line[1000];
181                 unsigned char old_sha1[20], new_sha1[20];
182                 struct command *cmd;
183                 char *refname;
184                 int len, reflen;
186                 len = packet_read_line(0, line, sizeof(line));
187                 if (!len)
188                         break;
189                 if (line[len-1] == '\n')
190                         line[--len] = 0;
191                 if (len < 83 ||
192                     line[40] != ' ' ||
193                     line[81] != ' ' ||
194                     get_sha1_hex(line, old_sha1) ||
195                     get_sha1_hex(line + 41, new_sha1))
196                         die("protocol error: expected old/new/ref, got '%s'",
197                             line);
199                 refname = line + 82;
200                 reflen = strlen(refname);
201                 if (reflen + 82 < len) {
202                         if (strstr(refname + reflen + 1, "report-status"))
203                                 report_status = 1;
204                 }
205                 cmd = xmalloc(sizeof(struct command) + len - 80);
206                 hashcpy(cmd->old_sha1, old_sha1);
207                 hashcpy(cmd->new_sha1, new_sha1);
208                 memcpy(cmd->ref_name, line + 82, len - 81);
209                 cmd->error_string = "n/a (unpacker error)";
210                 cmd->next = NULL;
211                 *p = cmd;
212                 p = &cmd->next;
213         }
216 static const char *unpack(int *error_code)
218         int code = run_command_v_opt(1, unpacker, RUN_GIT_CMD);
220         *error_code = 0;
221         switch (code) {
222         case 0:
223                 return NULL;
224         case -ERR_RUN_COMMAND_FORK:
225                 return "unpack fork failed";
226         case -ERR_RUN_COMMAND_EXEC:
227                 return "unpack execute failed";
228         case -ERR_RUN_COMMAND_WAITPID:
229                 return "waitpid failed";
230         case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
231                 return "waitpid is confused";
232         case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
233                 return "unpacker died of signal";
234         case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
235                 return "unpacker died strangely";
236         default:
237                 *error_code = -code;
238                 return "unpacker exited with error code";
239         }
242 static void report(const char *unpack_status)
244         struct command *cmd;
245         packet_write(1, "unpack %s\n",
246                      unpack_status ? unpack_status : "ok");
247         for (cmd = commands; cmd; cmd = cmd->next) {
248                 if (!cmd->error_string)
249                         packet_write(1, "ok %s\n",
250                                      cmd->ref_name);
251                 else
252                         packet_write(1, "ng %s %s\n",
253                                      cmd->ref_name, cmd->error_string);
254         }
255         packet_flush(1);
258 int main(int argc, char **argv)
260         int i;
261         char *dir = NULL;
263         argv++;
264         for (i = 1; i < argc; i++) {
265                 char *arg = *argv++;
267                 if (*arg == '-') {
268                         /* Do flag handling here */
269                         usage(receive_pack_usage);
270                 }
271                 if (dir)
272                         usage(receive_pack_usage);
273                 dir = arg;
274         }
275         if (!dir)
276                 usage(receive_pack_usage);
278         if (!enter_repo(dir, 0))
279                 die("'%s': unable to chdir or not a git archive", dir);
281         setup_ident();
282         git_config(git_default_config);
284         write_head_info();
286         /* EOF */
287         packet_flush(1);
289         read_head_info();
290         if (commands) {
291                 int code;
292                 const char *unpack_status = unpack(&code);
293                 if (!unpack_status)
294                         execute_commands();
295                 if (report_status)
296                         report(unpack_status);
297         }
298         return 0;