oh-my-devpod 0.15.3 → 0.15.5

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.3",
3
+ "version": "0.15.5",
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.3
1
+ 0.15.5
package/runtime/bin/omd CHANGED
Binary file
@@ -8,6 +8,7 @@ bin_dir="${OHMYDEVPOD_BIN_DIR:-${HOME}/.local/bin}"
8
8
  target_arch="${TARGETARCH:-}"
9
9
  repo="oschina/gitee-cli"
10
10
  staged_path=""
11
+ tar_version=""
11
12
 
12
13
  fail() {
13
14
  printf 'error: %s\n' "$*" >&2
@@ -110,7 +111,12 @@ actual_sha="$(sha256_file "${archive_path}")"
110
111
 
111
112
  extract_dir="${tmp_dir}/extract"
112
113
  mkdir -p "${extract_dir}"
113
- tar -xzf "${archive_path}" -C "${extract_dir}" gitee ||
114
+ tar_extract_args=(-xzf "${archive_path}" -C "${extract_dir}")
115
+ tar_version="$(tar --version 2>/dev/null || true)"
116
+ if [[ "${tar_version%%$'\n'*}" == *"GNU tar"* ]]; then
117
+ tar_extract_args=(--warning=no-unknown-keyword "${tar_extract_args[@]}")
118
+ fi
119
+ tar "${tar_extract_args[@]}" gitee ||
114
120
  fail "failed to extract Gitee CLI binary"
115
121
  [[ -f "${extract_dir}/gitee" && ! -L "${extract_dir}/gitee" ]] ||
116
122
  fail "release archive does not contain a regular gitee binary"
@@ -201,6 +201,14 @@ trusted_prefix_resolved() {
201
201
  printf '%s\n' "${resolved}"
202
202
  }
203
203
 
204
+ trusted_prefixes_equivalent() {
205
+ local first="$1" second="$2" first_resolved second_resolved
206
+ [[ "${first}" == /* && "${second}" == /* ]] || return 1
207
+ first_resolved="$(trusted_prefix_resolved "${first}")" || return 1
208
+ second_resolved="$(trusted_prefix_resolved "${second}")" || return 1
209
+ [[ "${first_resolved}" == "${second_resolved}" ]]
210
+ }
211
+
204
212
  prepare_prefix_parent() {
205
213
  if path_has_no_symlink_components "$(dirname "${prefix}")"; then
206
214
  ensure_safe_parent "${prefix}"
@@ -377,8 +385,12 @@ install_policy() {
377
385
  profile_tmp="${profile_file}.tmp.$$"
378
386
  {
379
387
  printf '%s\n' '# Generated by oh-my-devpod. Shared Linuxbrew gateway.'
380
- printf 'case ":$PATH:" in *":%s:"*) ;; *) PATH="%s:$PATH" ;; esac\n' "${libexec_dir}/bin" "${libexec_dir}/bin"
381
- printf '%s\n' 'export PATH'
388
+ printf '%s\n' 'case " $(id -nG 2>/dev/null) " in'
389
+ printf ' *" %s "*)\n' "${manager_group}"
390
+ printf ' PATH="%s:%s/bin:%s/sbin:$PATH"\n' "${libexec_dir}/bin" "${prefix}" "${prefix}"
391
+ printf '%s\n' ' export PATH'
392
+ printf '%s\n' ' ;;'
393
+ printf '%s\n' 'esac'
382
394
  } > "${profile_tmp}"
383
395
  chmod 0644 "${profile_tmp}"
384
396
  if [[ "${test_mode}" != "1" ]]; then chown root:root "${profile_tmp}"; fi
@@ -498,24 +510,30 @@ write_inventory_record() {
498
510
  }
499
511
 
500
512
  legacy_formula_is_managed() {
501
- local owner_home="$1" formula="$2" marker
513
+ local owner_home="$1" formula="$2" owner_uid="${3:-}" marker marker_prefix
502
514
  marker="${owner_home}/.local/state/oh-my-devpod/managed/${formula}"
503
515
  [[ -f "${marker}" && ! -L "${marker}" ]] || return 1
516
+ if [[ "${test_mode}" != "1" && -n "${owner_uid}" ]]; then
517
+ [[ "$(stat_uid "${marker}")" == "${owner_uid}" ]] || return 1
518
+ fi
504
519
  grep -qx 'managed_by=oh-my-devpod' "${marker}" || return 1
520
+ grep -Fqx "component=${formula}" "${marker}" || return 1
505
521
  grep -qx 'kind=brew-formula' "${marker}" || return 1
506
522
  grep -Fqx "artifact=${formula}" "${marker}" || return 1
507
- grep -Fqx "brew_prefix=${prefix}" "${marker}" || return 1
523
+ marker_prefix="$(sed -n 's/^brew_prefix=//p' "${marker}")"
524
+ [[ -n "${marker_prefix}" ]] || return 1
525
+ trusted_prefixes_equivalent "${marker_prefix}" "${prefix}"
508
526
  }
509
527
 
510
528
  stage_legacy_inventory() {
511
- local owner_home="$1" installation_id="$2" staging="$3" formula state provenance
529
+ local owner_home="$1" owner_uid="$2" installation_id="$3" staging="$4" formula state provenance
512
530
  mkdir -p "${staging}"
513
531
  [[ -d "${prefix}/Cellar" ]] || return 0
514
532
  while IFS= read -r formula; do
515
533
  [[ -n "${formula}" ]] || continue
516
534
  state=external
517
535
  provenance=legacy-preexisting
518
- if legacy_formula_is_managed "${owner_home}" "${formula}"; then
536
+ if legacy_formula_is_managed "${owner_home}" "${formula}" "${owner_uid}"; then
519
537
  state=managed
520
538
  provenance=legacy-marker
521
539
  fi
@@ -523,6 +541,71 @@ stage_legacy_inventory() {
523
541
  done < <(find "${prefix}/Cellar" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | LC_ALL=C sort -u)
524
542
  }
525
543
 
544
+ legacy_inventory_record_is_recoverable() {
545
+ local record="$1" formula="$2" installation_id="$3"
546
+ [[ -f "${record}" && ! -L "${record}" ]] || return 1
547
+ grep -qx 'managed_by=oh-my-devpod' "${record}" || return 1
548
+ grep -Fqx "component=${formula}" "${record}" || return 1
549
+ grep -qx 'kind=brew-formula' "${record}" || return 1
550
+ grep -Fqx "artifact=${formula}" "${record}" || return 1
551
+ grep -Fqx "brew_prefix=${prefix}" "${record}" || return 1
552
+ grep -Fqx "installation_id=${installation_id}" "${record}" || return 1
553
+ grep -qx 'state=external' "${record}" || return 1
554
+ grep -qx 'provenance=legacy-preexisting' "${record}"
555
+ }
556
+
557
+ member_identity_for_recovery() {
558
+ local record="$1" user uid home mode current_uid current_home
559
+ [[ -f "${record}" && ! -L "${record}" ]] || return 1
560
+ user="$(basename "${record}")"
561
+ valid_account_name "${user}" || return 1
562
+ if [[ "${test_mode}" != "1" ]]; then
563
+ [[ "$(stat_uid "${record}")" == "0" && "$(stat_gid "${record}")" == "0" ]] || return 1
564
+ mode="$(stat_mode "${record}")" || return 1
565
+ [[ "${mode}" =~ ^[0-7]{3,4}$ ]] || return 1
566
+ (( (8#${mode} & 8#022) == 0 )) || return 1
567
+ fi
568
+ grep -qx 'managed_by=oh-my-devpod' "${record}" || return 1
569
+ grep -Fqx "user=${user}" "${record}" || return 1
570
+ uid="$(sed -n 's/^uid=//p' "${record}")"
571
+ home="$(sed -n 's/^home=//p' "${record}")"
572
+ [[ "${uid}" =~ ^[0-9]+$ ]] || return 1
573
+ [[ "${home}" == /* && -d "${home}" && ! -L "${home}" ]] || return 1
574
+ if [[ "${test_mode}" != "1" ]]; then
575
+ current_uid="$(id -u "${user}" 2>/dev/null)" || return 1
576
+ current_home="$(passwd_home "${user}")"
577
+ [[ "${uid}" == "${current_uid}" && "${home}" == "${current_home}" ]] || return 1
578
+ fi
579
+ printf '%s\t%s\n' "${uid}" "${home}"
580
+ }
581
+
582
+ recover_legacy_inventory() {
583
+ local installation_id service_uid service_gid record formula member identity member_uid member_home recovered
584
+ installation_id="$(manifest_value installation_id || true)"
585
+ [[ -n "${installation_id}" ]] || return 0
586
+ service_uid="$(account_uid "${service_user}")"
587
+ service_gid="$(group_gid "${manager_group}")"
588
+ while IFS= read -r -d '' record; do
589
+ formula="$(basename "${record}")"
590
+ valid_formula_name "${formula}" || continue
591
+ legacy_inventory_record_is_recoverable "${record}" "${formula}" "${installation_id}" || continue
592
+ while IFS= read -r -d '' member; do
593
+ identity="$(member_identity_for_recovery "${member}" || true)"
594
+ [[ -n "${identity}" ]] || continue
595
+ IFS=$'\t' read -r member_uid member_home <<< "${identity}"
596
+ legacy_formula_is_managed "${member_home}" "${formula}" "${member_uid}" || continue
597
+ recovered="${inventory_dir}/.${formula}.recovered.$$"
598
+ write_inventory_record "${formula}" "${installation_id}" managed legacy-marker-recovered "${recovered}"
599
+ chmod 0644 "${recovered}"
600
+ if [[ "${test_mode}" != "1" ]]; then
601
+ chown "${service_uid}:${service_gid}" "${recovered}"
602
+ fi
603
+ mv -f "${recovered}" "${record}"
604
+ break
605
+ done < <(find "${members_dir}" -mindepth 1 -maxdepth 1 -type f -print0)
606
+ done < <(find "${inventory_dir}" -mindepth 1 -maxdepth 1 -type f -print0)
607
+ }
608
+
526
609
  write_manifest() {
527
610
  local mirror_profile="$1" installation_id="$2" service_uid="$3" service_gid="$4" destination="$5" resolved_prefix
528
611
  resolved_prefix="$(trusted_prefix_resolved "${prefix}")" || fail "shared Brew prefix path is not trusted"
@@ -589,7 +672,7 @@ initialize_shared_state() {
589
672
  if [[ -e "${prefix}" || -L "${prefix}" ]]; then
590
673
  legacy_info="$(validate_legacy_prefix)"
591
674
  IFS=$'\t' read -r legacy_owner legacy_uid legacy_gid legacy_home <<< "${legacy_info}"
592
- stage_legacy_inventory "${legacy_home}" "${installation_id}" "${inventory_staging}"
675
+ stage_legacy_inventory "${legacy_home}" "${legacy_uid}" "${installation_id}" "${inventory_staging}"
593
676
  else
594
677
  created_prefix=1
595
678
  if ! initialize_prefix "${mirror_profile}"; then
@@ -840,6 +923,7 @@ ensure_shared_brew() {
840
923
  fi
841
924
  rm -f "${state_dir}/.legacy-owner"
842
925
  fi
926
+ recover_legacy_inventory
843
927
  }
844
928
 
845
929
  case "${1:-}" in
@@ -237,6 +237,9 @@ omd_install_archive() {
237
237
  omd_warn "Shared Linuxbrew activation failed; restored the previous omd release"
238
238
  return 1
239
239
  fi
240
+ if ! omd_repair_managed_login_shell_if_present "${release_dir}"; then
241
+ omd_warn "Updated omd, but could not repair the managed login shell; run omd to retry"
242
+ fi
240
243
  [[ -z "${previous_dir}" ]] || rm -rf "${previous_dir}" || true
241
244
  printf '%s\n' "${version}"
242
245
  }
@@ -430,6 +433,25 @@ omd_activate_shared_linuxbrew_profile_if_present() {
430
433
  bash -c 'set -euo pipefail; source "$1"; omd_shared_linuxbrew_activate_if_present "$2" "$3"' _ "${helper}" "${release_root}" "${profile}"
431
434
  }
432
435
 
436
+ omd_repair_managed_login_shell_if_present() {
437
+ local release_root="$1" postflight managed_dir marker managed=0
438
+ managed_dir="${OHMYDEVPOD_MANAGED_DIR:-${OHMYDEVPOD_STATE_DIR:-${XDG_STATE_HOME:-${HOME}/.local/state}/oh-my-devpod}/managed}"
439
+ for marker in "${managed_dir}/zsh" "${managed_dir}/zsh-config"; do
440
+ if [[ -f "${marker}" && ! -L "${marker}" ]] &&
441
+ grep -Fqx 'managed_by=oh-my-devpod' "${marker}"; then
442
+ managed=1
443
+ break
444
+ fi
445
+ done
446
+ [[ "${managed}" == "1" ]] || return 0
447
+ postflight="${release_root}/modules/lib/postflight.sh"
448
+ [[ -f "${postflight}" && ! -L "${postflight}" ]] || {
449
+ omd_warn "Installed release cannot repair an existing managed login shell"
450
+ return 1
451
+ }
452
+ bash "${postflight}" repair-login-shell >&2
453
+ }
454
+
433
455
  omd_activate_shared_linuxbrew_if_present() {
434
456
  local release_root="$1" source="$2" profile
435
457
  profile="$(omd_source_mirror_profile "${source}")" || return 1
@@ -448,6 +448,16 @@ omd_module_zsh_path() {
448
448
  command -v zsh
449
449
  }
450
450
 
451
+ omd_module_target_user() {
452
+ if [[ -n "${OHMYDEVPOD_TARGET_USER:-}" ]]; then
453
+ printf '%s\n' "${OHMYDEVPOD_TARGET_USER}"
454
+ elif [[ "$(id -u)" -eq 0 && -n "${SUDO_USER:-}" ]]; then
455
+ printf '%s\n' "${SUDO_USER}"
456
+ else
457
+ id -un
458
+ fi
459
+ }
460
+
451
461
  omd_module_set_login_shell() {
452
462
  local zsh_path="$1" target_user current_shell shells_file sudo_bin
453
463
  [[ -x "${zsh_path}" ]] || {
@@ -455,7 +465,7 @@ omd_module_set_login_shell() {
455
465
  return 1
456
466
  }
457
467
 
458
- target_user="${OHMYDEVPOD_TARGET_USER:-${SUDO_USER:-$(id -un)}}"
468
+ target_user="$(omd_module_target_user)"
459
469
  shells_file="${OHMYDEVPOD_SHELLS_FILE:-/etc/shells}"
460
470
  sudo_bin="${OHMYDEVPOD_SUDO_BIN:-sudo}"
461
471
  if [[ -n "${OHMYDEVPOD_CURRENT_SHELL:-}" ]]; then
@@ -5,23 +5,26 @@ source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common.sh"
5
5
  # shellcheck source=source-config.sh
6
6
  source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/source-config.sh"
7
7
 
8
- case "${1:-}" in
9
- install|update) ;;
8
+ action="${1:-}"
9
+ case "${action}" in
10
+ install|update|repair-login-shell) ;;
10
11
  *) omd_module_unknown_action "${1:-}" ;;
11
12
  esac
12
13
 
13
- case "${OHMYDEVPOD_MIRROR_PROFILE:-upstream}" in
14
- cn) source_name="gitee" ;;
15
- upstream) source_name="github" ;;
16
- *)
17
- omd_module_info notice "unknown mirror profile; native source configuration was not changed"
18
- source_name=""
19
- ;;
20
- esac
21
- if [[ -n "${source_name}" ]] &&
22
- ! omd_source_config_apply_transactional "${source_name}"; then
23
- omd_module_info error "failed to apply native source configuration"
24
- exit 1
14
+ if [[ "${action}" != "repair-login-shell" ]]; then
15
+ case "${OHMYDEVPOD_MIRROR_PROFILE:-upstream}" in
16
+ cn) source_name="gitee" ;;
17
+ upstream) source_name="github" ;;
18
+ *)
19
+ omd_module_info notice "unknown mirror profile; native source configuration was not changed"
20
+ source_name=""
21
+ ;;
22
+ esac
23
+ if [[ -n "${source_name}" ]] &&
24
+ ! omd_source_config_apply_transactional "${source_name}"; then
25
+ omd_module_info error "failed to apply native source configuration"
26
+ exit 1
27
+ fi
25
28
  fi
26
29
 
27
30
  if ! omd_module_is_managed zsh && ! omd_module_is_managed zsh-config; then