main.sh 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #!/bin/bash
  2. # main.sh - Main entry point for USM installer
  3. # This file will be the entry point of the compiled installer
  4. # Default configuration
  5. TARGET_DIR="/opt/usm"
  6. ASSUME_YES="false"
  7. VERBOSE="false"
  8. SCRIPT_VERSION="@VERSION@"
  9. PM_TYPE=""
  10. ORIGINAL_ARGS=("$@")
  11. # Parse command line arguments
  12. parse_args() {
  13. while [[ $# -gt 0 ]]; do
  14. case "$1" in
  15. --target|-t)
  16. TARGET_DIR="$2"
  17. shift 2
  18. ;;
  19. --target=*)
  20. TARGET_DIR="${1#*=}"
  21. shift
  22. ;;
  23. -y|--yes|--assume-yes)
  24. ASSUME_YES="true"
  25. shift
  26. ;;
  27. --verbose|-V)
  28. VERBOSE="true"
  29. shift
  30. ;;
  31. --help|-h)
  32. show_help
  33. exit 0
  34. ;;
  35. --version|-v)
  36. echo "USM Installer v${SCRIPT_VERSION}"
  37. exit 0
  38. ;;
  39. *)
  40. echo "Unknown option: $1"
  41. show_help
  42. exit 1
  43. ;;
  44. esac
  45. done
  46. }
  47. # Show help message
  48. show_help() {
  49. cat << EOF
  50. USM Installer v${SCRIPT_VERSION}
  51. Usage: $(basename "$0") [OPTIONS]
  52. Options:
  53. -t, --target DIR Install to DIR instead of /opt/usm
  54. -y, --assume-yes Answer yes to all prompts automatically
  55. -V, --verbose Show verbose build output
  56. -h, --help Show this help message
  57. -v, --version Show version information
  58. Examples:
  59. $(basename "$0") # Install to /opt/usm
  60. $(basename "$0") -t /opt/myusm # Install to /opt/myusm
  61. $(basename "$0") -y # Non-interactive install
  62. $(basename "$0") -V # Verbose output
  63. EOF
  64. }
  65. # Check for root privileges and offer to re-run with sudo
  66. check_root() {
  67. if is_root; then
  68. return 0
  69. fi
  70. local sudo_cmd=$(get_sudo)
  71. if [[ -z "$sudo_cmd" ]]; then
  72. show_error_and_exit "This script requires root privileges. Please run with sudo or as root."
  73. fi
  74. log_error "This script requires root privileges."
  75. if confirm "Would you like to re-run the script with $sudo_cmd?" "y"; then
  76. log_info "Re-running with $sudo_cmd..."
  77. exec $sudo_cmd "$0" "${ORIGINAL_ARGS[@]}"
  78. else
  79. show_error_and_exit "Root privileges are required. Installation cancelled."
  80. fi
  81. }
  82. # Check if target directory exists and handle reinstallation
  83. check_existing_installation() {
  84. if [[ -d "$TARGET_DIR" ]]; then
  85. log_warn "Target directory '$TARGET_DIR' already exists."
  86. if [[ "$ASSUME_YES" == "true" ]]; then
  87. log_info "Removing existing installation (auto-confirmed with -y)..."
  88. rm -rf "$TARGET_DIR"
  89. return 0
  90. fi
  91. if confirm "Do you want to delete it and reinstall?" "n"; then
  92. log_info "Removing existing installation..."
  93. rm -rf "$TARGET_DIR"
  94. else
  95. echo "Installation cancelled."
  96. exit 0
  97. fi
  98. fi
  99. }
  100. # Install the system package manager helper matching the detected PM from
  101. # the extracted payload to /usr/bin. Runs before config generation so the
  102. # `usm genconfig` call in install_shim detects the system package manager
  103. # and wires the generated usm.config to this helper.
  104. install_spm_shim() {
  105. local extract_dir="$1"
  106. local shim_name="$PM_TYPE"
  107. local source_shim="$extract_dir/spm/$shim_name/usm-spm-$shim_name"
  108. local shim_path="/usr/bin/usm-spm-$shim_name"
  109. local sudo=""
  110. if ! is_root; then
  111. sudo=$(get_sudo)
  112. fi
  113. if [[ ! -f "$source_shim" ]]; then
  114. log_error "SPM helper \"$source_shim\" not found in the installer payload"
  115. return 1
  116. fi
  117. log_step "Installing SPM helper to $shim_path..."
  118. if [[ -n "$sudo" ]]; then
  119. $sudo cp "$source_shim" "$shim_path" && $sudo chmod 755 "$shim_path"
  120. else
  121. cp "$source_shim" "$shim_path" && chmod 755 "$shim_path"
  122. fi
  123. }
  124. # Main installation function
  125. run_installation() {
  126. # Install system dependencies first (before extracting sources)
  127. log_step "Checking system dependencies..."
  128. if ! pm_install_missing_deps; then
  129. show_error_and_exit "Failed to install system dependencies. Installation halted."
  130. fi
  131. # Set up temporary directory
  132. setup_temp_dir
  133. local extract_dir="$TEMP_DIR/sources"
  134. ensure_dir "$extract_dir"
  135. # Extract bundled sources
  136. log_step "Extracting bundled sources..."
  137. if ! extract_payload "$extract_dir"; then
  138. show_error_and_exit "Failed to extract bundled sources"
  139. fi
  140. # Build and install all components
  141. log_step "Building and installing components..."
  142. if ! build_all "$extract_dir" "$TARGET_DIR"; then
  143. show_error_and_exit "Failed to build components. Installation halted."
  144. fi
  145. # Install the SPM helper before the shim step so config generation sees it
  146. if ! install_spm_shim "$extract_dir"; then
  147. show_error_and_exit "Failed to install the SPM helper. Installation halted."
  148. fi
  149. # Install shim
  150. install_shim "$TARGET_DIR"
  151. # Show completion message
  152. show_completion "$TARGET_DIR"
  153. }
  154. # Main entry point
  155. main() {
  156. parse_args "$@"
  157. # Print banner
  158. print_banner
  159. # Check for root privileges
  160. check_root
  161. # Detect package manager
  162. if ! detect_package_manager; then
  163. show_error_and_exit "Could not detect a supported package manager (apk, apt, dnf or emerge)"
  164. fi
  165. log_info "Detected package manager: ${PM_TYPE}"
  166. # Get missing dependencies for display
  167. local missing_deps=$(pm_get_missing_deps)
  168. local deps_count=$(count_missing_deps)
  169. # Show installation summary and get confirmation
  170. if ! show_installation_summary "$TARGET_DIR" "$PM_TYPE" "$deps_count" "$missing_deps"; then
  171. echo "Installation cancelled."
  172. exit 0
  173. fi
  174. # Check if target directory exists and handle reinstallation
  175. check_existing_installation
  176. # Run the installation
  177. run_installation
  178. }