valise-sh 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +152 -2
- package/README.md +99 -146
- package/bin/valise +57 -5376
- package/docs/architecture.md +77 -121
- package/docs/contrib-modules.md +172 -218
- package/docs/installation.md +137 -83
- package/docs/module-abi.md +125 -126
- package/docs/projects.md +249 -0
- package/docs/release-policy.md +68 -93
- package/docs/shared-modules.md +40 -39
- package/examples/README.md +12 -11
- package/examples/e2e/README.md +59 -66
- package/examples/e2e/bundles.tsv +6 -0
- package/examples/e2e/module.d/e2e_aliases.meta +1 -2
- package/examples/e2e/module.d/e2e_completions_bash.meta +0 -1
- package/examples/e2e/module.d/e2e_completions_zsh.meta +0 -1
- package/examples/e2e/module.d/e2e_env_setup.meta +2 -3
- package/examples/e2e/module.d/e2e_fish_features.meta +0 -1
- package/examples/e2e/module.d/e2e_generated_config.meta +1 -2
- package/examples/e2e/module.d/e2e_ksh_features.meta +0 -1
- package/examples/e2e/module.d/e2e_layer_probe.meta +1 -2
- package/examples/e2e/module.d/e2e_optional_network.meta +1 -2
- package/examples/e2e/module.d/e2e_platform_tools.meta +8 -0
- package/examples/e2e/module.d/e2e_platform_tools_bsd.meta +2 -3
- package/examples/e2e/module.d/e2e_platform_tools_darwin.meta +2 -3
- package/examples/e2e/module.d/e2e_platform_tools_linux.meta +2 -3
- package/examples/e2e/valise.conf +4 -0
- package/examples/e2e/variants.tsv +3 -0
- package/examples/local/module.d/hello_valise.meta +1 -2
- package/examples/profile-project/README.md +78 -108
- package/examples/profile-project/bundles.tsv +8 -0
- package/examples/profile-project/{shell/layers → layers}/demo/module.d/contrib_demo_greeting.meta +1 -2
- package/examples/profile-project/{shell/module.d → module.d}/greeting.meta +1 -2
- package/examples/profile-project/{shell/module.d → module.d}/profile_main.meta +0 -1
- package/examples/profile-project/{shell/modules → modules}/greeting.sh +1 -1
- package/examples/profile-project/valise.conf +4 -0
- package/examples/profile-project/variants.tsv +3 -0
- package/examples/shared/README.md +13 -34
- package/examples/shared/module.d/contrib_shared_paths.meta +2 -3
- package/examples/shared/module.d/contrib_shared_umask.meta +1 -2
- package/examples/shared/modules/shared/contrib_shared_paths.sh +2 -2
- package/lib/capabilities.sh +40 -13
- package/lib/cli/commands.sh +278 -0
- package/lib/cli/common.sh +326 -0
- package/lib/cli/devtools.sh +539 -0
- package/lib/cli/fish-hook.sh +986 -0
- package/lib/cli/integration.sh +337 -0
- package/lib/cli/lifecycle.sh +578 -0
- package/lib/cli/project.sh +1807 -0
- package/lib/cli/store.sh +1023 -0
- package/lib/cli/usage.sh +308 -0
- package/lib/compiler.awk +11 -4
- package/lib/fish/loader.fish +69 -9
- package/lib/fish/metadata.fish +49 -5
- package/lib/fish/profile.fish +170 -0
- package/lib/loader.sh +6 -8
- package/lib/metadata.sh +111 -5
- package/manifests/parser-support.tsv +2 -2
- package/module.d/valise_editor.meta +9 -0
- package/module.d/valise_history.meta +9 -0
- package/module.d/valise_pager.meta +9 -0
- package/module.d/valise_path.meta +9 -0
- package/module.d/{platform_bsd.meta → valise_platform_bsd.meta} +3 -4
- package/module.d/{platform_linux.meta → valise_platform_linux.meta} +3 -4
- package/module.d/{platform_macos.meta → valise_platform_macos.meta} +3 -4
- package/module.d/{platform_posix.meta → valise_platform_posix.meta} +2 -3
- package/module.d/valise_xdg.meta +9 -0
- package/modules/system/{contrib_editor.sh → valise_editor.sh} +2 -2
- package/modules/system/{contrib_history.sh → valise_history.sh} +2 -2
- package/modules/system/{contrib_pager.sh → valise_pager.sh} +2 -2
- package/modules/system/{contrib_path.sh → valise_path.sh} +3 -3
- package/modules/system/{contrib_xdg.sh → valise_xdg.sh} +2 -2
- package/package.json +91 -10
- package/docs/variants.md +0 -327
- package/entrypoints/.gitkeep +0 -0
- package/entrypoints/fish/profile.fish +0 -99
- package/examples/e2e/build-manifest.sh +0 -138
- package/examples/local/.gitkeep +0 -0
- package/examples/profile-project/shell/release/bundle-roots +0 -9
- package/examples/profile-project/shell/release/install-variants +0 -3
- package/examples/profile-project/shell/release/module-registry.tsv +0 -4
- package/examples/profile-project/shell/release/project.conf +0 -3
- package/lib/.gitkeep +0 -0
- package/manifests/.gitkeep +0 -0
- package/module.d/.gitkeep +0 -0
- package/module.d/contrib_editor.meta +0 -10
- package/module.d/contrib_history.meta +0 -10
- package/module.d/contrib_pager.meta +0 -10
- package/module.d/contrib_path.meta +0 -10
- package/module.d/contrib_xdg.meta +0 -10
- package/modules/.gitkeep +0 -0
- /package/examples/profile-project/{shell/layers → layers}/demo/modules/shared/contrib_demo_greeting.sh +0 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Copyright (c) 2026 Joseph Cumines
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
# Fish adapter for a release built by `valise build`, installed at
|
|
5
|
+
# runtime/fish/profile.fish.
|
|
6
|
+
#
|
|
7
|
+
# The valise Fish integration authenticates the active sealed release and
|
|
8
|
+
# exports SHELL_PROJECT_ROOT pointing at its root before sourcing this file.
|
|
9
|
+
# The seeds are the release's own roots_fish line in valise-release.conf, so a
|
|
10
|
+
# Fish login loads exactly the bundle the release was built for. VALISE_MODE
|
|
11
|
+
# selects strict or permissive failure handling (default strict, as in the
|
|
12
|
+
# POSIX plans). The adapter sources the release's native Fish metadata and
|
|
13
|
+
# loader, consumes the loader's bootstrap status marker, and publishes
|
|
14
|
+
# VALISE_FISH_READY=1 only after a successful activation.
|
|
15
|
+
|
|
16
|
+
# Readiness and the bootstrap handshake are engine-private state. A forged
|
|
17
|
+
# or stale value must not survive this activation, even one that fails
|
|
18
|
+
# early: erase every visible scope first, failing closed if an erase is
|
|
19
|
+
# refused.
|
|
20
|
+
for _valise_fish_profile_stale in VALISE_FISH_READY _sp_fish_loader_bootstrap_mode _sp_fish_loader_bootstrap_seeds _sp_fish_loader_bootstrap_status _sp_fish_loader_expected_source _sp_fish_metadata_expected_source
|
|
21
|
+
if builtin set -q -g "$_valise_fish_profile_stale"; and not builtin set -e -g "$_valise_fish_profile_stale"
|
|
22
|
+
builtin printf '%s\n' "valise Fish profile: cannot clear stale global $_valise_fish_profile_stale" >&2
|
|
23
|
+
return 1
|
|
24
|
+
end
|
|
25
|
+
if builtin set -q -U "$_valise_fish_profile_stale"; and not builtin set -e -U "$_valise_fish_profile_stale"
|
|
26
|
+
builtin printf '%s\n' "valise Fish profile: cannot clear stale universal $_valise_fish_profile_stale" >&2
|
|
27
|
+
return 1
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Each activation starts from nothing. Remove the functions the previous
|
|
32
|
+
# activation's loader recorded as its own, but only where the live function
|
|
33
|
+
# still has the recorded Fish provenance, then drop that loader state. A
|
|
34
|
+
# failure below therefore never leaves the old activation callable without
|
|
35
|
+
# readiness.
|
|
36
|
+
set -l _valise_fish_profile_owned_index 1
|
|
37
|
+
for _valise_fish_profile_owned in $_sp_fish_loader_owned_exports
|
|
38
|
+
set -l _valise_fish_profile_owned_source "$_sp_fish_loader_owned_sources[$_valise_fish_profile_owned_index]"
|
|
39
|
+
if builtin test -n "$_valise_fish_profile_owned_source"; and builtin functions -q -- "$_valise_fish_profile_owned"; and builtin test (builtin functions --details -- "$_valise_fish_profile_owned") = "$_valise_fish_profile_owned_source"
|
|
40
|
+
builtin functions -e -- "$_valise_fish_profile_owned"; or builtin exit 125
|
|
41
|
+
end
|
|
42
|
+
set _valise_fish_profile_owned_index (builtin math $_valise_fish_profile_owned_index + 1)
|
|
43
|
+
end
|
|
44
|
+
for _valise_fish_profile_stale in _sp_fish_loader_owned_exports _sp_fish_loader_owned_sources _sp_fish_loaded_modules _sp_fish_module_roots _sp_fish_metadata_provider
|
|
45
|
+
if builtin set -q -g "$_valise_fish_profile_stale"; and not builtin set -e -g "$_valise_fish_profile_stale"
|
|
46
|
+
builtin exit 125
|
|
47
|
+
end
|
|
48
|
+
if builtin set -q -U "$_valise_fish_profile_stale"; and not builtin set -e -U "$_valise_fish_profile_stale"
|
|
49
|
+
builtin exit 125
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
if not builtin set -q SHELL_PROJECT_ROOT
|
|
54
|
+
builtin printf '%s\n' 'valise Fish profile: SHELL_PROJECT_ROOT is not set' >&2
|
|
55
|
+
return 1
|
|
56
|
+
end
|
|
57
|
+
set -l _valise_fish_profile_root (builtin path resolve -- "$SHELL_PROJECT_ROOT" 2>/dev/null)
|
|
58
|
+
if builtin test (builtin count $_valise_fish_profile_root) -ne 1; or builtin test -z "$_valise_fish_profile_root"
|
|
59
|
+
builtin printf '%s\n' 'valise Fish profile: SHELL_PROJECT_ROOT cannot be resolved' >&2
|
|
60
|
+
return 1
|
|
61
|
+
end
|
|
62
|
+
set -l _valise_fish_profile_runtime "$_valise_fish_profile_root/runtime/fish"
|
|
63
|
+
|
|
64
|
+
for _valise_fish_profile_file in "$_valise_fish_profile_root/valise-release.conf" "$_valise_fish_profile_runtime/metadata.fish" "$_valise_fish_profile_runtime/loader.fish"
|
|
65
|
+
if not builtin test -f "$_valise_fish_profile_file"; or not builtin test -r "$_valise_fish_profile_file"
|
|
66
|
+
builtin printf '%s\n' "valise Fish profile: release file is not readable: $_valise_fish_profile_file" >&2
|
|
67
|
+
return 1
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
set -l _valise_fish_profile_mode strict
|
|
72
|
+
if builtin set -q VALISE_MODE
|
|
73
|
+
set _valise_fish_profile_mode "$VALISE_MODE"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# roots_fish holds space-separated module references. The Fish loader
|
|
77
|
+
# resolves modules by name, so a qualified name@source keeps only its name.
|
|
78
|
+
set -l _valise_fish_profile_roots_lines (builtin string match -r '^roots_fish=.*' < "$_valise_fish_profile_root/valise-release.conf")
|
|
79
|
+
if builtin test (builtin count $_valise_fish_profile_roots_lines) -ne 1
|
|
80
|
+
builtin printf '%s\n' 'valise Fish profile: valise-release.conf must hold exactly one roots_fish line' >&2
|
|
81
|
+
return 1
|
|
82
|
+
end
|
|
83
|
+
set -l _valise_fish_profile_seeds
|
|
84
|
+
for _valise_fish_profile_ref in (builtin string split ' ' -- (builtin string replace 'roots_fish=' '' -- $_valise_fish_profile_roots_lines[1]))
|
|
85
|
+
builtin test -n "$_valise_fish_profile_ref"; or continue
|
|
86
|
+
set -a _valise_fish_profile_seeds (builtin string replace -r '@.*$' '' -- $_valise_fish_profile_ref)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# The adapter, not the sourced files, names the provenance anchors the
|
|
90
|
+
# loader checks its own definitions against. Pinning them here means a
|
|
91
|
+
# caller cannot preset a forged anchor before activation.
|
|
92
|
+
set -l _valise_fish_profile_loader_anchor "$_valise_fish_profile_runtime/loader.fish"
|
|
93
|
+
set -l _valise_fish_profile_metadata_anchor "$_valise_fish_profile_runtime/metadata.fish"
|
|
94
|
+
builtin set -g _sp_fish_loader_expected_source "$_valise_fish_profile_loader_anchor"
|
|
95
|
+
builtin set -g _sp_fish_metadata_expected_source "$_valise_fish_profile_metadata_anchor"
|
|
96
|
+
|
|
97
|
+
builtin set -gx _sp_fish_loader_bootstrap_mode "$_valise_fish_profile_mode"
|
|
98
|
+
builtin set -gx _sp_fish_loader_bootstrap_seeds $_valise_fish_profile_seeds
|
|
99
|
+
|
|
100
|
+
builtin source "$_valise_fish_profile_metadata_anchor"
|
|
101
|
+
set -l _valise_fish_profile_metadata_status $status
|
|
102
|
+
# Metadata defines functions only. It must leave the activation state it was
|
|
103
|
+
# handed untouched; a source that returns success after rewriting it is
|
|
104
|
+
# rejected the same as one that fails.
|
|
105
|
+
if builtin test $_valise_fish_profile_metadata_status -eq 0
|
|
106
|
+
set -l _valise_fish_profile_tampered
|
|
107
|
+
if not builtin test "$SHELL_PROJECT_ROOT" = "$_valise_fish_profile_root"; and not builtin test (builtin path resolve -- "$SHELL_PROJECT_ROOT" 2>/dev/null) = "$_valise_fish_profile_root"
|
|
108
|
+
set -a _valise_fish_profile_tampered SHELL_PROJECT_ROOT
|
|
109
|
+
end
|
|
110
|
+
if builtin set -q -U _sp_fish_loader_expected_source; or not builtin test "$_sp_fish_loader_expected_source" = "$_valise_fish_profile_loader_anchor"
|
|
111
|
+
set -a _valise_fish_profile_tampered _sp_fish_loader_expected_source
|
|
112
|
+
end
|
|
113
|
+
if builtin set -q -U _sp_fish_metadata_expected_source; or not builtin test "$_sp_fish_metadata_expected_source" = "$_valise_fish_profile_metadata_anchor"
|
|
114
|
+
set -a _valise_fish_profile_tampered _sp_fish_metadata_expected_source
|
|
115
|
+
end
|
|
116
|
+
if builtin set -q -U _sp_fish_loader_bootstrap_mode; or not builtin test "$_sp_fish_loader_bootstrap_mode" = "$_valise_fish_profile_mode"
|
|
117
|
+
set -a _valise_fish_profile_tampered _sp_fish_loader_bootstrap_mode
|
|
118
|
+
end
|
|
119
|
+
if builtin set -q -U _sp_fish_loader_bootstrap_seeds; or not builtin test "$_sp_fish_loader_bootstrap_seeds" = "$_valise_fish_profile_seeds"
|
|
120
|
+
set -a _valise_fish_profile_tampered _sp_fish_loader_bootstrap_seeds
|
|
121
|
+
end
|
|
122
|
+
if builtin set -q _sp_fish_loader_bootstrap_status
|
|
123
|
+
set -a _valise_fish_profile_tampered _sp_fish_loader_bootstrap_status
|
|
124
|
+
end
|
|
125
|
+
if builtin test (builtin count $_valise_fish_profile_tampered) -ne 0
|
|
126
|
+
builtin printf '%s\n' "valise Fish profile: metadata changed activation state: $_valise_fish_profile_tampered" >&2
|
|
127
|
+
set _valise_fish_profile_metadata_status 1
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
if builtin test $_valise_fish_profile_metadata_status -ne 0
|
|
131
|
+
for _valise_fish_profile_stale in _sp_fish_loader_bootstrap_mode _sp_fish_loader_bootstrap_seeds _sp_fish_loader_bootstrap_status _sp_fish_loader_expected_source _sp_fish_metadata_expected_source
|
|
132
|
+
builtin set -q -U "$_valise_fish_profile_stale"; and builtin set -e -U "$_valise_fish_profile_stale"
|
|
133
|
+
builtin set -q -g "$_valise_fish_profile_stale"; and builtin set -e -g "$_valise_fish_profile_stale"
|
|
134
|
+
end
|
|
135
|
+
builtin set -g _sp_fish_loader_expected_source "$_valise_fish_profile_loader_anchor"
|
|
136
|
+
builtin set -g _sp_fish_metadata_expected_source "$_valise_fish_profile_metadata_anchor"
|
|
137
|
+
return $_valise_fish_profile_metadata_status
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
builtin source "$_valise_fish_profile_loader_anchor"
|
|
141
|
+
set -l _valise_fish_profile_loader_status $status
|
|
142
|
+
# The loader consumes the bootstrap request when it sources cleanly; erase
|
|
143
|
+
# any request a failed source left behind so it cannot leak to callers.
|
|
144
|
+
if builtin set -q _sp_fish_loader_bootstrap_mode
|
|
145
|
+
builtin set -e _sp_fish_loader_bootstrap_mode
|
|
146
|
+
end
|
|
147
|
+
if builtin set -q _sp_fish_loader_bootstrap_seeds
|
|
148
|
+
builtin set -e _sp_fish_loader_bootstrap_seeds
|
|
149
|
+
end
|
|
150
|
+
if builtin test $_valise_fish_profile_loader_status -ne 0
|
|
151
|
+
if builtin set -q _sp_fish_loader_bootstrap_status
|
|
152
|
+
builtin set -e _sp_fish_loader_bootstrap_status
|
|
153
|
+
end
|
|
154
|
+
return $_valise_fish_profile_loader_status
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# The loader publishes a fresh bootstrap status marker on every activation;
|
|
158
|
+
# its absence means the loader never completed its handshake.
|
|
159
|
+
if not builtin set -q _sp_fish_loader_bootstrap_status
|
|
160
|
+
builtin printf '%s\n' 'valise Fish profile: loader bootstrap status marker is absent' >&2
|
|
161
|
+
return 1
|
|
162
|
+
end
|
|
163
|
+
set -l _valise_fish_profile_status $_sp_fish_loader_bootstrap_status
|
|
164
|
+
builtin set -e _sp_fish_loader_bootstrap_status
|
|
165
|
+
if builtin test $_valise_fish_profile_status -ne 0
|
|
166
|
+
return $_valise_fish_profile_status
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
builtin set -gx VALISE_FISH_READY 1
|
|
170
|
+
return 0
|
package/lib/loader.sh
CHANGED
|
@@ -94,7 +94,6 @@ _sp_loader_read_record() {
|
|
|
94
94
|
_splrr_platforms=
|
|
95
95
|
_splrr_side_effect=
|
|
96
96
|
_splrr_exports=
|
|
97
|
-
_splrr_updates=
|
|
98
97
|
_splrr_version=
|
|
99
98
|
_splrr_load=
|
|
100
99
|
while IFS= read -r _splrr_line || [ -n "$_splrr_line" ]; do
|
|
@@ -112,7 +111,6 @@ _sp_loader_read_record() {
|
|
|
112
111
|
platforms) _splrr_platforms=$_splrr_value ;;
|
|
113
112
|
side_effect) _splrr_side_effect=$_splrr_value ;;
|
|
114
113
|
exports) _splrr_exports=$_splrr_value ;;
|
|
115
|
-
updates) _splrr_updates=$_splrr_value ;;
|
|
116
114
|
version) _splrr_version=$_splrr_value ;;
|
|
117
115
|
load) _splrr_load=$_splrr_value ;;
|
|
118
116
|
esac
|
|
@@ -124,12 +122,11 @@ _sp_loader_read_record() {
|
|
|
124
122
|
_spl_record_platforms=$_splrr_platforms
|
|
125
123
|
_spl_record_side_effect=$_splrr_side_effect
|
|
126
124
|
_spl_record_exports=$_splrr_exports
|
|
127
|
-
_spl_record_updates=$_splrr_updates
|
|
128
125
|
_spl_record_version=$_splrr_version
|
|
129
126
|
_spl_record_load=$_splrr_load
|
|
130
127
|
unset _splrr_file _splrr_line _splrr_key _splrr_value _splrr_name _splrr_requires \
|
|
131
128
|
_splrr_optional _splrr_shells _splrr_platforms _splrr_side_effect _splrr_exports \
|
|
132
|
-
|
|
129
|
+
_splrr_version _splrr_load
|
|
133
130
|
}
|
|
134
131
|
|
|
135
132
|
_sp_loader_reserved_scan() {
|
|
@@ -639,7 +636,8 @@ sp_loader_load_modules() {
|
|
|
639
636
|
fi
|
|
640
637
|
IFS=' '
|
|
641
638
|
for _spl_value in $_spl_record_shells; do
|
|
642
|
-
|
|
639
|
+
# posix names every POSIX shell; sh names only the generic class.
|
|
640
|
+
[ "$_spl_value" = posix ] && _spl_shell_match=1
|
|
643
641
|
[ "$_spl_value" = "$_spl_current_shell" ] && _spl_shell_match=1
|
|
644
642
|
done
|
|
645
643
|
for _spl_value in $_spl_record_platforms; do
|
|
@@ -742,7 +740,7 @@ sp_loader_load_modules() {
|
|
|
742
740
|
fi
|
|
743
741
|
done
|
|
744
742
|
unset _spl_record_name _spl_record_requires _spl_record_optional _spl_record_shells \
|
|
745
|
-
_spl_record_platforms _spl_record_side_effect _spl_record_exports
|
|
743
|
+
_spl_record_platforms _spl_record_side_effect _spl_record_exports \
|
|
746
744
|
_spl_record_version _spl_record_load
|
|
747
745
|
if [ "$_spl_dep_ifs_was_set" -eq 1 ]; then
|
|
748
746
|
IFS=$_spl_dep_old_ifs
|
|
@@ -1613,7 +1611,7 @@ sp_loader_load_modules() {
|
|
|
1613
1611
|
_spl_order_words _spl_failed_words _spl_guard_seen_words _spl_guard_strict_required_words \
|
|
1614
1612
|
_spl_guard_blocked_words _spl_guard_modules_words _spl_guard_order_words _spl_guard_failed_words \
|
|
1615
1613
|
_spl_record_name _spl_record_requires _spl_record_optional _spl_record_shells \
|
|
1616
|
-
_spl_record_platforms _spl_record_side_effect _spl_record_exports
|
|
1614
|
+
_spl_record_platforms _spl_record_side_effect _spl_record_exports \
|
|
1617
1615
|
_spl_record_version _spl_record_load _spl_run_line _spl_module_root
|
|
1618
1616
|
unset -f _sp_loader_path_is_physical _sp_loader_read_record _sp_loader_reserved_scan 2>/dev/null || :
|
|
1619
1617
|
return 0
|
|
@@ -1663,7 +1661,7 @@ sp_loader_load_modules() {
|
|
|
1663
1661
|
_spl_order_words _spl_failed_words _spl_guard_seen_words _spl_guard_strict_required_words \
|
|
1664
1662
|
_spl_guard_blocked_words _spl_guard_modules_words _spl_guard_order_words _spl_guard_failed_words \
|
|
1665
1663
|
_spl_record_name _spl_record_requires _spl_record_optional _spl_record_shells \
|
|
1666
|
-
_spl_record_platforms _spl_record_side_effect _spl_record_exports
|
|
1664
|
+
_spl_record_platforms _spl_record_side_effect _spl_record_exports \
|
|
1667
1665
|
_spl_record_version _spl_record_load _spl_run_line _spl_module_root
|
|
1668
1666
|
unset -f _sp_loader_path_is_physical _sp_loader_read_record _sp_loader_reserved_scan 2>/dev/null || :
|
|
1669
1667
|
return 1
|
package/lib/metadata.sh
CHANGED
|
@@ -144,7 +144,7 @@ sp_metadata_validate_shell_list() {
|
|
|
144
144
|
for _spm_shell in $1; do
|
|
145
145
|
_spm_shell_seen=1
|
|
146
146
|
case "$_spm_shell" in
|
|
147
|
-
sh | bash | zsh | ksh | fish) ;;
|
|
147
|
+
posix | sh | bash | zsh | ksh | fish) ;;
|
|
148
148
|
*)
|
|
149
149
|
sp_metadata_error "invalid shell: $_spm_shell"
|
|
150
150
|
if [ "$_spm_shell_ifs_was_set" -eq 1 ]; then
|
|
@@ -285,6 +285,92 @@ sp_metadata_validate_relative_path() {
|
|
|
285
285
|
return 0
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
# sp_metadata_validate_path_list <list> <label>
|
|
289
|
+
# Validate space-separated module-relative file paths: each must be a
|
|
290
|
+
# relative path with no empty, "." or ".." segment and no trailing slash.
|
|
291
|
+
sp_metadata_validate_path_list() {
|
|
292
|
+
_spm_plist=$1
|
|
293
|
+
_spm_plabel=$2
|
|
294
|
+
sp_metadata_reject_glob_characters "$_spm_plist" "$_spm_plabel" || {
|
|
295
|
+
unset _spm_plist _spm_plabel
|
|
296
|
+
return 1
|
|
297
|
+
}
|
|
298
|
+
if [ "${IFS+x}" = x ]; then
|
|
299
|
+
_spm_plist_ifs_was_set=1
|
|
300
|
+
_spm_plist_ifs=${IFS-}
|
|
301
|
+
else
|
|
302
|
+
_spm_plist_ifs_was_set=0
|
|
303
|
+
_spm_plist_ifs=
|
|
304
|
+
fi
|
|
305
|
+
_spm_plist_status=0
|
|
306
|
+
IFS=' '
|
|
307
|
+
for _spm_pword in $_spm_plist; do
|
|
308
|
+
case "$_spm_pword" in
|
|
309
|
+
. | ./* | */. | */./* | *//* | */)
|
|
310
|
+
sp_metadata_error "invalid $_spm_plabel path: $_spm_pword"
|
|
311
|
+
_spm_plist_status=1
|
|
312
|
+
break
|
|
313
|
+
;;
|
|
314
|
+
esac
|
|
315
|
+
if ! sp_metadata_validate_relative_path "$_spm_pword"; then
|
|
316
|
+
_spm_plist_status=1
|
|
317
|
+
break
|
|
318
|
+
fi
|
|
319
|
+
if [ "$_spm_plabel" = executable ]; then
|
|
320
|
+
_spm_pbase=${_spm_pword##*/}
|
|
321
|
+
case "$_spm_pbase" in
|
|
322
|
+
[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*) ;;
|
|
323
|
+
*)
|
|
324
|
+
sp_metadata_error "invalid executable name: $_spm_pbase"
|
|
325
|
+
_spm_plist_status=1
|
|
326
|
+
break
|
|
327
|
+
;;
|
|
328
|
+
esac
|
|
329
|
+
fi
|
|
330
|
+
done
|
|
331
|
+
if [ "$_spm_plist_ifs_was_set" -eq 1 ]; then
|
|
332
|
+
IFS=$_spm_plist_ifs
|
|
333
|
+
else
|
|
334
|
+
unset IFS
|
|
335
|
+
fi
|
|
336
|
+
_spm_plist_rc=$_spm_plist_status
|
|
337
|
+
unset _spm_plist _spm_plabel _spm_pword _spm_pbase _spm_plist_ifs _spm_plist_ifs_was_set _spm_plist_status
|
|
338
|
+
return "$_spm_plist_rc"
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
# sp_metadata_validate_commands <commands> <exports>
|
|
342
|
+
# Every published command must be one of the module's declared exports.
|
|
343
|
+
sp_metadata_validate_commands() {
|
|
344
|
+
sp_metadata_validate_identifier_list "$1" command || return 1
|
|
345
|
+
if [ "${IFS+x}" = x ]; then
|
|
346
|
+
_spm_cmd_ifs_was_set=1
|
|
347
|
+
_spm_cmd_ifs=${IFS-}
|
|
348
|
+
else
|
|
349
|
+
_spm_cmd_ifs_was_set=0
|
|
350
|
+
_spm_cmd_ifs=
|
|
351
|
+
fi
|
|
352
|
+
_spm_cmd_status=0
|
|
353
|
+
IFS=' '
|
|
354
|
+
for _spm_cmd in $1; do
|
|
355
|
+
case " $2 " in
|
|
356
|
+
*" $_spm_cmd "*) ;;
|
|
357
|
+
*)
|
|
358
|
+
sp_metadata_error "command is not a declared export: $_spm_cmd"
|
|
359
|
+
_spm_cmd_status=1
|
|
360
|
+
break
|
|
361
|
+
;;
|
|
362
|
+
esac
|
|
363
|
+
done
|
|
364
|
+
if [ "$_spm_cmd_ifs_was_set" -eq 1 ]; then
|
|
365
|
+
IFS=$_spm_cmd_ifs
|
|
366
|
+
else
|
|
367
|
+
unset IFS
|
|
368
|
+
fi
|
|
369
|
+
_spm_cmd_rc=$_spm_cmd_status
|
|
370
|
+
unset _spm_cmd _spm_cmd_ifs _spm_cmd_ifs_was_set _spm_cmd_status
|
|
371
|
+
return "$_spm_cmd_rc"
|
|
372
|
+
}
|
|
373
|
+
|
|
288
374
|
sp_metadata_validate_load_target() {
|
|
289
375
|
_spm_target_load=$1
|
|
290
376
|
_spm_target_requires=${2-}
|
|
@@ -327,9 +413,12 @@ sp_metadata_read() (
|
|
|
327
413
|
_spm_platforms=
|
|
328
414
|
_spm_side_effect=
|
|
329
415
|
_spm_exports=
|
|
330
|
-
|
|
416
|
+
_spm_commands=
|
|
417
|
+
_spm_executables=
|
|
418
|
+
_spm_tests=
|
|
331
419
|
_spm_version=
|
|
332
420
|
_spm_load=
|
|
421
|
+
_spm_seen=' '
|
|
333
422
|
|
|
334
423
|
while IFS= read -r _spm_line || [ -n "$_spm_line" ]; do
|
|
335
424
|
case "$_spm_line" in
|
|
@@ -343,6 +432,13 @@ sp_metadata_read() (
|
|
|
343
432
|
_spm_key=${_spm_line%%=*}
|
|
344
433
|
_spm_value=${_spm_line#*=}
|
|
345
434
|
sp_metadata_reject_control_characters "$_spm_value" "$_spm_key" || return 1
|
|
435
|
+
case "$_spm_seen" in
|
|
436
|
+
*" $_spm_key "*)
|
|
437
|
+
sp_metadata_error "duplicate metadata field: $_spm_key"
|
|
438
|
+
return 1
|
|
439
|
+
;;
|
|
440
|
+
esac
|
|
441
|
+
_spm_seen="$_spm_seen$_spm_key "
|
|
346
442
|
case "$_spm_key" in
|
|
347
443
|
name) _spm_name=$_spm_value ;;
|
|
348
444
|
requires) _spm_requires=$_spm_value ;;
|
|
@@ -351,7 +447,13 @@ sp_metadata_read() (
|
|
|
351
447
|
platforms) _spm_platforms=$_spm_value ;;
|
|
352
448
|
side_effect) _spm_side_effect=$_spm_value ;;
|
|
353
449
|
exports) _spm_exports=$_spm_value ;;
|
|
354
|
-
|
|
450
|
+
commands) _spm_commands=$_spm_value ;;
|
|
451
|
+
executables) _spm_executables=$_spm_value ;;
|
|
452
|
+
tests) _spm_tests=$_spm_value ;;
|
|
453
|
+
updates)
|
|
454
|
+
sp_metadata_error 'metadata field updates is not supported since valise 0.3.0; publish commands with commands= or executables='
|
|
455
|
+
return 1
|
|
456
|
+
;;
|
|
355
457
|
version) _spm_version=$_spm_value ;;
|
|
356
458
|
load) _spm_load=$_spm_value ;;
|
|
357
459
|
load_hook)
|
|
@@ -381,7 +483,9 @@ sp_metadata_read() (
|
|
|
381
483
|
sp_metadata_validate_platform_list "$_spm_platforms" || return 1
|
|
382
484
|
sp_metadata_validate_side_effect "$_spm_side_effect" || return 1
|
|
383
485
|
sp_metadata_validate_identifier_list "$_spm_exports" export || return 1
|
|
384
|
-
|
|
486
|
+
sp_metadata_validate_commands "$_spm_commands" "$_spm_exports" || return 1
|
|
487
|
+
sp_metadata_validate_path_list "$_spm_executables" executable || return 1
|
|
488
|
+
sp_metadata_validate_path_list "$_spm_tests" test || return 1
|
|
385
489
|
sp_metadata_validate_version "$_spm_version" || return 1
|
|
386
490
|
sp_metadata_validate_relative_path "$_spm_load" || return 1
|
|
387
491
|
|
|
@@ -392,7 +496,9 @@ sp_metadata_read() (
|
|
|
392
496
|
printf 'platforms=%s\n' "$_spm_platforms"
|
|
393
497
|
printf 'side_effect=%s\n' "$_spm_side_effect"
|
|
394
498
|
printf 'exports=%s\n' "$_spm_exports"
|
|
395
|
-
printf '
|
|
499
|
+
printf 'commands=%s\n' "$_spm_commands"
|
|
500
|
+
printf 'executables=%s\n' "$_spm_executables"
|
|
501
|
+
printf 'tests=%s\n' "$_spm_tests"
|
|
396
502
|
printf 'version=%s\n' "$_spm_version"
|
|
397
503
|
printf 'load=%s\n' "$_spm_load"
|
|
398
504
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# path_pattern class parsers requirement notes
|
|
2
2
|
entrypoints/profile.sh posix sh,dash,ksh,busybox-ash,bash required Portable profile entrypoint must parse with POSIX-family shells and Bash when those parsers are available.
|
|
3
|
-
|
|
4
|
-
lib/*.sh posix sh,dash,ksh,busybox-ash,bash required Library files are portable core unless a narrower shell-specific path owns them.
|
|
3
|
+
bin/valise posix sh,dash,ksh,busybox-ash,bash required CLI dispatcher is pure POSIX sh.
|
|
4
|
+
lib/*.sh posix sh,dash,ksh,busybox-ash,bash required Library files (including lib/cli) are portable core unless a narrower shell-specific path owns them.
|
|
5
5
|
lib/*.awk non-shell none required Awk compiler is not a shell script; excluded from shell parser validation.
|
|
6
6
|
lib/fish/*.fish fish fish required Fish-native library files require Fish parser, not POSIX shells.
|
|
7
7
|
modules/system/*.sh posix sh,dash,ksh,busybox-ash,bash required System utility modules use portable syntax plus capability gates.
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
name=
|
|
2
|
-
requires=
|
|
1
|
+
name=valise_platform_bsd
|
|
2
|
+
requires=valise_platform_posix
|
|
3
3
|
optional=
|
|
4
|
-
shells=
|
|
4
|
+
shells=posix
|
|
5
5
|
platforms=bsd freebsd openbsd netbsd
|
|
6
6
|
side_effect=read-only
|
|
7
7
|
exports=sp_platform_bsd_available sp_platform_bsd_cpu_count sp_platform_bsd_file_mtime
|
|
8
|
-
updates=
|
|
9
8
|
load=modules/platform/bsd/capabilities.sh
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
name=
|
|
2
|
-
requires=
|
|
1
|
+
name=valise_platform_linux
|
|
2
|
+
requires=valise_platform_posix
|
|
3
3
|
optional=
|
|
4
|
-
shells=
|
|
4
|
+
shells=posix
|
|
5
5
|
platforms=linux
|
|
6
6
|
side_effect=read-only
|
|
7
7
|
exports=sp_platform_linux_available sp_platform_linux_cpu_count sp_platform_linux_file_mtime
|
|
8
|
-
updates=
|
|
9
8
|
load=modules/platform/linux/capabilities.sh
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
name=
|
|
2
|
-
requires=
|
|
1
|
+
name=valise_platform_macos
|
|
2
|
+
requires=valise_platform_posix
|
|
3
3
|
optional=
|
|
4
|
-
shells=
|
|
4
|
+
shells=posix
|
|
5
5
|
platforms=darwin
|
|
6
6
|
side_effect=read-only
|
|
7
7
|
exports=sp_platform_macos_available sp_platform_macos_homebrew_prefix sp_platform_macos_homebrew_gnubin sp_platform_macos_cpu_count
|
|
8
|
-
updates=
|
|
9
8
|
load=modules/platform/macos/capabilities.sh
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
name=
|
|
1
|
+
name=valise_platform_posix
|
|
2
2
|
requires=
|
|
3
3
|
optional=
|
|
4
|
-
shells=
|
|
4
|
+
shells=posix
|
|
5
5
|
platforms=any
|
|
6
6
|
side_effect=read-only
|
|
7
7
|
exports=sp_platform_os sp_platform_cpu_count sp_platform_file_mtime sp_platform_mktemp_dir sp_platform_canonical_path sp_platform_path_under sp_platform_command_path
|
|
8
|
-
updates=
|
|
9
8
|
load=modules/platform/posix.sh
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# Copyright (c) 2026 Joseph Cumines
|
|
2
2
|
# SPDX-License-Identifier: MIT
|
|
3
3
|
|
|
4
|
-
#
|
|
4
|
+
# valise_editor: predictable EDITOR/VISUAL defaults.
|
|
5
5
|
#
|
|
6
6
|
# Respects values the user already set; otherwise uses the first available
|
|
7
7
|
# of nvim, vim, vi. vi is POSIX-mandated and present on conforming systems,
|
|
8
8
|
# so a default is always found there. Prints nothing and succeeds in every
|
|
9
9
|
# case, including when nothing is available.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
valise_editor_defaults() {
|
|
12
12
|
if [ -n "${EDITOR-}" ] && [ -n "${VISUAL-}" ]; then
|
|
13
13
|
return 0
|
|
14
14
|
fi
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Copyright (c) 2026 Joseph Cumines
|
|
2
2
|
# SPDX-License-Identifier: MIT
|
|
3
3
|
|
|
4
|
-
#
|
|
4
|
+
# valise_history: predictable shell history defaults.
|
|
5
5
|
#
|
|
6
6
|
# Sets HISTFILE under HOME and a portable HISTSIZE only when each is unset
|
|
7
7
|
# or empty; values the user already set are never touched. When HOME is
|
|
8
8
|
# unset, HISTFILE is left alone. Prints nothing and succeeds in every case.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
valise_history_defaults() {
|
|
11
11
|
if [ -z "${HISTFILE-}" ] && [ -n "${HOME-}" ]; then
|
|
12
12
|
HISTFILE=$HOME/.sh_history
|
|
13
13
|
export HISTFILE
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Copyright (c) 2026 Joseph Cumines
|
|
2
2
|
# SPDX-License-Identifier: MIT
|
|
3
3
|
|
|
4
|
-
#
|
|
4
|
+
# valise_pager: predictable PAGER default.
|
|
5
5
|
#
|
|
6
6
|
# Respects a value the user already set; otherwise uses the first available
|
|
7
7
|
# of less, more. When neither exists, PAGER is left unset. Prints nothing
|
|
8
8
|
# and succeeds in every case.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
valise_pager_defaults() {
|
|
11
11
|
if [ -n "${PAGER-}" ]; then
|
|
12
12
|
return 0
|
|
13
13
|
fi
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Copyright (c) 2026 Joseph Cumines
|
|
2
2
|
# SPDX-License-Identifier: MIT
|
|
3
3
|
|
|
4
|
-
#
|
|
4
|
+
# valise_path: idempotent PATH augmentation.
|
|
5
5
|
#
|
|
6
6
|
# Each listed directory ends up in PATH exactly once. With no arguments the
|
|
7
7
|
# functions normalize PATH in place (duplicates and empty components are
|
|
@@ -73,12 +73,12 @@ _contrib_path_rebuild() {
|
|
|
73
73
|
unset _contrib_path_mode _contrib_path_wanted _contrib_path_item _contrib_path_kept _contrib_path_field _contrib_path_new _contrib_path_old_ifs _contrib_path_ifs_was_set _contrib_path_glob_off
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
valise_path_prepend() {
|
|
77
77
|
# Move each argument to the front of PATH, preserving argument order, so
|
|
78
78
|
# the first argument ends up first.
|
|
79
79
|
_contrib_path_rebuild prepend "$@"
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
valise_path_append() {
|
|
83
83
|
_contrib_path_rebuild append "$@"
|
|
84
84
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# Copyright (c) 2026 Joseph Cumines
|
|
2
2
|
# SPDX-License-Identifier: MIT
|
|
3
3
|
|
|
4
|
-
#
|
|
4
|
+
# valise_xdg: predictable XDG base directory defaults.
|
|
5
5
|
#
|
|
6
6
|
# Fills in each of XDG_DATA_HOME, XDG_CONFIG_HOME, XDG_STATE_HOME, and
|
|
7
7
|
# XDG_CACHE_HOME from HOME only when that variable is unset or empty;
|
|
8
8
|
# values the user already set are never touched. When HOME itself is
|
|
9
9
|
# unset, nothing is set. Prints nothing and succeeds in every case.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
valise_xdg_defaults() {
|
|
12
12
|
if [ -z "${HOME-}" ]; then
|
|
13
13
|
return 0
|
|
14
14
|
fi
|