startup.mojo (5771B)
1 from std.collections import List 2 from std.sys import argv 3 4 from hyf_runtime.env import ( 5 configured_paths_profile_from_env, 6 configured_repo_local_root_from_env, 7 configured_user_home_from_env, 8 ) 9 from hyf_runtime.config import HyfLoadedRuntimeConfig, load_runtime_config 10 from hyf_runtime.errors import raise_runtime_contract_error 11 from hyf_runtime.paths import RuntimePaths, hyf_runtime_paths_for_unix_profile 12 from hyf_runtime.profile import repo_local_profile 13 14 15 @fieldwise_init 16 struct RuntimeStartupContext(Copyable, Movable): 17 var paths_profile: String 18 var repo_local_base_root: String 19 var user_home: String 20 var startup_config_path: String 21 var startup_config_path_source: String 22 var config: HyfLoadedRuntimeConfig 23 var paths: RuntimePaths 24 25 26 @fieldwise_init 27 struct RuntimeStartupInput(Copyable, Movable): 28 var env_paths_profile: String 29 var env_repo_local_base_root: String 30 var user_home: String 31 var argv: List[String] 32 33 34 @fieldwise_init 35 struct _StartupOverrides(Copyable, Movable): 36 var paths_profile: String 37 var repo_local_base_root: String 38 var startup_config_path: String 39 40 41 def _require_flag_value( 42 args: List[String], value_index: Int, flag_name: String 43 ) raises -> String: 44 if value_index >= len(args): 45 raise_runtime_contract_error(flag_name + " requires a value") 46 var value = String(String(args[value_index]).strip()) 47 if value == "": 48 raise_runtime_contract_error(flag_name + " requires a non-empty value") 49 if value.startswith("-"): 50 raise_runtime_contract_error( 51 flag_name + " value must not be another flag" 52 ) 53 return value^ 54 55 56 def _parse_startup_overrides(args: List[String]) raises -> _StartupOverrides: 57 var overrides = _StartupOverrides( 58 paths_profile="", repo_local_base_root="", startup_config_path="" 59 ) 60 var index = 0 61 while index < len(args): 62 var arg = String(args[index]) 63 64 if arg == "--paths-profile": 65 overrides.paths_profile = _require_flag_value( 66 args, index + 1, "--paths-profile" 67 ) 68 index += 2 69 continue 70 71 if arg.startswith("--paths-profile="): 72 overrides.paths_profile = String( 73 arg[byte = len("--paths-profile=") :] 74 ) 75 if overrides.paths_profile == "": 76 raise_runtime_contract_error("--paths-profile requires a value") 77 index += 1 78 continue 79 80 if arg == "--repo-local-root": 81 overrides.repo_local_base_root = _require_flag_value( 82 args, index + 1, "--repo-local-root" 83 ) 84 index += 2 85 continue 86 87 if arg.startswith("--repo-local-root="): 88 overrides.repo_local_base_root = String( 89 arg[byte = len("--repo-local-root=") :] 90 ) 91 if overrides.repo_local_base_root == "": 92 raise_runtime_contract_error( 93 "--repo-local-root requires a value" 94 ) 95 index += 1 96 continue 97 98 if arg == "--config": 99 overrides.startup_config_path = _require_flag_value( 100 args, index + 1, "--config" 101 ) 102 index += 2 103 continue 104 105 if arg.startswith("--config="): 106 overrides.startup_config_path = String( 107 arg[byte = len("--config=") :] 108 ) 109 if overrides.startup_config_path == "": 110 raise_runtime_contract_error("--config requires a value") 111 index += 1 112 continue 113 114 raise_runtime_contract_error("unknown startup argument '" + arg + "'") 115 116 return overrides^ 117 118 119 def resolve_startup_context( 120 input: RuntimeStartupInput, 121 ) raises -> RuntimeStartupContext: 122 var profile = String(input.env_paths_profile) 123 if profile == "": 124 raise_runtime_contract_error("env paths profile must not be empty") 125 126 var repo_local_base_root = String(input.env_repo_local_base_root) 127 var overrides = _parse_startup_overrides(input.argv) 128 if overrides.paths_profile != "": 129 profile = String(overrides.paths_profile) 130 if overrides.repo_local_base_root != "": 131 repo_local_base_root = String(overrides.repo_local_base_root) 132 133 var paths = hyf_runtime_paths_for_unix_profile( 134 profile, input.user_home, repo_local_base_root 135 ) 136 var startup_config_path = String(paths.config_path) 137 var startup_config_path_source = String("canonical_runtime_path") 138 if overrides.startup_config_path != "": 139 startup_config_path = String(overrides.startup_config_path) 140 startup_config_path_source = String("startup_flag") 141 if profile != repo_local_profile(): 142 repo_local_base_root = String("") 143 var config = load_runtime_config(startup_config_path) 144 145 return RuntimeStartupContext( 146 paths_profile=profile, 147 repo_local_base_root=repo_local_base_root, 148 user_home=String(input.user_home), 149 startup_config_path=startup_config_path, 150 startup_config_path_source=startup_config_path_source, 151 config=config^, 152 paths=paths^, 153 ) 154 155 156 def process_startup_args() -> List[String]: 157 var raw_args = argv() 158 var args = List[String]() 159 for index in range(1, len(raw_args)): 160 args.append(String(raw_args[index])) 161 return args^ 162 163 164 def resolve_startup_context_from_process() raises -> RuntimeStartupContext: 165 return resolve_startup_context( 166 RuntimeStartupInput( 167 env_paths_profile=configured_paths_profile_from_env(), 168 env_repo_local_base_root=configured_repo_local_root_from_env(), 169 user_home=configured_user_home_from_env(), 170 argv=process_startup_args(), 171 ) 172 )