setup now creates a shell with the new environment
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Mon, 5 Oct 2026 09:29:42 +0000 (09:29 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Mon, 5 Oct 2026 09:29:42 +0000 (09:29 +0000)
setup [changed mode: 0644->0755]
setup_old_sourced [new file with mode: 0644]

diff --git a/setup b/setup
old mode 100644 (file)
new mode 100755 (executable)
index a249e2e..f750f1d
--- a/setup
+++ b/setup
@@ -1,63 +1,70 @@
-#!/usr/bin/env bash
+#!/usr/bin/env python3
 # setup - enter a project role environment
-# (must be sourced)
-
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-if [ "${BASH_SOURCE[0]}" == "${0}" ]; then
-  echo "${script_afp}:: This script must be sourced, not executed."
-  exit 1
-fi
-
-project_roles="administrator consumer developer tester"
-
-print_usage(){
-  echo "usage: . setup <role>"
-  echo "known roles: ${project_roles}"
-}
-
-if [ -z "${1:-}" ] || [ "${1}" == "-h" ] || [ "${1}" == "--help" ]; then
-  print_usage
-  return 0
-fi
-
-role_is_valid=false
-for r in ${project_roles}; do
-  if [ "${1}" == "${r}" ]; then
-    role_is_valid=true
-    break
-  fi
-done
-
-if [ "${role_is_valid}" == "false" ]; then
-  echo "setup: unrecognized role or option '${1}'"
-  print_usage
-  return 1
-fi
-
-# setup the project
-#
-  source shared/tool/setup
-  if [[ -f "shared/authored/setup" ]]; then
-    source shared/authored/setup
-  fi
-
-# setup the role
-#
-  export ROLE="${1}"
-  export ROLE_HOME="$REPO_HOME/$ROLE"
-  echo ROLE_HOME "$ROLE_HOME"
-
-  tool="${ROLE_HOME}/tool"
-  if [[ ":${PATH}:" != *":${tool}:"* ]]; then
-    export PATH="${tool}:${PATH}"
-  fi
-
-  export SETUP="${ROLE}/tool/setup"
-
-  cd "${ROLE}" || return 1
-  if [ -f "tool/setup" ]; then
-    source "tool/setup"
-    echo "in environment: ${SETUP}"
-  else
-    echo "not found: ${SETUP}"
-  fi
+
+import os
+import sys
+import argparse
+import tempfile
+
+PROJECT_ROLES = ["administrator", "consumer", "developer", "tester"]
+
+def main():
+    parser = argparse.ArgumentParser(
+        description="Enter a project role environment by spawning an isolated subshell."
+    )
+    parser.add_argument("role", choices=PROJECT_ROLES, help="The project role to assume.")
+    args = parser.parse_args()
+
+    env = os.environ.copy()
+
+    # Python-domain logic: Variables and Paths
+    repo_home = env.get("REPO_HOME", os.getcwd())
+    role = args.role
+    role_home = os.path.join(repo_home, role)
+    tool_dir = os.path.join(role_home, "tool")
+    setup_file = os.path.join(role, "tool", "setup")
+
+    env["ROLE"] = role
+    env["ROLE_HOME"] = role_home
+    env["SETUP"] = setup_file
+
+    print(f"ROLE_HOME {role_home}")
+
+    # Python-domain logic: PATH injection
+    path_parts = env.get("PATH", "").split(os.pathsep)
+    if tool_dir not in path_parts:
+        env["PATH"] = f"{tool_dir}{os.pathsep}{env.get('PATH', '')}"
+
+    # Python-domain logic: Directory validation
+    if not os.path.isdir(role):
+        print(f"setup: failed to locate directory for role '{role}'")
+        sys.exit(1)
+
+    # Bash-domain logic: The rcfile only handles operations Python cannot inherit 
+    # (sourcing bash functions) and performs the directory change internally to 
+    # guarantee the shared scripts are sourced from the project root.
+    bash_logic = [
+        'if [[ -f ~/.bashrc ]]; then source ~/.bashrc; fi',
+        'if [[ -f "shared/tool/setup" ]]; then source "shared/tool/setup"; fi',
+        'if [[ -f "shared/authored/setup" ]]; then source "shared/authored/setup"; fi',
+        f'cd "{role}"',
+        'if [[ -f "tool/setup" ]]; then',
+        '    source "tool/setup"',
+        f'    echo "in environment: {setup_file}"',
+        'else',
+        f'    echo "not found: {setup_file}"',
+        'fi',
+        'if [[ -n "${INSIDE_EMACS}" ]] && command -v env_to_emacs >/dev/null 2>&1; then',
+        '    env_to_emacs',
+        'fi',
+        'rm -f "${BASH_SOURCE[0]}"'
+    ]
+
+    fd, rcfile_path = tempfile.mkstemp(suffix="-rt-setup.sh")
+    with os.fdopen(fd, "w") as f:
+        f.write("\n".join(bash_logic) + "\n")
+
+    os.execvpe("bash", ["bash", "--rcfile", rcfile_path], env)
+
+if __name__ == "__main__":
+    main()
diff --git a/setup_old_sourced b/setup_old_sourced
new file mode 100644 (file)
index 0000000..a249e2e
--- /dev/null
@@ -0,0 +1,63 @@
+#!/usr/bin/env bash
+# setup - enter a project role environment
+# (must be sourced)
+
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+if [ "${BASH_SOURCE[0]}" == "${0}" ]; then
+  echo "${script_afp}:: This script must be sourced, not executed."
+  exit 1
+fi
+
+project_roles="administrator consumer developer tester"
+
+print_usage(){
+  echo "usage: . setup <role>"
+  echo "known roles: ${project_roles}"
+}
+
+if [ -z "${1:-}" ] || [ "${1}" == "-h" ] || [ "${1}" == "--help" ]; then
+  print_usage
+  return 0
+fi
+
+role_is_valid=false
+for r in ${project_roles}; do
+  if [ "${1}" == "${r}" ]; then
+    role_is_valid=true
+    break
+  fi
+done
+
+if [ "${role_is_valid}" == "false" ]; then
+  echo "setup: unrecognized role or option '${1}'"
+  print_usage
+  return 1
+fi
+
+# setup the project
+#
+  source shared/tool/setup
+  if [[ -f "shared/authored/setup" ]]; then
+    source shared/authored/setup
+  fi
+
+# setup the role
+#
+  export ROLE="${1}"
+  export ROLE_HOME="$REPO_HOME/$ROLE"
+  echo ROLE_HOME "$ROLE_HOME"
+
+  tool="${ROLE_HOME}/tool"
+  if [[ ":${PATH}:" != *":${tool}:"* ]]; then
+    export PATH="${tool}:${PATH}"
+  fi
+
+  export SETUP="${ROLE}/tool/setup"
+
+  cd "${ROLE}" || return 1
+  if [ -f "tool/setup" ]; then
+    source "tool/setup"
+    echo "in environment: ${SETUP}"
+  else
+    echo "not found: ${SETUP}"
+  fi