XDG library path support for OCaml via Eio capabilities
linux
macos
ocaml
xdg
1Test with default directories:
2
3 $ export HOME=./test_home
4 $ unset XDG_CONFIG_HOME XDG_DATA_HOME XDG_CACHE_HOME XDG_STATE_HOME XDG_RUNTIME_DIR
5 $ unset XDG_CONFIG_DIRS XDG_DATA_DIRS
6 $ ./xdg_example.exe
7 === Cmdliner Config ===
8 XDG config:
9
10 === XDG Directories ===
11 XDG directories for 'xdg_example':
12 User directories:
13 config: <fs:./test_home/./test_home/.config/xdg_example> [default]
14 data: <fs:./test_home/./test_home/.local/share/xdg_example> [default]
15 cache: <fs:./test_home/./test_home/.cache/xdg_example> [default]
16 state: <fs:./test_home/./test_home/.local/state/xdg_example> [default]
17 runtime: <none> [default]
18 System directories:
19 config_dirs: [<fs:/etc/xdg/xdg_example>]
20 data_dirs: [<fs:/usr/local/share/xdg_example>; <fs:/usr/share/xdg_example>]
21
22No command-line args or env vars are set, so all directories use defaults.
23Config shows empty (no overrides), and directories show [default] source. User
24directories follow XDG spec: ~/.config, ~/.local/share, ~/.cache,
25~/.local/state. Runtime dir is <none> since XDG_RUNTIME_DIR has no default.
26System dirs use XDG spec defaults: /etc/xdg for config, /usr/{local/,}share for
27data.
28
29Test with all command line arguments specified
30 $ unset XDG_CONFIG_HOME XDG_DATA_HOME XDG_CACHE_HOME XDG_STATE_HOME XDG_RUNTIME_DIR
31 $ unset XDG_CONFIG_DIRS XDG_DATA_DIRS
32 $ ./xdg_example.exe \
33 > --config-dir ./test-config \
34 > --data-dir ./test-data \
35 > --cache-dir ./test-cache \
36 > --state-dir ./test-state \
37 > --runtime-dir ./test-runtime
38 === Cmdliner Config ===
39 XDG config:
40 config_dir: ./test-config [cmdline]
41 data_dir: ./test-data [cmdline]
42 cache_dir: ./test-cache [cmdline]
43 state_dir: ./test-state [cmdline]
44 runtime_dir: ./test-runtime [cmdline]
45
46 === XDG Directories ===
47 XDG directories for 'xdg_example':
48 User directories:
49 config: <fs:./test_home/./test-config> [cmdline]
50 data: <fs:./test_home/./test-data> [cmdline]
51 cache: <fs:./test_home/./test-cache> [cmdline]
52 state: <fs:./test_home/./test-state> [cmdline]
53 runtime: <fs:./test_home/./test-runtime> [cmdline]
54 System directories:
55 config_dirs: [<fs:/etc/xdg/xdg_example>]
56 data_dirs: [<fs:/usr/local/share/xdg_example>; <fs:/usr/share/xdg_example>]
57
58All user directories are overridden by command-line arguments, showing
59[cmdline] as the source. The config section shows all overrides with their
60values and [cmdline] sources. System directories remain at their defaults since
61they cannot be overridden by user directories command-line options.
62
63Test with environment variables (app-specific)
64 $ XDG_EXAMPLE_CONFIG_DIR=./env-config \
65 > XDG_EXAMPLE_DATA_DIR=./env-data \
66 > XDG_EXAMPLE_CACHE_DIR=./env-cache \
67 > XDG_EXAMPLE_STATE_DIR=./env-state \
68 > XDG_EXAMPLE_RUNTIME_DIR=./env-runtime \
69 > ./xdg_example.exe
70 === Cmdliner Config ===
71 XDG config:
72 config_dir: ./env-config [env(XDG_EXAMPLE_CONFIG_DIR)]
73 data_dir: ./env-data [env(XDG_EXAMPLE_DATA_DIR)]
74 cache_dir: ./env-cache [env(XDG_EXAMPLE_CACHE_DIR)]
75 state_dir: ./env-state [env(XDG_EXAMPLE_STATE_DIR)]
76 runtime_dir: ./env-runtime [env(XDG_EXAMPLE_RUNTIME_DIR)]
77
78 === XDG Directories ===
79 XDG directories for 'xdg_example':
80 User directories:
81 config: <fs:./test_home/./env-config> [env(XDG_EXAMPLE_CONFIG_DIR)]
82 data: <fs:./test_home/./env-data> [env(XDG_EXAMPLE_DATA_DIR)]
83 cache: <fs:./test_home/./env-cache> [env(XDG_EXAMPLE_CACHE_DIR)]
84 state: <fs:./test_home/./env-state> [env(XDG_EXAMPLE_STATE_DIR)]
85 runtime: <fs:./test_home/./env-runtime> [env(XDG_EXAMPLE_RUNTIME_DIR)]
86 System directories:
87 config_dirs: [<fs:/etc/xdg/xdg_example>]
88 data_dirs: [<fs:/usr/local/share/xdg_example>; <fs:/usr/share/xdg_example>]
89
90App-specific environment variables (XDG_EXAMPLE_*) override the defaults. The
91source correctly shows [env(XDG_EXAMPLE_*)] for each variable. These
92app-specific variables take precedence over XDG standard variables when both
93are available, allowing per-application customization.
94
95Test with standard XDG environment variables:
96
97 $ XDG_CONFIG_HOME=/tmp/xdge/xdg-config \
98 > XDG_DATA_HOME=/tmp/xdge/xdg-data \
99 > XDG_CACHE_HOME=/tmp/xdge/xdg-cache \
100 > XDG_STATE_HOME=/tmp/xdge/xdg-state \
101 > XDG_RUNTIME_DIR=/tmp/xdge/xdg-runtime \
102 > ./xdg_example.exe
103 === Cmdliner Config ===
104 XDG config:
105 config_dir: /tmp/xdge/xdg-config [env(XDG_CONFIG_HOME)]
106 data_dir: /tmp/xdge/xdg-data [env(XDG_DATA_HOME)]
107 cache_dir: /tmp/xdge/xdg-cache [env(XDG_CACHE_HOME)]
108 state_dir: /tmp/xdge/xdg-state [env(XDG_STATE_HOME)]
109 runtime_dir: /tmp/xdge/xdg-runtime [env(XDG_RUNTIME_DIR)]
110
111 === XDG Directories ===
112 XDG directories for 'xdg_example':
113 User directories:
114 config: <fs:/tmp/xdge/xdg-config> [env(XDG_CONFIG_HOME)]
115 data: <fs:/tmp/xdge/xdg-data> [env(XDG_DATA_HOME)]
116 cache: <fs:/tmp/xdge/xdg-cache> [env(XDG_CACHE_HOME)]
117 state: <fs:/tmp/xdge/xdg-state> [env(XDG_STATE_HOME)]
118 runtime: <fs:/tmp/xdge/xdg-runtime> [env(XDG_RUNTIME_DIR)]
119 System directories:
120 config_dirs: [<fs:/etc/xdg/xdg_example>]
121 data_dirs: [<fs:/usr/local/share/xdg_example>; <fs:/usr/share/xdg_example>]
122
123Standard XDG environment variables (XDG_*_HOME, XDG_RUNTIME_DIR) override the
124defaults. The source correctly shows [env(XDG_*)] for each variable. Note that
125the user directories use the raw paths from env vars (not app-specific subdirs)
126since XDG_CONFIG_HOME etc. are intended to be the base directories for the
127user.
128
129Test command line overrides environment variables:
130
131 $ unset XDG_CONFIG_DIRS XDG_DATA_DIRS
132 $ XDG_EXAMPLE_CONFIG_DIR=./env-config \
133 > ./xdg_example.exe --config-dir ./cli-config
134 === Cmdliner Config ===
135 XDG config:
136 config_dir: ./cli-config [cmdline]
137
138 === XDG Directories ===
139 XDG directories for 'xdg_example':
140 User directories:
141 config: <fs:./test_home/./cli-config> [cmdline]
142 data: <fs:./test_home/./test_home/.local/share/xdg_example> [default]
143 cache: <fs:./test_home/./test_home/.cache/xdg_example> [default]
144 state: <fs:./test_home/./test_home/.local/state/xdg_example> [default]
145 runtime: <none> [default]
146 System directories:
147 config_dirs: [<fs:/etc/xdg/xdg_example>]
148 data_dirs: [<fs:/usr/local/share/xdg_example>; <fs:/usr/share/xdg_example>]
149
150Command-line arguments have highest precedence, overriding environment
151variables. Only config_dir is shown in the config section since it is the only
152one explicitly set. The config_dir shows [cmdline] source while other
153directories fall back to defaults, demonstrating the precedence hierarchy: of
154cmdline then app env vars then XDG env vars then defaults.
155
156Test mixed environment variable precedence (app-specific overrides XDG
157standard):
158
159 $ export HOME=./test_home
160 $ unset XDG_CONFIG_DIRS XDG_DATA_DIRS
161 $ XDG_CONFIG_HOME=/tmp/xdge/xdg-config \
162 > XDG_EXAMPLE_CONFIG_DIR=./app-config \
163 > XDG_DATA_HOME=/tmp/xdge/xdg-data \
164 > XDG_EXAMPLE_DATA_DIR=./app-data \
165 > ./xdg_example.exe
166 === Cmdliner Config ===
167 XDG config:
168 config_dir: ./app-config [env(XDG_EXAMPLE_CONFIG_DIR)]
169 data_dir: ./app-data [env(XDG_EXAMPLE_DATA_DIR)]
170
171 === XDG Directories ===
172 XDG directories for 'xdg_example':
173 User directories:
174 config: <fs:./test_home/./app-config> [env(XDG_EXAMPLE_CONFIG_DIR)]
175 data: <fs:./test_home/./app-data> [env(XDG_EXAMPLE_DATA_DIR)]
176 cache: <fs:./test_home/./test_home/.cache/xdg_example> [default]
177 state: <fs:./test_home/./test_home/.local/state/xdg_example> [default]
178 runtime: <none> [default]
179 System directories:
180 config_dirs: [<fs:/etc/xdg/xdg_example>]
181 data_dirs: [<fs:/usr/local/share/xdg_example>; <fs:/usr/share/xdg_example>]
182
183Demonstrates app-specific environment variables taking precedence over XDG
184standard ones. Both XDG_CONFIG_HOME and XDG_EXAMPLE_CONFIG_DIR are set, but the
185app-specific one wins. Same for data directories. Cache, state, and runtime
186fall back to defaults since no variables are set for them.
187
188Test partial environment variable override:
189
190 $ export HOME=./test_home
191 $ unset XDG_CONFIG_DIRS XDG_DATA_DIRS
192 $ XDG_EXAMPLE_CONFIG_DIR=./app-config \
193 > XDG_DATA_HOME=/tmp/xdge/xdg-data \
194 > XDG_CACHE_HOME=/tmp/xdge/xdg-cache \
195 > ./xdg_example.exe
196 === Cmdliner Config ===
197 XDG config:
198 config_dir: ./app-config [env(XDG_EXAMPLE_CONFIG_DIR)]
199 data_dir: /tmp/xdge/xdg-data [env(XDG_DATA_HOME)]
200 cache_dir: /tmp/xdge/xdg-cache [env(XDG_CACHE_HOME)]
201
202 === XDG Directories ===
203 XDG directories for 'xdg_example':
204 User directories:
205 config: <fs:./test_home/./app-config> [env(XDG_EXAMPLE_CONFIG_DIR)]
206 data: <fs:/tmp/xdge/xdg-data> [env(XDG_DATA_HOME)]
207 cache: <fs:/tmp/xdge/xdg-cache> [env(XDG_CACHE_HOME)]
208 state: <fs:./test_home/./test_home/.local/state/xdg_example> [default]
209 runtime: <none> [default]
210 System directories:
211 config_dirs: [<fs:/etc/xdg/xdg_example>]
212 data_dirs: [<fs:/usr/local/share/xdg_example>; <fs:/usr/share/xdg_example>]
213
214Shows mixed sources working together. Config uses app-specific env var (highest
215priority among env vars), data and cache use XDG standard env vars (no
216app-specific ones set), and state uses default (no env vars set). Each
217directory gets its value from the highest-priority available source.
218
219Test command line overrides mixed environment variables:
220
221 $ export HOME=./test_home
222 $ unset XDG_CONFIG_DIRS XDG_DATA_DIRS
223 $ XDG_CONFIG_HOME=/tmp/xdge/xdg-config \
224 > XDG_EXAMPLE_CONFIG_DIR=./app-config \
225 > ./xdg_example.exe --config-dir ./cli-config
226 === Cmdliner Config ===
227 XDG config:
228 config_dir: ./cli-config [cmdline]
229
230 === XDG Directories ===
231 XDG directories for 'xdg_example':
232 User directories:
233 config: <fs:./test_home/./cli-config> [cmdline]
234 data: <fs:./test_home/./test_home/.local/share/xdg_example> [default]
235 cache: <fs:./test_home/./test_home/.cache/xdg_example> [default]
236 state: <fs:./test_home/./test_home/.local/state/xdg_example> [default]
237 runtime: <none> [default]
238 System directories:
239 config_dirs: [<fs:/etc/xdg/xdg_example>]
240 data_dirs: [<fs:/usr/local/share/xdg_example>; <fs:/usr/share/xdg_example>]
241
242Command-line argument overrides both types of environment variables. Even
243though both XDG_CONFIG_HOME and XDG_EXAMPLE_CONFIG_DIR are set, the
244--config-dir flag takes precedence and shows [cmdline] source. Other
245directories fall back to defaults since no other command-line args are
246provided.
247
248Test empty environment variable handling:
249 $ export HOME=./test_home
250 $ unset XDG_CONFIG_DIRS XDG_DATA_DIRS
251 $ XDG_EXAMPLE_CONFIG_DIR="" \
252 > XDG_CONFIG_HOME=/tmp/xdge/xdg-config \
253 > ./xdg_example.exe
254 === Cmdliner Config ===
255 XDG config:
256 config_dir: /tmp/xdge/xdg-config [env(XDG_CONFIG_HOME)]
257
258 === XDG Directories ===
259 XDG directories for 'xdg_example':
260 User directories:
261 config: <fs:/tmp/xdge/xdg-config> [env(XDG_CONFIG_HOME)]
262 data: <fs:./test_home/./test_home/.local/share/xdg_example> [default]
263 cache: <fs:./test_home/./test_home/.cache/xdg_example> [default]
264 state: <fs:./test_home/./test_home/.local/state/xdg_example> [default]
265 runtime: <none> [default]
266 System directories:
267 config_dirs: [<fs:/etc/xdg/xdg_example>]
268 data_dirs: [<fs:/usr/local/share/xdg_example>; <fs:/usr/share/xdg_example>]
269
270When an app-specific env var is empty (""), it falls back to the XDG standard
271variable. XDG_EXAMPLE_CONFIG_DIR="" is ignored, so XDG_CONFIG_HOME is used
272instead, correctly showing [env(XDG_CONFIG_HOME)] as the source. This behavior
273ensures that empty app-specific variables do not override useful XDG standard
274settings.
275
276Test system directory environment variables:
277
278 $ export HOME=./test_home
279 $ unset XDG_CONFIG_HOME XDG_DATA_HOME XDG_CACHE_HOME XDG_STATE_HOME XDG_RUNTIME_DIR
280 $ XDG_CONFIG_DIRS=/tmp/xdge/sys1:/tmp/xdge/sys2 \
281 > XDG_DATA_DIRS=/tmp/xdge/data1:/tmp/xdge/data2 \
282 > ./xdg_example.exe
283 === Cmdliner Config ===
284 XDG config:
285
286 === XDG Directories ===
287 XDG directories for 'xdg_example':
288 User directories:
289 config: <fs:./test_home/./test_home/.config/xdg_example> [default]
290 data: <fs:./test_home/./test_home/.local/share/xdg_example> [default]
291 cache: <fs:./test_home/./test_home/.cache/xdg_example> [default]
292 state: <fs:./test_home/./test_home/.local/state/xdg_example> [default]
293 runtime: <none> [default]
294 System directories:
295 config_dirs: [<fs:/tmp/xdge/sys1/xdg_example>;
296 <fs:/tmp/xdge/sys2/xdg_example>]
297 data_dirs: [<fs:/tmp/xdge/data1/xdg_example>;
298 <fs:/tmp/xdge/data2/xdg_example>]
299
300XDG_CONFIG_DIRS and XDG_DATA_DIRS environment variables override the default
301system directories. The colon-separated paths are parsed and the app name is
302appended to each path. User directories remain at defaults since no user-level
303overrides are provided. System directory env vars only affect the system
304directories, not user directories.
305
306Test _path functions do not create directories but can access files within them:
307
308 $ export HOME=/tmp/xdge/xdg_path_test
309 $ mkdir -p /tmp/xdge/xdg_path_test
310 $ unset XDG_CONFIG_HOME XDG_DATA_HOME XDG_CACHE_HOME XDG_STATE_HOME XDG_RUNTIME_DIR
311 $ unset XDG_CONFIG_DIRS XDG_DATA_DIRS
312Create config subdirectory manually and write a test file:
313 $ mkdir -p "/tmp/xdge/xdg_path_test/.config/path_test/profiles"
314 $ echo "test profile content" > "/tmp/xdge/xdg_path_test/.config/path_test/profiles/default.json"
315Create data subdirectory manually and write a test file:
316 $ mkdir -p "/tmp/xdge/xdg_path_test/.local/share/path_test/databases"
317 $ echo "test database content" > "/tmp/xdge/xdg_path_test/.local/share/path_test/databases/main.db"
318Create cache subdirectory manually and write a test file:
319 $ mkdir -p "/tmp/xdge/xdg_path_test/.cache/path_test/thumbnails"
320 $ echo "test cache content" > "/tmp/xdge/xdg_path_test/.cache/path_test/thumbnails/thumb1.png"
321Create state subdirectory manually and write a test file:
322 $ mkdir -p "/tmp/xdge/xdg_path_test/.local/state/path_test/logs"
323 $ echo "test log content" > "/tmp/xdge/xdg_path_test/.local/state/path_test/logs/app.log"
324
325Now test that we can read the files through the XDG _path functions:
326 $ ./test_paths.exe
327 config file content: test profile content
328 data file content: test database content
329 cache file content: test cache content
330 state file content: test log content
331
332This test verifies that the _path functions return correct paths that can be used to access
333files within XDG subdirectories, without the functions automatically creating those directories.
334
335Test path resolution with --show-paths:
336
337Test with a preset HOME to verify correct path resolution:
338 $ export HOME=./home_testuser
339 $ unset XDG_CONFIG_HOME XDG_DATA_HOME XDG_CACHE_HOME XDG_STATE_HOME XDG_RUNTIME_DIR
340 $ unset XDG_CONFIG_DIRS XDG_DATA_DIRS
341 $ ./xdg_example.exe --show-paths
342 config_dir: ./home_testuser/./home_testuser/.config/xdg_example
343 data_dir: ./home_testuser/./home_testuser/.local/share/xdg_example
344 cache_dir: ./home_testuser/./home_testuser/.cache/xdg_example
345 state_dir: ./home_testuser/./home_testuser/.local/state/xdg_example
346 runtime_dir: <none>
347 config_dirs: /etc/xdg/xdg_example
348 data_dirs: /usr/local/share/xdg_example:/usr/share/xdg_example
349
350Test with environment variables set:
351 $ export HOME=./home_testuser
352 $ export XDG_CONFIG_HOME=/tmp/xdge/config
353 $ export XDG_DATA_HOME=/tmp/xdge/data
354 $ export XDG_CACHE_HOME=/tmp/xdge/cache
355 $ export XDG_STATE_HOME=/tmp/xdge/state
356 $ export XDG_CONFIG_DIRS=/tmp/xdge/config1:/tmp/xdge/config2
357 $ export XDG_DATA_DIRS=/tmp/xdge/data1:/tmp/xdge/data2
358 $ ./xdg_example.exe --show-paths
359 config_dir: /tmp/xdge/config
360 data_dir: /tmp/xdge/data
361 cache_dir: /tmp/xdge/cache
362 state_dir: /tmp/xdge/state
363 runtime_dir: <none>
364 config_dirs: /tmp/xdge/config1/xdg_example:/tmp/xdge/config2/xdg_example
365 data_dirs: /tmp/xdge/data1/xdg_example:/tmp/xdge/data2/xdg_example
366
367Test with command-line overrides:
368 $ export HOME=./home_testuser
369 $ unset XDG_CONFIG_HOME XDG_DATA_HOME XDG_CACHE_HOME XDG_STATE_HOME XDG_RUNTIME_DIR
370 $ unset XDG_CONFIG_DIRS XDG_DATA_DIRS
371 $ ./xdg_example.exe --show-paths --config-dir ./override/config --data-dir ./override/data
372 config_dir: ./home_testuser/./override/config
373 data_dir: ./home_testuser/./override/data
374 cache_dir: ./home_testuser/./home_testuser/.cache/xdg_example
375 state_dir: ./home_testuser/./home_testuser/.local/state/xdg_example
376 runtime_dir: <none>
377 config_dirs: /etc/xdg/xdg_example
378 data_dirs: /usr/local/share/xdg_example:/usr/share/xdg_example
379