commit - 29e86f7a5a094e0e5e9ca231e615a13c0c2e6ed0
commit + d1c1ae5fa698c48d70eb16cef11bb3710221ea88
blob - a7c6931c739bce2b4746264ec0f8a7e4ef97a80d
blob + 0a9ce6f2c219a2b2a5308d9efdeb9170171b5d96
--- TODO
+++ TODO
- 'histedit -c' prompts for log message even if there are no changes to commit
- recursive addition: got add -R
- recursive removal: got rm -R
-- allow for creating symbolic references with 'got ref -s'
tog:
- cosmetic display issues involving \n and TABs should be fixed
blob - 00c7548af39086e290bea57234ee1243e5e1e2bd
blob + a826de9bf1ee14823162c06c47bc24c7a3767ec1
--- got/got.1
+++ got/got.1
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.
+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 base-branch
Manage branches in a repository.
blob - 9a69229f803e9ee42a8f6cb234d669f3282effe6
blob + a322f32e174306295c8b5682c8a19d3280485378
--- got/got.c
+++ got/got.c
usage_ref(void)
{
fprintf(stderr,
- "usage: %s ref [-r repository] -l | -d name | name target\n",
+ "usage: %s ref [-r repository] -l | -d name | [-s] name target\n",
getprogname());
exit(1);
}
if (ref)
got_ref_close(ref);
free(id);
+ return err;
+}
+
+static const struct got_error *
+add_symref(struct got_repository *repo, const char *refname, const char *target)
+{
+ const struct got_error *err = NULL;
+ struct got_reference *ref = NULL;
+ struct got_reference *target_ref = NULL;
+
+ /*
+ * Don't let the user create a reference named '-'.
+ * While technically a valid reference name, this case is usually
+ * an unintended typo.
+ */
+ if (refname[0] == '-' && refname[1] == '\0')
+ return got_error(GOT_ERR_BAD_REF_NAME);
+
+ err = got_ref_open(&target_ref, repo, target, 0);
+ if (err)
+ return err;
+
+ err = got_ref_alloc_symref(&ref, refname, target_ref);
+ if (err)
+ goto done;
+
+ err = got_ref_write(ref, repo);
+done:
+ if (target_ref)
+ got_ref_close(target_ref);
+ if (ref)
+ got_ref_close(ref);
return err;
}
struct got_repository *repo = NULL;
struct got_worktree *worktree = NULL;
char *cwd = NULL, *repo_path = NULL;
- int ch, do_list = 0;
+ int ch, do_list = 0, create_symref = 0;
const char *delref = NULL;
/* TODO: Add -s option for adding symbolic references. */
- while ((ch = getopt(argc, argv, "d:r:l")) != -1) {
+ while ((ch = getopt(argc, argv, "d:r:ls")) != -1) {
switch (ch) {
case 'd':
delref = optarg;
break;
case 'l':
do_list = 1;
+ break;
+ case 's':
+ create_symref = 1;
break;
default:
usage_ref();
argv += optind;
if (do_list || delref) {
+ if (create_symref)
+ errx(1, "-s option cannot be used together with the "
+ "-l or -d options");
if (argc > 0)
usage_ref();
} else if (argc != 2)
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]);
done:
blob - e86ea7f544fae06c498afb4bfbe43ed12e0e2818
blob + c7f57651b4255a40c5e239acede9d76dae99f6dc
--- regress/cmdline/Makefile
+++ regress/cmdline/Makefile
-REGRESS_TARGETS=checkout update status log add rm diff blame branch commit \
+REGRESS_TARGETS=checkout update status log add rm diff blame branch ref commit \
revert cherrypick backout rebase import histedit stage unstage
NOOBJ=Yes
branch:
./branch.sh
+ref:
+ ./ref.sh
+
commit:
./commit.sh
blob - /dev/null
blob + 3774051198b40f4ceaef773bcd650eaba78d8ead (mode 755)
--- /dev/null
+++ regress/cmdline/ref.sh
+#!/bin/sh
+#
+# Copyright (c) 2019 Stefan Sperling <stsp@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+. ./common.sh
+
+function test_ref_create {
+ local testroot=`test_init ref_create`
+ local commit_id=`git_show_head $testroot/repo`
+
+ # Create a head ref based on repository's HEAD reference
+ got ref -r $testroot/repo refs/heads/newref HEAD
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "got ref command failed unexpectedly"
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # Ensure that Git recognizes the ref Got has created
+ (cd $testroot/repo && git checkout -q newref)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "git checkout command failed unexpectedly"
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # Ensure Git recognizes the new ref
+ got checkout -b newref $testroot/repo $testroot/wt >/dev/null
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "got checkout command failed unexpectedly"
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # Create a head ref based on another specific ref
+ (cd $testroot/wt && got ref refs/heads/anotherref refs/heads/master)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ (cd $testroot/repo && git checkout -q anotherref)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "git checkout command failed unexpectedly"
+ test_done "$testroot" "$ret"
+ fi
+
+ # Create a symbolic ref
+ (cd $testroot/wt && got ref -s refs/heads/symbolicref refs/heads/master)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ (cd $testroot/repo && git checkout -q symbolicref)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "git checkout command failed unexpectedly"
+ test_done "$testroot" "$ret"
+ fi
+
+ got ref -r $testroot/repo -l > $testroot/stdout
+ echo "HEAD: refs/heads/symbolicref" > $testroot/stdout.expected
+ echo -n "refs/got/worktree/base-" >> $testroot/stdout.expected
+ cat $testroot/wt/.got/uuid | tr -d '\n' >> $testroot/stdout.expected
+ echo ": $commit_id" >> $testroot/stdout.expected
+ echo "refs/heads/anotherref: $commit_id" >> $testroot/stdout.expected
+ echo "refs/heads/master: $commit_id" >> $testroot/stdout.expected
+ echo "refs/heads/newref: $commit_id" >> $testroot/stdout.expected
+ echo "refs/heads/symbolicref: refs/heads/master" \
+ >> $testroot/stdout.expected
+ cmp -s $testroot/stdout $testroot/stdout.expected
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ fi
+ test_done "$testroot" "$ret"
+}
+
+function test_ref_delete {
+ local testroot=`test_init 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
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "got ref command failed unexpectedly"
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+ done
+
+ got ref -d refs/heads/ref2 -r $testroot/repo > $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "got ref command failed unexpectedly"
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ got ref -l -r $testroot/repo > $testroot/stdout
+ echo "HEAD: refs/heads/master" > $testroot/stdout.expected
+ echo "refs/heads/master: $commit_id" >> $testroot/stdout.expected
+ echo "refs/heads/ref1: $commit_id" >> $testroot/stdout.expected
+ echo "refs/heads/ref3: $commit_id" >> $testroot/stdout.expected
+ cmp -s $testroot/stdout $testroot/stdout.expected
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ got ref -d refs/heads/bogus_ref_name -r $testroot/repo \
+ > $testroot/stdout 2> $testroot/stderr
+ ret="$?"
+ if [ "$ret" == "0" ]; then
+ echo "got ref succeeded unexpectedly"
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ echo "got: reference refs/heads/bogus_ref_name not found" \
+ > $testroot/stderr.expected
+ cmp -s $testroot/stderr $testroot/stderr.expected
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stderr.expected $testroot/stderr
+ fi
+ test_done "$testroot" "$ret"
+}
+
+run_test test_ref_create
+run_test test_ref_delete