/*
 * GIT - the stupid content tracker
 *
 * Copyright (c) Junio C Hamano, 2006
 */
#include "cache.h"
#include "strbuf.h"
#include "quote.h"
#include "tree.h"

static struct treeent {
	unsigned mode;
	unsigned char sha1[20];
	int len;
	char name[FLEX_ARRAY];
} **entries;
static int alloc, used;

static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
{
	struct treeent *ent;
	int len = strlen(path);
	if (strchr(path, '/'))
		die("path %s contains slash", path);

	if (alloc <= used) {
		alloc = alloc_nr(used);
		entries = xrealloc(entries, sizeof(*entries) * alloc);
	}
	ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1);
	ent->mode = mode;
	ent->len = len;
	memcpy(ent->sha1, sha1, 20);
	memcpy(ent->name, path, len+1);
}

static int ent_compare(const void *a_, const void *b_)
{
	struct treeent *a = *(struct treeent **)a_;
	struct treeent *b = *(struct treeent **)b_;
	return base_name_compare(a->name, a->len, a->mode,
				 b->name, b->len, b->mode);
}

static void write_tree(unsigned char *sha1)
{
	char *buffer;
	unsigned long size, offset;
	int i;

	qsort(entries, used, sizeof(*entries), ent_compare);
	size = 100;
	for (size = i = 0; i < used; i++)
		size += 32 + entries[i]->len;
	buffer = xmalloc(size);
	offset = 0;

	for (i = 0; i < used; i++) {
		struct treeent *ent = entries[i];

		if (offset + ent->len + 100 < size) {
			size = alloc_nr(offset + ent->len + 100);
			buffer = xrealloc(buffer, size);
		}
		offset += sprintf(buffer + offset, "%o ", ent->mode);
		offset += sprintf(buffer + offset, "%s", ent->name);
		buffer[offset++] = 0;
		memcpy(buffer + offset, ent->sha1, 20);
		offset += 20;
	}
	write_sha1_file(buffer, offset, tree_type, sha1);
}

static const char mktree_usage[] = "mktree [-z]";

int main(int ac, char **av)
{
	struct strbuf sb;
	unsigned char sha1[20];
	int line_termination = '\n';

	setup_git_directory();

	while ((1 < ac) && av[1][0] == '-') {
		char *arg = av[1];
		if (!strcmp("-z", arg))
			line_termination = 0;
		else
			usage(mktree_usage);
		ac--;
		av++;
	}

	strbuf_init(&sb);
	while (1) {
		int len;
		char *ptr, *ntr;
		unsigned mode;
		char type[20];
		char *path;

		read_line(&sb, stdin, line_termination);
		if (sb.eof)
			break;
		len = sb.len;
		ptr = sb.buf;
		/* Input is non-recursive ls-tree output format
		 * mode SP type SP sha1 TAB name
		 */
		mode = strtoul(ptr, &ntr, 8);
		if (ptr == ntr || !ntr || *ntr != ' ')
			die("input format error: %s", sb.buf);
		ptr = ntr + 1; /* type */
		ntr = strchr(ptr, ' ');
		if (!ntr || sb.buf + len <= ntr + 41 ||
		    ntr[41] != '\t' ||
		    get_sha1_hex(ntr + 1, sha1))
			die("input format error: %s", sb.buf);
		if (sha1_object_info(sha1, type, NULL))
			die("object %s unavailable", sha1_to_hex(sha1));
		*ntr++ = 0; /* now at the beginning of SHA1 */
		if (strcmp(ptr, type))
			die("object type %s mismatch (%s)", ptr, type);
		ntr += 41; /* at the beginning of name */
		if (line_termination && ntr[0] == '"')
			path = unquote_c_style(ntr, NULL);
		else
			path = ntr;

		append_to_tree(mode, sha1, path);

		if (path != ntr)
			free(path);
	}
	write_tree(sha1);
	puts(sha1_to_hex(sha1));
	exit(0);
}
