Skip to content
Browse files

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: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information...
1 parent 8371549 commit d8febde370aa464a5208cf094f306343e4ecb6dc René Scharfe committed with gitster Mar 24, 2013
Showing with 28 additions and 40 deletions.
  1. +28 −40 match-trees.c
View
68 match-trees.c
@@ -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);
- update_tree_entry(&two);
- continue;
- }
- 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);
- update_tree_entry(&one);
- continue;
- }
- 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;
+ else
+ break;
+
+ if (cmp < 0)
/* path1 does not appear in two */
- score += score_missing(mode1, path1);
- update_tree_entry(&one);
- continue;
- }
- 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);
- update_tree_entry(&two);
- continue;
- }
- 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);
else
/* same subtree or blob */
- score += score_matches(mode1, mode2, path1);
- update_tree_entry(&one);
- update_tree_entry(&two);
+ score += score_matches(e1.mode, e2.mode, e1.path);
}
free(one_buf);
free(two_buf);

0 comments on commit d8febde

Please sign in to comment.
Something went wrong with that request. Please try again.