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
List information: http://vger.kernel.org/majordomo-info.html
* 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.
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).