The branch, hooks has been updated
via 0ef7ad4d824b1dd039ac10a2513deda7d9356c85 (commit)
from 91b245e42e4393193f13566bb09d8bcb31f1005b (commit)
- Log -----------------------------------------------------------------
commit 0ef7ad4d824b1dd039ac10a2513deda7d9356c85
Author: Thomas Adam <[email protected]>
Commit: Thomas Adam <[email protected]>
Make hooked commands use cmdq_continue()
Certain commands (such as if-shell and run-shell) return CMD_RETURN_WAIT,
which is designed to block tmux until they complete. Rather than
side-lining the logic in cmdq_continue(), make all hooked commands go
through cmdq_continue() to benefit from its logic.
This change therefore uses up to three cmdqs; one for the before hooks, the
hooked command itself, and the after hooks. When a command is found to have
before hooks, the cmdq is swapped out, and the hooked
command added to the emptyfn() callback so that it can continue processing
where it left off. After hooks just run once the hooked command has
completed.
---
cmd-queue.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++----------
hooks.c | 19 +++++++----------
tmux.h | 8 +++++-
3 files changed, 66 insertions(+), 24 deletions(-)
diff --git a/cmd-queue.c b/cmd-queue.c
index d364ba8..8d4f50f 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -25,9 +25,11 @@
#include "tmux.h"
-void cmdq_run_hook(struct hooks *, const char *, struct cmd *,
+int cmdq_run_hook(struct hooks *, const char *, struct cmd *,
struct cmd_q *);
+int running_hooks = 0;
+
/* Create new command queue. */
struct cmd_q *
cmdq_new(struct client *c)
@@ -150,17 +152,33 @@ cmdq_run(struct cmd_q *cmdq, struct cmd_list *cmdlist)
}
/* Run hooks based on the hooks prefix (before/after). */
-void
+int
cmdq_run_hook(struct hooks *hooks, const char *prefix, struct cmd *cmd,
struct cmd_q *cmdq)
{
struct hook *hook;
+ struct cmd_q *hooks_cmdq;
char *s;
+ int retval;
xasprintf(&s, "%s-%s", prefix, cmd->entry->name);
- if ((hook = hooks_find(hooks, s)) != NULL)
- hooks_run(hook, cmdq);
+ if ((hook = hooks_find(hooks, s)) == NULL) {
+ cmdq->hooks_ran = 0;
+ retval = 0;
+ goto done;
+ }
+
+ hooks_cmdq = cmdq_new(cmdq->client);
+ hooks_cmdq->orig_cmdq = cmdq;
+ hooks_cmdq->emptyfn = hooks_emptyfn;
+ hooks_cmdq->hooks_ran = 1;
+ cmdq->references++;
+ cmdq_run(hooks_cmdq, hook->cmdlist);
+ retval = 1;
+
+done:
free(s);
+ return (retval);
}
/* Add command list to queue. */
@@ -192,11 +210,17 @@ cmdq_continue(struct cmd_q *cmdq)
if (empty)
goto empty;
- if (cmdq->item == NULL) {
- cmdq->item = TAILQ_FIRST(&cmdq->queue);
- cmdq->cmd = TAILQ_FIRST(&cmdq->item->cmdlist->list);
- } else
- cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
+ /* If the command isn't in the middle of running hooks (due to
+ * CMD_RETURN_WAIT), move onto the next command; otherwise, leave the
+ * state of the queue as is; we're already in the correct place.
+ */
+ if (cmdq->during == 0) {
+ if (cmdq->item == NULL) {
+ cmdq->item = TAILQ_FIRST(&cmdq->queue);
+ cmdq->cmd = TAILQ_FIRST(&cmdq->item->cmdlist->list);
+ } else
+ cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
+ }
do {
while (cmdq->cmd != NULL) {
@@ -210,6 +234,14 @@ cmdq_continue(struct cmd_q *cmdq)
cmdq->number++;
flags = !!(cmd->flags & CMD_CONTROL);
+
+ /*
+ * If we've come here because of running hooks, just
+ * run the command.
+ */
+ if (cmdq->during == 1)
+ goto runme;
+
guard = cmdq_guard(cmdq, "begin", flags);
if (cmd_prepare_state(cmd, cmdq) != 0) {
@@ -224,13 +256,21 @@ cmdq_continue(struct cmd_q *cmdq)
hooks = &cmdq->state.sflag.s->hooks;
else
hooks = &global_hooks;
- cmdq_run_hook(hooks, "before", cmd, cmdq);
+
+ if (cmdq->hooks_ran == 0) {
+ if (cmdq_run_hook(hooks, "before", cmd,
+ cmdq) == 1) {
+ cmdq->during = 1;
+ goto out;
+ }
+ }
/*
* hooks_run will change the state before each hook, so
* it needs to be restored afterwards. XXX not very
* obvious how this works from here...
*/
+runme:
if (cmd_prepare_state(cmd, cmdq) != 0)
retval = CMD_RETURN_ERROR;
else
@@ -240,7 +280,8 @@ cmdq_continue(struct cmd_q *cmdq)
cmdq_guard(cmdq, "error", flags);
break;
}
- cmdq_run_hook(hooks, "after", cmd, cmdq);
+ if (cmdq_run_hook(hooks, "after", cmd, cmdq) == 1)
+ goto out;
if (guard)
cmdq_guard(cmdq, "end", flags);
diff --git a/hooks.c b/hooks.c
index d485ae0..80e1c89 100644
--- a/hooks.c
+++ b/hooks.c
@@ -61,7 +61,6 @@ hooks_add(struct hooks *hooks, const char *name, struct
cmd_list *cmdlist)
hook->name = xstrdup(name);
hook->cmdlist = cmdlist;
hook->cmdlist->references++;
-
RB_INSERT(hooks_tree, &hooks->tree, hook);
}
@@ -100,19 +99,17 @@ hooks_find(struct hooks *hooks, const char *name)
}
void
-hooks_run(struct hook *hook, struct cmd_q *cmdq)
+hooks_emptyfn(struct cmd_q *cmdq1)
{
- struct cmd *cmd;
- char tmp[BUFSIZ];
+ struct cmd_q *cmdq = cmdq1->orig_cmdq;
- cmd_list_print(hook->cmdlist, tmp, sizeof tmp);
- log_debug("entering hook %s: %s", hook->name, tmp);
+ if (cmdq1->client_exit >= 0)
+ cmdq->client_exit = cmdq1->client_exit;
- TAILQ_FOREACH(cmd, &hook->cmdlist->list, qentry) {
- /* TA: FIXME: How do we handle errors here, if at all??? */
- if (cmd_prepare_state(cmd, cmdq) == 0)
- cmd->entry->exec(cmd, cmdq);
+ if (!cmdq_free(cmdq)) {
+ cmdq->hooks_ran = 1;
+ cmdq_continue(cmdq);
}
- log_debug("exiting hook %s", hook->name);
+ cmdq_free(cmdq1);
}
diff --git a/tmux.h b/tmux.h
index af82efc..387fe3f 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1030,6 +1030,7 @@ RB_HEAD(environ, environ_entry);
/* Hooks. */
struct hook {
const char *name;
+ struct cmd_q *cmdq;
struct cmd_list *cmdlist;
RB_ENTRY(hook) entry;
};
@@ -1433,6 +1434,9 @@ struct cmd_q {
void *data;
TAILQ_ENTRY(cmd_q) waitentry;
+ struct cmd_q *orig_cmdq;
+ int hooks_ran;
+ int during;
};
/* Command definition. */
@@ -1535,6 +1539,7 @@ extern time_t start_time;
extern char socket_path[PATH_MAX];
extern int login_shell;
extern char *environ_path;
+extern int running_hooks;
void logfile(const char *);
const char *getshell(void);
int checkshell(const char *);
@@ -1579,9 +1584,8 @@ void hooks_free(struct hooks *);
void hooks_add(struct hooks *, const char *, struct cmd_list *);
void hooks_copy(struct hooks *, struct hooks *);
void hooks_remove(struct hooks *, struct hook *);
-void hooks_run(struct hook *, struct cmd_q *);
struct hook *hooks_find(struct hooks *, const char *);
-
+void hooks_emptyfn(struct cmd_q *cmdq);
/* mode-key.c */
extern const struct mode_key_table mode_key_tables[];
extern struct mode_key_tree mode_key_tree_vi_edit;
-----------------------------------------------------------------------
Summary of changes:
cmd-queue.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++----------
hooks.c | 19 +++++++----------
tmux.h | 8 +++++-
3 files changed, 66 insertions(+), 24 deletions(-)
hooks/post-receive
--
tmux
------------------------------------------------------------------------------
Dive into the World of Parallel Programming. The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net/
_______________________________________________
tmux-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tmux-cvs