Example #1
0
/*
 * Inspect two trees, and give a score that tells how similar they are.
 */
static int score_trees(const unsigned char *hash1, const unsigned char *hash2)
{
	struct tree_desc one;
	struct tree_desc two;
	void *one_buf = fill_tree_desc_strict(&one, hash1);
	void *two_buf = fill_tree_desc_strict(&two, hash2);
	int score = 0;

	for (;;) {
		struct name_entry e1, e2;
		int got_entry_from_one = tree_entry(&one, &e1);
		int got_entry_from_two = tree_entry(&two, &e2);
		int cmp;

		if (got_entry_from_one && got_entry_from_two)
			cmp = base_name_entries_compare(&e1, &e2);
		else if (got_entry_from_one)
			/* two lacks this entry */
			cmp = -1;
		else if (got_entry_from_two)
			/* two has more entries */
			cmp = 1;
		else
			break;

		if (cmp < 0)
			/* path1 does not appear in two */
			score += score_missing(e1.mode, e1.path);
		else if (cmp > 0)
			/* path2 does not appear in one */
			score += score_missing(e2.mode, e2.path);
		else if (hashcmp(e1.sha1, e2.sha1))
			/* they are different */
			score += score_differs(e1.mode, e2.mode, e1.path);
		else
			/* same subtree or blob */
			score += score_matches(e1.mode, e2.mode, e1.path);
	}
	free(one_buf);
	free(two_buf);
	return score;
}
Example #2
0
/*
 * Inspect two trees, and give a score that tells how similar they are.
 */
static int score_trees(const unsigned char *hash1, const unsigned char *hash2)
{
	struct tree_desc one;
	struct tree_desc two;
	void *one_buf, *two_buf;
	int score = 0;
	enum object_type type;
	unsigned long size;

	one_buf = read_sha1_file(hash1, &type, &size);
	if (!one_buf)
		die("unable to read tree (%s)", sha1_to_hex(hash1));
	if (type != OBJ_TREE)
		die("%s is not a tree", sha1_to_hex(hash1));
	init_tree_desc(&one, one_buf, size);
	two_buf = read_sha1_file(hash2, &type, &size);
	if (!two_buf)
		die("unable to read tree (%s)", sha1_to_hex(hash2));
	if (type != OBJ_TREE)
		die("%s is not a tree", sha1_to_hex(hash2));
	init_tree_desc(&two, two_buf, size);
	while (one.size | two.size) {
		const unsigned char *elem1 = elem1;
		const unsigned char *elem2 = elem2;
		const char *path1 = path1;
		const char *path2 = path2;
		unsigned mode1 = mode1;
		unsigned mode2 = mode2;
		int cmp;

		if (one.size)
			elem1 = tree_entry_extract(&one, &path1, &mode1);
		if (two.size)
			elem2 = tree_entry_extract(&two, &path2, &mode2);

		if (!one.size) {
			/* two has more entries */
			score += score_missing(mode2, path2);
			update_tree_entry(&two);
			continue;
		}
		if (!two.size) {
			/* two lacks this entry */
			score += score_missing(mode1, path1);
			update_tree_entry(&one);
			continue;
		}
		cmp = base_name_compare(path1, strlen(path1), mode1,
					path2, strlen(path2), mode2);
		if (cmp < 0) {
			/* path1 does not appear in two */
			score += score_missing(mode1, path1);
			update_tree_entry(&one);
			continue;
		}
		else if (cmp > 0) {
			/* path2 does not appear in one */
			score += score_missing(mode2, path2);
			update_tree_entry(&two);
			continue;
		}
		else if (hashcmp(elem1, elem2))
			/* they are different */
			score += score_differs(mode1, mode2, path1);
		else
			/* same subtree or blob */
			score += score_matches(mode1, mode2, path1);
		update_tree_entry(&one);
		update_tree_entry(&two);
	}
	free(one_buf);
	free(two_buf);
	return score;
}