names_conflict(): simplify implementation

Save a bunch of lines of code and a couple of strlen() calls. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Apr 10, 2012 at 07:30 UTC 5a4d4947318d638f39a47be253d83460a10e65ef
1 file changed +37 -25
refs.c
+37 -25
@@ -342,41 +342,53 @@ static int do_for_each_ref_in_arrays(struct ref_array *array1,
342 */
343 static int names_conflict(const char *refname1, const char *refname2)
344 {
345 - int len1 = strlen(refname1);
346 - int len2 = strlen(refname2);
347 - int cmplen;
348 - const char *lead;
349 -
350 - if (len1 < len2) {
351 - cmplen = len1;
352 - lead = refname2;
353 - } else {
354 - cmplen = len2;
355 - lead = refname1;
345 + for (; *refname1 && *refname1 == *refname2; refname1++, refname2++)
346 + ;
347 + return (*refname1 == '\0' && *refname2 == '/')
348 + || (*refname1 == '/' && *refname2 == '\0');
349 +}
350 +
351 +struct name_conflict_cb {
352 + const char *refname;
353 + const char *oldrefname;
354 + const char *conflicting_refname;
355 +};
356 +
357 +static int name_conflict_fn(const char *existingrefname, const unsigned char *sha1,
358 + int flags, void *cb_data)
359 +{
360 + struct name_conflict_cb *data = (struct name_conflict_cb *)cb_data;
361 + if (data->oldrefname && !strcmp(data->oldrefname, existingrefname))
362 + return 0;
363 + if (names_conflict(data->refname, existingrefname)) {
364 + data->conflicting_refname = existingrefname;
365 + return 1;
366 }
357 - return !strncmp(refname1, refname2, cmplen) && lead[cmplen] == '/';
367 + return 0;
368 }
369
370 /*
371 * Return true iff a reference named refname could be created without
362 - * conflicting with the name of an existing reference. If oldrefname
363 - * is non-NULL, ignore potential conflicts with oldrefname (e.g.,
364 - * because oldrefname is scheduled for deletion in the same
372 + * conflicting with the name of an existing reference in array. If
373 + * oldrefname is non-NULL, ignore potential conflicts with oldrefname
374 + * (e.g., because oldrefname is scheduled for deletion in the same
375 * operation).
376 */
377 static int is_refname_available(const char *refname, const char *oldrefname,
378 struct ref_array *array)
379 {
370 - int i;
371 - for (i = 0; i < array->nr; i++) {
372 - struct ref_entry *entry = array->refs[i];
373 - if (oldrefname && !strcmp(oldrefname, entry->name))
374 - continue;
375 - if (names_conflict(refname, entry->name)) {
376 - error("'%s' exists; cannot create '%s'",
377 - entry->name, refname);
378 - return 0;
379 - }
380 + struct name_conflict_cb data;
381 + data.refname = refname;
382 + data.oldrefname = oldrefname;
383 + data.conflicting_refname = NULL;
384 +
385 + sort_ref_array(array);
386 + if (do_for_each_ref_in_array(array, 0, "", name_conflict_fn,
387 + 0, DO_FOR_EACH_INCLUDE_BROKEN,
388 + &data)) {
389 + error("'%s' exists; cannot create '%s'",
390 + data.conflicting_refname, refname);
391 + return 0;
392 }
393 return 1;
394 }