mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-24 09:57:08 -06:00
packaging: use [[ for bash conditional tests (SonarCloud S7688) (#8914)
* packaging: use [[ for bash conditional tests (SonarCloud S7688) SonarCloud flags every bare [ conditional in bash scripts under packaging/ as a reliability smell (rule S7688). Convert the flagged [ ... ] tests to [[ ... ]]: safer word-splitting and no glob surprises, same semantics for these string and file tests. * packaging/web: parse size overrides as base 10 under [[
This commit is contained in:
+6
-6
@@ -22,7 +22,7 @@ workspace_version() {
|
||||
}
|
||||
|
||||
VERSION="${PHOTOCRAFT_VERSION:-$(workspace_version)}"
|
||||
if [ -z "$VERSION" ]; then
|
||||
if [[ -z "$VERSION" ]]; then
|
||||
echo "error: could not read [workspace.package] version from $ROOT/Cargo.toml" >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -32,7 +32,7 @@ DIST="${DIST:-$ROOT/dist/release}"
|
||||
mkdir -p "$DIST"
|
||||
export DIST
|
||||
|
||||
if [ -z "${PHOTOCRAFT_BUILD_SHA:-}" ]; then
|
||||
if [[ -z "${PHOTOCRAFT_BUILD_SHA:-}" ]]; then
|
||||
PHOTOCRAFT_BUILD_SHA="$(git -C "$ROOT" rev-parse HEAD 2>/dev/null || true)"
|
||||
fi
|
||||
export PHOTOCRAFT_BUILD_SHA
|
||||
@@ -41,14 +41,14 @@ export CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$ROOT/target}"
|
||||
|
||||
# Emit a GitHub Actions warning (plain stderr outside Actions).
|
||||
warn() {
|
||||
if [ -n "${GITHUB_ACTIONS:-}" ]; then echo "::warning::$*"; else echo "warning: $*" >&2; fi
|
||||
if [[ -n "${GITHUB_ACTIONS:-}" ]]; then echo "::warning::$*"; else echo "warning: $*" >&2; fi
|
||||
}
|
||||
|
||||
# Copy licence and readme files that exist into a package directory.
|
||||
copy_docs() {
|
||||
local dest="$1" f
|
||||
for f in README.md LICENSE LICENSE-MIT LICENSE-APACHE COPYRIGHT; do
|
||||
if [ -f "$ROOT/$f" ]; then cp "$ROOT/$f" "$dest/"; fi
|
||||
if [[ -f "$ROOT/$f" ]]; then cp "$ROOT/$f" "$dest/"; fi
|
||||
done
|
||||
copy_font_licences "$dest"
|
||||
}
|
||||
@@ -57,9 +57,9 @@ copy_docs() {
|
||||
# are OFL-1.1: ship each font's licence as OFL-<family-dir>.txt. No-op without CRAFT_FONTS_DIR.
|
||||
copy_font_licences() {
|
||||
local dest="$1" lic fam
|
||||
[ -n "${CRAFT_FONTS_DIR:-}" ] || return 0
|
||||
[[ -n "${CRAFT_FONTS_DIR:-}" ]] || return 0
|
||||
for lic in "$CRAFT_FONTS_DIR"/fonts/*/OFL.txt; do
|
||||
[ -f "$lic" ] || continue
|
||||
[[ -f "$lic" ]] || continue
|
||||
fam="$(basename "$(dirname "$lic")")"
|
||||
cp "$lic" "$dest/OFL-$fam.txt"
|
||||
done
|
||||
|
||||
@@ -20,7 +20,7 @@ APP_ID=ai.storyteller.photocraft
|
||||
|
||||
SKIP_BUILD=0
|
||||
DRY_RUN=0
|
||||
while [ $# -gt 0 ]; do
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--skip-build) SKIP_BUILD=1; shift ;;
|
||||
--dry-run) DRY_RUN=1; SKIP_BUILD=1; shift ;;
|
||||
@@ -36,7 +36,7 @@ case "$MACHINE" in
|
||||
arm64 | aarch64) ARCH=aarch64 ;;
|
||||
*) echo "unsupported architecture $MACHINE" >&2; exit 2 ;;
|
||||
esac
|
||||
if [ "$DRY_RUN" = 0 ] && [ "$(uname -s)" != FreeBSD ]; then
|
||||
if [[ "$DRY_RUN" = 0 ]] && [[ "$(uname -s)" != FreeBSD ]]; then
|
||||
echo "error: build on FreeBSD (or pass --dry-run to check the tree layout)" >&2
|
||||
exit 2
|
||||
fi
|
||||
@@ -46,7 +46,7 @@ echo "==> PhotoCraft $VERSION for FreeBSD $ARCH"
|
||||
|
||||
# The release VM has 12 GB; full parallelism on the biggest crates runs it out of memory.
|
||||
export CARGO_BUILD_JOBS="${CARGO_BUILD_JOBS:-4}"
|
||||
if [ "$SKIP_BUILD" = 0 ]; then
|
||||
if [[ "$SKIP_BUILD" = 0 ]]; then
|
||||
(cd "$ROOT" && cargo build --release --locked -p photocraft -p photocraft-cli --features heif)
|
||||
fi
|
||||
WORK="$CARGO_TARGET_DIR/freebsd-package"
|
||||
@@ -56,7 +56,7 @@ mkdir -p "$WORK"
|
||||
|
||||
BIN="$CARGO_TARGET_DIR/release"
|
||||
OUT_DIR="$DIST"
|
||||
if [ "$DRY_RUN" = 1 ]; then
|
||||
if [[ "$DRY_RUN" = 1 ]]; then
|
||||
# Stub binaries, and the tarball stays in the work dir so dist/ only ever holds real builds.
|
||||
BIN="$WORK/stub-bin"
|
||||
OUT_DIR="$WORK"
|
||||
@@ -81,13 +81,13 @@ sed -e "s/@VERSION@/$VERSION/g" -e "s/@DATE@/$PHOTOCRAFT_BUILD_DATE/g" \
|
||||
cp -R "$ROOT/assets/app-icon/hicolor" "$STAGE/share/icons/"
|
||||
copy_docs "$STAGE/share/doc/photocraft"
|
||||
for f in NOTICE ATTRIBUTION.md; do
|
||||
if [ -f "$ROOT/$f" ]; then install -m 644 "$ROOT/$f" "$STAGE/share/doc/photocraft/"; fi
|
||||
if [[ -f "$ROOT/$f" ]]; then install -m 644 "$ROOT/$f" "$STAGE/share/doc/photocraft/"; fi
|
||||
done
|
||||
|
||||
for f in bin/photocraft bin/photocraft-cli "share/applications/$APP_ID.desktop" \
|
||||
"share/icons/hicolor/256x256/apps/$APP_ID.png" "share/icons/hicolor/scalable/apps/$APP_ID.svg" \
|
||||
share/doc/photocraft/LICENSE-MIT share/doc/photocraft/LICENSE-APACHE; do
|
||||
if [ ! -e "$STAGE/$f" ]; then echo "error: $f is missing from the package" >&2; exit 1; fi
|
||||
if [[ ! -e "$STAGE/$f" ]]; then echo "error: $f is missing from the package" >&2; exit 1; fi
|
||||
done
|
||||
|
||||
# ---- .tar.gz ------------------------------------------------------------------------------------
|
||||
@@ -96,7 +96,7 @@ tar -C "$WORK" -czf "$OUT_DIR/$BASENAME.tar.gz" "$BASENAME"
|
||||
echo "wrote $OUT_DIR/$BASENAME.tar.gz"
|
||||
|
||||
"$STAGE/bin/photocraft-cli" --version
|
||||
if [ "$DRY_RUN" = 1 ]; then
|
||||
if [[ "$DRY_RUN" = 1 ]]; then
|
||||
echo "==> dry run: tarball contents"
|
||||
tar -tzvf "$OUT_DIR/$BASENAME.tar.gz"
|
||||
fi
|
||||
|
||||
@@ -37,10 +37,10 @@ fail() {
|
||||
|
||||
# 1. Launch works and passes arguments through.
|
||||
out="$("$APPDIR/AppRun" open file.png)" || fail "AppRun exited non-zero"
|
||||
[ "$out" = "stub: open file.png" ] || fail "arguments not forwarded: $out"
|
||||
[[ "$out" = "stub: open file.png" ]] || fail "arguments not forwarded: $out"
|
||||
|
||||
DESKTOP="$XDG_DATA_HOME/applications/$APP_ID.desktop"
|
||||
[ -f "$DESKTOP" ] || fail "desktop entry not installed"
|
||||
[[ -f "$DESKTOP" ]] || fail "desktop entry not installed"
|
||||
|
||||
# 2. Exec rewritten to the AppImage (quoted, spaces intact), TryExec dropped,
|
||||
# everything else preserved from the packaged entry.
|
||||
@@ -56,15 +56,15 @@ fi
|
||||
|
||||
# 3. Icons landed under the name the .desktop entry references.
|
||||
for f in "16x16/apps/$APP_ID.png" "256x256/apps/$APP_ID.png" "scalable/apps/$APP_ID.svg"; do
|
||||
[ -f "$XDG_DATA_HOME/icons/hicolor/$f" ] || fail "icon missing: $f"
|
||||
[[ -f "$XDG_DATA_HOME/icons/hicolor/$f" ]] || fail "icon missing: $f"
|
||||
done
|
||||
|
||||
# 4. Idempotent: a second launch must not rewrite anything (inode unchanged).
|
||||
before="$(stat -c %i "$DESKTOP")"
|
||||
out="$("$APPDIR/AppRun")" || fail "second launch exited non-zero"
|
||||
[ "$out" = "stub: " ] || fail "second launch output: $out"
|
||||
[[ "$out" = "stub: " ]] || fail "second launch output: $out"
|
||||
after="$(stat -c %i "$DESKTOP")"
|
||||
[ "$before" = "$after" ] || fail "desktop entry rewritten although unchanged"
|
||||
[[ "$before" = "$after" ]] || fail "desktop entry rewritten although unchanged"
|
||||
|
||||
# 5. Moving the AppImage refreshes Exec.
|
||||
mv "$APPIMAGE" "$TMP/moved.AppImage"
|
||||
@@ -78,9 +78,9 @@ grep -Fxq "Exec=\"$(readlink -f "$APPIMAGE")\" %F" "$DESKTOP" || fail "Exec not
|
||||
ext_desktop="$XDG_DATA_HOME/applications/appimagekit-photocraft.desktop"
|
||||
printf '[Desktop Entry]\nType=Application\nName=PhotoCraft\nExec="%s" %%F\nIcon=%s\n' "$(readlink -f "$APPIMAGE")" "$APP_ID" >"$ext_desktop"
|
||||
"$APPDIR/AppRun" >/dev/null || fail "launch with external integrator desktop entry exited non-zero"
|
||||
[ ! -e "$DESKTOP" ] || fail "duplicate desktop entry kept alongside external integrator entry"
|
||||
[ -f "$ext_desktop" ] || fail "external integrator desktop entry removed"
|
||||
[ -f "$XDG_DATA_HOME/icons/hicolor/256x256/apps/$APP_ID.png" ] || fail "icons missing with external integrator"
|
||||
[[ ! -e "$DESKTOP" ]] || fail "duplicate desktop entry kept alongside external integrator entry"
|
||||
[[ -f "$ext_desktop" ]] || fail "external integrator desktop entry removed"
|
||||
[[ -f "$XDG_DATA_HOME/icons/hicolor/256x256/apps/$APP_ID.png" ]] || fail "icons missing with external integrator"
|
||||
rm -f "$ext_desktop"
|
||||
|
||||
# 7. AppImageLauncher exports DESKTOPINTEGRATION even after X-AppImage-Integrate=false
|
||||
@@ -88,53 +88,53 @@ rm -f "$ext_desktop"
|
||||
# writes its own entry and a later launch must not delete it (#5534).
|
||||
rm -rf "$XDG_DATA_HOME"
|
||||
DESKTOPINTEGRATION=AppImageLauncher "$APPDIR/AppRun" >/dev/null || fail "DESKTOPINTEGRATION launch exited non-zero"
|
||||
[ -f "$DESKTOP" ] || fail "DESKTOPINTEGRATION suppressed the desktop entry (#5534)"
|
||||
[[ -f "$DESKTOP" ]] || fail "DESKTOPINTEGRATION suppressed the desktop entry (#5534)"
|
||||
grep -Fxq "Exec=\"$(readlink -f "$APPIMAGE")\" %F" "$DESKTOP" || fail "Exec missing under DESKTOPINTEGRATION"
|
||||
grep -Fxq "X-AppImage-Integrate=false" "$DESKTOP" || fail "X-AppImage-Integrate=false missing under DESKTOPINTEGRATION"
|
||||
[ -f "$XDG_DATA_HOME/icons/hicolor/256x256/apps/$APP_ID.png" ] || fail "icons not installed under DESKTOPINTEGRATION"
|
||||
[[ -f "$XDG_DATA_HOME/icons/hicolor/256x256/apps/$APP_ID.png" ]] || fail "icons not installed under DESKTOPINTEGRATION"
|
||||
before="$(stat -c %i "$DESKTOP")"
|
||||
DESKTOPINTEGRATION=AppImageLauncher "$APPDIR/AppRun" >/dev/null || fail "second DESKTOPINTEGRATION launch exited non-zero"
|
||||
[ -f "$DESKTOP" ] || fail "DESKTOPINTEGRATION removed the desktop entry on a later launch"
|
||||
[ "$before" = "$(stat -c %i "$DESKTOP")" ] || fail "desktop entry rewritten under DESKTOPINTEGRATION although unchanged"
|
||||
[[ -f "$DESKTOP" ]] || fail "DESKTOPINTEGRATION removed the desktop entry on a later launch"
|
||||
[[ "$before" = "$(stat -c %i "$DESKTOP")" ]] || fail "desktop entry rewritten under DESKTOPINTEGRATION although unchanged"
|
||||
# A real integrator entry still wins, including when DESKTOPINTEGRATION is also set (#3623).
|
||||
ext_desktop="$XDG_DATA_HOME/applications/appimagekit-photocraft.desktop"
|
||||
printf '[Desktop Entry]\nType=Application\nName=PhotoCraft\nExec="%s" %%F\nIcon=%s\n' "$(readlink -f "$APPIMAGE")" "$APP_ID" >"$ext_desktop"
|
||||
DESKTOPINTEGRATION=AppImageLauncher "$APPDIR/AppRun" >/dev/null || fail "launch with integrator entry and DESKTOPINTEGRATION exited non-zero"
|
||||
[ ! -e "$DESKTOP" ] || fail "duplicate desktop entry kept when an integrator entry exists"
|
||||
[ -f "$ext_desktop" ] || fail "external integrator desktop entry removed"
|
||||
[ -f "$XDG_DATA_HOME/icons/hicolor/256x256/apps/$APP_ID.png" ] || fail "icons missing when DESKTOPINTEGRATION and an integrator entry coexist"
|
||||
[[ ! -e "$DESKTOP" ]] || fail "duplicate desktop entry kept when an integrator entry exists"
|
||||
[[ -f "$ext_desktop" ]] || fail "external integrator desktop entry removed"
|
||||
[[ -f "$XDG_DATA_HOME/icons/hicolor/256x256/apps/$APP_ID.png" ]] || fail "icons missing when DESKTOPINTEGRATION and an integrator entry coexist"
|
||||
rm -f "$ext_desktop"
|
||||
|
||||
# 8. Opt-out installs nothing.
|
||||
rm -rf "$XDG_DATA_HOME"
|
||||
PHOTOCRAFT_NO_DESKTOP_INTEGRATION=1 "$APPDIR/AppRun" >/dev/null || fail "opt-out launch exited non-zero"
|
||||
[ ! -e "$XDG_DATA_HOME" ] || fail "opt-out still integrated"
|
||||
[[ ! -e "$XDG_DATA_HOME" ]] || fail "opt-out still integrated"
|
||||
|
||||
# 9. An unwritable data dir never blocks the launch.
|
||||
mkdir -p "$TMP/ro" && chmod a-w "$TMP/ro"
|
||||
out="$(XDG_DATA_HOME="$TMP/ro/data" "$APPDIR/AppRun" out.txt)" || fail "launch blocked by unwritable data dir"
|
||||
[ "$out" = "stub: out.txt" ] || fail "stub not run against unwritable data dir: $out"
|
||||
[[ "$out" = "stub: out.txt" ]] || fail "stub not run against unwritable data dir: $out"
|
||||
chmod u+w "$TMP/ro"
|
||||
|
||||
# 10. No $APPIMAGE (extracted AppDir): launch only, nothing installed.
|
||||
rm -rf "$XDG_DATA_HOME"
|
||||
env -u APPIMAGE "$APPDIR/AppRun" >/dev/null || fail "extracted-AppDir launch exited non-zero"
|
||||
[ ! -e "$XDG_DATA_HOME" ] || fail "integrated without $APPIMAGE"
|
||||
[[ ! -e "$XDG_DATA_HOME" ]] || fail "integrated without $APPIMAGE"
|
||||
|
||||
# 11. A path that would need Exec escaping (here a `$`): launch only, nothing installed.
|
||||
rm -rf "$XDG_DATA_HOME"
|
||||
odd="$TMP/odd\$(id).AppImage"
|
||||
: >"$odd"
|
||||
out="$(APPIMAGE="$odd" "$APPDIR/AppRun" x)" || fail "launch with an odd path exited non-zero"
|
||||
[ "$out" = "stub: x" ] || fail "odd path: $out"
|
||||
[ ! -e "$XDG_DATA_HOME" ] || fail "integrated an AppImage path that needs escaping"
|
||||
[[ "$out" = "stub: x" ]] || fail "odd path: $out"
|
||||
[[ ! -e "$XDG_DATA_HOME" ]] || fail "integrated an AppImage path that needs escaping"
|
||||
|
||||
# 12. AM / AppMan (#6392): a photocraft-AM.desktop launcher in the user's applications
|
||||
# dir owns the menu entry. AppRun removes its own entry left from an earlier run,
|
||||
# writes no second one and still installs the icons.
|
||||
rm -rf "$XDG_DATA_HOME"
|
||||
"$APPDIR/AppRun" >/dev/null || fail "launch before AM install exited non-zero"
|
||||
[ -f "$DESKTOP" ] || fail "no desktop entry before AM install"
|
||||
[[ -f "$DESKTOP" ]] || fail "no desktop entry before AM install"
|
||||
am_desktop="$XDG_DATA_HOME/applications/photocraft-AM.desktop"
|
||||
printf '[Desktop Entry]
|
||||
Type=Application
|
||||
@@ -143,13 +143,13 @@ Exec=photocraft %%F
|
||||
Icon=%s
|
||||
' "$APP_ID" >"$am_desktop"
|
||||
"$APPDIR/AppRun" >/dev/null || fail "launch with AM launcher exited non-zero"
|
||||
[ ! -e "$DESKTOP" ] || fail "duplicate desktop entry kept alongside AM launcher (#6392)"
|
||||
[ -f "$am_desktop" ] || fail "AM launcher was removed"
|
||||
[ -f "$XDG_DATA_HOME/icons/hicolor/256x256/apps/$APP_ID.png" ] || fail "icons missing with AM launcher"
|
||||
[[ ! -e "$DESKTOP" ]] || fail "duplicate desktop entry kept alongside AM launcher (#6392)"
|
||||
[[ -f "$am_desktop" ]] || fail "AM launcher was removed"
|
||||
[[ -f "$XDG_DATA_HOME/icons/hicolor/256x256/apps/$APP_ID.png" ]] || fail "icons missing with AM launcher"
|
||||
|
||||
# 13. Once AM removes its launcher, AppRun writes its own entry again.
|
||||
rm -f "$am_desktop"
|
||||
"$APPDIR/AppRun" >/dev/null || fail "launch after AM removal exited non-zero"
|
||||
[ -f "$DESKTOP" ] || fail "no desktop entry after the AM launcher was removed"
|
||||
[[ -f "$DESKTOP" ]] || fail "no desktop entry after the AM launcher was removed"
|
||||
|
||||
echo "AppRun desktop integration ok"
|
||||
|
||||
@@ -21,7 +21,7 @@ FLATHUB=https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||
|
||||
TEST=1
|
||||
TARBALL=""
|
||||
while [ $# -gt 0 ]; do
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--no-test) TEST=0; shift ;;
|
||||
-h | --help) sed -n '2,14p' "$0"; exit 0 ;;
|
||||
@@ -38,7 +38,7 @@ case "$ARCH" in
|
||||
esac
|
||||
BASENAME="photocraft-$VERSION-linux-$ARCH"
|
||||
TARBALL="${TARBALL:-$DIST/$BASENAME.tar.gz}"
|
||||
[ -f "$TARBALL" ] || { echo "error: $TARBALL not found (run packaging/linux/package.sh --formats tar first)" >&2; exit 1; }
|
||||
[[ -f "$TARBALL" ]] || { echo "error: $TARBALL not found (run packaging/linux/package.sh --formats tar first)" >&2; exit 1; }
|
||||
for tool in flatpak flatpak-builder; do
|
||||
command -v "$tool" >/dev/null || { echo "error: $tool not found (apt install flatpak flatpak-builder librsvg2-common)" >&2; exit 1; }
|
||||
done
|
||||
@@ -49,7 +49,7 @@ WORK="$CARGO_TARGET_DIR/flatpak-bundle"
|
||||
rm -rf "$WORK"
|
||||
mkdir -p "$WORK/stage"
|
||||
tar -xzf "$TARBALL" -C "$WORK/stage" --strip-components=1
|
||||
[ -x "$WORK/stage/bin/photocraft" ] || { echo "error: $TARBALL has no bin/photocraft" >&2; exit 1; }
|
||||
[[ -x "$WORK/stage/bin/photocraft" ]] || { echo "error: $TARBALL has no bin/photocraft" >&2; exit 1; }
|
||||
cp "$HERE/flatpak/$APP_ID.bundle.yml" "$WORK/$APP_ID.yml"
|
||||
|
||||
flatpak remote-add --user --if-not-exists flathub "$FLATHUB"
|
||||
@@ -62,7 +62,7 @@ OUT="$DIST/$BASENAME.flatpak"
|
||||
flatpak build-bundle --runtime-repo="$FLATHUB" "$WORK/repo" "$OUT" "$APP_ID" stable
|
||||
echo "wrote $OUT"
|
||||
|
||||
if [ "$TEST" = 1 ]; then
|
||||
if [[ "$TEST" = 1 ]]; then
|
||||
flatpak install --user -y --noninteractive --reinstall "$OUT"
|
||||
flatpak info --user "$APP_ID"
|
||||
flatpak run --command=photocraft-cli "$APP_ID" --version
|
||||
|
||||
@@ -27,7 +27,7 @@ APP_ID=ai.storyteller.photocraft
|
||||
|
||||
SKIP_BUILD=0
|
||||
FORMATS="appimage deb rpm tar"
|
||||
while [ $# -gt 0 ]; do
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--skip-build) SKIP_BUILD=1; shift ;;
|
||||
--formats) FORMATS="$2"; shift 2 ;;
|
||||
@@ -48,8 +48,8 @@ BASENAME="photocraft-$VERSION-linux-$ARCH"
|
||||
|
||||
echo "==> PhotoCraft $VERSION for Linux $ARCH ($FORMATS)"
|
||||
|
||||
if [ "$SKIP_BUILD" = 0 ]; then
|
||||
if [ -n "${CROSS_TARGET:-}" ]; then
|
||||
if [[ "$SKIP_BUILD" = 0 ]]; then
|
||||
if [[ -n "${CROSS_TARGET:-}" ]]; then
|
||||
(cd "$ROOT" && cargo build --release --locked -p photocraft -p photocraft-cli --features heif --target "$CROSS_TARGET")
|
||||
else
|
||||
(cd "$ROOT" && cargo build --release --locked -p photocraft -p photocraft-cli --features heif)
|
||||
@@ -136,7 +136,7 @@ if has appimage; then
|
||||
esac
|
||||
mkdir -p "$CARGO_TARGET_DIR"
|
||||
TOOL="${APPIMAGETOOL:-$CARGO_TARGET_DIR/appimagetool-$TOOL_VERSION-$ARCH.AppImage}"
|
||||
if [ -n "${APPIMAGETOOL:-}" ]; then
|
||||
if [[ -n "${APPIMAGETOOL:-}" ]]; then
|
||||
verify_appimagetool_override "$TOOL" "$TOOL_SHA256" "$TOOL_VERSION" "$ARCH"
|
||||
else
|
||||
download_verified \
|
||||
@@ -167,16 +167,16 @@ if has appimage; then
|
||||
(cd "$DIST" && ARCH="$ARCH" APPIMAGE_EXTRACT_AND_RUN=1 "$TOOL" --no-appstream \
|
||||
--runtime-file "$RUNTIME" -u "$UPDATE_INFO" "$APPDIR" "$OUT")
|
||||
echo "wrote $OUT"
|
||||
if [ -s "$OUT.zsync" ]; then
|
||||
if [[ -s "$OUT.zsync" ]]; then
|
||||
echo "wrote $OUT.zsync"
|
||||
else
|
||||
warn "zsyncmake not found, so $OUT.zsync was not written; AppImage delta updates need it"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "${CROSS_TARGET:-}" ]; then
|
||||
if [[ -z "${CROSS_TARGET:-}" ]]; then
|
||||
"$STAGE/usr/bin/photocraft-cli" --version
|
||||
elif [ -n "${EMULATOR:-}" ]; then
|
||||
elif [[ -n "${EMULATOR:-}" ]]; then
|
||||
"$EMULATOR" "$STAGE/usr/bin/photocraft-cli" --version
|
||||
fi
|
||||
echo "==> done"
|
||||
|
||||
@@ -22,7 +22,7 @@ expected="$(sha256 "$source_asset")"
|
||||
cp "$source_asset" "$cache"
|
||||
/bin/chmod 644 "$cache"
|
||||
download_verified "file://$TMP/unavailable" "$cache" "$expected" true || fail "offline cache was not reused"
|
||||
[ -x "$cache" ] || fail "valid preseed did not become executable"
|
||||
[[ -x "$cache" ]] || fail "valid preseed did not become executable"
|
||||
|
||||
# If a valid but non-executable cache cannot be chmod'd, fail here rather than at invocation.
|
||||
/bin/chmod 644 "$cache"
|
||||
@@ -44,27 +44,27 @@ cp "$source_asset" "$runtime"
|
||||
chmod() { fail "chmod called for a readable runtime cache"; }
|
||||
download_verified "file://$TMP/unavailable" "$runtime" "$expected" || fail "readable runtime was not reused"
|
||||
unset -f chmod
|
||||
[ ! -x "$runtime" ] || fail "runtime was needlessly made executable"
|
||||
[[ ! -x "$runtime" ]] || fail "runtime was needlessly made executable"
|
||||
|
||||
# A fresh runtime download is verified, readable data rather than an executable program.
|
||||
fresh_runtime="$TMP/fresh-runtime"
|
||||
download_verified "file://$source_asset" "$fresh_runtime" "$expected" || fail "fresh runtime download failed"
|
||||
cmp -s "$source_asset" "$fresh_runtime" || fail "fresh runtime differs from verified asset"
|
||||
[ -r "$fresh_runtime" ] || fail "fresh runtime is not readable"
|
||||
[ ! -x "$fresh_runtime" ] || fail "fresh runtime was made executable"
|
||||
[[ -r "$fresh_runtime" ]] || fail "fresh runtime is not readable"
|
||||
[[ ! -x "$fresh_runtime" ]] || fail "fresh runtime was made executable"
|
||||
mode="$(stat -c %a "$fresh_runtime" 2>/dev/null || stat -f %Lp "$fresh_runtime")"
|
||||
[ "$mode" = 644 ] || fail "fresh runtime mode is $mode, expected 644"
|
||||
[[ "$mode" = 644 ]] || fail "fresh runtime mode is $mode, expected 644"
|
||||
|
||||
# A corrupt cache is replaced only by bytes with the pinned digest.
|
||||
printf 'corrupt' >"$cache"
|
||||
download_verified "file://$source_asset" "$cache" "$expected" true || fail "corrupt cache was not replaced"
|
||||
cmp -s "$source_asset" "$cache" || fail "replacement differs from verified asset"
|
||||
[ -x "$cache" ] || fail "replacement is not executable"
|
||||
[[ -x "$cache" ]] || fail "replacement is not executable"
|
||||
|
||||
wrong_digest="$(printf '%064d' 0)"
|
||||
bad="$TMP/bad.AppImage"
|
||||
if download_verified "file://$source_asset" "$bad" "$wrong_digest" >/dev/null 2>&1; then fail "wrong digest accepted"; fi
|
||||
[ ! -e "$bad" ] || fail "wrong-digest download left a cache entry"
|
||||
[[ ! -e "$bad" ]] || fail "wrong-digest download left a cache entry"
|
||||
|
||||
verify_appimagetool_override "$cache" "$expected" 1.9.1 x86_64 || fail "valid override rejected"
|
||||
/bin/chmod 644 "$cache"
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
download_verified() {
|
||||
local url="$1" dest="$2" expected="$3" executable="${4:-false}" tmp
|
||||
if [ -f "$dest" ] && [ "$(sha256 "$dest")" = "$expected" ]; then
|
||||
if [ "$executable" = true ] && [ ! -x "$dest" ] && ! chmod 755 "$dest"; then
|
||||
if [[ -f "$dest" ]] && [[ "$(sha256 "$dest")" = "$expected" ]]; then
|
||||
if [[ "$executable" = true ]] && [[ ! -x "$dest" ]] && ! chmod 755 "$dest"; then
|
||||
echo "error: verified asset is not executable and cannot be chmod'd: $dest" >&2
|
||||
return 1
|
||||
fi
|
||||
@@ -13,12 +13,12 @@ download_verified() {
|
||||
fi
|
||||
tmp="$(mktemp "$dest.XXXXXX")"
|
||||
if ! curl -fsSL -o "$tmp" "$url"; then rm -f "$tmp"; return 1; fi
|
||||
if [ "$(sha256 "$tmp")" != "$expected" ]; then
|
||||
if [[ "$(sha256 "$tmp")" != "$expected" ]]; then
|
||||
echo "error: SHA-256 mismatch for $url" >&2
|
||||
rm -f "$tmp"
|
||||
return 1
|
||||
fi
|
||||
if [ "$executable" = true ]; then
|
||||
if [[ "$executable" = true ]]; then
|
||||
if ! chmod 755 "$tmp"; then rm -f "$tmp"; return 1; fi
|
||||
else
|
||||
if ! chmod 644 "$tmp"; then rm -f "$tmp"; return 1; fi
|
||||
@@ -28,11 +28,11 @@ download_verified() {
|
||||
|
||||
verify_appimagetool_override() {
|
||||
local tool="$1" expected="$2" version="$3" arch="$4"
|
||||
if [ ! -f "$tool" ] || [ "$(sha256 "$tool")" != "$expected" ]; then
|
||||
if [[ ! -f "$tool" ]] || [[ "$(sha256 "$tool")" != "$expected" ]]; then
|
||||
echo "error: APPIMAGETOOL must be the verified $version $arch release asset" >&2
|
||||
return 1
|
||||
fi
|
||||
if [ ! -x "$tool" ]; then
|
||||
if [[ ! -x "$tool" ]]; then
|
||||
echo "error: APPIMAGETOOL must be executable (chmod +x $tool)" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -12,7 +12,7 @@ umask 077
|
||||
# shellcheck source=../env.sh
|
||||
. "$(dirname "${BASH_SOURCE[0]}")/../env.sh"
|
||||
|
||||
if [ -z "${APPLE_CERTIFICATE:-}" ]; then
|
||||
if [[ -z "${APPLE_CERTIFICATE:-}" ]]; then
|
||||
warn "APPLE_CERTIFICATE is not set: macOS builds will be ad-hoc signed and not notarized"
|
||||
exit 0
|
||||
fi
|
||||
@@ -36,13 +36,13 @@ security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KC_PASS"
|
||||
security list-keychains -d user -s "$KEYCHAIN" $(security list-keychains -d user | tr -d '"')
|
||||
|
||||
IDENTITY="$(security find-identity -v -p codesigning "$KEYCHAIN" | awk '/Developer ID Application/ { print $2; exit }')"
|
||||
if [ -z "$IDENTITY" ]; then
|
||||
if [[ -z "$IDENTITY" ]]; then
|
||||
security find-identity -v -p codesigning "$KEYCHAIN" >&2
|
||||
echo "error: no 'Developer ID Application' identity in APPLE_CERTIFICATE" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Imported signing identity $IDENTITY"
|
||||
if [ -n "${GITHUB_ENV:-}" ]; then
|
||||
if [[ -n "${GITHUB_ENV:-}" ]]; then
|
||||
{ echo "MACOS_SIGN_IDENTITY=$IDENTITY"; echo "MACOS_KEYCHAIN=$KEYCHAIN"; } >>"$GITHUB_ENV"
|
||||
else
|
||||
echo "MACOS_SIGN_IDENTITY=$IDENTITY"
|
||||
|
||||
+12
-12
@@ -19,7 +19,7 @@ HERE="$ROOT/packaging/macos"
|
||||
|
||||
ARCH=universal
|
||||
SKIP_BUILD=0
|
||||
while [ $# -gt 0 ]; do
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--arch) ARCH="$2"; shift 2 ;;
|
||||
--skip-build) SKIP_BUILD=1; shift ;;
|
||||
@@ -44,9 +44,9 @@ DMG="$DIST/photocraft-$VERSION-macos-$ARCH.dmg"
|
||||
CLI_ZIP="$DIST/photocraft-cli-$VERSION-macos-$ARCH.zip"
|
||||
|
||||
NOTARIZE=0
|
||||
if [ "$IDENTITY" = "-" ]; then
|
||||
if [[ "$IDENTITY" = "-" ]]; then
|
||||
warn "macOS: ad-hoc signing (no MACOS_SIGN_IDENTITY); artifacts are not notarized"
|
||||
elif [ -n "${APPLE_ID:-}" ] && [ -n "${APPLE_PASSWORD:-}" ] && [ -n "${APPLE_TEAM_ID:-}" ]; then
|
||||
elif [[ -n "${APPLE_ID:-}" ]] && [[ -n "${APPLE_PASSWORD:-}" ]] && [[ -n "${APPLE_TEAM_ID:-}" ]]; then
|
||||
NOTARIZE=1
|
||||
else
|
||||
warn "macOS: APPLE_ID / APPLE_PASSWORD / APPLE_TEAM_ID incomplete; signed but not notarized"
|
||||
@@ -55,7 +55,7 @@ fi
|
||||
echo "==> PhotoCraft $VERSION for macOS ($ARCH), identity: $IDENTITY, notarize: $NOTARIZE"
|
||||
|
||||
# ---- build -------------------------------------------------------------------------------------
|
||||
if [ "$SKIP_BUILD" = 0 ]; then
|
||||
if [[ "$SKIP_BUILD" = 0 ]]; then
|
||||
args=()
|
||||
for t in "${TARGETS[@]}"; do args+=(--target "$t"); done
|
||||
(cd "$ROOT" && cargo build --release --locked -p photocraft -p photocraft-cli --features heif "${args[@]}")
|
||||
@@ -74,9 +74,9 @@ done
|
||||
sign() {
|
||||
# Hardened runtime + secure timestamp for a real identity; ad-hoc can't be timestamped.
|
||||
local ts=(--timestamp)
|
||||
[ "$IDENTITY" = "-" ] && ts=(--timestamp=none)
|
||||
[[ "$IDENTITY" = "-" ]] && ts=(--timestamp=none)
|
||||
local kc=()
|
||||
[ -n "${MACOS_KEYCHAIN:-}" ] && kc=(--keychain "$MACOS_KEYCHAIN")
|
||||
[[ -n "${MACOS_KEYCHAIN:-}" ]] && kc=(--keychain "$MACOS_KEYCHAIN")
|
||||
codesign --force --sign "$IDENTITY" ${kc[@]+"${kc[@]}"} "${ts[@]}" "$@"
|
||||
}
|
||||
|
||||
@@ -88,8 +88,8 @@ notarize() {
|
||||
echo "$out"
|
||||
id="$(printf '%s' "$out" | plutil -extract id raw -o - - 2>/dev/null || true)"
|
||||
status="$(printf '%s' "$out" | plutil -extract status raw -o - - 2>/dev/null || true)"
|
||||
if [ "$status" != "Accepted" ]; then
|
||||
if [ -n "$id" ]; then
|
||||
if [[ "$status" != "Accepted" ]]; then
|
||||
if [[ -n "$id" ]]; then
|
||||
xcrun notarytool log "$id" --apple-id "$APPLE_ID" --password "$APPLE_PASSWORD" --team-id "$APPLE_TEAM_ID" || true
|
||||
fi
|
||||
echo "error: notarization of $(basename "$file") failed (status: ${status:-unknown})" >&2
|
||||
@@ -104,7 +104,7 @@ mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Resources"
|
||||
cp "$WORK/bin/photocraft" "$APP/Contents/MacOS/PhotoCraft"
|
||||
cp "$ROOT/assets/app-icon/photocraft.icns" "$APP/Contents/Resources/PhotoCraft.icns"
|
||||
# Licences of the embedded craft-fonts fonts (only when built with CRAFT_FONTS_DIR).
|
||||
if [ -n "${CRAFT_FONTS_DIR:-}" ]; then
|
||||
if [[ -n "${CRAFT_FONTS_DIR:-}" ]]; then
|
||||
mkdir -p "$APP/Contents/Resources/Licenses"
|
||||
copy_font_licences "$APP/Contents/Resources/Licenses"
|
||||
fi
|
||||
@@ -120,7 +120,7 @@ sign --options runtime --entitlements "$HERE/entitlements.plist" "$APP/Contents/
|
||||
sign --options runtime --entitlements "$HERE/entitlements.plist" "$APP"
|
||||
codesign --verify --strict --deep --verbose=2 "$APP"
|
||||
|
||||
if [ "$NOTARIZE" = 1 ]; then
|
||||
if [[ "$NOTARIZE" = 1 ]]; then
|
||||
ditto -c -k --keepParent "$APP" "$WORK/PhotoCraft-notarize.zip"
|
||||
notarize "$WORK/PhotoCraft-notarize.zip"
|
||||
xcrun stapler staple "$APP"
|
||||
@@ -147,7 +147,7 @@ hdiutil convert "$WORK/raw.dmg" -format UDZO -imagekey zlib-level=9 -o "$DMG"
|
||||
rm -f "$WORK/raw.dmg"
|
||||
sign "$DMG"
|
||||
codesign --verify --strict --verbose=2 "$DMG"
|
||||
if [ "$NOTARIZE" = 1 ]; then
|
||||
if [[ "$NOTARIZE" = 1 ]]; then
|
||||
notarize "$DMG"
|
||||
xcrun stapler staple "$DMG"
|
||||
xcrun stapler validate "$DMG"
|
||||
@@ -168,7 +168,7 @@ rm -f "$CLI_ZIP"
|
||||
ditto -c -k --keepParent "$CLI_DIR" "$CLI_ZIP"
|
||||
# notarytool accepts a zip of the bare binary. A bare Mach-O can't carry a stapled ticket, so
|
||||
# Gatekeeper looks the notarization up online when a quarantined copy first runs.
|
||||
if [ "$NOTARIZE" = 1 ]; then notarize "$CLI_ZIP"; fi
|
||||
if [[ "$NOTARIZE" = 1 ]]; then notarize "$CLI_ZIP"; fi
|
||||
|
||||
"$WORK/bin/photocraft-cli" --version
|
||||
echo "==> done (check the artifacts as shipped with packaging/macos/verify.sh --arch $ARCH)"
|
||||
|
||||
+12
-12
@@ -23,7 +23,7 @@ set -euo pipefail
|
||||
. "$(dirname "${BASH_SOURCE[0]}")/../env.sh"
|
||||
|
||||
ARCH=universal
|
||||
while [ $# -gt 0 ]; do
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--arch) ARCH="$2"; shift 2 ;;
|
||||
-h | --help) sed -n '2,20p' "$0"; exit 0 ;;
|
||||
@@ -41,13 +41,13 @@ DMG="$DIST/photocraft-$VERSION-macos-$ARCH.dmg"
|
||||
CLI_ZIP="$DIST/photocraft-cli-$VERSION-macos-$ARCH.zip"
|
||||
IDENTITY="${MACOS_SIGN_IDENTITY:--}"
|
||||
STRICT=0
|
||||
if [ "$IDENTITY" != "-" ] && [ -n "${APPLE_ID:-}" ] && [ -n "${APPLE_PASSWORD:-}" ] && [ -n "${APPLE_TEAM_ID:-}" ]; then
|
||||
if [[ "$IDENTITY" != "-" ]] && [[ -n "${APPLE_ID:-}" ]] && [[ -n "${APPLE_PASSWORD:-}" ]] && [[ -n "${APPLE_TEAM_ID:-}" ]]; then
|
||||
STRICT=1
|
||||
fi
|
||||
|
||||
FAILED=0
|
||||
fail() {
|
||||
if [ "$STRICT" = 1 ]; then
|
||||
if [[ "$STRICT" = 1 ]]; then
|
||||
echo "error: $*" >&2
|
||||
FAILED=1
|
||||
else
|
||||
@@ -58,20 +58,20 @@ fail() {
|
||||
# spctl's online ticket lookup can lag a few seconds behind notarytool's "Accepted".
|
||||
assess() {
|
||||
local out attempt tries=1
|
||||
[ "$STRICT" = 1 ] && tries=5
|
||||
[[ "$STRICT" = 1 ]] && tries=5
|
||||
for attempt in $(seq "$tries"); do
|
||||
if out="$(spctl "$@" 2>&1)"; then
|
||||
printf '%s\n' "$out"
|
||||
return 0
|
||||
fi
|
||||
[ "$attempt" = "$tries" ] || sleep 10
|
||||
[[ "$attempt" = "$tries" ]] || sleep 10
|
||||
done
|
||||
printf '%s\n' "$out"
|
||||
return 1
|
||||
}
|
||||
|
||||
for f in "$DMG" "$CLI_ZIP"; do
|
||||
if [ ! -f "$f" ]; then
|
||||
if [[ ! -f "$f" ]]; then
|
||||
echo "error: missing $f" >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -84,7 +84,7 @@ trap 'rm -rf "$WORK"' EXIT
|
||||
echo "==> $(basename "$CLI_ZIP")"
|
||||
ditto -x -k "$CLI_ZIP" "$WORK/cli"
|
||||
CLI="$WORK/cli/photocraft-cli-$VERSION-macos-$ARCH/photocraft-cli"
|
||||
if [ ! -x "$CLI" ]; then
|
||||
if [[ ! -x "$CLI" ]]; then
|
||||
echo "error: $(basename "$CLI_ZIP") has no executable photocraft-cli-$VERSION-macos-$ARCH/photocraft-cli" >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -108,7 +108,7 @@ printf '%s\n' "$details" | grep -q '^Authority=Developer ID Application:' \
|
||||
|| fail "photocraft-cli is not signed with a Developer ID Application identity"
|
||||
printf '%s\n' "$details" | grep -q '^Timestamp=' \
|
||||
|| fail "photocraft-cli signature has no secure timestamp"
|
||||
if [ -n "${APPLE_TEAM_ID:-}" ]; then
|
||||
if [[ -n "${APPLE_TEAM_ID:-}" ]]; then
|
||||
printf '%s\n' "$details" | grep -qx "TeamIdentifier=$APPLE_TEAM_ID" \
|
||||
|| fail "photocraft-cli is signed by a different team"
|
||||
fi
|
||||
@@ -125,24 +125,24 @@ fi
|
||||
# ---- DMG ---------------------------------------------------------------------------------------
|
||||
echo "==> $(basename "$DMG")"
|
||||
codesign --verify --strict --verbose=2 "$DMG"
|
||||
if [ "$STRICT" = 1 ]; then
|
||||
if [[ "$STRICT" = 1 ]]; then
|
||||
xcrun stapler validate "$DMG" || fail "no notarization ticket stapled to the DMG"
|
||||
assess --assess --type open --context context:primary-signature -vv "$DMG" \
|
||||
|| fail "Gatekeeper rejects the DMG"
|
||||
fi
|
||||
|
||||
if [ "$FAILED" != 0 ]; then
|
||||
if [[ "$FAILED" != 0 ]]; then
|
||||
echo "error: macOS artifacts failed verification" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$STRICT" = 1 ]; then
|
||||
if [[ "$STRICT" = 1 ]]; then
|
||||
result="signed (Developer ID, hardened runtime), notarized; DMG stapled"
|
||||
else
|
||||
result="signature intact; Developer ID and notarization not required (no signing secrets)"
|
||||
fi
|
||||
echo "==> verified: $result"
|
||||
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
|
||||
if [[ -n "${GITHUB_STEP_SUMMARY:-}" ]]; then
|
||||
{
|
||||
echo "- macOS \`$(basename "$DMG")\`, \`$(basename "$CLI_ZIP")\`: $result"
|
||||
} >>"$GITHUB_STEP_SUMMARY"
|
||||
|
||||
+13
-13
@@ -15,7 +15,7 @@ set -euo pipefail
|
||||
. "$(dirname "${BASH_SOURCE[0]}")/../env.sh"
|
||||
HERE="$ROOT/packaging/web"
|
||||
|
||||
if [ "${1:-}" != "--skip-build" ]; then
|
||||
if [[ "${1:-}" != "--skip-build" ]]; then
|
||||
command -v trunk >/dev/null || { echo "error: trunk not found (cargo install trunk --locked)" >&2; exit 1; }
|
||||
(cd "$ROOT/apps/photocraft-web" && trunk build --release)
|
||||
(cd "$ROOT/apps/photocraft-web-boot" && trunk build --release)
|
||||
@@ -24,7 +24,7 @@ fi
|
||||
APP="$ROOT/dist/web" # the app: index.html, wasm-bindgen glue, one .wasm
|
||||
BOOT="$ROOT/dist/web-boot" # the page that ships, and the module that starts the app from parts
|
||||
for site in "$APP" "$BOOT"; do
|
||||
[ -f "$site/index.html" ] || { echo "error: $site/index.html missing; run without --skip-build" >&2; exit 1; }
|
||||
[[ -f "$site/index.html" ]] || { echo "error: $site/index.html missing; run without --skip-build" >&2; exit 1; }
|
||||
# Paths must be relative so the site works under any prefix (public_url = "./" in Trunk.toml).
|
||||
if grep -Eq '(src|href)="/[^/]' "$site/index.html"; then
|
||||
echo "error: $site/index.html has root-absolute URLs; it would break when served from a sub-path" >&2
|
||||
@@ -35,23 +35,23 @@ done
|
||||
# Size limit (issues #198, #5302): Cloudflare Pages/Workers reject any single file over 25 MiB,
|
||||
# and other hosts and CDNs have similar caps. No file in the site may come near that; the app's
|
||||
# wasm, the one file that does, ships as parts of PART_BYTES. Override only to investigate.
|
||||
MAX_FILE_BYTES="${PHOTOCRAFT_WEB_MAX_FILE_BYTES:-25165824}" # 24 MiB
|
||||
PART_BYTES="${PHOTOCRAFT_WEB_PART_BYTES:-20971520}" # 20 MiB
|
||||
if [ "$PART_BYTES" -le 0 ] || [ "$PART_BYTES" -gt "$MAX_FILE_BYTES" ]; then
|
||||
MAX_FILE_BYTES=$((10#${PHOTOCRAFT_WEB_MAX_FILE_BYTES:-25165824})) # 24 MiB
|
||||
PART_BYTES=$((10#${PHOTOCRAFT_WEB_PART_BYTES:-20971520})) # 20 MiB
|
||||
if [[ "$PART_BYTES" -le 0 ]] || [[ "$PART_BYTES" -gt "$MAX_FILE_BYTES" ]]; then
|
||||
echo "error: a part of $PART_BYTES bytes doesn't fit the $MAX_FILE_BYTES-byte file limit" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WASM=""
|
||||
for wasm in "$APP"/*_bg.wasm; do
|
||||
[ -f "$wasm" ] || continue
|
||||
[ -z "$WASM" ] || { echo "error: more than one .wasm in $APP; remove it and run without --skip-build" >&2; exit 1; }
|
||||
[[ -f "$wasm" ]] || continue
|
||||
[[ -z "$WASM" ]] || { echo "error: more than one .wasm in $APP; remove it and run without --skip-build" >&2; exit 1; }
|
||||
WASM="$wasm"
|
||||
done
|
||||
[ -n "$WASM" ] || { echo "error: no .wasm in $APP" >&2; exit 1; }
|
||||
[[ -n "$WASM" ]] || { echo "error: no .wasm in $APP" >&2; exit 1; }
|
||||
STEM="$(basename "$WASM" _bg.wasm)" # photocraft-web-<content hash>
|
||||
GLUE="$APP/$STEM.js"
|
||||
[ -f "$GLUE" ] || { echo "error: $GLUE missing" >&2; exit 1; }
|
||||
[[ -f "$GLUE" ]] || { echo "error: $GLUE missing" >&2; exit 1; }
|
||||
|
||||
NAME="photocraft-web-$VERSION"
|
||||
WORK="$CARGO_TARGET_DIR/web-package"
|
||||
@@ -80,9 +80,9 @@ copy_docs "$WORK/$NAME"
|
||||
# Optional served fonts (README.md › Fonts): PHOTOCRAFT_WEB_FONTS_DIR=<a craft-fonts checkout, or any
|
||||
# folder with a fonts/manifest.txt in its format> copies the manifest, every font and licence file
|
||||
# it lists into the site, at the same paths. The wasm is unchanged; the app fetches fonts on demand.
|
||||
if [ -n "${PHOTOCRAFT_WEB_FONTS_DIR:-}" ]; then
|
||||
if [[ -n "${PHOTOCRAFT_WEB_FONTS_DIR:-}" ]]; then
|
||||
FONTS_MANIFEST="$PHOTOCRAFT_WEB_FONTS_DIR/fonts/manifest.txt"
|
||||
[ -f "$FONTS_MANIFEST" ] || { echo "error: $FONTS_MANIFEST missing (PHOTOCRAFT_WEB_FONTS_DIR)" >&2; exit 1; }
|
||||
[[ -f "$FONTS_MANIFEST" ]] || { echo "error: $FONTS_MANIFEST missing (PHOTOCRAFT_WEB_FONTS_DIR)" >&2; exit 1; }
|
||||
mkdir -p "$WORK/$NAME/fonts"
|
||||
cp "$FONTS_MANIFEST" "$WORK/$NAME/fonts/manifest.txt"
|
||||
# Field 3 is the font file, field 6 (if any) its licence file; both relative to the folder.
|
||||
@@ -98,8 +98,8 @@ fi
|
||||
largest=0
|
||||
while IFS= read -r file; do
|
||||
bytes=$(size "$file")
|
||||
[ "$bytes" -le "$largest" ] || largest=$bytes
|
||||
if [ "$bytes" -gt "$MAX_FILE_BYTES" ]; then
|
||||
[[ "$bytes" -le "$largest" ]] || largest=$bytes
|
||||
if [[ "$bytes" -gt "$MAX_FILE_BYTES" ]]; then
|
||||
echo "error: ${file#"$WORK/$NAME/"} is $bytes bytes, over the $MAX_FILE_BYTES-byte limit (Cloudflare's per-file cap is 25 MiB)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user