[RFC PATCH] ce_uptodate(): discriminate lstat()-based and assume-unchanged uptodate

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Commit 1dcafcc (verify_uptodate(): add ce_uptodate(ce) test) makes me
realize that people might not be well aware of assume-unchanged bit (CE_VALID).

Back when there was no assume-unchanged bit, ce_uptodate() means that
entry is really uptodate and has been checked by lstat(). When
assume-unchanged comes into play, it will blindly mark an entry
uptodate if that entry is assume-unchanged.

Even if it is assume-unchanged, it may have local changes that users
may want to keep. Thus when it comes to updating worktree, we may need to
know if it is _really_ uptodate regardless assume-unchanged. For that
matter, ce_uptodate() does not help much as it could be a result of
lstat() or assume-unchanged bit.

This patch attempts to make Git developers think twice about that
by.. getting rid of ce_uptodate() in favor of two new macros
ce_maybe_uptodate() and ce_really_uptodate()

 - ce_maybe_uptodate() works as ce_uptodate() does now.
 - ce_really_uptodate() is true only if it is lstat()-based uptodate.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx>
---
 OK I could not stop looking at CE_VALID :-) I think this is a good
 change. However I may have made mistakes in translating from
 ce_uptodate() to ce_{maybe,really}_uptodate().

 cache.h         |   14 ++++++++++++--
 diff-lib.c      |    6 +++---
 diff.c          |    2 +-
 dir.c           |    4 ++--
 preload-index.c |    4 ++--
 read-cache.c    |   12 ++++++------
 unpack-trees.c  |    4 ++--
 7 files changed, 28 insertions(+), 18 deletions(-)

diff --git a/cache.h b/cache.h
index f793789..24f66ab 100644
--- a/cache.h
+++ b/cache.h
@@ -176,6 +176,7 @@ struct cache_entry {
 
 #define CE_HASHED    (0x100000)
 #define CE_UNHASHED  (0x200000)
+#define CE_ASSUME_UPTODATE (0x800000)
 
 /*
  * Extended on-disk flags
@@ -232,8 +233,9 @@ static inline size_t ce_namelen(const struct cache_entry *ce)
 			    ondisk_cache_entry_extended_size(ce_namelen(ce)) : \
 			    ondisk_cache_entry_size(ce_namelen(ce)))
 #define ce_stage(ce) ((CE_STAGEMASK & (ce)->ce_flags) >> CE_STAGESHIFT)
-#define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE)
-#define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE)
+#define ce_maybe_uptodate(ce) ((ce)->ce_flags & (CE_UPTODATE | CE_ASSUME_UPTODATE))
+#define ce_really_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE)
+/* #define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE) */
 
 #define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)
 static inline unsigned int create_ce_mode(unsigned int mode)
@@ -463,6 +465,14 @@ extern int index_name_is_other(const struct index_state *, const char *, int);
 extern int ie_match_stat(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
 extern int ie_modified(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
 
+static inline void ce_mark_uptodate(struct cache_entry *ce, int options)
+{
+	if ((ce->ce_flags & CE_VALID) && !(options & CE_MATCH_IGNORE_VALID))
+		ce->ce_flags |= CE_ASSUME_UPTODATE;
+	else
+		ce->ce_flags |= CE_UPTODATE;
+}
+
 extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
 extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);
 extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
diff --git a/diff-lib.c b/diff-lib.c
index e7e8e88..9cbfec0 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_maybe_uptodate(ce))
 			continue;
 
 		changed = check_removed(ce, &st);
@@ -176,7 +176,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
 		}
 		changed = ce_match_stat(ce, &st, ce_option);
 		if (!changed) {
-			ce_mark_uptodate(ce);
+			ce_mark_uptodate(ce, ce_option);
 			if (!DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER))
 				continue;
 		}
@@ -214,7 +214,7 @@ static int get_stat_data(struct cache_entry *ce,
 	const unsigned char *sha1 = ce->sha1;
 	unsigned int mode = ce->ce_mode;
 
-	if (!cached && !ce_uptodate(ce)) {
+	if (!cached && !ce_really_uptodate(ce)) {
 		int changed;
 		struct stat st;
 		changed = check_removed(ce, &st);
diff --git a/diff.c b/diff.c
index 91d6ea2..7b94fb9 100644
--- a/diff.c
+++ b/diff.c
@@ -1811,7 +1811,7 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
 	/*
 	 * If ce matches the file in the work tree, we can reuse it.
 	 */
-	if (ce_uptodate(ce) ||
+	if (ce_really_uptodate(ce) ||
 	    (!lstat(name, &st) && !ce_match_stat(ce, &st, 0)))
 		return 1;
 
diff --git a/dir.c b/dir.c
index d0999ba..64f0fc6 100644
--- a/dir.c
+++ b/dir.c
@@ -573,7 +573,7 @@ static int get_index_dtype(const char *path, int len)
 
 	ce = cache_name_exists(path, len, 0);
 	if (ce) {
-		if (!ce_uptodate(ce))
+		if (!ce_maybe_uptodate(ce))
 			return DT_UNKNOWN;
 		if (S_ISGITLINK(ce->ce_mode))
 			return DT_DIR;
@@ -597,7 +597,7 @@ static int get_index_dtype(const char *path, int len)
 			break;
 		if (ce->name[len] < '/')
 			continue;
-		if (!ce_uptodate(ce))
+		if (!ce_maybe_uptodate(ce))
 			break;	/* continue? */
 		return DT_DIR;
 	}
diff --git a/preload-index.c b/preload-index.c
index 9289933..85c31c5 100644
--- a/preload-index.c
+++ b/preload-index.c
@@ -47,7 +47,7 @@ static void *preload_thread(void *_data)
 
 		if (ce_stage(ce))
 			continue;
-		if (ce_uptodate(ce))
+		if (ce_maybe_uptodate(ce))
 			continue;
 		if (!ce_path_match(ce, p->pathspec))
 			continue;
@@ -57,7 +57,7 @@ static void *preload_thread(void *_data)
 			continue;
 		if (ie_match_stat(index, ce, &st, CE_MATCH_RACY_IS_DIRTY))
 			continue;
-		ce_mark_uptodate(ce);
+		ce_mark_uptodate(ce, 0);
 	} while (--nr > 0);
 	return NULL;
 }
diff --git a/read-cache.c b/read-cache.c
index 4e3e272..ac7cdd3 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -81,7 +81,7 @@ void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
 		ce->ce_flags |= CE_VALID;
 
 	if (S_ISREG(st->st_mode))
-		ce_mark_uptodate(ce);
+		ce_mark_uptodate(ce, CE_MATCH_IGNORE_VALID);
 }
 
 static int ce_compare_data(struct cache_entry *ce, struct stat *st)
@@ -605,7 +605,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
 	if (alias && !ce_stage(alias) && !ie_match_stat(istate, alias, st, ce_option)) {
 		/* Nothing changed, really */
 		free(ce);
-		ce_mark_uptodate(alias);
+		ce_mark_uptodate(alias, ce_option);
 		alias->ce_flags |= CE_ADDED;
 		return 0;
 	}
@@ -1001,7 +1001,7 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
 	int changed, size;
 	int ignore_valid = options & CE_MATCH_IGNORE_VALID;
 
-	if (ce_uptodate(ce))
+	if (ce_maybe_uptodate(ce))
 		return ce;
 
 	/*
@@ -1009,7 +1009,7 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
 	 * the work tree does not matter and told us not to worry.
 	 */
 	if (!ignore_valid && (ce->ce_flags & CE_VALID)) {
-		ce_mark_uptodate(ce);
+		ce_mark_uptodate(ce, options);
 		return ce;
 	}
 
@@ -1037,7 +1037,7 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
 			 * because CE_UPTODATE flag is in-core only;
 			 * we are not going to write this change out.
 			 */
-			ce_mark_uptodate(ce);
+			ce_mark_uptodate(ce, options);
 			return ce;
 		}
 	}
@@ -1543,7 +1543,7 @@ int write_index(struct index_state *istate, int newfd)
 		struct cache_entry *ce = cache[i];
 		if (ce->ce_flags & CE_REMOVE)
 			continue;
-		if (!ce_uptodate(ce) && is_racy_timestamp(istate, ce))
+		if (!ce_maybe_uptodate(ce) && is_racy_timestamp(istate, ce))
 			ce_smudge_racily_clean_entry(ce);
 		if (ce_write_entry(&c, newfd, ce) < 0)
 			return -1;
diff --git a/unpack-trees.c b/unpack-trees.c
index 720f7a1..c0774d7 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -450,7 +450,7 @@ static int verify_uptodate(struct cache_entry *ce,
 {
 	struct stat st;
 
-	if (o->index_only || o->reset || ce_uptodate(ce))
+	if (o->index_only || o->reset || ce_really_uptodate(ce))
 		return 0;
 
 	if (!lstat(ce->name, &st)) {
@@ -1004,7 +1004,7 @@ int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o)
 
 	if (old && same(old, a)) {
 		int update = 0;
-		if (o->reset && !ce_uptodate(old)) {
+		if (o->reset && !ce_really_uptodate(old)) {
 			struct stat st;
 			if (lstat(old->name, &st) ||
 			    ie_match_stat(o->src_index, old, &st, CE_MATCH_IGNORE_VALID))
-- 
1.6.3.GIT

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]