merge-recursive: add pointer about unduly complex looking code
[gitweb.git] / refs / iterator.c
index c475360f0a8c6bc5aa26876f8fd8d2ca5ebc3ebd..2ac91ac3401c87108b9cdb4983acb7c165df82d9 100644 (file)
@@ -54,7 +54,7 @@ static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator)
 static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator,
                                   struct object_id *peeled)
 {
-       die("BUG: peel called for empty iterator");
+       BUG("peel called for empty iterator");
 }
 
 static int empty_ref_iterator_abort(struct ref_iterator *ref_iterator)
@@ -177,7 +177,7 @@ static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator,
                (struct merge_ref_iterator *)ref_iterator;
 
        if (!iter->current) {
-               die("BUG: peel called before advance for merge iterator");
+               BUG("peel called before advance for merge iterator");
        }
        return ref_iterator_peel(*iter->current, peeled);
 }
@@ -287,6 +287,20 @@ struct prefix_ref_iterator {
        int trim;
 };
 
+/* Return -1, 0, 1 if refname is before, inside, or after the prefix. */
+static int compare_prefix(const char *refname, const char *prefix)
+{
+       while (*prefix) {
+               if (*refname != *prefix)
+                       return ((unsigned char)*refname < (unsigned char)*prefix) ? -1 : +1;
+
+               refname++;
+               prefix++;
+       }
+
+       return 0;
+}
+
 static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
 {
        struct prefix_ref_iterator *iter =
@@ -294,9 +308,25 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
        int ok;
 
        while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
-               if (!starts_with(iter->iter0->refname, iter->prefix))
+               int cmp = compare_prefix(iter->iter0->refname, iter->prefix);
+
+               if (cmp < 0)
                        continue;
 
+               if (cmp > 0) {
+                       /*
+                        * If the source iterator is ordered, then we
+                        * can stop the iteration as soon as we see a
+                        * refname that comes after the prefix:
+                        */
+                       if (iter->iter0->ordered) {
+                               ok = ref_iterator_abort(iter->iter0);
+                               break;
+                       } else {
+                               continue;
+                       }
+               }
+
                if (iter->trim) {
                        /*
                         * It is nonsense to trim off characters that
@@ -308,7 +338,7 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
                         * trimming, report it as a bug:
                         */
                        if (strlen(iter->iter0->refname) <= iter->trim)
-                               die("BUG: attempt to trim too many characters");
+                               BUG("attempt to trim too many characters");
                        iter->base.refname = iter->iter0->refname + iter->trim;
                } else {
                        iter->base.refname = iter->iter0->refname;