summaryrefslogtreecommitdiff
path: root/sha1_name.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2012-06-18 13:10:38 -0700
committerJunio C Hamano <gitster@pobox.com>2012-07-03 10:24:15 -0700
commitf703e6ea5e3bc7ff39b3ef6d3a21208fb63dfabd (patch)
treed7ce56142a3637d5d300e3704a4ce0d7bba1e999 /sha1_name.c
parent1b27c2f01af398706acf554794644daaf6bc8835 (diff)
downloadgit-f703e6ea5e3bc7ff39b3ef6d3a21208fb63dfabd.tar.gz
sha1_name.c: refactor find_short_packed_object()
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>
Diffstat (limited to 'sha1_name.c')
-rw-r--r--sha1_name.c103
1 files changed, 56 insertions, 47 deletions
diff --git a/sha1_name.c b/sha1_name.c
index c5c4591f98..7bef45fcea 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -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;