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
}