git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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 v4 04/19] Teach Git to respect skip-worktree bit (reading part)
Date: Thu, 20 Aug 2009 20:46:58 +0700	[thread overview]
Message-ID: <1250776033-12395-5-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1250776033-12395-4-git-send-email-pclouds@gmail.com>

grep: turn on --cached for files that is marked skip-worktree
ls-files: do not check for deleted file that is marked skip-worktree
update-index: ignore update request if it's skip-worktree, while still allows removing
diff*: skip worktree version

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin-commit.c                 |    5 +
 builtin-grep.c                   |    2 +-
 builtin-ls-files.c               |    2 +
 builtin-update-index.c           |   38 +++++----
 diff-lib.c                       |    5 +-
 diff.c                           |    2 +-
 read-cache.c                     |    8 +--
 t/t7011-skip-worktree-reading.sh |  163 ++++++++++++++++++++++++++++++++++++++
 8 files changed, 199 insertions(+), 26 deletions(-)
 create mode 100755 t/t7011-skip-worktree-reading.sh

diff --git a/builtin-commit.c b/builtin-commit.c
index 200ffda..cb64cde 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -181,6 +181,11 @@ static void add_remove_files(struct string_list *list)
 	for (i = 0; i < list->nr; i++) {
 		struct stat st;
 		struct string_list_item *p = &(list->items[i]);
+		int pos = index_name_pos(&the_index, p->string, strlen(p->string));
+		struct cache_entry *ce = pos < 0 ? NULL : active_cache[pos];
+
+		if (ce && ce_skip_worktree(ce))
+			continue;
 
 		if (!lstat(p->string, &st)) {
 			if (add_to_cache(p->string, &st, 0))
diff --git a/builtin-grep.c b/builtin-grep.c
index ad0e0a5..813fe97 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -517,7 +517,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached,
 		 * are identical, even if worktree file has been modified, so use
 		 * cache version instead
 		 */
-		if (cached || (ce->ce_flags & CE_VALID)) {
+		if (cached || (ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) {
 			if (ce_stage(ce))
 				continue;
 			hit |= grep_sha1(opt, ce->sha1, ce->name, 0);
diff --git a/builtin-ls-files.c b/builtin-ls-files.c
index c1afbad..ad7e447 100644
--- a/builtin-ls-files.c
+++ b/builtin-ls-files.c
@@ -194,6 +194,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
 				continue;
 			if (ce->ce_flags & CE_UPDATE)
 				continue;
+			if (ce_skip_worktree(ce))
+				continue;
 			err = lstat(ce->name, &st);
 			if (show_deleted && err)
 				show_ce_entry(tag_removed, ce);
diff --git a/builtin-update-index.c b/builtin-update-index.c
index 5e97d09..97b9ea6 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -172,29 +172,29 @@ static int process_directory(const char *path, int len, struct stat *st)
 	return error("%s: is a directory - add files inside instead", path);
 }
 
-/*
- * Process a regular file
- */
-static int process_file(const char *path, int len, struct stat *st)
-{
-	int pos = cache_name_pos(path, len);
-	struct cache_entry *ce = pos < 0 ? NULL : active_cache[pos];
-
-	if (ce && S_ISGITLINK(ce->ce_mode))
-		return error("%s is already a gitlink, not replacing", path);
-
-	return add_one_path(ce, path, len, st);
-}
-
 static int process_path(const char *path)
 {
-	int len;
+	int pos, len;
 	struct stat st;
+	struct cache_entry *ce;
 
 	len = strlen(path);
 	if (has_symlink_leading_path(path, len))
 		return error("'%s' is beyond a symbolic link", path);
 
+	pos = cache_name_pos(path, len);
+	ce = pos < 0 ? NULL : active_cache[pos];
+	if (ce && ce_skip_worktree(ce)) {
+		/*
+		 * working directory version is assumed "good"
+		 * so updating it does not make sense.
+		 * On the other hand, removing it from index should work
+		 */
+		if (allow_remove && remove_file_from_cache(path))
+			return error("%s: cannot remove from the index", path);
+		return 0;
+	}
+
 	/*
 	 * First things first: get the stat information, to decide
 	 * what to do about the pathname!
@@ -205,7 +205,13 @@ static int process_path(const char *path)
 	if (S_ISDIR(st.st_mode))
 		return process_directory(path, len, &st);
 
-	return process_file(path, len, &st);
+	/*
+	 * Process a regular file
+	 */
+	if (ce && S_ISGITLINK(ce->ce_mode))
+		return error("%s is already a gitlink, not replacing", path);
+
+	return add_one_path(ce, path, len, &st);
 }
 
 static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
diff --git a/diff-lib.c b/diff-lib.c
index e7e8e88..fc98678 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -159,7 +159,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
 				continue;
 		}
 
-		if (ce_uptodate(ce))
+		if (ce_uptodate(ce) || ce_skip_worktree(ce))
 			continue;
 
 		changed = check_removed(ce, &st);
@@ -321,6 +321,8 @@ static void do_oneway_diff(struct unpack_trees_options *o,
 	struct rev_info *revs = o->unpack_data;
 	int match_missing, cached;
 
+	/* if the entry is not checked out, don't examine work tree */
+	cached = o->index_only || (idx && ce_skip_worktree(idx));
 	/*
 	 * Backward compatibility wart - "diff-index -m" does
 	 * not mean "do not ignore merges", but "match_missing".
@@ -328,7 +330,6 @@ static void do_oneway_diff(struct unpack_trees_options *o,
 	 * But with the revision flag parsing, that's found in
 	 * "!revs->ignore_merges".
 	 */
-	cached = o->index_only;
 	match_missing = !revs->ignore_merges;
 
 	if (cached && idx && ce_stage(idx)) {
diff --git a/diff.c b/diff.c
index 91d6ea2..215e6b3 100644
--- a/diff.c
+++ b/diff.c
@@ -1805,7 +1805,7 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
 	 * If ce is marked as "assume unchanged", there is no
 	 * guarantee that work tree matches what we are looking for.
 	 */
-	if (ce->ce_flags & CE_VALID)
+	if ((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce))
 		return 0;
 
 	/*
diff --git a/read-cache.c b/read-cache.c
index 4e3e272..5ee7d9d 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -265,7 +265,7 @@ int ie_match_stat(const struct index_state *istate,
 	 * If it's marked as always valid in the index, it's
 	 * valid whatever the checked-out copy says.
 	 */
-	if (!ignore_valid && (ce->ce_flags & CE_VALID))
+	if (!ignore_valid && ((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)))
 		return 0;
 
 	/*
@@ -1004,11 +1004,7 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
 	if (ce_uptodate(ce))
 		return ce;
 
-	/*
-	 * CE_VALID means the user promised us that the change to
-	 * the work tree does not matter and told us not to worry.
-	 */
-	if (!ignore_valid && (ce->ce_flags & CE_VALID)) {
+	if (!ignore_valid && ((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce))) {
 		ce_mark_uptodate(ce);
 		return ce;
 	}
diff --git a/t/t7011-skip-worktree-reading.sh b/t/t7011-skip-worktree-reading.sh
new file mode 100755
index 0000000..e996928
--- /dev/null
+++ b/t/t7011-skip-worktree-reading.sh
@@ -0,0 +1,163 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Nguyễn Thái Ngọc Duy
+#
+
+test_description='skip-worktree bit test'
+
+. ./test-lib.sh
+
+cat >expect.full <<EOF
+H 1
+H 2
+H init.t
+H sub/1
+H sub/2
+EOF
+
+cat >expect.skip <<EOF
+S 1
+H 2
+H init.t
+S sub/1
+H sub/2
+EOF
+
+NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
+ZERO_SHA0=0000000000000000000000000000000000000000
+setup_absent() {
+	test -f 1 && rm 1
+	git update-index --remove 1 &&
+	git update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&
+	git update-index --skip-worktree 1
+}
+
+test_absent() {
+	echo "100644 $NULL_SHA1 0	1" > expected &&
+	git ls-files --stage 1 > result &&
+	test_cmp expected result &&
+	test ! -f 1
+}
+
+setup_dirty() {
+	git update-index --force-remove 1 &&
+	echo dirty > 1 &&
+	git update-index --add --cacheinfo 100644 $NULL_SHA1 1 &&
+	git update-index --skip-worktree 1
+}
+
+test_dirty() {
+	echo "100644 $NULL_SHA1 0	1" > expected &&
+	git ls-files --stage 1 > result &&
+	test_cmp expected result &&
+	echo dirty > expected
+	test_cmp expected 1
+}
+
+test_expect_success 'setup' '
+	test_commit init &&
+	mkdir sub &&
+	touch ./1 ./2 sub/1 sub/2 &&
+	git add 1 2 sub/1 sub/2 &&
+	git update-index --skip-worktree 1 sub/1 &&
+	git ls-files -t > result &&
+	test_cmp expect.skip result
+'
+
+test_expect_success 'update-index' '
+	setup_absent &&
+	git update-index 1 &&
+	test_absent
+'
+
+test_expect_success 'update-index' '
+	setup_dirty &&
+	git update-index 1 &&
+	test_dirty
+'
+
+test_expect_success 'update-index --remove' '
+	setup_absent &&
+	git update-index --remove 1 &&
+	test -z "$(git ls-files 1)" &&
+	test ! -f 1
+'
+
+test_expect_success 'update-index --remove' '
+	setup_dirty &&
+	git update-index --remove 1 &&
+	test -z "$(git ls-files 1)" &&
+	echo dirty > expected &&
+	test_cmp expected 1
+'
+
+test_expect_success 'ls-files --delete' '
+	setup_absent &&
+	test -z "$(git ls-files -d)"
+'
+
+test_expect_success 'ls-files --delete' '
+	setup_dirty &&
+	test -z "$(git ls-files -d)"
+'
+
+test_expect_success 'ls-files --modified' '
+	setup_absent &&
+	test -z "$(git ls-files -m)"
+'
+
+test_expect_success 'ls-files --modified' '
+	setup_dirty &&
+	test -z "$(git ls-files -m)"
+'
+
+test_expect_success 'grep with skip-worktree file' '
+	git update-index --no-skip-worktree 1 &&
+	echo test > 1 &&
+	git update-index 1 &&
+	git update-index --skip-worktree 1 &&
+	rm 1 &&
+	test "$(git grep --no-ext-grep test)" = "1:test"
+'
+
+echo ":000000 100644 $ZERO_SHA0 $NULL_SHA1 A	1" > expected
+test_expect_success 'diff-index does not examine skip-worktree absent entries' '
+	setup_absent &&
+	git diff-index HEAD -- 1 > result &&
+	test_cmp expected result
+'
+
+test_expect_success 'diff-index does not examine skip-worktree dirty entries' '
+	setup_dirty &&
+	git diff-index HEAD -- 1 > result &&
+	test_cmp expected result
+'
+
+test_expect_success 'diff-files does not examine skip-worktree absent entries' '
+	setup_absent &&
+	test -z "$(git diff-files -- one)"
+'
+
+test_expect_success 'diff-files does not examine skip-worktree dirty entries' '
+	setup_dirty &&
+	test -z "$(git diff-files -- one)"
+'
+
+test_expect_success 'git-rm succeeds on skip-worktree absent entries' '
+	setup_absent &&
+	git rm 1
+'
+
+test_expect_failure 'commit on skip-worktree absent entries' '
+	git reset &&
+	setup_absent &&
+	test_must_fail git commit -m null 1
+'
+
+test_expect_failure 'commit on skip-worktree dirty entries' '
+	git reset &&
+	setup_dirty &&
+	test_must_fail git commit -m null 1
+'
+
+test_done
-- 
1.6.3.GIT

  reply	other threads:[~2009-08-20 13:49 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-08-20 13:46 [RFC PATCH v4 00/19] Sparse checkout Nguyễn Thái Ngọc Duy
2009-08-20 13:46 ` [RFC PATCH v4 01/19] update-index: refactor mark_valid() in preparation for new options Nguyễn Thái Ngọc Duy
2009-08-20 13:46   ` [RFC PATCH v4 02/19] Add test-index-version Nguyễn Thái Ngọc Duy
2009-08-20 13:46     ` [RFC PATCH v4 03/19] Introduce "skip-worktree" bit in index, teach Git to get/set this bit Nguyễn Thái Ngọc Duy
2009-08-20 13:46       ` Nguyễn Thái Ngọc Duy [this message]
2009-08-20 13:46         ` [RFC PATCH v4 05/19] Teach Git to respect skip-worktree bit (writing part) Nguyễn Thái Ngọc Duy
2009-08-20 13:47           ` [RFC PATCH v4 06/19] Avoid writing to buffer in add_excludes_from_file_1() Nguyễn Thái Ngọc Duy
2009-08-20 13:47             ` [RFC PATCH v4 07/19] Read .gitignore from index if it is skip-worktree Nguyễn Thái Ngọc Duy
2009-08-20 13:47               ` [RFC PATCH v4 08/19] unpack-trees(): carry skip-worktree bit over in merged_entry() Nguyễn Thái Ngọc Duy
2009-08-20 13:47                 ` [RFC PATCH v4 09/19] excluded_1(): support exclude files in index Nguyễn Thái Ngọc Duy
2009-08-20 13:47                   ` [RFC PATCH v4 10/19] dir.c: export excluded_1() and add_excludes_from_file_1() Nguyễn Thái Ngọc Duy
2009-08-20 13:47                     ` [RFC PATCH v4 11/19] Introduce "sparse checkout" Nguyễn Thái Ngọc Duy
2009-08-20 13:47                       ` [RFC PATCH v4 12/19] unpack-trees(): add CE_WT_REMOVE to remove on worktree alone Nguyễn Thái Ngọc Duy
2009-08-20 13:47                         ` [RFC PATCH v4 13/19] unpack-trees.c: generalize verify_* functions Nguyễn Thái Ngọc Duy
2009-08-20 13:47                           ` [RFC PATCH v4 14/19] unpack-trees(): "enable" sparse checkout and load $GIT_DIR/info/sparse-checkout Nguyễn Thái Ngọc Duy
2009-08-20 13:47                             ` [RFC PATCH v4 15/19] unpack_trees(): apply $GIT_DIR/info/sparse-checkout to the final index Nguyễn Thái Ngọc Duy
2009-08-20 13:47                               ` [RFC PATCH v4 16/19] unpack-trees(): ignore worktree check outside checkout area Nguyễn Thái Ngọc Duy
2009-08-20 13:47                                 ` [RFC PATCH v4 17/19] read-tree: add --no-sparse-checkout to disable sparse checkout support Nguyễn Thái Ngọc Duy
2009-08-20 13:47                                   ` [RFC PATCH v4 18/19] Add tests for sparse checkout Nguyễn Thái Ngọc Duy
2009-08-20 13:47                                     ` [RFC PATCH v4 19/19] sparse checkout: inhibit empty worktree Nguyễn Thái Ngọc Duy
2009-08-21  9:19         ` [RFC PATCH v4 04/19] Teach Git to respect skip-worktree bit (reading part) Nguyen Thai Ngoc Duy
2009-08-21 17:32           ` Junio C Hamano
2009-08-22 11:56             ` Nguyen Thai Ngoc Duy
2009-08-20 15:21 ` [RFC PATCH v4 00/19] Sparse checkout Jakub Narebski
2009-08-20 15:31   ` Matthieu Moy
2009-08-21  7:50 ` Junio C Hamano
2009-08-21  9:15   ` Nguyen Thai Ngoc Duy

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=1250776033-12395-5-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).