From 3d08ffad17357f56030dd446ab9706b943a3c3d2 Mon Sep 17 00:00:00 2001 From: Rafal Gumienny <guma44@gmail.com> Date: Thu, 22 Mar 2018 15:59:48 +0100 Subject: [PATCH] feat: Add actions to OST --- CMakeLists.txt | 1 + actions/CMakeLists.txt | 4 ++ cmake_support/OST.cmake | 46 +++++++++++++++++++++++ modules/doc/contributing.rst | 71 ++++++++++++++++++++++++++++++++++++ scripts/ost.in | 34 +++++++++++++++-- scripts/ost_config.in | 12 ------ scripts/ost_startup.py.in | 19 +++++++++- 7 files changed, 169 insertions(+), 18 deletions(-) create mode 100644 actions/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 2cf4c283a..4327ea12f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -330,6 +330,7 @@ endif() add_subdirectory(modules) add_subdirectory(scripts) add_subdirectory(tools) +add_subdirectory(actions) # deployment has to come last, to ensure that all install commands are run before deployment # magic is done add_subdirectory(deployment) diff --git a/actions/CMakeLists.txt b/actions/CMakeLists.txt new file mode 100644 index 000000000..bda606e42 --- /dev/null +++ b/actions/CMakeLists.txt @@ -0,0 +1,4 @@ +add_custom_target(actions ALL) + +ost_action_init() +# ost_action(awesome-action actions) diff --git a/cmake_support/OST.cmake b/cmake_support/OST.cmake index 8e4e24343..4364b0c94 100644 --- a/cmake_support/OST.cmake +++ b/cmake_support/OST.cmake @@ -929,3 +929,49 @@ macro(setup_boost) set(BOOST_THREAD ${Boost_LIBRARIES}) set(Boost_LIBRARIES) endmacro() + + +#------------------------------------------------------------------------------- +# Synopsis: +# ost_action_init() +# +# Description: +# Initialise cached variables +#------------------------------------------------------------------------------- +macro(ost_action_init) + set(OST_ACTION_NAMES "" CACHE INTERNAL "" FORCE) +endmacro(ost_action_init) + +#------------------------------------------------------------------------------- +# Synopsis: +# ost_action(ACTION TARGET) +# +# Description: +# Add a script to actions. +# ACTION script to be added (needs to have permissions to be executed) +# TARGET make target to add the action to +#------------------------------------------------------------------------------- +macro(ost_action ACTION TARGET) + copy_if_different("${CMAKE_CURRENT_SOURCE_DIR}" + "${STAGE_DIR}/${LIBEXEC_PATH}" + "${ACTION}" "TARGETS" ${TARGET}) + install(FILES "${ACTION}" DESTINATION "${LIBEXEC_PATH}" + PERMISSIONS WORLD_EXECUTE GROUP_EXECUTE OWNER_EXECUTE + WORLD_READ GROUP_READ OWNER_READ) + # storing tool names for bash completion + string(REGEX REPLACE "^ost-" "" stripped_action ${ACTION}) + if(DEFINED OST_ACTION_NAMES) + if(${OST_ACTION_NAMES} MATCHES "${stripped_action}") + set(_ACTION_NAMES "${OST_ACTION_NAMES}") + else() + if("${OST_ACTION_NAMES}" STREQUAL "") + set(_ACTION_NAMES "${stripped_action}") + else() + set(_ACTION_NAMES "${OST_ACTION_NAMES} ${stripped_action}") + endif() + endif() + else() + set(_ACTION_NAMES "${stripped_action}") + endif() + set(OST_ACTION_NAMES "${_ACTION_NAMES}" CACHE INTERNAL "" FORCE) +endmacro(ost_action) \ No newline at end of file diff --git a/modules/doc/contributing.rst b/modules/doc/contributing.rst index c87c2daa0..c171b7c0d 100644 --- a/modules/doc/contributing.rst +++ b/modules/doc/contributing.rst @@ -109,3 +109,74 @@ If you got a patch from someone else and would like to use apply it to your repo .. code-block:: bash git am < changeset.diff + +Starting Your Own Action +-------------------------------------------------------------------------------- +In OST we call scripts/ programs 'actions'. They are started by a +launcher found in your staging directory at :file:`stage/bin/ost`. This little +guy helps keeping the shell environment in the right mood to carry out your +job. So usually you will start an action by + +.. code-block:: console + + $ stage/bin/ost --help + +Starting new action **do** go for a dedicated branch for action-development. +There you can produce intermediate commits while other branches stay clean in +case you have to do some work there which needs to get public. + +After preparing your repository its time to create a file for the action. That +is a bit different than for modules. Assuming we are sitting in the +repository's root: + +.. code-block:: console + + $ touch action/ost-awesome-action + $ chmod +x action/ost-awesome-action + +Two things are important here: actions are prefixed with :file:`ost-`, so they +are recognised by the :file:`ost` launcher. Secondly, action files need to be +executable, which does not propagate if you do it **after** the first call to +``make``. + +To get the new action recognised by ``make`` to be placed in +:file:`stage/libexec/openstructure`, it has to be registered with ``cmake`` in +:file:`actions/CMakeLists.txt`: + +.. code-block:: console + :linenos: + + add_custom_target(actions ALL) + + ost_action_init() + ost_action(ost-awesome-action actions) + +Just add your action with its full filename with a call to `ost_action` at +the end of the file. + +Now its time to fill your action with code. Instead of reading a lot more of +explanations, it should be easy to go by examples from the :file:`actions` +directory. There are only two really important points: + +* No shebang line (``#! /usr/bin/python``) in your action! Also no + ``#! /usr/bin/env python`` or anything like this. This may lead to funny side + effects, like calling a ``python`` interpreter from outside a virtual + environment or calling a different version. Basically it may mess up the + environment your action is running in. Actions are called by :file:`ost`, + that's enough to get everything just right. + +* The action of your action happens in the ost branch of the script. + Your action will have own function definitions, variables and all the bells + and whistles. Hiding behind ost keeps everything separated and makes + things easier when it gets to debugging. So just after + + .. code-block:: python + + import alot + + def functions_specific_to_your_action(...): + + if __name__ == "__main__": + <put together what your action should do here> + + start putting your action together. diff --git a/scripts/ost.in b/scripts/ost.in index f610b2446..aca9ea26e 100755 --- a/scripts/ost.in +++ b/scripts/ost.in @@ -28,9 +28,35 @@ else SCRIPT_NAME="$0" fi BIN_DIR=`dirname "$SCRIPT_NAME"` +OST_EXEC_DIR=$(cd $BIN_DIR/../@LIBEXEC_PATH@ && pwd) +export OST_EXEC_DIR -source "$BIN_DIR/../@LIBEXEC_PATH@/ost_config" +source "$OST_EXEC_DIR/ost_config" -$pyexec $interactive -c "execfile('$DNG_ROOT/@LIBDIR@/python@PYTHON_VERSION@/site-packages/ost/ost_startup.py')" $opts -RC=$? -exit $RC +ACTION="$1" +OST_SCRIPT="${OST_EXEC_DIR}/ost-${ACTION}" + +IFS="#" +if test -e "${OST_SCRIPT}" ; then + opts="" + for argument in "${@:2}";do + if [ -n "$opts" ]; then + opts=$opts"#""$argument" + else + opts="$argument" + fi + done + $pyexec -c "execfile('$DNG_ROOT/@LIBDIR@/python@PYTHON_VERSION@/site-packages/ost/ost_startup.py')" "${OST_SCRIPT}" $opts +else + opts="" + for argument in "$@";do + if [ -n "$opts" ]; then + opts=$opts"#""$argument" + else + opts="$argument" + fi + done + $pyexec $interactive -c "execfile('$DNG_ROOT/@LIBDIR@/python@PYTHON_VERSION@/site-packages/ost/ost_startup.py')" $opts + RC=$? + exit $RC +fi diff --git a/scripts/ost_config.in b/scripts/ost_config.in index afce131f1..cda517095 100644 --- a/scripts/ost_config.in +++ b/scripts/ost_config.in @@ -76,15 +76,6 @@ fi set -o noglob -opts="" -for argument in "$@";do - if [ -n "$opts" ]; then - opts=$opts"#""$argument" - else - opts="$argument" - fi -done - # decide whether to start interactively or not # interactive mode can be forced by setting -i as a iplt option interactive="" @@ -95,6 +86,3 @@ else interactive="-i" fi fi - - -IFS="#" diff --git a/scripts/ost_startup.py.in b/scripts/ost_startup.py.in index 612b6485c..d3cac43d8 100644 --- a/scripts/ost_startup.py.in +++ b/scripts/ost_startup.py.in @@ -1,4 +1,4 @@ -import sys, os, platform +import sys, os, platform, glob import optparse def show_help(option, opt, value, parser): @@ -11,7 +11,22 @@ def interactive_flag(option, opt, value, parser): def stop(): sys.exit(0) -usage = 'usage: ost [ost options] [script to execute] [script parameters]' +usage = """ + + ost [ost options] [script to execute] [script parameters] + +or + ost [action name] [action options] + +""" + +action_path = os.path.abspath(os.environ.get("OST_EXEC_DIR", "")) + +usage += 'Following actions are available:\n' +for action in sorted(glob.glob(os.path.join(action_path, 'ost-*'))): + usage += " %s\n" % action[len(action_path)+5:] +usage += '\nEach action should respond to "--help".\n' + class OstOptionParser(optparse.OptionParser): def __init__(self, **kwargs): optparse.OptionParser.__init__(self, **kwargs) -- GitLab