The branch, hooks has been updated
       via  0ef7ad4d824b1dd039ac10a2513deda7d9356c85 (commit)
      from  91b245e42e4393193f13566bb09d8bcb31f1005b (commit)

- Log -----------------------------------------------------------------
commit 0ef7ad4d824b1dd039ac10a2513deda7d9356c85
Author: Thomas Adam <tho...@xteddy.org>
Commit: Thomas Adam <tho...@xteddy.org>

    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
tmux-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-cvs

Reply via email to