Commit Diff


commit - 4c4ce67b628a0b29afb50487072e667ee37e1dad
commit + 7b5b670e542e9a69edcd9c3d76ce9ab4a3855c6f
blob - 5f2594f5af806ea9b99c358f35fa4e7ce16f7efb
blob + 8a7ddd1fed280c5ace7be5e759d1b7ef2c6cc784
--- include/got_reference.h
+++ include/got_reference.h
@@ -139,3 +139,28 @@ const struct got_error *got_ref_delete(struct got_refe
 
 /* Unlock a reference which was opened in locked state. */
 const struct got_error *got_ref_unlock(struct got_reference *);
+
+/* Map object IDs to references. */
+struct got_reflist_object_id_map;
+
+/*
+ * Create and populate an object ID map for a given list of references.
+ * Map entries will contain deep-copies of elements of the reflist.
+ * The caller must dispose of the map with got_reflist_object_map_free().
+ */
+const struct got_error *got_reflist_object_id_map_create(
+    struct got_reflist_object_id_map **, struct got_reflist_head *, 
+    struct got_repository *);
+
+/*
+ * Return a list of references which correspond to a given object ID.
+ * The returned list must be considered read-only.
+ * The caller must _not_ call free(3) on the returned pointer!
+ * If no references are associated with the ID, return NULL.
+ */
+struct got_reflist_head *
+got_reflist_object_id_map_lookup(struct got_reflist_object_id_map *,
+    struct got_object_id *);
+
+/* Free the specified object ID map. */
+void got_reflist_object_map_free(struct got_reflist_object_id_map *);
blob - 7df07c953f7657dda28101ec2213bf5c222db220
blob + d9f1596591be3332b0a51e1ec4e6c77a90720fae
--- lib/reference.c
+++ lib/reference.c
@@ -43,6 +43,7 @@
 #include "got_lib_delta.h"
 #include "got_lib_inflate.h"
 #include "got_lib_object.h"
+#include "got_lib_object_idset.h"
 #include "got_lib_lockfile.h"
 
 #ifndef nitems
@@ -1400,3 +1401,97 @@ got_ref_unlock(struct got_reference *ref)
 	ref->lf = NULL;
 	return err;
 }
+
+struct got_reflist_object_id_map {
+	struct got_object_idset *idset;
+};
+
+struct got_reflist_object_id_map_entry {
+	struct got_reflist_head refs;
+};
+
+const struct got_error *
+got_reflist_object_id_map_create(struct got_reflist_object_id_map **map,
+    struct got_reflist_head *refs, struct got_repository *repo)
+{
+	const struct got_error *err = NULL;
+	struct got_object_idset *idset;
+	struct got_object_id *id = NULL;
+	struct got_reflist_entry *re;
+
+	idset = got_object_idset_alloc();
+	if (idset == NULL)
+		return got_error_from_errno("got_object_idset_alloc");
+
+	*map = malloc(sizeof(**map));
+	if (*map == NULL) {
+		got_object_idset_free(idset);
+		return got_error_from_errno("malloc");
+	}
+	(*map)->idset = idset;
+
+	SIMPLEQ_FOREACH(re, refs, entry) {
+		struct got_reflist_entry *new;
+		struct got_reflist_object_id_map_entry *ent;
+
+		err = got_ref_resolve(&id, repo, re->ref);
+		if (err)
+			goto done;
+
+		ent = got_object_idset_get(idset, id);
+		if (ent == NULL) {
+			ent = malloc(sizeof(*ent));
+			if (ent == NULL) {
+				err = got_error_from_errno("malloc");
+				goto done;
+			}
+			SIMPLEQ_INIT(&ent->refs);
+			err = got_object_idset_add(idset, id, ent);
+			if (err)
+				goto done;
+		}
+
+		err = got_reflist_entry_dup(&new, re);
+		if (err)
+			goto done;
+		SIMPLEQ_INSERT_TAIL(&ent->refs, new, entry);
+		free(id);
+		id = NULL;
+	}
+done:
+	free(id);
+	if (err) {
+		got_reflist_object_map_free(*map);
+		*map = NULL;
+	}
+	return NULL;
+}
+
+struct got_reflist_head *
+got_reflist_object_id_map_lookup(struct got_reflist_object_id_map *map,
+    struct got_object_id *id)
+{
+	struct got_reflist_object_id_map_entry *ent;
+	ent = got_object_idset_get(map->idset, id);
+	if (ent)
+		return &ent->refs;
+	return NULL;
+}
+
+static const struct got_error *
+free_id_map_entry(struct got_object_id *id, void *data, void *arg)
+{
+	struct got_reflist_object_id_map_entry *ent = data;
+
+	got_ref_list_free(&ent->refs);
+	free(ent);
+	return NULL;
+}
+
+void
+got_reflist_object_map_free(struct got_reflist_object_id_map *map)
+{
+	got_object_idset_for_each(map->idset, free_id_map_entry, NULL);
+	got_object_idset_free(map->idset);
+	free(map);
+}