t7006: add tests for how git tag paginates
[gitweb.git] / refs / iterator.c
index 93ba472f9148938c99bc0de7ac1bb2ec163a5bda..4cf449ef660e2bc9ee5b6ddb4efd8662d27e12b3 100644 (file)
@@ -292,7 +292,23 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
                if (!starts_with(iter->iter0->refname, iter->prefix))
                        continue;
 
-               iter->base.refname = iter->iter0->refname + iter->trim;
+               if (iter->trim) {
+                       /*
+                        * It is nonsense to trim off characters that
+                        * you haven't already checked for via a
+                        * prefix check, whether via this
+                        * `prefix_ref_iterator` or upstream in
+                        * `iter0`). So if there wouldn't be at least
+                        * one character left in the refname after
+                        * trimming, report it as a bug:
+                        */
+                       if (strlen(iter->iter0->refname) <= iter->trim)
+                               die("BUG: attempt to trim too many characters");
+                       iter->base.refname = iter->iter0->refname + iter->trim;
+               } else {
+                       iter->base.refname = iter->iter0->refname;
+               }
+
                iter->base.oid = iter->iter0->oid;
                iter->base.flags = iter->iter0->flags;
                return ITER_OK;
@@ -353,3 +369,32 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
 
        return ref_iterator;
 }
+
+struct ref_iterator *current_ref_iter = NULL;
+
+int do_for_each_ref_iterator(struct ref_iterator *iter,
+                            each_ref_fn fn, void *cb_data)
+{
+       int retval = 0, ok;
+       struct ref_iterator *old_ref_iter = current_ref_iter;
+
+       current_ref_iter = iter;
+       while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
+               retval = fn(iter->refname, iter->oid, iter->flags, cb_data);
+               if (retval) {
+                       /*
+                        * If ref_iterator_abort() returns ITER_ERROR,
+                        * we ignore that error in deference to the
+                        * callback function's return value.
+                        */
+                       ref_iterator_abort(iter);
+                       goto out;
+               }
+       }
+
+out:
+       current_ref_iter = old_ref_iter;
+       if (ok == ITER_ERROR)
+               return -1;
+       return retval;
+}