- commit
- 7a0d3fbe59a245b0ec17a6101aa70ec542f9c12a
- parent
- f5be3d47dc7f82732fe345c68ad16e3a936c9984
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2024-06-16 21:06
improve expandvars - support xdg-base-dirs - resolve variables in correct context
Diffstat
| M | rules/base | 1 | + |
| M | rules/gui | 13 | +++++++------ |
| M | xiwrap.py | 68 | ++++++++++++++++++++++++++++++++++++++++++++----------------- |
3 files changed, 57 insertions, 25 deletions
diff --git a/rules/base b/rules/base
@@ -2,6 +2,7 @@ import env-lang 2 2 setenv TERM 3 3 setenv USER 4 4 setenv HOME -1 5 setenv XDG_RUNTIME_DIR 5 6 6 7 tmpfs /tmp 7 8 dev /dev
diff --git a/rules/gui b/rules/gui
@@ -1,5 +1,6 @@1 -1 setenv HOME2 1 setenv XDG_RUNTIME_DIR -1 2 setenv XDG_DATA_HOME -1 3 setenv XDG_CACHE_HOME 3 4 4 5 setenv DISPLAY 5 6 setenv WAYLAND_DISPLAY @@ -10,11 +11,11 @@ ro-bind-try /etc/fonts 10 11 ro-bind-try /usr/share/fonts 11 12 ro-bind-try /usr/share/icons 12 13 ro-bind-try /usr/share/themes/13 -1 ro-bind-try $HOME/.local/share/fonts14 -1 ro-bind-try $HOME/.local/share/icons15 -1 ro-bind-try $HOME/.local/share/themes16 -1 bind-try $HOME/.cache/fontconfig17 -1 bind-try $HOME/.cache/thumbnails-1 14 ro-bind-try $XDG_DATA_HOME/fonts -1 15 ro-bind-try $XDG_DATA_HOME/icons -1 16 ro-bind-try $XDG_DATA_HOME/themes -1 17 bind-try $XDG_CACHE_HOME/fontconfig -1 18 bind-try $XDG_CACHE_HOME/thumbnails 18 19 19 20 dbus-talk org.a11y.Bus 20 21
diff --git a/xiwrap.py b/xiwrap.py
@@ -1,17 +1,8 @@ 1 1 import os 2 2 import subprocess 3 3 import sys4 -1 from os.path import expandvars5 4 from pathlib import Path 6 57 -1 XDG_RUNTIME_DIR = Path(os.getenv('XDG_RUNTIME_DIR'))8 -1 XDG_CONFIG_HOME = Path(os.getenv('XDG_CONFIG_HOME', '~/.config')).expanduser()9 -110 -1 USER_CONFIG = XDG_CONFIG_HOME / 'xiwrap'11 -1 SYSTEM_CONFIG = Path('/etc') / 'xiwrap'12 -113 -1 DBUS_PROXY_PATH = XDG_RUNTIME_DIR / f'dbus-proxy-{os.getpid()}'14 -115 6 USAGE = """Usage: xiwrap [OPTION]... -- CMD 16 7 17 8 Example: xiwrap --import host-os --setenv TERM -- bash @@ -48,6 +39,9 @@ The following options are available: 48 39 Empty lines or lines starting with # are ignored. 49 40 """ 50 41 -1 42 DBUS_SRC = f'{os.environ["XDG_RUNTIME_DIR"]}/dbus-proxy-{os.getpid()}' -1 43 DBUS_DEST = '$XDG_RUNTIME_DIR/bus' -1 44 51 45 52 46 class RuleError(ValueError): 53 47 def __init__(self, key, args): @@ -55,6 +49,38 @@ class RuleError(ValueError): 55 49 super().__init__(f'Invalid rule: {rule}') 56 50 57 51 -1 52 def expandvars(path, env): -1 53 # https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html -1 54 -1 55 if not path.startswith('$'): -1 56 return path -1 57 -1 58 for var, default in [ -1 59 ('HOME', None), -1 60 ('XDG_DATA_HOME', '.local/share'), -1 61 ('XDG_CONFIG_HOME', '.config'), -1 62 ('XDG_STATE_HOME', '.local/state'), -1 63 ('XDG_CACHE_HOME', '.cache'), -1 64 ('XDG_RUNTIME_DIR', None), -1 65 ]: -1 66 if path.startswith(f'${var}'): -1 67 if env.get(var): -1 68 head = Path(env.get(var)) -1 69 elif default is not None: -1 70 head = Path(env.get('HOME')) / default -1 71 else: -1 72 raise ValueError( -1 73 f'Invalid path {path}: {var} is not defined in this context.' -1 74 ) -1 75 if '/' in path: -1 76 tail = path.removeprefix(f'${var}/') -1 77 return str(head / tail) -1 78 else: -1 79 return str(head) -1 80 -1 81 raise ValueError(path) -1 82 -1 83 58 84 class RuleSet: 59 85 def __init__(self): 60 86 self.env = {} @@ -64,13 +90,15 @@ class RuleSet: 64 90 self.sync_fds = None 65 91 self.debug = False 66 92 self.usage = False -1 93 self.userconfig = Path(expandvars('$XDG_CONFIG_HOME/xiwrap', os.environ)) -1 94 self.sysconfig = Path('/etc/xiwrap') 67 95 68 96 def find_config_file(self, name, cwd): 69 97 if name.startswith('/'): 70 98 return Path(name) 71 99 elif name.startswith('~'): 72 100 return Path(name).expanduser()73 -1 for base in [cwd, USER_CONFIG, SYSTEM_CONFIG]:-1 101 for base in [cwd, self.userconfig, self.sysconfig]: 74 102 path = base / name 75 103 if path.exists(): 76 104 return path @@ -96,9 +124,7 @@ class RuleSet: 96 124 if self.sync_fds is not None: 97 125 return 98 126 self.sync_fds = os.pipe2(0)99 -1 bus = str(XDG_RUNTIME_DIR / 'bus')100 -1 self.paths[bus] = ('ro-bind', str(DBUS_PROXY_PATH))101 -1 self.env['DBUS_SESSION_BUS_ADDRESS'] = f'unix:path={bus}'-1 127 self.push_rule('ro-bind', [DBUS_SRC, DBUS_DEST], cwd=None) 102 128 103 129 def push_rule(self, key, args, *, cwd): 104 130 if key == 'import': @@ -129,11 +155,11 @@ class RuleSet: 129 155 'ro-bind-try', 130 156 ]: 131 157 src, target = self.parse_path(key, args)132 -1 self.paths[expandvars(target)] = (key, expandvars(src))-1 158 self.paths[target] = (key, src) 133 159 elif key in ['tmpfs', 'dev', 'proc', 'mqueue', 'dir']: 134 160 if len(args) != 1: 135 161 raise RuleError(key, args)136 -1 self.paths[expandvars(args[0])] = (key, None)-1 162 self.paths[args[0]] = (key, None) 137 163 else: 138 164 raise RuleError(key, args) 139 165 @@ -178,18 +204,22 @@ class RuleSet: 178 204 ] 179 205 if self.sync_fds is not None: 180 206 cmd += ['--sync-fd', str(self.sync_fds[0])] -1 207 bus = expandvars(DBUS_DEST, self.env) -1 208 cmd += ['--setenv', 'DBUS_SESSION_BUS_ADDRESS', f'unix:path={bus}'] 181 209 for key in ['share-ipc', 'share-pid', 'share-net']: 182 210 if not self.share.get(key): 183 211 cmd.append(f'--un{key}') 184 212 for key, value in self.env.items(): 185 213 if value is not None: 186 214 cmd += ['--setenv', key, value]187 -1 for target, value in sorted(self.paths.items()):188 -1 typ, src = value-1 215 for target, typ, src in sorted( -1 216 (expandvars(target, self.env), *value) -1 217 for target, value in self.paths.items() -1 218 ): 189 219 if src is None: 190 220 cmd += [f'--{typ}', target] 191 221 else:192 -1 cmd += [f'--{typ}', src, target]-1 222 cmd += [f'--{typ}', expandvars(src, os.environ), target] 193 223 return cmd + bwrap_args 194 224 195 225 def build_dbus(self): @@ -199,7 +229,7 @@ class RuleSet: 199 229 'xdg-dbus-proxy', 200 230 f'--fd={self.sync_fds[1]}', 201 231 os.getenv('DBUS_SESSION_BUS_ADDRESS'),202 -1 str(DBUS_PROXY_PATH),-1 232 DBUS_SRC, 203 233 '--filter', 204 234 ] 205 235 for value, typ in sorted(self.dbus.items()):