Esempio n. 1
0
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);
}
Esempio n. 2
0
static int compare_paths(const struct combine_diff_path *one,
			  const struct diff_filespec *two)
{
	if (!S_ISDIR(one->mode) && !S_ISDIR(two->mode))
		return strcmp(one->path, two->path);

	return base_name_compare(one->path, strlen(one->path), one->mode,
				 two->path, strlen(two->path), two->mode);
}
Esempio n. 3
0
static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const char *base, int baselen, struct diff_options *opt)
{
	unsigned mode1, mode2;
	const char *path1, *path2;
	const unsigned char *sha1, *sha2;
	int cmp, pathlen1, pathlen2;
	char *fullname;

	sha1 = tree_entry_extract(t1, &path1, &mode1);
	sha2 = tree_entry_extract(t2, &path2, &mode2);

	pathlen1 = tree_entry_len(path1, sha1);
	pathlen2 = tree_entry_len(path2, sha2);
	cmp = base_name_compare(path1, pathlen1, mode1, path2, pathlen2, mode2);
	if (cmp < 0) {
		show_entry(opt, "-", t1, base, baselen);
		return -1;
	}
	if (cmp > 0) {
		show_entry(opt, "+", t2, base, baselen);
		return 1;
	}
	if (!DIFF_OPT_TST(opt, FIND_COPIES_HARDER) && !hashcmp(sha1, sha2) && mode1 == mode2)
		return 0;

	/*
	 * If the filemode has changed to/from a directory from/to a regular
	 * file, we need to consider it a remove and an add.
	 */
	if (S_ISDIR(mode1) != S_ISDIR(mode2)) {
		show_entry(opt, "-", t1, base, baselen);
		show_entry(opt, "+", t2, base, baselen);
		return 0;
	}

	if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode1)) {
		int retval;
		char *newbase = malloc_base(base, baselen, path1, pathlen1);
		if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) {
			newbase[baselen + pathlen1] = 0;
			opt->change(opt, mode1, mode2,
				    sha1, sha2, newbase);
			newbase[baselen + pathlen1] = '/';
		}
		retval = diff_tree_sha1(sha1, sha2, newbase, opt);
		free(newbase);
		return retval;
	}

	fullname = malloc_fullname(base, baselen, path1, pathlen1);
	opt->change(opt, mode1, mode2, sha1, sha2, fullname);
	free(fullname);
	return 0;
}
Esempio n. 4
0
static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2,
			      struct strbuf *base, struct diff_options *opt)
{
	unsigned mode1, mode2;
	const char *path1, *path2;
	const unsigned char *sha1, *sha2;
	int cmp, pathlen1, pathlen2;
	int old_baselen = base->len;

	sha1 = tree_entry_extract(t1, &path1, &mode1);
	sha2 = tree_entry_extract(t2, &path2, &mode2);

	pathlen1 = tree_entry_len(path1, sha1);
	pathlen2 = tree_entry_len(path2, sha2);
	cmp = base_name_compare(path1, pathlen1, mode1, path2, pathlen2, mode2);
	if (cmp < 0) {
		show_entry(opt, "-", t1, base);
		return -1;
	}
	if (cmp > 0) {
		show_entry(opt, "+", t2, base);
		return 1;
	}
	if (!DIFF_OPT_TST(opt, FIND_COPIES_HARDER) && !hashcmp(sha1, sha2) && mode1 == mode2)
		return 0;

	/*
	 * If the filemode has changed to/from a directory from/to a regular
	 * file, we need to consider it a remove and an add.
	 */
	if (S_ISDIR(mode1) != S_ISDIR(mode2)) {
		show_entry(opt, "-", t1, base);
		show_entry(opt, "+", t2, base);
		return 0;
	}

	strbuf_add(base, path1, pathlen1);
	if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode1)) {
		if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) {
			opt->change(opt, mode1, mode2,
				    sha1, sha2, base->buf, 0, 0);
		}
		strbuf_addch(base, '/');
		diff_tree_sha1(sha1, sha2, base->buf, opt);
	} else {
		opt->change(opt, mode1, mode2, sha1, sha2, base->buf, 0, 0);
	}
	strbuf_setlen(base, old_baselen);
	return 0;
}
Esempio n. 5
0
static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt)
{
	unsigned mode1, mode2;
	const char *path1, *path2;
	const unsigned char *sha1, *sha2;
	int cmp, pathlen1, pathlen2;

	sha1 = extract(t1, &path1, &mode1);
	sha2 = extract(t2, &path2, &mode2);

	pathlen1 = strlen(path1);
	pathlen2 = strlen(path2);
	cmp = base_name_compare(path1, pathlen1, mode1, path2, pathlen2, mode2);
	if (cmp < 0) {
		show_entry(opt, "-", t1, base);
		return -1;
	}
	if (cmp > 0) {
		show_entry(opt, "+", t2, base);
		return 1;
	}
	if (!opt->find_copies_harder &&
	    !memcmp(sha1, sha2, 20) && mode1 == mode2)
		return 0;

	/*
	 * If the filemode has changed to/from a directory from/to a regular
	 * file, we need to consider it a remove and an add.
	 */
	if (S_ISDIR(mode1) != S_ISDIR(mode2)) {
		show_entry(opt, "-", t1, base);
		show_entry(opt, "+", t2, base);
		return 0;
	}

	if (opt->recursive && S_ISDIR(mode1)) {
		int retval;
		char *newbase = malloc_base(base, path1, pathlen1);
		if (opt->tree_in_recursive)
			opt->change(opt, mode1, mode2,
				    sha1, sha2, base, path1);
		retval = diff_tree_sha1(sha1, sha2, newbase, opt);
		free(newbase);
		return retval;
	}

	opt->change(opt, mode1, mode2, sha1, sha2, base, path1);
	return 0;
}
Esempio n. 6
0
/*
 * Compare two tree entries, taking into account only path/S_ISDIR(mode),
 * but not their sha1's.
 *
 * NOTE files and directories *always* compare differently, even when having
 *      the same name - thanks to base_name_compare().
 *
 * NOTE empty (=invalid) descriptor(s) take part in comparison as +infty,
 *      so that they sort *after* valid tree entries.
 *
 *      Due to this convention, if trees are scanned in sorted order, all
 *      non-empty descriptors will be processed first.
 */
static int tree_entry_pathcmp(struct tree_desc *t1, struct tree_desc *t2)
{
	struct name_entry *e1, *e2;
	int cmp;

	/* empty descriptors sort after valid tree entries */
	if (!t1->size)
		return t2->size ? 1 : 0;
	else if (!t2->size)
		return -1;

	e1 = &t1->entry;
	e2 = &t2->entry;
	cmp = base_name_compare(e1->path, tree_entry_len(e1), e1->mode,
				e2->path, tree_entry_len(e2), e2->mode);
	return cmp;
}
Esempio n. 7
0
static int base_name_entries_compare(const struct name_entry *a,
				     const struct name_entry *b)
{
	return base_name_compare(a->path, tree_entry_len(a), a->mode,
				 b->path, tree_entry_len(b), b->mode);
}
Esempio n. 8
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;
}