aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--refs/debug.c11
-rw-r--r--refs/iterator.c24
-rw-r--r--refs/refs-internal.h24
3 files changed, 59 insertions, 0 deletions
diff --git a/refs/debug.c b/refs/debug.c
index a9786da4ba..5390fa9c18 100644
--- a/refs/debug.c
+++ b/refs/debug.c
@@ -169,6 +169,16 @@ static int debug_ref_iterator_advance(struct ref_iterator *ref_iterator)
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)
{
@@ -189,6 +199,7 @@ static void debug_ref_iterator_release(struct ref_iterator *ref_iterator)
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,
};
diff --git a/refs/iterator.c b/refs/iterator.c
index d61474cba7..ea4db59481 100644
--- a/refs/iterator.c
+++ b/refs/iterator.c
@@ -15,6 +15,12 @@ int ref_iterator_advance(struct ref_iterator *ref_iterator)
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)
{
@@ -50,6 +56,12 @@ static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator UNUSED)
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)
{
@@ -62,6 +74,7 @@ static void empty_ref_iterator_release(struct ref_iterator *ref_iterator 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,
};
@@ -373,6 +386,16 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
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)
{
@@ -392,6 +415,7 @@ static void prefix_ref_iterator_release(struct ref_iterator *ref_iterator)
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,
};
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 7d3bab654b..e5862757a7 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -328,6 +328,22 @@ struct ref_iterator {
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.
*/
@@ -446,6 +462,13 @@ void base_ref_iterator_init(struct ref_iterator *iter,
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.
*/
typedef int ref_iterator_peel_fn(struct ref_iterator *ref_iterator,
@@ -459,6 +482,7 @@ typedef void ref_iterator_release_fn(struct ref_iterator *ref_iterator);
struct ref_iterator_vtable {
ref_iterator_advance_fn *advance;
+ ref_iterator_seek_fn *seek;
ref_iterator_peel_fn *peel;
ref_iterator_release_fn *release;
};