#include "cache.h"
#include "refs.h"
#include "pkt-line.h"
#include "run-command.h"
#include <sys/wait.h>

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

static const char unpacker[] = "git-unpack-objects";

static int show_ref(const char *path, const unsigned char *sha1)
{
	packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
	return 0;
}

static void write_head_info(void)
{
	for_each_ref(show_ref);
}

struct command {
	struct command *next;
	unsigned char updated;
	unsigned char old_sha1[20];
	unsigned char new_sha1[20];
	char ref_name[0];
};

static struct command *commands = NULL;

static int is_all_zeroes(const char *hex)
{
	int i;
	for (i = 0; i < 40; i++)
		if (*hex++ != '0')
			return 0;
	return 1;
}

static int verify_old_ref(const char *name, char *hex_contents)
{
	int fd, ret;
	char buffer[60];

	if (is_all_zeroes(hex_contents))
		return 0;
	fd = open(name, O_RDONLY);
	if (fd < 0)
		return -1;
	ret = read(fd, buffer, 40);
	close(fd);
	if (ret != 40)
		return -1;
	if (memcmp(buffer, hex_contents, 40))
		return -1;
	return 0;
}

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:
		die("hook fork failed");
	case -ERR_RUN_COMMAND_EXEC:
		die("hook execute failed");
	case -ERR_RUN_COMMAND_WAITPID:
		die("waitpid failed");
	case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
		die("waitpid is confused");
	case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
		fprintf(stderr, "%s died of signal\n", update_hook);
		return -1;
	case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
		die("%s died strangely", update_hook);
	default:
		error("%s exited with error code %d", update_hook, -code);
		return -code;
	}
}

static int update(const char *name,
		  unsigned char *old_sha1, unsigned char *new_sha1)
{
	char new_hex[60], *old_hex, *lock_name;
	int newfd, namelen, written;

	if (!strncmp(name, "refs/", 5) && check_ref_format(name + 5))
		return error("refusing to create funny ref '%s' locally",
			     name);

	namelen = strlen(name);
	lock_name = xmalloc(namelen + 10);
	memcpy(lock_name, name, namelen);
	memcpy(lock_name + namelen, ".lock", 6);

	strcpy(new_hex, sha1_to_hex(new_sha1));
	old_hex = sha1_to_hex(old_sha1);
	if (!has_sha1_file(new_sha1))
		return error("unpack should have generated %s, "
			     "but I can't find it!", new_hex);

	safe_create_leading_directories(lock_name);

	newfd = open(lock_name, O_CREAT | O_EXCL | O_WRONLY, 0666);
	if (newfd < 0)
		return error("unable to create %s (%s)",
			     lock_name, strerror(errno));

	/* Write the ref with an ending '\n' */
	new_hex[40] = '\n';
	new_hex[41] = 0;
	written = write(newfd, new_hex, 41);
	/* Remove the '\n' again */
	new_hex[40] = 0;

	close(newfd);
	if (written != 41) {
		unlink(lock_name);
		return error("unable to write %s", lock_name);
	}
	if (verify_old_ref(name, old_hex) < 0) {
		unlink(lock_name);
		return error("%s changed during push", name);
	}
	if (run_update_hook(name, old_hex, new_hex)) {
		unlink(lock_name);
		return error("hook declined to update %s\n", name);
	}
	else if (rename(lock_name, name) < 0) {
		unlink(lock_name);
		return error("unable to replace %s", name);
	}
	else {
		fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex);
		return 0;
	}
}

static char update_post_hook[] = "hooks/post-update";

static void run_update_post_hook(struct command *cmd)
{
	struct command *cmd_p;
	int argc;
	char **argv;

	if (access(update_post_hook, X_OK) < 0)
		return;
	for (argc = 1, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
		if (!cmd_p->updated)
			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) {
		if (!cmd_p->updated)
			continue;
		argv[argc] = xmalloc(strlen(cmd_p->ref_name) + 1);
		strcpy(argv[argc], cmd_p->ref_name);
		argc++;
	}
	argv[argc] = NULL;
	run_command_v_opt(argc, argv, RUN_COMMAND_NO_STDIO);
}

/*
 * This gets called after(if) we've successfully
 * unpacked the data payload.
 */
static void execute_commands(void)
{
	struct command *cmd = commands;

	while (cmd) {
		cmd->updated = !update(cmd->ref_name,
				       cmd->old_sha1, cmd->new_sha1);
		cmd = cmd->next;
	}
	run_update_post_hook(commands);
}

static void read_head_info(void)
{
	struct command **p = &commands;
	for (;;) {
		static char line[1000];
		unsigned char old_sha1[20], new_sha1[20];
		struct command *cmd;
		int len;

		len = packet_read_line(0, line, sizeof(line));
		if (!len)
			break;
		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))
			die("protocol error: expected old/new/ref, got '%s'", line);
		cmd = xmalloc(sizeof(struct command) + len - 80);
		memcpy(cmd->old_sha1, old_sha1, 20);
		memcpy(cmd->new_sha1, new_sha1, 20);
		memcpy(cmd->ref_name, line + 82, len - 81);
		cmd->next = NULL;
		*p = cmd;
		p = &cmd->next;
	}
}

static void unpack(void)
{
	int code = run_command(unpacker, NULL);
	switch (code) {
	case 0:
		return;
	case -ERR_RUN_COMMAND_FORK:
		die("unpack fork failed");
	case -ERR_RUN_COMMAND_EXEC:
		die("unpack execute failed");
	case -ERR_RUN_COMMAND_WAITPID:
		die("waitpid failed");
	case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
		die("waitpid is confused");
	case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
		die("%s died of signal", unpacker);
	case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
		die("%s died strangely", unpacker);
	default:
		die("%s exited with error code %d", unpacker, -code);
	}
}

int main(int argc, char **argv)
{
	int i;
	char *dir = NULL;

	argv++;
	for (i = 1; i < argc; i++) {
		char *arg = *argv++;

		if (*arg == '-') {
			/* Do flag handling here */
			usage(receive_pack_usage);
		}
		if (dir)
			usage(receive_pack_usage);
		dir = arg;
	}
	if (!dir)
		usage(receive_pack_usage);

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

	write_head_info();

	/* EOF */
	packet_flush(1);

	read_head_info();
	if (commands) {
		unpack();
		execute_commands();
	}
	return 0;
}
