Download raw body.
fix .{cvs,git}ignore handling
If both .cvsignore and .gitignore files exist in a directory, only
.cvsignore will be respected and ignores from the .gitignore will be
dropped, inlined patch fixes that, both files are respected now, the
test case is included.
This work is part of my larger patch where I'd want to add support for
.gitconfig core.excludesfile, this the feature I wanted for a long time,
because in every project I have either Session.vim or cscope.* files,
and it's not feasible to ask to add those to their ignore files,
excludesfile helps here a lot to keep the 'status' output clean.
I decided to split excludesfile proposal in two patches for easier
review, I'll send the second one later.
diff refs/heads/main 4afdcfff1150279725f55deefa98bc97a858eebb
commit - ae25db3f82d89c28505e5fc1f58b8ba693282f5b
commit + 4afdcfff1150279725f55deefa98bc97a858eebb
blob - fca04b3b62b7ecd7035e827c334fa35ad977b7a3
blob + 74a2ceb62249e0a6b2c282d6644bb777c03415b5
--- lib/worktree.c
+++ lib/worktree.c
@@ -3662,6 +3662,11 @@ done:
return err;
}
+struct got_ignores {
+ struct got_pathlist_head cvs;
+ struct got_pathlist_head git;
+};
+
struct diff_dir_cb_arg {
struct got_fileindex *fileindex;
struct got_worktree *worktree;
@@ -3672,8 +3677,7 @@ struct diff_dir_cb_arg {
void *status_arg;
got_cancel_cb cancel_cb;
void *cancel_arg;
- /* A pathlist containing per-directory pathlists of ignore patterns. */
- struct got_pathlist_head *ignores;
+ struct got_ignores *ignores;
int report_unchanged;
int no_ignores;
};
@@ -3778,7 +3782,7 @@ status_old(void *arg, struct got_fileindex_entry *ie,
}
static void
-free_ignores(struct got_pathlist_head *ignores)
+free_ignore_list(struct got_pathlist_head *ignores)
{
struct got_pathlist_entry *pe;
@@ -3790,6 +3794,13 @@ free_ignores(struct got_pathlist_head *ignores)
got_pathlist_free(ignores, GOT_PATHLIST_FREE_ALL);
}
+static void
+free_ignores(struct got_ignores *ignores)
+{
+ free_ignore_list(&ignores->cvs);
+ free_ignore_list(&ignores->git);
+}
+
static const struct got_error *
read_ignores(struct got_pathlist_head *ignores, const char *path, FILE *f)
{
@@ -3882,7 +3893,7 @@ match_path(const char *pattern, size_t pattern_len, co
}
static int
-match_ignores(struct got_pathlist_head *ignores, const char *path)
+match_dir_ignores(struct got_pathlist_head *ignores, const char *path)
{
struct got_pathlist_entry *pe;
@@ -3940,6 +3951,16 @@ match_ignores(struct got_pathlist_head *ignores, const
return 0;
}
+static int
+match_ignores(struct got_ignores *ignores, const char *path)
+{
+ if (match_dir_ignores(&ignores->cvs, path))
+ return 1;
+ if (match_dir_ignores(&ignores->git, path))
+ return 1;
+ return 0;
+}
+
static const struct got_error *
add_ignores(struct got_pathlist_head *ignores, const char *root_path,
const char *path, int dirfd, const char *ignores_filename)
@@ -4034,12 +4055,12 @@ status_traverse(void *arg, const char *path, int dirfd
if (a->no_ignores)
return NULL;
- err = add_ignores(a->ignores, a->worktree->root_path,
+ err = add_ignores(&a->ignores->cvs, a->worktree->root_path,
path, dirfd, ".cvsignore");
if (err)
return err;
- err = add_ignores(a->ignores, a->worktree->root_path, path,
+ err = add_ignores(&a->ignores->git, a->worktree->root_path, path,
dirfd, ".gitignore");
return err;
@@ -4049,7 +4070,7 @@ static const struct got_error *
report_single_file_status(const char *path, const char *ondisk_path,
struct got_fileindex *fileindex, got_worktree_status_cb status_cb,
void *status_arg, struct got_repository *repo, int report_unchanged,
- struct got_pathlist_head *ignores, int no_ignores)
+ struct got_ignores *ignores, int no_ignores)
{
struct got_fileindex_entry *ie;
struct stat sb;
@@ -4077,18 +4098,18 @@ report_single_file_status(const char *path, const char
}
static const struct got_error *
-add_ignores_from_parent_paths(struct got_pathlist_head *ignores,
+add_ignores_from_parent_paths(struct got_ignores *ignores,
const char *root_path, const char *path)
{
const struct got_error *err;
char *parent_path, *next_parent_path = NULL;
- err = add_ignores(ignores, root_path, "", -1,
+ err = add_ignores(&ignores->cvs, root_path, "", -1,
".cvsignore");
if (err)
return err;
- err = add_ignores(ignores, root_path, "", -1,
+ err = add_ignores(&ignores->git, root_path, "", -1,
".gitignore");
if (err)
return err;
@@ -4100,11 +4121,11 @@ add_ignores_from_parent_paths(struct got_pathlist_head
return err;
}
for (;;) {
- err = add_ignores(ignores, root_path, parent_path, -1,
+ err = add_ignores(&ignores->cvs, root_path, parent_path, -1,
".cvsignore");
if (err)
break;
- err = add_ignores(ignores, root_path, parent_path, -1,
+ err = add_ignores(&ignores->git, root_path, parent_path, -1,
".gitignore");
if (err)
break;
@@ -4156,7 +4177,7 @@ static const struct got_error *
report_children(struct got_pathlist_head *children,
struct got_worktree *worktree, struct got_fileindex *fileindex,
struct got_repository *repo, int is_root_dir, int report_unchanged,
- struct got_pathlist_head *ignores, int no_ignores,
+ struct got_ignores *ignores, int no_ignores,
got_worktree_status_cb status_cb, void *status_arg,
got_cancel_cb cancel_cb, void *cancel_arg)
{
@@ -4204,10 +4225,12 @@ worktree_status(struct got_worktree *worktree, const c
struct got_fileindex_diff_dir_cb fdiff_cb;
struct diff_dir_cb_arg arg;
char *ondisk_path = NULL;
- struct got_pathlist_head ignores, missing_children;
+ struct got_ignores ignores;
+ struct got_pathlist_head missing_children;
struct got_fileindex_entry *ie;
- RB_INIT(&ignores);
+ RB_INIT(&ignores.cvs);
+ RB_INIT(&ignores.git);
RB_INIT(&missing_children);
if (asprintf(&ondisk_path, "%s%s%s",
blob - 0874b88152ef2725e3b0e312b01cda5d76c37b91
blob + e8ac4403e2d35fac28fe1b01bfe6242b5ede36c4
--- regress/cmdline/status.sh
+++ regress/cmdline/status.sh
@@ -875,6 +875,88 @@ test_status_multiple_gitignore_files() {
test_done "$testroot" "$ret"
}
+test_status_cvsignore_and_gitignore_together() {
+ local testroot=`test_init status_cvsignore_and_gitignore_together`
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ echo "unversioned file" > $testroot/wt/foo
+ echo "unversioned file" > $testroot/wt/bar
+ echo "unversioned file" > $testroot/wt/baz
+ echo "unversioned file" > $testroot/wt/epsilon/foo
+ echo "unversioned file" > $testroot/wt/epsilon/bar
+ echo "unversioned file" > $testroot/wt/epsilon/baz
+
+ # .{cvs,git}ignore together
+ echo "foo" > $testroot/wt/.cvsignore
+ echo "bar" > $testroot/wt/.gitignore
+ echo "foo" > $testroot/wt/epsilon/.cvsignore
+ echo "bar" > $testroot/wt/epsilon/.gitignore
+
+ echo '? .cvsignore' > $testroot/stdout.expected
+ echo '? .gitignore' >> $testroot/stdout.expected
+ echo '? baz' >> $testroot/stdout.expected
+ echo '? epsilon/.cvsignore' >> $testroot/stdout.expected
+ echo '? epsilon/.gitignore' >> $testroot/stdout.expected
+ echo '? epsilon/baz' >> $testroot/stdout.expected
+ (cd $testroot/wt && got status > $testroot/stdout)
+
+ 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
+
+ # .{cvs,git}ignore in subdir
+ echo '? epsilon/.cvsignore' > $testroot/stdout.expected
+ echo '? epsilon/.gitignore' >> $testroot/stdout.expected
+ echo '? epsilon/baz' >> $testroot/stdout.expected
+ (cd $testroot/wt && got status epsilon > $testroot/stdout)
+
+ 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
+
+ # -I should show files from both ignores
+ cat > $testroot/stdout.expected <<EOF
+? .cvsignore
+? .gitignore
+? bar
+? baz
+? epsilon/.cvsignore
+? epsilon/.gitignore
+? epsilon/bar
+? epsilon/baz
+? epsilon/foo
+? foo
+EOF
+ (cd $testroot/wt && got status -I > $testroot/stdout)
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "got status failed unexpectedly" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ fi
+ test_done "$testroot" "$ret"
+}
+
test_status_status_code() {
local testroot=`test_init status_status_code`
@@ -1247,6 +1329,7 @@ run_test test_status_gitignore_leading_slashes
run_test test_status_gitignore_trailing_slashes
run_test test_status_gitignore_comments
run_test test_status_multiple_gitignore_files
+run_test test_status_cvsignore_and_gitignore_together
run_test test_status_status_code
run_test test_status_suppress
run_test test_status_empty_file
fix .{cvs,git}ignore handling