Commit cbd1af7a5ac90edbfeec7507187896b76710c60e

Stefan Sperling 2019-03-18T16:41:10

make 'got log PATH' work consistently from inside a work tree

diff --git a/got/got.c b/got/got.c
index bae0368..fd0fb74 100644
--- a/got/got.c
+++ b/got/got.c
@@ -200,6 +200,47 @@ apply_unveil(const char *repo_path, int repo_read_only,
 	return NULL;
 }
 
+static const struct got_error *
+resolve_path_in_worktree(char **wt_path, struct got_worktree *worktree,
+    const char *arg)
+{
+	const struct got_error *err = NULL;
+	char *resolved, *path = NULL;
+	size_t len;
+
+	*wt_path = NULL;
+
+	resolved = realpath(arg, NULL);
+	if (resolved == NULL)
+		return got_error_from_errno();
+
+	if (strncmp(got_worktree_get_root_path(worktree), resolved,
+	    strlen(got_worktree_get_root_path(worktree)))) {
+		err = got_error(GOT_ERR_BAD_PATH);
+		goto done;
+	}
+
+	path = strdup(resolved + strlen(got_worktree_get_root_path(worktree)));
+	if (path == NULL) {
+		err = got_error_from_errno();
+		goto done;
+	}
+
+	/* XXX status walk can't deal with trailing slash! */
+	len = strlen(path);
+	while (path[len - 1] == '/') {
+		path[len - 1] = '\0';
+		len--;
+	}
+done:
+	free(resolved);
+	if (err == NULL)
+		*wt_path = path;
+	else
+		free(path);
+	return err;
+}
+
 __dead static void
 usage_checkout(void)
 {
@@ -824,15 +865,6 @@ cmd_log(int argc, char *argv[])
 	argc -= optind;
 	argv += optind;
 
-	if (argc == 0)
-		path = strdup("");
-	else if (argc == 1)
-		path = strdup(argv[0]);
-	else
-		usage_log();
-	if (path == NULL)
-		return got_error_from_errno();
-
 	cwd = getcwd(NULL, 0);
 	if (cwd == NULL) {
 		error = got_error_from_errno();
@@ -844,6 +876,17 @@ cmd_log(int argc, char *argv[])
 		goto done;
 	error = NULL;
 
+	if (argc == 0)
+		path = strdup("");
+	else if (argc == 1) {
+		error = resolve_path_in_worktree(&path, worktree, argv[0]);
+		if (error)
+			goto done;
+	} else
+		usage_log();
+	if (path == NULL)
+		goto done;
+
 	repo_path = worktree ?
 	    strdup(got_worktree_get_repo_path(worktree)) : strdup(cwd);
 	if (repo_path == NULL) {
@@ -1019,47 +1062,6 @@ done:
 }
 
 static const struct got_error *
-get_status_path(char **status_path, struct got_worktree *worktree,
-    const char *arg)
-{
-	const struct got_error *err = NULL;
-	char *resolved, *path = NULL;
-	size_t len;
-
-	*status_path = NULL;
-
-	resolved = realpath(arg, NULL);
-	if (resolved == NULL)
-		return got_error_from_errno();
-
-	if (strncmp(got_worktree_get_root_path(worktree), resolved,
-	    strlen(got_worktree_get_root_path(worktree)))) {
-		err = got_error(GOT_ERR_BAD_PATH);
-		goto done;
-	}
-
-	path = strdup(resolved + strlen(got_worktree_get_root_path(worktree)));
-	if (path == NULL) {
-		err = got_error_from_errno();
-		goto done;
-	}
-
-	/* XXX status walk can't deal with trailing slash! */
-	len = strlen(path);
-	while (path[len - 1] == '/') {
-		path[len - 1] = '\0';
-		len--;
-	}
-done:
-	free(resolved);
-	if (err == NULL)
-		*status_path = path;
-	else
-		free(path);
-	return err;
-}
-
-static const struct got_error *
 cmd_diff(int argc, char *argv[])
 {
 	const struct got_error *error;
@@ -1122,7 +1124,8 @@ cmd_diff(int argc, char *argv[])
 			goto done;
 		}
 		if (argc == 1) {
-			error = get_status_path(&path, worktree, argv[0]);
+			error = resolve_path_in_worktree(&path, worktree,
+			    argv[0]);
 			if (error)
 				goto done;
 		} else {
@@ -1654,7 +1657,7 @@ cmd_status(int argc, char *argv[])
 			goto done;
 		}
 	} else if (argc == 1) {
-		error = get_status_path(&path, worktree, argv[0]);
+		error = resolve_path_in_worktree(&path, worktree, argv[0]);
 		if (error)
 			goto done;
 	} else
diff --git a/regress/cmdline/Makefile b/regress/cmdline/Makefile
index 53654f5..d26e993 100644
--- a/regress/cmdline/Makefile
+++ b/regress/cmdline/Makefile
@@ -10,4 +10,7 @@ update:
 status:
 	./status.sh
 
+log:
+	./log.sh
+
 .include <bsd.regress.mk>
diff --git a/regress/cmdline/log.sh b/regress/cmdline/log.sh
new file mode 100755
index 0000000..1e0c31a
--- /dev/null
+++ b/regress/cmdline/log.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+#
+# Copyright (c) 2019 Stefan Sperling <stsp@openbsd.org>
+#
+# 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.
+
+. ./common.sh
+
+function test_log_in_worktree {
+	local testroot=`test_init log_in_worktree`
+	local head_rev=`git_show_head $testroot/repo`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo "commit $head_rev (master)" > $testroot/stdout.expected
+
+	for p in "" "." alpha epsilon; do
+		(cd $testroot/wt && got log $p | \
+			grep ^commit > $testroot/stdout)
+		cmp $testroot/stdout.expected $testroot/stdout
+		ret="$?"
+		if [ "$ret" != "0" ]; then
+			diff -u $testroot/stdout.expected $testroot/stdout
+			test_done "$testroot" "$ret"
+			return 1
+		fi
+	done
+
+	for p in "" "." zeta; do
+		(cd $testroot/wt/epsilon && got log $p | \
+			grep ^commit > $testroot/stdout)
+		cmp $testroot/stdout.expected $testroot/stdout
+		ret="$?"
+		if [ "$ret" != "0" ]; then
+			diff -u $testroot/stdout.expected $testroot/stdout
+			test_done "$testroot" "$ret"
+			return 1
+		fi
+	done
+
+	test_done "$testroot" "0"
+}
+
+run_test test_log_in_worktree