Pin installer and updater downloads to the builds tip commit.

raw.githubusercontent.com caches branch-named files, so the installer was serving a stale zip after CI rewrote builds.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
pepaskopec-blip 2026-09-17 17:31:16 +02:00
commit 7fabe1846e
5 changed files with 151 additions and 64 deletions

View file

@ -19,16 +19,18 @@ zatím zamčené placeholdery. Aplikace se po instalaci aktualizuje sama.
Žádné releasy ani čísla verzí nejsou. CI po každém pushi na `main` uloží Žádné releasy ani čísla verzí nejsou. CI po každém pushi na `main` uloží
balíčky do větve [`builds`](https://github.com/pepaskopec-blip/maturita.c/tree/builds). balíčky do větve [`builds`](https://github.com/pepaskopec-blip/maturita.c/tree/builds).
Instalátor samotnou aplikaci neobsahuje — při spuštění si stáhne aktuální Instalátor samotnou aplikaci neobsahuje — při spuštění si dohledá aktuální
build, takže soubor nikdy nezestárne. commit větve `builds` a stáhne ten soubor, ne kešovanou kopii podle názvu
větve.
**Nejjednodušší je instalátor pro vaši platformu:** **Nejjednodušší je instalátor pro vaši platformu** (soubory z `main`, ať
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/builds/maturita-installer-macos.zip) | Rozbalit, pravý klik → **Otevřít** | | macOS (Apple Silicon) | [maturita-installer-macos.command](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-macos.command) | Stáhnout, v Terminálu `chmod +x` a pak pravý klik → **Otevřít** |
| Windows (x64) | [maturita-installer-windows.cmd](https://github.com/pepaskopec-blip/maturita.c/raw/builds/maturita-installer-windows.cmd) | Dvojklik; u SmartScreenu **Další informace → Přesto spustit** | | Windows (x64) | [maturita-installer-windows.cmd](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-windows.cmd) | Dvojklik; u SmartScreenu **Další informace → Přesto spustit** |
| Linux (x86_64) | [maturita-installer-linux.sh](https://github.com/pepaskopec-blip/maturita.c/raw/builds/maturita-installer-linux.sh) | `sh maturita-installer-linux.sh` | | Linux (x86_64) | [maturita-installer-linux.sh](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-linux.sh) | `sh maturita-installer-linux.sh` |
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).
@ -41,7 +43,9 @@ v **Nastavení → Aktualizace**.
#### Bez instalátoru #### Bez instalátoru
Na stejné větvi jsou i hotové balíčky: Na větvi [`builds`](https://github.com/pepaskopec-blip/maturita.c/tree/builds)
jsou i hotové balíčky. Odkazy podle názvu větve umí CDN kešovat, proto je
spolehlivější instalátor výše, nebo stažení přímo z té stránky větve:
- [maturita-macos-arm64.zip](https://github.com/pepaskopec-blip/maturita.c/raw/builds/maturita-macos-arm64.zip) - [maturita-macos-arm64.zip](https://github.com/pepaskopec-blip/maturita.c/raw/builds/maturita-macos-arm64.zip)
- [maturita-windows-x64.zip](https://github.com/pepaskopec-blip/maturita.c/raw/builds/maturita-windows-x64.zip) - [maturita-windows-x64.zip](https://github.com/pepaskopec-blip/maturita.c/raw/builds/maturita-windows-x64.zip)
@ -152,15 +156,17 @@ placeholders. After install the app updates itself.
There are no releases and no version numbers. CI writes packages to the There are no releases and no version numbers. CI writes packages to the
[`builds`](https://github.com/pepaskopec-blip/maturita.c/tree/builds) branch [`builds`](https://github.com/pepaskopec-blip/maturita.c/tree/builds) branch
whenever `main` changes. The installer carries no app of its own — it fetches whenever `main` changes. The installer carries no app of its own — it fetches
the current build when you run it, so the file never goes stale. the current `builds` commit when you run it, not a CDN-cached copy of the
branch-named file.
**Start with the installer for your platform:** **Start with the installer for your platform** (files from `main`, so you
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/builds/maturita-installer-macos.zip) | Unzip, then right-click → **Open** | | macOS (Apple Silicon) | [maturita-installer-macos.command](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-macos.command) | Download, `chmod +x` in Terminal, then right-click → **Open** |
| Windows (x64) | [maturita-installer-windows.cmd](https://github.com/pepaskopec-blip/maturita.c/raw/builds/maturita-installer-windows.cmd) | Double-click; if SmartScreen appears, **More info → Run anyway** | | Windows (x64) | [maturita-installer-windows.cmd](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-windows.cmd) | Double-click; if SmartScreen appears, **More info → Run anyway** |
| Linux (x86_64) | [maturita-installer-linux.sh](https://github.com/pepaskopec-blip/maturita.c/raw/builds/maturita-installer-linux.sh) | `sh maturita-installer-linux.sh` | | Linux (x86_64) | [maturita-installer-linux.sh](https://github.com/pepaskopec-blip/maturita.c/raw/main/installers/maturita-installer-linux.sh) | `sh maturita-installer-linux.sh` |
Install locations: `/Applications` or `~/Applications` (macOS), Install locations: `/Applications` or `~/Applications` (macOS),
`%LOCALAPPDATA%\Programs\Maturita` (Windows), `~/Applications` (Linux). `%LOCALAPPDATA%\Programs\Maturita` (Windows), `~/Applications` (Linux).
@ -172,6 +178,11 @@ banner. Manual check: **Settings → Updates**.
#### Packages without the installer #### Packages without the installer
The same files live on
[`builds`](https://github.com/pepaskopec-blip/maturita.c/tree/builds).
Branch-named raw URLs can be cached by the CDN, so prefer the installer
above, or download from that branch page:
- [maturita-macos-arm64.zip](https://github.com/pepaskopec-blip/maturita.c/raw/builds/maturita-macos-arm64.zip) - [maturita-macos-arm64.zip](https://github.com/pepaskopec-blip/maturita.c/raw/builds/maturita-macos-arm64.zip)
- [maturita-windows-x64.zip](https://github.com/pepaskopec-blip/maturita.c/raw/builds/maturita-windows-x64.zip) - [maturita-windows-x64.zip](https://github.com/pepaskopec-blip/maturita.c/raw/builds/maturita-windows-x64.zip)
- [maturita-linux-x86_64.AppImage](https://github.com/pepaskopec-blip/maturita.c/raw/builds/maturita-linux-x86_64.AppImage) - [maturita-linux-x86_64.AppImage](https://github.com/pepaskopec-blip/maturita.c/raw/builds/maturita-linux-x86_64.AppImage)

View file

@ -1,9 +1,9 @@
#!/bin/sh #!/bin/sh
# maturita.c installer for Linux. # maturita.c installer for Linux.
# #
# Carries no application of its own: it downloads the current build straight # Carries no application of its own. Fastly caches branch-named URLs on
# from the repository's `builds` branch, which CI rewrites whenever main # raw.githubusercontent.com, so this script looks up the tip of `builds`
# changes. This file therefore never goes stale. # and downloads that commit — not a stale AppImage from the last five minutes.
# #
# Run it with: sh maturita-installer-linux.sh # Run it with: sh maturita-installer-linux.sh
# The app updates itself from then on. # The app updates itself from then on.
@ -13,10 +13,7 @@ set -eu
REPO="pepaskopec-blip/maturita.c" REPO="pepaskopec-blip/maturita.c"
BRANCH="builds" BRANCH="builds"
ASSET="maturita-linux-x86_64.AppImage" ASSET="maturita-linux-x86_64.AppImage"
URL="https://raw.githubusercontent.com/$REPO/$BRANCH/$ASSET"
# ~/Applications is where desktop environments look for AppImages, and the app
# keeps its progress/ directory next to its own file.
DEST_DIR="$HOME/Applications" DEST_DIR="$HOME/Applications"
DEST="$DEST_DIR/maturita.AppImage" DEST="$DEST_DIR/maturita.AppImage"
DESKTOP_DIR="$HOME/.local/share/applications" DESKTOP_DIR="$HOME/.local/share/applications"
@ -25,6 +22,13 @@ 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; exit 1; }
builds_sha() {
curl -fsSL --max-time 20 \
"https://github.com/$REPO/commits/$BRANCH.atom" |
sed -n 's/.*Commit\/\([0-9a-f]\{40\}\).*/\1/p' |
head -n 1
}
say "Installing maturita.C" say "Installing maturita.C"
say "---------------------" say "---------------------"
@ -41,16 +45,19 @@ mkdir -p "$DEST_DIR"
tmp=$(mktemp -d) tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT INT TERM trap 'rm -rf "$tmp"' EXIT INT TERM
say "Downloading the latest build..." say "Looking up the latest build..."
curl -fL --progress-bar -o "$tmp/$ASSET" "$URL" || sha=$(builds_sha)
[ ${#sha} -eq 40 ] || die "could not find the latest build on GitHub."
URL="https://raw.githubusercontent.com/$REPO/$sha/$ASSET"
say "Downloading build $(printf '%.7s' "$sha")..."
curl -fL --progress-bar --max-time 1800 -o "$tmp/$ASSET" "$URL" ||
die "the download failed. Check your internet connection." die "the download failed. Check your internet connection."
say "Installing to $DEST" say "Installing to $DEST"
chmod +x "$tmp/$ASSET" chmod +x "$tmp/$ASSET"
mv -f "$tmp/$ASSET" "$DEST" || die "could not write to $DEST_DIR." mv -f "$tmp/$ASSET" "$DEST" || die "could not write to $DEST_DIR."
# A menu entry needs the icon as a separate file, which the AppImage can
# unpack without FUSE. Losing the icon is not worth failing the install over.
if (cd "$tmp" && "$DEST" --appimage-extract \ if (cd "$tmp" && "$DEST" --appimage-extract \
'usr/share/icons/hicolor/512x512/apps/maturita.png' >/dev/null 2>&1); then 'usr/share/icons/hicolor/512x512/apps/maturita.png' >/dev/null 2>&1); then
icon="$tmp/squashfs-root/usr/share/icons/hicolor/512x512/apps/maturita.png" icon="$tmp/squashfs-root/usr/share/icons/hicolor/512x512/apps/maturita.png"

View file

@ -1,9 +1,9 @@
#!/bin/sh #!/bin/sh
# maturita.c installer for macOS. # maturita.c installer for macOS.
# #
# Carries no application of its own: it downloads the current build straight # Carries no application of its own. Fastly caches branch-named URLs on
# from the repository's `builds` branch, which CI rewrites whenever main # raw.githubusercontent.com, so this script looks up the tip of `builds`
# changes. This file therefore never goes stale. # 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 file to run it. The app updates itself from then on.
@ -12,15 +12,21 @@ set -eu
REPO="pepaskopec-blip/maturita.c" REPO="pepaskopec-blip/maturita.c"
BRANCH="builds" BRANCH="builds"
ASSET="maturita-macos-arm64.zip" ASSET="maturita-macos-arm64.zip"
URL="https://raw.githubusercontent.com/$REPO/$BRANCH/$ASSET"
say() { printf '%s\n' "$*"; } say() { printf '%s\n' "$*"; }
die() { printf '\nError: %s\n' "$*" >&2; printf 'Press Return to close. '; read -r _; exit 1; } die() { printf '\nError: %s\n' "$*" >&2; printf 'Press Return to close. '; read -r _; exit 1; }
# Atom feed of the builds branch: curl only, no GitHub API token.
builds_sha() {
curl -fsSL --max-time 20 \
"https://github.com/$REPO/commits/$BRANCH.atom" |
sed -n 's/.*Commit\/\([0-9a-f]\{40\}\).*/\1/p' |
head -n 1
}
say "Installing maturita.C" say "Installing maturita.C"
say "---------------------" say "---------------------"
# Only Apple Silicon builds are published; Rosetta cannot run an arm64 app.
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 "this build is for Apple Silicon Macs, but this one reports '$arch'.
@ -29,7 +35,6 @@ fi
command -v curl >/dev/null 2>&1 || die "curl was not found." command -v curl >/dev/null 2>&1 || die "curl was not found."
# Prefer the shared folder, fall back to the user's own when it is locked down.
if [ -w /Applications ]; then if [ -w /Applications ]; then
dest_dir="/Applications" dest_dir="/Applications"
else else
@ -40,13 +45,17 @@ fi
tmp=$(mktemp -d) tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT INT TERM trap 'rm -rf "$tmp"' EXIT INT TERM
say "Downloading the latest build..." say "Looking up the latest build..."
curl -fL --progress-bar -o "$tmp/$ASSET" "$URL" || sha=$(builds_sha)
[ ${#sha} -eq 40 ] || die "could not find the latest build on GitHub."
URL="https://raw.githubusercontent.com/$REPO/$sha/$ASSET"
say "Downloading build $(printf '%.7s' "$sha")..."
curl -fL --progress-bar --max-time 1800 -o "$tmp/$ASSET" "$URL" ||
die "the download failed. Check your internet connection." die "the download failed. Check your internet connection."
say "Unpacking..." say "Unpacking..."
mkdir -p "$tmp/new" mkdir -p "$tmp/new"
# ditto keeps bundle symlinks and permissions intact, unlike plain unzip.
ditto -x -k "$tmp/$ASSET" "$tmp/new" || die "the archive could not be unpacked." ditto -x -k "$tmp/$ASSET" "$tmp/new" || die "the archive could not be unpacked."
app=$(find "$tmp/new" -maxdepth 1 -name '*.app' -print -quit) app=$(find "$tmp/new" -maxdepth 1 -name '*.app' -print -quit)
@ -61,13 +70,10 @@ fi
if mv "$app" "$dest_dir/$name"; then if mv "$app" "$dest_dir/$name"; then
rm -rf "$dest_dir/$name.old" rm -rf "$dest_dir/$name.old"
else else
# Put the previous copy back rather than leaving nothing installed.
[ -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 "could not write to $dest_dir."
fi fi
# The download carries a quarantine flag, and the app is not signed, so
# without this macOS refuses to open it.
xattr -cr "$dest_dir/$name" 2>/dev/null || true xattr -cr "$dest_dir/$name" 2>/dev/null || true
say "" say ""

View file

@ -1,23 +1,21 @@
@echo off @echo off
rem maturita.c installer for Windows. rem maturita.c installer for Windows.
rem rem
rem Carries no application of its own: it downloads the current build straight rem Carries no application of its own. Fastly caches branch-named URLs on
rem from the repository's `builds` branch, which CI rewrites whenever main rem raw.githubusercontent.com, so this script looks up the tip of `builds`
rem changes. This file therefore never goes stale. rem and downloads that commit — not a stale zip from the last five minutes.
rem rem
rem Double-click the file to run it. The app updates itself from then on. rem Double-click the file to run it. The app updates itself from then on.
setlocal setlocal EnableDelayedExpansion
set "REPO=pepaskopec-blip/maturita.c" set "REPO=pepaskopec-blip/maturita.c"
set "BRANCH=builds" set "BRANCH=builds"
set "ASSET=maturita-windows-x64.zip" set "ASSET=maturita-windows-x64.zip"
set "URL=https://raw.githubusercontent.com/%REPO%/%BRANCH%/%ASSET%"
set "DEST=%LOCALAPPDATA%\Programs\Maturita" set "DEST=%LOCALAPPDATA%\Programs\Maturita"
echo Installing maturita.C echo Installing maturita.C
echo --------------------- echo ---------------------
rem curl and tar both ship with Windows 10 1803 and later.
where curl >nul 2>&1 || goto :no_tools where curl >nul 2>&1 || goto :no_tools
where tar >nul 2>&1 || goto :no_tools where tar >nul 2>&1 || goto :no_tools
@ -25,17 +23,20 @@ set "TMP_DIR=%TEMP%\maturita-installer"
rmdir /s /q "%TMP_DIR%" 2>nul rmdir /s /q "%TMP_DIR%" 2>nul
mkdir "%TMP_DIR%" || goto :fail_tmp mkdir "%TMP_DIR%" || goto :fail_tmp
echo Downloading the latest build... echo Looking up the latest build...
curl -fL --progress-bar -o "%TMP_DIR%\%ASSET%" "%URL%" || goto :fail_download set "SHA="
for /f "usebackq delims=" %%S in (`powershell -NoProfile -ExecutionPolicy Bypass -Command "$r = & curl.exe -fsSL --max-time 20 'https://github.com/%REPO%/commits/%BRANCH%.atom'; if ($r -match 'Commit/([0-9a-f]{40})') { $Matches[1] }"`) do set "SHA=%%S"
if not defined SHA goto :fail_download
set "URL=https://raw.githubusercontent.com/%REPO%/%SHA%/%ASSET%"
echo Downloading build %SHA:~0,7%...
curl -fL --progress-bar --max-time 1800 -o "%TMP_DIR%\%ASSET%" "%URL%" || goto :fail_download
echo Installing to %DEST% echo Installing to %DEST%
if not exist "%DEST%" mkdir "%DEST%" || goto :fail_dest if not exist "%DEST%" mkdir "%DEST%" || goto :fail_dest
rem Extracted over any existing install rather than replacing the folder, so
rem the progress files kept inside it survive an upgrade.
tar -xf "%TMP_DIR%\%ASSET%" -C "%DEST%" || goto :fail_extract tar -xf "%TMP_DIR%\%ASSET%" -C "%DEST%" || goto :fail_extract
rem Start menu entry, so the app can be found without digging for the folder.
set "LNK=%APPDATA%\Microsoft\Windows\Start Menu\Programs\maturita.C.lnk" set "LNK=%APPDATA%\Microsoft\Windows\Start Menu\Programs\maturita.C.lnk"
powershell -NoProfile -ExecutionPolicy Bypass -Command ^ powershell -NoProfile -ExecutionPolicy Bypass -Command ^
"$s=(New-Object -ComObject WScript.Shell).CreateShortcut('%LNK%');" ^ "$s=(New-Object -ComObject WScript.Shell).CreateShortcut('%LNK%');" ^

View file

@ -1,5 +1,7 @@
#include "maturita.h" #include "maturita.h"
#include <string.h>
#ifdef _WIN32 #ifdef _WIN32
#include <process.h> #include <process.h>
#define update_getpid() ((long)_getpid()) #define update_getpid() ((long)_getpid())
@ -23,9 +25,14 @@
* the repository, which CI rewrites on every change to main, so an update is * the repository, which CI rewrites on every change to main, so an update is
* simply whatever that branch currently holds. The branch also carries a * simply whatever that branch currently holds. The branch also carries a
* VERSION file naming the commit its packages were built from; comparing that * VERSION file naming the commit its packages were built from; comparing that
* against the commit baked into this binary is the whole check. Serving it * against the commit baked into this binary is the whole check.
* from raw.githubusercontent.com avoids the REST API and its unauthenticated *
* rate limit, and needs no JSON parser. * raw.githubusercontent.com is cached by Fastly by branch name, so a URL that
* says `/builds/VERSION` can keep serving yesterday's file after CI rewrote
* the branch. The check therefore reads the branch tip from the Atom feed
* (plain curl, no API token) and then fetches VERSION and the package from
* that commit SHA. Serving files from raw.githubusercontent.com still avoids
* the REST API and its unauthenticated rate limit, and needs no JSON parser.
* *
* An application cannot reliably replace its own files while it is running, so * An application cannot reliably replace its own files while it is running, so
* all three platforms follow the same shape: unpack the new version into a * all three platforms follow the same shape: unpack the new version into a
@ -34,9 +41,8 @@
* script detached and quit. Staging beside the install keeps the final move on * script detached and quit. Staging beside the install keeps the final move on
* one filesystem and proves up front that the location is writable. */ * one filesystem and proves up front that the location is writable. */
#define UPDATE_BASE_URL "https://raw.githubusercontent.com/" UPDATE_REPO \ #define UPDATE_ATOM_URL "https://github.com/" UPDATE_REPO \
"/" UPDATE_BRANCH "/" "/commits/" UPDATE_BRANCH ".atom"
#define UPDATE_VERSION_URL UPDATE_BASE_URL "VERSION"
#define UPDATE_STAGING_DIR ".maturita-update" #define UPDATE_STAGING_DIR ".maturita-update"
#ifdef _WIN32 #ifdef _WIN32
@ -68,6 +74,7 @@ typedef enum {
static struct { static struct {
UpdateState state; UpdateState state;
gboolean interactive; /* user asked, so also report "up to date" */ gboolean interactive; /* user asked, so also report "up to date" */
char *tip; /* current commit of the builds branch itself */
char *latest; /* commit the published packages were built from */ char *latest; /* commit the published packages were built from */
char *staging; /* scratch directory beside the install */ char *staging; /* scratch directory beside the install */
char *archive; /* asset downloaded into the staging directory */ char *archive; /* asset downloaded into the staging directory */
@ -114,6 +121,35 @@ static char *parse_commit(const char *text) {
return NULL; return NULL;
} }
/* First Grit::Commit/<40-hex> in a GitHub Atom feed is the branch tip. */
static char *parse_atom_commit(const char *text) {
const char *p;
if (!text)
return NULL;
p = strstr(text, "Commit/");
while (p) {
const char *s = p + 7;
size_t n = 0;
while (g_ascii_isxdigit(s[n]))
n++;
if (n == 40)
return g_strndup(s, 40);
p = strstr(s, "Commit/");
}
return NULL;
}
/* Pin raw.githubusercontent.com to a commit so Fastly cannot serve a stale
* branch-named file. Falls back to the branch name if the tip is unknown. */
static char *builds_raw_url(const char *name) {
const char *ref = (up.tip && up.tip[0]) ? up.tip : UPDATE_BRANCH;
return g_strdup_printf("https://raw.githubusercontent.com/%s/%s/%s",
UPDATE_REPO, ref, name);
}
static gboolean same_commit(const char *a, const char *b) { static gboolean same_commit(const char *a, const char *b) {
char *ca = parse_commit(a); char *ca = parse_commit(a);
char *cb = parse_commit(b); char *cb = parse_commit(b);
@ -614,7 +650,7 @@ static void size_probe_done(GObject *src, GAsyncResult *res, gpointer data) {
if (up.state != UPDATE_DOWNLOADING) if (up.state != UPDATE_DOWNLOADING)
return; return;
url = g_strconcat(UPDATE_BASE_URL, asset_name(), NULL); url = builds_raw_url(asset_name());
argv[0] = "curl"; argv[0] = "curl";
argv[1] = "-fsSL"; argv[1] = "-fsSL";
argv[2] = "--max-time"; argv[2] = "--max-time";
@ -663,7 +699,7 @@ static void update_start_download(void) {
update_set_state(UPDATE_DOWNLOADING); update_set_state(UPDATE_DOWNLOADING);
/* HEAD the asset with its headers on stdout, to size the progress bar. */ /* HEAD the asset with its headers on stdout, to size the progress bar. */
url = g_strconcat(UPDATE_BASE_URL, asset_name(), NULL); url = builds_raw_url(asset_name());
argv[0] = "curl"; argv[0] = "curl";
argv[1] = "-fsSLI"; argv[1] = "-fsSLI";
argv[2] = "--max-time"; argv[2] = "--max-time";
@ -729,9 +765,41 @@ static void check_done(GObject *src, GAsyncResult *res, gpointer data) {
update_set_state(UPDATE_IDLE); update_set_state(UPDATE_IDLE);
} }
void update_check_async(gboolean interactive) { static void tip_done(GObject *src, GAsyncResult *res, gpointer data) {
const char *argv[8]; GSubprocess *proc = G_SUBPROCESS(src);
char *out = NULL;
gboolean ok;
char *url; char *url;
const char *argv[6];
(void)data;
g_subprocess_communicate_utf8_finish(proc, res, &out, NULL, NULL);
ok = g_subprocess_get_successful(proc);
g_object_unref(proc);
g_free(up.tip);
up.tip = (ok && out) ? parse_atom_commit(out) : NULL;
g_free(out);
if (!up.tip) {
check_giveup();
return;
}
url = builds_raw_url("VERSION");
argv[0] = "curl";
argv[1] = "-fsSL";
argv[2] = "--max-time";
argv[3] = "20";
argv[4] = url;
argv[5] = NULL;
if (!curl_async(argv, check_done))
check_giveup();
g_free(url);
}
void update_check_async(gboolean interactive) {
const char *argv[6];
if (up.state == UPDATE_CHECKING || up.state == UPDATE_DOWNLOADING || if (up.state == UPDATE_CHECKING || up.state == UPDATE_DOWNLOADING ||
up.state == UPDATE_STAGED) up.state == UPDATE_STAGED)
@ -748,25 +816,19 @@ void update_check_async(gboolean interactive) {
update_set_state(UPDATE_CHECKING); update_set_state(UPDATE_CHECKING);
/* raw.githubusercontent.com caches VERSION; a unique query bypasses it. */
url = g_strdup_printf("%s?t=%ld", UPDATE_VERSION_URL,
(long)g_get_real_time());
argv[0] = "curl"; argv[0] = "curl";
argv[1] = "-fsSL"; argv[1] = "-fsSL";
argv[2] = "--max-time"; argv[2] = "--max-time";
argv[3] = "20"; argv[3] = "20";
argv[4] = "-H"; argv[4] = UPDATE_ATOM_URL;
argv[5] = "Cache-Control: no-cache"; argv[5] = NULL;
argv[6] = url;
argv[7] = NULL;
if (!curl_async(argv, check_done)) { if (!curl_async(argv, tip_done)) {
if (interactive) if (interactive)
update_fail(tr("update_err_curl")); update_fail(tr("update_err_curl"));
else else
update_set_state(UPDATE_IDLE); update_set_state(UPDATE_IDLE);
} }
g_free(url);
} }
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */