"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
add 'got branch' -c option
To:
gameoftrees@openbsd.org
Cc:
Pavel Korovin <pvk@openbsd.org>, Kurt Mosiejczuk <kmos@openbsd.org>
Date:
Sun, 10 Nov 2019 13:25:09 +0200

Download raw body.

Thread
This changes the synopsis of 'got branch' slightly (in a backwards
incompatble way, but we don't promise a stable UI yet anyway).

The current way to create a branch based on a specific commit is:

	got branch branch_name commit_id

where "commit_id" can also be specified indirectly via a reference.

With the patch below, this becomes:

	got branch -c commit_id branch_name

The idea is to avoid confusion about the order of branch name and
commit id arguments, and to make 'got branch' rely on the commit
option parsing code already used by other commands.

Prompted by a discussion with Kurt Mosiejczuk and Pavel Korovin
over glasses of fine Romanian wine :-)

ok?

diff a837b5e488f7dbfbb1e161c9583b4b76b473fe62 /home/stsp/src/got
blob - 84fbdf46212019d1180049f41ff6f024f3848b6d
file + got/got.1
--- got/got.1
+++ got/got.1
@@ -509,7 +509,7 @@ which must be an existing reference.
 Care should be taken not to create loops between references when
 this option is used.
 .El
-.It Cm branch Oo Fl r Ar repository-path Oc Oo Fl l Oc Oo Fl d Ar name Oc Op Ar name Op Ar commit
+.It Cm branch Oo Fl c Ar commit Oc Oo Fl r Ar repository-path Oc Oo Fl l Oc Oo Fl d Ar name Oc Op Ar name
 Manage branches in a repository.
 .Pp
 Branches are managed via references which live in the
@@ -521,25 +521,24 @@ command operates on references in this namespace only.
 .Pp
 If invoked in a work tree without any arguments, print the name of the
 work tree's current branch.
-If one or two arguments are passed, attempt to create a branch reference
-with the given
-.Ar name ,
-and make it point at the given
-.Ar commit .
-The expected
-.Ar commit
-argument is a commit ID SHA1 hash or an existing reference
-or tag name which will be resolved to a commit ID.
-If no
-.Ar commit
-is specified, default to the latest commit on the work tree's current
-branch if invoked in a work tree, or to a commit resolved via the
-repository's HEAD reference.
+If a
+.Ar name
+argument is passed, attempt to create a branch reference with the given name.
+By default the new branch reference will point at the latest commit on the
+work tree's current branch if invoked in a work tree, and otherwise to a commit
+resolved via the repository's HEAD reference.
 .Pp
 The options for
 .Cm got branch
 are as follows:
 .Bl -tag -width Ds
+.It Fl c Ar commit
+Make a newly created branch reference point at the specified
+.Ar commit .
+The expected
+.Ar commit
+argument is a commit ID SHA1 hash or an existing reference
+or tag name which will be resolved to a commit ID.
 .It Fl r Ar repository-path
 Use the repository at the specified path.
 If not specified, assume the repository is located at or above the current
blob - 3a3fb516b76cb9ed59e3a1cd223e1f0d2b0fdd9c
file + got/got.c
--- got/got.c
+++ got/got.c
@@ -3275,8 +3275,8 @@ __dead static void
 usage_branch(void)
 {
 	fprintf(stderr,
-	    "usage: %s branch [-r repository] [-l] | -d name | "
-	    "[name [commit]]\n", getprogname());
+	    "usage: %s branch [-c commit] [-r repository] [-l] | -d name | "
+	    "[name]\n", getprogname());
 	exit(1);
 }
 
@@ -3415,11 +3415,9 @@ done:
 
 static const struct got_error *
 add_branch(struct got_repository *repo, const char *branch_name,
-    const char *base_branch)
+    struct got_object_id *base_commit_id)
 {
 	const struct got_error *err = NULL;
-	struct got_object_id *id = NULL;
-	char *label;
 	struct got_reference *ref = NULL;
 	char *base_refname = NULL, *refname = NULL;
 
@@ -3431,11 +3429,6 @@ add_branch(struct got_repository *repo, const char *br
 	if (branch_name[0] == '-' && branch_name[1] == '\0')
 		return got_error_path(branch_name, GOT_ERR_BAD_REF_NAME);
 
-	err = match_object_id(&id, &label, base_branch,
-	    GOT_OBJ_TYPE_COMMIT, 1, repo);
-	if (err)
-		return err;
-
 	if (asprintf(&refname, "refs/heads/%s", branch_name) == -1) {
 		 err = got_error_from_errno("asprintf");
 		 goto done;
@@ -3448,7 +3441,7 @@ add_branch(struct got_repository *repo, const char *br
 	} else if (err->code != GOT_ERR_NOT_REF)
 		goto done;
 
-	err = got_ref_alloc(&ref, refname, id);
+	err = got_ref_alloc(&ref, refname, base_commit_id);
 	if (err)
 		goto done;
 
@@ -3456,7 +3449,6 @@ add_branch(struct got_repository *repo, const char *br
 done:
 	if (ref)
 		got_ref_close(ref);
-	free(id);
 	free(base_refname);
 	free(refname);
 	return err;
@@ -3470,10 +3462,13 @@ cmd_branch(int argc, char *argv[])
 	struct got_worktree *worktree = NULL;
 	char *cwd = NULL, *repo_path = NULL;
 	int ch, do_list = 0, do_show = 0;
-	const char *delref = NULL;
+	const char *delref = NULL, *commit_id_arg = NULL;
 
-	while ((ch = getopt(argc, argv, "d:r:l")) != -1) {
+	while ((ch = getopt(argc, argv, "c:d:r:l")) != -1) {
 		switch (ch) {
+		case 'c':
+			commit_id_arg = optarg;
+			break;
 		case 'd':
 			delref = optarg;
 			break;
@@ -3502,10 +3497,13 @@ cmd_branch(int argc, char *argv[])
 	if (!do_list && !delref && argc == 0)
 		do_show = 1;
 
+	if ((do_list || delref || do_show) && commit_id_arg != NULL)
+		errx(1, "-c option can only be used when creating a branch");
+
 	if (do_list || delref) {
 		if (argc > 0)
 			usage_branch();
-	} else if (!do_show && (argc < 1 || argc > 2))
+	} else if (!do_show && argc != 1)
 		usage_branch();
 
 #ifndef PROFILE
@@ -3563,16 +3561,16 @@ cmd_branch(int argc, char *argv[])
 	else if (delref)
 		error = delete_branch(repo, worktree, delref);
 	else {
-		const char *base_branch;
-		if (argc == 1) {
-			base_branch = worktree ?
+		struct got_object_id *commit_id;
+		if (commit_id_arg == NULL)
+			commit_id_arg = worktree ?
 			    got_worktree_get_head_ref_name(worktree) :
 			    GOT_REF_HEAD;
-			if (strncmp(base_branch, "refs/heads/", 11) == 0)
-				base_branch += 11;
-		} else
-			base_branch = argv[1];
-		error = add_branch(repo, argv[0], base_branch);
+		error = resolve_commit_arg(&commit_id, commit_id_arg, repo);
+		if (error)
+			goto done;
+		error = add_branch(repo, argv[0], commit_id);
+		free(commit_id);
 	}
 done:
 	if (repo)
blob - 05f7d1c68bc1b11636a716791ffe719b6799e6b7
file + regress/cmdline/branch.sh
--- regress/cmdline/branch.sh
+++ regress/cmdline/branch.sh
@@ -74,7 +74,7 @@ function test_branch_create {
 	fi
 
 	# Create a branch based on another specific branch
-	(cd $testroot/wt && got branch yetanotherbranch master)
+	(cd $testroot/wt && got branch -c master yetanotherbranch)
 	ret="$?"
 	if [ "$ret" != "0" ]; then
 		test_done "$testroot" "$ret"
@@ -91,7 +91,7 @@ function test_branch_create {
 
 	# Create a branch based on a specific commit
 	local commit_id=`git_show_head $testroot/repo`
-	got branch -r $testroot/repo commitbranch $commit_id
+	got branch -r $testroot/repo -c $commit_id commitbranch
 	ret="$?"
 	if [ "$ret" != "0" ]; then
 		echo "got branch command failed unexpectedly"