commit - 2539ccf28b5b0e6be13e9a7f2063a104efa7217b
commit + 30f6c0c64b5c08d79e22cc2c0bd1f1340288a7f5
blob - 607d9e411094bc0ccc199c39ccb264406f3ef169
blob + bdded67d33703dcd1607e51d0887179126d00a83
--- got/got.1
+++ got/got.1
is never traversed.
.El
.Tg di
-.It Cm diff Oo Fl a Oc Oo Fl C Ar number Oc Oo Fl r Ar repository-path Oc Oo Fl s Oc Oo Fl w Oc Op Ar object1 Ar object2 | Ar path
+.It Cm diff Oo Fl a Oc Oo Fl C Ar number Oc Oo Fl r Ar repository-path Oc Oo Fl s Oc Oo Fl P Oc Oo Fl w Oc Op Ar object1 Ar object2 | Ar path ...
.Dl (alias: Cm di )
-When invoked within a work tree with less than two arguments, display
+When invoked within a work tree without any arguments, display all
local changes in the work tree.
-If a
+If one or more
.Ar path
-is specified, only show changes within this path.
+arguments are specified, only show changes within the specified paths.
.Pp
If two arguments are provided, treat each argument as a reference, a tag
name, or an object ID SHA1 hash, and display differences between the
Both objects must be of the same type (blobs, trees, or commits).
An abbreviated hash argument will be expanded to a full SHA1 hash
automatically, provided the abbreviation is unique.
+If none of these interpretations produce a valid result or if the
+.Fl P
+option is used,
+and if
+.Cm got diff
+is running in a work tree, attempt to interpret the two arguments as paths.
.Pp
The options for
.Cm got diff
Show changes staged with
.Cm got stage
instead of showing local changes in the work tree.
+This option is only valid when
+.Cm got diff
+is invoked in a work tree.
+.It Fl P
+Interpret all arguments as paths only.
+This option can be used to resolve ambiguity in cases where paths
+look like tag names, reference names, or object IDs.
This option is only valid when
.Cm got diff
is invoked in a work tree.
blob - 369d7d7369f7a373f6eef08f611035ae2b846fe5
blob + ad7b886219f18cc55190a65296d733c9de7a8214
--- got/got.c
+++ got/got.c
usage_diff(void)
{
fprintf(stderr, "usage: %s diff [-a] [-C number] [-r repository-path] "
- "[-s] [-w] [object1 object2 | path]\n", getprogname());
+ "[-s] [-w] [-P] [object1 object2 | path ...]\n", getprogname());
exit(1);
}
struct got_repository *repo = NULL;
struct got_worktree *worktree = NULL;
char *cwd = NULL, *repo_path = NULL;
- struct got_object_id *id1 = NULL, *id2 = NULL;
- const char *id_str1 = NULL, *id_str2 = NULL;
- char *label1 = NULL, *label2 = NULL;
+ struct got_object_id *ids[2] = { NULL, NULL };
+ char *labels[2] = { NULL, NULL };
int type1, type2;
- int diff_context = 3, diff_staged = 0, ignore_whitespace = 0, ch;
- int force_text_diff = 0;
+ int diff_context = 3, diff_staged = 0, ignore_whitespace = 0, ch, i;
+ int force_text_diff = 0, force_path = 0, rflag = 0;
const char *errstr;
- char *path = NULL;
struct got_reflist_head refs;
+ struct got_pathlist_head paths;
+ struct got_pathlist_entry *pe;
TAILQ_INIT(&refs);
+ TAILQ_INIT(&paths);
#ifndef PROFILE
if (pledge("stdio rpath wpath cpath flock proc exec sendfd unveil",
err(1, "pledge");
#endif
- while ((ch = getopt(argc, argv, "aC:r:sw")) != -1) {
+ while ((ch = getopt(argc, argv, "aC:r:swP")) != -1) {
switch (ch) {
case 'a':
force_text_diff = 1;
return got_error_from_errno2("realpath",
optarg);
got_path_strip_trailing_slashes(repo_path);
+ rflag = 1;
break;
case 's':
diff_staged = 1;
case 'w':
ignore_whitespace = 1;
break;
+ case 'P':
+ force_path = 1;
+ break;
default:
usage_diff();
/* NOTREACHED */
error = got_error_from_errno("getcwd");
goto done;
}
- if (argc <= 1) {
- if (repo_path)
- errx(1,
- "-r option can't be used when diffing a work tree");
+
+ if (repo_path == NULL) {
error = got_worktree_open(&worktree, cwd);
- if (error) {
- if (error->code == GOT_ERR_NOT_WORKTREE)
- error = wrap_not_worktree_error(error, "diff",
- cwd);
+ if (error && error->code != GOT_ERR_NOT_WORKTREE)
goto done;
- }
- repo_path = strdup(got_worktree_get_repo_path(worktree));
- if (repo_path == NULL) {
- error = got_error_from_errno("strdup");
- goto done;
- }
- if (argc == 1) {
- error = got_worktree_resolve_path(&path, worktree,
- argv[0]);
- if (error)
+ else
+ error = NULL;
+ if (worktree) {
+ repo_path =
+ strdup(got_worktree_get_repo_path(worktree));
+ if (repo_path == NULL) {
+ error = got_error_from_errno("strdup");
goto done;
+ }
} else {
- path = strdup("");
- if (path == NULL) {
+ repo_path = strdup(cwd);
+ if (repo_path == NULL) {
error = got_error_from_errno("strdup");
goto done;
}
}
- } else if (argc == 2) {
- if (diff_staged)
- errx(1, "-s option can't be used when diffing "
- "objects in repository");
- id_str1 = argv[0];
- id_str2 = argv[1];
+ }
+
+ if (worktree) {
+ repo_path = strdup(got_worktree_get_repo_path(worktree));
if (repo_path == NULL) {
- error = got_worktree_open(&worktree, cwd);
- if (error && error->code != GOT_ERR_NOT_WORKTREE)
- goto done;
- repo_path = strdup(worktree ?
- got_worktree_get_repo_path(worktree) : cwd);
+ error = got_error_from_errno("strdup");
+ goto done;
+ }
+ } else {
+ if (repo_path == NULL) {
+ repo_path = strdup(cwd);
if (repo_path == NULL) {
error = got_error_from_errno("strdup");
goto done;
}
}
- } else
- usage_diff();
+ }
+ if (force_path && (rflag || worktree == NULL))
+ errx(1, "-P option can only be used when diffing a work tree");
+
error = got_repo_open(&repo, repo_path, NULL);
free(repo_path);
if (error != NULL)
if (error)
goto done;
- if (argc <= 1) {
+ if (!force_path && argc == 2) {
+ error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name,
+ NULL);
+ if (error)
+ goto done;
+ for (i = 0; i < argc; i++) {
+ error = got_repo_match_object_id(&ids[i], &labels[i],
+ argv[i], GOT_OBJ_TYPE_ANY, &refs, repo);
+ if (error) {
+ if (error->code != GOT_ERR_NOT_REF &&
+ error->code != GOT_ERR_NO_OBJ)
+ goto done;
+ error = NULL;
+ break;
+ }
+ }
+ }
+
+ if (worktree != NULL && (ids[0] == NULL || ids[1] == NULL)) {
+ error = get_worktree_paths_from_argv(&paths,
+ argc, argv, worktree);
+ if (error)
+ goto done;
+ }
+
+ if (!TAILQ_EMPTY(&paths)) {
struct print_diff_arg arg;
- struct got_pathlist_head paths;
char *id_str;
- TAILQ_INIT(&paths);
-
error = got_object_id_str(&id_str,
got_worktree_get_base_commit_id(worktree));
if (error)
arg.ignore_whitespace = ignore_whitespace;
arg.force_text_diff = force_text_diff;
- error = got_pathlist_append(&paths, path, NULL);
- if (error)
- goto done;
-
error = got_worktree_status(worktree, &paths, repo, 0,
print_diff, &arg, check_cancelled, NULL);
free(id_str);
- got_pathlist_free(&paths);
goto done;
}
- error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL);
- if (error)
- return error;
-
- error = got_repo_match_object_id(&id1, &label1, id_str1,
- GOT_OBJ_TYPE_ANY, &refs, repo);
- if (error)
- goto done;
+ if (ids[0] == NULL || ids[1] == NULL) {
+ if (argc == 2) {
+ error = got_error_fmt(GOT_ERR_NO_OBJ, "%s",
+ ids[0] ? argv[1] : argv[0]);
+ goto done;
+ } if (worktree == NULL) {
+ error = got_error(GOT_ERR_NOT_WORKTREE);
+ goto done;
+ } else
+ usage_diff();
+ }
+ if (diff_staged)
+ errx(1, "-s option can't be used when diffing "
+ "objects in repository");
- error = got_repo_match_object_id(&id2, &label2, id_str2,
- GOT_OBJ_TYPE_ANY, &refs, repo);
+ error = got_object_get_type(&type1, repo, ids[0]);
if (error)
goto done;
- error = got_object_get_type(&type1, repo, id1);
+ error = got_object_get_type(&type2, repo, ids[1]);
if (error)
goto done;
-
- error = got_object_get_type(&type2, repo, id2);
- if (error)
- goto done;
-
if (type1 != type2) {
error = got_error(GOT_ERR_OBJ_TYPE);
goto done;
switch (type1) {
case GOT_OBJ_TYPE_BLOB:
- error = got_diff_objects_as_blobs(NULL, NULL, id1, id2,
+ error = got_diff_objects_as_blobs(NULL, NULL, ids[0], ids[1],
NULL, NULL, diff_context, ignore_whitespace,
force_text_diff, repo, stdout);
break;
case GOT_OBJ_TYPE_TREE:
- error = got_diff_objects_as_trees(NULL, NULL, id1, id2,
+ error = got_diff_objects_as_trees(NULL, NULL, ids[0], ids[1],
"", "", diff_context, ignore_whitespace, force_text_diff,
repo, stdout);
break;
case GOT_OBJ_TYPE_COMMIT:
- printf("diff %s %s\n", label1, label2);
- error = got_diff_objects_as_commits(NULL, NULL, id1, id2,
+ printf("diff %s %s\n", labels[0], labels[1]);
+ error = got_diff_objects_as_commits(NULL, NULL, ids[0], ids[1],
diff_context, ignore_whitespace, force_text_diff, repo,
stdout);
break;
error = got_error(GOT_ERR_OBJ_TYPE);
}
done:
- free(label1);
- free(label2);
- free(id1);
- free(id2);
- free(path);
+ free(labels[0]);
+ free(labels[1]);
+ free(ids[0]);
+ free(ids[1]);
if (worktree)
got_worktree_close(worktree);
if (repo) {
if (error == NULL)
error = close_err;
}
+ TAILQ_FOREACH(pe, &paths, entry)
+ free((char *)pe->path);
+ got_pathlist_free(&paths);
got_ref_list_free(&refs);
return error;
}
blob - 9987502cc2a56a00f9c9a0960fb32f8ba17770df
blob + 7bc83f4d3575b51f65002d99ae9beedadfea7495
--- regress/cmdline/diff.sh
+++ regress/cmdline/diff.sh
return 1
fi
+ # 'got diff' in a repository without any arguments is an error
+ (cd $testroot/repo && got diff 2> $testroot/stderr)
+ echo "got: no got work tree found" > $testroot/stderr.expected
+ cmp -s $testroot/stderr.expected $testroot/stderr
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stderr.expected $testroot/stderr
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # 'got diff' in a repository with two arguments requires that
+ # both named objects exist
+ (cd $testroot/repo && got diff $head_rev foo 2> $testroot/stderr)
+ echo "got: foo: object not found" > $testroot/stderr.expected
+ cmp -s $testroot/stderr.expected $testroot/stderr
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stderr.expected $testroot/stderr
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
# diff non-existent path
(cd $testroot/wt && got diff nonexistent > $testroot/stdout \
2> $testroot/stderr)
fi
echo "got: nonexistent: No such file or directory" \
+ > $testroot/stderr.expected
+ cmp -s $testroot/stderr.expected $testroot/stderr
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stderr.expected $testroot/stderr
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ echo "modified zeta" > $testroot/wt/epsilon/zeta
+
+ # diff several paths in a work tree
+ echo "diff $head_rev $testroot/wt" > $testroot/stdout.expected
+ echo 'blob - /dev/null' >> $testroot/stdout.expected
+ echo 'file + new' >> $testroot/stdout.expected
+ echo '--- /dev/null' >> $testroot/stdout.expected
+ echo '+++ new' >> $testroot/stdout.expected
+ echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected
+ echo '+new file' >> $testroot/stdout.expected
+ echo -n 'blob - ' >> $testroot/stdout.expected
+ got tree -r $testroot/repo -i | grep 'alpha$' | cut -d' ' -f 1 \
+ >> $testroot/stdout.expected
+ echo 'file + alpha' >> $testroot/stdout.expected
+ echo '--- alpha' >> $testroot/stdout.expected
+ echo '+++ alpha' >> $testroot/stdout.expected
+ echo '@@ -1 +1 @@' >> $testroot/stdout.expected
+ echo '-alpha' >> $testroot/stdout.expected
+ echo '+modified alpha' >> $testroot/stdout.expected
+ echo -n 'blob - ' >> $testroot/stdout.expected
+ got tree -r $testroot/repo -i epsilon | grep 'zeta$' | cut -d' ' -f 1 \
+ >> $testroot/stdout.expected
+ echo 'file + epsilon/zeta' >> $testroot/stdout.expected
+ echo '--- epsilon/zeta' >> $testroot/stdout.expected
+ echo '+++ epsilon/zeta' >> $testroot/stdout.expected
+ echo '@@ -1 +1 @@' >> $testroot/stdout.expected
+ echo '-zeta' >> $testroot/stdout.expected
+ echo '+modified zeta' >> $testroot/stdout.expected
+ echo -n 'blob - ' >> $testroot/stdout.expected
+ got tree -r $testroot/repo -i | grep 'beta$' | cut -d' ' -f 1 \
+ >> $testroot/stdout.expected
+ echo 'file + /dev/null' >> $testroot/stdout.expected
+ echo '--- beta' >> $testroot/stdout.expected
+ echo '+++ /dev/null' >> $testroot/stdout.expected
+ echo '@@ -1 +0,0 @@' >> $testroot/stdout.expected
+ echo '-beta' >> $testroot/stdout.expected
+
+ (cd $testroot/wt && got diff new alpha epsilon beta > $testroot/stdout)
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # a branch 'new' should not collide with path 'new' if more
+ # than two arguments are passed
+ got br -r $testroot/repo -c master new > /dev/null
+ (cd $testroot/wt && got diff new alpha epsilon beta \
+ > $testroot/stdout 2> $testroot/stderr)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "diff failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # different order of arguments results in different output order
+ echo "diff $head_rev $testroot/wt" > $testroot/stdout.expected
+ echo -n 'blob - ' >> $testroot/stdout.expected
+ got tree -r $testroot/repo -i | grep 'alpha$' | cut -d' ' -f 1 \
+ >> $testroot/stdout.expected
+ echo 'file + alpha' >> $testroot/stdout.expected
+ echo '--- alpha' >> $testroot/stdout.expected
+ echo '+++ alpha' >> $testroot/stdout.expected
+ echo '@@ -1 +1 @@' >> $testroot/stdout.expected
+ echo '-alpha' >> $testroot/stdout.expected
+ echo '+modified alpha' >> $testroot/stdout.expected
+ echo 'blob - /dev/null' >> $testroot/stdout.expected
+ echo 'file + new' >> $testroot/stdout.expected
+ echo '--- /dev/null' >> $testroot/stdout.expected
+ echo '+++ new' >> $testroot/stdout.expected
+ echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected
+ echo '+new file' >> $testroot/stdout.expected
+ echo -n 'blob - ' >> $testroot/stdout.expected
+ got tree -r $testroot/repo -i epsilon | grep 'zeta$' | cut -d' ' -f 1 \
+ >> $testroot/stdout.expected
+ echo 'file + epsilon/zeta' >> $testroot/stdout.expected
+ echo '--- epsilon/zeta' >> $testroot/stdout.expected
+ echo '+++ epsilon/zeta' >> $testroot/stdout.expected
+ echo '@@ -1 +1 @@' >> $testroot/stdout.expected
+ echo '-zeta' >> $testroot/stdout.expected
+ echo '+modified zeta' >> $testroot/stdout.expected
+ echo -n 'blob - ' >> $testroot/stdout.expected
+ got tree -r $testroot/repo -i | grep 'beta$' | cut -d' ' -f 1 \
+ >> $testroot/stdout.expected
+ echo 'file + /dev/null' >> $testroot/stdout.expected
+ echo '--- beta' >> $testroot/stdout.expected
+ echo '+++ /dev/null' >> $testroot/stdout.expected
+ echo '@@ -1 +0,0 @@' >> $testroot/stdout.expected
+ echo '-beta' >> $testroot/stdout.expected
+ (cd $testroot/wt && got diff alpha new epsilon beta \
+ > $testroot/stdout 2> $testroot/stderr)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "diff failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # Two arguments are interpreted as objects if a colliding path exists
+ echo master > $testroot/wt/master
+ (cd $testroot/wt && got add master > /dev/null)
+ (cd $testroot/wt && got diff master new > $testroot/stdout)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "diff failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+ echo "diff refs/heads/master refs/heads/new" > $testroot/stdout.expected
+ # diff between the branches is empty
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+ # same without a work tree
+ (cd $testroot/repo && got diff master new > $testroot/stdout)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "diff failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+ echo "diff refs/heads/master refs/heads/new" > $testroot/stdout.expected
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+ # same with -r argument
+ got diff -r $testroot/repo master new > $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "diff failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+ echo "diff refs/heads/master refs/heads/new" > $testroot/stdout.expected
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # -P can be used to force use of paths
+ (cd $testroot/wt && got diff -P new master > $testroot/stdout)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "diff failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+ echo "diff $head_rev $testroot/wt" > $testroot/stdout.expected
+ echo 'blob - /dev/null' >> $testroot/stdout.expected
+ echo 'file + new' >> $testroot/stdout.expected
+ echo '--- /dev/null' >> $testroot/stdout.expected
+ echo '+++ new' >> $testroot/stdout.expected
+ echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected
+ echo '+new file' >> $testroot/stdout.expected
+ echo 'blob - /dev/null' >> $testroot/stdout.expected
+ echo 'file + master' >> $testroot/stdout.expected
+ echo '--- /dev/null' >> $testroot/stdout.expected
+ echo '+++ master' >> $testroot/stdout.expected
+ echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected
+ echo '+master' >> $testroot/stdout.expected
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # -P can only be used in a work tree
+ got diff -r $testroot/repo -P new master 2> $testroot/stderr
+ ret="$?"
+ if [ "$ret" == "0" ]; then
+ echo "diff succeeded unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+ echo "got: -P option can only be used when diffing a work tree" \
> $testroot/stderr.expected
cmp -s $testroot/stderr.expected $testroot/stderr
ret="$?"
if [ "$ret" != "0" ]; then
diff -u $testroot/stderr.expected $testroot/stderr
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # a single argument which can be resolved to a path is not ambiguous
+ echo "diff $head_rev $testroot/wt" > $testroot/stdout.expected
+ echo 'blob - /dev/null' >> $testroot/stdout.expected
+ echo 'file + new' >> $testroot/stdout.expected
+ echo '--- /dev/null' >> $testroot/stdout.expected
+ echo '+++ new' >> $testroot/stdout.expected
+ echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected
+ echo '+new file' >> $testroot/stdout.expected
+ (cd $testroot/wt && got diff new > $testroot/stdout)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "diff failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # diff with just one object ID argument results in
+ # interpretation of argument as a path
+ (cd $testroot/wt && got diff $head_rev 2> $testroot/stderr)
+ ret="$?"
+ if [ "$ret" = "0" ]; then
+ echo "diff succeeded unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+ echo "got: $head_rev: No such file or directory" \
+ > $testroot/stderr.expected
+ cmp -s $testroot/stderr.expected $testroot/stderr
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stderr.expected $testroot/stderr
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # diff with more than two object arguments results in
+ # interpretation of arguments as paths
+ (cd $testroot/wt && got diff new $head_rev master \
+ > $testroot/stout 2> $testroot/stderr)
+ ret="$?"
+ if [ "$ret" = "0" ]; then
+ echo "diff succeeded unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ echo "diff $head_rev $testroot/wt" > $testroot/stdout.expected
+ echo 'blob - /dev/null' >> $testroot/stdout.expected
+ echo 'file + new' >> $testroot/stdout.expected
+ echo '--- /dev/null' >> $testroot/stdout.expected
+ echo '+++ new' >> $testroot/stdout.expected
+ echo '@@ -0,0 +1 @@' >> $testroot/stdout.expected
+ echo '+new file' >> $testroot/stdout.expected
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ echo "got: $head_rev: No such file or directory" \
+ > $testroot/stderr.expected
+ cmp -s $testroot/stderr.expected $testroot/stderr
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stderr.expected $testroot/stderr
+ return 1
fi
test_done "$testroot" "$ret"
}