Commit Diff


commit - 255c4055a2c4c323dace71509df44c6b59ddd819
commit + e31abbf21f99a7312bdfd392f33ace285feadfe5
blob - 62fe17b1245763f96d147bf56f10249beae43dc3
blob + 59cc0bc74ca2f04ba3df6a2dc55756f8e29edde5
--- got/got.1
+++ got/got.1
@@ -821,20 +821,15 @@ Recurse into sub-directories in the repository.
 .It Cm tr
 Short alias for
 .Cm tree .
-.It Cm ref Oo Fl r Ar repository-path Oc Oo Fl l Oc Oo Fl d Ar name Oc Oo Fl s Oc Op Ar name Ar target
+.It Cm ref Oo Fl r Ar repository-path Oc Oo Fl l Oc Oo Fl c Ar object Oc Oo Fl s Ar reference Oc Oo Fl d Oc Op Ar name
 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 target .
-The name must be an absolute reference name, i.e. it must begin with
+References may be listed, created, deleted, and changed.
+When creating, deleting, or changing a reference the specified
+.Ar name
+must be an absolute reference name, i.e. it must begin with
 .Dq refs/ .
-The target may be an object ID SHA1 hash or an existing reference which
-will be resolved to an object ID.
-An abbreviated hash argument will be expanded to a full SHA1 hash
-automatically, provided the abbreviation is unique.
+.Pp
 .Pp
 The options for
 .Cm got ref
@@ -849,14 +844,37 @@ If this directory is a
 work tree, use the repository path associated with this work tree.
 .It Fl l
 List all existing references in the repository.
-.It Fl d Ar name
-Delete the reference with the specified name from the repository.
-.It Fl s
-Create a symbolic reference pointing at the specified
-.Ar target ,
-which must be an existing reference.
+Cannot be used together with any other options except
+.Fl r .
+.It Fl c Ar object
+Create a reference or change an existing reference.
+The reference with the specified
+.Ar name
+will point at the specified
+.Ar object.
+The expected
+.Ar object
+argument is a ID SHA1 hash or an existing reference or tag name which will
+be resolved to the ID of a corresponding commit, tree, tag, or blob object.
+Cannot be used together with any other options except
+.Fl r .
+.It Fl s Ar reference
+Create a symbolic reference, or change an existing symbolic reference.
+The symbolic reference with the specified
+.Ar name
+will point at the specified
+.Ar reference
+which must already exist in the repository.
 Care should be taken not to create loops between references when
 this option is used.
+Cannot be used together with any other options except
+.Fl r .
+.It Fl d
+Delete the reference with the specified
+.Ar name
+from the repository.
+Cannot be used together with any other options except
+.Fl r .
 .El
 .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 Oo Fl n Oc Op Ar name
 Create, list, or delete branches.
blob - cebadef7f168d056f60bdde3f2eae62abb1e79b6
blob + b27ba046f77b825e22827ab64329341daa4b767b
--- got/got.c
+++ got/got.c
@@ -4175,7 +4175,8 @@ __dead static void
 usage_ref(void)
 {
 	fprintf(stderr,
-	    "usage: %s ref [-r repository] -l | -d name | [-s] name target\n",
+	    "usage: %s ref [-r repository] [-l] [-c object] [-s reference] "
+	        "[-d] [name]\n",
 	    getprogname());
 	exit(1);
 }
@@ -4302,14 +4303,16 @@ cmd_ref(int argc, char *argv[])
 	struct got_repository *repo = NULL;
 	struct got_worktree *worktree = NULL;
 	char *cwd = NULL, *repo_path = NULL;
-	int ch, do_list = 0, create_symref = 0;
-	const char *delref = NULL;
+	int ch, do_list = 0, do_delete = 0;
+	const char *refname = NULL, *obj_arg = NULL, *symref_target= NULL;
 
-	/* TODO: Add -s option for adding symbolic references. */
-	while ((ch = getopt(argc, argv, "d:r:ls")) != -1) {
+	while ((ch = getopt(argc, argv, "c:dr:ls:")) != -1) {
 		switch (ch) {
+		case 'c':
+			obj_arg = optarg;
+			break;
 		case 'd':
-			delref = optarg;
+			do_delete = 1;
 			break;
 		case 'r':
 			repo_path = realpath(optarg, NULL);
@@ -4322,7 +4325,7 @@ cmd_ref(int argc, char *argv[])
 			do_list = 1;
 			break;
 		case 's':
-			create_symref = 1;
+			symref_target = optarg;
 			break;
 		default:
 			usage_ref();
@@ -4330,20 +4333,30 @@ cmd_ref(int argc, char *argv[])
 		}
 	}
 
-	if (do_list && delref)
-		errx(1, "-l and -d options are mutually exclusive\n");
+	if (obj_arg && do_list)
+		errx(1, "-c and -l options are mutually exclusive\n");
+	if (obj_arg && do_delete)
+		errx(1, "-c and -d options are mutually exclusive\n");
+	if (obj_arg && symref_target)
+		errx(1, "-c and -s options are mutually exclusive\n");
+	if (symref_target && do_delete)
+		errx(1, "-s and -d options are mutually exclusive\n");
+	if (symref_target && do_list)
+		errx(1, "-s and -l options are mutually exclusive\n");
+	if (do_delete && do_list)
+		errx(1, "-d and -l options are mutually exclusive\n");
 
 	argc -= optind;
 	argv += optind;
 
-	if (do_list || delref) {
-		if (create_symref)
-			errx(1, "-s option cannot be used together with the "
-			    "-l or -d options");
+	if (do_list) {
 		if (argc > 0)
 			usage_ref();
-	} else if (argc != 2)
-		usage_ref();
+	} else {
+		if (argc != 1)
+			usage_ref();
+		refname = argv[0];
+	}
 
 #ifndef PROFILE
 	if (do_list) {
@@ -4395,12 +4408,15 @@ cmd_ref(int argc, char *argv[])
 
 	if (do_list)
 		error = list_refs(repo);
-	else if (delref)
-		error = delete_ref(repo, delref);
-	else if (create_symref)
-		error = add_symref(repo, argv[0], argv[1]);
-	else
-		error = add_ref(repo, argv[0], argv[1]);
+	else if (do_delete)
+		error = delete_ref(repo, refname);
+	else if (symref_target)
+		error = add_symref(repo, refname, symref_target);
+	else {
+		if (obj_arg == NULL)
+			usage_ref();
+		error = add_ref(repo, refname, obj_arg);
+	}
 done:
 	if (repo)
 		got_repo_close(repo);
blob - f3a8329ac8336d70b30d8bb5d62f5fa383572eba
blob + 446d7b73e9428139a538555e3c55ae5786cb6eb8
--- regress/cmdline/clone.sh
+++ regress/cmdline/clone.sh
@@ -93,7 +93,7 @@ function test_clone_list {
 	local commit_id=`git_show_head $testroot/repo`
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 	got tag -r $testroot/repo -c $commit_id -m tag "1.0" >/dev/null
 
 	got clone -l $testurl/repo > $testroot/stdout 2>$testroot/stderr
@@ -121,7 +121,7 @@ function test_clone_branch {
 	local commit_id=`git_show_head $testroot/repo`
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 	got tag -r $testroot/repo -c $commit_id -m tag "1.0" >/dev/null
 	local tag_id=`got ref -r $testroot/repo -l \
 		| grep "^refs/tags/$tag" | tr -d ' ' | cut -d: -f2`
@@ -157,7 +157,7 @@ function test_clone_all {
 	local commit_id=`git_show_head $testroot/repo`
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 	got tag -r $testroot/repo -c $commit_id -m tag "1.0" >/dev/null
 	local tag_id=`got ref -r $testroot/repo -l \
 		| grep "^refs/tags/$tag" | tr -d ' ' | cut -d: -f2`
@@ -195,7 +195,7 @@ function test_clone_mirror {
 	local commit_id=`git_show_head $testroot/repo`
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 	got tag -r $testroot/repo -c $commit_id -m tag "1.0" >/dev/null
 	local tag_id=`got ref -r $testroot/repo -l \
 		| grep "^refs/tags/$tag" | tr -d ' ' | cut -d: -f2`
@@ -230,7 +230,7 @@ function test_clone_mirror_all {
 	local commit_id=`git_show_head $testroot/repo`
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 	got tag -r $testroot/repo -c $commit_id -m tag "1.0" >/dev/null
 	local tag_id=`got ref -r $testroot/repo -l \
 		| grep "^refs/tags/$tag" | tr -d ' ' | cut -d: -f2`
@@ -265,7 +265,7 @@ function test_clone_reference {
 	local commit_id=`git_show_head $testroot/repo`
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 	got tag -r $testroot/repo -c $commit_id -m tag "1.0" >/dev/null
 	local tag_id=`got ref -r $testroot/repo -l \
 		| grep "^refs/tags/$tag" | tr -d ' ' | cut -d: -f2`
@@ -302,7 +302,7 @@ function test_clone_branch_and_reference {
 	local commit_id=`git_show_head $testroot/repo`
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 	got tag -r $testroot/repo -c $commit_id -m tag "1.0" >/dev/null
 	local tag_id=`got ref -r $testroot/repo -l \
 		| grep "^refs/tags/$tag" | tr -d ' ' | cut -d: -f2`
@@ -339,7 +339,7 @@ function test_clone_reference_mirror {
 	local commit_id=`git_show_head $testroot/repo`
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 	got tag -r $testroot/repo -c $commit_id -m tag "1.0" >/dev/null
 	local tag_id=`got ref -r $testroot/repo -l \
 		| grep "^refs/tags/$tag" | tr -d ' ' | cut -d: -f2`
blob - fbf48ee5570790ff88f8e64e0c4f1a1aab82289f
blob + a131681c03b7c5c023fa5603baf9b704a0bc4779
--- regress/cmdline/commit.sh
+++ regress/cmdline/commit.sh
@@ -499,7 +499,7 @@ function test_commit_selected_paths {
 function test_commit_outside_refs_heads {
 	local testroot=`test_init commit_outside_refs_heads`
 
-	got ref -r $testroot/repo refs/remotes/origin/master master
+	got ref -r $testroot/repo -c master refs/remotes/origin/master
 
 	got checkout -b refs/remotes/origin/master \
 	    $testroot/repo $testroot/wt > /dev/null
blob - b59b39ef20a710f192c51ed6560b8c1b58bb3e67
blob + fb811d10678197846f753b9591a2ea121483ebc1
--- regress/cmdline/fetch.sh
+++ regress/cmdline/fetch.sh
@@ -123,7 +123,7 @@ function test_fetch_list {
 	local commit_id=`git_show_head $testroot/repo`
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 	got tag -r $testroot/repo -c $commit_id -m tag "1.0" >/dev/null
 
 	got clone -q $testurl/repo $testroot/repo-clone
@@ -168,7 +168,7 @@ function test_fetch_branch {
 	fi
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 	got tag -r $testroot/repo -c $commit_id -m tag "1.0" >/dev/null
 	local tag_id=`got ref -r $testroot/repo -l \
 		| grep "^refs/tags/$tag" | tr -d ' ' | cut -d: -f2`
@@ -271,7 +271,7 @@ function test_fetch_all {
 	fi
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 	got tag -r $testroot/repo -c $commit_id -m tag "1.0" >/dev/null
 	local tag_id=`got ref -r $testroot/repo -l \
 		| grep "^refs/tags/$tag" | tr -d ' ' | cut -d: -f2`
@@ -337,7 +337,7 @@ function test_fetch_empty_packfile {
 	fi
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 
 	got ref -l -r $testroot/repo-clone > $testroot/stdout
 
@@ -390,7 +390,7 @@ function test_fetch_delete_branch {
 
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 	got tag -r $testroot/repo -c $commit_id -m tag "1.0" >/dev/null
 	local tag_id=`got ref -r $testroot/repo -l \
 		| grep "^refs/tags/$tag" | tr -d ' ' | cut -d: -f2`
@@ -497,7 +497,7 @@ function test_fetch_update_tag {
 
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 	got tag -r $testroot/repo -c $commit_id -m tag "1.0" >/dev/null
 	local tag_id=`got ref -r $testroot/repo -l \
 		| grep "^refs/tags/$tag" | tr -d ' ' | cut -d: -f2`
@@ -656,7 +656,7 @@ function test_fetch_reference {
 	fi
 
 	got branch -r $testroot/repo -c $commit_id foo
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
 	got tag -r $testroot/repo -c $commit_id -m tag "1.0" >/dev/null
 	local tag_id=`got ref -r $testroot/repo -l \
 		| grep "^refs/tags/$tag" | tr -d ' ' | cut -d: -f2`
@@ -741,8 +741,8 @@ function test_fetch_replace_symref {
 		return 1
 	fi
 
-	got ref -r $testroot/repo refs/hoo/boo/zoo $commit_id
-	got ref -r $testroot/repo-clone -s refs/hoo/boo/zoo refs/heads/master
+	got ref -r $testroot/repo -c $commit_id refs/hoo/boo/zoo
+	got ref -r $testroot/repo-clone -s refs/heads/master refs/hoo/boo/zoo
 
 	got ref -l -r $testroot/repo-clone > $testroot/stdout
 
blob - d85840618184c07990545e7fc5f807ff54e29b6b
blob + a2bae29b0a70794309a14b5440419d30c4ff9cc0
--- regress/cmdline/histedit.sh
+++ regress/cmdline/histedit.sh
@@ -1086,7 +1086,7 @@ function test_histedit_outside_refs_heads {
 	fi
 	local commit2=`git_show_head $testroot/repo`
 
-	got ref -r $testroot/repo refs/remotes/origin/master master
+	got ref -r $testroot/repo -c master refs/remotes/origin/master
 	ret="$?"
 	if [ "$ret" != "0" ]; then
 		echo "got ref failed unexpectedly" >&2
blob - 262922a8781a97382dedbb832e92a3f68736454d
blob + 7423d96b389d81dc4599fdcc9579c42cf945db16
--- regress/cmdline/rebase.sh
+++ regress/cmdline/rebase.sh
@@ -819,9 +819,8 @@ function test_rebase_forward {
 	# commit ffcffcd102cf1af6572fbdbb4cf07a0f1fd2d840 (master)
 	# commit 87a6a8a2263a15b61c016ff1720b24741d455eb5
 	(cd $testroot/repo && got ref -d master)
-	(cd $testroot/repo && got ref refs/heads/master $commit1)
-	(cd $testroot/repo && got ref refs/remotes/origin/master $commit2)
-
+	(cd $testroot/repo && got ref -c $commit1 refs/heads/master)
+	(cd $testroot/repo && got ref -c $commit2 refs/remotes/origin/master)
 
 	(cd $testroot/wt && got up -b origin/master > /dev/null)
 
blob - 50b3132f130ff87c2a04152bb8ed0a243a817079
blob + 94736443ecd38ab37cc59e7464129a48092a6a72
--- regress/cmdline/ref.sh
+++ regress/cmdline/ref.sh
@@ -20,8 +20,8 @@ function test_ref_create {
 	local testroot=`test_init ref_create`
 	local commit_id=`git_show_head $testroot/repo`
 
-	# Create a ref based on a commit ID
-	got ref -r $testroot/repo refs/heads/commitref $commit_id
+	# Create a ref pointing at a commit ID
+	got ref -r $testroot/repo -c $commit_id refs/heads/commitref
 	ret="$?"
 	if [ "$ret" != "0" ]; then
 		echo "got ref command failed unexpectedly"
@@ -30,7 +30,7 @@ function test_ref_create {
 	fi
 
 	# Create a ref based on repository's HEAD reference
-	got ref -r $testroot/repo refs/heads/newref HEAD
+	got ref -r $testroot/repo -c HEAD refs/heads/newref
 	ret="$?"
 	if [ "$ret" != "0" ]; then
 		echo "got ref command failed unexpectedly"
@@ -57,7 +57,7 @@ function test_ref_create {
 	fi
 
 	# Create a head ref based on another specific ref
-	(cd $testroot/wt && got ref refs/heads/anotherref refs/heads/master)
+	(cd $testroot/wt && got ref -c refs/heads/master refs/heads/anotherref)
 	ret="$?"
 	if [ "$ret" != "0" ]; then
 		test_done "$testroot" "$ret"
@@ -72,7 +72,7 @@ function test_ref_create {
 	fi
 
 	# Create a symbolic ref
-	(cd $testroot/wt && got ref -s refs/heads/symbolicref refs/heads/master)
+	(cd $testroot/wt && got ref -s refs/heads/master refs/heads/symbolicref)
 	ret="$?"
 	if [ "$ret" != "0" ]; then
 		test_done "$testroot" "$ret"
@@ -88,7 +88,7 @@ function test_ref_create {
 	fi
 
 	# Attempt to create a symbolic ref pointing at a non-reference
-	(cd $testroot/wt && got ref -s refs/heads/symbolicref $commit_id \
+	(cd $testroot/wt && got ref -s $commit_id refs/heads/symbolicref \
 		2> $testroot/stderr)
 	ret="$?"
 	if [ "$ret" == "0" ]; then
@@ -106,8 +106,45 @@ function test_ref_create {
 		return 1
 	fi
 
+	# Attempt to create a reference without specifying a name
+	(cd $testroot/wt && got ref -c $commit_id 2> $testroot/stderr)
+	ret="$?"
+	if [ "$ret" == "0" ]; then
+		echo "git ref command succeeded unexpectedly"
+		test_done "$testroot" "1"
+		return 1
+	fi
+
+	grep -q '^usage: got ref' $testroot/stderr
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		echo "unexpected usage error message: " >&2
+		cat $testroot/stderr >&2
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	# Attempt to create a symbolic reference without specifying a name
+	(cd $testroot/wt && got ref -s refs/heads/symbolicref \
+		2> $testroot/stderr)
+	ret="$?"
+	if [ "$ret" == "0" ]; then
+		echo "git ref command succeeded unexpectedly"
+		test_done "$testroot" "1"
+		return 1
+	fi
+
+	grep -q '^usage: got ref' $testroot/stderr
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		echo "unexpected usage error message: " >&2
+		cat $testroot/stderr >&2
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
 	# Change HEAD
-	got ref -r $testroot/repo -s HEAD refs/heads/newref
+	got ref -r $testroot/repo -s refs/heads/newref HEAD
 	ret="$?"
 	if [ "$ret" != "0" ]; then
 		echo "got ref command failed unexpectedly"
@@ -156,7 +193,7 @@ function test_ref_delete {
 	local commit_id=`git_show_head $testroot/repo`
 
 	for b in ref1 ref2 ref3; do
-		got ref -r $testroot/repo refs/heads/$b refs/heads/master
+		got ref -r $testroot/repo -c refs/heads/master refs/heads/$b
 		ret="$?"
 		if [ "$ret" != "0" ]; then
 			echo "got ref command failed unexpectedly"
@@ -165,7 +202,7 @@ function test_ref_delete {
 		fi
 	done
 
-	got ref -d refs/heads/ref2 -r $testroot/repo > $testroot/stdout
+	got ref -d -r $testroot/repo refs/heads/ref2 > $testroot/stdout
 	ret="$?"
 	if [ "$ret" != "0" ]; then
 		echo "got ref command failed unexpectedly"
@@ -186,7 +223,7 @@ function test_ref_delete {
 		return 1
 	fi
 
-	got ref -d refs/heads/bogus_ref_name -r $testroot/repo \
+	got ref -r $testroot/repo -d refs/heads/bogus_ref_name \
 		> $testroot/stdout 2> $testroot/stderr
 	ret="$?"
 	if [ "$ret" == "0" ]; then