Commit Diff


commit - e87a53ff87b118b0f2144d7d2e111986d2380240
commit + fb95e70d03a91abd90acdff115ea7aa7ce29b9a4
blob - 927c10b5f2d5bd38831138167a2c77e989ca9afe
blob + dedfb8f826bb8de777445aaff9b19bc8a855d36e
--- include/got_reference.h
+++ include/got_reference.h
@@ -140,6 +140,11 @@ const struct got_error *
 got_reflist_insert(struct got_reflist_entry **newp, struct got_reflist_head *refs,
     struct got_reference *ref, got_ref_cmp_cb cmp_cb, void *cmp_arg);
 
+/* Sort a list of references with the provided comparison callback. */
+const struct got_error *
+got_reflist_sort(struct got_reflist_head *refs, got_ref_cmp_cb cmp_cb,
+    void *cmp_arg);
+
 /* Indicate whether the provided reference is symbolic (points at another
  * refernce) or not (points at an object ID). */
 int got_ref_is_symbolic(struct got_reference *);
blob - daf8aad1354470865d9b76172bd39ea13f3d397f
blob + ef49f6ae3027c24639570e51b560c120d68f78e6
--- lib/reference.c
+++ lib/reference.c
@@ -888,7 +888,32 @@ got_reflist_insert(struct got_reflist_entry **newp, st
 	TAILQ_INSERT_HEAD(refs, new, entry);
 	return NULL;
 }
+
+const struct got_error *
+got_reflist_sort(struct got_reflist_head *refs,
+    got_ref_cmp_cb cmp_cb, void *cmp_arg)
+{
+	const struct got_error *err = NULL;
+	struct got_reflist_entry *re, *tmp, *new;
+	struct got_reflist_head sorted;
 
+	TAILQ_INIT(&sorted);
+
+	TAILQ_FOREACH_SAFE(re, refs, entry, tmp) {
+		struct got_reference *ref = re->ref;
+		TAILQ_REMOVE(refs, re, entry);
+		free(re);
+		err = got_reflist_insert(&new, &sorted, ref, cmp_cb, cmp_arg);
+		if (err || new == NULL /* duplicate */)
+			got_ref_close(ref);
+		if (err)
+			return err;
+	}
+
+	TAILQ_CONCAT(refs, &sorted, entry);
+	return NULL;
+}
+
 static const struct got_error *
 gather_on_disk_refs(struct got_reflist_head *refs, const char *path_refs,
     const char *subdir, struct got_repository *repo,