"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Hagen <sh+got@codevoid.de>
Subject:
got: don't search through ignored paths/files on commit
To:
gameoftrees@openbsd.org
Date:
Fri, 2 Sep 2022 17:15:19 +0200

Download raw body.

Thread
Hi,

I'm using my home directory as worktree checkout (for dotfile 
management). This leads to a super slow "got status" because it
walks through my whole home directory to show unversioned files.

I fixed this by creating a .gitignore file with "**" and I add files 
with got add -I. This works great and "got status" is fast again.

Then I noticed that "got commit" is still very slow and walking through
all files.

I don't think this is necessary, because the commit is only interested 
in files that have been added to the worktree already. And it checks the
tree first before it looks through the file system.

With his patch, got commit behaves like got status and won't look at 
files that are ignored.

Actually, I don't really see a point why it should ever look at files
not added to the worktree before. So we can probably be more drastic
here and disable the file system traversal for commit completely?

Well, this patch makes got nicer for me. And there's a small regress
test that works with and without the change to show that there's no
difference in behavior.

Best Regards,
Stefan

diff /home/sdk/code/got
commit - 1d09d7aab4ab3e72f40b6ea6a78164bf6e6f5477
path + /home/sdk/code/got
blob - f82a9689259ee66048cc0d9c503e6eb31568215b
file + lib/worktree.c
--- lib/worktree.c
+++ lib/worktree.c
@@ -5921,7 +5921,7 @@ got_worktree_commit(struct got_object_id **new_commit_
 	cc_arg.allow_bad_symlinks = allow_bad_symlinks;
 	TAILQ_FOREACH(pe, paths, entry) {
 		err = worktree_status(worktree, pe->path, fileindex, repo,
-		    collect_commitables, &cc_arg, NULL, NULL, 1, 0);
+		    collect_commitables, &cc_arg, NULL, NULL, 0, 0);
 		if (err)
 			goto done;
 	}
blob - 98c2c07a14f46473a38a3a8a4e3118a018b05d80
file + regress/cmdline/commit.sh
--- regress/cmdline/commit.sh
+++ regress/cmdline/commit.sh
@@ -1619,7 +1619,68 @@ test_commit_large_file() {
 
 }
 
+test_commit_gitignore() {
+	local testroot=`test_init commit_gitignores`
 
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	mkdir -p $testroot/wt/tree1/foo
+	mkdir -p $testroot/wt/tree2/foo
+	echo "tree1/**" > $testroot/wt/.gitignore
+	echo "tree2/**" >> $testroot/wt/.gitignore
+	echo -n > $testroot/wt/tree1/bar
+	echo -n > $testroot/wt/tree1/foo/baz
+	echo -n > $testroot/wt/tree2/bar
+	echo -n > $testroot/wt/tree2/foo/baz
+	echo -n > $testroot/wt/epsilon/zeta1
+	echo -n > $testroot/wt/epsilon/zeta2
+
+	(cd $testroot/wt && got add -I -R tree1 > /dev/null)
+	(cd $testroot/wt && got add -I tree2/foo/baz > /dev/null)
+	(cd $testroot/wt && got commit -m "gitignore add" > /dev/null)
+	(cd $testroot/wt && got log -P -l 1 | egrep '^ .' > $testroot/stdout)
+
+	echo ' gitignore add' > $testroot/stdout.expected
+	echo ' A  tree1/bar' >> $testroot/stdout.expected
+	echo ' A  tree1/foo/baz' >> $testroot/stdout.expected
+	echo ' A  tree2/foo/baz' >> $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
+
+	echo touch > $testroot/wt/tree1/bar
+	echo touch > $testroot/wt/tree1/foo/baz
+	echo touch > $testroot/wt/epsilon/zeta1
+
+	(cd $testroot/wt && got commit -m "gitignore change" > /dev/null)
+	(cd $testroot/wt && got log -P -l 1 | egrep '^ .' > $testroot/stdout)
+
+	echo ' gitignore change' > $testroot/stdout.expected
+	echo ' M  tree1/bar' >> $testroot/stdout.expected
+	echo ' M  tree1/foo/baz' >> $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
+
+	test_done "$testroot" "$ret"
+}
+
+
 test_parseargs "$@"
 run_test test_commit_basic
 run_test test_commit_new_subdir
@@ -1648,3 +1709,4 @@ run_test test_commit_symlink
 run_test test_commit_fix_bad_symlink
 run_test test_commit_prepared_logmsg
 run_test test_commit_large_file
+run_test test_commit_gitignore