Commit d8febde3 authored by René Scharfe's avatar René Scharfe Committed by Junio C Hamano

match-trees: simplify score_trees() using tree_entry()

Convert the loop in score_trees() to tree_entry().  The code becomes
shorter and simpler because the calls to update_tree_entry() are not
needed any more.

Another benefit is that we need less variables to track the current
tree entries; as a side-effect of that the compiler has an easier
job figuring out the control flow and thus can avoid false warnings
about uninitialized variables.

Using struct name_entry also allows the use of tree_entry_len() for
finding the path length instead of strlen(), which may be slightly
more efficient.

Also unify the handling of missing entries in one of the two trees
(i.e. added or removed files): Just set cmp appropriately first, no
matter if we ran off the end of a tree or if we actually have two
entries to compare, and check its value a bit later without
duplicating the handler code.
Signed-off-by: default avatarRene Scharfe <[email protected]>
Signed-off-by: default avatarJunio C Hamano <[email protected]>
parent 83715497
......@@ -47,6 +47,13 @@ static int score_matches(unsigned mode1, unsigned mode2, const char *path)
return score;
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);
* Inspect two trees, and give a score that tells how similar they are.
......@@ -71,54 +78,35 @@ static int score_trees(const unsigned char *hash1, const unsigned char *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;
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 (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);
if (!two.size) {
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 */
score += score_missing(mode1, path1);
cmp = base_name_compare(path1, strlen(path1), mode1,
path2, strlen(path2), mode2);
if (cmp < 0) {
cmp = -1;
else if (got_entry_from_two)
/* two has more entries */
cmp = 1;
if (cmp < 0)
/* path1 does not appear in two */
score += score_missing(mode1, path1);
else if (cmp > 0) {
score += score_missing(e1.mode, e1.path);
else if (cmp > 0)
/* path2 does not appear in one */
score += score_missing(mode2, path2);
else if (hashcmp(elem1, elem2))
score += score_missing(e2.mode, e2.path);
else if (hashcmp(e1.sha1, e2.sha1))
/* they are different */
score += score_differs(mode1, mode2, path1);
score += score_differs(e1.mode, e2.mode, e1.path);
/* same subtree or blob */
score += score_matches(mode1, mode2, path1);
score += score_matches(e1.mode, e2.mode, e1.path);
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment