The previous patch has the logic to clear bits in 'WAMA' bitmap. This
patch has logic to set bits as told by watchman. The missing bit,
_using_ these bits, are not here yet.

A lot of this code is written by David Turner originally, mostly from
[1]. I'm just copying and polishing it a bit.

[1] http://article.gmane.org/gmane.comp.version-control.git/248006

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 Makefile                 |   7 +++
 cache.h                  |   1 +
 config.c                 |   5 +++
 configure.ac             |   8 ++++
 environment.c            |   3 ++
 watchman-support.c (new) | 108 +++++++++++++++++++++++++++++++++++++++++++++++
 watchman-support.h (new) |   8 ++++
 7 files changed, 140 insertions(+)
 create mode 100644 watchman-support.c
 create mode 100644 watchman-support.h

diff --git a/Makefile b/Makefile
index c01cd2e..761acb6 100644
--- a/Makefile
+++ b/Makefile
@@ -1389,6 +1389,12 @@ else
        LIB_OBJS += thread-utils.o
 endif
 
+ifdef USE_WATCHMAN
+       LIB_H += watchman-support.h
+       LIB_OBJS += watchman-support.o
+       BASIC_CFLAGS += -DUSE_WATCHMAN
+endif
+
 ifdef HAVE_PATHS_H
        BASIC_CFLAGS += -DHAVE_PATHS_H
 endif
@@ -2135,6 +2141,7 @@ GIT-BUILD-OPTIONS: FORCE
        @echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@+
        @echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@+
        @echo NO_UNIX_SOCKETS=\''$(subst ','\'',$(subst 
','\'',$(NO_UNIX_SOCKETS)))'\' >>$@+
+       @echo USE_WATCHMAN=\''$(subst ','\'',$(subst 
','\'',$(USE_WATCHMAN)))'\' >>$@+
 ifdef TEST_OUTPUT_DIRECTORY
        @echo TEST_OUTPUT_DIRECTORY=\''$(subst ','\'',$(subst 
','\'',$(TEST_OUTPUT_DIRECTORY)))'\' >>$@+
 endif
diff --git a/cache.h b/cache.h
index a05fd31..572299c 100644
--- a/cache.h
+++ b/cache.h
@@ -648,6 +648,7 @@ extern char *git_replace_ref_base;
 
 extern int fsync_object_files;
 extern int core_preload_index;
+extern int core_watchman_sync_timeout;
 extern int core_apply_sparse_checkout;
 extern int precomposed_unicode;
 extern int protect_hfs;
diff --git a/config.c b/config.c
index 248a21a..6b63f66 100644
--- a/config.c
+++ b/config.c
@@ -881,6 +881,11 @@ static int git_default_core_config(const char *var, const 
char *value)
                return 0;
        }
 
+       if (!strcmp(var, "core.watchmansynctimeout")) {
+               core_watchman_sync_timeout = git_config_int(var, value);
+               return 0;
+       }
+
        if (!strcmp(var, "core.createobject")) {
                if (!strcmp(value, "rename"))
                        object_creation_mode = OBJECT_CREATION_USES_RENAMES;
diff --git a/configure.ac b/configure.ac
index 76170ad..9772f79 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1092,6 +1092,14 @@ AC_COMPILE_IFELSE([BSD_SYSCTL_SRC],
        HAVE_BSD_SYSCTL=])
 GIT_CONF_SUBST([HAVE_BSD_SYSCTL])
 
+#
+# Check for watchman client library
+
+AC_CHECK_LIB([watchman], [watchman_connect],
+       [USE_WATCHMAN=YesPlease],
+       [USE_WATCHMAN=])
+GIT_CONF_SUBST([USE_WATCHMAN])
+
 ## Other checks.
 # Define USE_PIC if you need the main git objects to be built with -fPIC
 # in order to build and link perl/Git.so.  x86-64 seems to need this.
diff --git a/environment.c b/environment.c
index 2da7fe2..84df431 100644
--- a/environment.c
+++ b/environment.c
@@ -87,6 +87,9 @@ int auto_comment_line_char;
 /* Parallel index stat data preload? */
 int core_preload_index = 1;
 
+int core_watchman_sync_timeout = 300;
+
+
 /* This is set by setup_git_dir_gently() and/or git_default_config() */
 char *git_work_tree_cfg;
 static char *work_tree;
diff --git a/watchman-support.c b/watchman-support.c
new file mode 100644
index 0000000..7f6c0a9
--- /dev/null
+++ b/watchman-support.c
@@ -0,0 +1,108 @@
+#include "cache.h"
+#include "watchman-support.h"
+#include "strbuf.h"
+#include <watchman.h>
+
+static struct watchman_query *make_query(const char *last_update)
+{
+       struct watchman_query *query = watchman_query();
+       watchman_query_set_fields(query, WATCHMAN_FIELD_NAME |
+                                        WATCHMAN_FIELD_EXISTS |
+                                        WATCHMAN_FIELD_NEWER);
+       watchman_query_set_empty_on_fresh(query, 1);
+       query->sync_timeout = core_watchman_sync_timeout;
+       if (*last_update)
+               watchman_query_set_since_oclock(query, last_update);
+       return query;
+}
+
+static struct watchman_query_result* query_watchman(
+       struct index_state *istate, struct watchman_connection *connection,
+       const char *fs_path, const char *last_update)
+{
+       struct watchman_error wm_error;
+       struct watchman_query *query;
+       struct watchman_expression *expr;
+       struct watchman_query_result *result;
+
+       query = make_query(last_update);
+       expr = watchman_true_expression();
+       result = watchman_do_query(connection, fs_path, query, expr, &wm_error);
+       watchman_free_query(query);
+       watchman_free_expression(expr);
+
+       if (!result)
+               warning("Watchman query error: %s (at %s)",
+                       wm_error.message,
+                       *last_update ? last_update : "the beginning");
+
+       return result;
+}
+
+static void update_index(struct index_state *istate,
+                        struct watchman_query_result *result)
+{
+       int i;
+
+       if (result->is_fresh_instance) {
+               /* let refresh clear them later */
+               for (i = 0; i < istate->cache_nr; i++)
+                       istate->cache[i]->ce_flags |= CE_NO_WATCH;
+               goto done;
+       }
+
+       for (i = 0; i < result->nr; i++) {
+               struct watchman_stat *wm = result->stats + i;
+               int pos;
+
+               if (!strncmp(wm->name, ".git/", 5) ||
+                   strstr(wm->name, "/.git/"))
+                       continue;
+
+               pos = index_name_pos(istate, wm->name, strlen(wm->name));
+               if (pos < 0)
+                       continue;
+               /* FIXME: ignore staged entries and gitlinks too? */
+
+               istate->cache[pos]->ce_flags |= CE_NO_WATCH;
+       }
+
+done:
+       free(istate->last_update);
+       istate->last_update    = xstrdup(result->clock);
+       istate->cache_changed |= WATCHMAN_CHANGED;
+}
+
+int check_watchman(struct index_state *istate)
+{
+       struct watchman_error wm_error;
+       struct watchman_connection *connection;
+       struct watchman_query_result *result;
+       const char *fs_path;
+
+       fs_path = get_git_work_tree();
+       if (!fs_path)
+               return -1;
+
+       connection = watchman_connect(&wm_error);
+
+       if (!connection) {
+               warning("Watchman watch error: %s", wm_error.message);
+               return -1;
+       }
+
+       if (watchman_watch(connection, fs_path, &wm_error)) {
+               warning("Watchman watch error: %s", wm_error.message);
+               watchman_connection_close(connection);
+               return -1;
+       }
+
+
+       result = query_watchman(istate, connection, fs_path, 
istate->last_update);
+       watchman_connection_close(connection);
+       if (!result)
+               return -1;
+       update_index(istate, result);
+       watchman_free_query_result(result);
+       return 0;
+}
diff --git a/watchman-support.h b/watchman-support.h
new file mode 100644
index 0000000..5610409
--- /dev/null
+++ b/watchman-support.h
@@ -0,0 +1,8 @@
+#ifndef WATCHMAN_SUPPORT_H
+#define WATCHMAN_SUPPORT_H
+
+struct index_state;
+int check_watchman(struct index_state *index);
+
+
+#endif /* WATCHMAN_SUPPORT_H */
-- 
2.2.0.513.g477eb31

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

Reply via email to