sha1_name.c: refactor find_short_packed_object()
authorJunio C Hamano <gitster@pobox.com>
Mon, 18 Jun 2012 20:10:38 +0000 (13:10 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 3 Jul 2012 17:24:15 +0000 (10:24 -0700)
Extract the logic to find object(s) that match a given prefix inside
a single pack into a separate helper function, and give it a bit more
comment.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
sha1_name.c

index c5c4591f98989e48b13f2625a9f09f09e546a2f8..7bef45fcea14c6c14e723788c125509c494e0ec1 100644 (file)
@@ -78,6 +78,59 @@ static int match_sha(unsigned len, const unsigned char *a, const unsigned char *
        return 1;
 }
 
+static int unique_in_pack(int len,
+                         const unsigned char *match,
+                         struct packed_git *p,
+                         const unsigned char **found_sha1,
+                         int seen_so_far)
+{
+       uint32_t num, last, i, first = 0;
+       const unsigned char *current = NULL;
+
+       open_pack_index(p);
+       num = p->num_objects;
+       last = num;
+       while (first < last) {
+               uint32_t mid = (first + last) / 2;
+               const unsigned char *current;
+               int cmp;
+
+               current = nth_packed_object_sha1(p, mid);
+               cmp = hashcmp(match, current);
+               if (!cmp) {
+                       first = mid;
+                       break;
+               }
+               if (cmp > 0) {
+                       first = mid+1;
+                       continue;
+               }
+               last = mid;
+       }
+
+       /*
+        * At this point, "first" is the location of the lowest object
+        * with an object name that could match "match".  See if we have
+        * 0, 1 or more objects that actually match(es).
+        */
+       for (i = first; i < num; i++) {
+               current = nth_packed_object_sha1(p, first);
+               if (!match_sha(len, match, current))
+                       break;
+
+               /* current matches */
+               if (!seen_so_far) {
+                       *found_sha1 = current;
+                       seen_so_far++;
+               } else if (seen_so_far) {
+                       /* is it the same as the one previously found elsewhere? */
+                       if (hashcmp(*found_sha1, current))
+                               return 2; /* definitely not unique */
+               }
+       }
+       return seen_so_far;
+}
+
 static int find_short_packed_object(int len, const unsigned char *match, unsigned char *sha1)
 {
        struct packed_git *p;
@@ -85,53 +138,9 @@ static int find_short_packed_object(int len, const unsigned char *match, unsigne
        int found = 0;
 
        prepare_packed_git();
-       for (p = packed_git; p && found < 2; p = p->next) {
-               uint32_t num, last;
-               uint32_t first = 0;
-               open_pack_index(p);
-               num = p->num_objects;
-               last = num;
-               while (first < last) {
-                       uint32_t mid = (first + last) / 2;
-                       const unsigned char *current;
-                       int cmp;
-
-                       current = nth_packed_object_sha1(p, mid);
-                       cmp = hashcmp(match, current);
-                       if (!cmp) {
-                               first = mid;
-                               break;
-                       }
-                       if (cmp > 0) {
-                               first = mid+1;
-                               continue;
-                       }
-                       last = mid;
-               }
-               if (first < num) {
-                       const unsigned char *current, *next;
-                       current = nth_packed_object_sha1(p, first);
-                       if (match_sha(len, match, current)) {
-                               next = nth_packed_object_sha1(p, first+1);
-                               if (!next|| !match_sha(len, match, next)) {
-                                       /* unique within this pack */
-                                       if (!found) {
-                                               found_sha1 = current;
-                                               found++;
-                                       }
-                                       else if (hashcmp(found_sha1, current)) {
-                                               found = 2;
-                                               break;
-                                       }
-                               }
-                               else {
-                                       /* not even unique within this pack */
-                                       found = 2;
-                                       break;
-                               }
-                       }
-               }
-       }
+       for (p = packed_git; p && found < 2; p = p->next)
+               found = unique_in_pack(len, match, p, &found_sha1, found);
+
        if (found == 1)
                hashcpy(sha1, found_sha1);
        return found;