return res;
}
+static int debug_ref_iterator_seek(struct ref_iterator *ref_iterator,
+ const char *prefix)
+{
+ struct debug_ref_iterator *diter =
+ (struct debug_ref_iterator *)ref_iterator;
+ int res = diter->iter->vtable->seek(diter->iter, prefix);
+ trace_printf_key(&trace_refs, "iterator_seek: %s: %d\n", prefix ? prefix : "", res);
+ return res;
+}
+
static int debug_ref_iterator_peel(struct ref_iterator *ref_iterator,
struct object_id *peeled)
{
static struct ref_iterator_vtable debug_ref_iterator_vtable = {
.advance = debug_ref_iterator_advance,
+ .seek = debug_ref_iterator_seek,
.peel = debug_ref_iterator_peel,
.release = debug_ref_iterator_release,
};
return ref_iterator->vtable->advance(ref_iterator);
}
+int ref_iterator_seek(struct ref_iterator *ref_iterator,
+ const char *prefix)
+{
+ return ref_iterator->vtable->seek(ref_iterator, prefix);
+}
+
int ref_iterator_peel(struct ref_iterator *ref_iterator,
struct object_id *peeled)
{
return ITER_DONE;
}
+static int empty_ref_iterator_seek(struct ref_iterator *ref_iterator UNUSED,
+ const char *prefix UNUSED)
+{
+ return 0;
+}
+
static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
struct object_id *peeled UNUSED)
{
static struct ref_iterator_vtable empty_ref_iterator_vtable = {
.advance = empty_ref_iterator_advance,
+ .seek = empty_ref_iterator_seek,
.peel = empty_ref_iterator_peel,
.release = empty_ref_iterator_release,
};
return ok;
}
+static int prefix_ref_iterator_seek(struct ref_iterator *ref_iterator,
+ const char *prefix)
+{
+ struct prefix_ref_iterator *iter =
+ (struct prefix_ref_iterator *)ref_iterator;
+ free(iter->prefix);
+ iter->prefix = xstrdup_or_null(prefix);
+ return ref_iterator_seek(iter->iter0, prefix);
+}
+
static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator,
struct object_id *peeled)
{
static struct ref_iterator_vtable prefix_ref_iterator_vtable = {
.advance = prefix_ref_iterator_advance,
+ .seek = prefix_ref_iterator_seek,
.peel = prefix_ref_iterator_peel,
.release = prefix_ref_iterator_release,
};
*/
int ref_iterator_advance(struct ref_iterator *ref_iterator);
+/*
+ * Seek the iterator to the first reference with the given prefix.
+ * The prefix is matched as a literal string, without regard for path
+ * separators. If prefix is NULL or the empty string, seek the iterator to the
+ * first reference again.
+ *
+ * This function is expected to behave as if a new ref iterator with the same
+ * prefix had been created, but allows reuse of iterators and thus may allow
+ * the backend to optimize. Parameters other than the prefix that have been
+ * passed when creating the iterator will remain unchanged.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+int ref_iterator_seek(struct ref_iterator *ref_iterator,
+ const char *prefix);
+
/*
* If possible, peel the reference currently being viewed by the
* iterator. Return 0 on success.
*/
typedef int ref_iterator_advance_fn(struct ref_iterator *ref_iterator);
+/*
+ * Seek the iterator to the first reference matching the given prefix. Should
+ * behave the same as if a new iterator was created with the same prefix.
+ */
+typedef int ref_iterator_seek_fn(struct ref_iterator *ref_iterator,
+ const char *prefix);
+
/*
* Peels the current ref, returning 0 for success or -1 for failure.
*/
struct ref_iterator_vtable {
ref_iterator_advance_fn *advance;
+ ref_iterator_seek_fn *seek;
ref_iterator_peel_fn *peel;
ref_iterator_release_fn *release;
};