/*
 * GIT - The information manager from hell
 *
 * Copyright (C) Linus Torvalds, 2005
 */
#include "cache.h"
#include "diff.h"

static const char diff_files_usage[] =
"git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
COMMON_DIFF_OPTIONS_HELP;

static struct diff_options diff_options;
static int silent = 0;
static int diff_unmerged_stage = 2;
static int combine_merges = 0;
static int dense_combined_merges = 0;

static void show_unmerge(const char *path)
{
	diff_unmerge(&diff_options, path);
}

static void show_file(int pfx, struct cache_entry *ce)
{
	diff_addremove(&diff_options, pfx, ntohl(ce->ce_mode),
		       ce->sha1, ce->name, NULL);
}

static void show_modified(int oldmode, int mode,
			  const unsigned char *old_sha1, const unsigned char *sha1,
			  char *path)
{
	diff_change(&diff_options, oldmode, mode, old_sha1, sha1, path, NULL);
}

int main(int argc, const char **argv)
{
	const char **pathspec;
	const char *prefix = setup_git_directory();
	int entries, i;

	git_config(git_diff_config);
	diff_setup(&diff_options);
	while (1 < argc && argv[1][0] == '-') {
		if (!strcmp(argv[1], "--")) {
			argv++;
			argc--;
			break;
		}
		if (!strcmp(argv[1], "-0"))
			diff_unmerged_stage = 0;
		else if (!strcmp(argv[1], "-1"))
			diff_unmerged_stage = 1;
		else if (!strcmp(argv[1], "-2"))
			diff_unmerged_stage = 2;
		else if (!strcmp(argv[1], "-3"))
			diff_unmerged_stage = 3;
		else if (!strcmp(argv[1], "--base"))
			diff_unmerged_stage = 1;
		else if (!strcmp(argv[1], "--ours"))
			diff_unmerged_stage = 2;
		else if (!strcmp(argv[1], "--theirs"))
			diff_unmerged_stage = 3;
		else if (!strcmp(argv[1], "-q"))
			silent = 1;
		else if (!strcmp(argv[1], "-r"))
			; /* no-op */
		else if (!strcmp(argv[1], "-s"))
			; /* no-op */
		else if (!strcmp(argv[1], "-c"))
			combine_merges = 1;
		else if (!strcmp(argv[1], "--cc"))
			dense_combined_merges = combine_merges = 1;
		else {
			int diff_opt_cnt;
			diff_opt_cnt = diff_opt_parse(&diff_options,
						      argv+1, argc-1);
			if (diff_opt_cnt < 0)
				usage(diff_files_usage);
			else if (diff_opt_cnt) {
				argv += diff_opt_cnt;
				argc -= diff_opt_cnt;
				continue;
			}
			else
				usage(diff_files_usage);
		}
		argv++; argc--;
	}
	if (dense_combined_merges)
		diff_options.output_format = DIFF_FORMAT_PATCH;

	/* Find the directory, and set up the pathspec */
	pathspec = get_pathspec(prefix, argv + 1);
	entries = read_cache();

	if (diff_setup_done(&diff_options) < 0)
		usage(diff_files_usage);

	/* At this point, if argc == 1, then we are doing everything.
	 * Otherwise argv[1] .. argv[argc-1] have the explicit paths.
	 */
	if (entries < 0) {
		perror("read_cache");
		exit(1);
	}

	for (i = 0; i < entries; i++) {
		struct stat st;
		unsigned int oldmode, newmode;
		struct cache_entry *ce = active_cache[i];
		int changed;

		if (!ce_path_match(ce, pathspec))
			continue;

		if (ce_stage(ce)) {
			struct {
				struct combine_diff_path p;
				struct combine_diff_parent filler[5];
			} combine;
			int num_compare_stages = 0;

			combine.p.next = NULL;
			combine.p.len = ce_namelen(ce);
			combine.p.path = xmalloc(combine.p.len + 1);
			memcpy(combine.p.path, ce->name, combine.p.len);
			combine.p.path[combine.p.len] = 0;
			combine.p.mode = 0;
			memset(combine.p.sha1, 0, 20);
			memset(&combine.p.parent[0], 0,
			       sizeof(combine.filler));

			while (i < entries) {
				struct cache_entry *nce = active_cache[i];
				int stage;

				if (strcmp(ce->name, nce->name))
					break;

				/* Stage #2 (ours) is the first parent,
				 * stage #3 (theirs) is the second.
				 */
				stage = ce_stage(nce);
				if (2 <= stage) {
					int mode = ntohl(nce->ce_mode);
					num_compare_stages++;
					memcpy(combine.p.parent[stage-2].sha1,
					       nce->sha1, 20);
					combine.p.parent[stage-2].mode =
						DIFF_FILE_CANON_MODE(mode);
					combine.p.parent[stage-2].status =
						DIFF_STATUS_MODIFIED;
				}

				/* diff against the proper unmerged stage */
				if (stage == diff_unmerged_stage)
					ce = nce;
				i++;
			}
			/*
			 * Compensate for loop update
			 */
			i--;

			if (combine_merges && num_compare_stages == 2) {
				show_combined_diff(&combine.p, 2,
						   dense_combined_merges,
						   NULL,
						   &diff_options);
				free(combine.p.path);
				continue;
			}
			free(combine.p.path);

			/*
			 * Show the diff for the 'ce' if we found the one
			 * from the desired stage.
			 */
			show_unmerge(ce->name);
			if (ce_stage(ce) != diff_unmerged_stage)
				continue;
		}

		if (lstat(ce->name, &st) < 0) {
			if (errno != ENOENT && errno != ENOTDIR) {
				perror(ce->name);
				continue;
			}
			if (silent)
				continue;
			show_file('-', ce);
			continue;
		}
		changed = ce_match_stat(ce, &st);
		if (!changed && !diff_options.find_copies_harder)
			continue;
		oldmode = ntohl(ce->ce_mode);

		newmode = DIFF_FILE_CANON_MODE(st.st_mode);
		if (!trust_executable_bit &&
		    S_ISREG(newmode) && S_ISREG(oldmode) &&
		    ((newmode ^ oldmode) == 0111))
			newmode = oldmode;
		show_modified(oldmode, newmode,
			      ce->sha1, (changed ? null_sha1 : ce->sha1),
			      ce->name);
	}
	diffcore_std(&diff_options);
	diff_flush(&diff_options);
	return 0;
}
