4 #include "run-command.h"
6 static const char receive_pack_usage
[] = "git-receive-pack <git-dir>";
8 static const char *unpacker
[] = { "unpack-objects", NULL
};
10 static int report_status
;
12 static char capabilities
[] = "report-status";
13 static int capabilities_sent
;
15 static int show_ref(const char *path
, const unsigned char *sha1
)
17 if (capabilities_sent
)
18 packet_write(1, "%s %s\n", sha1_to_hex(sha1
), path
);
20 packet_write(1, "%s %s%c%s\n",
21 sha1_to_hex(sha1
), path
, 0, capabilities
);
22 capabilities_sent
= 1;
26 static void write_head_info(void)
28 for_each_ref(show_ref
);
29 if (!capabilities_sent
)
30 show_ref("capabilities^{}", null_sha1
);
36 const char *error_string
;
37 unsigned char old_sha1
[20];
38 unsigned char new_sha1
[20];
39 char ref_name
[FLEX_ARRAY
]; /* more */
42 static struct command
*commands
;
44 static int is_all_zeroes(const char *hex
)
47 for (i
= 0; i
< 40; i
++)
53 static int verify_old_ref(const char *name
, char *hex_contents
)
58 if (is_all_zeroes(hex_contents
))
60 fd
= open(name
, O_RDONLY
);
63 ret
= read(fd
, buffer
, 40);
67 if (memcmp(buffer
, hex_contents
, 40))
72 static char update_hook
[] = "hooks/update";
74 static int run_update_hook(const char *refname
,
75 char *old_hex
, char *new_hex
)
79 if (access(update_hook
, X_OK
) < 0)
81 code
= run_command(update_hook
, refname
, old_hex
, new_hex
, NULL
);
85 case -ERR_RUN_COMMAND_FORK
:
86 return error("hook fork failed");
87 case -ERR_RUN_COMMAND_EXEC
:
88 return error("hook execute failed");
89 case -ERR_RUN_COMMAND_WAITPID
:
90 return error("waitpid failed");
91 case -ERR_RUN_COMMAND_WAITPID_WRONG_PID
:
92 return error("waitpid is confused");
93 case -ERR_RUN_COMMAND_WAITPID_SIGNAL
:
94 return error("%s died of signal", update_hook
);
95 case -ERR_RUN_COMMAND_WAITPID_NOEXIT
:
96 return error("%s died strangely", update_hook
);
98 error("%s exited with error code %d", update_hook
, -code
);
103 static int update(struct command
*cmd
)
105 const char *name
= cmd
->ref_name
;
106 unsigned char *old_sha1
= cmd
->old_sha1
;
107 unsigned char *new_sha1
= cmd
->new_sha1
;
108 char new_hex
[60], *old_hex
, *lock_name
;
109 int newfd
, namelen
, written
;
111 cmd
->error_string
= NULL
;
112 if (!strncmp(name
, "refs/", 5) && check_ref_format(name
+ 5)) {
113 cmd
->error_string
= "funny refname";
114 return error("refusing to create funny ref '%s' locally",
118 namelen
= strlen(name
);
119 lock_name
= xmalloc(namelen
+ 10);
120 memcpy(lock_name
, name
, namelen
);
121 memcpy(lock_name
+ namelen
, ".lock", 6);
123 strcpy(new_hex
, sha1_to_hex(new_sha1
));
124 old_hex
= sha1_to_hex(old_sha1
);
125 if (!has_sha1_file(new_sha1
)) {
126 cmd
->error_string
= "bad pack";
127 return error("unpack should have generated %s, "
128 "but I can't find it!", new_hex
);
130 safe_create_leading_directories(lock_name
);
132 newfd
= open(lock_name
, O_CREAT
| O_EXCL
| O_WRONLY
, 0666);
134 cmd
->error_string
= "can't lock";
135 return error("unable to create %s (%s)",
136 lock_name
, strerror(errno
));
139 /* Write the ref with an ending '\n' */
142 written
= write(newfd
, new_hex
, 41);
143 /* Remove the '\n' again */
149 cmd
->error_string
= "can't write";
150 return error("unable to write %s", lock_name
);
152 if (verify_old_ref(name
, old_hex
) < 0) {
154 cmd
->error_string
= "raced";
155 return error("%s changed during push", name
);
157 if (run_update_hook(name
, old_hex
, new_hex
)) {
159 cmd
->error_string
= "hook declined";
160 return error("hook declined to update %s", name
);
162 else if (rename(lock_name
, name
) < 0) {
164 cmd
->error_string
= "can't rename";
165 return error("unable to replace %s", name
);
168 fprintf(stderr
, "%s: %s -> %s\n", name
, old_hex
, new_hex
);
173 static char update_post_hook
[] = "hooks/post-update";
175 static void run_update_post_hook(struct command
*cmd
)
177 struct command
*cmd_p
;
181 if (access(update_post_hook
, X_OK
) < 0)
183 for (argc
= 1, cmd_p
= cmd
; cmd_p
; cmd_p
= cmd_p
->next
) {
184 if (cmd_p
->error_string
)
188 argv
= xmalloc(sizeof(*argv
) * (1 + argc
));
189 argv
[0] = update_post_hook
;
191 for (argc
= 1, cmd_p
= cmd
; cmd_p
; cmd_p
= cmd_p
->next
) {
193 if (cmd_p
->error_string
)
195 p
= xmalloc(strlen(cmd_p
->ref_name
) + 1);
196 strcpy(p
, cmd_p
->ref_name
);
201 run_command_v_opt(argc
, argv
, RUN_COMMAND_NO_STDIO
);
205 * This gets called after(if) we've successfully
206 * unpacked the data payload.
208 static void execute_commands(void)
210 struct command
*cmd
= commands
;
216 run_update_post_hook(commands
);
219 static void read_head_info(void)
221 struct command
**p
= &commands
;
223 static char line
[1000];
224 unsigned char old_sha1
[20], new_sha1
[20];
229 len
= packet_read_line(0, line
, sizeof(line
));
232 if (line
[len
-1] == '\n')
237 get_sha1_hex(line
, old_sha1
) ||
238 get_sha1_hex(line
+ 41, new_sha1
))
239 die("protocol error: expected old/new/ref, got '%s'",
243 reflen
= strlen(refname
);
244 if (reflen
+ 82 < len
) {
245 if (strstr(refname
+ reflen
+ 1, "report-status"))
248 cmd
= xmalloc(sizeof(struct command
) + len
- 80);
249 hashcpy(cmd
->old_sha1
, old_sha1
);
250 hashcpy(cmd
->new_sha1
, new_sha1
);
251 memcpy(cmd
->ref_name
, line
+ 82, len
- 81);
252 cmd
->error_string
= "n/a (unpacker error)";
259 static const char *unpack(int *error_code
)
261 int code
= run_command_v_opt(1, unpacker
, RUN_GIT_CMD
);
267 case -ERR_RUN_COMMAND_FORK
:
268 return "unpack fork failed";
269 case -ERR_RUN_COMMAND_EXEC
:
270 return "unpack execute failed";
271 case -ERR_RUN_COMMAND_WAITPID
:
272 return "waitpid failed";
273 case -ERR_RUN_COMMAND_WAITPID_WRONG_PID
:
274 return "waitpid is confused";
275 case -ERR_RUN_COMMAND_WAITPID_SIGNAL
:
276 return "unpacker died of signal";
277 case -ERR_RUN_COMMAND_WAITPID_NOEXIT
:
278 return "unpacker died strangely";
281 return "unpacker exited with error code";
285 static void report(const char *unpack_status
)
288 packet_write(1, "unpack %s\n",
289 unpack_status
? unpack_status
: "ok");
290 for (cmd
= commands
; cmd
; cmd
= cmd
->next
) {
291 if (!cmd
->error_string
)
292 packet_write(1, "ok %s\n",
295 packet_write(1, "ng %s %s\n",
296 cmd
->ref_name
, cmd
->error_string
);
301 int main(int argc
, char **argv
)
307 for (i
= 1; i
< argc
; i
++) {
311 /* Do flag handling here */
312 usage(receive_pack_usage
);
315 usage(receive_pack_usage
);
319 usage(receive_pack_usage
);
321 if(!enter_repo(dir
, 0))
322 die("'%s': unable to chdir or not a git archive", dir
);
332 const char *unpack_status
= unpack(&code
);
336 report(unpack_status
);