Commit b249b824fbd8134a3152b48798682db67aa45c68

Stefan Sperling 2019-05-09T13:47:59

add APIs to change references

diff --git a/include/got_error.h b/include/got_error.h
index c5fb394..c3c1b5a 100644
--- a/include/got_error.h
+++ b/include/got_error.h
@@ -83,6 +83,7 @@
 #define GOT_ERR_FILE_MODIFIED	67
 #define GOT_ERR_FILE_STATUS	68
 #define GOT_ERR_COMMIT_CONFLICT	69
+#define GOT_ERR_BAD_REF_TYPE	70
 
 static const struct got_error {
 	int code;
@@ -157,6 +158,7 @@ static const struct got_error {
 	{ GOT_ERR_FILE_MODIFIED,"file contains modifications" },
 	{ GOT_ERR_FILE_STATUS,	"file has unexpected status" },
 	{ GOT_ERR_COMMIT_CONFLICT,"cannot commit file in conflicted status" },
+	{ GOT_ERR_BAD_REF_TYPE,	"bad reference type" },
 };
 
 /*
diff --git a/include/got_reference.h b/include/got_reference.h
index cf87b34..5c3eed9 100644
--- a/include/got_reference.h
+++ b/include/got_reference.h
@@ -77,6 +77,18 @@ const struct got_error *got_ref_list(struct got_reflist_head *,
 /* Free all references on a ref list. */
 void got_ref_list_free(struct got_reflist_head *);
 
+/* 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 *);
+
+/* Change the object ID a reference points to. */
+const struct got_error *
+got_ref_change_ref(struct got_reference *, struct got_object_id *);
+
+/* Change the reference name a symbolic reference points to. */
+const struct got_error *got_ref_change_symref(struct got_reference *,
+    char *);
+
 /* Write a reference to its on-disk path in the repository. */
 const struct got_error *got_ref_write(struct got_reference *,
     struct got_repository *);
diff --git a/lib/reference.c b/lib/reference.c
index f01bb78..168ef0c 100644
--- a/lib/reference.c
+++ b/lib/reference.c
@@ -765,6 +765,39 @@ got_ref_list_free(struct got_reflist_head *refs)
 
 }
 
+int
+got_ref_is_symbolic(struct got_reference *ref)
+{
+	return (ref->flags & GOT_REF_IS_SYMBOLIC);
+}
+
+const struct got_error *
+got_ref_change_ref(struct got_reference *ref, struct got_object_id *id)
+{
+	if (ref->flags & GOT_REF_IS_SYMBOLIC)
+		return got_error(GOT_ERR_BAD_REF_TYPE);
+
+	memcpy(ref->ref.ref.sha1, id->sha1, sizeof(ref->ref.ref.sha1));
+	return NULL;
+}
+
+const struct got_error *
+got_ref_change_symref(struct got_reference *ref, char *refname)
+{
+	char *new_name;
+
+	if ((ref->flags & GOT_REF_IS_SYMBOLIC) == 0)
+		return got_error(GOT_ERR_BAD_REF_TYPE);
+
+	new_name = strdup(refname);
+	if (new_name == NULL)
+		return got_error_from_errno();
+
+	free(ref->ref.symref.name);
+	ref->ref.symref.name = new_name;
+	return NULL;
+}
+
 const struct got_error *
 got_ref_write(struct got_reference *ref, struct got_repository *repo)
 {