/*
 * Check-out files from the "current cache directory"
 *
 * Copyright (C) 2005 Linus Torvalds
 *
 * Careful: order of argument flags does matter. For example,
 *
 *	git-checkout-index -a -f file.c
 *
 * Will first check out all files listed in the cache (but not
 * overwrite any old ones), and then force-checkout "file.c" a
 * second time (ie that one _will_ overwrite any old contents
 * with the same filename).
 *
 * Also, just doing "git-checkout-index" does nothing. You probably
 * meant "git-checkout-index -a". And if you want to force it, you
 * want "git-checkout-index -f -a".
 *
 * Intuitiveness is not the goal here. Repeatability is. The
 * reason for the "no arguments means no work" thing is that
 * from scripts you are supposed to be able to do things like
 *
 *	find . -name '*.h' -print0 | xargs -0 git-checkout-index -f --
 *
 * or:
 *
 *	find . -name '*.h' -print0 | git-checkout-index -f -z --stdin
 *
 * which will force all existing *.h files to be replaced with
 * their cached copies. If an empty command line implied "all",
 * then this would force-refresh everything in the cache, which
 * was not the point.
 *
 * Oh, and the "--" is just a good idea when you know the rest
 * will be filenames. Just so that you wouldn't have a filename
 * of "-a" causing problems (not possible in the above example,
 * but get used to it in scripting!).
 */
#include "builtin.h"
#include "cache.h"
#include "quote.h"
#include "cache-tree.h"

#define CHECKOUT_ALL 4
static int line_termination = '\n';
static int checkout_stage; /* default to checkout stage0 */
static int to_tempfile;
static char topath[4][PATH_MAX + 1];

static struct checkout state;

static void write_tempfile_record(const char *name, int prefix_length)
{
	int i;

	if (CHECKOUT_ALL == checkout_stage) {
		for (i = 1; i < 4; i++) {
			if (i > 1)
				putchar(' ');
			if (topath[i][0])
				fputs(topath[i], stdout);
			else
				putchar('.');
		}
	} else
		fputs(topath[checkout_stage], stdout);

	putchar('\t');
	write_name_quoted(name + prefix_length, stdout, line_termination);

	for (i = 0; i < 4; i++) {
		topath[i][0] = 0;
	}
}

static int checkout_file(const char *name, int prefix_length)
{
	int namelen = strlen(name);
	int pos = cache_name_pos(name, namelen);
	int has_same_name = 0;
	int did_checkout = 0;
	int errs = 0;

	if (pos < 0)
		pos = -pos - 1;

	while (pos < active_nr) {
		struct cache_entry *ce = active_cache[pos];
		if (ce_namelen(ce) != namelen ||
		    memcmp(ce->name, name, namelen))
			break;
		has_same_name = 1;
		pos++;
		if (ce_stage(ce) != checkout_stage
		    && (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
			continue;
		did_checkout = 1;
		if (checkout_entry(ce, &state,
		    to_tempfile ? topath[ce_stage(ce)] : NULL) < 0)
			errs++;
	}

	if (did_checkout) {
		if (to_tempfile)
			write_tempfile_record(name, prefix_length);
		return errs > 0 ? -1 : 0;
	}

	if (!state.quiet) {
		fprintf(stderr, "git-checkout-index: %s ", name);
		if (!has_same_name)
			fprintf(stderr, "is not in the cache");
		else if (checkout_stage)
			fprintf(stderr, "does not exist at stage %d",
				checkout_stage);
		else
			fprintf(stderr, "is unmerged");
		fputc('\n', stderr);
	}
	return -1;
}

static void checkout_all(const char *prefix, int prefix_length)
{
	int i, errs = 0;
	struct cache_entry* last_ce = NULL;

	for (i = 0; i < active_nr ; i++) {
		struct cache_entry *ce = active_cache[i];
		if (ce_stage(ce) != checkout_stage
		    && (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
			continue;
		if (prefix && *prefix &&
		    (ce_namelen(ce) <= prefix_length ||
		     memcmp(prefix, ce->name, prefix_length)))
			continue;
		if (last_ce && to_tempfile) {
			if (ce_namelen(last_ce) != ce_namelen(ce)
			    || memcmp(last_ce->name, ce->name, ce_namelen(ce)))
				write_tempfile_record(last_ce->name, prefix_length);
		}
		if (checkout_entry(ce, &state,
		    to_tempfile ? topath[ce_stage(ce)] : NULL) < 0)
			errs++;
		last_ce = ce;
	}
	if (last_ce && to_tempfile)
		write_tempfile_record(last_ce->name, prefix_length);
	if (errs)
		/* we have already done our error reporting.
		 * exit with the same code as die().
		 */
		exit(128);
}

static const char checkout_cache_usage[] =
"git-checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]|all] [--prefix=<string>] [--temp] [--] <file>...";

static struct lock_file lock_file;

int cmd_checkout_index(int argc, const char **argv, const char *prefix)
{
	int i;
	int newfd = -1;
	int all = 0;
	int read_from_stdin = 0;
	int prefix_length;

	git_config(git_default_config);
	state.base_dir = "";
	prefix_length = prefix ? strlen(prefix) : 0;

	if (read_cache() < 0) {
		die("invalid cache");
	}

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

		if (!strcmp(arg, "--")) {
			i++;
			break;
		}
		if (!strcmp(arg, "-a") || !strcmp(arg, "--all")) {
			all = 1;
			continue;
		}
		if (!strcmp(arg, "-f") || !strcmp(arg, "--force")) {
			state.force = 1;
			continue;
		}
		if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet")) {
			state.quiet = 1;
			continue;
		}
		if (!strcmp(arg, "-n") || !strcmp(arg, "--no-create")) {
			state.not_new = 1;
			continue;
		}
		if (!strcmp(arg, "-u") || !strcmp(arg, "--index")) {
			state.refresh_cache = 1;
			if (newfd < 0)
				newfd = hold_locked_index(&lock_file, 1);
			continue;
		}
		if (!strcmp(arg, "-z")) {
			line_termination = 0;
			continue;
		}
		if (!strcmp(arg, "--stdin")) {
			if (i != argc - 1)
				die("--stdin must be at the end");
			read_from_stdin = 1;
			i++; /* do not consider arg as a file name */
			break;
		}
		if (!strcmp(arg, "--temp")) {
			to_tempfile = 1;
			continue;
		}
		if (!prefixcmp(arg, "--prefix=")) {
			state.base_dir = arg+9;
			state.base_dir_len = strlen(state.base_dir);
			continue;
		}
		if (!prefixcmp(arg, "--stage=")) {
			if (!strcmp(arg + 8, "all")) {
				to_tempfile = 1;
				checkout_stage = CHECKOUT_ALL;
			} else {
				int ch = arg[8];
				if ('1' <= ch && ch <= '3')
					checkout_stage = arg[8] - '0';
				else
					die("stage should be between 1 and 3 or all");
			}
			continue;
		}
		if (arg[0] == '-')
			usage(checkout_cache_usage);
		break;
	}

	if (state.base_dir_len || to_tempfile) {
		/* when --prefix is specified we do not
		 * want to update cache.
		 */
		if (state.refresh_cache) {
			close(newfd); newfd = -1;
			rollback_lock_file(&lock_file);
		}
		state.refresh_cache = 0;
	}

	/* Check out named files first */
	for ( ; i < argc; i++) {
		const char *arg = argv[i];
		const char *p;

		if (all)
			die("git-checkout-index: don't mix '--all' and explicit filenames");
		if (read_from_stdin)
			die("git-checkout-index: don't mix '--stdin' and explicit filenames");
		p = prefix_path(prefix, prefix_length, arg);
		checkout_file(p, prefix_length);
		if (p < arg || p > arg + strlen(arg))
			free((char*)p);
	}

	if (read_from_stdin) {
		struct strbuf buf, nbuf;

		if (all)
			die("git-checkout-index: don't mix '--all' and '--stdin'");

		strbuf_init(&buf, 0);
		strbuf_init(&nbuf, 0);
		while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
			const char *p;
			if (line_termination && buf.buf[0] == '"') {
				strbuf_reset(&nbuf);
				if (unquote_c_style(&nbuf, buf.buf, NULL))
					die("line is badly quoted");
				strbuf_swap(&buf, &nbuf);
			}
			p = prefix_path(prefix, prefix_length, buf.buf);
			checkout_file(p, prefix_length);
			if (p < buf.buf || p > buf.buf + buf.len)
				free((char *)p);
		}
		strbuf_release(&nbuf);
		strbuf_release(&buf);
	}

	if (all)
		checkout_all(prefix, prefix_length);

	if (0 <= newfd &&
	    (write_cache(newfd, active_cache, active_nr) ||
	     close(newfd) || commit_locked_index(&lock_file)))
		die("Unable to write new index file");
	return 0;
}
