From: Stefan Sperling Subject: Re: got: don't search through ignored paths/files on commit To: Stefan Hagen Cc: gameoftrees@openbsd.org Date: Fri, 2 Sep 2022 17:32:46 +0200 On Fri, Sep 02, 2022 at 05:15:19PM +0200, Stefan Hagen wrote: > 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 ok by me, as discussed off-list. > 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 > >