Commit 90e8619ee9b8bee8f5ded8ee921fd30b186059f4

Stefan Sperling 2019-07-25T19:42:29

make 'got commit' work with a directory path

diff --git a/got/got.1 b/got/got.1
index e28eea6..cb00a11 100644
--- a/got/got.1
+++ b/got/got.1
@@ -472,9 +472,12 @@ it will be restored.
 .It Cm rv
 Short alias for
 .Cm revert .
-.It Cm commit [ Fl m Ar message ] [ file-path ]
+.It Cm commit [ Fl m Ar message ] [ path ]
 Create a new commit in the repository from local changes in a work tree
 and use this commit as the new base commit for the work tree.
+If a
+.Ar path
+is specified, only commit local changes at or within this path.
 .Pp
 Show the status of each affected file, using the following status codes:
 .Bl -column YXZ description
diff --git a/got/got.c b/got/got.c
index 4cbbcf1..3e915e8 100644
--- a/got/got.c
+++ b/got/got.c
@@ -3088,7 +3088,7 @@ done:
 __dead static void
 usage_commit(void)
 {
-	fprintf(stderr, "usage: %s commit [-m msg] file-path\n", getprogname());
+	fprintf(stderr, "usage: %s commit [-m msg] [path]\n", getprogname());
 	exit(1);
 }
 
diff --git a/lib/worktree.c b/lib/worktree.c
index a4aa679..80edb4d 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -3498,10 +3498,18 @@ got_worktree_commit(struct got_object_id **new_commit_id,
 		goto done;
 
 	if (ondisk_path) {
-		err = got_path_skip_common_ancestor(&relpath,
-		    worktree->root_path, ondisk_path);
-		if (err)
-			return err;
+		if (strcmp(ondisk_path, worktree->root_path) == 0) {
+			relpath = strdup("");
+			if (relpath == NULL) {
+				err = got_error_from_errno("strdup");
+				goto done;
+			}
+		} else {
+			err = got_path_skip_common_ancestor(&relpath,
+			    worktree->root_path, ondisk_path);
+			if (err)
+				return err;
+		}
 	}
 
 	err = open_fileindex(&fileindex, &fileindex_path, worktree);
diff --git a/regress/cmdline/commit.sh b/regress/cmdline/commit.sh
index 4cb5ebe..a8ec799 100755
--- a/regress/cmdline/commit.sh
+++ b/regress/cmdline/commit.sh
@@ -381,6 +381,44 @@ function test_commit_path_prefix {
 	test_done "$testroot" "$ret"
 }
 
+function test_commit_dir_path {
+	local testroot=`test_init commit_dir_path`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo "modified alpha" > $testroot/wt/alpha
+	echo "modified zeta" > $testroot/wt/epsilon/zeta
+
+	(cd $testroot/wt && got commit -m 'changed zeta' epsilon \
+		> $testroot/stdout)
+
+	local head_rev=`git_show_head $testroot/repo`
+	echo "M  epsilon/zeta" >> $testroot/stdout.expected
+	echo "Created commit $head_rev" >> $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 "M  alpha" > $testroot/stdout.expected
+	(cd $testroot/wt && got status > $testroot/stdout)
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+	fi
+	test_done "$testroot" "$ret"
+}
+
 run_test test_commit_basic
 run_test test_commit_new_subdir
 run_test test_commit_subdir
@@ -391,3 +429,4 @@ run_test test_commit_rejects_conflicted_file
 run_test test_commit_single_file_multiple
 run_test test_commit_added_and_modified_in_same_dir
 run_test test_commit_path_prefix
+run_test test_commit_dir_path