-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·218 lines (194 loc) · 6.46 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·218 lines (194 loc) · 6.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#!/bin/sh
# -e: exit on error
# -u: exit on unset variables
set -eu
dry_run=false
destination=""
# Parse --dry-run / --destination before any other work
while [ $# -gt 0 ]; do
case "$1" in
--dry-run)
dry_run=true
shift
;;
--destination)
destination="${2:?--destination requires a value}"
shift 2
;;
--destination=*)
destination="${1#*=}"
shift
;;
*)
break
;;
esac
done
# Set bin directory based on OS
set_bin_dir() {
if [ "$(uname)" = "Darwin" ]; then
# Use Homebrew's bin directory on macOS if brew is installed
if command -v brew > /dev/null 2>&1; then
bin_dir="$(brew --prefix)/bin"
else
# Fallback to local bin if brew is not installed
bin_dir="${HOME}/.local/bin"
fi
else
# Use local bin directory on Linux
bin_dir="${HOME}/.local/bin"
fi
mkdir -p "${bin_dir}"
printf '%s\n' "${bin_dir}"
}
# Install Homebrew on macOS if not already present; idempotent
install_homebrew() {
[ "$(uname)" = "Darwin" ] || return 0
if command -v brew > /dev/null 2>&1; then
echo "Homebrew already installed" >&2
return 0
fi
echo "Installing Homebrew..." >&2
[ "$dry_run" = "true" ] && return 0
NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
}
# Install GitHub CLI first if not already installed
install_github_cli() {
if ! command -v gh > /dev/null 2>&1; then
echo "Installing GitHub CLI..." >&2
bin_dir="$(set_bin_dir)"
# On macOS, prefer Homebrew installation
if [ "$(uname)" = "Darwin" ] && command -v brew > /dev/null 2>&1; then
echo "Installing GitHub CLI via Homebrew..." >&2
brew install gh
return
fi
# Get latest version
latest_version=$(curl -s https://api.github.com/repos/cli/cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
# Download and install for current architecture
arch=$(uname -m)
case "${arch}" in
x86_64) arch_name="amd64" ;;
aarch64 | arm64) arch_name="arm64" ;;
*)
echo "Unsupported architecture: ${arch}" >&2
exit 1
;;
esac
# Set OS-specific download URL
os="linux"
if [ "$(uname)" = "Darwin" ]; then
os="macOS"
fi
download_url="https://github.com/cli/cli/releases/download/v${latest_version}/gh_${latest_version}_${os}_${arch_name}.tar.gz"
tmp_dir=$(mktemp -d)
curl -sL "${download_url}" | tar xz -C "${tmp_dir}"
cp "${tmp_dir}"/gh_*/bin/gh "${bin_dir}/"
rm -rf "${tmp_dir}"
echo "GitHub CLI installed successfully" >&2
else
echo "GitHub CLI already installed" >&2
fi
}
# Ensure GitHub CLI authentication, exit if authentication fails
ensure_github_auth() {
# Check if already authenticated
if gh auth status > /dev/null 2>&1; then
echo "GitHub CLI already authenticated" >&2
return 0
fi
echo "GitHub CLI authentication required" >&2
# Check if we have a token in environment variables
if [ -n "${GH_TOKEN:-}" ] || [ -n "${GITHUB_TOKEN:-}" ]; then
echo "Using token from environment variables" >&2
# Verify token works
temp_error_file=$(mktemp)
if ! gh auth status 2> "$temp_error_file" > /dev/null; then
err_msg=$(cat "$temp_error_file" 2> /dev/null || echo "Unknown authentication error")
echo "ERROR: Invalid GitHub token provided in environment variables" >&2
echo "ERROR: Details: $err_msg" >&2
rm -f "$temp_error_file"
exit 1
fi
rm -f "$temp_error_file"
return 0
fi
# Check if we're in an interactive environment
if [ -t 0 ] && [ -t 1 ] && [ -t 2 ]; then
echo "Starting interactive GitHub authentication..." >&2
# Default required scopes for full functionality
SCOPES="repo,read:org,gist"
# Attempt browser-based authentication with SSH for git operations
# This is preferred as it's more secure and supports 2FA
if gh auth login \
--git-protocol ssh \
--scopes "${SCOPES}" \
--web \
||
# Fallback to HTTPS if SSH fails
gh auth login \
--git-protocol https \
--scopes "${SCOPES}" \
--web; then
echo "GitHub CLI authentication successful" >&2
return 0
fi
fi
echo "ERROR: GitHub CLI authentication required to enable full functionality." >&2
echo "For interactive environments, run this script in a terminal." >&2
echo "For non-interactive environments, set GH_TOKEN environment variable." >&2
exit 1
}
# Install Homebrew first on macOS so chezmoi scripts inherit brew on PATH
install_homebrew
if [ "$(uname)" = "Darwin" ]; then
# A fresh `install_homebrew` writes brew to /opt/homebrew/bin (Apple
# Silicon) or /usr/local/bin (Intel) but doesn't update the current
# shell's PATH. Probe the canonical install paths so `brew shellenv`
# below succeeds even on a cold install — without this, the eval is
# silently skipped and chezmoi inherits a brew-less PATH.
if ! command -v brew > /dev/null 2>&1; then
if [ -x "/opt/homebrew/bin/brew" ]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [ -x "/usr/local/bin/brew" ]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
fi
if command -v brew > /dev/null 2>&1; then
eval "$(brew shellenv)"
fi
fi
# GitHub CLI setup (skipped in dry-run)
if [ "$dry_run" = "false" ]; then
install_github_cli
ensure_github_auth
fi
# Install chezmoi if not already installed (skipped in dry-run)
if [ "$dry_run" = "false" ]; then
if ! chezmoi="$(command -v chezmoi)"; then
bin_dir="$(set_bin_dir)"
chezmoi="${bin_dir}/chezmoi"
echo "Installing chezmoi to '${chezmoi}'" >&2
if command -v curl > /dev/null; then
chezmoi_install_script="$(curl -fsSL https://chezmoi.io/get)"
elif command -v wget > /dev/null; then
chezmoi_install_script="$(wget -qO- https://chezmoi.io/get)"
else
echo "To install chezmoi, you must have curl or wget installed." >&2
exit 1
fi
sh -c "${chezmoi_install_script}" -- -b "${bin_dir}"
unset chezmoi_install_script bin_dir
fi
else
chezmoi="chezmoi"
fi
# POSIX way to get script's dir: https://stackoverflow.com/a/29834779/12156188
script_dir="$(cd -P -- "$(dirname -- "$(command -v -- "$0")")" && pwd -P)"
set -- init --apply "--source=${script_dir}"
[ -n "${destination}" ] && set -- "$@" "--destination=${destination}"
[ "$dry_run" = "true" ] && set -- "$@" "--dry-run"
echo "Running 'chezmoi $*'" >&2
[ "$dry_run" = "true" ] && exit 0
# exec: replace current process with chezmoi
exec "$chezmoi" "$@"