Merge branch 'bp/fsmonitor'

We learned to talk to watchman to speed up "git status" and other
operations that need to see which paths have been modified.

* bp/fsmonitor:
  fsmonitor: preserve utf8 filenames in fsmonitor-watchman log
  fsmonitor: read entirety of watchman output
  fsmonitor: MINGW support for watchman integration
  fsmonitor: add a performance test
  fsmonitor: add a sample integration script for Watchman
  fsmonitor: add test cases for fsmonitor extension
  split-index: disable the fsmonitor extension when running the split index test
  fsmonitor: add a test tool to dump the index extension
  update-index: add fsmonitor support to update-index
  ls-files: Add support in ls-files to display the fsmonitor valid bit
  fsmonitor: add documentation for the fsmonitor extension.
  fsmonitor: teach git to optionally utilize a file system monitor to speed up detecting new or changed files.
  update-index: add a new --force-write-index option
  preload-index: add override to enable testing preload-index
  bswap: add 64 bit endianness helper get_be64
This commit is contained in:
Junio C Hamano
2017-11-21 14:07:50 +09:00
33 changed files with 1570 additions and 23 deletions

View File

@ -19,6 +19,7 @@
#include "varint.h"
#include "split-index.h"
#include "utf8.h"
#include "fsmonitor.h"
/* Mask for the name length in ce_flags in the on-disk index */
@ -38,11 +39,12 @@
#define CACHE_EXT_RESOLVE_UNDO 0x52455543 /* "REUC" */
#define CACHE_EXT_LINK 0x6c696e6b /* "link" */
#define CACHE_EXT_UNTRACKED 0x554E5452 /* "UNTR" */
#define CACHE_EXT_FSMONITOR 0x46534D4E /* "FSMN" */
/* changes that can be kept in $GIT_DIR/index (basically all extensions) */
#define EXTMASK (RESOLVE_UNDO_CHANGED | CACHE_TREE_CHANGED | \
CE_ENTRY_ADDED | CE_ENTRY_REMOVED | CE_ENTRY_CHANGED | \
SPLIT_INDEX_ORDERED | UNTRACKED_CHANGED)
SPLIT_INDEX_ORDERED | UNTRACKED_CHANGED | FSMONITOR_CHANGED)
struct index_state the_index;
static const char *alternate_index_output;
@ -62,6 +64,7 @@ static void replace_index_entry(struct index_state *istate, int nr, struct cache
free(old);
set_index_entry(istate, nr, ce);
ce->ce_flags |= CE_UPDATE_IN_BASE;
mark_fsmonitor_invalid(istate, ce);
istate->cache_changed |= CE_ENTRY_CHANGED;
}
@ -150,8 +153,10 @@ void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
if (assume_unchanged)
ce->ce_flags |= CE_VALID;
if (S_ISREG(st->st_mode))
if (S_ISREG(st->st_mode)) {
ce_mark_uptodate(ce);
mark_fsmonitor_valid(ce);
}
}
static int ce_compare_data(const struct cache_entry *ce, struct stat *st)
@ -301,7 +306,7 @@ int match_stat_data_racy(const struct index_state *istate,
return match_stat_data(sd, st);
}
int ie_match_stat(const struct index_state *istate,
int ie_match_stat(struct index_state *istate,
const struct cache_entry *ce, struct stat *st,
unsigned int options)
{
@ -309,7 +314,10 @@ int ie_match_stat(const struct index_state *istate,
int ignore_valid = options & CE_MATCH_IGNORE_VALID;
int ignore_skip_worktree = options & CE_MATCH_IGNORE_SKIP_WORKTREE;
int assume_racy_is_modified = options & CE_MATCH_RACY_IS_DIRTY;
int ignore_fsmonitor = options & CE_MATCH_IGNORE_FSMONITOR;
if (!ignore_fsmonitor)
refresh_fsmonitor(istate);
/*
* If it's marked as always valid in the index, it's
* valid whatever the checked-out copy says.
@ -320,6 +328,8 @@ int ie_match_stat(const struct index_state *istate,
return 0;
if (!ignore_valid && (ce->ce_flags & CE_VALID))
return 0;
if (!ignore_fsmonitor && (ce->ce_flags & CE_FSMONITOR_VALID))
return 0;
/*
* Intent-to-add entries have not been added, so the index entry
@ -357,7 +367,7 @@ int ie_match_stat(const struct index_state *istate,
return changed;
}
int ie_modified(const struct index_state *istate,
int ie_modified(struct index_state *istate,
const struct cache_entry *ce,
struct stat *st, unsigned int options)
{
@ -778,6 +788,7 @@ int chmod_index_entry(struct index_state *istate, struct cache_entry *ce,
}
cache_tree_invalidate_path(istate, ce->name);
ce->ce_flags |= CE_UPDATE_IN_BASE;
mark_fsmonitor_invalid(istate, ce);
istate->cache_changed |= CE_ENTRY_CHANGED;
return 0;
@ -1229,10 +1240,13 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
int ignore_valid = options & CE_MATCH_IGNORE_VALID;
int ignore_skip_worktree = options & CE_MATCH_IGNORE_SKIP_WORKTREE;
int ignore_missing = options & CE_MATCH_IGNORE_MISSING;
int ignore_fsmonitor = options & CE_MATCH_IGNORE_FSMONITOR;
if (!refresh || ce_uptodate(ce))
return ce;
if (!ignore_fsmonitor)
refresh_fsmonitor(istate);
/*
* CE_VALID or CE_SKIP_WORKTREE means the user promised us
* that the change to the work tree does not matter and told
@ -1246,6 +1260,10 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
ce_mark_uptodate(ce);
return ce;
}
if (!ignore_fsmonitor && (ce->ce_flags & CE_FSMONITOR_VALID)) {
ce_mark_uptodate(ce);
return ce;
}
if (has_symlink_leading_path(ce->name, ce_namelen(ce))) {
if (ignore_missing)
@ -1283,8 +1301,10 @@ 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.
*/
if (!S_ISGITLINK(ce->ce_mode))
if (!S_ISGITLINK(ce->ce_mode)) {
ce_mark_uptodate(ce);
mark_fsmonitor_valid(ce);
}
return ce;
}
}
@ -1392,6 +1412,7 @@ int refresh_index(struct index_state *istate, unsigned int flags,
*/
ce->ce_flags &= ~CE_VALID;
ce->ce_flags |= CE_UPDATE_IN_BASE;
mark_fsmonitor_invalid(istate, ce);
istate->cache_changed |= CE_ENTRY_CHANGED;
}
if (quiet)
@ -1554,6 +1575,9 @@ static int read_index_extension(struct index_state *istate,
case CACHE_EXT_UNTRACKED:
istate->untracked = read_untracked_extension(data, sz);
break;
case CACHE_EXT_FSMONITOR:
read_fsmonitor_extension(istate, data, sz);
break;
default:
if (*ext < 'A' || 'Z' < *ext)
return error("index uses %.4s extension, which we do not understand",
@ -1729,6 +1753,7 @@ static void post_read_index_from(struct index_state *istate)
check_ce_order(istate);
tweak_untracked_cache(istate);
tweak_split_index(istate);
tweak_fsmonitor(istate);
}
/* remember to discard_cache() before reading a different cache! */
@ -2320,6 +2345,16 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
if (err)
return -1;
}
if (!strip_extensions && istate->fsmonitor_last_update) {
struct strbuf sb = STRBUF_INIT;
write_fsmonitor_extension(&sb, istate);
err = write_index_ext_header(&c, newfd, CACHE_EXT_FSMONITOR, sb.len) < 0
|| ce_write(&c, newfd, sb.buf, sb.len) < 0;
strbuf_release(&sb);
if (err)
return -1;
}
if (ce_flush(&c, newfd, istate->sha1))
return -1;