get_short_sha1: refactor init of disambiguation code

The disambiguation machinery has two callers: get_short_sha1 and for_each_abbrev. Both need to repeat much of the same setup: declaring buffers, sanity-checking lengths, preparing the prefixes, etc. Let's pull that into a single init function so we can avoid repeating ourselves. Pulling the buffers into the "struct disambiguate_state" isn't strictly necessary, but it does make things simpler for the callers, who no longer have to worry about sizing them correctly (i.e., it's an implicit requirement that the caller provide 20- and 40-byte buffers). And while we're touching this code, we can convert any magic-number sizes to the more modern GIT_SHA1_* constants. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Sep 26, 2016 at 08:00 UTC 0016043bf46f4b85054c61f9000ccc58d0ef4ad7
1 file changed +35 -44
sha1_name.c
+35 -44
@@ -13,9 +13,13 @@ static int get_sha1_oneline(const char *, unsigned char *, struct commit_list *)
13 typedef int (*disambiguate_hint_fn)(const unsigned char *, void *);
14
15 struct disambiguate_state {
16 + int len; /* length of prefix in hex chars */
17 + char hex_pfx[GIT_SHA1_HEXSZ];
18 + unsigned char bin_pfx[GIT_SHA1_RAWSZ];
19 +
20 disambiguate_hint_fn fn;
21 void *cb_data;
18 - unsigned char candidate[20];
22 + unsigned char candidate[GIT_SHA1_RAWSZ];
23 unsigned candidate_exists:1;
24 unsigned candidate_checked:1;
25 unsigned candidate_ok:1;
@@ -72,10 +76,10 @@ static void update_candidates(struct disambiguate_state *ds, const unsigned char
76 /* otherwise, current can be discarded and candidate is still good */
77 }
78
75 -static void find_short_object_filename(int len, const char *hex_pfx, struct disambiguate_state *ds)
79 +static void find_short_object_filename(struct disambiguate_state *ds)
80 {
81 struct alternate_object_database *alt;
78 - char hex[40];
82 + char hex[GIT_SHA1_HEXSZ];
83 static struct alternate_object_database *fakeent;
84
85 if (!fakeent) {
@@ -95,7 +99,7 @@ static void find_short_object_filename(int len, const char *hex_pfx, struct disa
99 }
100 fakeent->next = alt_odb_list;
101
98 - xsnprintf(hex, sizeof(hex), "%.2s", hex_pfx);
102 + xsnprintf(hex, sizeof(hex), "%.2s", ds->hex_pfx);
103 for (alt = fakeent; alt && !ds->ambiguous; alt = alt->next) {
104 struct dirent *de;
105 DIR *dir;
@@ -103,7 +107,7 @@ static void find_short_object_filename(int len, const char *hex_pfx, struct disa
107 * every alt_odb struct has 42 extra bytes after the base
108 * for exactly this purpose
109 */
106 - xsnprintf(alt->name, 42, "%.2s/", hex_pfx);
110 + xsnprintf(alt->name, 42, "%.2s/", ds->hex_pfx);
111 dir = opendir(alt->base);
112 if (!dir)
113 continue;
@@ -113,7 +117,7 @@ static void find_short_object_filename(int len, const char *hex_pfx, struct disa
117
118 if (strlen(de->d_name) != 38)
119 continue;
116 - if (memcmp(de->d_name, hex_pfx + 2, len - 2))
120 + if (memcmp(de->d_name, ds->hex_pfx + 2, ds->len - 2))
121 continue;
122 memcpy(hex + 2, de->d_name, 38);
123 if (!get_sha1_hex(hex, sha1))
@@ -138,9 +142,7 @@ static int match_sha(unsigned len, const unsigned char *a, const unsigned char *
142 return 1;
143 }
144
141 -static void unique_in_pack(int len,
142 - const unsigned char *bin_pfx,
143 - struct packed_git *p,
145 +static void unique_in_pack(struct packed_git *p,
146 struct disambiguate_state *ds)
147 {
148 uint32_t num, last, i, first = 0;
@@ -155,7 +157,7 @@ static void unique_in_pack(int len,
157 int cmp;
158
159 current = nth_packed_object_sha1(p, mid);
158 - cmp = hashcmp(bin_pfx, current);
160 + cmp = hashcmp(ds->bin_pfx, current);
161 if (!cmp) {
162 first = mid;
163 break;
@@ -174,20 +176,19 @@ static void unique_in_pack(int len,
176 */
177 for (i = first; i < num && !ds->ambiguous; i++) {
178 current = nth_packed_object_sha1(p, i);
177 - if (!match_sha(len, bin_pfx, current))
179 + if (!match_sha(ds->len, ds->bin_pfx, current))
180 break;
181 update_candidates(ds, current);
182 }
183 }
184
183 -static void find_short_packed_object(int len, const unsigned char *bin_pfx,
184 - struct disambiguate_state *ds)
185 +static void find_short_packed_object(struct disambiguate_state *ds)
186 {
187 struct packed_git *p;
188
189 prepare_packed_git();
190 for (p = packed_git; p && !ds->ambiguous; p = p->next)
190 - unique_in_pack(len, bin_pfx, p, ds);
191 + unique_in_pack(p, ds);
192 }
193
194 #define SHORT_NAME_NOT_FOUND (-1)
@@ -281,14 +282,17 @@ static int disambiguate_blob_only(const unsigned char *sha1, void *cb_data_unuse
282 return kind == OBJ_BLOB;
283 }
284
284 -static int prepare_prefixes(const char *name, int len,
285 - unsigned char *bin_pfx,
286 - char *hex_pfx)
285 +static int init_object_disambiguation(const char *name, int len,
286 + struct disambiguate_state *ds)
287 {
288 int i;
289
290 - hashclr(bin_pfx);
291 - memset(hex_pfx, 'x', 40);
290 + if (len < MINIMUM_ABBREV || len > GIT_SHA1_HEXSZ)
291 + return -1;
292 +
293 + memset(ds, 0, sizeof(*ds));
294 + memset(ds->hex_pfx, 'x', GIT_SHA1_HEXSZ);
295 +
296 for (i = 0; i < len ;i++) {
297 unsigned char c = name[i];
298 unsigned char val;
@@ -302,11 +306,14 @@ static int prepare_prefixes(const char *name, int len,
306 }
307 else
308 return -1;
305 - hex_pfx[i] = c;
309 + ds->hex_pfx[i] = c;
310 if (!(i & 1))
311 val <<= 4;
308 - bin_pfx[i >> 1] |= val;
312 + ds->bin_pfx[i >> 1] |= val;
313 }
314 +
315 + ds->len = len;
316 + prepare_alt_odb();
317 return 0;
318 }
319
@@ -314,20 +321,12 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1,
321 unsigned flags)
322 {
323 int status;
317 - char hex_pfx[40];
318 - unsigned char bin_pfx[20];
324 struct disambiguate_state ds;
325 int quietly = !!(flags & GET_SHA1_QUIETLY);
326
322 - if (len < MINIMUM_ABBREV || len > 40)
323 - return -1;
324 - if (prepare_prefixes(name, len, bin_pfx, hex_pfx) < 0)
327 + if (init_object_disambiguation(name, len, &ds) < 0)
328 return -1;
329
327 - prepare_alt_odb();
328 -
329 - memset(&ds, 0, sizeof(ds));
330 -
330 if (HAS_MULTI_BITS(flags & GET_SHA1_DISAMBIGUATORS))
331 die("BUG: multiple get_short_sha1 disambiguator flags");
332
@@ -342,36 +341,28 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1,
341 else if (flags & GET_SHA1_BLOB)
342 ds.fn = disambiguate_blob_only;
343
345 - find_short_object_filename(len, hex_pfx, &ds);
346 - find_short_packed_object(len, bin_pfx, &ds);
344 + find_short_object_filename(&ds);
345 + find_short_packed_object(&ds);
346 status = finish_object_disambiguation(&ds, sha1);
347
348 if (!quietly && (status == SHORT_NAME_AMBIGUOUS))
350 - return error("short SHA1 %.*s is ambiguous.", len, hex_pfx);
349 + return error("short SHA1 %.*s is ambiguous.", ds.len, ds.hex_pfx);
350 return status;
351 }
352
353 int for_each_abbrev(const char *prefix, each_abbrev_fn fn, void *cb_data)
354 {
356 - char hex_pfx[40];
357 - unsigned char bin_pfx[20];
355 struct disambiguate_state ds;
359 - int len = strlen(prefix);
356
361 - if (len < MINIMUM_ABBREV || len > 40)
357 + if (init_object_disambiguation(prefix, strlen(prefix), &ds) < 0)
358 return -1;
363 - if (prepare_prefixes(prefix, len, bin_pfx, hex_pfx) < 0)
364 - return -1;
365 -
366 - prepare_alt_odb();
359
368 - memset(&ds, 0, sizeof(ds));
360 ds.always_call_fn = 1;
361 ds.cb_data = cb_data;
362 ds.fn = fn;
363
373 - find_short_object_filename(len, hex_pfx, &ds);
374 - find_short_packed_object(len, bin_pfx, &ds);
364 + find_short_object_filename(&ds);
365 + find_short_packed_object(&ds);
366 return ds.ambiguous;
367 }
368