From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [RFC PATCH v2 2/4] gitignore: read from index if .gitignore is assume-unchanged
Date: Mon, 10 Aug 2009 22:19:20 +0700 [thread overview]
Message-ID: <1249917562-5931-3-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1249917562-5931-2-git-send-email-pclouds@gmail.com>
In sparse checkout mode (aka CE_VALID or assume-unchanged) some files
may be missing from working directory. If some of those files are
.gitignore, it will affect how git excludes files.
Because those files are by definition "assume unchanged" we can
instead read them from index. This adds index as a prerequisite for
directory listing. At the moment directory listing is used by "git
clean", "git add", "git ls-files" and "git status"/"git commit" and
unpack_trees()-related commands. These commands have been
checked/modified to populate index before doing directory listing.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
Documentation/technical/api-directory-listing.txt | 3 +
builtin-clean.c | 5 +-
builtin-ls-files.c | 4 +-
dir.c | 70 ++++++++++++++-------
t/t3001-ls-files-others-exclude.sh | 20 ++++++
t/t7300-clean.sh | 19 ++++++
6 files changed, 96 insertions(+), 25 deletions(-)
diff --git a/Documentation/technical/api-directory-listing.txt b/Documentation/technical/api-directory-listing.txt
index 5bbd18f..7d0e282 100644
--- a/Documentation/technical/api-directory-listing.txt
+++ b/Documentation/technical/api-directory-listing.txt
@@ -58,6 +58,9 @@ The result of the enumeration is left in these fields::
Calling sequence
----------------
+* Ensure the_index is populated as it may have CE_VALID entries that
+ affect directory listing.
+
* Prepare `struct dir_struct dir` and clear it with `memset(&dir, 0,
sizeof(dir))`.
diff --git a/builtin-clean.c b/builtin-clean.c
index 2d8c735..d917472 100644
--- a/builtin-clean.c
+++ b/builtin-clean.c
@@ -71,8 +71,11 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
- if (!ignored)
+ if (!ignored) {
+ if (read_cache() < 0)
+ die("index file corrupt");
setup_standard_excludes(&dir);
+ }
pathspec = get_pathspec(prefix, argv);
read_cache();
diff --git a/builtin-ls-files.c b/builtin-ls-files.c
index f473220..d1a23c4 100644
--- a/builtin-ls-files.c
+++ b/builtin-ls-files.c
@@ -481,6 +481,9 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
prefix_offset = strlen(prefix);
git_config(git_default_config, NULL);
+ if (read_cache() < 0)
+ die("index file corrupt");
+
argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
ls_files_usage, 0);
if (show_tag || show_valid_bit) {
@@ -508,7 +511,6 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
pathspec = get_pathspec(prefix, argv);
/* be nice with submodule paths ending in a slash */
- read_cache();
if (pathspec)
strip_trailing_slash_from_submodules();
diff --git a/dir.c b/dir.c
index e05b850..e55344f 100644
--- a/dir.c
+++ b/dir.c
@@ -200,11 +200,36 @@ void add_exclude(const char *string, const char *base,
which->excludes[which->nr++] = x;
}
+static void *read_index_data(const char *path, size_t *size)
+{
+ int pos, len;
+ unsigned long sz;
+ enum object_type type;
+ void *data;
+ struct index_state *istate = &the_index;
+
+ len = strlen(path);
+ pos = index_name_pos(istate, path, len);
+ if (pos < 0)
+ return NULL;
+ /* only applies to CE_VALID entries */
+ if (!(istate->cache[pos]->ce_flags & CE_VALID))
+ return NULL;
+ data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
+ if (!data || type != OBJ_BLOB) {
+ free(data);
+ return NULL;
+ }
+ *size = xsize_t(sz);
+ return data;
+}
+
static int add_excludes_from_file_1(const char *fname,
const char *base,
int baselen,
char **buf_p,
- struct exclude_list *which)
+ struct exclude_list *which,
+ int check_index)
{
struct stat st;
int fd, i;
@@ -212,27 +237,31 @@ static int add_excludes_from_file_1(const char *fname,
char *buf, *entry;
fd = open(fname, O_RDONLY);
- if (fd < 0 || fstat(fd, &st) < 0)
- goto err;
- size = xsize_t(st.st_size);
- if (size == 0) {
- close(fd);
- return 0;
+ if (fd < 0 || fstat(fd, &st) < 0) {
+ if (0 <= fd)
+ close(fd);
+ if (!check_index || (buf = read_index_data(fname, &size)) == NULL)
+ return -1;
}
- buf = xmalloc(size+1);
- if (read_in_full(fd, buf, size) != size)
- {
- free(buf);
- goto err;
+ else {
+ size = xsize_t(st.st_size);
+ if (size == 0) {
+ close(fd);
+ return 0;
+ }
+ buf = xmalloc(size);
+ if (read_in_full(fd, buf, size) != size) {
+ close(fd);
+ return -1;
+ }
+ close(fd);
}
- close(fd);
if (buf_p)
*buf_p = buf;
- buf[size++] = '\n';
entry = buf;
- for (i = 0; i < size; i++) {
- if (buf[i] == '\n') {
+ for (i = 0; i <= size; i++) {
+ if (i == size || buf[i] == '\n') {
if (entry != buf + i && entry[0] != '#') {
buf[i - (i && buf[i-1] == '\r')] = 0;
add_exclude(entry, base, baselen, which);
@@ -241,17 +270,12 @@ static int add_excludes_from_file_1(const char *fname,
}
}
return 0;
-
- err:
- if (0 <= fd)
- close(fd);
- return -1;
}
void add_excludes_from_file(struct dir_struct *dir, const char *fname)
{
if (add_excludes_from_file_1(fname, "", 0, NULL,
- &dir->exclude_list[EXC_FILE]) < 0)
+ &dir->exclude_list[EXC_FILE], 0) < 0)
die("cannot use %s as an exclude file", fname);
}
@@ -302,7 +326,7 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
strcpy(dir->basebuf + stk->baselen, dir->exclude_per_dir);
add_excludes_from_file_1(dir->basebuf,
dir->basebuf, stk->baselen,
- &stk->filebuf, el);
+ &stk->filebuf, el, 1);
dir->exclude_stack = stk;
current = stk->baselen;
}
diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh
index c65bca8..88b69bc 100755
--- a/t/t3001-ls-files-others-exclude.sh
+++ b/t/t3001-ls-files-others-exclude.sh
@@ -85,6 +85,26 @@ test_expect_success \
>output &&
test_cmp expect output'
+test_expect_success 'setup sparse gitignore' '
+ git add .gitignore one/.gitignore one/two/.gitignore &&
+ git update-index --assume-unchanged .gitignore one/.gitignore one/two/.gitignore &&
+ rm .gitignore one/.gitignore one/two/.gitignore
+'
+
+test_expect_success \
+ 'git ls-files --others with various exclude options.' \
+ 'git ls-files --others \
+ --exclude=\*.6 \
+ --exclude-per-directory=.gitignore \
+ --exclude-from=.git/ignore \
+ >output &&
+ test_cmp expect output'
+
+test_expect_success 'restore gitignore' '
+ git checkout .gitignore one/.gitignore one/two/.gitignore &&
+ rm .git/index
+'
+
cat > excludes-file <<\EOF
*.[1-8]
e*
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 929d5d4..4886d5f 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -22,6 +22,25 @@ test_expect_success 'setup' '
'
+test_expect_success 'git clean with assume-unchanged .gitignore' '
+ git update-index --assume-unchanged .gitignore &&
+ rm .gitignore &&
+ mkdir -p build docs &&
+ touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
+ git clean &&
+ test -f Makefile &&
+ test -f README &&
+ test -f src/part1.c &&
+ test -f src/part2.c &&
+ test ! -f a.out &&
+ test ! -f src/part3.c &&
+ test -f docs/manual.txt &&
+ test -f obj.o &&
+ test -f build/lib.so &&
+ git update-index --no-assume-unchanged .gitignore &&
+ git checkout .gitignore
+'
+
test_expect_success 'git clean' '
mkdir -p build docs &&
--
1.6.3.GIT
next prev parent reply other threads:[~2009-08-10 15:20 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-08-10 15:19 [RFC PATCH v2 0/4] Sparse checkout Nguyễn Thái Ngọc Duy
2009-08-10 15:19 ` [RFC PATCH v2 1/4] Prevent diff machinery from examining assume-unchanged entries on worktree Nguyễn Thái Ngọc Duy
2009-08-10 15:19 ` Nguyễn Thái Ngọc Duy [this message]
2009-08-10 15:19 ` [RFC PATCH v2 3/4] unpack_trees(): add support for sparse checkout Nguyễn Thái Ngọc Duy
2009-08-10 15:19 ` [RFC PATCH v2 4/4] read-tree: add --no-sparse to turn off sparse hook Nguyễn Thái Ngọc Duy
2009-08-10 16:46 ` Johannes Schindelin
2009-08-11 1:38 ` Nguyen Thai Ngoc Duy
2009-08-11 5:13 ` Junio C Hamano
2009-08-11 6:50 ` Johannes Schindelin
2009-08-11 7:08 ` Nguyen Thai Ngoc Duy
2009-08-10 16:41 ` [RFC PATCH v2 3/4] unpack_trees(): add support for sparse checkout Johannes Schindelin
2009-08-11 1:47 ` Nguyen Thai Ngoc Duy
2009-08-11 7:02 ` Johannes Schindelin
2009-08-10 16:33 ` [RFC PATCH v2 2/4] gitignore: read from index if .gitignore is assume-unchanged Johannes Schindelin
2009-08-11 1:57 ` Nguyen Thai Ngoc Duy
2009-08-11 8:12 ` Johannes Schindelin
2009-08-10 16:20 ` [RFC PATCH v2 1/4] Prevent diff machinery from examining assume-unchanged entries on worktree Johannes Schindelin
2009-08-11 1:34 ` Nguyen Thai Ngoc Duy
2009-08-11 6:45 ` Johannes Schindelin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1249917562-5931-3-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).