1function zmx-remote-install --description "Install zmx on a remote host by streaming a locally downloaded release tarball"
2 argparse 'h/help' 'upgrade-only' 'v/version=' -- $argv
3 or return 1
4
5 if set -q _flag_help; or test (count $argv) -ne 1
6 echo "Usage: zmx-remote-install [--upgrade-only] [--version VERSION] [user@]host"
7 echo "Example: zmx-remote-install hel1"
8 echo "By default, installs the active local zmx version."
9 echo "With --upgrade-only, only upgrades an existing remote zmx that is older than local."
10 return 0
11 end
12
13 set -l destination $argv[1]
14 set -l desired_version
15
16 if set -q _flag_version
17 set desired_version $_flag_version
18 else if type -q zmx
19 set desired_version (zmx version | awk 'NR == 1 {print $2}')
20 else if type -q mise
21 set desired_version (mise exec -- zmx version | awk 'NR == 1 {print $2}')
22 end
23
24 if test -z "$desired_version"
25 echo "zmx-remote-install: could not determine local zmx version from zmx or mise" >&2
26 return 1
27 end
28
29 mkdir -p "$HOME/.ssh/controlmasters"
30
31 set -l remote_version (command ssh \
32 -o ControlMaster=auto \
33 -o ControlPersist=10m \
34 -o ControlPath="$HOME/.ssh/controlmasters/%C" \
35 $destination \
36 "sh -c 'PATH=\"\$HOME/.local/bin:\$PATH\"; if command -v zmx >/dev/null 2>&1; then zmx version | awk \"NR == 1 {print \\\$2}\"; fi'")
37 or return $status
38
39 if test -z "$remote_version"
40 if set -q _flag_upgrade_only
41 return 0
42 end
43
44 echo "Remote zmx is not installed; installing local zmx $desired_version..." >&2
45 else if test "$remote_version" = "$desired_version"
46 return 0
47 else
48 if not type -q semver
49 echo "zmx-remote-install: semver is required to compare local zmx $desired_version with remote zmx $remote_version" >&2
50 return 1
51 end
52
53 if not semver "$desired_version" >/dev/null 2>&1; or not semver "$remote_version" >/dev/null 2>&1
54 echo "zmx-remote-install: cannot compare local zmx $desired_version with remote zmx $remote_version; refusing to sidegrade" >&2
55 return 1
56 end
57
58 if not semver -r ">$remote_version" "$desired_version" >/dev/null 2>&1
59 return 0
60 end
61
62 echo "Remote zmx is $remote_version; upgrading to local zmx $desired_version..." >&2
63 end
64
65 set -l remote_platform (command ssh \
66 -o ControlMaster=auto \
67 -o ControlPersist=10m \
68 -o ControlPath="$HOME/.ssh/controlmasters/%C" \
69 $destination \
70 "sh -c 'printf \"%s %s\\n\" \"\$(uname -s)\" \"\$(uname -m)\"'")
71 or return $status
72
73 set -l remote_os (string split ' ' -- $remote_platform)[1]
74 set -l remote_arch (string split ' ' -- $remote_platform)[2]
75 set -l zmx_os
76 set -l zmx_arch
77
78 switch $remote_os
79 case Linux
80 set zmx_os linux
81 case Darwin
82 set zmx_os macos
83 case '*'
84 echo "zmx-remote-install: unsupported remote OS '$remote_os'" >&2
85 return 2
86 end
87
88 switch $remote_arch
89 case x86_64 amd64
90 set zmx_arch x86_64
91 case aarch64 arm64
92 set zmx_arch aarch64
93 case '*'
94 echo "zmx-remote-install: unsupported remote architecture '$remote_arch'" >&2
95 return 2
96 end
97
98 set -l archive "zmx-$desired_version-$zmx_os-$zmx_arch.tar.gz"
99 set -l base_url "https://zmx.sh/a"
100 set -l temp_dir (mktemp -d)
101 set -l archive_path "$temp_dir/$archive"
102 set -l checksum_path "$archive_path.sha256"
103
104 if test -z "$temp_dir"
105 echo "zmx-remote-install: failed to create a temporary directory" >&2
106 return 1
107 end
108
109 echo "Downloading $archive..." >&2
110 if not curl -fsSL "$base_url/$archive" -o "$archive_path"
111 rm -rf $temp_dir
112 return 1
113 end
114
115 if curl -fsSL "$base_url/$archive.sha256" -o "$checksum_path"
116 set -l expected (awk '{print $1}' "$checksum_path")
117 set -l actual
118
119 if type -q sha256sum
120 set actual (sha256sum "$archive_path" | awk '{print $1}')
121 else if type -q shasum
122 set actual (shasum -a 256 "$archive_path" | awk '{print $1}')
123 else
124 echo "zmx-remote-install: no local sha256sum or shasum found; refusing to install unverified archive" >&2
125 rm -rf $temp_dir
126 return 1
127 end
128
129 if test "$expected" != "$actual"
130 echo "zmx-remote-install: checksum verification failed for $archive" >&2
131 rm -rf $temp_dir
132 return 1
133 end
134 else
135 echo "zmx-remote-install: could not download checksum for $archive; refusing to install unverified archive" >&2
136 rm -rf $temp_dir
137 return 1
138 end
139
140 echo "Installing zmx $desired_version on $destination..." >&2
141 if not command ssh \
142 -o ControlMaster=auto \
143 -o ControlPersist=10m \
144 -o ControlPath="$HOME/.ssh/controlmasters/%C" \
145 $destination \
146 "sh -c 'mkdir -p \"\$HOME/.local/bin\" && tmp=\$(mktemp \"\$HOME/.local/bin/.zmx.XXXXXX\") && tar -xOzf - zmx > \"\$tmp\" && chmod 755 \"\$tmp\" && mv \"\$tmp\" \"\$HOME/.local/bin/zmx\"'" <"$archive_path"
147 rm -rf $temp_dir
148 return 1
149 end
150
151 rm -rf $temp_dir
152
153 command ssh \
154 -o ControlMaster=auto \
155 -o ControlPersist=10m \
156 -o ControlPath="$HOME/.ssh/controlmasters/%C" \
157 $destination \
158 "sh -c 'PATH=\"\$HOME/.local/bin:\$PATH\"; zmx version'"
159end