commit 4390d6c167c321d53ad289366248325c8e0bfcf5 from: Mark Jamsek date: Tue Jul 18 14:37:13 2023 UTC got: enable more commands to accept commit keywords More work adding commit keyword support to the blame, cat, ref, tag, and tree commands. With this, all Got commands that take a option argument or operand now support keywords. Regress flub saved by op! fixes + ok op@ commit - 6b483b319568902f913006779dad34b89cb4c979 commit + 4390d6c167c321d53ad289366248325c8e0bfcf5 blob - 086e9968300ec8161ed6529d40471881657f0b98 blob + 490b0fc0306064290fd3f914cb132d0add57258c --- got/got.1 +++ got/got.1 @@ -1191,6 +1191,46 @@ The expected argument is a commit ID SHA1 hash or an e 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. +.Pp +The special +.Ar commit +keywords +.Qq :base +and +.Qq :head +can also be used to represent the work tree's base commit +and branch head, respectively. +The former is only valid if invoked in a work tree, while the latter will +resolve to the tip of the work tree's current branch if invoked in a +work tree, otherwise it will resolve to the repository's HEAD reference. +Keywords and references may be appended with +.Qq :+ +or +.Qq :- +modifiers and an optional integer N to denote the +Nth descendant or antecedent by first parent traversal, respectively; +for example, +.Sy :head:-2 +denotes the work tree branch head's 2nd generation ancestor, and +.Sy :base:+4 +denotes the 4th generation descendant of the work tree's base commit. +Similarly, +.Sy xyz:-5 +will denote the 5th generation ancestor of the commit resolved by the +.Qq xyz +reference. +A +.Qq :+ +or +.Qq :- +modifier without a trailing integer has an implicit +.Qq 1 +appended +.Po e.g., +.Sy :base:+ +is equivalent to +.Sy :base:+1 +.Pc . .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 @@ -1238,6 +1278,46 @@ The expected argument is a commit ID SHA1 hash or an e 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. +.Pp +The special +.Ar commit +keywords +.Qq :base +and +.Qq :head +can also be used to represent the work tree's base commit +and branch head, respectively. +The former is only valid if invoked in a work tree, while the latter will +resolve to the tip of the work tree's current branch if invoked in a +work tree, otherwise it will resolve to the repository's HEAD reference. +Keywords and references may be appended with +.Qq :+ +or +.Qq :- +modifiers and an optional integer N to denote the +Nth descendant or antecedent by first parent traversal, respectively; +for example, +.Sy :head:-2 +denotes the work tree branch head's 2nd generation ancestor, and +.Sy :base:+4 +denotes the 4th generation descendant of the work tree's base commit. +Similarly, +.Sy spam:-3 +will denote the 3rd generation ancestor of the commit resolved by the +.Qq spam +reference. +A +.Qq :+ +or +.Qq :- +modifier without a trailing integer has an implicit +.Qq 1 +appended +.Po e.g., +.Sy :base:+ +is equivalent to +.Sy :base:+1 +.Pc . .It Fl i Show object IDs of files (blob objects) and directories (tree objects). .It Fl R @@ -1276,10 +1356,48 @@ The reference with the specified .Ar name will point at the specified .Ar object . +.Pp 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. +argument is an ID SHA1 hash or an existing reference or tag name +or a keyword which will be resolved to the ID of a corresponding commit, +tree, tag, or blob object. +An abbreviated hash argument will be expanded to a full SHA1 hash +automatically, provided the abbreviation is unique. +The keywords +.Qq :base +and +.Qq :head +resolve to the work tree's base commit and branch head, respectively. +The former is only valid if invoked in a work tree, while the latter will +resolve to the tip of the work tree's current branch if invoked in a +work tree, otherwise it will resolve to the repository's HEAD reference. +Keywords and reference names may be appended with +.Qq :+ +or +.Qq :- +modifiers and an optional integer N to denote the +Nth descendant or antecedent by first parent traversal, respectively; +for example, +.Sy :head:-2 +denotes the work tree branch head's 2nd generation ancestor, and +.Sy tagged:-3 +will denote the 3rd generation ancestor of the commit resolved by the +.Qq tagged +reference. +If an integer does not follow the +.Qq :+ +or +.Qq :- +modifier, a +.Qq 1 +is implicitly appended +.Po e.g., +.Sy :head:- +is equivalent to +.Sy :head:-1 +.Pc . +.Pp Cannot be used together with any other options except .Fl r . .It Fl d @@ -1520,6 +1638,46 @@ argument is a commit ID SHA1 hash or an existing refer 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. +.Pp +The special +.Ar commit +keywords +.Qq :base +and +.Qq :head +can also be used to represent the work tree's base commit +and branch head, respectively. +The former is only valid if invoked in a work tree, while the latter will +resolve to the tip of the work tree's current branch if invoked in a +work tree, otherwise it will resolve to the repository's HEAD reference. +Keywords and references may be appended with +.Qq :+ +or +.Qq :- +modifiers and an optional integer N to denote the +Nth descendant or antecedent by first parent traversal, respectively; +for example, +.Sy :head:-2 +denotes the work tree branch head's 2nd generation ancestor, and +.Sy :base:+4 +denotes the 4th generation descendant of the work tree's base commit. +Similarly, +.Sy eggs:-3 +will denote the 3rd generation ancestor of the commit resolved by the +.Qq eggs +reference. +A +.Qq :+ +or +.Qq :- +modifier without a trailing integer has an implicit +.Qq 1 +appended +.Po e.g., +.Sy :base:+ +is equivalent to +.Sy :base:+1 +.Pc . .It Fl l List all existing tags in the repository instead of creating a new tag. If a @@ -3475,6 +3633,46 @@ The expected argument is a commit ID SHA1 hash or an e 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. +.Pp +The special +.Ar commit +keywords +.Qq :base +and +.Qq :head +can also be used to represent the work tree's base commit +and branch head, respectively. +The former is only valid if invoked in a work tree, while the latter will +resolve to the tip of the work tree's current branch if invoked in a +work tree, otherwise it will resolve to the repository's HEAD reference. +Keywords and references may be appended with +.Qq :+ +or +.Qq :- +modifiers and an optional integer N to denote the +Nth descendant or antecedent by first parent traversal, respectively; +for example, +.Sy :head:-2 +denotes the work tree branch head's 2nd generation ancestor, and +.Sy :base:+4 +denotes the 4th generation descendant of the work tree's base commit. +Similarly, +.Sy quux:-8 +will denote the 8th generation ancestor of the commit resolved by the +.Qq quux +reference. +A +.Qq :+ +or +.Qq :- +modifier without a trailing integer has an implicit +.Qq 1 +appended +.Po e.g., +.Sy :base:+ +is equivalent to +.Sy :base:+1 +.Pc . .It Fl P Interpret all arguments as paths only. This option can be used to resolve ambiguity in cases where paths blob - f0cea264f130ba792c3c19b55d2632c8a81f9735 blob + d762fe811564e7d6320b7826fb5a9680e3900517 --- got/got.c +++ got/got.c @@ -5721,7 +5721,7 @@ cmd_blame(int argc, char *argv[]) struct got_object_id *commit_id = NULL; struct got_commit_object *commit = NULL; struct got_blob_object *blob = NULL; - char *commit_id_str = NULL; + char *commit_id_str = NULL, *keyword_idstr = NULL; struct blame_cb_args bca; int ch, obj_type, i, fd1 = -1, fd2 = -1, fd3 = -1; off_t filesize; @@ -5840,11 +5840,20 @@ cmd_blame(int argc, char *argv[]) goto done; } else { struct got_reflist_head refs; + TAILQ_INIT(&refs); error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL); if (error) + goto done; + + error = got_keyword_to_idstr(&keyword_idstr, commit_id_str, + repo, worktree); + if (error != NULL) goto done; + if (keyword_idstr != NULL) + commit_id_str = keyword_idstr; + error = got_repo_match_object_id(&commit_id, NULL, commit_id_str, GOT_OBJ_TYPE_COMMIT, &refs, repo); got_ref_list_free(&refs); @@ -5937,6 +5946,7 @@ cmd_blame(int argc, char *argv[]) repo, GOT_DIFF_ALGORITHM_PATIENCE, blame_cb, &bca, check_cancelled, NULL, fd2, fd3, f1, f2); done: + free(keyword_idstr); free(in_repo_path); free(link_target); free(repo_path); @@ -6112,7 +6122,7 @@ cmd_tree(int argc, char *argv[]) char *cwd = NULL, *repo_path = NULL, *in_repo_path = NULL; struct got_object_id *commit_id = NULL; struct got_commit_object *commit = NULL; - char *commit_id_str = NULL; + char *commit_id_str = NULL, *keyword_idstr = NULL; int show_ids = 0, recurse = 0; int ch; int *pack_fds = NULL; @@ -6239,11 +6249,20 @@ cmd_tree(int argc, char *argv[]) goto done; } else { struct got_reflist_head refs; + TAILQ_INIT(&refs); error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL); if (error) goto done; + + error = got_keyword_to_idstr(&keyword_idstr, commit_id_str, + repo, worktree); + if (error != NULL) + goto done; + if (keyword_idstr != NULL) + commit_id_str = keyword_idstr; + error = got_repo_match_object_id(&commit_id, NULL, commit_id_str, GOT_OBJ_TYPE_COMMIT, &refs, repo); got_ref_list_free(&refs); @@ -6264,6 +6283,7 @@ cmd_tree(int argc, char *argv[]) error = print_tree(in_repo_path, commit, show_ids, recurse, in_repo_path, repo); done: + free(keyword_idstr); free(in_repo_path); free(repo_path); free(cwd); @@ -6585,7 +6605,7 @@ cmd_ref(int argc, char *argv[]) char *cwd = NULL, *repo_path = NULL; int ch, do_list = 0, do_delete = 0, sort_by_time = 0; const char *obj_arg = NULL, *symref_target= NULL; - char *refname = NULL; + char *refname = NULL, *keyword_idstr = NULL; int *pack_fds = NULL; #ifndef PROFILE @@ -6724,6 +6744,14 @@ cmd_ref(int argc, char *argv[]) else { if (obj_arg == NULL) usage_ref(); + + error = got_keyword_to_idstr(&keyword_idstr, obj_arg, + repo, worktree); + if (error != NULL) + goto done; + if (keyword_idstr != NULL) + obj_arg = keyword_idstr; + error = add_ref(repo, refname, obj_arg); } done: @@ -6743,6 +6771,7 @@ done: } free(cwd); free(repo_path); + free(keyword_idstr); return error; } @@ -7629,7 +7658,7 @@ cmd_tag(int argc, char *argv[]) struct got_repository *repo = NULL; struct got_worktree *worktree = NULL; char *cwd = NULL, *repo_path = NULL, *commit_id_str = NULL; - char *gitconfig_path = NULL, *tagger = NULL; + char *gitconfig_path = NULL, *tagger = NULL, *keyword_idstr = NULL; char *allowed_signers = NULL, *revoked_signers = NULL; const char *signer_id = NULL; const char *tag_name = NULL, *commit_id_arg = NULL, *tagmsg = NULL; @@ -7814,7 +7843,13 @@ cmd_tag(int argc, char *argv[]) error = got_object_id_str(&commit_id_str, commit_id); free(commit_id); if (error) + goto done; + } else { + error = got_keyword_to_idstr(&keyword_idstr, + commit_id_arg, repo, worktree); + if (error != NULL) goto done; + commit_id_str = keyword_idstr; } if (worktree) { @@ -14043,6 +14078,7 @@ cmd_cat(int argc, char *argv[]) struct got_repository *repo = NULL; struct got_worktree *worktree = NULL; char *cwd = NULL, *repo_path = NULL, *label = NULL; + char *keyword_idstr = NULL; const char *commit_id_str = NULL; struct got_object_id *id = NULL, *commit_id = NULL; struct got_commit_object *commit = NULL; @@ -14104,9 +14140,11 @@ cmd_cat(int argc, char *argv[]) goto done; } - /* Release work tree lock. */ - got_worktree_close(worktree); - worktree = NULL; + if (commit_id_str == NULL) { + /* Release work tree lock. */ + got_worktree_close(worktree); + worktree = NULL; + } } } @@ -14129,7 +14167,18 @@ cmd_cat(int argc, char *argv[]) if (error) goto done; - if (commit_id_str == NULL) + if (commit_id_str != NULL) { + error = got_keyword_to_idstr(&keyword_idstr, commit_id_str, + repo, worktree); + if (error != NULL) + goto done; + if (keyword_idstr != NULL) + commit_id_str = keyword_idstr; + if (worktree != NULL) { + got_worktree_close(worktree); + worktree = NULL; + } + } else commit_id_str = GOT_REF_HEAD; error = got_repo_match_object_id(&commit_id, NULL, commit_id_str, GOT_OBJ_TYPE_COMMIT, &refs, repo); @@ -14193,6 +14242,7 @@ done: free(label); free(id); free(commit_id); + free(keyword_idstr); if (commit) got_object_commit_close(commit); if (worktree) blob - 106ff741cc1c94c5becd70905a3da2249b9dc826 blob + a52ad3f5f3953de8ae74d10f7a9f2b3d9f880cc1 --- regress/cmdline/blame.sh +++ regress/cmdline/blame.sh @@ -982,10 +982,139 @@ EOF ret=$? if [ $ret -ne 0 ]; then diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + blame_cmp "$testroot" "alpha" + ret=$? + test_done "$testroot" "$ret" +} + +test_blame_commit_keywords() { + local testroot=$(test_init blame_commit_keywords) + local repo="$testroot/repo" + local wt="$testroot/wt" + local id=$(git_show_head "$repo") + + set -A ids "$(trim_obj_id 32 $id)" + + # :base requires work tree + echo "got: '-c :base' requires work tree" > "$testroot/stderr.expected" + got blame -r "$repo" -c:base alpha 2> "$testroot/stderr" + ret=$? + if [ $ret -eq 0 ]; then + echo "blame command succeeded unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + cmp -s "$testroot/stderr.expected" "$testroot/stderr" + ret=$? + if [ $ret -ne 0 ]; then + diff -u "$testroot/stderr.expected" "$testroot/stderr" + test_done "$testroot" "$ret" + return 1 + fi + + got checkout "$repo" "$wt" > /dev/null + ret=$? + if [ $ret -ne 0 ]; then + test_done "$testroot" "$ret" + return 1 + fi + + echo -n > "$wt/alpha" + + for i in $(seq 8); do + echo "change $i" >> "$wt/alpha" + + (cd "$wt" && got ci -m "commit $i" > /dev/null) + ret=$? + if [ $ret -ne 0 ]; then + echo "commit failed unexpectedly" >&2 + test_done "$testroot" "$ret" + return 1 + fi + + id=$(git_show_head "$repo") + set -- "$ids" "$(trim_obj_id 32 $id)" + ids=$* + done + + local author_time=$(git_show_author_time "$repo") + local d=$(date -u -r $author_time +"%G-%m-%d") + + got blame -r "$repo" -c:head:-8 alpha > "$testroot/stdout" + echo "1) $(pop_id 1 $ids) $d $GOT_AUTHOR_8 alpha" > \ + "$testroot/stdout.expected" + + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u "$testroot/stdout.expected" "$testroot/stdout" test_done "$testroot" "$ret" return 1 fi + (cd "$wt" && got blame -cmaster:-5 alpha > "$testroot/stdout") + + echo "1) $(pop_id 2 $ids) $d $GOT_AUTHOR_8 change 1" > \ + "$testroot/stdout.expected" + echo "2) $(pop_id 3 $ids) $d $GOT_AUTHOR_8 change 2" >> \ + "$testroot/stdout.expected" + echo "3) $(pop_id 4 $ids) $d $GOT_AUTHOR_8 change 3" >> \ + "$testroot/stdout.expected" + + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u "$testroot/stdout.expected" "$testroot/stdout" + test_done "$testroot" "$ret" + return 1 + fi + + (cd "$wt" && got blame -c:head:-4 alpha > "$testroot/stdout") + + echo "1) $(pop_id 2 $ids) $d $GOT_AUTHOR_8 change 1" > \ + "$testroot/stdout.expected" + echo "2) $(pop_id 3 $ids) $d $GOT_AUTHOR_8 change 2" >> \ + "$testroot/stdout.expected" + echo "3) $(pop_id 4 $ids) $d $GOT_AUTHOR_8 change 3" >> \ + "$testroot/stdout.expected" + echo "4) $(pop_id 5 $ids) $d $GOT_AUTHOR_8 change 4" >> \ + "$testroot/stdout.expected" + + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u "$testroot/stdout.expected" "$testroot/stdout" + test_done "$testroot" "$ret" + return 1 + fi + + (cd "$wt" && got up -c:head:-8 > /dev/null) + (cd "$wt" && got blame -c:base:+5 alpha > "$testroot/stdout") + + echo "1) $(pop_id 2 $ids) $d $GOT_AUTHOR_8 change 1" > \ + "$testroot/stdout.expected" + echo "2) $(pop_id 3 $ids) $d $GOT_AUTHOR_8 change 2" >> \ + "$testroot/stdout.expected" + echo "3) $(pop_id 4 $ids) $d $GOT_AUTHOR_8 change 3" >> \ + "$testroot/stdout.expected" + echo "4) $(pop_id 5 $ids) $d $GOT_AUTHOR_8 change 4" >> \ + "$testroot/stdout.expected" + echo "5) $(pop_id 6 $ids) $d $GOT_AUTHOR_8 change 5" >> \ + "$testroot/stdout.expected" + + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u "$testroot/stdout.expected" "$testroot/stdout" + test_done "$testroot" "$ret" + return 1 + fi + blame_cmp "$testroot" "alpha" ret=$? test_done "$testroot" "$ret" @@ -1005,3 +1134,4 @@ run_test test_blame_added_on_branch run_test test_blame_submodule run_test test_blame_symlink run_test test_blame_lines_shifted_skip +run_test test_blame_commit_keywords blob - 2e37e870ce0e06673c3f701e940ebdd2438b8c38 blob + 4b561d845788314e3f478551421310e1934634f2 --- regress/cmdline/cat.sh +++ regress/cmdline/cat.sh @@ -331,10 +331,107 @@ test_cat_symlink() { ret=$? if [ $ret -ne 0 ]; then diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + test_done "$testroot" "$ret" +} + +test_cat_commit_keywords() { + local testroot=$(test_init cat_commit_keywords) + local repo="$testroot/repo" + local wt="$testroot/wt" + + # :base requires work tree + echo "got: '-c :base' requires work tree" > "$testroot/stderr.expected" + got cat -r "$repo" -c:base alpha 2> "$testroot/stderr" + ret=$? + if [ $ret -eq 0 ]; then + echo "cat command succeeded unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + cmp -s "$testroot/stderr.expected" "$testroot/stderr" + ret=$? + if [ $ret -ne 0 ]; then + diff -u "$testroot/stderr.expected" "$testroot/stderr" + test_done "$testroot" "$ret" + return 1 + fi + + got checkout "$repo" "$wt" > /dev/null + ret=$? + if [ $ret -ne 0 ]; then + test_done "$testroot" "$ret" + return 1 + fi + + for i in $(seq 8); do + echo "change $i" > "$wt/alpha" + echo "delta $i" > "$wt/gamma/delta" + + (cd "$wt" && got ci -m "commit $i" > /dev/null) + ret=$? + if [ $ret -ne 0 ]; then + echo "commit failed unexpectedly" >&2 + test_done "$testroot" "$ret" + return 1 + fi + + local delta_id=$(got tree -r "$repo" -i gamma | \ + grep 'delta$' | cut -d' ' -f 1) + set -- "$delta_ids" "$delta_id" + delta_ids=$* + done + + # cat blob by path + echo "change 6" > "$testroot/stdout.expected" + (cd "$wt" && got cat -c:head:-2 alpha > "$testroot/stdout") + cmp -s "$testroot/stdout.expected" "$testroot/stdout" + ret=$? + if [ $ret -ne 0 ]; then + diff -u "$testroot/stdout.expected" "$testroot/stdout" test_done "$testroot" "$ret" return 1 fi + # cat blob by path with -r repo + echo "delta 7" > "$testroot/stdout.expected" + got cat -r "$repo" -c:head:- gamma/delta > "$testroot/stdout" + cmp -s "$testroot/stdout.expected" "$testroot/stdout" + ret=$? + if [ $ret -ne 0 ]; then + diff -u "$testroot/stdout.expected" "$testroot/stdout" + test_done "$testroot" "$ret" + return 1 + fi + + # cat tree by path + echo "$(pop_id 4 $delta_ids) 0100644 delta" > \ + "$testroot/stdout.expected" + (cd "$wt" && got cat -c:base:-4 gamma > "$testroot/stdout") + cmp -s "$testroot/stdout.expected" "$testroot/stdout" + ret=$? + if [ $ret -ne 0 ]; then + diff -u "$testroot/stdout.expected" "$testroot/stdout" + test_done "$testroot" "$ret" + return 1 + fi + + # cat blob by path with -P + echo "delta 4" > "$testroot/stdout.expected" + (cd "$wt" && got up -c:base:-8 > /dev/null) + (cd "$wt" && got cat -c:base:+4 -P gamma/delta > "$testroot/stdout") + cmp -s "$testroot/stdout.expected" "$testroot/stdout" + ret=$? + if [ $ret -ne 0 ]; then + diff -u "$testroot/stdout.expected" "$testroot/stdout" + test_done "$testroot" "$ret" + return 1 + fi + test_done "$testroot" "$ret" } @@ -344,3 +441,4 @@ run_test test_cat_path run_test test_cat_submodule run_test test_cat_submodule_of_same_repo run_test test_cat_symlink +run_test test_cat_commit_keywords blob - b86a51bf2a102808072428b8f575dc6a449b6769 blob + 40d49081040f0fd5396d77e82ad19b2f5c960858 --- regress/cmdline/ref.sh +++ regress/cmdline/ref.sh @@ -438,7 +438,86 @@ test_ref_list() { test_done "$testroot" "$ret" } +test_ref_commit_keywords() { + local testroot=$(test_init ref_commit_keywords) + local repo="$testroot/repo" + local wt="$testroot/wt" + + got checkout "$repo" "$wt" > /dev/null + ret=$? + if [ $ret -ne 0 ]; then + echo "checkout failed unexpectedly" >&2 + test_done "$testroot" "$ret" + return 1 + fi + + for i in $(seq 8); do + echo "alpha change $i" > "$wt/alpha" + + (cd "$wt" && got ci -m "commit number $i" > /dev/null) + ret=$? + if [ $ret -ne 0 ]; then + echo "commit failed unexpectedly" >&2 + test_done "$testroot" "$ret" + return 1 + fi + + set -- "$ids" "$(git_show_head $repo)" + ids=$* + done + + (cd "$wt" && got ref -c:head:-4 refs/heads/head-4) + ret=$? + if [ $ret -ne 0 ]; then + echo "got ref command failed unexpectedly" + test_done "$testroot" "$ret" + return 1 + fi + + (cd "$wt" && got up -c head-4 > /dev/null) + ret=$? + if [ $ret -ne 0 ]; then + echo "got checkout command failed unexpectedly" + test_done "$testroot" "$ret" + return 1 + fi + + (cd "$wt" && got ref -c:base:+2 refs/heads/base+2) + ret=$? + if [ $ret -ne 0 ]; then + echo "got ref command failed unexpectedly" + test_done "$testroot" "$ret" + return 1 + fi + + (cd "$wt" && got ref -cmaster:- refs/heads/master-) + ret=$? + if [ $ret -ne 0 ]; then + echo "got ref command failed unexpectedly" + test_done "$testroot" "$ret" + return 1 + fi + + echo "HEAD: refs/heads/master" > $testroot/stdout.expected + echo -n "refs/got/worktree/base-" >> $testroot/stdout.expected + cat "$wt/.got/uuid" | tr -d '\n' >> $testroot/stdout.expected + echo ": $(pop_id 4 $ids)" >> $testroot/stdout.expected + echo "refs/heads/base+2: $(pop_id 6 $ids)" >> $testroot/stdout.expected + echo "refs/heads/head-4: $(pop_id 4 $ids)" >> $testroot/stdout.expected + echo "refs/heads/master: $(pop_id 8 $ids)" >> $testroot/stdout.expected + echo "refs/heads/master-: $(pop_id 7 $ids)" >> $testroot/stdout.expected + + got ref -r "$repo" -l > $testroot/stdout + cmp -s $testroot/stdout $testroot/stdout.expected + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi + test_done "$testroot" "$ret" +} + test_parseargs "$@" run_test test_ref_create run_test test_ref_delete run_test test_ref_list +run_test test_ref_commit_keywords blob - 20ccfdcdf9a3a29fed86ad247da1be233bf3945a blob + 58cc28c89680ed685a25bf71155506a5c55715a3 --- regress/cmdline/tag.sh +++ regress/cmdline/tag.sh @@ -462,7 +462,110 @@ test_tag_create_ssh_signed_missing_key() { ret=$? if [ $ret -ne 0 ]; then diff -u $testroot/stderr.expected $testroot/stderr + fi + test_done "$testroot" "$ret" +} + +test_tag_commit_keywords() { + local testroot=$(test_init tag_commit_keywords) + local repo="$testroot/repo" + local wt="$testroot/wt" + local commit_id=$(git_show_head "$repo") + local tag=1.0.0 + local tag2=2.0.0 + + echo "alphas" > "$repo/alpha" + git_commit "$repo" -m "alphas" + + # create tag based on first gen ancestor of the repository's HEAD + got tag -m 'v1.0.0' -r "$repo" -c:head:- "$tag" > "$testroot/stdout" + ret=$? + if [ $ret -ne 0 ]; then + echo "got ref command failed unexpectedly" + test_done "$testroot" "$ret" + return 1 + fi + + tag_id=$(got ref -r "$repo" -l \ + | grep "^refs/tags/$tag" | tr -d ' ' | cut -d: -f2) + echo "Created tag $tag_id" > "$testroot/stdout.expected" + cmp -s "$testroot/stdout" "$testroot/stdout.expected" + ret=$? + if [ $ret -ne 0 ]; then + diff -u "$testroot/stdout.expected" "$testroot/stdout" + test_done "$testroot" "$ret" + return 1 + fi + + tag_commit=$(got cat -r "$repo" "$tag" | grep ^object | cut -d' ' -f2) + if [ "$tag_commit" != "$commit_id" ]; then + echo "wrong commit was tagged" >&2 + test_done "$testroot" "1" + return 1 + fi + + got checkout -c "$tag" "$repo" "$wt" >/dev/null + ret=$? + if [ $ret -ne 0 ]; then + echo "got checkout command failed unexpectedly" + test_done "$testroot" "$ret" + return 1 + fi + + # create new tag based on the base commit's 2nd gen descendant + (cd "$wt" && got up > /dev/null) + echo 'foo' > "$wt/alpha" + echo 'boo' > "$wt/beta" + echo 'hoo' > "$wt/gamma/delta" + (cd "$wt" && got commit -m foo alpha > /dev/null) + (cd "$wt" && got commit -m boo beta > /dev/null) + (cd "$wt" && got commit -m hoo gamma/delta > /dev/null) + local head_id=$(git_show_branch_head "$repo") + (cd "$wt" && got up -c:base:-2 > /dev/null) + local base_id=$(cd "$wt" && got info | grep base | cut -d' ' -f5) + + (cd "$wt" && got tag -m 'v2.0.0' -c:base:+2 $tag2 > "$testroot/stdout") + ret=$? + if [ $ret -ne 0 ]; then + test_done "$testroot" "$ret" + return 1 fi + + tag_id2=$(got ref -r "$repo" -l \ + | grep "^refs/tags/$tag2" | tr -d ' ' | cut -d: -f2) + echo "Created tag $tag_id2" > $testroot/stdout.expected + + cmp -s $testroot/stdout $testroot/stdout.expected + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + tag2_commit=$(got cat -r "$repo" "$tag2" | grep ^object | cut -d' ' -f2) + if [ "$tag2_commit" != "$head_id" ]; then + echo "wrong commit was tagged" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo "HEAD: refs/heads/master" > $testroot/stdout.expected + echo -n "refs/got/worktree/base-" >> $testroot/stdout.expected + cat "$wt/.got/uuid" | tr -d '\n' >> $testroot/stdout.expected + echo ": $base_id" >> $testroot/stdout.expected + echo "refs/heads/master: $head_id" >> $testroot/stdout.expected + echo "refs/tags/$tag: $tag_id" >> $testroot/stdout.expected + echo "refs/tags/$tag2: $tag_id2" >> $testroot/stdout.expected + + got ref -r "$repo" -l > $testroot/stdout + + cmp -s $testroot/stdout $testroot/stdout.expected + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi + test_done "$testroot" "$ret" } @@ -472,3 +575,4 @@ run_test test_tag_list run_test test_tag_list_lightweight run_test test_tag_create_ssh_signed run_test test_tag_create_ssh_signed_missing_key +run_test test_tag_commit_keywords blob - 5fa15d25ce341431bf7f64d2a7236abc04edb893 blob + 62eb987ba62876f4026cd0d830472dd2a3060c20 --- regress/cmdline/tree.sh +++ regress/cmdline/tree.sh @@ -146,8 +146,131 @@ test_tree_submodule_of_same_repo() { test_done "$testroot" "$ret" } +test_tree_commit_keywords() { + local testroot=$(test_init tree_commit_keywords) + local wt="$testroot/wt" + + # :base requires work tree + echo "got: '-c :base' requires work tree" > "$testroot/stderr.expected" + got tree -r "$testroot/repo" -c:base 2> "$testroot/stderr" + ret=$? + if [ $ret -eq 0 ]; then + echo "tree command succeeded unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + cmp -s "$testroot/stderr.expected" "$testroot/stderr" + ret=$? + if [ $ret -ne 0 ]; then + diff -u "$testroot/stderr.expected" "$testroot/stderr" + test_done "$testroot" "$ret" + return 1 + fi + + echo 'alpha' > $testroot/stdout.expected + echo 'beta' >> $testroot/stdout.expected + echo 'epsilon/' >> $testroot/stdout.expected + echo 'gamma/' >> $testroot/stdout.expected + + got tree -r "$testroot/repo" -c:head > "$testroot/stdout" + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + got checkout "$testroot/repo" "$wt" > /dev/null + + ( + cd "$wt" + mkdir bing + echo "foo" > foo + echo "bar" > bar + echo "baz" > baz + echo "bob" > bing/bob + got add foo bar baz bing/bob > /dev/null + got commit -m "add foo" foo > /dev/null + got commit -m "add bar" bar > /dev/null + got commit -m "add baz" baz > /dev/null + got commit -m "add bing/bob" > /dev/null + ) + + echo 'alpha' > $testroot/stdout.expected + echo 'beta' >> $testroot/stdout.expected + echo 'epsilon/' >> $testroot/stdout.expected + echo 'foo' >> $testroot/stdout.expected + echo 'gamma/' >> $testroot/stdout.expected + + (cd "$wt" && got tree -c:base:-3 > $testroot/stdout) + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo 'alpha' > $testroot/stdout.expected + echo 'bar' >> $testroot/stdout.expected + echo 'beta' >> $testroot/stdout.expected + echo 'epsilon/' >> $testroot/stdout.expected + echo 'foo' >> $testroot/stdout.expected + echo 'gamma/' >> $testroot/stdout.expected + + (cd "$wt" && got tree -cmaster:-2 > $testroot/stdout) + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo 'alpha' > $testroot/stdout.expected + echo 'bar' >> $testroot/stdout.expected + echo 'baz' >> $testroot/stdout.expected + echo 'beta' >> $testroot/stdout.expected + echo 'epsilon/' >> $testroot/stdout.expected + echo 'foo' >> $testroot/stdout.expected + echo 'gamma/' >> $testroot/stdout.expected + + (cd "$wt" && got tree -c:head:- > $testroot/stdout) + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo 'alpha' > $testroot/stdout.expected + echo 'bar' >> $testroot/stdout.expected + echo 'baz' >> $testroot/stdout.expected + echo 'beta' >> $testroot/stdout.expected + echo 'bing/' >> $testroot/stdout.expected + echo 'epsilon/' >> $testroot/stdout.expected + echo 'foo' >> $testroot/stdout.expected + echo 'gamma/' >> $testroot/stdout.expected + + (cd "$wt" && got up -c:base:-4 > $testroot/stdout) + (cd "$wt" && got tree -c:base:+4 > $testroot/stdout) + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + test_done "$testroot" "0" +} + test_parseargs "$@" run_test test_tree_basic run_test test_tree_branch run_test test_tree_submodule run_test test_tree_submodule_of_same_repo +run_test test_tree_commit_keywords