From: Mark Jamsek Subject: Re: expand keyword support to more commands To: Omar Polo Cc: Stefan Sperling , gameoftrees@openbsd.org Date: Wed, 19 Jul 2023 00:00:57 +1000 Omar Polo wrote: > On 2023/07/18 22:20:47 +1000, Mark Jamsek wrote: > > Here's the diff for adding commit keywords to the blame, cat, tag, and > > tree commands, which includes some basic test coverage too. > > > > To help review, the man page bits are literal copypastas of the other > > keyword paragraphs with a slight tweak to example reference names. > > reads fine, ok for me Thanks, op! > > I forgot about the ref command, which I'll do next, but that's all that > > remains in got :) > > > > Before starting on temporal expressions, do we want to support various > > formats (e.g., relative terms like yesterday, last month), or keep it > > simple and stick to perhaps YYYYMMDD or full ISO 8601? We can always > > grow the supported keywords, but it would be good to have an idea of > > what we might want to allow. The initial plan was to start with > > YYYYMMDD and take it from there. > > full ISO8601 is quite large and probably not really useful in > practice. YYYYMMDD is used in other parts of the got UI and should be > fine IMHO. > > I've never used CVS date specifications so I'm not sure how much "last > friday" or "a fortnigh ago" is really useful in practice. (have to > admit that the _seem_ to be useful.) I agree with you; I think YYYYMMDD should suffice--at least for the time being. As you mention, this format will also be consistent with other bits like got's and tog's log date field, so it will be easy to cross-reference when building commands. While the relative terms do indeed sound like they might be useful, I'm not sure how much I'd use them in practice. More frequent cvs users would have a more informed opinion of their utility compared to me, though, so I'm happy to defer to their better judgement. Here's the diff adding keyword support to 'got ref', I've rebased it and the above diff you've already reviewed on top of main: ----------------------------------------------- commit c7fbe39e782036117bb95e46766f600b9f49c5c8 (main) from: Mark Jamsek date: Tue Jul 18 13:57:41 2023 UTC add commit keywords to 'got ref' command With this, all Got commands that take a option argument or operand now support keywords. M got/got.1 | 40+ 2- M got/got.c | 10+ 1- M regress/cmdline/ref.sh | 79+ 0- 3 files changed, 129 insertions(+), 3 deletions(-) diff 4373213e55d98f170d7251838f9ec1ebe3626f2d c7fbe39e782036117bb95e46766f600b9f49c5c8 commit - 4373213e55d98f170d7251838f9ec1ebe3626f2d commit + c7fbe39e782036117bb95e46766f600b9f49c5c8 blob - d7d91763a0a7f459379b8ea104739e7c38f7eba5 blob + 490b0fc0306064290fd3f914cb132d0add57258c --- got/got.1 +++ got/got.1 @@ -1356,10 +1356,48 @@ The expected .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 blob - 63e6b694eb21da3f0d1d6c5489c8f548efaee615 blob + d762fe811564e7d6320b7826fb5a9680e3900517 --- got/got.c +++ got/got.c @@ -6605,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 @@ -6744,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: @@ -6763,6 +6771,7 @@ done: } free(cwd); free(repo_path); + free(keyword_idstr); return error; } blob - b86a51bf2a102808072428b8f575dc6a449b6769 blob + 25a0030729467b7d7fd8a9e364331c723db3a4e6 --- regress/cmdline/ref.sh +++ regress/cmdline/ref.sh @@ -438,7 +438,86 @@ test_parseargs "$@" 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 ----------------------------------------------- commit 4373213e55d98f170d7251838f9ec1ebe3626f2d from: Mark Jamsek date: Tue Jul 18 13:57:41 2023 UTC got: enable more commands to accept commit keywords More work adding commit keyword support to the blame, cat, tag, and tree commands. Just the ref command remains in got before adding more expressions, and introducing keywords to tog. ok op@ M got/got.1 | 160+ 0- M got/got.c | 48+ 7- M regress/cmdline/blame.sh | 130+ 0- M regress/cmdline/cat.sh | 98+ 0- M regress/cmdline/tag.sh | 104+ 0- M regress/cmdline/tree.sh | 123+ 0- 6 files changed, 663 insertions(+), 7 deletions(-) diff 6b483b319568902f913006779dad34b89cb4c979 4373213e55d98f170d7251838f9ec1ebe3626f2d commit - 6b483b319568902f913006779dad34b89cb4c979 commit + 4373213e55d98f170d7251838f9ec1ebe3626f2d blob - 086e9968300ec8161ed6529d40471881657f0b98 blob + d7d91763a0a7f459379b8ea104739e7c38f7eba5 --- got/got.1 +++ got/got.1 @@ -1191,6 +1191,46 @@ automatically, provided the abbreviation is unique. 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 @@ automatically, provided the abbreviation is unique. 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 @@ -1520,6 +1600,46 @@ automatically, provided the abbreviation is unique. 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 +3595,46 @@ automatically, provided the abbreviation is unique. 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 + 63e6b694eb21da3f0d1d6c5489c8f548efaee615 --- 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 @@ done: 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 @@ done: 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); @@ -7629,7 +7649,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; @@ -7815,6 +7835,12 @@ cmd_tag(int argc, char *argv[]) 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 +14069,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 +14131,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 +14158,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 +14233,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 @@ -991,6 +991,135 @@ test_parseargs "$@" 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" +} + test_parseargs "$@" run_test test_blame_basic run_test test_blame_tag @@ -1005,3 +1134,4 @@ run_test test_blame_lines_shifted_skip 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 + 050c09307ac69c50f17c243968c77d344f8cf5ac --- regress/cmdline/cat.sh +++ regress/cmdline/cat.sh @@ -338,9 +338,107 @@ test_parseargs "$@" 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" +} + test_parseargs "$@" run_test test_cat_basic 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 - 20ccfdcdf9a3a29fed86ad247da1be233bf3945a blob + 58cc28c89680ed685a25bf71155506a5c55715a3 --- regress/cmdline/tag.sh +++ regress/cmdline/tag.sh @@ -466,9 +466,113 @@ test_parseargs "$@" 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" +} + test_parseargs "$@" run_test test_tag_create 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_parseargs "$@" 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 -- Mark Jamsek GPG: F2FF 13DE 6A06 C471 CA80 E6E2 2930 DC66 86EE CF68