oh-my-devpod 0.15.0 → 0.15.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-devpod",
3
- "version": "0.15.0",
3
+ "version": "0.15.2",
4
4
  "description": "Ubuntu productivity tool manager with the omd terminal interface",
5
5
  "license": "MIT",
6
6
  "author": "zhangdw156",
package/runtime/VERSION CHANGED
@@ -1 +1 @@
1
- 0.15.0
1
+ 0.15.2
package/runtime/bin/omd CHANGED
Binary file
@@ -63,13 +63,21 @@ stat_mode() {
63
63
 
64
64
  validate_manifest() {
65
65
  local service_user manager_group expected_uid expected_gid actual_uid actual_gid installation_id
66
+ local schema resolved_prefix recorded_resolved_prefix
66
67
  [[ -f "${manifest}" && ! -L "${manifest}" ]] || fail "missing or unsafe shared manifest"
67
- [[ "$(manifest_value schema_version || true)" == "1" ]] || fail "unsupported shared manifest schema"
68
+ schema="$(manifest_value schema_version || true)"
69
+ case "${schema}" in 1|2) ;; *) fail "unsupported shared manifest schema" ;; esac
68
70
  [[ "$(manifest_value managed_by || true)" == "oh-my-devpod" ]] || fail "shared manifest ownership mismatch"
69
71
  [[ "$(manifest_value mode || true)" == "shared-service-account" ]] || fail "shared manifest mode mismatch"
70
72
  [[ "$(manifest_value prefix || true)" == "${prefix}" ]] || fail "shared prefix mismatch"
71
73
  [[ -d "${prefix}" && ! -L "${prefix}" && -x "${real_brew}" ]] || fail "real Brew backend is unavailable"
72
- [[ "$(cd "${prefix}" 2>/dev/null && pwd -P)" == "${prefix}" ]] || fail "shared prefix resolves outside its fixed path"
74
+ resolved_prefix="$(cd "${prefix}" 2>/dev/null && pwd -P)" || fail "shared prefix cannot be resolved"
75
+ if [[ "${schema}" == "1" ]]; then
76
+ recorded_resolved_prefix="${prefix}"
77
+ else
78
+ recorded_resolved_prefix="$(manifest_value resolved_prefix || true)"
79
+ fi
80
+ [[ "${resolved_prefix}" == "${recorded_resolved_prefix}" ]] || fail "shared resolved prefix mismatch"
73
81
  [[ "$(cd "${state_dir}" 2>/dev/null && pwd -P)" == "${state_dir}" ]] || fail "shared state resolves outside its fixed path"
74
82
  [[ -d "${inventory_dir}" && ! -L "${inventory_dir}" ]] || fail "shared inventory is unavailable"
75
83
  [[ -f "${lock_file}" && ! -L "${lock_file}" ]] || fail "shared mutation lock is unavailable"
@@ -95,6 +95,121 @@ path_has_no_symlink_components() {
95
95
  done
96
96
  }
97
97
 
98
+ trusted_storage_root() {
99
+ if [[ "${test_mode}" == "1" ]]; then
100
+ printf '%s\n' "${OHMYDEVPOD_SHARED_BREW_TEST_TRUSTED_STORAGE_ROOT:-/}"
101
+ else
102
+ printf '/\n'
103
+ fi
104
+ }
105
+
106
+ trusted_storage_uid() {
107
+ if [[ "${test_mode}" == "1" ]]; then
108
+ printf '%s\n' "${OHMYDEVPOD_SHARED_BREW_TEST_TRUSTED_STORAGE_UID:-$(id -u)}"
109
+ else
110
+ printf '0\n'
111
+ fi
112
+ }
113
+
114
+ trusted_storage_gid() {
115
+ if [[ "${test_mode}" == "1" ]]; then
116
+ printf '%s\n' "${OHMYDEVPOD_SHARED_BREW_TEST_TRUSTED_STORAGE_GID:-$(id -g)}"
117
+ else
118
+ printf '0\n'
119
+ fi
120
+ }
121
+
122
+ path_is_within() {
123
+ local path="$1" root="$2"
124
+ [[ "${path}" == "${root}" || "${path}" == "${root%/}"/* ]]
125
+ }
126
+
127
+ trusted_storage_directory() {
128
+ local path="$1" expected_uid="$2" expected_gid="$3" mode
129
+ [[ -d "${path}" && ! -L "${path}" ]] || return 1
130
+ [[ "$(stat_uid "${path}")" == "${expected_uid}" ]] || return 1
131
+ mode="$(stat_mode "${path}")" || return 1
132
+ [[ "${mode}" =~ ^[0-7]{3,4}$ ]] || return 1
133
+ (( (8#${mode} & 8#002) == 0 )) || return 1
134
+ if (( (8#${mode} & 8#020) != 0 )); then
135
+ [[ "$(stat_gid "${path}")" == "${expected_gid}" ]] || return 1
136
+ fi
137
+ }
138
+
139
+ trusted_storage_parent_chain() {
140
+ local path="$1" root="$2" expected_uid="$3" expected_gid="$4"
141
+ local parent relative current part
142
+ parent="$(dirname "${path}")"
143
+ path_is_within "${parent}" "${root}" || return 1
144
+ trusted_storage_directory "${root}" "${expected_uid}" "${expected_gid}" || return 1
145
+ if [[ "${root}" == "/" ]]; then
146
+ relative="${parent#/}"
147
+ current="/"
148
+ elif [[ "${parent}" == "${root}" ]]; then
149
+ relative=""
150
+ current="${root}"
151
+ else
152
+ relative="${parent#"${root%/}/"}"
153
+ current="${root%/}"
154
+ fi
155
+ while IFS= read -r part; do
156
+ [[ -n "${part}" ]] || continue
157
+ if [[ "${current}" == "/" ]]; then
158
+ current="/${part}"
159
+ else
160
+ current="${current}/${part}"
161
+ fi
162
+ if [[ -L "${current}" ]]; then
163
+ [[ "$(stat_uid "${current}")" == "${expected_uid}" ]] || return 1
164
+ else
165
+ trusted_storage_directory "${current}" "${expected_uid}" "${expected_gid}" || return 1
166
+ fi
167
+ done < <(tr '/' '\n' <<< "${relative}")
168
+ }
169
+
170
+ trusted_prefix_parent_resolved() {
171
+ local candidate="$1" root expected_uid expected_gid parent resolved_parent resolved_candidate
172
+ [[ "${candidate}" == /* ]] || return 1
173
+ parent="$(dirname "${candidate}")"
174
+ [[ -d "${parent}" ]] || return 1
175
+ root="$(trusted_storage_root)"
176
+ root="$(cd "${root}" 2>/dev/null && pwd -P)" || return 1
177
+ expected_uid="$(trusted_storage_uid)"
178
+ expected_gid="$(trusted_storage_gid)"
179
+ [[ "${expected_uid}" =~ ^[0-9]+$ && "${expected_gid}" =~ ^[0-9]+$ ]] || return 1
180
+ trusted_storage_parent_chain \
181
+ "${candidate}" "${root}" "${expected_uid}" "${expected_gid}" || return 1
182
+ resolved_parent="$(cd "${parent}" 2>/dev/null && pwd -P)" || return 1
183
+ resolved_candidate="${resolved_parent%/}/$(basename "${candidate}")"
184
+ trusted_storage_parent_chain \
185
+ "${resolved_candidate}" "${root}" "${expected_uid}" "${expected_gid}" || return 1
186
+ printf '%s\n' "${resolved_candidate}"
187
+ }
188
+
189
+ trusted_prefix_resolved() {
190
+ local candidate="$1" resolved expected_resolved
191
+ [[ "${candidate}" == /* && -d "${candidate}" && ! -L "${candidate}" ]] || return 1
192
+ resolved="$(cd "${candidate}" 2>/dev/null && pwd -P)" || return 1
193
+ [[ "${resolved}" == /* && -d "${resolved}" && ! -L "${resolved}" ]] || return 1
194
+ if path_has_no_symlink_components "${candidate}"; then
195
+ [[ "${resolved}" == "${candidate}" ]] || return 1
196
+ printf '%s\n' "${resolved}"
197
+ return 0
198
+ fi
199
+ expected_resolved="$(trusted_prefix_parent_resolved "${candidate}")" || return 1
200
+ [[ "${resolved}" == "${expected_resolved}" ]] || return 1
201
+ printf '%s\n' "${resolved}"
202
+ }
203
+
204
+ prepare_prefix_parent() {
205
+ if path_has_no_symlink_components "$(dirname "${prefix}")"; then
206
+ ensure_safe_parent "${prefix}"
207
+ return 0
208
+ fi
209
+ trusted_prefix_parent_resolved "${prefix}" >/dev/null ||
210
+ fail "shared Brew prefix parent is not controlled by the trusted storage root"
211
+ }
212
+
98
213
  ensure_safe_parent() {
99
214
  local path="$1" parent
100
215
  parent="$(dirname "${path}")"
@@ -198,7 +313,7 @@ ensure_accounts() {
198
313
  prepare_state_layout() {
199
314
  local service_uid service_gid
200
315
  ensure_safe_parent "${state_dir}"
201
- ensure_safe_parent "${prefix}"
316
+ prepare_prefix_parent
202
317
  path_has_no_symlink_components "${libexec_dir}" || fail "unsafe libexec path"
203
318
  [[ ! -e "${state_dir}" || -d "${state_dir}" ]] || fail "shared state path is not a directory"
204
319
  [[ ! -L "${state_dir}" ]] || fail "shared state path is a symlink"
@@ -341,7 +456,7 @@ legacy_home_for_user() {
341
456
  validate_legacy_prefix() {
342
457
  local owner_uid owner_gid owner owner_home marker marker_uid reported
343
458
  [[ -d "${prefix}" && ! -L "${prefix}" && -x "${prefix}/bin/brew" ]] || fail "unmanaged-prefix-conflict: prefix is missing or unsafe"
344
- path_has_no_symlink_components "${prefix}" || fail "unmanaged-prefix-conflict: prefix path contains a symlink"
459
+ trusted_prefix_resolved "${prefix}" >/dev/null || fail "unmanaged-prefix-conflict: prefix path is not controlled by the trusted storage root"
345
460
  owner_uid="$(stat_uid "${prefix}")"
346
461
  owner_gid="$(stat_gid "${prefix}")"
347
462
  owner="$(user_for_uid "${owner_uid}")"
@@ -409,12 +524,14 @@ stage_legacy_inventory() {
409
524
  }
410
525
 
411
526
  write_manifest() {
412
- local mirror_profile="$1" installation_id="$2" service_uid="$3" service_gid="$4" destination="$5"
527
+ local mirror_profile="$1" installation_id="$2" service_uid="$3" service_gid="$4" destination="$5" resolved_prefix
528
+ resolved_prefix="$(trusted_prefix_resolved "${prefix}")" || fail "shared Brew prefix path is not trusted"
413
529
  {
414
- printf 'schema_version=1\n'
530
+ printf 'schema_version=2\n'
415
531
  printf 'managed_by=oh-my-devpod\n'
416
532
  printf 'mode=shared-service-account\n'
417
533
  printf 'prefix=%s\n' "${prefix}"
534
+ printf 'resolved_prefix=%s\n' "${resolved_prefix}"
418
535
  printf 'service_user=%s\n' "${service_user}"
419
536
  printf 'service_uid=%s\n' "${service_uid}"
420
537
  printf 'manager_group=%s\n' "${manager_group}"
@@ -426,10 +543,11 @@ write_manifest() {
426
543
  }
427
544
 
428
545
  validate_existing_manifest() {
429
- local expected_uid expected_gid
546
+ local expected_uid expected_gid schema resolved_prefix recorded_resolved_prefix
430
547
  [[ -f "${manifest}" && ! -L "${manifest}" ]] || fail "shared manifest is missing or unsafe"
431
548
  path_has_no_symlink_components "${state_dir}" || fail "shared state path contains a symlink"
432
- [[ "$(manifest_value schema_version || true)" == "1" ]] || fail "unsupported shared manifest schema"
549
+ schema="$(manifest_value schema_version || true)"
550
+ case "${schema}" in 1|2) ;; *) fail "unsupported shared manifest schema" ;; esac
433
551
  [[ "$(manifest_value managed_by || true)" == "oh-my-devpod" ]] || fail "shared manifest ownership mismatch"
434
552
  [[ "$(manifest_value mode || true)" == "shared-service-account" ]] || fail "shared manifest mode mismatch"
435
553
  [[ "$(manifest_value prefix || true)" == "${prefix}" ]] || fail "shared manifest prefix mismatch"
@@ -441,9 +559,15 @@ validate_existing_manifest() {
441
559
  [[ "$(manifest_value service_gid || true)" == "${expected_gid}" ]] || fail "shared manifest service GID mismatch"
442
560
  [[ "$(manifest_value installation_id || true)" =~ ^[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}$ ]] || fail "shared manifest installation ID is invalid"
443
561
  [[ -x "${prefix}/bin/brew" && ! -L "${prefix}" ]] || fail "shared Brew backend is missing or unsafe"
444
- path_has_no_symlink_components "${prefix}" || fail "shared Brew prefix contains a symlink"
445
- [[ "${test_mode}" == "1" || "$(stat_uid "${prefix}")" == "${expected_uid}" ]] || fail "shared Brew prefix owner mismatch"
446
- [[ "${test_mode}" == "1" || "$(stat_gid "${prefix}")" == "${expected_gid}" ]] || fail "shared Brew prefix group mismatch"
562
+ resolved_prefix="$(trusted_prefix_resolved "${prefix}")" || fail "shared Brew prefix path is not trusted"
563
+ if [[ "${schema}" == "1" ]]; then
564
+ recorded_resolved_prefix="${prefix}"
565
+ else
566
+ recorded_resolved_prefix="$(manifest_value resolved_prefix || true)"
567
+ fi
568
+ [[ "${resolved_prefix}" == "${recorded_resolved_prefix}" ]] || fail "shared Brew resolved prefix mismatch"
569
+ [[ "${test_mode}" == "1" || "$(stat_uid "${resolved_prefix}")" == "${expected_uid}" ]] || fail "shared Brew prefix owner mismatch"
570
+ [[ "${test_mode}" == "1" || "$(stat_gid "${resolved_prefix}")" == "${expected_gid}" ]] || fail "shared Brew prefix group mismatch"
447
571
  if [[ "${test_mode}" != "1" ]]; then
448
572
  [[ "$(stat_uid "${manifest}")" == "0" && "$(stat_gid "${manifest}")" == "0" ]] || fail "shared manifest is not root-owned"
449
573
  (( (8#$(stat_mode "${manifest}") & 8#022) == 0 )) || fail "shared manifest is writable by non-root users"
@@ -421,16 +421,8 @@ omd_source_brew_core_remote() {
421
421
  }
422
422
 
423
423
  omd_activate_shared_linuxbrew_profile_if_present() {
424
- local release_root="$1" profile="$2" helper prefix state_dir
424
+ local release_root="$1" profile="$2" helper
425
425
  helper="${release_root}/modules/lib/shared-linuxbrew.sh"
426
- if [[ "${OHMYDEVPOD_SHARED_BREW_TEST_MODE:-0}" == "1" ]]; then
427
- prefix="${OHMYDEVPOD_SHARED_BREW_PREFIX:-/home/linuxbrew/.linuxbrew}"
428
- state_dir="${OHMYDEVPOD_SHARED_BREW_STATE_DIR:-/var/lib/oh-my-devpod/linuxbrew}"
429
- else
430
- prefix="/home/linuxbrew/.linuxbrew"
431
- state_dir="/var/lib/oh-my-devpod/linuxbrew"
432
- fi
433
- [[ -e "${prefix}" || -L "${prefix}" || -e "${state_dir}/manifest" || -L "${state_dir}/manifest" ]] || return 0
434
426
  [[ -f "${helper}" && ! -L "${helper}" ]] || {
435
427
  omd_warn "Installed release cannot activate the existing shared Linuxbrew installation"
436
428
  return 1
@@ -43,6 +43,38 @@ omd_shared_linuxbrew_state_claim_present() {
43
43
  [[ -e "${manifest}" || -L "${manifest}" ]]
44
44
  }
45
45
 
46
+ omd_shared_linuxbrew_legacy_marker() {
47
+ local prefix owner_uid owner_home=""
48
+ prefix="$(omd_shared_linuxbrew_prefix)"
49
+ if omd_shared_linuxbrew_test_mode; then
50
+ owner_home="${OHMYDEVPOD_SHARED_BREW_TEST_LEGACY_HOME:-${HOME}}"
51
+ else
52
+ owner_uid="$(omd_shared_linuxbrew_stat_uid "${prefix}")" || return 1
53
+ if command -v getent >/dev/null 2>&1; then
54
+ owner_home="$(getent passwd "${owner_uid}" 2>/dev/null | awk -F: '{print $6}')"
55
+ elif [[ "$(id -u)" == "${owner_uid}" ]]; then
56
+ owner_home="${HOME}"
57
+ fi
58
+ fi
59
+ [[ "${owner_home}" == /* && -d "${owner_home}" && ! -L "${owner_home}" ]] || return 1
60
+ printf '%s/.local/state/oh-my-devpod/managed/linuxbrew\n' "${owner_home}"
61
+ }
62
+
63
+ omd_shared_linuxbrew_activation_candidate() {
64
+ local prefix marker
65
+ if omd_shared_linuxbrew_state_claim_present; then
66
+ return 0
67
+ fi
68
+ prefix="$(omd_shared_linuxbrew_prefix)"
69
+ [[ -e "${prefix}" || -L "${prefix}" ]] || return 1
70
+ marker="$(omd_shared_linuxbrew_legacy_marker)"
71
+ [[ -f "${marker}" && ! -L "${marker}" ]] || return 1
72
+ grep -Fqx 'managed_by=oh-my-devpod' "${marker}" || return 1
73
+ grep -Fqx 'component=linuxbrew' "${marker}" || return 1
74
+ grep -Fqx 'kind=directory' "${marker}" || return 1
75
+ grep -Fqx "artifact=${prefix}" "${marker}"
76
+ }
77
+
46
78
  omd_shared_linuxbrew_enabled() {
47
79
  [[ "${OHMYDEVPOD_SHARED_BREW_DISABLE:-0}" != "1" ]]
48
80
  }
@@ -76,12 +108,14 @@ omd_shared_linuxbrew_stat_mode() {
76
108
  }
77
109
 
78
110
  omd_shared_linuxbrew_validate() {
79
- local manifest prefix recorded_prefix service_user manager_group installation_id
111
+ local manifest prefix recorded_prefix resolved_prefix recorded_resolved_prefix schema
112
+ local service_user manager_group installation_id
80
113
  local expected_uid expected_gid actual_uid actual_gid
81
114
  omd_shared_linuxbrew_enabled || return 1
82
115
  manifest="$(omd_shared_linuxbrew_manifest)"
83
116
  [[ -f "${manifest}" && ! -L "${manifest}" ]] || return 1
84
- [[ "$(omd_shared_linuxbrew_manifest_value schema_version || true)" == "1" ]] || return 1
117
+ schema="$(omd_shared_linuxbrew_manifest_value schema_version || true)"
118
+ case "${schema}" in 1|2) ;; *) return 1 ;; esac
85
119
  [[ "$(omd_shared_linuxbrew_manifest_value managed_by || true)" == "oh-my-devpod" ]] || return 1
86
120
  [[ "$(omd_shared_linuxbrew_manifest_value mode || true)" == "shared-service-account" ]] || return 1
87
121
 
@@ -89,8 +123,13 @@ omd_shared_linuxbrew_validate() {
89
123
  recorded_prefix="$(omd_shared_linuxbrew_manifest_value prefix || true)"
90
124
  [[ "${recorded_prefix}" == "${prefix}" && "${prefix}" == /* && ! -L "${prefix}" ]] || return 1
91
125
  [[ -d "${prefix}" && -x "${prefix}/bin/brew" ]] || return 1
92
- prefix="$(cd "${prefix}" 2>/dev/null && pwd -P)" || return 1
93
- [[ "${prefix}" == "${recorded_prefix}" ]] || return 1
126
+ resolved_prefix="$(cd "${prefix}" 2>/dev/null && pwd -P)" || return 1
127
+ if [[ "${schema}" == "1" ]]; then
128
+ recorded_resolved_prefix="${recorded_prefix}"
129
+ else
130
+ recorded_resolved_prefix="$(omd_shared_linuxbrew_manifest_value resolved_prefix || true)"
131
+ fi
132
+ [[ "${resolved_prefix}" == "${recorded_resolved_prefix}" ]] || return 1
94
133
 
95
134
  service_user="$(omd_shared_linuxbrew_manifest_value service_user || true)"
96
135
  manager_group="$(omd_shared_linuxbrew_manifest_value manager_group || true)"
@@ -108,8 +147,8 @@ omd_shared_linuxbrew_validate() {
108
147
  actual_gid="$(omd_shared_linuxbrew_group_gid "${manager_group}" 2>/dev/null || true)"
109
148
  fi
110
149
  [[ "${actual_uid}" == "${expected_uid}" && "${actual_gid}" == "${expected_gid}" ]] || return 1
111
- [[ "$(omd_shared_linuxbrew_stat_uid "${prefix}")" == "${expected_uid}" ]] || return 1
112
- [[ "$(omd_shared_linuxbrew_stat_gid "${prefix}")" == "${expected_gid}" ]] || return 1
150
+ [[ "$(omd_shared_linuxbrew_stat_uid "${resolved_prefix}")" == "${expected_uid}" ]] || return 1
151
+ [[ "$(omd_shared_linuxbrew_stat_gid "${resolved_prefix}")" == "${expected_gid}" ]] || return 1
113
152
  if ! omd_shared_linuxbrew_test_mode; then
114
153
  [[ "$(omd_shared_linuxbrew_stat_uid "${manifest}")" == "0" ]] || return 1
115
154
  [[ "$(omd_shared_linuxbrew_stat_gid "${manifest}")" == "0" ]] || return 1
@@ -233,10 +272,8 @@ omd_shared_linuxbrew_set_profile() {
233
272
  }
234
273
 
235
274
  omd_shared_linuxbrew_activate_if_present() {
236
- local bundle_root="$1" mirror_profile="${2:-upstream}" prefix manifest
275
+ local bundle_root="$1" mirror_profile="${2:-upstream}"
237
276
  omd_shared_linuxbrew_enabled || return 0
238
- prefix="$(omd_shared_linuxbrew_prefix)"
239
- manifest="$(omd_shared_linuxbrew_manifest)"
240
- [[ -e "${prefix}" || -L "${prefix}" || -e "${manifest}" || -L "${manifest}" ]] || return 0
277
+ omd_shared_linuxbrew_activation_candidate || return 0
241
278
  omd_shared_linuxbrew_provision "${bundle_root}" "${mirror_profile}"
242
279
  }