receive-pack.c 10.6 KB
Newer Older
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 8
#include "commit.h"
#include "object.h"
9
#include <sys/wait.h>
10

11
static const char receive_pack_usage[] = "git-receive-pack <git-dir>";
12

13
static int deny_non_fast_forwards = 0;
14
static int unpack_limit = 5000;
15
static int report_status;
16

17
static char capabilities[] = " report-status delete-refs ";
18
static int capabilities_sent;
19

20 21 22 23 24 25 26 27 28 29
static int receive_pack_config(const char *var, const char *value)
{
	git_default_config(var, value);

	if (strcmp(var, "receive.denynonfastforwards") == 0)
	{
		deny_non_fast_forwards = git_config_bool(var, value);
		return 0;
	}

30 31 32 33 34 35
	if (strcmp(var, "receive.unpacklimit") == 0)
	{
		unpack_limit = git_config_int(var, value);
		return 0;
	}

36 37 38
	return 0;
}

39
static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
40
{
41 42 43 44 45 46
	if (capabilities_sent)
		packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
	else
		packet_write(1, "%s %s%c%s\n",
			     sha1_to_hex(sha1), path, 0, capabilities);
	capabilities_sent = 1;
47
	return 0;
48 49
}

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);
55

56 57
}

58 59
struct command {
	struct command *next;
60
	const char *error_string;
61 62
	unsigned char old_sha1[20];
	unsigned char new_sha1[20];
63
	char ref_name[FLEX_ARRAY]; /* more */
64 65
};

66
static struct command *commands;
67

68 69 70 71 72 73 74 75 76 77 78 79 80 81
static char update_hook[] = "hooks/update";

static int run_update_hook(const char *refname,
			   char *old_hex, char *new_hex)
{
	int code;

	if (access(update_hook, X_OK) < 0)
		return 0;
	code = run_command(update_hook, refname, old_hex, new_hex, NULL);
	switch (code) {
	case 0:
		return 0;
	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 94 95 96 97 98
	default:
		error("%s exited with error code %d", update_hook, -code);
		return -code;
	}
}

99
static int update(struct command *cmd)
100
{
101 102 103
	const char *name = cmd->ref_name;
	unsigned char *old_sha1 = cmd->old_sha1;
	unsigned char *new_sha1 = cmd->new_sha1;
104 105
	char new_hex[41], old_hex[41];
	struct ref_lock *lock;
106

107 108 109
	cmd->error_string = NULL;
	if (!strncmp(name, "refs/", 5) && check_ref_format(name + 5)) {
		cmd->error_string = "funny refname";
110 111
		return error("refusing to create funny ref '%s' locally",
			     name);
112
	}
113

114
	strcpy(new_hex, sha1_to_hex(new_sha1));
115
	strcpy(old_hex, sha1_to_hex(old_sha1));
116 117

	if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
118
		cmd->error_string = "bad pack";
J
Junio C Hamano 已提交
119 120
		return error("unpack should have generated %s, "
			     "but I can't find it!", new_hex);
121
	}
122
	if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
J
Junio C Hamano 已提交
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;
127 128 129

		old_commit = (struct commit *)parse_object(old_sha1);
		new_commit = (struct commit *)parse_object(new_sha1);
130 131 132
		bases = get_merge_bases(old_commit, new_commit, 1);
		for (ent = bases; ent; ent = ent->next)
			if (!hashcmp(old_sha1, ent->item->object.sha1))
133
				break;
134 135
		free_commit_list(bases);
		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
	}
143

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
	if (is_null_sha1(new_sha1)) {
		if (delete_ref(name, old_sha1)) {
			cmd->error_string = "failed to delete";
			return error("failed to delete %s", name);
		}
		fprintf(stderr, "%s: %s -> deleted\n", name, old_hex);
	}
	else {
		lock = lock_any_ref_for_update(name, old_sha1);
		if (!lock) {
			cmd->error_string = "failed to lock";
			return error("failed to lock %s", name);
		}
		write_ref_sha1(lock, new_sha1, "push");
		fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex);
J
Junio C Hamano 已提交
159
	}
160
	return 0;
161 162
}

J
Junio C Hamano 已提交
163 164 165 166 167 168
static char update_post_hook[] = "hooks/post-update";

static void run_update_post_hook(struct command *cmd)
{
	struct command *cmd_p;
	int argc;
J
Junio C Hamano 已提交
169
	const char **argv;
J
Junio C Hamano 已提交
170 171 172 173

	if (access(update_post_hook, X_OK) < 0)
		return;
	for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
174
		if (cmd_p->error_string)
J
Junio C Hamano 已提交
175 176 177 178 179 180 181
			continue;
		argc++;
	}
	argv = xmalloc(sizeof(*argv) * (1 + argc));
	argv[0] = update_post_hook;

	for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
J
Junio C Hamano 已提交
182
		char *p;
183
		if (cmd_p->error_string)
J
Junio C Hamano 已提交
184
			continue;
J
Junio C Hamano 已提交
185 186 187
		p = xmalloc(strlen(cmd_p->ref_name) + 1);
		strcpy(p, cmd_p->ref_name);
		argv[argc] = p;
J
Junio C Hamano 已提交
188 189 190
		argc++;
	}
	argv[argc] = NULL;
191
	run_command_v_opt(argc, argv, RUN_COMMAND_NO_STDIO);
J
Junio C Hamano 已提交
192
}
193

194 195 196 197 198 199
/*
 * This gets called after(if) we've successfully
 * unpacked the data payload.
 */
static void execute_commands(void)
{
200 201 202
	struct command *cmd = commands;

	while (cmd) {
203
		update(cmd);
204
		cmd = cmd->next;
205
	}
J
Junio C Hamano 已提交
206
	run_update_post_hook(commands);
207 208 209 210
}

static void read_head_info(void)
{
211
	struct command **p = &commands;
212 213
	for (;;) {
		static char line[1000];
214 215
		unsigned char old_sha1[20], new_sha1[20];
		struct command *cmd;
216 217
		char *refname;
		int len, reflen;
218 219

		len = packet_read_line(0, line, sizeof(line));
220 221
		if (!len)
			break;
222 223 224 225 226 227 228
		if (line[len-1] == '\n')
			line[--len] = 0;
		if (len < 83 ||
		    line[40] != ' ' ||
		    line[81] != ' ' ||
		    get_sha1_hex(line, old_sha1) ||
		    get_sha1_hex(line + 41, new_sha1))
229 230 231 232 233 234 235 236 237
			die("protocol error: expected old/new/ref, got '%s'",
			    line);

		refname = line + 82;
		reflen = strlen(refname);
		if (reflen + 82 < len) {
			if (strstr(refname + reflen + 1, "report-status"))
				report_status = 1;
		}
238
		cmd = xmalloc(sizeof(struct command) + len - 80);
239 240
		hashcpy(cmd->old_sha1, old_sha1);
		hashcpy(cmd->new_sha1, new_sha1);
241
		memcpy(cmd->ref_name, line + 82, len - 81);
242
		cmd->error_string = "n/a (unpacker error)";
243 244 245
		cmd->next = NULL;
		*p = cmd;
		p = &cmd->next;
246 247 248
	}
}

249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
static const char *parse_pack_header(struct pack_header *hdr)
{
	char *c = (char*)hdr;
	ssize_t remaining = sizeof(struct pack_header);
	do {
		ssize_t r = xread(0, c, remaining);
		if (r <= 0)
			return "eof before pack header was fully read";
		remaining -= r;
		c += r;
	} while (remaining > 0);
	if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
		return "protocol error (pack signature mismatch detected)";
	if (!pack_version_ok(hdr->hdr_version))
		return "protocol error (pack version unsupported)";
	return NULL;
}

267 268
static const char *pack_lockfile;

269
static const char *unpack(void)
270
{
271 272 273 274 275 276 277 278 279 280 281
	struct pack_header hdr;
	const char *hdr_err;
	char hdr_arg[38];

	hdr_err = parse_pack_header(&hdr);
	if (hdr_err)
		return hdr_err;
	snprintf(hdr_arg, sizeof(hdr_arg), "--pack_header=%u,%u",
			ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));

	if (ntohl(hdr.hdr_entries) < unpack_limit) {
282
		int code;
283 284 285 286 287
		const char *unpacker[3];
		unpacker[0] = "unpack-objects";
		unpacker[1] = hdr_arg;
		unpacker[2] = NULL;
		code = run_command_v_opt(1, unpacker, RUN_GIT_CMD);
288
		switch (code) {
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
		case 0:
			return NULL;
		case -ERR_RUN_COMMAND_FORK:
			return "unpack fork failed";
		case -ERR_RUN_COMMAND_EXEC:
			return "unpack execute failed";
		case -ERR_RUN_COMMAND_WAITPID:
			return "waitpid failed";
		case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
			return "waitpid is confused";
		case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
			return "unpacker died of signal";
		case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
			return "unpacker died strangely";
		default:
			return "unpacker exited with error code";
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
		}
	} else {
		const char *keeper[6];
		int fd[2], s, len, status;
		pid_t pid;
		char keep_arg[256];
		char packname[46];

		s = sprintf(keep_arg, "--keep=receive-pack %i on ", getpid());
		if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
			strcpy(keep_arg + s, "localhost");

		keeper[0] = "index-pack";
		keeper[1] = "--stdin";
		keeper[2] = "--fix-thin";
		keeper[3] = hdr_arg;
		keeper[4] = keep_arg;
		keeper[5] = NULL;

		if (pipe(fd) < 0)
			return "index-pack pipe failed";
		pid = fork();
		if (pid < 0)
			return "index-pack fork failed";
		if (!pid) {
			dup2(fd[1], 1);
			close(fd[1]);
			close(fd[0]);
			execv_git_cmd(keeper);
			die("execv of index-pack failed");
		}
		close(fd[1]);

		/*
		 * The first thing we expects from index-pack's output
		 * is "pack\t%40s\n" or "keep\t%40s\n" (46 bytes) where
		 * %40s is the newly created pack SHA1 name.  In the "keep"
		 * case, we need it to remove the corresponding .keep file
		 * later on.  If we don't get that then tough luck with it.
		 */
		for (len = 0;
		     len < 46 && (s = xread(fd[0], packname+len, 46-len)) > 0;
		     len += s);
		close(fd[0]);
		if (len == 46 && packname[45] == '\n' &&
		    memcmp(packname, "keep\t", 5) == 0) {
			char path[PATH_MAX];
			packname[45] = 0;
			snprintf(path, sizeof(path), "%s/pack/pack-%s.keep",
				 get_object_directory(), packname + 5);
			pack_lockfile = xstrdup(path);
		}

		/* Then wrap our index-pack process. */
		while (waitpid(pid, &status, 0) < 0)
			if (errno != EINTR)
				return "waitpid failed";
		if (WIFEXITED(status)) {
			int code = WEXITSTATUS(status);
			if (code)
				return "index-pack exited with error code";
			reprepare_packed_git();
			return NULL;
		}
		return "index-pack abnormal exit";
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
	}
}

static void report(const char *unpack_status)
{
	struct command *cmd;
	packet_write(1, "unpack %s\n",
		     unpack_status ? unpack_status : "ok");
	for (cmd = commands; cmd; cmd = cmd->next) {
		if (!cmd->error_string)
			packet_write(1, "ok %s\n",
				     cmd->ref_name);
		else
			packet_write(1, "ng %s %s\n",
				     cmd->ref_name, cmd->error_string);
385
	}
386
	packet_flush(1);
387 388
}

389 390 391 392 393 394 395 396 397 398
static int delete_only(struct command *cmd)
{
	while (cmd) {
		if (!is_null_sha1(cmd->new_sha1))
			return 0;
		cmd = cmd->next;
	}
	return 1;
}

399 400
int main(int argc, char **argv)
{
401
	int i;
402
	char *dir = NULL;
403 404 405

	argv++;
	for (i = 1; i < argc; i++) {
406
		char *arg = *argv++;
407 408 409 410 411

		if (*arg == '-') {
			/* Do flag handling here */
			usage(receive_pack_usage);
		}
412 413
		if (dir)
			usage(receive_pack_usage);
414 415 416 417 418
		dir = arg;
	}
	if (!dir)
		usage(receive_pack_usage);

419
	if (!enter_repo(dir, 0))
420
		die("'%s': unable to chdir or not a git archive", dir);
421

422
	setup_ident();
423 424
	git_config(receive_pack_config);

425
	write_head_info();
426 427

	/* EOF */
428
	packet_flush(1);
429 430

	read_head_info();
431
	if (commands) {
432 433 434 435
		const char *unpack_status = NULL;

		if (!delete_only(commands))
			unpack_status = unpack();
436 437
		if (!unpack_status)
			execute_commands();
438 439
		if (pack_lockfile)
			unlink(pack_lockfile);
440 441
		if (report_status)
			report(unpack_status);
442
	}
443 444
	return 0;
}