mirror of
https://github.com/pepaskopec-blip/Graduately.git
synced 2026-10-27 15:14:35 +00:00
Ship the macOS installer as a double-clickable app.
A regular user can unzip and open it; install no longer needs Terminal or chmod. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
2d6e1f04c3
commit
45ed500fa2
9 changed files with 146 additions and 39 deletions
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
|
|
@ -158,11 +158,11 @@ jobs:
|
||||||
|
|
||||||
- name: Collect installers
|
- name: Collect installers
|
||||||
run: |
|
run: |
|
||||||
|
chmod +x installers/pack-installer-zips.sh
|
||||||
|
./installers/pack-installer-zips.sh
|
||||||
cp installers/maturita-installer-linux.sh staged/
|
cp installers/maturita-installer-linux.sh staged/
|
||||||
cp installers/maturita-installer-windows.cmd staged/
|
cp installers/maturita-installer-windows.cmd staged/
|
||||||
chmod +x installers/maturita-installer-macos.command
|
cp installers/maturita-installer-*.zip staged/
|
||||||
(cd installers && zip -q ../staged/maturita-installer-macos.zip \
|
|
||||||
maturita-installer-macos.command)
|
|
||||||
# The updater downloads this to see whether it is behind.
|
# The updater downloads this to see whether it is behind.
|
||||||
echo "${{ github.sha }}" > staged/VERSION
|
echo "${{ github.sha }}" > staged/VERSION
|
||||||
|
|
||||||
|
|
|
||||||
8
Makefile
8
Makefile
|
|
@ -107,11 +107,11 @@ bundle:
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Browsers render .command/.sh/.cmd as text/plain. Rebuild these zips after
|
# Browsers render .command/.sh/.cmd as text/plain. Rebuild these zips after
|
||||||
# changing a script so the README download links stay in sync.
|
# changing a script so the README download links stay in sync. The macOS zip
|
||||||
|
# is a double-clickable .app — no Terminal, no chmod.
|
||||||
installer-zips:
|
installer-zips:
|
||||||
cd installers && zip -q -FS maturita-installer-macos.zip maturita-installer-macos.command
|
chmod +x installers/pack-installer-zips.sh
|
||||||
cd installers && zip -q -FS maturita-installer-windows.zip maturita-installer-windows.cmd
|
./installers/pack-installer-zips.sh
|
||||||
cd installers && zip -q -FS maturita-installer-linux.zip maturita-installer-linux.sh
|
|
||||||
|
|
||||||
-include $(DEP)
|
-include $(DEP)
|
||||||
|
|
||||||
|
|
|
||||||
18
README.md
18
README.md
|
|
@ -23,14 +23,13 @@ Instalátor samotnou aplikaci neobsahuje — při spuštění si dohledá aktuá
|
||||||
commit větve `builds` a stáhne ten soubor, ne kešovanou kopii podle názvu
|
commit větve `builds` a stáhne ten soubor, ne kešovanou kopii podle názvu
|
||||||
větve.
|
větve.
|
||||||
|
|
||||||
**Nejjednodušší je instalátor pro vaši platformu** (soubory z `main`, ať
|
**Stáhni zip, rozbal ho a otevři instalátor.** Nic víc (žádný Terminál):
|
||||||
nedostanete starý skript z keše větve `builds`):
|
|
||||||
|
|
||||||
| Platforma | Soubor | Jak spustit |
|
| Platforma | Soubor | Jak spustit |
|
||||||
| --------- | ------ | ----------- |
|
| --------- | ------ | ----------- |
|
||||||
| macOS (Apple Silicon) | [maturita-installer-macos.zip](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-macos.zip) | Rozbalit, v Terminálu `chmod +x maturita-installer-macos.command` a pak pravý klik → **Otevřít** |
|
| macOS (Apple Silicon) | [maturita-installer-macos.zip](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-macos.zip) | Rozbalit, pravý klik na **Nainstalovat maturita.C** → **Otevřít** |
|
||||||
| Windows (x64) | [maturita-installer-windows.zip](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-windows.zip) | Rozbalit a dvojklik na `.cmd`; u SmartScreenu **Další informace → Přesto spustit** |
|
| Windows (x64) | [maturita-installer-windows.zip](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-windows.zip) | Rozbalit a dvojklik; u SmartScreenu **Další informace → Přesto spustit** |
|
||||||
| Linux (x86_64) | [maturita-installer-linux.zip](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-linux.zip) | Rozbalit a `sh maturita-installer-linux.sh` |
|
| Linux (x86_64) | [maturita-installer-linux.zip](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-linux.zip) | Rozbalit a dvojklik na instalátor |
|
||||||
|
|
||||||
Kam se to nainstaluje: `/Applications` nebo `~/Applications` (macOS),
|
Kam se to nainstaluje: `/Applications` nebo `~/Applications` (macOS),
|
||||||
`%LOCALAPPDATA%\Programs\Maturita` (Windows), `~/Applications` (Linux).
|
`%LOCALAPPDATA%\Programs\Maturita` (Windows), `~/Applications` (Linux).
|
||||||
|
|
@ -159,14 +158,13 @@ whenever `main` changes. The installer carries no app of its own — it fetches
|
||||||
the current `builds` commit when you run it, not a CDN-cached copy of the
|
the current `builds` commit when you run it, not a CDN-cached copy of the
|
||||||
branch-named file.
|
branch-named file.
|
||||||
|
|
||||||
**Start with the installer for your platform** (files from `main`, so you
|
**Download the zip, unzip it, and open the installer.** No Terminal:
|
||||||
do not get a stale script cached from the `builds` branch):
|
|
||||||
|
|
||||||
| Platform | File | How to run |
|
| Platform | File | How to run |
|
||||||
| -------- | ---- | ---------- |
|
| -------- | ---- | ---------- |
|
||||||
| macOS (Apple Silicon) | [maturita-installer-macos.zip](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-macos.zip) | Unzip, `chmod +x maturita-installer-macos.command` in Terminal, then right-click → **Open** |
|
| macOS (Apple Silicon) | [maturita-installer-macos.zip](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-macos.zip) | Unzip, right-click **Nainstalovat maturita.C** → **Open** |
|
||||||
| Windows (x64) | [maturita-installer-windows.zip](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-windows.zip) | Unzip and double-click the `.cmd`; if SmartScreen appears, **More info → Run anyway** |
|
| Windows (x64) | [maturita-installer-windows.zip](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-windows.zip) | Unzip and double-click; if SmartScreen appears, **More info → Run anyway** |
|
||||||
| Linux (x86_64) | [maturita-installer-linux.zip](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-linux.zip) | Unzip, then `sh maturita-installer-linux.sh` |
|
| Linux (x86_64) | [maturita-installer-linux.zip](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-linux.zip) | Unzip and double-click the installer |
|
||||||
|
|
||||||
Install locations: `/Applications` or `~/Applications` (macOS),
|
Install locations: `/Applications` or `~/Applications` (macOS),
|
||||||
`%LOCALAPPDATA%\Programs\Maturita` (Windows), `~/Applications` (Linux).
|
`%LOCALAPPDATA%\Programs\Maturita` (Windows), `~/Applications` (Linux).
|
||||||
|
|
|
||||||
26
installers/macos/Info.plist
Normal file
26
installers/macos/Info.plist
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>cs</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>installer</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>org.maturita.installer</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>Nainstalovat maturita.C</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>12.0</string>
|
||||||
|
<key>LSUIElement</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSHighResolutionCapable</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
# raw.githubusercontent.com, so this script looks up the tip of `builds`
|
# raw.githubusercontent.com, so this script looks up the tip of `builds`
|
||||||
# and downloads that commit — not a stale AppImage from the last five minutes.
|
# and downloads that commit — not a stale AppImage from the last five minutes.
|
||||||
#
|
#
|
||||||
# Run it with: sh maturita-installer-linux.sh
|
# Double-click the file (or run: sh maturita-installer-linux.sh).
|
||||||
# The app updates itself from then on.
|
# The app updates itself from then on.
|
||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
@ -20,7 +20,12 @@ DESKTOP_DIR="$HOME/.local/share/applications"
|
||||||
ICON_DIR="$HOME/.local/share/icons/hicolor/512x512/apps"
|
ICON_DIR="$HOME/.local/share/icons/hicolor/512x512/apps"
|
||||||
|
|
||||||
say() { printf '%s\n' "$*"; }
|
say() { printf '%s\n' "$*"; }
|
||||||
die() { printf '\nError: %s\n' "$*" >&2; exit 1; }
|
die() {
|
||||||
|
printf '\nError: %s\n' "$*" >&2
|
||||||
|
printf 'Press Enter to close. '
|
||||||
|
read -r _ || true
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
builds_sha() {
|
builds_sha() {
|
||||||
curl -fsSL --max-time 20 \
|
curl -fsSL --max-time 20 \
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -5,7 +5,7 @@
|
||||||
# raw.githubusercontent.com, so this script looks up the tip of `builds`
|
# raw.githubusercontent.com, so this script looks up the tip of `builds`
|
||||||
# and downloads that commit — not a stale zip from the last five minutes.
|
# and downloads that commit — not a stale zip from the last five minutes.
|
||||||
#
|
#
|
||||||
# Double-click the file to run it. The app updates itself from then on.
|
# Double-click the bundled .app (or this file). No Terminal commands needed.
|
||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
|
|
@ -13,10 +13,41 @@ REPO="pepaskopec-blip/maturita.c"
|
||||||
BRANCH="builds"
|
BRANCH="builds"
|
||||||
ASSET="maturita-macos-arm64.zip"
|
ASSET="maturita-macos-arm64.zip"
|
||||||
|
|
||||||
say() { printf '%s\n' "$*"; }
|
# An .app has no TTY; show dialogs so a regular user never needs Terminal.
|
||||||
die() { printf '\nError: %s\n' "$*" >&2; printf 'Press Return to close. '; read -r _; exit 1; }
|
GUI=0
|
||||||
|
if [ ! -t 1 ] && command -v osascript >/dev/null 2>&1; then
|
||||||
|
GUI=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
say() { printf '%s\n' "$*"; }
|
||||||
|
|
||||||
|
gui_dialog() {
|
||||||
|
osascript - "$1" <<'APPLESCRIPT'
|
||||||
|
on run argv
|
||||||
|
display dialog (item 1 of argv) with title "maturita.C" buttons {"OK"} default button 1
|
||||||
|
end run
|
||||||
|
APPLESCRIPT
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_alert() {
|
||||||
|
osascript - "$1" <<'APPLESCRIPT'
|
||||||
|
on run argv
|
||||||
|
display dialog (item 1 of argv) with title "maturita.C" buttons {"OK"} default button 1 with icon stop
|
||||||
|
end run
|
||||||
|
APPLESCRIPT
|
||||||
|
}
|
||||||
|
|
||||||
|
die() {
|
||||||
|
if [ "$GUI" = 1 ]; then
|
||||||
|
gui_alert "$*" >/dev/null || true
|
||||||
|
else
|
||||||
|
printf '\nChyba: %s\n' "$*" >&2
|
||||||
|
printf 'Stiskněte Return. '
|
||||||
|
read -r _ || true
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
# Atom feed of the builds branch: curl only, no GitHub API token.
|
|
||||||
builds_sha() {
|
builds_sha() {
|
||||||
curl -fsSL --max-time 20 \
|
curl -fsSL --max-time 20 \
|
||||||
"https://github.com/$REPO/commits/$BRANCH.atom" |
|
"https://github.com/$REPO/commits/$BRANCH.atom" |
|
||||||
|
|
@ -24,16 +55,24 @@ builds_sha() {
|
||||||
head -n 1
|
head -n 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if [ "$GUI" = 1 ]; then
|
||||||
|
if ! osascript <<'APPLESCRIPT'
|
||||||
|
display dialog "Nainstalovat maturita.C do složky Aplikace? Stáhne se aktuální verze." with title "maturita.C" buttons {"Zrušit", "Instalovat"} default button "Instalovat"
|
||||||
|
APPLESCRIPT
|
||||||
|
then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
else
|
||||||
say "Installing maturita.C"
|
say "Installing maturita.C"
|
||||||
say "---------------------"
|
say "---------------------"
|
||||||
|
fi
|
||||||
|
|
||||||
arch=$(uname -m)
|
arch=$(uname -m)
|
||||||
if [ "$arch" != "arm64" ]; then
|
if [ "$arch" != "arm64" ]; then
|
||||||
die "this build is for Apple Silicon Macs, but this one reports '$arch'.
|
die "Tento instalátor je pro Mac s čipem Apple. Tento počítač hlásí '$arch'."
|
||||||
Build from source instead: https://github.com/$REPO"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
command -v curl >/dev/null 2>&1 || die "curl was not found."
|
command -v curl >/dev/null 2>&1 || die "Na Macu chybí curl, bez něj nejde nic stáhnout."
|
||||||
|
|
||||||
if [ -w /Applications ]; then
|
if [ -w /Applications ]; then
|
||||||
dest_dir="/Applications"
|
dest_dir="/Applications"
|
||||||
|
|
@ -45,24 +84,33 @@ fi
|
||||||
tmp=$(mktemp -d)
|
tmp=$(mktemp -d)
|
||||||
trap 'rm -rf "$tmp"' EXIT INT TERM
|
trap 'rm -rf "$tmp"' EXIT INT TERM
|
||||||
|
|
||||||
say "Looking up the latest build..."
|
if [ "$GUI" = 1 ]; then
|
||||||
|
osascript <<'APPLESCRIPT' >/dev/null || true
|
||||||
|
display notification "Stahuji aktuální verzi…" with title "maturita.C"
|
||||||
|
APPLESCRIPT
|
||||||
|
fi
|
||||||
|
|
||||||
sha=$(builds_sha)
|
sha=$(builds_sha)
|
||||||
[ ${#sha} -eq 40 ] || die "could not find the latest build on GitHub."
|
[ ${#sha} -eq 40 ] || die "Nepodařilo se najít aktuální verzi na GitHubu."
|
||||||
URL="https://raw.githubusercontent.com/$REPO/$sha/$ASSET"
|
URL="https://raw.githubusercontent.com/$REPO/$sha/$ASSET"
|
||||||
|
|
||||||
|
if [ "$GUI" = 1 ]; then
|
||||||
|
curl -fsSL --max-time 1800 -o "$tmp/$ASSET" "$URL" ||
|
||||||
|
die "Stažení se nezdařilo. Zkontrolujte internet a zkuste to znovu."
|
||||||
|
else
|
||||||
say "Downloading build $(printf '%.7s' "$sha")..."
|
say "Downloading build $(printf '%.7s' "$sha")..."
|
||||||
curl -fL --progress-bar --max-time 1800 -o "$tmp/$ASSET" "$URL" ||
|
curl -fL --progress-bar --max-time 1800 -o "$tmp/$ASSET" "$URL" ||
|
||||||
die "the download failed. Check your internet connection."
|
die "Stažení se nezdařilo. Zkontrolujte internet a zkuste to znovu."
|
||||||
|
|
||||||
say "Unpacking..."
|
say "Unpacking..."
|
||||||
|
fi
|
||||||
|
|
||||||
mkdir -p "$tmp/new"
|
mkdir -p "$tmp/new"
|
||||||
ditto -x -k "$tmp/$ASSET" "$tmp/new" || die "the archive could not be unpacked."
|
ditto -x -k "$tmp/$ASSET" "$tmp/new" || die "Archiv se nepodařilo rozbalit."
|
||||||
|
|
||||||
app=$(find "$tmp/new" -maxdepth 1 -name '*.app' -print -quit)
|
app=$(find "$tmp/new" -maxdepth 1 -name '*.app' -print -quit)
|
||||||
[ -n "$app" ] || die "the archive did not contain an application."
|
[ -n "$app" ] || die "V archivu není žádná aplikace."
|
||||||
name=$(basename "$app")
|
name=$(basename "$app")
|
||||||
|
|
||||||
say "Installing to $dest_dir/$name"
|
|
||||||
rm -rf "$dest_dir/$name.old"
|
rm -rf "$dest_dir/$name.old"
|
||||||
if [ -e "$dest_dir/$name" ]; then
|
if [ -e "$dest_dir/$name" ]; then
|
||||||
mv "$dest_dir/$name" "$dest_dir/$name.old"
|
mv "$dest_dir/$name" "$dest_dir/$name.old"
|
||||||
|
|
@ -71,11 +119,15 @@ if mv "$app" "$dest_dir/$name"; then
|
||||||
rm -rf "$dest_dir/$name.old"
|
rm -rf "$dest_dir/$name.old"
|
||||||
else
|
else
|
||||||
[ -e "$dest_dir/$name.old" ] && mv "$dest_dir/$name.old" "$dest_dir/$name"
|
[ -e "$dest_dir/$name.old" ] && mv "$dest_dir/$name.old" "$dest_dir/$name"
|
||||||
die "could not write to $dest_dir."
|
die "Do $dest_dir se nepodařilo zapsat."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
xattr -cr "$dest_dir/$name" 2>/dev/null || true
|
xattr -cr "$dest_dir/$name" 2>/dev/null || true
|
||||||
|
|
||||||
|
if [ "$GUI" = 1 ]; then
|
||||||
|
gui_dialog "Hotovo. Aplikace se teď otevře." >/dev/null || true
|
||||||
|
else
|
||||||
say ""
|
say ""
|
||||||
say "Done. Starting the app..."
|
say "Done. Starting the app..."
|
||||||
|
fi
|
||||||
open "$dest_dir/$name"
|
open "$dest_dir/$name"
|
||||||
|
|
|
||||||
Binary file not shown.
26
installers/pack-installer-zips.sh
Executable file
26
installers/pack-installer-zips.sh
Executable file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Rebuild the three installer zips that README links to. Browsers download a
|
||||||
|
# zip; they render .command / .sh / .cmd as a text tab.
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
here=$PWD
|
||||||
|
|
||||||
|
chmod +x maturita-installer-macos.command maturita-installer-linux.sh
|
||||||
|
|
||||||
|
tmp=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$tmp"' EXIT INT TERM
|
||||||
|
|
||||||
|
app="$tmp/Nainstalovat maturita.C.app"
|
||||||
|
mkdir -p "$app/Contents/MacOS"
|
||||||
|
cp macos/Info.plist "$app/Contents/Info.plist"
|
||||||
|
cp maturita-installer-macos.command "$app/Contents/MacOS/installer"
|
||||||
|
chmod +x "$app/Contents/MacOS/installer"
|
||||||
|
|
||||||
|
rm -f "$here/maturita-installer-macos.zip"
|
||||||
|
(cd "$tmp" && zip -r -q "$here/maturita-installer-macos.zip" \
|
||||||
|
"Nainstalovat maturita.C.app")
|
||||||
|
|
||||||
|
zip -q -FS maturita-installer-windows.zip maturita-installer-windows.cmd
|
||||||
|
zip -q -FS maturita-installer-linux.zip maturita-installer-linux.sh
|
||||||
Loading…
Add table
Add a link
Reference in a new issue