From 84aaf451f7f3ed2aabf62616331b65ff7cb5cf96 Mon Sep 17 00:00:00 2001 From: Adrian Malacoda Date: Sun, 10 Jan 2021 01:21:38 -0600 Subject: [PATCH] Add ability to load config files, which are processed before command line arguments. --- README.md | 3 +++ otherworld | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/README.md b/README.md index 62e5bba..612bf6f 100644 --- a/README.md +++ b/README.md @@ -58,5 +58,8 @@ Image to create the container with (default: `debian:stable`) ### OW_CONTAINER Name to assign to container (default: `otherworld_$USER`) +## Config Files +Otherworld will look for config files named `.otherworld` in the current directory and all ancestor directories. Config files are Python scripts that can access and redefine the following variables: `command`, `user`, `uid`, `command_user`, `image_name`, `container_name`, `build_path`, `command_workdir`, `user_volumes`, `pull`, `command_env`. Config files are loaded in descending order (e.g. so `~/.otherworld` is loaded before `~/Projects/.otherworld`) and before command line arguments are processed. Additional variables available are `cwd` (the current directory), `config_file` (path to current configuration file) and `config_file_dir` (parent directory of config file) + ## License [GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.en.html) or later diff --git a/otherworld b/otherworld index 8b2782b..5c2465b 100755 --- a/otherworld +++ b/otherworld @@ -10,6 +10,8 @@ CONTAINER_NAME = "otherworld" DEFAULT_IMAGE_NAME = "debian:stable" OTHERWORLD_LABEL = "otherworldowner" +OTHERWORLD_CONFIG = ".otherworld" + def create_x11_mapping (): home = os.environ["HOME"] xdg_dir = os.environ["XDG_RUNTIME_DIR"] @@ -129,6 +131,32 @@ def expand_user_volumes (volumes): return mappings +def find_config_files (config_name): + config_files = [] + directory = os.path.abspath(os.getcwd()) + while True: + config_file = os.path.join(directory, config_name) + if os.path.exists(config_file): + config_files.append(config_file) + + if directory == "/" or (not directory): + break + + directory = os.path.dirname(directory) + config_files.reverse() + return config_files + +def load_config_files (namespace, config_files): + config_keys = list(namespace.keys()) + for config_file in config_files: + with open(config_file) as config_code: + namespace.update({ + "config_file": config_file, + "config_file_dir": os.path.dirname(config_file) + }) + exec(config_code.read(), {}, namespace) + return dict([item for item in namespace.items() if item[0] in config_keys]) + user = os.environ["USER"] uid = int(check_output(["id", "-u"]).strip()) image_name = os.environ.get("OW_IMAGE", None) @@ -146,6 +174,24 @@ command_env = {} command_workdir = None quiet = False + +# load config from files +config = load_config_files({ + "command": command, + "user": user, + "uid": uid, + "command_user": command_user, + "image_name": image_name, + "container_name": container_name, + "build_path": build_path, + "command_workdir": command_workdir, + "user_volumes": user_volumes, + "pull": pull, + "command_env": command_env, + "cwd": os.getcwd() +}, find_config_files(OTHERWORLD_CONFIG)) +locals().update(config) + while len(command) > 0: arg = command[0] if arg == "--quiet":