From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH v3 23/26] file-watcher: tests for the daemon
Date: Mon, 3 Feb 2014 11:29:11 +0700 [thread overview]
Message-ID: <1391401754-15347-24-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1391401754-15347-1-git-send-email-pclouds@gmail.com>
test-file-watcher is a simple chat program to talk to file
watcher. Typically you would write something like this
cat >expect <<EOF
# send "hello". Oh and this is a comment!
<hello
# Wait for reply and print to stdout.
# test-file-watcher does not care about anything after '>'
>hello
<index foo bar
>ok
EOF
test-file-watcher . <expect >actual
and test-file-watcher will execute the commands and get responses. If
all go well, "actual" should be the same as "expect". '<' and '>'
denote send and receive packets respectively. '<<' and '>>' can be
used to send and receive a list of NUL-terminated paths.
$GIT_TEST_WATCHER enables a few more commands for testing purposes.
The most important one is 'test-mode' where system inotify is taken
out and inotify events could be injected via test-file-watcher.
There are two debug commands in file-watcher that's not used by the
test suite, but would help debugging: setenv and log. They can be used
to turn on GIT_TRACE_PACKET then any "log" command will show, which
functions as barrier between events file watcher.
GIT_TRACE_WATCHER can also be enabled (dynamically or at startup) to
track inotify events.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
.gitignore | 1 +
Makefile | 1 +
file-watcher.c | 181 ++++++++++++++++++-
t/t7513-file-watcher.sh (new +x) | 382 +++++++++++++++++++++++++++++++++++++++
test-file-watcher.c (new) | 96 ++++++++++
5 files changed, 657 insertions(+), 4 deletions(-)
create mode 100755 t/t7513-file-watcher.sh
create mode 100644 test-file-watcher.c
diff --git a/.gitignore b/.gitignore
index 12c78f0..277f929 100644
--- a/.gitignore
+++ b/.gitignore
@@ -181,6 +181,7 @@
/test-date
/test-delta
/test-dump-cache-tree
+/test-file-watcher
/test-scrap-cache-tree
/test-genrandom
/test-index-version
diff --git a/Makefile b/Makefile
index 1c4d659..f0dc2cc 100644
--- a/Makefile
+++ b/Makefile
@@ -555,6 +555,7 @@ TEST_PROGRAMS_NEED_X += test-ctype
TEST_PROGRAMS_NEED_X += test-date
TEST_PROGRAMS_NEED_X += test-delta
TEST_PROGRAMS_NEED_X += test-dump-cache-tree
+TEST_PROGRAMS_NEED_X += test-file-watcher
TEST_PROGRAMS_NEED_X += test-genrandom
TEST_PROGRAMS_NEED_X += test-index-version
TEST_PROGRAMS_NEED_X += test-line-buffer
diff --git a/file-watcher.c b/file-watcher.c
index 1e45b25..3ab0a11 100644
--- a/file-watcher.c
+++ b/file-watcher.c
@@ -65,7 +65,8 @@ struct connection {
static struct connection **conns;
static struct pollfd *pfd;
static int conns_alloc, pfd_nr, pfd_alloc;
-static int inotify_fd;
+static int inotify_fd, test_mode;
+static int wd_counter = 1;
/*
* IN_DONT_FOLLOW does not matter now as we do not monitor
@@ -78,10 +79,19 @@ static struct dir *create_dir(struct dir *parent, const char *path,
const char *basename)
{
struct dir *d;
- int wd = inotify_add_watch(inotify_fd, path, INOTIFY_MASKS);
+ int wd;
+ if (!test_mode)
+ wd = inotify_add_watch(inotify_fd, path, INOTIFY_MASKS);
+ else {
+ wd = wd_counter++;
+ if (wd > 8)
+ wd = -1;
+ }
if (wd < 0)
return NULL;
+ trace_printf_key("GIT_TRACE_WATCHER", "inotify: watch %d %s\n",
+ wd, path);
d = xmalloc(sizeof(*d));
memset(d, 0, sizeof(*d));
d->wd = wd;
@@ -124,7 +134,9 @@ static void free_dir(struct dir *d, int topdown)
if (d->repo)
d->repo->root = NULL;
wds[d->wd] = NULL;
- inotify_rm_watch(inotify_fd, d->wd);
+ if (!test_mode)
+ inotify_rm_watch(inotify_fd, d->wd);
+ trace_printf_key("GIT_TRACE_WATCHER", "inotify: unwatch %d\n", d->wd);
if (topdown) {
int i;
for (i = 0; i < d->nr_subdirs; i++)
@@ -265,6 +277,7 @@ static inline void queue_file_changed(struct file *f, struct strbuf *sb)
int len = sb->len;
strbuf_addf(sb, "%s%s", f->parent->parent ? "/" : "", f->name);
string_list_append(&f->repo->updated, sb->buf);
+ trace_printf_key("GIT_TRACE_WATCHER", "watcher: changed %s\n", sb->buf);
f->repo->updated_sorted = 0;
strbuf_setlen(sb, len);
}
@@ -324,6 +337,10 @@ static int do_handle_inotify(const struct inotify_event *event)
struct dir *d;
int pos;
+ trace_printf_key("GIT_TRACE_WATCHER", "inotify: event %08x wd %d %s\n",
+ event->mask, event->wd,
+ event->len ? event->name : "N/A");
+
if (event->mask & (IN_Q_OVERFLOW | IN_UNMOUNT)) {
int i;
for (i = 0; i < nr_repos; i++)
@@ -385,6 +402,81 @@ static int handle_inotify(int fd)
return ret;
}
+struct constant {
+ const char *name;
+ int value;
+};
+
+#define CONSTANT(x) { #x, x }
+static const struct constant inotify_masks[] = {
+ CONSTANT(IN_DELETE_SELF),
+ CONSTANT(IN_MOVE_SELF),
+ CONSTANT(IN_ATTRIB),
+ CONSTANT(IN_DELETE),
+ CONSTANT(IN_MODIFY),
+ CONSTANT(IN_MOVED_FROM),
+ CONSTANT(IN_MOVED_TO),
+ CONSTANT(IN_Q_OVERFLOW),
+ CONSTANT(IN_UNMOUNT),
+ { NULL, 0 },
+};
+
+static void inject_inotify(const char *msg)
+{
+ char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
+ struct inotify_event *event = (struct inotify_event *)buf;
+ char *end, *p;
+ int i;
+ memset(event, 0, sizeof(*event));
+ event->wd = strtol(msg, &end, 0);
+ if (*end++ != ' ')
+ die("expect a space after watch descriptor");
+ p = end;
+ end = strchrnul(p, ' ');
+ if (*end)
+ strcpy(event->name, end + 1);
+ while (p < end) {
+ char *sep = strchrnul(p, '|');
+ if (sep > end)
+ sep = end;
+ *sep = '\0';
+ for (i = 0; inotify_masks[i].name; i++)
+ if (!strcmp(inotify_masks[i].name, p))
+ break;
+ if (!inotify_masks[i].name)
+ die("unrecognize event mask %s", p);
+ event->mask |= inotify_masks[i].value;
+ p = sep + 1;
+ }
+ do_handle_inotify(event);
+}
+
+static void dump_watches(struct dir *d, struct strbuf *sb, struct strbuf *out)
+{
+ int i, len = sb->len;
+ strbuf_addstr(sb, d->name);
+ strbuf_addf(out, "%s %d%c", sb->buf[0] ? sb->buf : ".", d->wd, '\0');
+ if (d->name[0])
+ strbuf_addch(sb, '/');
+ for (i = 0; i < d->nr_subdirs; i++)
+ dump_watches(d->subdirs[i], sb, out);
+ for (i = 0; i < d->nr_files; i++)
+ strbuf_addf(out, "%s%s%c", sb->buf, d->files[i]->name, '\0');
+ strbuf_setlen(sb, len);
+}
+
+static void dump_changes(struct repository *repo, struct strbuf *sb)
+{
+ int i;
+ if (!repo->updated_sorted) {
+ sort_string_list(&repo->updated);
+ repo->updated_sorted = 1;
+ }
+ for (i = 0; i < repo->updated.nr; i++)
+ strbuf_add(sb, repo->updated.items[i].string,
+ strlen(repo->updated.items[i].string) + 1);
+}
+
static void get_changed_list(int conn_id)
{
struct strbuf sb = STRBUF_INIT;
@@ -483,11 +575,13 @@ static void unchange(int conn_id, unsigned long size)
item = string_list_lookup(&repo->updated, p);
if (!item)
continue;
+ trace_printf_key("GIT_TRACE_WATCHER", "watcher: unchange %s\n", p);
unsorted_string_list_delete_item(&repo->updated,
item - repo->updated.items, 0);
}
strbuf_release(&sb);
}
+ trace_printf_key("GIT_TRACE_WATCHER", "watcher: unchange complete\n");
memcpy(repo->index_signature, conn->new_index, 40);
/*
* If other connections on this repo are in some sort of
@@ -540,6 +634,13 @@ static void reset_watches(struct repository *repo)
static void reset_repo(struct repository *repo, ino_t inode)
{
+ if (test_mode)
+ /*
+ * test-mode is designed for single repo, we can
+ * safely reset wd counter because all wd should be
+ * deleted
+ */
+ wd_counter = 1;
reset_watches(repo);
string_list_clear(&repo->updated, 0);
memcpy(repo->index_signature, invalid_signature, 40);
@@ -560,6 +661,7 @@ static int shutdown_connection(int id)
return 0;
}
+static void cleanup(void);
static int handle_command(int conn_id)
{
int fd = conns[conn_id]->sock;
@@ -754,6 +856,71 @@ static int handle_command(int conn_id)
}
unchange(conn_id, n);
}
+
+ /*
+ * Testing and debugging support
+ */
+ else if (!strcmp(msg, "test-mode") && getenv("GIT_TEST_WATCHER")) {
+ test_mode = 1;
+ packet_write(fd, "test mode on");
+ }
+ else if (starts_with(msg, "setenv ")) {
+ /* useful for setting GIT_TRACE_WATCHER or GIT_TRACE_PACKET */
+ char *sep = strchr(msg + 7, ' ');
+ if (!sep) {
+ packet_write(fd, "error invalid setenv line %s", msg);
+ return shutdown_connection(conn_id);
+ }
+ *sep = '\0';
+ setenv(msg + 7, sep + 1, 1);
+ }
+ else if (starts_with(msg, "log ")) {
+ ; /* do nothing, if GIT_TRACE_PACKET is on, it's already logged */
+ }
+ else if (!strcmp(msg, "die") && getenv("GIT_TEST_WATCHER")) {
+ /*
+ * The client will wait for "see you" before it may
+ * run another daemon with the same path. So there's
+ * no racing on unlink() and listen() on the same
+ * socket path.
+ */
+ cleanup();
+ packet_write(fd, "see you");
+ close(fd);
+ exit(0);
+ }
+ else if (starts_with(msg, "dump ") && getenv("GIT_TEST_WATCHER")) {
+ struct strbuf sb = STRBUF_INIT;
+ struct strbuf out = STRBUF_INIT;
+ const char *reply = NULL;
+ if (!strcmp(msg + 5, "watches")) {
+ if (conns[conn_id]->repo) {
+ if (conns[conn_id]->repo->root)
+ dump_watches(conns[conn_id]->repo->root, &sb, &out);
+ } else {
+ int i;
+ for (i = 0; i < nr_repos; i++) {
+ strbuf_addf(&out, "%s%c", repos[i]->work_tree, '\0');
+ if (repos[i]->root)
+ dump_watches(repos[i]->root, &sb, &out);
+ strbuf_reset(&out);
+ strbuf_reset(&sb);
+ }
+ }
+ reply = "watching";
+ } else if (!strcmp(msg + 5, "changes")) {
+ dump_changes(conns[conn_id]->repo, &out);
+ reply = "changed";
+ }
+ packet_write(fd, "%s %d", reply, (int)out.len);
+ if (out.len)
+ write_in_full(fd, out.buf, out.len);
+ strbuf_release(&out);
+ strbuf_release(&sb);
+ }
+ else if (starts_with(msg, "inotify ") && getenv("GIT_TEST_WATCHER")) {
+ inject_inotify(msg + 8);
+ }
else {
packet_write(fd, "error unrecognized command %s", msg);
return shutdown_connection(conn_id);
@@ -848,11 +1015,13 @@ int main(int argc, const char **argv)
{
struct strbuf sb = STRBUF_INIT;
int i, new_nr, fd, quit = 0, nr_common;
- int daemon = 0;
+ int daemon = 0, check_support = 0;
time_t last_checked;
struct option options[] = {
OPT_BOOL(0, "detach", &daemon,
N_("run in background")),
+ OPT_BOOL(0, "check-support", &check_support,
+ N_("return zero file watcher is available")),
OPT_END()
};
@@ -865,6 +1034,10 @@ int main(int argc, const char **argv)
argc = parse_options(argc, argv, NULL, options,
file_watcher_usage, 0);
+
+ if (check_support)
+ return 0;
+
if (argc < 1)
die(_("socket path missing"));
else if (argc > 1)
diff --git a/t/t7513-file-watcher.sh b/t/t7513-file-watcher.sh
new file mode 100755
index 0000000..bf64fc4
--- /dev/null
+++ b/t/t7513-file-watcher.sh
@@ -0,0 +1,382 @@
+#!/bin/sh
+
+test_description='File watcher daemon tests'
+
+. ./test-lib.sh
+
+if git file-watcher --check-support && test_have_prereq POSIXPERM; then
+ : # good
+else
+ skip_all="file-watcher not supported on this system"
+ test_done
+fi
+
+kill_it() {
+ test-file-watcher "$1" <<EOF >/dev/null
+<die
+>see you
+EOF
+}
+
+GIT_TEST_WATCHER=1
+export GIT_TEST_WATCHER
+
+test_expect_success 'test-file-watcher can kill the daemon' '
+ chmod 700 . &&
+ git file-watcher --detach . &&
+ cat >expect <<EOF &&
+<die
+>see you
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual &&
+ ! test -S socket
+'
+
+test_expect_success 'exchange hello' '
+ git file-watcher --detach . &&
+ cat >expect <<EOF &&
+<hello
+>hello
+<die
+>see you
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'normal index sequence' '
+ git file-watcher --detach . &&
+ SIG=0123456789012345678901234567890123456789 &&
+ cat >expect <<EOF &&
+<hello
+>hello
+<index $SIG $TRASH_DIRECTORY
+>inconsistent
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual &&
+ cat >expect2 <<EOF &&
+<hello
+>hello
+<index $SIG $TRASH_DIRECTORY
+# inconsistent again because new-index has not been issued yet
+>inconsistent
+<new-index $SIG
+<<unchange
+<<
+EOF
+ test-file-watcher . >actual2 <expect2 &&
+ test_cmp expect2 actual2 &&
+ cat >expect3 <<EOF &&
+<hello
+>hello
+<index $SIG $TRASH_DIRECTORY
+>ok
+<die
+>see you
+EOF
+ test-file-watcher . >actual3 <expect3 &&
+ test_cmp expect3 actual3
+'
+
+test_expect_success 'unaccepted index: hello not sent' '
+ git file-watcher --detach . &&
+ SIG=0123456789012345678901234567890123456789 &&
+ cat >expect <<EOF &&
+<index $SIG $TRASH_DIRECTORY
+>error why did you not greet me? go away
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual &&
+ kill_it .
+'
+
+test_expect_success 'unaccepted index: signature too short' '
+ git file-watcher --detach . &&
+ cat >expect <<EOF &&
+<hello
+>hello
+<index 1234 $TRASH_DIRECTORY
+>error invalid index line index 1234 $TRASH_DIRECTORY
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual &&
+ kill_it .
+'
+
+test_expect_success 'unaccepted index: worktree unavailable' '
+ git file-watcher --detach . &&
+ SIG=0123456789012345678901234567890123456789 &&
+ cat >expect <<EOF &&
+<hello
+>hello
+<index $SIG $TRASH_DIRECTORY/non-existent
+>error work tree does not exist: No such file or directory
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual &&
+ kill_it .
+'
+
+test_expect_success 'watch foo and abc/bar' '
+ git file-watcher --detach . &&
+ SIG=0123456789012345678901234567890123456789 &&
+ cat >expect <<EOF &&
+<hello
+>hello
+<index $SIG $TRASH_DIRECTORY
+>inconsistent
+<test-mode
+>test mode on
+<<watch
+<<foo
+<<abc/bar
+<<
+>watched 2
+<dump watches
+>>watching
+>>. 1
+>>abc 2
+>>abc/bar
+>>foo
+<new-index $SIG
+<<unchange
+<<
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'modify abc/bar' '
+ SIG=0123456789012345678901234567890123456789 &&
+ cat >expect <<EOF &&
+<hello
+>hello
+<index $SIG $TRASH_DIRECTORY
+>ok
+<inotify 2 IN_MODIFY bar
+<dump watches
+>>watching
+>>. 1
+>>foo
+<dump changes
+>>changed
+>>abc/bar
+<die
+>see you
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'delete abc makes abc/bar changed' '
+ git file-watcher --detach . &&
+ SIG=0123456789012345678901234567890123456789 &&
+ cat >expect <<EOF &&
+<hello
+>hello
+<index $SIG $TRASH_DIRECTORY
+>inconsistent
+<test-mode
+>test mode on
+<<watch
+<<foo/abc/bar
+<<
+>watched 1
+<dump watches
+>>watching
+>>. 1
+>>foo 2
+>>foo/abc 3
+>>foo/abc/bar
+<inotify 2 IN_DELETE_SELF
+<dump watches
+>>watching
+<dump changes
+>>changed
+>>foo/abc/bar
+<new-index $SIG
+<<unchange
+<<
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'get changed list' '
+ SIG=0123456789012345678901234567890123456789 &&
+ cat >expect <<EOF &&
+<hello
+>hello
+<index $SIG $TRASH_DIRECTORY
+>ok
+<get-changed
+>>changed
+>>foo/abc/bar
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'incomplete new-index request' '
+ SIG=0123456789012345678901234567890123456789 &&
+ SIG2=9123456789012345678901234567890123456780 &&
+ cat >expect <<EOF &&
+<hello
+>hello
+<index $SIG $TRASH_DIRECTORY
+>ok
+<new-index $SIG2
+<dump changes
+>>changed
+>>foo/abc/bar
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'delete abc/bar from changed list' '
+ SIG=0123456789012345678901234567890123456789 &&
+ SIG2=9123456789012345678901234567890123456780 &&
+ cat >expect <<EOF &&
+<hello
+>hello
+<index $SIG $TRASH_DIRECTORY
+>ok
+<new-index $SIG2
+<<unchange
+<<foo/abc/bar
+<<
+<dump changes
+>>changed
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'file-watcher index updated after new-index' '
+ SIG2=9123456789012345678901234567890123456780 &&
+ cat >expect <<EOF &&
+<hello
+>hello
+<index $SIG2 $TRASH_DIRECTORY
+>ok
+<die
+>see you
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual
+'
+
+# When test-mode is on, file-watch only accepts 8 directories
+test_expect_success 'watch too many directories' '
+ git file-watcher --detach . &&
+ SIG=0123456789012345678901234567890123456789 &&
+ cat >expect <<EOF &&
+<hello
+>hello
+<index $SIG $TRASH_DIRECTORY
+>inconsistent
+# Do not call inotify_add_watch()
+<test-mode
+>test mode on
+# First batch should be all ok
+<<watch
+<<dir1/foo
+<<dir2/foo
+<<dir3/foo
+<<dir4/foo
+<<
+>watched 4
+# Second batch hits the limit
+<<watch
+<<dir5/foo
+<<dir6/foo
+<<dir7/foo
+<<dir8/foo
+<<dir9/foo
+<<
+>watched 3
+# The third batch is already registered, should accept too
+<<watch
+<<dir5/foo
+<<dir6/foo
+<<dir7/foo
+<<
+>watched 3
+# Try again, see if it still rejects
+<<watch
+<<dir8/foo
+<<dir9/foo
+<<
+>watched 0
+<dump watches
+>>watching
+>>. 1
+>>dir1 2
+>>dir1/foo
+>>dir2 3
+>>dir2/foo
+>>dir3 4
+>>dir3/foo
+>>dir4 5
+>>dir4/foo
+>>dir5 6
+>>dir5/foo
+>>dir6 7
+>>dir6/foo
+>>dir7 8
+>>dir7/foo
+<die
+>see you
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'event overflow' '
+ git file-watcher --detach . &&
+ SIG=0123456789012345678901234567890123456789 &&
+ cat >expect <<EOF &&
+<hello
+>hello
+<index $SIG $TRASH_DIRECTORY
+>inconsistent
+<test-mode
+>test mode on
+<<watch
+<<foo
+<<abc/bar
+<<
+>watched 2
+<inotify 2 IN_MODIFY bar
+<dump watches
+>>watching
+>>. 1
+>>foo
+<dump changes
+>>changed
+>>abc/bar
+<inotify -1 IN_Q_OVERFLOW
+<dump watches
+>>watching
+<dump changes
+>>changed
+EOF
+ test-file-watcher . >actual <expect &&
+ test_cmp expect actual &&
+ cat >expect2 <<EOF &&
+<hello
+>hello
+<index $SIG $TRASH_DIRECTORY
+# Must be inconsistent because of IN_Q_OVERFLOW
+>inconsistent
+<die
+>see you
+EOF
+ test-file-watcher . >actual2 <expect2 &&
+ test_cmp expect2 actual2
+'
+
+test_done
diff --git a/test-file-watcher.c b/test-file-watcher.c
new file mode 100644
index 0000000..ffff198
--- /dev/null
+++ b/test-file-watcher.c
@@ -0,0 +1,96 @@
+#include "cache.h"
+#include "unix-socket.h"
+#include "pkt-line.h"
+#include "strbuf.h"
+
+int main(int ac, char **av)
+{
+ struct strbuf sb = STRBUF_INIT;
+ struct strbuf packed = STRBUF_INIT;
+ char *packing = NULL;
+ int last_command_is_reply = 0;
+ int fd;
+
+ strbuf_addf(&sb, "%s/socket", av[1]);
+ fd = unix_stream_connect(sb.buf);
+ if (fd < 0)
+ die_errno("connect");
+ strbuf_reset(&sb);
+
+ /*
+ * test-file-watcher crashes sometimes, make sure to flush
+ */
+ setbuf(stdout, NULL);
+
+ while (!strbuf_getline(&sb, stdin, '\n')) {
+ if (sb.buf[0] == '#') {
+ puts(sb.buf);
+ continue;
+ }
+ if (sb.buf[0] == '>') {
+ if (last_command_is_reply)
+ continue;
+ last_command_is_reply = 1;
+ } else
+ last_command_is_reply = 0;
+
+ if (sb.buf[0] == '<' && sb.buf[1] == '<') {
+ puts(sb.buf);
+ if (!packing) {
+ packing = xstrdup(sb.buf + 2);
+ strbuf_reset(&packed);
+ continue;
+ }
+ if (!sb.buf[2]) {
+ packet_write(fd, "%s %d", packing, (int)packed.len);
+ if (packed.len)
+ write_in_full(fd, packed.buf, packed.len);
+ free(packing);
+ packing = NULL;
+ } else
+ strbuf_add(&packed, sb.buf + 2, sb.len - 2 + 1);
+ continue;
+ }
+ if (sb.buf[0] == '<') {
+ packet_write(fd, "%s", sb.buf + 1);
+ puts(sb.buf);
+ continue;
+ }
+ if (sb.buf[0] == '>' && sb.buf[1] == '>') {
+ int len;
+ char *p, *reply = packet_read_line(fd, &len);
+ if (!starts_with(reply, sb.buf + 2) ||
+ reply[sb.len - 2] != ' ') {
+ printf(">%s\n", reply);
+ continue;
+ } else {
+ p = reply + sb.len - 2;
+ printf(">>%.*s\n", (int)(p - reply), reply);
+ len = atoi(p + 1);
+ if (!len)
+ continue;
+ }
+ strbuf_reset(&packed);
+ strbuf_grow(&packed, len);
+ if (read_in_full(fd, packed.buf, len) <= 0)
+ return 1;
+ strbuf_setlen(&packed, len);
+ for (p = packed.buf; p - packed.buf < packed.len; p += len + 1) {
+ len = strlen(p);
+ printf(">>%s\n", p);
+ }
+ continue;
+ }
+ if (sb.buf[0] == '>') {
+ int len;
+ char *reply = packet_read_line(fd, &len);
+ if (!reply)
+ puts(">");
+ else
+ printf(">%s\n", reply);
+ continue;
+ }
+ die("unrecognize command %s", sb.buf);
+ }
+ return 0;
+}
--
1.8.5.2.240.g8478abd
next prev parent reply other threads:[~2014-02-03 4:31 UTC|newest]
Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-12 11:03 [PATCH 0/6] inotify support Nguyễn Thái Ngọc Duy
2014-01-12 11:03 ` [PATCH 1/6] read-cache: save trailing sha-1 Nguyễn Thái Ngọc Duy
2014-01-12 11:03 ` [PATCH 2/6] read-cache: new extension to mark what file is watched Nguyễn Thái Ngọc Duy
2014-01-13 17:02 ` Jonathan Nieder
2014-01-14 1:25 ` Duy Nguyen
2014-01-14 1:39 ` Duy Nguyen
2014-01-12 11:03 ` [PATCH 3/6] read-cache: connect to file watcher Nguyễn Thái Ngọc Duy
2014-01-15 10:58 ` Jeff King
2014-01-12 11:03 ` [PATCH 4/6] read-cache: get "updated" path list from " Nguyễn Thái Ngọc Duy
2014-01-12 11:03 ` [PATCH 5/6] read-cache: ask file watcher to watch files Nguyễn Thái Ngọc Duy
2014-01-12 11:03 ` [PATCH 6/6] file-watcher: support inotify Nguyễn Thái Ngọc Duy
2014-01-17 9:47 ` [PATCH/WIP v2 00/14] inotify support Nguyễn Thái Ngọc Duy
2014-01-17 9:47 ` [PATCH/WIP v2 01/14] read-cache: save trailing sha-1 Nguyễn Thái Ngọc Duy
2014-01-17 9:47 ` [PATCH/WIP v2 02/14] read-cache: new extension to mark what file is watched Nguyễn Thái Ngọc Duy
2014-01-17 11:19 ` Thomas Gummerer
2014-01-19 17:06 ` Thomas Rast
2014-01-20 1:38 ` Duy Nguyen
2014-01-17 9:47 ` [PATCH/WIP v2 03/14] read-cache: connect to file watcher Nguyễn Thái Ngọc Duy
2014-01-17 15:24 ` Torsten Bögershausen
2014-01-17 16:21 ` Duy Nguyen
2014-01-17 9:47 ` [PATCH/WIP v2 04/14] read-cache: ask file watcher to watch files Nguyễn Thái Ngọc Duy
2014-01-17 9:47 ` [PATCH/WIP v2 05/14] read-cache: put some limits on file watching Nguyễn Thái Ngọc Duy
2014-01-19 17:06 ` Thomas Rast
2014-01-20 1:36 ` Duy Nguyen
2014-01-17 9:47 ` [PATCH/WIP v2 06/14] read-cache: get modified file list from file watcher Nguyễn Thái Ngọc Duy
2014-01-17 9:47 ` [PATCH/WIP v2 07/14] read-cache: add config to start file watcher automatically Nguyễn Thái Ngọc Duy
2014-01-17 9:47 ` [PATCH/WIP v2 08/14] read-cache: add GIT_TEST_FORCE_WATCHER for testing Nguyễn Thái Ngọc Duy
2014-01-19 17:04 ` Thomas Rast
2014-01-20 1:32 ` Duy Nguyen
2014-01-17 9:47 ` [PATCH/WIP v2 09/14] file-watcher: add --shutdown and --log options Nguyễn Thái Ngọc Duy
2014-01-17 9:47 ` [PATCH/WIP v2 10/14] file-watcher: automatically quit Nguyễn Thái Ngọc Duy
2014-01-17 9:47 ` [PATCH/WIP v2 11/14] file-watcher: support inotify Nguyễn Thái Ngọc Duy
2014-01-19 17:04 ` [PATCH/WIP v2 00/14] inotify support Thomas Rast
2014-01-20 1:28 ` Duy Nguyen
2014-01-20 21:51 ` Thomas Rast
2014-01-28 10:46 ` Duy Nguyen
2014-02-03 4:28 ` [PATCH v3 00/26] " Nguyễn Thái Ngọc Duy
2014-02-03 4:28 ` [PATCH v3 01/26] pkt-line.c: rename global variable buffer[] to something less generic Nguyễn Thái Ngọc Duy
2014-02-03 4:28 ` [PATCH v3 02/26] pkt-line.c: add packet_write_timeout() Nguyễn Thái Ngọc Duy
2014-02-03 4:28 ` [PATCH v3 03/26] pkt-line.c: add packet_read_line_timeout() Nguyễn Thái Ngọc Duy
2014-02-03 4:28 ` [PATCH v3 04/26] unix-socket: make unlink() optional in unix_stream_listen() Nguyễn Thái Ngọc Duy
2014-02-03 4:28 ` [PATCH v3 05/26] Add git-file-watcher and basic connection handling logic Nguyễn Thái Ngọc Duy
2014-02-03 4:28 ` [PATCH v3 06/26] file-watcher: check socket directory permission Nguyễn Thái Ngọc Duy
2014-02-03 4:28 ` [PATCH v3 07/26] file-watcher: remove socket on exit Nguyễn Thái Ngọc Duy
2014-02-03 4:28 ` [PATCH v3 08/26] file-watcher: add --detach Nguyễn Thái Ngọc Duy
2014-02-03 4:28 ` [PATCH v3 09/26] read-cache: save trailing sha-1 Nguyễn Thái Ngọc Duy
2014-02-03 4:28 ` [PATCH v3 10/26] read-cache: new flag CE_WATCHED to mark what file is watched Nguyễn Thái Ngọc Duy
2014-02-03 4:28 ` [PATCH v3 11/26] Clear CE_WATCHED when set CE_VALID alone Nguyễn Thái Ngọc Duy
2014-02-03 4:29 ` [PATCH v3 12/26] read-cache: basic hand shaking to the file watcher Nguyễn Thái Ngọc Duy
2014-02-03 4:29 ` [PATCH v3 13/26] read-cache: ask file watcher to watch files Nguyễn Thái Ngọc Duy
2014-02-03 4:29 ` [PATCH v3 14/26] read-cache: put some limits on file watching Nguyễn Thái Ngọc Duy
2014-02-03 4:29 ` [PATCH v3 15/26] read-cache: get changed file list from file watcher Nguyễn Thái Ngọc Duy
2014-02-03 4:29 ` [PATCH v3 16/26] git-compat-util.h: add inotify stubs on non-Linux platforms Nguyễn Thái Ngọc Duy
2014-02-03 4:29 ` [PATCH v3 17/26] file-watcher: inotify support, watching part Nguyễn Thái Ngọc Duy
2014-02-03 4:29 ` [PATCH v3 18/26] file-watcher: inotify support, notification part Nguyễn Thái Ngọc Duy
2014-02-03 4:29 ` [PATCH v3 19/26] Wrap CE_VALID test with ce_valid() Nguyễn Thái Ngọc Duy
2014-02-03 4:29 ` [PATCH v3 20/26] read-cache: new variable to verify file-watcher results Nguyễn Thái Ngọc Duy
2014-02-03 4:29 ` [PATCH v3 21/26] Support running file watcher with the test suite Nguyễn Thái Ngọc Duy
2014-02-03 4:29 ` [PATCH v3 22/26] file-watcher: quit if $WATCHER/socket is gone Nguyễn Thái Ngọc Duy
2014-02-03 4:29 ` Nguyễn Thái Ngọc Duy [this message]
2014-02-03 4:29 ` [PATCH v3 24/26] ls-files: print CE_WATCHED as W (or "w" with CE_VALID) Nguyễn Thái Ngọc Duy
2014-02-03 4:29 ` [PATCH v3 25/26] file-watcher: tests for the client side Nguyễn Thái Ngọc Duy
2014-02-03 4:29 ` [PATCH v3 26/26] Disable file-watcher with system inotify on some tests Nguyễn Thái Ngọc Duy
2014-02-08 8:04 ` [PATCH v3 00/26] inotify support Torsten Bögershausen
2014-02-08 8:53 ` Duy Nguyen
2014-02-09 20:19 ` Torsten Bögershausen
2014-02-10 10:37 ` Duy Nguyen
2014-02-10 16:55 ` Torsten Bögershausen
2014-02-10 23:34 ` Duy Nguyen
2014-02-17 12:36 ` Duy Nguyen
2014-02-19 20:35 ` [PATCH 0/6] " Shawn Pearce
2014-02-19 23:45 ` Duy Nguyen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1391401754-15347-24-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.