Commit d83d9d5c431189537fc94c38a85ce2b8e3217f5d

Stefan Sperling 2019-05-13T17:16:28

make it possible to duplicate another reference with 'got ref'

diff --git a/got/got.1 b/got/got.1
index d986705..73e69b6 100644
--- a/got/got.1
+++ b/got/got.1
@@ -260,16 +260,17 @@ Show object IDs of files (blob objects) and directories (tree objects).
 .It Fl R
 Recurse into sub-directories in the repository.
 .El
-.It Cm ref [ Fl r Ar repository-path ] [ Fl l ] [ Fl d Ar name ] [ Ar name Ar object ]
+.It Cm ref [ Fl r Ar repository-path ] [ Fl l ] [ Fl d Ar name ] [ Ar name Ar target ]
 Manage references in a repository.
 .Pp
 If no options are passed, expect two arguments and attempt to create,
 or update, the reference with the given
 .Ar name ,
 and make it point at the given
-.Ar object .
-The object argument is a SHA1 hash which corresponds to an existing
-object in the repository.
+.Ar target .
+The target may be a SHA1 hash which corresponds to an existing object ID
+in the repository, or an existing reference which will be resolved to an
+object ID.
 .Pp
 The options for
 .Cm got ref
@@ -373,6 +374,14 @@ Check out a work tree of
 kernel sources from a Git repository at /var/repo/openbsd-src to ~/sys:
 .Pp
 .Dl $ got checkout -p sys /var/repo/openbsd-src ~/sys
+.Pp
+Create a new branch
+.Dq mybranch
+which is forked off the
+.Dq master
+branch:
+.Pp
+.Dl $ got ref mybranch master
 .Sh SEE ALSO
 .Xr git-repository 5
 .Xr got-worktree 5
diff --git a/got/got.c b/got/got.c
index 3ef3e75..9469b96 100644
--- a/got/got.c
+++ b/got/got.c
@@ -1735,7 +1735,7 @@ __dead static void
 usage_ref(void)
 {
 	fprintf(stderr,
-	    "usage: %s ref [-r repository] -l | -d name | name object\n",
+	    "usage: %s ref [-r repository] -l | -d name | name target\n",
 	    getprogname());
 	exit(1);
 }
@@ -1781,15 +1781,26 @@ delete_ref(struct got_repository *repo, const char *refname)
 }
 
 static const struct got_error *
-add_ref(struct got_repository *repo, const char *refname, const char *id_str)
+add_ref(struct got_repository *repo, const char *refname, const char *target)
 {
 	const struct got_error *err = NULL;
 	struct got_object_id *id;
 	struct got_reference *ref = NULL;
 
-	err = got_object_resolve_id_str(&id, repo, id_str);
-	if (err)
-		return err;
+	err = got_object_resolve_id_str(&id, repo, target);
+	if (err) {
+		struct got_reference *target_ref;
+
+		if (err->code != GOT_ERR_BAD_OBJ_ID_STR)
+			return err;
+		err = got_ref_open(&target_ref, repo, target, 0);
+		if (err)
+			return err;
+		err = got_ref_resolve(&id, repo, target_ref);
+		got_ref_close(target_ref);
+		if (err)
+			return err;
+	}
 
 	err = got_ref_alloc(&ref, refname, id);
 	if (err)