git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH] builtin-commit: Refresh cache after adding files.
@ 2007-11-09 16:40 Kristian Høgsberg
  2007-11-09 17:05 ` Johannes Schindelin
  0 siblings, 1 reply; 14+ messages in thread
From: Kristian Høgsberg @ 2007-11-09 16:40 UTC (permalink / raw
  To: gitster; +Cc: git, Johannes Schindelin, Kristian Høgsberg

This fixes the race in the last test int t3700.

Signed-off-by: Kristian Høgsberg <krh@redhat.com>
---

I'm basically just copying what git-commit.sh does, but I'll admit to not
quite understanding why it's necessary.  It does fix the race in t3700 though.
Applies on top of pu.

cheers,
Kristian

 builtin-commit.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/builtin-commit.c b/builtin-commit.c
index 7dc8977..19862df 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -81,6 +81,7 @@ static char *prepare_index(const char **files, const char *prefix)
 
 	if (all || also) {
 		add_files_to_cache(verbose, also ? prefix : NULL, files);
+		refresh_cache(REFRESH_QUIET);
 		if (write_cache(fd, active_cache, active_nr) || close(fd))
 			die("unable to write new_index file");
 		return lock_file.filename;
@@ -110,6 +111,7 @@ static char *prepare_index(const char **files, const char *prefix)
 	fd = hold_lock_file_for_update(next_index_lock,
 				       git_path("next-index-%d", getpid()), 1);
 	add_files_to_cache(verbose, prefix, files);
+	refresh_cache(REFRESH_QUIET);
 	if (write_cache(fd, active_cache, active_nr) || close(fd))
 		die("unable to write new_index file");
 
-- 
1.5.3.4.206.g58ba4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH] builtin-commit: Refresh cache after adding files.
  2007-11-09 16:40 [PATCH] builtin-commit: Refresh cache after adding files Kristian Høgsberg
@ 2007-11-09 17:05 ` Johannes Schindelin
  2007-11-09 17:13   ` Kristian Høgsberg
  2007-11-09 18:24   ` Junio C Hamano
  0 siblings, 2 replies; 14+ messages in thread
From: Johannes Schindelin @ 2007-11-09 17:05 UTC (permalink / raw
  To: Kristian Høgsberg; +Cc: gitster, git

[-- Attachment #1: Type: TEXT/PLAIN, Size: 368 bytes --]

Hi,

On Fri, 9 Nov 2007, Kristian Høgsberg wrote:

> This fixes the race in the last test int t3700.

Well, it is not a race.  My fault.  I thought it was.

What you basically did was to make sure that the index is up-to-date after 
adding the files.  You might even want to say that in the commit message, 
and only then say that it fixes t3700, too.

Thanks,
Dscho

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] builtin-commit: Refresh cache after adding files.
  2007-11-09 17:05 ` Johannes Schindelin
@ 2007-11-09 17:13   ` Kristian Høgsberg
  2007-11-09 17:24     ` Johannes Schindelin
  2007-11-09 18:24   ` Junio C Hamano
  1 sibling, 1 reply; 14+ messages in thread
From: Kristian Høgsberg @ 2007-11-09 17:13 UTC (permalink / raw
  To: Johannes Schindelin; +Cc: gitster, git

On Fri, 2007-11-09 at 17:05 +0000, Johannes Schindelin wrote:
> Hi,
> 
> On Fri, 9 Nov 2007, Kristian Høgsberg wrote:
> 
> > This fixes the race in the last test int t3700.
> 
> Well, it is not a race.  My fault.  I thought it was.
> 
> What you basically did was to make sure that the index is up-to-date after 
> adding the files.  You might even want to say that in the commit message, 
> and only then say that it fixes t3700, too.

OK, I guess what I was wondering was why write_cache() doesn't write out
an up-to-date index.  I'll send an updated patch.  Do we need a call to
refresh_cache() when we update the user cache but commit an index
created from read_tree+add_files?  I.e. after the add_files_to_index()
call on line 97?  The shell script doesn't do this, it only runs
update-index --refresh for the index that gets committed.

Kristian

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] builtin-commit: Refresh cache after adding files.
  2007-11-09 17:13   ` Kristian Høgsberg
@ 2007-11-09 17:24     ` Johannes Schindelin
  2007-11-09 17:38       ` Kristian Høgsberg
  0 siblings, 1 reply; 14+ messages in thread
From: Johannes Schindelin @ 2007-11-09 17:24 UTC (permalink / raw
  To: Kristian Høgsberg; +Cc: gitster, git

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1128 bytes --]

Hi,

On Fri, 9 Nov 2007, Kristian H?gsberg wrote:

> On Fri, 2007-11-09 at 17:05 +0000, Johannes Schindelin wrote:
> 
> > On Fri, 9 Nov 2007, Kristian Høgsberg wrote:
> > 
> > > This fixes the race in the last test int t3700.
> > 
> > Well, it is not a race.  My fault.  I thought it was.
> > 
> > What you basically did was to make sure that the index is up-to-date 
> > after adding the files.  You might even want to say that in the commit 
> > message, and only then say that it fixes t3700, too.
> 
> OK, I guess what I was wondering was why write_cache() doesn't write out
> an up-to-date index.

write_cache() only writes the index, it does not update it.

> Do we need a call to refresh_cache() when we update the user cache but 
> commit an index created from read_tree+add_files?  I.e. after the 
> add_files_to_index() call on line 97?  The shell script doesn't do this, 
> it only runs update-index --refresh for the index that gets committed.

I think it would be sane to do so.

IIUC this basically means that "git add <file> && git commit" should do 
the same to the cache as "git commit <file>".

Thanks,
Dscho

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] builtin-commit: Refresh cache after adding files.
  2007-11-09 17:24     ` Johannes Schindelin
@ 2007-11-09 17:38       ` Kristian Høgsberg
  0 siblings, 0 replies; 14+ messages in thread
From: Kristian Høgsberg @ 2007-11-09 17:38 UTC (permalink / raw
  To: Johannes Schindelin; +Cc: gitster, git

On Fri, 2007-11-09 at 17:24 +0000, Johannes Schindelin wrote:
> Hi,
> 
> On Fri, 9 Nov 2007, Kristian H?gsberg wrote:
> 
> > On Fri, 2007-11-09 at 17:05 +0000, Johannes Schindelin wrote:
> > 
> > > On Fri, 9 Nov 2007, Kristian Høgsberg wrote:
> > > 
> > > > This fixes the race in the last test int t3700.
> > > 
> > > Well, it is not a race.  My fault.  I thought it was.
> > > 
> > > What you basically did was to make sure that the index is up-to-date 
> > > after adding the files.  You might even want to say that in the commit 
> > > message, and only then say that it fixes t3700, too.
> > 
> > OK, I guess what I was wondering was why write_cache() doesn't write out
> > an up-to-date index.
> 
> write_cache() only writes the index, it does not update it.
> 
> > Do we need a call to refresh_cache() when we update the user cache but 
> > commit an index created from read_tree+add_files?  I.e. after the 
> > add_files_to_index() call on line 97?  The shell script doesn't do this, 
> > it only runs update-index --refresh for the index that gets committed.
> 
> I think it would be sane to do so.
> 
> IIUC this basically means that "git add <file> && git commit" should do 
> the same to the cache as "git commit <file>".

No, that's equivalent to "git commit -i <file>".  If you just say "git
commit <file>", that will create a temporary index initialized to HEAD,
add file to that index and the regular (user) index, and then commit the
temporary index file.  The shell script doesn't refresh the regular
index in this case.  I think it makes sense to add that, but it will be
a subtle difference in behaviour.

cheers,
Kristian

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] builtin-commit: Refresh cache after adding files.
  2007-11-09 17:05 ` Johannes Schindelin
  2007-11-09 17:13   ` Kristian Høgsberg
@ 2007-11-09 18:24   ` Junio C Hamano
  2007-11-09 18:39     ` Kristian Høgsberg
                       ` (2 more replies)
  1 sibling, 3 replies; 14+ messages in thread
From: Junio C Hamano @ 2007-11-09 18:24 UTC (permalink / raw
  To: Johannes Schindelin; +Cc: Kristian Høgsberg, git

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> On Fri, 9 Nov 2007, Kristian Høgsberg wrote:
>
>> This fixes the race in the last test int t3700.
>
> Well, it is not a race.  My fault.  I thought it was.
>
> What you basically did was to make sure that the index is up-to-date after 
> adding the files.  You might even want to say that in the commit message, 
> and only then say that it fixes t3700, too.

Ah, it all makes sense.  I should have been more relaxed and
careful when I first read your t3700 patch.

If this were a breakage in racy-git-avoidance code, then
refresh_cache() Kristian added (or "add --refresh" immediately
after "git commit" in the test script) would have been fooled by
the same raciness and wouldn't have changed a thing.

This discussion exposes a problem with add_files_to_cache()
function.

Try this in a clean repository that tracks Makefile:

	$ git diff-files --name-only    ;# no output
        $ touch Makefile
        $ git diff-files --name-only
	Makefile
        $ git add -u
        $ git diff-files --name-only
	Makefile
        $ git add Makefile
        $ git diff-files --name-only    ;# no output

I think this is a broken behaviour.  As long as we are adding
the contents from a path on the filesystem to the corresponding
location in the index, it should sync the stat bits for the
entry in the index with the filesystem to make the entry
stat-clean.  IOW, we should not see stat-dirtiness reported
after "add -u".

The funny thing is that add_files_to_cache() run by "git add -u"
calls add_file_to_cache() to add the updated contents for
touched paths, but the latter function is used in the more
explicit "git add Makefile" codepath, without any magic
postprocessing after the function returns to sync the stat
info.  IOW, both "add -u" and "add Makefile" ends up calling
add_file_to_cache("Makefile") and I do not see why we are
getting different results.

And add_file_to_cache(), which calls add_file_to_index() on
the_index, does call the fill_stat_cache_info() to sync the stat
information by itself, as it should be.  I am still puzzled with
this.

So I think Kristian's two refresh_cache() do fix the issue, but
at the same time I _think_ it is a workaround for broken
add_files_to_cache() behaviour, which is what we should fix.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] builtin-commit: Refresh cache after adding files.
  2007-11-09 18:24   ` Junio C Hamano
@ 2007-11-09 18:39     ` Kristian Høgsberg
  2007-11-10  1:40     ` *[PATCH] " Junio C Hamano
  2007-11-10  2:22     ` [PATCH] git-add: make the entry stat-clean after re-adding the same contents Junio C Hamano
  2 siblings, 0 replies; 14+ messages in thread
From: Kristian Høgsberg @ 2007-11-09 18:39 UTC (permalink / raw
  To: Junio C Hamano; +Cc: Johannes Schindelin, git


On Fri, 2007-11-09 at 10:24 -0800, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > On Fri, 9 Nov 2007, Kristian Høgsberg wrote:
> >
> >> This fixes the race in the last test int t3700.
> >
> > Well, it is not a race.  My fault.  I thought it was.
> >
> > What you basically did was to make sure that the index is up-to-date after 
> > adding the files.  You might even want to say that in the commit message, 
> > and only then say that it fixes t3700, too.
> 
> Ah, it all makes sense.  I should have been more relaxed and
> careful when I first read your t3700 patch.
> 
> If this were a breakage in racy-git-avoidance code, then
> refresh_cache() Kristian added (or "add --refresh" immediately
> after "git commit" in the test script) would have been fooled by
> the same raciness and wouldn't have changed a thing.
> 
> This discussion exposes a problem with add_files_to_cache()
> function.
> 
> Try this in a clean repository that tracks Makefile:
> 
> 	$ git diff-files --name-only    ;# no output
>         $ touch Makefile
>         $ git diff-files --name-only
> 	Makefile
>         $ git add -u
>         $ git diff-files --name-only
> 	Makefile
>         $ git add Makefile
>         $ git diff-files --name-only    ;# no output
> 
> I think this is a broken behaviour.  As long as we are adding
> the contents from a path on the filesystem to the corresponding
> location in the index, it should sync the stat bits for the
> entry in the index with the filesystem to make the entry
> stat-clean.  IOW, we should not see stat-dirtiness reported
> after "add -u".

Yup, that's what I expected, and why I couldn't quite understand why the
refresh was necessary.

> The funny thing is that add_files_to_cache() run by "git add -u"
> calls add_file_to_cache() to add the updated contents for
> touched paths, but the latter function is used in the more
> explicit "git add Makefile" codepath, without any magic
> postprocessing after the function returns to sync the stat
> info.  IOW, both "add -u" and "add Makefile" ends up calling
> add_file_to_cache("Makefile") and I do not see why we are
> getting different results.

There is some timing involved in this, which may explain the different
results you see.  On my laptop I can trigger the add_files_to_cache()
problem roughly 4 out of 5 times, but on my faster desktop, it can't
trigger it.

> And add_file_to_cache(), which calls add_file_to_index() on
> the_index, does call the fill_stat_cache_info() to sync the stat
> information by itself, as it should be.  I am still puzzled with
> this.
> 
> So I think Kristian's two refresh_cache() do fix the issue, but
> at the same time I _think_ it is a workaround for broken
> add_files_to_cache() behaviour, which is what we should fix.

OK, I'll resend the patch with a better description, and add a refresh
call for the user index too, for the git commit <file> case.

cheers,
Kristian

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: *[PATCH] builtin-commit: Refresh cache after adding files.
  2007-11-09 18:24   ` Junio C Hamano
  2007-11-09 18:39     ` Kristian Høgsberg
@ 2007-11-10  1:40     ` Junio C Hamano
  2007-11-10  2:02       ` Johannes Schindelin
  2007-11-10  2:22     ` [PATCH] git-add: make the entry stat-clean after re-adding the same contents Junio C Hamano
  2 siblings, 1 reply; 14+ messages in thread
From: Junio C Hamano @ 2007-11-10  1:40 UTC (permalink / raw
  To: Johannes Schindelin; +Cc: Kristian Høgsberg, git

Junio C Hamano <gitster@pobox.com> writes:

> This discussion exposes a problem with add_files_to_cache()
> function.
> ...
> And add_file_to_cache(), which calls add_file_to_index() on
> the_index, does call the fill_stat_cache_info() to sync the stat
> information by itself, as it should be.  I am still puzzled with
> this.

Blech.  I think it is 0781b8a9b2fe760fc4ed519a3a26e4b9bd6ccffe
(add_file_to_index: skip rehashing if the cached stat already
matches) that broke "git add".  I get the same problem not just
with "git add -u" but also with an explicit "git add Makefile".

In add_file_to_index(), we check if ie_modified() says if the
path is modified, but that is actually a very wrong check in
that function.  ie_modified() knows the racy git condition and
digs deeper to find if the file in the work tree is really
different.  We end up saying "ah, Ok, if that is the same, then
we do not add it to the index again", which is why we do not
update the stat info in this case.

Instead, we should ask ie_match_stat() which answers "does not
match" for a entry that _could_ be racily clean, so that we make
sure we re-add such an entry to clear the stat info.

This applies to maint and all the way up.

I also suspect that run_diff_files() that is called from
builtin-add.c:update() needs to tell ie_match_stat() to assume
that a racily clean path is unclean (that is what bit (1<<1) of
the third parameter to ie_match_stat() is about), so that "add
-u" will call the add_file_to_index() function, but that would
be a bigger patch.

---

 read-cache.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/read-cache.c b/read-cache.c
index 928e8fa..75e2d46 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -420,7 +420,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose)
 	pos = index_name_pos(istate, ce->name, namelen);
 	if (0 <= pos &&
 	    !ce_stage(istate->cache[pos]) &&
-	    !ie_modified(istate, istate->cache[pos], &st, 1)) {
+	    !ie_match_stat(istate, istate->cache[pos], &st, 3)) {
 		/* Nothing changed, really */
 		free(ce);
 		return 0;

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: *[PATCH] builtin-commit: Refresh cache after adding files.
  2007-11-10  1:40     ` *[PATCH] " Junio C Hamano
@ 2007-11-10  2:02       ` Johannes Schindelin
  2007-11-10  2:26         ` Junio C Hamano
  0 siblings, 1 reply; 14+ messages in thread
From: Johannes Schindelin @ 2007-11-10  2:02 UTC (permalink / raw
  To: Junio C Hamano; +Cc: Kristian Høgsberg, git

Hi,

On Fri, 9 Nov 2007, Junio C Hamano wrote:

> Junio C Hamano <gitster@pobox.com> writes:
> 
> > This discussion exposes a problem with add_files_to_cache()
> > function.
> > ...
> > And add_file_to_cache(), which calls add_file_to_index() on
> > the_index, does call the fill_stat_cache_info() to sync the stat
> > information by itself, as it should be.  I am still puzzled with
> > this.
> 
> Blech.  I think it is 0781b8a9b2fe760fc4ed519a3a26e4b9bd6ccffe 
> (add_file_to_index: skip rehashing if the cached stat already matches) 
> that broke "git add".  I get the same problem not just with "git add -u" 
> but also with an explicit "git add Makefile".

But I think that we still need to refresh the index.  It outputs which 
files names were new, and which ones were removed.  Otherwise git commit 
would be eerily silent on those.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH] git-add: make the entry stat-clean after re-adding the same contents
  2007-11-09 18:24   ` Junio C Hamano
  2007-11-09 18:39     ` Kristian Høgsberg
  2007-11-10  1:40     ` *[PATCH] " Junio C Hamano
@ 2007-11-10  2:22     ` Junio C Hamano
  2007-11-10  2:43       ` Linus Torvalds
  2 siblings, 1 reply; 14+ messages in thread
From: Junio C Hamano @ 2007-11-10  2:22 UTC (permalink / raw
  To: Johannes Schindelin; +Cc: Kristian Høgsberg, git

Earlier in commit 0781b8a9b2fe760fc4ed519a3a26e4b9bd6ccffe
(add_file_to_index: skip rehashing if the cached stat already
matches), add_file_to_index() were taught not to re-add the path
if it already matches the index.

The change meant well, but was not executed quite right.  It
used ie_modified() to see if the file on the work tree is really
different from the index, and skipped adding the contents if the
function says "not modified".

This was wrong.  There are three possible comparison results
between the index and the file in the work tree:

 - with lstat(2) we _know_ they are different.  E.g. if the
   length or the owner in the cached stat information is
   different from the length we just obtained from lstat(2), we
   can tell the file is modified without looking at the actual
   contents.

 - with lstat(2) we _know_ they are the same.  The same length,
   the same owner, the same everything (but this has a twist, as
   described below).

 - we cannot tell from lstat(2) information alone and need to go
   to the filesystem to actually compare.

The last case arises from what we call 'racy git' situation,
that can be caused with this sequence:

    $ echo hello >file
    $ git add file
    $ echo aeiou >file ;# the same length

If the second "echo" is done within the same filesystem
timestamp granularity as the first "echo", then the timestamp
recorded by "git add" and the timestamp we get from lstat(2)
will be the same, and we can mistakenly say the file is not
modified.  The path is called 'racily clean'.  We need to
reliably detect racily clean paths are in fact modified.

To solve this problem, when we write out the index, we mark the
index entry that has the same timestamp as the index file itself
(that is the time from the point of view of the filesystem) to
tell any later code that does the lstat(2) comparison not to
trust the cached stat info, and ie_modified() then actually goes
to the filesystem to compare the contents for such a path.

That's all good, but it should not be used for this "git add"
optimization, as the goal of "git add" is to actually update the
path in the index and make it stat-clean.  With the false
optimization, we did _not_ cause any data loss (after all, what
we failed to do was only to update the cached stat information),
but it made the following sequence leave the file stat dirty:

    $ echo hello >file
    $ git add file
    $ echo hello >file ;# the same contents
    $ git add file

The solution is not to use ie_modified() which goes to the
filesystem to see if it is really clean, but instead use
ie_match_stat() with "assume racily clean paths are dirty"
option, to force re-adding of such a path.

There was another problem with "git add -u".  The codepath
shares the same issue when adding the paths that are found to be
modified, but in addition, it asked "git diff-files" machinery
run_diff_files() function (which is "git diff-files") to list
the paths that are modified.  But "git diff-files" machinery
uses the same ie_modified() call so that it does not report
racily clean _and_ actually clean paths as modified, which is
not what we want.

The patch allows the callers of run_diff_files() to pass the
same "assume racily clean paths are dirty" option, and makes
"git-add -u" codepath to use that option, to discover and re-add
racily clean _and_ actually clean paths.

We could further optimize on top of this patch to differentiate
the case where the path really needs re-adding (i.e. the content
of the racily clean entry was indeed different) and the case
where only the cached stat information needs to be refreshed
(i.e. the racily clean entry was actually clean), but I do not
think it is worth it.

This patch applies to maint and all the way up.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

 * Blech.  This took longer than I thought.  It's only cached
   stat info and does not cause real data breakage, but I think
   it is a good thing to fix nevertheless.

 builtin-add.c |    2 +-
 diff-lib.c    |    6 ++++--
 diff.h        |    2 +-
 read-cache.c  |    2 +-
 4 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/builtin-add.c b/builtin-add.c
index 373f87f..b6d6bbe 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -123,7 +123,7 @@ static void update(int verbose, const char *prefix, const char **files)
 	rev.diffopt.format_callback_data = &verbose;
 	if (read_cache() < 0)
 		die("index file corrupt");
-	run_diff_files(&rev, 0);
+	run_diff_files(&rev, 2);
 }
 
 static void refresh(int verbose, const char **pathspec)
diff --git a/diff-lib.c b/diff-lib.c
index da55713..b83f650 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -332,10 +332,12 @@ int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
 	return run_diff_files(revs, silent_on_removed);
 }
 
-int run_diff_files(struct rev_info *revs, int silent_on_removed)
+int run_diff_files(struct rev_info *revs, int option)
 {
 	int entries, i;
 	int diff_unmerged_stage = revs->max_count;
+	int silent_on_removed = option & 01;
+	int assume_racy_is_modified = option & 02;
 
 	if (diff_unmerged_stage < 0)
 		diff_unmerged_stage = 2;
@@ -441,7 +443,7 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed)
 				       ce->sha1, ce->name, NULL);
 			continue;
 		}
-		changed = ce_match_stat(ce, &st, 0);
+		changed = ce_match_stat(ce, &st, assume_racy_is_modified);
 		if (!changed && !revs->diffopt.find_copies_harder)
 			continue;
 		oldmode = ntohl(ce->ce_mode);
diff --git a/diff.h b/diff.h
index 4546aad..040e18c 100644
--- a/diff.h
+++ b/diff.h
@@ -224,7 +224,7 @@ extern void diff_flush(struct diff_options*);
 
 extern const char *diff_unique_abbrev(const unsigned char *, int);
 
-extern int run_diff_files(struct rev_info *revs, int silent_on_removed);
+extern int run_diff_files(struct rev_info *revs, int option);
 extern int setup_diff_no_index(struct rev_info *revs,
 		int argc, const char ** argv, int nongit, const char *prefix);
 extern int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv);
diff --git a/read-cache.c b/read-cache.c
index 928e8fa..75e2d46 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -420,7 +420,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose)
 	pos = index_name_pos(istate, ce->name, namelen);
 	if (0 <= pos &&
 	    !ce_stage(istate->cache[pos]) &&
-	    !ie_modified(istate, istate->cache[pos], &st, 1)) {
+	    !ie_match_stat(istate, istate->cache[pos], &st, 3)) {
 		/* Nothing changed, really */
 		free(ce);
 		return 0;
-- 
1.5.3.5.1651.g30bf0

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: *[PATCH] builtin-commit: Refresh cache after adding files.
  2007-11-10  2:02       ` Johannes Schindelin
@ 2007-11-10  2:26         ` Junio C Hamano
  0 siblings, 0 replies; 14+ messages in thread
From: Junio C Hamano @ 2007-11-10  2:26 UTC (permalink / raw
  To: Johannes Schindelin; +Cc: Kristian Høgsberg, git

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> But I think that we still need to refresh the index.

You are correct.  See

    http://article.gmane.org/gmane.comp.version-control.git/64254

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] git-add: make the entry stat-clean after re-adding the same contents
  2007-11-10  2:22     ` [PATCH] git-add: make the entry stat-clean after re-adding the same contents Junio C Hamano
@ 2007-11-10  2:43       ` Linus Torvalds
  2007-11-10  9:01         ` [PATCH 1/2] ce_match_stat, run_diff_files: use symbolic constants for readability Junio C Hamano
  2007-11-10  9:02         ` [PATCH 2/2] git-add: make the entry stat-clean after re-adding the same contents Junio C Hamano
  0 siblings, 2 replies; 14+ messages in thread
From: Linus Torvalds @ 2007-11-10  2:43 UTC (permalink / raw
  To: Junio C Hamano; +Cc: Johannes Schindelin, Kristian Høgsberg, git



On Fri, 9 Nov 2007, Junio C Hamano wrote:
>  
> -int run_diff_files(struct rev_info *revs, int silent_on_removed)
> +int run_diff_files(struct rev_info *revs, int option)

Wouldn't it be much better to now 
 - make it "unsigned int flags"
 - create a few enums or #define's to make the usage be more readable?

Because this:

>-       run_diff_files(&rev, 0);
>+       run_diff_files(&rev, 2);
> -	    !ie_modified(istate, istate->cache[pos], &st, 1)) {
> +	    !ie_match_stat(istate, istate->cache[pos], &st, 3)) {

just went from subtle to "incredibly non-obvious".

I realize that 3 is "silent + assume_racy" and 2 is just "assume_racy", 
but I may realize that now, and in a month? I'd need to look it up.

		Linus

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/2] ce_match_stat, run_diff_files: use symbolic constants for readability
  2007-11-10  2:43       ` Linus Torvalds
@ 2007-11-10  9:01         ` Junio C Hamano
  2007-11-10  9:02         ` [PATCH 2/2] git-add: make the entry stat-clean after re-adding the same contents Junio C Hamano
  1 sibling, 0 replies; 14+ messages in thread
From: Junio C Hamano @ 2007-11-10  9:01 UTC (permalink / raw
  To: Linus Torvalds; +Cc: Johannes Schindelin, Kristian Høgsberg, git

ce_match_stat() can be told:

 (1) to ignore CE_VALID bit (used under "assume unchanged" mode)
     and perform the stat comparison anyway;

 (2) not to perform the contents comparison for racily clean
     entries and report mismatch of cached stat information;

using its "option" parameter.  Give them symbolic constants.

Similarly, run_diff_files() can be told not to report anything
on removed paths.  Also give it a symbolic constant for that.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

 Linus Torvalds <torvalds@linux-foundation.org> writes:

 > On Fri, 9 Nov 2007, Junio C Hamano wrote:
 >>  
 >> -int run_diff_files(struct rev_info *revs, int silent_on_removed)
 >> +int run_diff_files(struct rev_info *revs, int option)
 >
 > Wouldn't it be much better to now 
 >  - make it "unsigned int flags"
 >  - create a few enums or #define's to make the usage be more readable?
 >
 > Because this:
 >
 >>-       run_diff_files(&rev, 0);
 >>+       run_diff_files(&rev, 2);
 >> -	    !ie_modified(istate, istate->cache[pos], &st, 1)) {
 >> +	    !ie_match_stat(istate, istate->cache[pos], &st, 3)) {
 >
 > just went from subtle to "incredibly non-obvious".

 That really is true.  Apparently I am getting much slower
 lately.  This is to just introduce the constants and change the
 types.

 builtin-apply.c |    2 +-
 cache.h         |   14 ++++++++++----
 check-racy.c    |    2 +-
 diff-lib.c      |   16 +++++++++-------
 diff.h          |    4 +++-
 entry.c         |    2 +-
 read-cache.c    |   47 ++++++++++++++++++++++++++++++-----------------
 unpack-trees.c  |    4 ++--
 8 files changed, 57 insertions(+), 34 deletions(-)

diff --git a/builtin-apply.c b/builtin-apply.c
index 5cc90e6..0fff02e 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -2099,7 +2099,7 @@ static int verify_index_match(struct cache_entry *ce, struct stat *st)
 			return -1;
 		return 0;
 	}
-	return ce_match_stat(ce, st, 1);
+	return ce_match_stat(ce, st, CE_MATCH_IGNORE_VALID);
 }
 
 static int check_patch(struct patch *patch, struct patch *prev_patch)
diff --git a/cache.h b/cache.h
index fc195bc..31af16a 100644
--- a/cache.h
+++ b/cache.h
@@ -174,8 +174,8 @@ extern struct index_state the_index;
 #define remove_file_from_cache(path) remove_file_from_index(&the_index, (path))
 #define add_file_to_cache(path, verbose) add_file_to_index(&the_index, (path), (verbose))
 #define refresh_cache(flags) refresh_index(&the_index, (flags), NULL, NULL)
-#define ce_match_stat(ce, st, really) ie_match_stat(&the_index, (ce), (st), (really))
-#define ce_modified(ce, st, really) ie_modified(&the_index, (ce), (st), (really))
+#define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))
+#define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
 #endif
 
 enum object_type {
@@ -266,8 +266,14 @@ extern int remove_file_from_index(struct index_state *, const char *path);
 extern int add_file_to_index(struct index_state *, const char *path, int verbose);
 extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);
 extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
-extern int ie_match_stat(struct index_state *, struct cache_entry *, struct stat *, int);
-extern int ie_modified(struct index_state *, struct cache_entry *, struct stat *, int);
+
+/* do stat comparison even if CE_VALID is true */
+#define CE_MATCH_IGNORE_VALID		01
+/* do not check the contents but report dirty on racily-clean entries */
+#define CE_MATCH_RACY_IS_DIRTY	02
+extern int ie_match_stat(struct index_state *, struct cache_entry *, struct stat *, unsigned int);
+extern int ie_modified(struct index_state *, struct cache_entry *, struct stat *, unsigned int);
+
 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 read_fd(int fd, char **return_buf, unsigned long *return_size);
diff --git a/check-racy.c b/check-racy.c
index d6a08b4..00d92a1 100644
--- a/check-racy.c
+++ b/check-racy.c
@@ -18,7 +18,7 @@ int main(int ac, char **av)
 
 		if (ce_match_stat(ce, &st, 0))
 			dirty++;
-		else if (ce_match_stat(ce, &st, 2))
+		else if (ce_match_stat(ce, &st, CE_MATCH_RACY_IS_DIRTY))
 			racy++;
 		else
 			clean++;
diff --git a/diff-lib.c b/diff-lib.c
index da55713..9f8afbe 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -173,9 +173,10 @@ static int is_in_index(const char *path)
 }
 
 static int handle_diff_files_args(struct rev_info *revs,
-		int argc, const char **argv, int *silent)
+				  int argc, const char **argv,
+				  unsigned int *options)
 {
-	*silent = 0;
+	*options = 0;
 
 	/* revs->max_count == -2 means --no-index */
 	while (1 < argc && argv[1][0] == '-') {
@@ -192,7 +193,7 @@ static int handle_diff_files_args(struct rev_info *revs,
 			revs->diffopt.no_index = 1;
 		}
 		else if (!strcmp(argv[1], "-q"))
-			*silent = 1;
+			*options |= DIFF_SILENT_ON_REMOVED;
 		else
 			return error("invalid option: %s", argv[1]);
 		argv++; argc--;
@@ -305,9 +306,9 @@ int setup_diff_no_index(struct rev_info *revs,
 
 int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
 {
-	int silent_on_removed;
+	unsigned int options;
 
-	if (handle_diff_files_args(revs, argc, argv, &silent_on_removed))
+	if (handle_diff_files_args(revs, argc, argv, &options))
 		return -1;
 
 	if (revs->diffopt.no_index) {
@@ -329,13 +330,14 @@ int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
 		perror("read_cache");
 		return -1;
 	}
-	return run_diff_files(revs, silent_on_removed);
+	return run_diff_files(revs, options);
 }
 
-int run_diff_files(struct rev_info *revs, int silent_on_removed)
+int run_diff_files(struct rev_info *revs, unsigned int option)
 {
 	int entries, i;
 	int diff_unmerged_stage = revs->max_count;
+	int silent_on_removed = option & DIFF_SILENT_ON_REMOVED;
 
 	if (diff_unmerged_stage < 0)
 		diff_unmerged_stage = 2;
diff --git a/diff.h b/diff.h
index 4546aad..de533da 100644
--- a/diff.h
+++ b/diff.h
@@ -224,7 +224,9 @@ extern void diff_flush(struct diff_options*);
 
 extern const char *diff_unique_abbrev(const unsigned char *, int);
 
-extern int run_diff_files(struct rev_info *revs, int silent_on_removed);
+/* do not report anything on removed paths */
+#define DIFF_SILENT_ON_REMOVED 01
+extern int run_diff_files(struct rev_info *revs, unsigned int option);
 extern int setup_diff_no_index(struct rev_info *revs,
 		int argc, const char ** argv, int nongit, const char *prefix);
 extern int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv);
diff --git a/entry.c b/entry.c
index fc3a506..ef88f62 100644
--- a/entry.c
+++ b/entry.c
@@ -200,7 +200,7 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t
 	strcpy(path + len, ce->name);
 
 	if (!lstat(path, &st)) {
-		unsigned changed = ce_match_stat(ce, &st, 1);
+		unsigned changed = ce_match_stat(ce, &st, CE_MATCH_IGNORE_VALID);
 		if (!changed)
 			return 0;
 		if (!state->force) {
diff --git a/read-cache.c b/read-cache.c
index 928e8fa..9e4d4a9 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -194,11 +194,12 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
 }
 
 int ie_match_stat(struct index_state *istate,
-		  struct cache_entry *ce, struct stat *st, int options)
+		  struct cache_entry *ce, struct stat *st,
+		  unsigned int options)
 {
 	unsigned int changed;
-	int ignore_valid = options & 01;
-	int assume_racy_is_modified = options & 02;
+	int ignore_valid = options & CE_MATCH_IGNORE_VALID;
+	int assume_racy_is_modified = options & CE_MATCH_RACY_IS_DIRTY;
 
 	/*
 	 * If it's marked as always valid in the index, it's
@@ -238,10 +239,11 @@ int ie_match_stat(struct index_state *istate,
 }
 
 int ie_modified(struct index_state *istate,
-		struct cache_entry *ce, struct stat *st, int really)
+		struct cache_entry *ce, struct stat *st, unsigned int options)
 {
 	int changed, changed_fs;
-	changed = ie_match_stat(istate, ce, st, really);
+
+	changed = ie_match_stat(istate, ce, st, options);
 	if (!changed)
 		return 0;
 	/*
@@ -420,7 +422,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose)
 	pos = index_name_pos(istate, ce->name, namelen);
 	if (0 <= pos &&
 	    !ce_stage(istate->cache[pos]) &&
-	    !ie_modified(istate, istate->cache[pos], &st, 1)) {
+	    !ie_modified(istate, istate->cache[pos], &st, CE_MATCH_IGNORE_VALID)) {
 		/* Nothing changed, really */
 		free(ce);
 		return 0;
@@ -782,11 +784,13 @@ int add_index_entry(struct index_state *istate, struct cache_entry *ce, int opti
  * to link up the stat cache details with the proper files.
  */
 static struct cache_entry *refresh_cache_ent(struct index_state *istate,
-					     struct cache_entry *ce, int really, int *err)
+					     struct cache_entry *ce,
+					     unsigned int options, int *err)
 {
 	struct stat st;
 	struct cache_entry *updated;
 	int changed, size;
+	int ignore_valid = options & CE_MATCH_IGNORE_VALID;
 
 	if (lstat(ce->name, &st) < 0) {
 		if (err)
@@ -794,16 +798,23 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
 		return NULL;
 	}
 
-	changed = ie_match_stat(istate, ce, &st, really);
+	changed = ie_match_stat(istate, ce, &st, options);
 	if (!changed) {
-		if (really && assume_unchanged &&
+		/*
+		 * The path is unchanged.  If we were told to ignore
+		 * valid bit, then we did the actual stat check and
+		 * found that the entry is unmodified.  If the entry
+		 * is not marked VALID, this is the place to mark it
+		 * valid again, under "assume unchanged" mode.
+		 */
+		if (ignore_valid && assume_unchanged &&
 		    !(ce->ce_flags & htons(CE_VALID)))
 			; /* mark this one VALID again */
 		else
 			return ce;
 	}
 
-	if (ie_modified(istate, ce, &st, really)) {
+	if (ie_modified(istate, ce, &st, options)) {
 		if (err)
 			*err = EINVAL;
 		return NULL;
@@ -814,13 +825,14 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
 	memcpy(updated, ce, size);
 	fill_stat_cache_info(updated, &st);
 
-	/* In this case, if really is not set, we should leave
-	 * CE_VALID bit alone.  Otherwise, paths marked with
-	 * --no-assume-unchanged (i.e. things to be edited) will
-	 * reacquire CE_VALID bit automatically, which is not
-	 * really what we want.
+	/*
+	 * If ignore_valid is not set, we should leave CE_VALID bit
+	 * alone.  Otherwise, paths marked with --no-assume-unchanged
+	 * (i.e. things to be edited) will reacquire CE_VALID bit
+	 * automatically, which is not really what we want.
 	 */
-	if (!really && assume_unchanged && !(ce->ce_flags & htons(CE_VALID)))
+	if (!ignore_valid && assume_unchanged &&
+	    !(ce->ce_flags & htons(CE_VALID)))
 		updated->ce_flags &= ~htons(CE_VALID);
 
 	return updated;
@@ -834,6 +846,7 @@ int refresh_index(struct index_state *istate, unsigned int flags, const char **p
 	int allow_unmerged = (flags & REFRESH_UNMERGED) != 0;
 	int quiet = (flags & REFRESH_QUIET) != 0;
 	int not_new = (flags & REFRESH_IGNORE_MISSING) != 0;
+	unsigned int options = really ? CE_MATCH_IGNORE_VALID : 0;
 
 	for (i = 0; i < istate->cache_nr; i++) {
 		struct cache_entry *ce, *new;
@@ -855,7 +868,7 @@ int refresh_index(struct index_state *istate, unsigned int flags, const char **p
 		if (pathspec && !match_pathspec(pathspec, ce->name, strlen(ce->name), 0, seen))
 			continue;
 
-		new = refresh_cache_ent(istate, ce, really, &cache_errno);
+		new = refresh_cache_ent(istate, ce, options, &cache_errno);
 		if (new == ce)
 			continue;
 		if (!new) {
diff --git a/unpack-trees.c b/unpack-trees.c
index ccfeb6e..9411c67 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -406,7 +406,7 @@ static void verify_uptodate(struct cache_entry *ce,
 		return;
 
 	if (!lstat(ce->name, &st)) {
-		unsigned changed = ce_match_stat(ce, &st, 1);
+		unsigned changed = ce_match_stat(ce, &st, CE_MATCH_IGNORE_VALID);
 		if (!changed)
 			return;
 		/*
@@ -927,7 +927,7 @@ int oneway_merge(struct cache_entry **src,
 		if (o->reset) {
 			struct stat st;
 			if (lstat(old->name, &st) ||
-			    ce_match_stat(old, &st, 1))
+			    ce_match_stat(old, &st, CE_MATCH_IGNORE_VALID))
 				old->ce_flags |= htons(CE_UPDATE);
 		}
 		return keep_entry(old, o);
-- 
1.5.3.5.1651.g30bf0

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/2] git-add: make the entry stat-clean after re-adding the same contents
  2007-11-10  2:43       ` Linus Torvalds
  2007-11-10  9:01         ` [PATCH 1/2] ce_match_stat, run_diff_files: use symbolic constants for readability Junio C Hamano
@ 2007-11-10  9:02         ` Junio C Hamano
  1 sibling, 0 replies; 14+ messages in thread
From: Junio C Hamano @ 2007-11-10  9:02 UTC (permalink / raw
  To: Linus Torvalds; +Cc: Johannes Schindelin, Kristian Høgsberg, git

Earlier in commit 0781b8a9b2fe760fc4ed519a3a26e4b9bd6ccffe
(add_file_to_index: skip rehashing if the cached stat already
matches), add_file_to_index() were taught not to re-add the path
if it already matches the index.

The change meant well, but was not executed quite right.  It
used ie_modified() to see if the file on the work tree is really
different from the index, and skipped adding the contents if the
function says "not modified".

This was wrong.  There are three possible comparison results
between the index and the file in the work tree:

 - with lstat(2) we _know_ they are different.  E.g. if the
   length or the owner in the cached stat information is
   different from the length we just obtained from lstat(2), we
   can tell the file is modified without looking at the actual
   contents.

 - with lstat(2) we _know_ they are the same.  The same length,
   the same owner, the same everything (but this has a twist, as
   described below).

 - we cannot tell from lstat(2) information alone and need to go
   to the filesystem to actually compare.

The last case arises from what we call 'racy git' situation,
that can be caused with this sequence:

    $ echo hello >file
    $ git add file
    $ echo aeiou >file ;# the same length

If the second "echo" is done within the same filesystem
timestamp granularity as the first "echo", then the timestamp
recorded by "git add" and the timestamp we get from lstat(2)
will be the same, and we can mistakenly say the file is not
modified.  The path is called 'racily clean'.  We need to
reliably detect racily clean paths are in fact modified.

To solve this problem, when we write out the index, we mark the
index entry that has the same timestamp as the index file itself
(that is the time from the point of view of the filesystem) to
tell any later code that does the lstat(2) comparison not to
trust the cached stat info, and ie_modified() then actually goes
to the filesystem to compare the contents for such a path.

That's all good, but it should not be used for this "git add"
optimization, as the goal of "git add" is to actually update the
path in the index and make it stat-clean.  With the false
optimization, we did _not_ cause any data loss (after all, what
we failed to do was only to update the cached stat information),
but it made the following sequence leave the file stat dirty:

    $ echo hello >file
    $ git add file
    $ echo hello >file ;# the same contents
    $ git add file

The solution is not to use ie_modified() which goes to the
filesystem to see if it is really clean, but instead use
ie_match_stat() with "assume racily clean paths are dirty"
option, to force re-adding of such a path.

There was another problem with "git add -u".  The codepath
shares the same issue when adding the paths that are found to be
modified, but in addition, it asked "git diff-files" machinery
run_diff_files() function (which is "git diff-files") to list
the paths that are modified.  But "git diff-files" machinery
uses the same ie_modified() call so that it does not report
racily clean _and_ actually clean paths as modified, which is
not what we want.

The patch allows the callers of run_diff_files() to pass the
same "assume racily clean paths are dirty" option, and makes
"git-add -u" codepath to use that option, to discover and re-add
racily clean _and_ actually clean paths.

We could further optimize on top of this patch to differentiate
the case where the path really needs re-adding (i.e. the content
of the racily clean entry was indeed different) and the case
where only the cached stat information needs to be refreshed
(i.e. the racily clean entry was actually clean), but I do not
think it is worth it.

This patch applies to maint and all the way up.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

 * And this is a respin of the earlier fix, using the new
   constants.

 builtin-add.c |    2 +-
 diff-lib.c    |    4 +++-
 diff.h        |    2 ++
 read-cache.c  |    3 ++-
 4 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/builtin-add.c b/builtin-add.c
index 373f87f..e072320 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -123,7 +123,7 @@ static void update(int verbose, const char *prefix, const char **files)
 	rev.diffopt.format_callback_data = &verbose;
 	if (read_cache() < 0)
 		die("index file corrupt");
-	run_diff_files(&rev, 0);
+	run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
 }
 
 static void refresh(int verbose, const char **pathspec)
diff --git a/diff-lib.c b/diff-lib.c
index 9f8afbe..ec1b5e3 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -338,6 +338,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
 	int entries, i;
 	int diff_unmerged_stage = revs->max_count;
 	int silent_on_removed = option & DIFF_SILENT_ON_REMOVED;
+	unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED)
+			      ? CE_MATCH_RACY_IS_DIRTY : 0);
 
 	if (diff_unmerged_stage < 0)
 		diff_unmerged_stage = 2;
@@ -443,7 +445,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
 				       ce->sha1, ce->name, NULL);
 			continue;
 		}
-		changed = ce_match_stat(ce, &st, 0);
+		changed = ce_match_stat(ce, &st, ce_option);
 		if (!changed && !revs->diffopt.find_copies_harder)
 			continue;
 		oldmode = ntohl(ce->ce_mode);
diff --git a/diff.h b/diff.h
index de533da..efaa8f7 100644
--- a/diff.h
+++ b/diff.h
@@ -226,6 +226,8 @@ extern const char *diff_unique_abbrev(const unsigned char *, int);
 
 /* do not report anything on removed paths */
 #define DIFF_SILENT_ON_REMOVED 01
+/* report racily-clean paths as modified */
+#define DIFF_RACY_IS_MODIFIED 02
 extern int run_diff_files(struct rev_info *revs, unsigned int option);
 extern int setup_diff_no_index(struct rev_info *revs,
 		int argc, const char ** argv, int nongit, const char *prefix);
diff --git a/read-cache.c b/read-cache.c
index 9e4d4a9..c3dbf89 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -388,6 +388,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose)
 	int size, namelen, pos;
 	struct stat st;
 	struct cache_entry *ce;
+	unsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_RACY_IS_DIRTY;
 
 	if (lstat(path, &st))
 		die("%s: unable to stat (%s)", path, strerror(errno));
@@ -422,7 +423,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose)
 	pos = index_name_pos(istate, ce->name, namelen);
 	if (0 <= pos &&
 	    !ce_stage(istate->cache[pos]) &&
-	    !ie_modified(istate, istate->cache[pos], &st, CE_MATCH_IGNORE_VALID)) {
+	    !ie_match_stat(istate, istate->cache[pos], &st, ce_option)) {
 		/* Nothing changed, really */
 		free(ce);
 		return 0;
-- 
1.5.3.5.1651.g30bf0

^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2007-11-10  9:02 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-11-09 16:40 [PATCH] builtin-commit: Refresh cache after adding files Kristian Høgsberg
2007-11-09 17:05 ` Johannes Schindelin
2007-11-09 17:13   ` Kristian Høgsberg
2007-11-09 17:24     ` Johannes Schindelin
2007-11-09 17:38       ` Kristian Høgsberg
2007-11-09 18:24   ` Junio C Hamano
2007-11-09 18:39     ` Kristian Høgsberg
2007-11-10  1:40     ` *[PATCH] " Junio C Hamano
2007-11-10  2:02       ` Johannes Schindelin
2007-11-10  2:26         ` Junio C Hamano
2007-11-10  2:22     ` [PATCH] git-add: make the entry stat-clean after re-adding the same contents Junio C Hamano
2007-11-10  2:43       ` Linus Torvalds
2007-11-10  9:01         ` [PATCH 1/2] ce_match_stat, run_diff_files: use symbolic constants for readability Junio C Hamano
2007-11-10  9:02         ` [PATCH 2/2] git-add: make the entry stat-clean after re-adding the same contents Junio C Hamano

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).