From: Mark Jamsek Subject: Re: got {diff,log,update} -c KEYWORD (cf. svn revision keywords) To: Omar Polo Cc: Stefan Sperling , gameoftrees@openbsd.org Date: Fri, 14 Jul 2023 23:44:08 +1000 Omar Polo wrote: > On 2023/07/14 00:59:15 +1000, Mark Jamsek wrote: > > The below diff makes the discussed changes to the keyword syntax, and > > adds the ":(+|-)[N]" modifier to reference names. This enables: > > > > got up -cmain:-2 # 2nd gen ancestor of main > > got up -cfoo:+N # Nth gen descendant of foo > > got up -c:base:+ # 1st gen descendant of work tree base commit > > got up -c:head:-4 # 4th gen ancestor of HEAD > > got up -cbase:- # 1st gen descendant of ref "base" > > > > Tests and docs have been tweaked to cover the changes, and I have also > > added a little cover for the newly added ability of reference modifiers > > (e.g., -cmain:+). However, I will expand regress to add some contrived > > and non-trivial cases before adding support for temporal expressions and > > further improvements. I wanted to get this out to confirm that we indeed > > do like the syntax and are happy with this direction. > > briefily played with it but it's very nice to have, thank you! > > I guess that we should eventually use this syntax everywhere we accept > a ref (more or less), so it could make sense to define the parsing > code somewhere in lib/ for easier reuse between got, tog, cvg and > gotadmin. > > I can imagine myself using, say, `got patch -c ':last friday' or `gotadmin dump -x main:-3 main >incremental.bundle' Yes, that's the plan! This will be quite a nice convenience across several commands. I was going to wait till expanding support but good idea--no point double handling--I've moved it into lib/ now. > some quick comments on the diff. Thanks, op! I've made a few changes that I think make it a lot nicer, and have added some non-trivial and somewhat contrived tests too. I nixed the hand-rolled overflow code so we use strtonum(3), and made the keyword parsing strict. That lax keyword comparison was by design initially but I forgot to remove it; I was using -cBASED in testing :) Something I just noticed that I like about the ':' delimiters is ^W removes back to the ':', which is handy. And the +/-N works great with tog's count modifier. You can open tog, see which commit it is you want with Nj, and use the same N count (or the headline index-1) in the 'got * -c:head:-N' command! This is going to save a lot of copypasting and misremembering commit ids. It's pretty neat :) diffstat refs/remotes/origin/main refs/heads/main M got/Makefile | 6+ 6- M got/got.1 | 114+ 0- M got/got.c | 37+ 1- M include/got_error.h | 1+ 0- A include/got_keyword.h | 40+ 0- M lib/error.c | 1+ 0- A lib/keyword.c | 263+ 0- M regress/cmdline/common.sh | 6+ 0- M regress/cmdline/diff.sh | 249+ 0- M regress/cmdline/log.sh | 149+ 0- M regress/cmdline/update.sh | 340+ 0- 11 files changed, 1206 insertions(+), 7 deletions(-) diff refs/remotes/origin/main refs/heads/main commit - 5fb50fce7978aa218c87ec7ac6c3f4e7bf20e5b3 commit + 8b2303df6e23cc7b3482116a03c4e40a9b88625c blob - 3a08950d455ea0bc1854f88ea4f006059b16a199 blob + a90f11274f0add12325c0aa1d7c5099b5edc5b83 --- got/Makefile +++ got/Makefile @@ -4,12 +4,12 @@ SRCS= got.c blame.c commit_graph.c delta.c diff.c \ PROG= got SRCS= got.c blame.c commit_graph.c delta.c diff.c \ - diffreg.c error.c fileindex.c object.c object_cache.c \ - object_idset.c object_parse.c opentemp.c path.c pack.c \ - privsep.c reference.c repository.c hash.c worktree.c \ - worktree_open.c inflate.c buf.c rcsutil.c diff3.c lockfile.c \ - deflate.c object_create.c delta_cache.c fetch.c \ - gotconfig.c diff_main.c diff_atomize_text.c \ + diffreg.c error.c fileindex.c keyword.c object.c \ + object_cache.c object_idset.c object_parse.c opentemp.c \ + path.c pack.c privsep.c reference.c repository.c hash.c \ + worktree.c worktree_open.c inflate.c buf.c rcsutil.c \ + diff3.c lockfile.c deflate.c object_create.c delta_cache.c \ + fetch.c gotconfig.c diff_main.c diff_atomize_text.c \ diff_myers.c diff_output.c diff_output_plain.c \ diff_output_unidiff.c diff_output_edscript.c \ diff_patience.c send.c deltify.c pack_create.c dial.c \ blob - ea3b833f1bc15d5ea3e276e75da0a16f1e29702c blob + 6bfb6097c9169b2a18264006c657a13145a78816 --- got/got.1 +++ got/got.1 @@ -698,6 +698,42 @@ If this option is not specified, the most recent commi 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. +The special +.Ar commit +keywords +.Qq :base +and +.Qq :head +can also be used to represent the work tree's base commit +and HEAD reference, respectively. +Keywords and reference names may be appended with +.Qq :+ +or +.Qq :- +modifiers and an optional integer N to denote the +Nth descendant or antecedent, respectively, by first parent traversal; +for example, +.Sy :head:-2 +denotes the HEAD reference's 2nd generation ancestor, and +.Sy :base:+4 +denotes the 4th generation descendant of the work tree's base commit. +Similarly, +.Sy foo:-3 +will denote the 3rd generation ancestor of the commit resolved by the +.Qq foo +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 . If this option is not specified, the most recent commit on the work tree's branch will be used. .It Fl q @@ -857,6 +893,45 @@ If this option is not specified, default to the work t 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. +The special +.Ar commit +keywords +.Qq :base +and +.Qq :head +can also be used to represent the work tree's base commit +and HEAD reference, 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, respectively, by first parent traversal; +for example, +.Sy :head:-2 +denotes the HEAD reference's 2nd generation ancestor, and +.Sy :base:+4 +denotes the 4th generation descendant of the work tree's base commit. +Similarly, +.Sy bar:+3 +will denote the 3rd generation descendant of the commit resolved by the +.Qq bar +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 . If this option is not specified, default to the work tree's current branch if invoked in a work tree, or to the repository's HEAD reference. .It Fl d @@ -981,6 +1056,45 @@ 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. +The special +.Ar commit +keywords +.Qq :base +and +.Qq :head +can also be used to represent the work tree's base commit +and HEAD reference, 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, respectively, by first parent traversal; +for example, +.Sy :head:-2 +denotes the HEAD reference's 2nd generation ancestor, and +.Sy :base:+4 +denotes the 4th generation descendant of the work tree's base commit. +Similarly, +.Sy baz:+8 +will denote the 8th generation descendant of the commit resolved by the +.Qq baz +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 If the .Fl c blob - 01fe4299c82e150fcd8020915536f48fc73bacbc blob + 5daaa2a45ce2ad20cfb3278576a2454d4befeb46 --- got/got.c +++ got/got.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,7 @@ #include "got_patch.h" #include "got_sigs.h" #include "got_date.h" +#include "got_keyword.h" #ifndef nitems #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) @@ -3565,11 +3567,24 @@ cmd_update(int argc, char *argv[]) goto done; } else { struct got_reflist_head refs; + char *keyword_idstr = NULL; + 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) { + free(commit_id_str); + 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); @@ -4730,8 +4745,18 @@ cmd_log(int argc, char *argv[]) goto done; got_object_commit_close(commit); } else { + char *keyword_idstr = NULL; + + error = got_keyword_to_idstr(&keyword_idstr, start_commit, + repo, worktree); + if (error != NULL) + goto done; + if (keyword_idstr != NULL) + start_commit = keyword_idstr; + error = got_repo_match_object_id(&start_id, NULL, start_commit, GOT_OBJ_TYPE_COMMIT, &refs, repo); + free(keyword_idstr); if (error != NULL) goto done; } @@ -5232,13 +5257,24 @@ cmd_diff(int argc, char *argv[]) if (error) goto done; for (i = 0; i < (ncommit_args > 0 ? ncommit_args : argc); i++) { - const char *arg; + const char *arg; + char *keyword_idstr = NULL; + if (ncommit_args > 0) arg = commit_args[i]; else arg = argv[i]; + + error = got_keyword_to_idstr(&keyword_idstr, arg, + repo, worktree); + if (error != NULL) + goto done; + if (keyword_idstr != NULL) + arg = keyword_idstr; + error = got_repo_match_object_id(&ids[i], &labels[i], arg, obj_type, &refs, repo); + free(keyword_idstr); if (error) { if (error->code != GOT_ERR_NOT_REF && error->code != GOT_ERR_NO_OBJ) blob - 105744fb64ab3e71162d690183b908dcd64cc259 blob + 60384f611195c8632002438feac20a8570779eae --- include/got_error.h +++ include/got_error.h @@ -186,6 +186,7 @@ #define GOT_ERR_NO_PROG 169 #define GOT_ERR_MERGE_COMMIT_OUT_OF_DATE 170 #define GOT_ERR_BUNDLE_FORMAT 171 +#define GOT_ERR_BAD_KEYWORD 172 struct got_error { int code; blob - /dev/null blob + c7a8dc04900df90b19f64e5ccbf759b1f0ae49e8 (mode 644) --- /dev/null +++ include/got_keyword.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Mark Jamsek + * + * 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. + */ + +/* + * Commit keywords to specify references in the repository + * (cf. svn keywords, fossil special tags, hg revsets). + */ +#define GOT_KEYWORD_BASE "base" /* work tree base commit */ +#define GOT_KEYWORD_HEAD "head" /* worktree/repo HEAD commit */ + +/* + * Parse a commit id string for keywords and/or lineage modifiers "(+|-)[N]". + * Valid keywords are "base" or "head" and must be prefixed with a ":". + * Lineage modifiers must be prefixed with a ":" and may suffix keywords or + * reference names: + * :keyword:(+/-)N Nth generation descendant/antecedent of keyword + * :keyword:(+/-) 1st generation descendant/antecedent of keyword + * :keyword commit pointed to by keyword + * ref:(+/-)[N] Nth generation descendant/antecedent of ref + * If a match is found, return the corresponding commit id string in the + * char ** out parameter, of which the caller takes ownership and must free. + * Otherwise it will contain NULL, indicating a match was not found. + * If the modifier is greater than the number of ancestors/descendants, the id + * string of the oldest/most recent commit (i.e., ROOT/HEAD) will be returned. + */ +const struct got_error *got_keyword_to_idstr(char **, const char *, + struct got_repository *, struct got_worktree *); blob - 9be6fcbe0d2e6af91f5c95d80f653bc3f359d729 blob + 5d970a01a42033eb7fed3d588895e1ec8def46df --- lib/error.c +++ lib/error.c @@ -236,6 +236,7 @@ static const struct got_error got_errors[] = { "the work tree is no longer up-to-date; merge must be aborted " "and retried" }, { GOT_ERR_BUNDLE_FORMAT, "unknown git bundle version" }, + { GOT_ERR_BAD_KEYWORD, "invalid commit keyword" } }; static struct got_custom_error { blob - /dev/null blob + 0075f77ebd9d0912817d71d320463c4f76bdeed0 (mode 644) --- /dev/null +++ lib/keyword.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2023 Mark Jamsek + * + * 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. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "got_reference.h" +#include "got_error.h" +#include "got_object.h" +#include "got_repository.h" +#include "got_cancel.h" +#include "got_worktree.h" +#include "got_commit_graph.h" +#include "got_keyword.h" + +struct keyword_mod { + char *kw; + uint64_t n; + uint8_t sym; + uint8_t iskeyword; + uint8_t ismodified; +}; + +#define GOT_KEYWORD_DESCENDANT '+' +#define GOT_KEYWORD_ANCESTOR '-' + +static const struct got_error * +parse_keyword(struct keyword_mod *kwm, const char *keyword) +{ + const char *kw; + char *p; + + if (keyword == NULL) + return NULL; + + /* check if it is a (modified) keyword or modified reference */ + if (*keyword == ':') { + kwm->iskeyword = 1; + kw = keyword + 1; + } else + kw = keyword; + + kwm->kw = strdup(kw); + if (kwm->kw == NULL) + return got_error_from_errno("strdup"); + + p = strchr(kwm->kw, ':'); + + if (p != NULL) { + *p = '\0'; + ++p; + if (*p != GOT_KEYWORD_DESCENDANT && *p != GOT_KEYWORD_ANCESTOR) + return got_error_fmt(GOT_ERR_BAD_KEYWORD, + "'%s'", keyword); + + kwm->ismodified = 1; + kwm->sym = *p; + ++p; + + if (*p) { + const char *errstr; + long long n; + + n = strtonum(p, 0, LLONG_MAX, &errstr); + if (errstr != NULL) + return got_error_fmt(GOT_ERR_BAD_KEYWORD, + "'%s'", keyword); + + kwm->n = n; + } else + kwm->n = 1; /* :(+/-) == :(+/-)1 */ + } + + return NULL; +} + +const struct got_error * +got_keyword_to_idstr(char **ret, const char *keyword, + struct got_repository *repo, struct got_worktree *wt) +{ + const struct got_error *err = NULL; + struct got_commit_graph *graph = NULL; + struct got_object_id *head_id = NULL, *kwid = NULL; + struct got_object_id iter_id; + struct got_reflist_head refs; + struct got_object_id_queue commits; + struct got_object_qid *qid; + struct keyword_mod kwm; + char *kw = NULL, *kwid_str = NULL; + uint64_t n = 0; + + *ret = NULL; + TAILQ_INIT(&refs); + STAILQ_INIT(&commits); + memset(&kwm, 0, sizeof(kwm)); + + err = parse_keyword(&kwm, keyword); + if (err != NULL) + goto done; + + kw = kwm.kw; + + if (kwm.iskeyword) { + if (strcmp(kw, GOT_KEYWORD_BASE) == 0) { + if (wt == NULL) { + err = got_error_msg(GOT_ERR_NOT_WORKTREE, + "'-c :base' requires work tree"); + goto done; + } + + err = got_object_id_str(&kwid_str, + got_worktree_get_base_commit_id(wt)); + if (err != NULL) + goto done; + } else if (strcmp(kw, GOT_KEYWORD_HEAD) == 0) { + struct got_reference *head_ref; + + err = got_ref_open(&head_ref, repo, wt != NULL ? + got_worktree_get_head_ref_name(wt) : + GOT_REF_HEAD, 0); + if (err != NULL) + goto done; + + kwid_str = got_ref_to_str(head_ref); + got_ref_close(head_ref); + if (kwid_str == NULL) { + err = got_error_from_errno("got_ref_to_str"); + goto done; + } + } else { + err = got_error_fmt(GOT_ERR_BAD_KEYWORD, "'%s'", kw); + goto done; + } + } else if (kwm.ismodified) { + /* reference:[(+|-)[N]] */ + kwid_str = strdup(kw); + if (kwid_str == NULL) { + err = got_error_from_errno("strdup"); + goto done; + } + } else + goto done; + + if (kwm.n == 0) + goto done; /* unmodified keyword */ + + err = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL); + if (err) + goto done; + + err = got_repo_match_object_id(&kwid, NULL, kwid_str, + GOT_OBJ_TYPE_COMMIT, &refs, repo); + if (err != NULL) + goto done; + + /* + * If looking for a descendant, we need to iterate from + * HEAD so grab its id now if it's not already in kwid. + */ + if (kwm.sym == GOT_KEYWORD_DESCENDANT && kw != NULL && + strcmp(kw, GOT_KEYWORD_HEAD) != 0) { + struct got_reference *head_ref; + + err = got_ref_open(&head_ref, repo, wt != NULL ? + got_worktree_get_head_ref_name(wt) : GOT_REF_HEAD, 0); + if (err != NULL) + goto done; + err = got_ref_resolve(&head_id, repo, head_ref); + got_ref_close(head_ref); + if (err != NULL) + goto done; + } + + err = got_commit_graph_open(&graph, "/", 1); + if (err) + goto done; + + err = got_commit_graph_iter_start(graph, + head_id != NULL ? head_id : kwid, repo, NULL, NULL); + if (err) + goto done; + + while (n <= kwm.n) { + err = got_commit_graph_iter_next(&iter_id, graph, repo, + NULL, NULL); + if (err) { + if (err->code == GOT_ERR_ITER_COMPLETED) + err = NULL; + break; + } + + if (kwm.sym == GOT_KEYWORD_DESCENDANT) { + /* + * We want the Nth generation descendant of KEYWORD, + * so queue all commits from HEAD to KEYWORD then we + * can walk from KEYWORD to its Nth gen descendent. + */ + err = got_object_qid_alloc(&qid, &iter_id); + if (err) + goto done; + STAILQ_INSERT_HEAD(&commits, qid, entry); + + if (got_object_id_cmp(&iter_id, kwid) == 0) + break; + continue; + } + ++n; + } + + if (kwm.sym == GOT_KEYWORD_DESCENDANT) { + n = 0; + + STAILQ_FOREACH(qid, &commits, entry) { + if (qid == STAILQ_LAST(&commits, got_object_qid, entry) + || n == kwm.n) + break; + ++n; + } + + memcpy(&iter_id, &qid->id, sizeof(iter_id)); + + } + + free(kwid_str); + err = got_object_id_str(&kwid_str, &iter_id); + +done: + free(kwid); + free(kwm.kw); + free(head_id); + got_ref_list_free(&refs); + got_object_id_queue_free(&commits); + if (graph != NULL) + got_commit_graph_close(graph); + + if (err != NULL) { + free(kwid_str); + return err; + } + + *ret = kwid_str; + return NULL; +} blob - f8c6bfd3e10294f056b420f98add07f8c8d0dd33 blob + fa848632bdd2c520f0e5186a325f388de3cc8c4b --- regress/cmdline/common.sh +++ regress/cmdline/common.sh @@ -140,6 +140,12 @@ git_commit_tree() echo ${id%$pat} } +pop_id() +{ + shift "$1" + printf '%s' "${1:-index-out-of-bounds}" +} + git_commit_tree() { local repo="$1" blob - 03e05611a400a2ffc9c91e307d0d5c048fdc6cf3 blob + 592e477643b13ce4e2a8ce6037f11ee4ba539cdf --- regress/cmdline/diff.sh +++ regress/cmdline/diff.sh @@ -2022,6 +2022,254 @@ test_parseargs "$@" test_done "$testroot" "$ret" } +test_diff_commit_keywords() { + local testroot=`test_init diff_commit_keywords` + + got checkout $testroot/repo $testroot/wt > /dev/null + ret=$? + if [ $ret -ne 0 ]; then + echo "checkout failed unexpectedly" >&2 + test_done "$testroot" "$ret" + return 1 + fi + + set -A ids "$(git_show_head $testroot/repo)" + set -A alpha_ids "$(get_blob_id $testroot/repo "" alpha)" + set -A beta_ids "$(get_blob_id $testroot/repo "" beta)" + + for i in `seq 8`; do + if [ $(( i % 2 )) -eq 0 ]; then + echo "alpha change $i" > "$testroot/wt/alpha" + else + echo "beta change $i" > "$testroot/wt/beta" + fi + + (cd "$testroot/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 + + if [ $(( i % 2 )) -eq 0 ]; then + set -- "$alpha_ids" \ + "$(get_blob_id $testroot/repo "" alpha)" + alpha_ids=$* + else + set -- "$beta_ids" \ + "$(get_blob_id $testroot/repo "" beta)" + beta_ids=$* + fi + + set -- "$ids" "$(git_show_head $testroot/repo)" + ids=$* + done + + echo "diff $(pop_id 7 $ids) $(pop_id 8 $ids)" > \ + $testroot/stdout.expected + echo "commit - $(pop_id 7 $ids)" >> $testroot/stdout.expected + echo "commit + $(pop_id 8 $ids)" >> $testroot/stdout.expected + echo "blob - $(pop_id 4 $beta_ids)" >> $testroot/stdout.expected + echo "blob + $(pop_id 5 $beta_ids)" >> $testroot/stdout.expected + echo '--- beta' >> $testroot/stdout.expected + echo '+++ beta' >> $testroot/stdout.expected + echo '@@ -1 +1 @@' >> $testroot/stdout.expected + echo '-beta change 5' >> $testroot/stdout.expected + echo '+beta change 7' >> $testroot/stdout.expected + + (cd $testroot/wt && got diff -cmaster:- > $testroot/stdout) + ret=$? + if [ $ret -ne 0 ]; then + echo "diff failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + 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 $testroot/wt && got update -c:head:-6 > /dev/null) + ret=$? + if [ $ret -ne 0 ]; then + echo "update failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo "diff $(pop_id 1 $ids) $(pop_id 2 $ids)" > \ + $testroot/stdout.expected + echo "commit - $(pop_id 1 $ids)" >> $testroot/stdout.expected + echo "commit + $(pop_id 2 $ids)" >> $testroot/stdout.expected + echo "blob - $(pop_id 1 $beta_ids)" >> $testroot/stdout.expected + echo "blob + $(pop_id 2 $beta_ids)" >> $testroot/stdout.expected + echo '--- beta' >> $testroot/stdout.expected + echo '+++ beta' >> $testroot/stdout.expected + echo '@@ -1 +1 @@' >> $testroot/stdout.expected + echo '-beta' >> $testroot/stdout.expected + echo '+beta change 1' >> $testroot/stdout.expected + + (cd $testroot/wt && got diff -c:base:- > $testroot/stdout) + ret=$? + if [ $ret -ne 0 ]; then + echo "diff failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + 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 "diff $(pop_id 3 $ids) $(pop_id 4 $ids)" > \ + $testroot/stdout.expected + echo "commit - $(pop_id 3 $ids)" >> $testroot/stdout.expected + echo "commit + $(pop_id 4 $ids)" >> $testroot/stdout.expected + echo "blob - $(pop_id 2 $beta_ids)" >> $testroot/stdout.expected + echo "blob + $(pop_id 3 $beta_ids)" >> $testroot/stdout.expected + echo '--- beta' >> $testroot/stdout.expected + echo '+++ beta' >> $testroot/stdout.expected + echo '@@ -1 +1 @@' >> $testroot/stdout.expected + echo '-beta change 1' >> $testroot/stdout.expected + echo '+beta change 3' >> $testroot/stdout.expected + + (cd $testroot/wt && got diff -c:base:+ > $testroot/stdout) + ret=$? + if [ $ret -ne 0 ]; then + echo "diff failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + 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 + + # if modifier extends beyond HEAD, we should use HEAD ref + echo "diff $(pop_id 8 $ids) $(pop_id 9 $ids)" > \ + $testroot/stdout.expected + echo "commit - $(pop_id 8 $ids)" >> $testroot/stdout.expected + echo "commit + $(pop_id 9 $ids)" >> $testroot/stdout.expected + echo "blob - $(pop_id 4 $alpha_ids)" >> $testroot/stdout.expected + echo "blob + $(pop_id 5 $alpha_ids)" >> $testroot/stdout.expected + echo '--- alpha' >> $testroot/stdout.expected + echo '+++ alpha' >> $testroot/stdout.expected + echo '@@ -1 +1 @@' >> $testroot/stdout.expected + echo '-alpha change 6' >> $testroot/stdout.expected + echo '+alpha change 8' >> $testroot/stdout.expected + + (cd $testroot/wt && got diff -c:base:+20 > $testroot/stdout) + ret=$? + if [ $ret -ne 0 ]; then + echo "diff failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + 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 "diff $(pop_id 3 $ids) $(pop_id 9 $ids)" > \ + $testroot/stdout.expected + echo "commit - $(pop_id 3 $ids)" >> $testroot/stdout.expected + echo "commit + $(pop_id 9 $ids)" >> $testroot/stdout.expected + echo "blob - $(pop_id 2 $alpha_ids)" >> $testroot/stdout.expected + echo "blob + $(pop_id 5 $alpha_ids)" >> $testroot/stdout.expected + echo '--- alpha' >> $testroot/stdout.expected + echo '+++ alpha' >> $testroot/stdout.expected + echo '@@ -1 +1 @@' >> $testroot/stdout.expected + echo '-alpha change 2' >> $testroot/stdout.expected + echo '+alpha change 8' >> $testroot/stdout.expected + echo "blob - $(pop_id 2 $beta_ids)" >> $testroot/stdout.expected + echo "blob + $(pop_id 5 $beta_ids)" >> $testroot/stdout.expected + echo '--- beta' >> $testroot/stdout.expected + echo '+++ beta' >> $testroot/stdout.expected + echo '@@ -1 +1 @@' >> $testroot/stdout.expected + echo '-beta change 1' >> $testroot/stdout.expected + echo '+beta change 7' >> $testroot/stdout.expected + + (cd $testroot/wt && got diff -c:base -c:head > $testroot/stdout) + ret=$? + if [ $ret -ne 0 ]; then + echo "diff failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + 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 "diff $(pop_id 6 $ids) $(pop_id 8 $ids)" > \ + $testroot/stdout.expected + echo "commit - $(pop_id 6 $ids)" >> $testroot/stdout.expected + echo "commit + $(pop_id 8 $ids)" >> $testroot/stdout.expected + echo "blob - $(pop_id 3 $alpha_ids)" >> $testroot/stdout.expected + echo "blob + $(pop_id 4 $alpha_ids)" >> $testroot/stdout.expected + echo '--- alpha' >> $testroot/stdout.expected + echo '+++ alpha' >> $testroot/stdout.expected + echo '@@ -1 +1 @@' >> $testroot/stdout.expected + echo '-alpha change 4' >> $testroot/stdout.expected + echo '+alpha change 6' >> $testroot/stdout.expected + echo "blob - $(pop_id 4 $beta_ids)" >> $testroot/stdout.expected + echo "blob + $(pop_id 5 $beta_ids)" >> $testroot/stdout.expected + echo '--- beta' >> $testroot/stdout.expected + echo '+++ beta' >> $testroot/stdout.expected + echo '@@ -1 +1 @@' >> $testroot/stdout.expected + echo '-beta change 5' >> $testroot/stdout.expected + echo '+beta change 7' >> $testroot/stdout.expected + + got diff -r "$testroot/repo" -cmaster:-3 -c:head:-1 > $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + echo "diff failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + 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 "'-c BASE' requires work tree" > "$testroot/stderr.expected" + + got diff -r "$testroot/repo" -c:base -c:head 2> $testroot/stderr + + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi + + test_done "$testroot" "$ret" +} + test_parseargs "$@" run_test test_diff_basic run_test test_diff_shows_conflict @@ -2041,3 +2289,4 @@ run_test test_diff_path_in_root_commit run_test test_diff_file_to_dir run_test test_diff_dir_to_file run_test test_diff_path_in_root_commit +run_test test_diff_commit_keywords blob - aa6a545fe216654b76ca23bbe186211d313c59a2 blob + 96004ce8b8a631507d11bbb3ba545448a1a16429 --- regress/cmdline/log.sh +++ regress/cmdline/log.sh @@ -900,6 +900,154 @@ test_parseargs "$@" test_done "$testroot" "$ret" } +test_log_commit_keywords() { + local testroot=$(test_init log_commit_keywords) + local commit_time=`git_show_author_time $testroot/repo` + local d=`date -u -r $commit_time +"%G-%m-%d"` + + set -A ids "$(git_show_head $testroot/repo)" + + got checkout $testroot/repo $testroot/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 16); do + echo "alpha change $i" > "$testroot/wt/alpha" + + (cd "$testroot/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 $testroot/repo)" + ids=$* + done + + for i in $(seq 16 2); do + printf '%s %.7s commit number %s\n' \ + "$d" $(pop_id $i $ids) "$(( i-1 ))" \ + >> $testroot/stdout.expected + done + + got log -r "$testroot/repo" -scmaster:- -l15 > $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 + + (cd $testroot/wt && got update -c:head:-8 > /dev/null) + ret=$? + if [ $ret -ne 0 ]; then + echo "update failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo -n > "$testroot/stdout.expected" + + for i in $(seq 9 2); do + printf '%s %.7s commit number %s\n' \ + "$d" $(pop_id $i $ids) "$(( i-1 ))" \ + >> $testroot/stdout.expected + done + printf '%s %.7s adding the test tree\n' "$d" $(pop_id 1 $ids) >> \ + $testroot/stdout.expected + + (cd $testroot/wt && got log -sc:base > $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 + + # if + modifier is too great, use HEAD commit + printf '%s %-7s commit number %s\n' "$d" master 16 > \ + $testroot/stdout.expected + printf '%s %.7s commit number %s\n' "$d" $(pop_id 16 $ids) 15 >> \ + $testroot/stdout.expected + + (cd $testroot/wt && got log -sc:base:+20 -l2 > $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 + + # if - modifier is too great, use root commit + printf '%s %.7s adding the test tree\n' "$d" $(pop_id 1 $ids) > \ + $testroot/stdout.expected + + (cd $testroot/wt && got log -sc:base:-10 > $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 br -r "$testroot/repo" -c $(pop_id 1 $ids) base+ + + printf '%s %.7s commit number 1\n' "$d" $(pop_id 2 $ids) > \ + $testroot/stdout.expected + + (cd $testroot/wt && got log -scbase+:+ -l1 > $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 br -r "$testroot/repo" -c $(pop_id 3 $ids) head-1 + + printf '%s %.7s commit number 1\n' "$d" $(pop_id 2 $ids) > \ + $testroot/stdout.expected + + (cd $testroot/wt && got log -schead-1:- -l1 > $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 br -r "$testroot/repo" -c $(pop_id 16 $ids) base-1+2 + + printf '%s %.7s commit number 12\n' "$d" $(pop_id 13 $ids) > \ + $testroot/stdout.expected + + (cd $testroot/wt && got log -scbase-1+2:-3 -l1 > $testroot/stdout) + + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi + + test_done "$testroot" "$ret" +} + test_parseargs "$@" run_test test_log_in_repo run_test test_log_in_bare_repo @@ -916,3 +1064,4 @@ run_test test_log_diffstat run_test test_log_changed_paths run_test test_log_submodule run_test test_log_diffstat +run_test test_log_commit_keywords blob - c08237c6cd1b14453b8e4f8e39789a3c6c017f1c blob + 9c979ff35454c34d02151d8a65d66ad2cdf10d86 --- regress/cmdline/update.sh +++ regress/cmdline/update.sh @@ -3230,6 +3230,345 @@ test_parseargs "$@" test_done "$testroot" 0 } +test_update_commit_keywords() { + local testroot=`test_init update_commit_keywords` + + set -A ids "$(git_show_head $testroot/repo)" + + got checkout $testroot/repo $testroot/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 + if [ $(( i % 2 )) -eq 0 ]; then + echo "alpha change $i" > "$testroot/wt/alpha" + else + echo "beta change $i" > "$testroot/wt/beta" + fi + + (cd "$testroot/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 $testroot/repo)" + ids=$* + done + + echo "got: reference base not found" > $testroot/stderr.expected + + (cd $testroot/wt && got update -cbase:-2 2> $testroot/stderr) + ret=$? + if [ $ret -ne 1 ]; then + echo "update succeeded unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo "got: 'basefoo': invalid commit keyword" > \ + $testroot/stderr.expected + + (cd $testroot/wt && got update -c:basefoo:-2 2> $testroot/stderr) + ret=$? + if [ $ret -ne 1 ]; then + echo "update succeeded unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo "got: ':base::': invalid commit keyword" > \ + $testroot/stderr.expected + + (cd $testroot/wt && got update -c:base:: 2> $testroot/stderr) + ret=$? + if [ $ret -ne 1 ]; then + echo "update succeeded unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo "got: ':head:++': invalid commit keyword" > \ + $testroot/stderr.expected + + (cd $testroot/wt && got update -c:head:++ 2> $testroot/stderr) + ret=$? + if [ $ret -ne 1 ]; then + echo "update succeeded unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo "got: ':head:+x': invalid commit keyword" > \ + $testroot/stderr.expected + + (cd $testroot/wt && got update -c:head:+x 2> $testroot/stderr) + ret=$? + if [ $ret -ne 1 ]; then + echo "update succeeded unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo "got: 'master::': invalid commit keyword" > \ + $testroot/stderr.expected + + (cd $testroot/wt && got update -cmaster:: 2> $testroot/stderr) + ret=$? + if [ $ret -ne 1 ]; then + echo "update succeeded unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo "got: 'master:++': invalid commit keyword" > \ + $testroot/stderr.expected + + (cd $testroot/wt && got update -cmaster:++ 2> $testroot/stderr) + ret=$? + if [ $ret -ne 1 ]; then + echo "update succeeded unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo "got: 'master:+x': invalid commit keyword" > \ + $testroot/stderr.expected + + (cd $testroot/wt && got update -cmaster:+x 2> $testroot/stderr) + ret=$? + if [ $ret -ne 1 ]; then + echo "update 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 "U alpha" > $testroot/stdout.expected + echo "U beta" >> $testroot/stdout.expected + echo -n "Updated to refs/heads/master: " >> $testroot/stdout.expected + echo $(pop_id 7 $ids) >> "$testroot/stdout.expected" + + (cd $testroot/wt && got update -c:base:-2 > $testroot/stdout) + ret=$? + if [ $ret -ne 0 ]; then + echo "update failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + 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 "U beta" > $testroot/stdout.expected + echo -n "Updated to refs/heads/master: " >> $testroot/stdout.expected + echo $(pop_id 8 $ids) >> "$testroot/stdout.expected" + + (cd $testroot/wt && got update -cmaster:- > $testroot/stdout) + ret=$? + if [ $ret -ne 0 ]; then + echo "update failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + 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 change 6" > $testroot/content.expected + cat $testroot/wt/alpha > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + echo "U alpha" > $testroot/stdout.expected + echo "U beta" >> $testroot/stdout.expected + echo -n "Updated to refs/heads/master: " >> $testroot/stdout.expected + echo $(pop_id 2 $ids) >> "$testroot/stdout.expected" + + (cd $testroot/wt && got update -c:base:-6 > $testroot/stdout) + ret=$? + if [ $ret -ne 0 ]; then + echo "update failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + 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 "beta change 1" > $testroot/content.expected + cat $testroot/wt/beta > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + echo "U alpha" > $testroot/stdout.expected + echo -n "Updated to refs/heads/master: " >> $testroot/stdout.expected + echo $(pop_id 3 $ids) >> "$testroot/stdout.expected" + + (cd $testroot/wt && got update -c:base:+ > $testroot/stdout) + ret=$? + if [ $ret -ne 0 ]; then + echo "update failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + 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 change 2" > $testroot/content.expected + cat $testroot/wt/alpha > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + echo "U alpha" > $testroot/stdout.expected + echo "U beta" >> $testroot/stdout.expected + echo -n "Updated to refs/heads/master: " >> $testroot/stdout.expected + echo $(pop_id 7 $ids) >> "$testroot/stdout.expected" + + (cd $testroot/wt && got update -c:head:-2 > $testroot/stdout) + ret=$? + if [ $ret -ne 0 ]; then + echo "update failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + 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 change 6" > $testroot/content.expected + cat $testroot/wt/alpha > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + # if - modifier is too great, use root commit + echo "U alpha" > $testroot/stdout.expected + echo "U beta" >> $testroot/stdout.expected + echo -n "Updated to refs/heads/master: " >> $testroot/stdout.expected + echo $(pop_id 1 $ids) >> "$testroot/stdout.expected" + + (cd $testroot/wt && got update -c:base:-20 > $testroot/stdout) + ret=$? + if [ $ret -ne 0 ]; then + echo "update failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + 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/content.expected + cat $testroot/wt/alpha > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + # if + modifier is too great, use HEAD commit + echo "U alpha" > $testroot/stdout.expected + echo "U beta" >> $testroot/stdout.expected + echo -n "Updated to refs/heads/master: " >> $testroot/stdout.expected + echo $(pop_id 9 $ids) >> "$testroot/stdout.expected" + + (cd $testroot/wt && got update -c:head:+10 > $testroot/stdout) + ret=$? + if [ $ret -ne 0 ]; then + echo "update failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + 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 change 8" > $testroot/content.expected + cat $testroot/wt/alpha > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/content.expected $testroot/content + fi + test_done "$testroot" "$ret" +} + test_parseargs "$@" run_test test_update_basic run_test test_update_adds_file @@ -3278,3 +3617,4 @@ run_test test_update_umask run_test test_update_quiet run_test test_update_binary_file run_test test_update_umask +run_test test_update_commit_keywords -- Mark Jamsek GPG: F2FF 13DE 6A06 C471 CA80 E6E2 2930 DC66 86EE CF68