netstar pushed a commit to branch master. http://git.enlightenment.org/tools/edi.git/commit/?id=7e9f33a635bfe560196de42eed4d42b502678521
commit 7e9f33a635bfe560196de42eed4d42b502678521 Author: Al Poole <[email protected]> Date: Tue Sep 5 15:58:00 2017 +0100 exe: Add methods to handle async shell execution and acting on exit status. This adds two methods for handling executing shells async. The notification has been reworked to use this method so there is less blocking. A callback can be passed to the handler method for various actions on the exit status of the script execution. --- src/bin/edi_main.c | 11 ++++-- src/lib/edi_build_provider.h | 2 +- src/lib/edi_build_provider_cargo.c | 6 +-- src/lib/edi_build_provider_cmake.c | 4 +- src/lib/edi_build_provider_make.c | 22 +++++------ src/lib/edi_build_provider_meson.c | 10 ++--- src/lib/edi_build_provider_python.c | 6 +-- src/lib/edi_builder.c | 6 +-- src/lib/edi_builder.h | 4 +- src/lib/edi_exe.c | 73 +++++++++++++++++++++++++++++++++++++ src/lib/edi_exe.h | 21 +++++++++++ 11 files changed, 128 insertions(+), 37 deletions(-) diff --git a/src/bin/edi_main.c b/src/bin/edi_main.c index c5b0d8b..a2dbab0 100644 --- a/src/bin/edi_main.c +++ b/src/bin/edi_main.c @@ -701,14 +701,12 @@ _edi_launcher_run(Edi_Project_Config_Launch *launch) } static void -_edi_build_project(void) +_edi_build_display_status_cb(int status) { Eina_Strbuf *message; - int status; message = eina_strbuf_new(); - status = edi_builder_build(); if (status != 0) eina_strbuf_append_printf(message, "Build of project <b>%s</b> in %s failed with status code %d.", edi_project_name_get(), edi_project_get(), status); else @@ -720,6 +718,13 @@ _edi_build_project(void) } static void +_edi_build_project(void) +{ + if (edi_exe_notify_handle("edi_build", _edi_build_display_status_cb)) + edi_builder_build(); +} + +static void _tb_build_cb(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) { if (_edi_build_prep(obj)) diff --git a/src/lib/edi_build_provider.h b/src/lib/edi_build_provider.h index 4fb19eb..6e68869 100644 --- a/src/lib/edi_build_provider.h +++ b/src/lib/edi_build_provider.h @@ -18,7 +18,7 @@ typedef struct _Edi_Build_Provider Eina_Bool (*file_hidden_is)(const char *path); Eina_Bool (*project_runnable_is)(const char *path); - int (*build)(void); + void (*build)(void); void (*test)(void); void (*run)(const char *path, const char *args); void (*clean)(void); diff --git a/src/lib/edi_build_provider_cargo.c b/src/lib/edi_build_provider_cargo.c index a2d22b0..3394510 100644 --- a/src/lib/edi_build_provider_cargo.c +++ b/src/lib/edi_build_provider_cargo.c @@ -56,13 +56,11 @@ _cargo_project_runnable_is(const char *file EINA_UNUSED) return EINA_TRUE; } -static int +static void _cargo_build(void) { if (chdir(edi_project_get()) == 0) - return edi_exe_wait("cargo build"); - - return -1; + edi_exe_notify("edi_build", "cargo build"); } static void diff --git a/src/lib/edi_build_provider_cmake.c b/src/lib/edi_build_provider_cmake.c index ea4286c..31001f5 100644 --- a/src/lib/edi_build_provider_cmake.c +++ b/src/lib/edi_build_provider_cmake.c @@ -46,13 +46,13 @@ _cmake_project_runnable_is(const char *path) return ecore_file_exists(path); } -static int +static void _cmake_build(void) { if (chdir(edi_project_get()) != 0) ERR("Could not chdir"); - return edi_exe_wait("mkdir -p build && cd build && cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 .. && make && cd .."); + edi_exe_notify("edi_build", "mkdir -p build && cd build && cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 .. && make && cd .."); } static void diff --git a/src/lib/edi_build_provider_make.c b/src/lib/edi_build_provider_make.c index 57da187..588a503 100644 --- a/src/lib/edi_build_provider_make.c +++ b/src/lib/edi_build_provider_make.c @@ -67,7 +67,7 @@ _make_comand_compound_get(const char *prepend, const char *append) return cmd; } -static int +static void _make_build_make(void) { static const char *cmd = NULL; @@ -77,10 +77,10 @@ _make_build_make(void) if (chdir(edi_project_get()) != 0) ERR("Could not chdir"); - return edi_exe_wait(cmd); + edi_exe_notify("edi_build", cmd); } -static int +static void _make_build_configure(void) { static const char *cmd = NULL; @@ -90,10 +90,10 @@ _make_build_configure(void) if (chdir(edi_project_get()) != 0) ERR("Could not chdir"); - return edi_exe_wait(cmd); + edi_exe_notify("edi_build", cmd); } -static int +static void _make_build_autogen(void) { static const char *cmd = NULL; @@ -103,20 +103,18 @@ _make_build_autogen(void) if (chdir(edi_project_get()) != 0) ERR("Could not chdir"); - return edi_exe_wait(cmd); + edi_exe_notify("edi_build", cmd); } -static int +static void _make_build(void) { if (edi_project_file_exists("Makefile") || edi_project_file_exists("makefile")) - return _make_build_make(); + _make_build_make(); else if (edi_project_file_exists("configure")) - return _make_build_configure(); + _make_build_configure(); else if (edi_project_file_exists("autogen.sh")) - return _make_build_autogen(); - - return -1; + _make_build_autogen(); } static void diff --git a/src/lib/edi_build_provider_meson.c b/src/lib/edi_build_provider_meson.c index 928b44d..9b0ddc1 100644 --- a/src/lib/edi_build_provider_meson.c +++ b/src/lib/edi_build_provider_meson.c @@ -79,14 +79,14 @@ _meson_project_runnable_is(const char *path) return ecore_file_can_exec(path); } -static int +static void _meson_ninja_do(Meson_Data *md, const char *arg) { const char *cmd; cmd = eina_slstr_printf("ninja -C %s %s", md->fulldir, arg ?: ""); - return edi_exe_wait(cmd); + edi_exe_notify("edi_build", cmd); } static Eina_Bool @@ -123,15 +123,15 @@ _meson_prepare(Meson_Data *md) return EINA_FALSE; } -static int +static void _meson_build(void) { Meson_Data *md = _meson_data_get(); if (!_meson_prepare(md)) - return -1; + return; - return _meson_ninja_do(md, NULL); + _meson_ninja_do(md, NULL); } static void diff --git a/src/lib/edi_build_provider_python.c b/src/lib/edi_build_provider_python.c index 31270d6..4dcb751 100644 --- a/src/lib/edi_build_provider_python.c +++ b/src/lib/edi_build_provider_python.c @@ -56,13 +56,11 @@ _python_project_runnable_is(const char *file EINA_UNUSED) return EINA_TRUE; } -static int +static void _python_build(void) { if (chdir(edi_project_get()) == 0) - return edi_exe_wait("./setup.py build"); - - return -1; + edi_exe_notify("edi_build", "./setup.py build"); } static void diff --git a/src/lib/edi_builder.c b/src/lib/edi_builder.c index a643d28..bb5f987 100644 --- a/src/lib/edi_builder.c +++ b/src/lib/edi_builder.c @@ -29,16 +29,16 @@ edi_builder_can_run(const char *runpath) return provider && provider->project_runnable_is(runpath); } -EAPI int +EAPI void edi_builder_build(void) { Edi_Build_Provider *provider; provider = edi_build_provider_for_project_get(); if (!provider) - return -1; + return; - return provider->build(); + provider->build(); } EAPI void diff --git a/src/lib/edi_builder.h b/src/lib/edi_builder.h index bd4930f..cab5918 100644 --- a/src/lib/edi_builder.h +++ b/src/lib/edi_builder.h @@ -48,13 +48,11 @@ edi_builder_can_run(const char *runpath); /** * Run a build for the current project. * - * @return The status code of the build process. - * * @see edi_builder_can_build(). * * @ingroup Builder */ -EAPI int +EAPI void edi_builder_build(void); /** diff --git a/src/lib/edi_exe.c b/src/lib/edi_exe.c index ed22845..a48591e 100644 --- a/src/lib/edi_exe.c +++ b/src/lib/edi_exe.c @@ -5,10 +5,83 @@ #include <sys/wait.h> #include <Ecore.h> +#include <Ecore_Con.h> #include "Edi.h" #include "edi_private.h" +static Ecore_Event_Handler *_edi_exe_handler = NULL; +static Ecore_Event_Handler *_edi_exe_notify_handler = NULL; + +static Eina_Bool +_edi_exe_notify_data_cb(void *data, int type EINA_UNUSED, void *event EINA_UNUSED) +{ + int *status; + void *(*func)(int value); + Ecore_Con_Server *srv; + Ecore_Con_Event_Client_Data *ev = event; + + status = ev->data; + func = data; + srv = ecore_con_client_server_get(ev->client); + + func(*status); + + ecore_event_handler_del(_edi_exe_notify_handler); + _edi_exe_notify_handler = NULL; + + ecore_con_client_del(ev->client); + ecore_con_server_del(srv); + + return EINA_FALSE; +} + +EAPI Eina_Bool +edi_exe_notify_handle(const char *name, void ((*func)(int))) +{ + if (_edi_exe_notify_handler) return EINA_FALSE; + + ecore_con_server_add(ECORE_CON_LOCAL_USER, name, 0, NULL); + + _edi_exe_notify_handler = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, (Ecore_Event_Handler_Cb) _edi_exe_notify_data_cb, func); + + return EINA_TRUE; +} + +static Eina_Bool +_edi_exe_event_done_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Ecore_Exe_Event_Del *ev; + Ecore_Con_Server *srv; + const char *name = data; + + ev = event; + + if (!ev->exe) return ECORE_CALLBACK_RENEW; + + srv = ecore_con_server_connect(ECORE_CON_LOCAL_USER, name, 0, NULL); + + ecore_con_server_send(srv, &ev->exit_code, sizeof(int *)); + + ecore_event_handler_del(_edi_exe_handler); + _edi_exe_handler = NULL; + + return ECORE_CALLBACK_DONE; +} + +EAPI void +edi_exe_notify(const char *name, const char *command) +{ + if (_edi_exe_handler) return; + + ecore_exe_pipe_run(command, + ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ | + ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR | + ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL); + + _edi_exe_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _edi_exe_event_done_cb, name); +} + EAPI int edi_exe_wait(const char *command) { diff --git a/src/lib/edi_exe.h b/src/lib/edi_exe.h index ab665e0..1165c8e 100644 --- a/src/lib/edi_exe.h +++ b/src/lib/edi_exe.h @@ -41,6 +41,27 @@ EAPI int edi_exe_wait(const char *command); EAPI char *edi_exe_response(const char *command); /** + * Run an executable command with notifcation enabled. + * + * @param name The name of the resource used to identify the notification. + * @param command The command to execute in a child process. + * + * @ingroup Exe + */ +EAPI void edi_exe_notify(const char *name, const char *command); + +/** + * This function is used to set a callback that will execute when an + * edi_exe_response has terminated and supplied its exit status. + * + * @param name The name of the resource used to identify the notification. + * @param func Function that will execute upon receiving exit code of exe. + * + * @ingroup Exe + */ +EAPI Eina_Bool edi_exe_notify_handle(const char *name, void ((*func)(int))); + +/** * @} */ --
