Commit 29606af7a3a58767bf817a38035490899609d13e

Stefan Sperling 2019-08-23T18:42:27

allow got_ref_list() to restrict returned refs to a particular namespace

diff --git a/got/got.c b/got/got.c
index d39a982..6148cc9 100644
--- a/got/got.c
+++ b/got/got.c
@@ -1763,7 +1763,7 @@ cmd_log(int argc, char *argv[])
 		path = in_repo_path;
 	}
 
-	error = got_ref_list(&refs, repo);
+	error = got_ref_list(&refs, repo, NULL);
 	if (error)
 		goto done;
 
@@ -2825,7 +2825,7 @@ list_refs(struct got_repository *repo)
 	struct got_reflist_entry *re;
 
 	SIMPLEQ_INIT(&refs);
-	err = got_ref_list(&refs, repo);
+	err = got_ref_list(&refs, repo, NULL);
 	if (err)
 		return err;
 
@@ -3065,7 +3065,7 @@ list_branches(struct got_repository *repo, struct got_worktree *worktree)
 
 	SIMPLEQ_INIT(&refs);
 
-	err = got_ref_list(&refs, repo);
+	err = got_ref_list(&refs, repo, "refs/heads");
 	if (err)
 		return err;
 
@@ -3073,8 +3073,6 @@ list_branches(struct got_repository *repo, struct got_worktree *worktree)
 		const char *refname, *marker = "  ";
 		char *refstr;
 		refname = got_ref_get_name(re->ref);
-		if (strncmp(refname, "refs/heads/", 11) != 0)
-			continue;
 		if (worktree && strcmp(refname,
 		    got_worktree_get_head_ref_name(worktree)) == 0) {
 			struct got_object_id *id = NULL;
@@ -3088,7 +3086,7 @@ list_branches(struct got_repository *repo, struct got_worktree *worktree)
 				marker = "~ ";
 			free(id);
 		}
-		refname += 11;
+		refname += strlen("refs/heads/");
 		refstr = got_ref_to_str(re->ref);
 		if (refstr == NULL)
 			return got_error_from_errno("got_ref_to_str");
@@ -3315,7 +3313,7 @@ list_tags(struct got_repository *repo, struct got_worktree *worktree)
 
 	SIMPLEQ_INIT(&refs);
 
-	err = got_ref_list(&refs, repo);
+	err = got_ref_list(&refs, repo, "refs/tags");
 	if (err)
 		return err;
 
diff --git a/include/got_reference.h b/include/got_reference.h
index 15b4fba..67fa4cc 100644
--- a/include/got_reference.h
+++ b/include/got_reference.h
@@ -83,9 +83,13 @@ struct got_reflist_entry {
 };
 SIMPLEQ_HEAD(got_reflist_head, got_reflist_entry);
 
-/* Append all known references to a caller-provided ref list head. */
+/*
+ * Append all known references to a caller-provided ref list head.
+ * Optionally limit references returned to those within a given
+ * reference namespace.
+ */
 const struct got_error *got_ref_list(struct got_reflist_head *,
-    struct got_repository *);
+    struct got_repository *, const char *);
 
 /* Free all references on a ref list. */
 void got_ref_list_free(struct got_reflist_head *);
diff --git a/lib/reference.c b/lib/reference.c
index eb58d3c..27bcf86 100644
--- a/lib/reference.c
+++ b/lib/reference.c
@@ -742,7 +742,8 @@ done:
 }
 
 const struct got_error *
-got_ref_list(struct got_reflist_head *refs, struct got_repository *repo)
+got_ref_list(struct got_reflist_head *refs, struct got_repository *repo,
+    const char *ref_namespace)
 {
 	const struct got_error *err;
 	char *packed_refs_path, *path_refs = NULL;
@@ -750,20 +751,25 @@ got_ref_list(struct got_reflist_head *refs, struct got_repository *repo)
 	struct got_reference *ref;
 	struct got_reflist_entry *new;
 
-	/* HEAD ref should always exist. */
-	path_refs = get_refs_dir_path(repo, GOT_REF_HEAD);
-	if (path_refs == NULL) {
-		err = got_error_from_errno("get_refs_dir_path");
-		goto done;
+	if (ref_namespace == NULL || ref_namespace[0] == '\0') {
+		/* HEAD ref should always exist. */
+		path_refs = get_refs_dir_path(repo, GOT_REF_HEAD);
+		if (path_refs == NULL) {
+			err = got_error_from_errno("get_refs_dir_path");
+			goto done;
+		}
+		err = open_ref(&ref, path_refs, "", GOT_REF_HEAD, 0);
+		if (err)
+			goto done;
+		err = insert_ref(&new, refs, ref, repo);
+		if (err || new == NULL /* duplicate */)
+			got_ref_close(ref);
+		if (err)
+			goto done;
 	}
-	err = open_ref(&ref, path_refs, "", GOT_REF_HEAD, 0);
-	if (err)
-		goto done;
-	err = insert_ref(&new, refs, ref, repo);
-	if (err || new == NULL /* duplicate */)
-		got_ref_close(ref);
-	if (err)
-		goto done;
+
+	if (ref_namespace && strncmp(ref_namespace, "refs/", 5) == 0)
+		ref_namespace += 5;
 
 	/* Gather on-disk refs before parsing packed-refs. */
 	free(path_refs);
@@ -772,7 +778,8 @@ got_ref_list(struct got_reflist_head *refs, struct got_repository *repo)
 		err = got_error_from_errno("get_refs_dir_path");
 		goto done;
 	}
-	err = gather_on_disk_refs(refs, path_refs, "", repo);
+	err = gather_on_disk_refs(refs, path_refs,
+	    ref_namespace ? ref_namespace : "", repo);
 	if (err)
 		goto done;
 
@@ -805,6 +812,15 @@ got_ref_list(struct got_reflist_head *refs, struct got_repository *repo)
 			if (err)
 				goto done;
 			if (ref) {
+				if (ref_namespace) {
+					const char *name;
+					name = got_ref_get_name(ref);
+					if (strncmp(name, ref_namespace,
+					    strlen(ref_namespace)) != 0) {
+						got_ref_close(ref);
+						continue;
+					}
+				}
 				err = insert_ref(&new, refs, ref, repo);
 				if (err || new == NULL /* duplicate */)
 					got_ref_close(ref);
diff --git a/lib/repository.c b/lib/repository.c
index 6b47a6c..4ed88ea 100644
--- a/lib/repository.c
+++ b/lib/repository.c
@@ -1128,17 +1128,16 @@ got_repo_object_match_tag(struct got_tag_object **tag, const char *name,
 	SIMPLEQ_INIT(&refs);
 	*tag = NULL;
 
-	err = got_ref_list(&refs, repo);
+	err = got_ref_list(&refs, repo, "refs/tags");
 	if (err)
 		return err;
 
 	SIMPLEQ_FOREACH(re, &refs, entry) {
 		const char *refname;
 		refname = got_ref_get_name(re->ref);
-		if (got_ref_is_symbolic(re->ref) ||
-		    strncmp("refs/tags/", refname, 10) != 0)
+		if (got_ref_is_symbolic(re->ref))
 			continue;
-		refname += 10;
+		refname += strlen("refs/tags/");
 		if (strcmp(refname, name) != 0)
 			continue;
 		err = got_ref_resolve(&tag_id, repo, re->ref);
diff --git a/tog/tog.c b/tog/tog.c
index 0efa00c..a1865a5 100644
--- a/tog/tog.c
+++ b/tog/tog.c
@@ -2303,7 +2303,7 @@ cmd_log(int argc, char *argv[])
 	if (error != NULL)
 		goto done;
 
-	error = got_ref_list(&refs, repo);
+	error = got_ref_list(&refs, repo, NULL);
 	if (error)
 		goto done;
 
@@ -2928,7 +2928,7 @@ cmd_diff(int argc, char *argv[])
 	if (error)
 		goto done;
 
-	error = got_ref_list(&refs, repo);
+	error = got_ref_list(&refs, repo, NULL);
 	if (error)
 		goto done;
 
@@ -3832,7 +3832,7 @@ cmd_blame(int argc, char *argv[])
 	if (error != NULL)
 		goto done;
 
-	error = got_ref_list(&refs, repo);
+	error = got_ref_list(&refs, repo, NULL);
 	if (error)
 		goto done;
 
@@ -4589,7 +4589,7 @@ cmd_tree(int argc, char *argv[])
 	if (error != NULL)
 		goto done;
 
-	error = got_ref_list(&refs, repo);
+	error = got_ref_list(&refs, repo, NULL);
 	if (error)
 		goto done;