From: Stefan Sperling Subject: add 'got branch' -c option To: gameoftrees@openbsd.org Cc: Pavel Korovin , Kurt Mosiejczuk Date: Sun, 10 Nov 2019 13:25:09 +0200 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"