Message ID | 08741d986c2b51828f115ab50f178d62e9982978.1570654810.git.gitgitgadget@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | fsmonitor: don't fill bitmap with entries to be removed | expand |
On Wed, Oct 09, 2019 at 02:00:12PM -0700, William Baker via GitGitGadget wrote: > diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh > index 81a375fa0f..87042470ab 100755 > --- a/t/t7519-status-fsmonitor.sh > +++ b/t/t7519-status-fsmonitor.sh > @@ -354,4 +354,17 @@ test_expect_success 'discard_index() also discards fsmonitor info' ' > test_cmp expect actual > ' > > +# This test covers staging/unstaging files that appear at the end of the index. > +# Test files with names beginning with 'z' are used under the assumption that > +# earlier tests do not add/leave index entries that sort below them. > +test_expect_success 'status succeeds after staging/unstaging ' ' > + test_commit initial && This is confusing: this is the 29th test case in this script and it creates an "initial" commit?! The first "setup" test case has already created an initial commit, so this should rather be called "second". OTOH, none of the later commands in this test case seem to have anything to do with this second commit, and indeed the test case works even without it (i.e. 'git status' still segfaults without the fix and then succeeds with the fix applied), so instead of updating its message perhaps it could simply be removed. > + removed=$(test_seq 1 100 | sed "s/^/z/") && > + touch $removed && > + git add $removed && > + test_config core.fsmonitor "$TEST_DIRECTORY/t7519/fsmonitor-env" && > + FSMONITOR_LIST="$removed" git restore -S $removed && > + FSMONITOR_LIST="$removed" git status > +' > + > test_done
On Thu, Oct 10, 2019 at 01:07:32PM +0200, SZEDER Gábor wrote: > On Wed, Oct 09, 2019 at 02:00:12PM -0700, William Baker via GitGitGadget wrote: > > diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh > > index 81a375fa0f..87042470ab 100755 > > --- a/t/t7519-status-fsmonitor.sh > > +++ b/t/t7519-status-fsmonitor.sh > > @@ -354,4 +354,17 @@ test_expect_success 'discard_index() also discards fsmonitor info' ' > > test_cmp expect actual > > ' > > > > +# This test covers staging/unstaging files that appear at the end of the index. > > +# Test files with names beginning with 'z' are used under the assumption that > > +# earlier tests do not add/leave index entries that sort below them. I just read through Junio's comments on the first version of this patch, in particular his remarks about this comment. If this new test case below were run in a dedicated repository, then this comment wouldn't be necessary, and all my comments below about that not-really-initial commit would be moot, too. > > +test_expect_success 'status succeeds after staging/unstaging ' ' > > + test_commit initial && > > This is confusing: this is the 29th test case in this script and it > creates an "initial" commit?! > > The first "setup" test case has already created an initial commit, so > this should rather be called "second". > > OTOH, none of the later commands in this test case seem to have > anything to do with this second commit, and indeed the test case works > even without it (i.e. 'git status' still segfaults without the fix and > then succeeds with the fix applied), so instead of updating its > message perhaps it could simply be removed. > > > + removed=$(test_seq 1 100 | sed "s/^/z/") && > > + touch $removed && > > + git add $removed && > > + test_config core.fsmonitor "$TEST_DIRECTORY/t7519/fsmonitor-env" && > > + FSMONITOR_LIST="$removed" git restore -S $removed && > > + FSMONITOR_LIST="$removed" git status > > +' > > + > > test_done
On 10/10/19 4:22 AM, SZEDER Gábor wrote: >>> +# This test covers staging/unstaging files that appear at the end of the index. >>> +# Test files with names beginning with 'z' are used under the assumption that >>> +# earlier tests do not add/leave index entries that sort below them. > > I just read through Junio's comments on the first version of this > patch, in particular his remarks about this comment. > > If this new test case below were run in a dedicated repository, then > this comment wouldn't be necessary, and all my comments below about > that not-really-initial commit would be moot, too. > Thanks for this suggestion! I will submit a v3 version of the patch with an update to the test script. - William
diff --git a/fsmonitor.c b/fsmonitor.c index 231e83a94d..7e27839278 100644 --- a/fsmonitor.c +++ b/fsmonitor.c @@ -14,8 +14,13 @@ struct trace_key trace_fsmonitor = TRACE_KEY_INIT(FSMONITOR); static void fsmonitor_ewah_callback(size_t pos, void *is) { struct index_state *istate = (struct index_state *)is; - struct cache_entry *ce = istate->cache[pos]; + struct cache_entry *ce; + + if (pos >= istate->cache_nr) + BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" >= %u)", + (uintmax_t)pos, istate->cache_nr); + ce = istate->cache[pos]; ce->ce_flags &= ~CE_FSMONITOR_VALID; } @@ -50,17 +55,24 @@ int read_fsmonitor_extension(struct index_state *istate, const void *data, } istate->fsmonitor_dirty = fsmonitor_dirty; + if (istate->fsmonitor_dirty->bit_size > istate->cache_nr) + BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)", + (uintmax_t)istate->fsmonitor_dirty->bit_size, istate->cache_nr); + trace_printf_key(&trace_fsmonitor, "read fsmonitor extension successful"); return 0; } void fill_fsmonitor_bitmap(struct index_state *istate) { - unsigned int i; + unsigned int i, skipped = 0; istate->fsmonitor_dirty = ewah_new(); - for (i = 0; i < istate->cache_nr; i++) - if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID)) - ewah_set(istate->fsmonitor_dirty, i); + for (i = 0; i < istate->cache_nr; i++) { + if (istate->cache[i]->ce_flags & CE_REMOVE) + skipped++; + else if (!(istate->cache[i]->ce_flags & CE_FSMONITOR_VALID)) + ewah_set(istate->fsmonitor_dirty, i - skipped); + } } void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate) @@ -71,6 +83,10 @@ void write_fsmonitor_extension(struct strbuf *sb, struct index_state *istate) uint32_t ewah_size = 0; int fixup = 0; + if (istate->fsmonitor_dirty->bit_size > istate->cache_nr) + BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)", + (uintmax_t)istate->fsmonitor_dirty->bit_size, istate->cache_nr); + put_be32(&hdr_version, INDEX_EXTENSION_VERSION); strbuf_add(sb, &hdr_version, sizeof(uint32_t)); @@ -236,6 +252,9 @@ void tweak_fsmonitor(struct index_state *istate) } /* Mark all previously saved entries as dirty */ + if (istate->fsmonitor_dirty->bit_size > istate->cache_nr) + BUG("fsmonitor_dirty has more entries than the index (%"PRIuMAX" > %u)", + (uintmax_t)istate->fsmonitor_dirty->bit_size, istate->cache_nr); ewah_each_bit(istate->fsmonitor_dirty, fsmonitor_ewah_callback, istate); /* Now mark the untracked cache for fsmonitor usage */ diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh index 81a375fa0f..87042470ab 100755 --- a/t/t7519-status-fsmonitor.sh +++ b/t/t7519-status-fsmonitor.sh @@ -354,4 +354,17 @@ test_expect_success 'discard_index() also discards fsmonitor info' ' test_cmp expect actual ' +# This test covers staging/unstaging files that appear at the end of the index. +# Test files with names beginning with 'z' are used under the assumption that +# earlier tests do not add/leave index entries that sort below them. +test_expect_success 'status succeeds after staging/unstaging ' ' + test_commit initial && + removed=$(test_seq 1 100 | sed "s/^/z/") && + touch $removed && + git add $removed && + test_config core.fsmonitor "$TEST_DIRECTORY/t7519/fsmonitor-env" && + FSMONITOR_LIST="$removed" git restore -S $removed && + FSMONITOR_LIST="$removed" git status +' + test_done diff --git a/t/t7519/fsmonitor-env b/t/t7519/fsmonitor-env new file mode 100755 index 0000000000..8f1f7ab164 --- /dev/null +++ b/t/t7519/fsmonitor-env @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An test hook script to integrate with git to test fsmonitor. +# +# The hook is passed a version (currently 1) and a time in nanoseconds +# formatted as a string and outputs to stdout all files that have been +# modified since the given time. Paths must be relative to the root of +# the working tree and separated by a single NUL. +# +#echo "$0 $*" >&2 + +if test "$#" -ne 2 +then + echo "$0: exactly 2 arguments expected" >&2 + exit 2 +fi + +if test "$1" != 1 +then + echo "Unsupported core.fsmonitor hook version." >&2 + exit 1 +fi + +printf '%s\n' $FSMONITOR_LIST