commit 303e2782e0a61a1cf76da52a945ab8645a8a78ca from: Stefan Sperling date: Fri Aug 09 11:37:56 2019 UTC add support for tags to -c options of some got commands commit - 8479284323dc11b5f08a6d8896bd806722b34634 commit + 303e2782e0a61a1cf76da52a945ab8645a8a78ca blob - 967828d4c76fd2aff9b23dcefda926b5a25846f9 blob + 7f75a48345e3d059e9439ae651ab97f98016f253 --- got/got.1 +++ got/got.1 @@ -153,7 +153,7 @@ Check out files from the specified .Ar commit on the selected branch. The expected argument is a commit ID SHA1 hash or an existing reference -which will be resolved to a commit ID. +or tag name which will be resolved to a commit ID. An abbreviated hash argument will be expanded to a full SHA1 hash automatically, provided the abbreviation is unique. If this option is not specified, the most recent commit on the selected @@ -223,7 +223,7 @@ This option requires that all paths in the work tree a Update the work tree to the specified .Ar commit . The expected argument is a commit ID SHA1 hash or an existing reference -which will be resolved to a commit ID. +or tag name which will be resolved to a commit ID. An abbreviated hash argument will be expanded to a full SHA1 hash automatically, provided the abbreviation is unique. If this option is not specified, the most recent commit on the work tree's @@ -299,7 +299,7 @@ are as follows: Start traversing history at the specified .Ar commit . The expected argument is a commit ID SHA1 hash or an existing reference -which will be resolved to a commit ID. +or tag name which will be resolved to a commit ID. An abbreviated hash argument will be expanded to a full SHA1 hash automatically, provided the abbreviation is unique. If this option is not specified, default to the work tree's current branch @@ -374,7 +374,7 @@ are as follows: Start traversing history at the specified .Ar commit . The expected argument is a commit ID SHA1 hash or an existing reference -which will be resolved to a commit ID. +or tag name which will be resolved to a commit ID. An abbreviated hash argument will be expanded to a full SHA1 hash automatically, provided the abbreviation is unique. .It Fl r Ar repository-path @@ -412,7 +412,7 @@ are as follows: List files and directories as they appear in the specified .Ar commit . The expected argument is a commit ID SHA1 hash or an existing reference -which will be resolved to a commit ID. +or tag name which will be resolved to a commit ID. An abbreviated hash argument will be expanded to a full SHA1 hash automatically, provided the abbreviation is unique. .It Fl r Ar repository-path blob - c05635e7b6ff95fde0b9d9366149284a8ce8a5d2 blob + e30bb0b425d521c0d92f3f3300537958da8a6919 --- got/got.c +++ got/got.c @@ -825,7 +825,20 @@ resolve_commit_arg(struct got_object_id **commit_id, { const struct got_error *err; struct got_reference *ref; + struct got_tag_object *tag; + err = got_repo_object_match_tag(&tag, commit_id_arg, + GOT_OBJ_TYPE_COMMIT, repo); + if (err == NULL) { + *commit_id = got_object_id_dup( + got_object_tag_get_object_id(tag)); + if (*commit_id == NULL) + err = got_error_from_errno("got_object_id_dup"); + got_object_tag_close(tag); + return err; + } else if (err->code != GOT_ERR_NO_OBJ) + return err; + err = got_ref_open(&ref, repo, commit_id_arg, 0); if (err == NULL) { err = got_ref_resolve(commit_id, repo, ref); blob - 6b8435a8f69b24786fa17e77464465e2339529e4 blob + 16cdca51a48b0e15d4516534fe4efec46fe384af --- include/got_repository.h +++ include/got_repository.h @@ -16,6 +16,7 @@ struct got_repository; struct got_pathlist_head; +struct got_tag_object; /* Open and close repositories. */ const struct got_error *got_repo_open(struct got_repository**, const char *); @@ -63,6 +64,13 @@ const struct got_error *got_repo_init(const char *); const struct got_error *got_repo_match_object_id_prefix(struct got_object_id **, const char *, int, struct got_repository *); +/* + * Attempt to find a tag object with a given name and target object type. + * Return GOT_ERR_NO_OBJ if no matching tag can be found. + */ +const struct got_error *got_repo_object_match_tag(struct got_tag_object **, + const char *, int, struct got_repository *); + /* A callback function which is invoked when a path is imported. */ typedef const struct got_error *(*got_repo_import_cb)(void *, const char *); blob - 8f6a04258f4bc1a53b5c23649fecf82243266b08 blob + 60e8e27f0ead8fbd0ef767acaaa4a7618826a10d --- lib/repository.c +++ lib/repository.c @@ -1111,7 +1111,51 @@ done: *id = NULL; } else if (*id == NULL) err = got_error(GOT_ERR_NO_OBJ); + + return err; +} + +const struct got_error * +got_repo_object_match_tag(struct got_tag_object **tag, const char *name, + int obj_type, struct got_repository *repo) +{ + const struct got_error *err; + struct got_reflist_head refs; + struct got_reflist_entry *re; + struct got_object_id *tag_id; + + SIMPLEQ_INIT(&refs); + *tag = NULL; + + err = got_ref_list(&refs, repo); + if (err) + return err; + + SIMPLEQ_FOREACH(re, &refs, entry) { + const char *refname; + refname = got_ref_get_name(re->ref); + if (got_ref_is_symbolic(re->ref) || + strncmp("refs/tags/", refname, 10) != 0) + continue; + refname += 10; + if (strcmp(refname, name) != 0) + continue; + err = got_ref_resolve(&tag_id, repo, re->ref); + if (err) + break; + err = got_object_open_as_tag(tag, repo, tag_id); + free(tag_id); + if (err) + break; + if (got_object_tag_get_object_type(*tag) == obj_type) + break; + got_object_tag_close(*tag); + *tag = NULL; + } + got_ref_list_free(&refs); + if (err == NULL && *tag == NULL) + err = got_error(GOT_ERR_NO_OBJ); return err; } blob - e1dbec4d3615974a53043664c84ecffb8591e6d1 blob + ccd7980f4fa22dcd0dfb01b2e5a895ca27b01246 --- regress/cmdline/blame.sh +++ regress/cmdline/blame.sh @@ -57,4 +57,45 @@ function test_blame_basic { test_done "$testroot" "$ret" } +function test_blame_tag { + local testroot=`test_init blame_tag` + local tag=1.0.0 + + got checkout $testroot/repo $testroot/wt > /dev/null + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + echo 1 > $testroot/wt/alpha + (cd $testroot/wt && got commit -m "change 1" > /dev/null) + local commit1=`git_show_head $testroot/repo` + + echo 2 >> $testroot/wt/alpha + (cd $testroot/wt && got commit -m "change 2" > /dev/null) + local commit2=`git_show_head $testroot/repo` + + (cd $testroot/repo && git tag -a -m "test" $tag) + + echo 3 >> $testroot/wt/alpha + (cd $testroot/wt && got commit -m "change 3" > /dev/null) + local commit3=`git_show_head $testroot/repo` + + (cd $testroot/wt && got blame -c $tag alpha > $testroot/stdout) + + local short_commit1=`trim_obj_id 32 $commit1` + local short_commit2=`trim_obj_id 32 $commit2` + + echo "$short_commit1 1" > $testroot/stdout.expected + echo "$short_commit2 2" >> $testroot/stdout.expected + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi + test_done "$testroot" "$ret" +} + run_test test_blame_basic +run_test test_blame_tag blob - 2f03e3f22ca34a05036830cc0af2ab635a0799fb blob + b967040ffd7b21b1c0cda99ba37b84c58b0a8cb3 --- regress/cmdline/checkout.sh +++ regress/cmdline/checkout.sh @@ -210,8 +210,51 @@ function test_checkout_commit_from_wrong_branch { test_done "$testroot" "$ret" } +function test_checkout_tag { + local testroot=`test_init checkout_tag` + local tag="1.0.0" + + (cd $testroot/repo && git tag -a -m "test" $tag) + + echo "A $testroot/wt/alpha" > $testroot/stdout.expected + echo "A $testroot/wt/beta" >> $testroot/stdout.expected + echo "A $testroot/wt/epsilon/zeta" >> $testroot/stdout.expected + echo "A $testroot/wt/gamma/delta" >> $testroot/stdout.expected + echo "Now shut up and hack" >> $testroot/stdout.expected + + got checkout -c $tag $testroot/repo $testroot/wt > $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo "alpha" > $testroot/content.expected + echo "beta" >> $testroot/content.expected + echo "zeta" >> $testroot/content.expected + echo "delta" >> $testroot/content.expected + cat $testroot/wt/alpha $testroot/wt/beta $testroot/wt/epsilon/zeta \ + $testroot/wt/gamma/delta > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + fi + test_done "$testroot" "$ret" +} + run_test test_checkout_basic run_test test_checkout_dir_exists run_test test_checkout_dir_not_empty run_test test_checkout_sets_xbit run_test test_checkout_commit_from_wrong_branch +run_test test_checkout_tag blob - 11f0724fc95a705812f15b4d42b2e204fbaebb8f blob + fa21749675c7093587f9e3be79dea42b3d341fe4 --- regress/cmdline/log.sh +++ regress/cmdline/log.sh @@ -110,6 +110,33 @@ function test_log_in_worktree { test_done "$testroot" "0" } +function test_log_tag { + local testroot=`test_init log_tag` + local commit_id=`git_show_head $testroot/repo` + local tag="1.0.0" + + got checkout $testroot/repo $testroot/wt > /dev/null + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + + (cd $testroot/repo && git tag -a -m "test" $tag) + + echo "commit $commit_id (master)" > $testroot/stdout.expected + (cd $testroot/wt && got log -l1 -c $tag | grep ^commit \ + > $testroot/stdout) + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi + test_done "$testroot" "$ret" +} + + run_test test_log_in_repo run_test test_log_in_bare_repo run_test test_log_in_worktree +run_test test_log_tag blob - e4c536758c2ec2596e840c7ca32b464bf1864be3 blob + ec4a92da12fc55731c312cca75266994641a944b --- regress/cmdline/update.sh +++ regress/cmdline/update.sh @@ -1500,6 +1500,39 @@ function test_update_bumps_base_commit_id { local head_rev=`git_show_head $testroot/repo` echo "M epsilon/zeta" > $testroot/stdout.expected echo "Created commit $head_rev" >> $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + test_done "$testroot" "$ret" +} + +function test_update_tag { + local testroot=`test_init update_tag` + local tag="1.0.0" + + got checkout $testroot/repo $testroot/wt > /dev/null + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + + echo "modified alpha" > $testroot/repo/alpha + git_commit $testroot/repo -m "modified alpha" + (cd $testroot/repo && git tag -m "test" -a $tag) + + echo "U alpha" > $testroot/stdout.expected + echo -n "Updated to commit " >> $testroot/stdout.expected + git_show_head $testroot/repo >> $testroot/stdout.expected + echo >> $testroot/stdout.expected + + (cd $testroot/wt && got update -c $tag > $testroot/stdout) + cmp -s $testroot/stdout.expected $testroot/stdout ret="$?" if [ "$ret" != "0" ]; then @@ -1508,6 +1541,14 @@ function test_update_bumps_base_commit_id { return 1 fi + echo "modified alpha" > $testroot/content.expected + cat $testroot/wt/alpha > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + fi test_done "$testroot" "$ret" } @@ -1540,3 +1581,4 @@ run_test test_update_moved_branch_ref run_test test_update_to_another_branch run_test test_update_to_commit_on_wrong_branch run_test test_update_bumps_base_commit_id +run_test test_update_tag