make: factorize code for generating release updates (#12655)

Instead of splitting remove / exclusion of unwanted files in 2-3 places
(`all` rule, `update` rule, and update script in some cases), install
the same files in debug & release builds, and exclude unwanted stuff
when generating the update.

This should finally fix the CI issue with OCR tests (since we don't
remove the `data/dict` & `data/tessdata` directories on release build
anymore).
This commit is contained in:
Benoit Pierre
2024-11-23 20:48:37 +01:00
committed by GitHub
parent de7c5920b8
commit c04023f1d1
15 changed files with 544 additions and 345 deletions

View File

@@ -197,7 +197,9 @@ jobs:
# Generate / upload artifact. {{{
- name: Generate artifact
run: make update --assume-old=base
# Note: ensure the build skeleton is created, so there are no dangling
# symlinks (e.g. `data/dict`) to trip 7zip during artifact generation…
run: make skeleton update --assume-old=base
- name: Upload artifact
uses: actions/upload-artifact@v4

View File

@@ -14,10 +14,6 @@ ifneq (,$(findstring -,$(VERSION)))
VERSION := $(VERSION)_$(RELEASE_DATE)
endif
# releases do not contain tests and misc data
IS_RELEASE := $(if $(or $(EMULATE_READER),$(WIN32)),,1)
IS_RELEASE := $(if $(or $(IS_RELEASE),$(APPIMAGE),$(LINUX),$(MACOS)),1,)
LINUX_ARCH?=native
ifeq ($(LINUX_ARCH), native)
LINUX_ARCH_NAME:=$(shell uname -m)
@@ -50,11 +46,14 @@ WIN32_DIR=$(PLATFORM_DIR)/win32
define CR3GUI_DATADIR_EXCLUDES
%/KoboUSBMS.tar.gz
%/NOTES.txt
%/cr3.ini
%/cr3skin-format.txt
%/desktop
%/devices
%/dict
%/manual
%/tessdata
endef
CR3GUI_DATADIR_FILES = $(filter-out $(CR3GUI_DATADIR_EXCLUDES),$(wildcard $(CR3GUI_DATADIR)/*))
@@ -71,18 +70,78 @@ INSTALL_FILES=reader.lua setupkoenv.lua frontend resources defaults.lua datastor
OUTPUT_DIR_ARTIFACTS = $(abspath $(OUTPUT_DIR))/!(cache|cmake|data|history|staging|thirdparty)
OUTPUT_DIR_DATAFILES = $(OUTPUT_DIR)/data/*
# Release excludes. {{{
define UPDATE_PATH_EXCLUDES
cache
clipboard
data/dict
data/tessdata
ev_replay.py
help
history
l10n/templates
ota
resources/fonts*
resources/icons/src*
screenshots
spec
endef
# Files created after execution.
define UPDATE_PATH_EXCLUDES +=
data/cr3.ini
defaults.*.lua
history.lua
scripts
settings
settings.reader.lua*
styletweaks
version.log
endef
# Testsuite leftovers.
define UPDATE_PATH_EXCLUDES +=
dummy-test-file*
file.sdr*
readerbookmark.*
readerhighlight.*
testdata
this-is-not-a-valid-file*
endef
# Globally excluded.
define UPDATE_GLOBAL_EXCLUDES
*.orig
*.swo
*.swp
*.un~
.*
endef
release_excludes = $(strip $(UPDATE_PATH_EXCLUDES:%='-x!$1%') $(UPDATE_GLOBAL_EXCLUDES:%='-xr!%'))
# }}}
define mkupdate
cd $(INSTALL_DIR) &&
'$(abspath tools/mkrelease.sh)'
$(if $(PARALLEL_JOBS),--jobs $(PARALLEL_JOBS))
--manifest=$(or $2,koreader)/ota/package.index
$(foreach a,$1,'$(if $(filter --%,$a),$a,$(abspath $a))') $(or $2,koreader)
$(call release_excludes,$(or $2,koreader)/)
endef
all: base
install -d $(INSTALL_DIR)/koreader
rm -f $(INSTALL_DIR)/koreader/git-rev; echo "$(VERSION)" > $(INSTALL_DIR)/koreader/git-rev
ifdef ANDROID
rm -f android-fdroid-version; echo -e "$(ANDROID_NAME)\n$(ANDROID_VERSION)" > koreader-android-fdroid-latest
endif
ifeq (,$(IS_RELEASE))
$(SYMLINK) $(KOR_BASE)/ev_replay.py $(INSTALL_DIR)/koreader/
endif
bash -O extglob -c '$(SYMLINK) $(OUTPUT_DIR_ARTIFACTS) $(INSTALL_DIR)/koreader/'
ifneq (,$(EMULATE_READER))
@echo "[*] install front spec only for the emulator"
@echo "[*] Install front spec only for the emulator"
$(SYMLINK) spec $(INSTALL_DIR)/koreader/spec/front
$(SYMLINK) test $(INSTALL_DIR)/koreader/spec/front/unit/data
endif
@@ -112,10 +171,6 @@ endif
! test -L $(INSTALL_DIR)/koreader/data || rm $(INSTALL_DIR)/koreader/data
install -d $(INSTALL_DIR)/koreader/data
$(SYMLINK) $(strip $(DATADIR_FILES)) $(INSTALL_DIR)/koreader/data/
ifneq (,$(IS_RELEASE))
@echo "[*] Clean up, remove unused files for releases"
rm -rf $(INSTALL_DIR)/koreader/data/{cr3.ini,desktop,devices,dict,manual,tessdata}
endif
base: base-all
@@ -198,3 +253,5 @@ doc:
.PHONY: $(PHONY)
include $(KOR_BASE)/Makefile
# vim: foldmethod=marker foldlevel=0

View File

@@ -42,6 +42,12 @@ ANDROID_DIR = $(PLATFORM_DIR)/android
ANDROID_LAUNCHER_DIR = $(ANDROID_DIR)/luajit-launcher
ANDROID_LAUNCHER_BUILD = $(INSTALL_DIR)/luajit-launcher
ANDROID_ASSETS = $(ANDROID_LAUNCHER_BUILD)/assets
# Assets compression method:
# - LZMA/LZMA2: `-m0=lzma2 -mx=9`
# - LZMA/LZMA2 (7z >= 17.02, fast version): `-m0=flzma2 -mx=9`
# - ZSTD (7z >= 17.02, LZMA still used for archive headers): `-m0=zstd -mx=16`
# - ZSTD (7z >= 17.02): `-m0=zstd -mhc=off -mx=16`
ANDROID_ASSETS_COMPRESSION ?= -m0=lzma2 -mx=9
ANDROID_LIBS = $(ANDROID_LAUNCHER_BUILD)/libs/$(ANDROID_ABI)
ANDROID_FLAVOR ?= Rocks
@@ -61,6 +67,22 @@ else
ANDROID_ABI ?= armeabi-v7a
endif
define UPDATE_PATH_EXCLUDES +=
plugins/SSH.koplugin
plugins/autofrontlight.koplugin
plugins/hello.koplugin
plugins/timesync.koplugin
tools
endef
define UPDATE_GLOBAL_EXCLUDES +=
README.md
COPYING
LICENSE*
*license.txt
NOTICE
endef
androiddev: update
$(MAKE) -C $(ANDROID_LAUNCHER_DIR) dev
@@ -83,35 +105,14 @@ update: all
# binaries are stored as shared libraries to prevent W^X exception on Android 10+
# https://developer.android.com/about/versions/10/behavior-changes-10#execute-permission
llvm-strip --strip-unneeded $(INSTALL_DIR)/koreader/sdcv -o $(ANDROID_LIBS)/libsdcv.so
# assets are compressed manually and stored inside the APK.
# Assets are compressed manually and stored inside the APK.
cd $(INSTALL_DIR)/koreader && \
./tools/mk7z.sh \
$(abspath $(ANDROID_ASSETS)/module/koreader.7z) \
"$$(git show -s --format='%ci')" \
-m0=lzma2 -mx=9 \
-- . \
'-x!cache' \
'-x!clipboard' \
'-x!data/dict' \
'-x!data/tessdata' \
'-x!history' \
'-x!l10n/templates' \
'-x!libs' \
'-x!ota' \
'-x!resources/fonts*' \
'-x!resources/icons/src*' \
'-x!rocks/bin' \
'-x!rocks/lib/luarocks' \
'-x!screenshots' \
'-x!sdcv' \
'-x!spec' \
'-x!tools' \
'-xr!.*' \
'-xr!COPYING' \
'-xr!NOTES.txt' \
'-xr!NOTICE' \
'-xr!README.md' \
;
./tools/mkrelease.sh \
$(if $(PARALLEL_JOBS),--jobs $(PARALLEL_JOBS)) \
--epoch="$$(git show -s --format='%ci')" \
--options='$(ANDROID_ASSETS_COMPRESSION)' \
$(abspath $(ANDROID_ASSETS)/module/koreader.7z) \
. '-x!libs' '-x!sdcv' $(release_excludes)
# Note: we filter out the `--debug=…` make flag so the old
# crummy version provided by the NDK does not blow a gasket.
env \

View File

@@ -1,31 +1,36 @@
APPIMAGE_DIR = $(PLATFORM_DIR)/appimage
APPIMAGETOOL = appimagetool-x86_64.AppImage
APPIMAGETOOL_URL = https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage
APPIMAGETOOL_URL = https://github.com/AppImage/AppImageKit/releases/download/13/$(APPIMAGETOOL)
KOREADER_APPIMAGE = koreader-$(DIST)-$(MACHINE)-$(VERSION).AppImage
UBUNTU_LIBBSD = /lib/x86_64-linux-gnu/libbsd.so.0
define UPDATE_PATH_EXCLUDES +=
plugins/SSH.koplugin
plugins/autofrontlight.koplugin
plugins/timesync.koplugin
$(filter-out tools/trace_require.lua tools/wbuilder.lua,$(wildcard tools/*))
endef
update: all
# remove old package if any
rm -f koreader-appimage-$(MACHINE)-$(VERSION).appimage
$(SYMLINK) $(APPIMAGE_DIR)/AppRun $(INSTALL_DIR)/koreader/
$(SYMLINK) $(APPIMAGE_DIR)/koreader.desktop $(INSTALL_DIR)/koreader/
$(SYMLINK) resources/koreader.png $(INSTALL_DIR)/koreader/
sed -e 's/%%VERSION%%/$(VERSION)/' -e 's/%%DATE%%/$(RELEASE_DATE)/' $(PLATFORM_DIR)/common/koreader.metainfo.xml >$(INSTALL_DIR)/koreader/koreader.appdata.xml
# also copy libbsd.so.0, cf. https://github.com/koreader/koreader/issues/4627
$(SYMLINK) /lib/x86_64-linux-gnu/libbsd.so.0 $(INSTALL_DIR)/koreader/libs/
ifeq ("$(wildcard $(APPIMAGETOOL))","")
# download appimagetool
wget "$(APPIMAGETOOL_URL)"
chmod a+x "$(APPIMAGETOOL)"
cd $(INSTALL_DIR)/koreader && '$(abspath tools/mkrelease.sh)' ../appimage/ . $(release_excludes)
cp $(APPIMAGE_DIR)/{AppRun,koreader.desktop} resources/koreader.png $(INSTALL_DIR)/appimage/
sed -e 's/%%VERSION%%/$(VERSION)/' -e 's/%%DATE%%/$(RELEASE_DATE)/' $(PLATFORM_DIR)/common/koreader.metainfo.xml >$(INSTALL_DIR)/appimage/koreader.appdata.xml
# Also copy libbsd.so.0 (cf. https://github.com/koreader/koreader/issues/4627).
ifeq (,$(wildcard $(UBUNTU_LIBBSD)))
# Only warn if it's missing (e.g. when testing on a non-Ubuntu distribution).
echo 'WARNING: not bundling missing $(UBUNTU_LIBBSD)' 1>&2
else
cp $(UBUNTU_LIBBSD) $(INSTALL_DIR)/appimage/libs/
endif
cd $(INSTALL_DIR) && pwd && \
rm -rf tmp && mkdir -p tmp && \
cp -Lr koreader tmp && \
rm -rf tmp/koreader/ota && \
rm -rf tmp/koreader/resources/icons/src && \
rm -rf tmp/koreader/spec
# generate AppImage
cd $(INSTALL_DIR)/tmp && \
ARCH=x86_64 "$$OLDPWD/$(APPIMAGETOOL)" --appimage-extract-and-run koreader && \
mv *.AppImage ../../koreader-$(DIST)-$(MACHINE)-$(VERSION).AppImage
ifeq (,$(wildcard $(APPIMAGETOOL)))
# Download appimagetool.
wget '$(APPIMAGETOOL_URL)'
chmod a+x ./$(APPIMAGETOOL)
endif
# Generate AppImage.
ARCH=x86_64 ./$(APPIMAGETOOL) --appimage-extract-and-run $(INSTALL_DIR)/appimage $(KOREADER_APPIMAGE)
PHONY += update

View File

@@ -2,32 +2,21 @@ CERVANTES_DIR = $(PLATFORM_DIR)/cervantes
CERVANTES_PACKAGE = koreader-cervantes$(KODEDUG_SUFFIX)-$(VERSION).zip
CERVANTES_PACKAGE_OTA = koreader-cervantes$(KODEDUG_SUFFIX)-$(VERSION).targz
define UPDATE_PATH_EXCLUDES +=
tools
endef
update: all
# ensure that the binaries were built for ARM
file --dereference $(INSTALL_DIR)/koreader/luajit | grep ARM
# remove old package if any
rm -f $(CERVANTES_PACKAGE)
# Cervantes launching scripts
cp $(COMMON_DIR)/spinning_zsync $(INSTALL_DIR)/koreader/spinning_zsync.sh
cp $(CERVANTES_DIR)/*.sh $(INSTALL_DIR)/koreader
cp $(CERVANTES_DIR)/spinning_zsync $(INSTALL_DIR)/koreader
# create new package
cd $(INSTALL_DIR) && \
zip -9 -r \
../$(CERVANTES_PACKAGE) \
koreader -x "koreader/resources/fonts/*" \
"koreader/resources/icons/src/*" "koreader/spec/*" \
$(ZIP_EXCLUDE)
# generate update package index file
zipinfo -1 $(CERVANTES_PACKAGE) > \
$(INSTALL_DIR)/koreader/ota/package.index
echo "koreader/ota/package.index" >> $(INSTALL_DIR)/koreader/ota/package.index
# update index file in zip package
cd $(INSTALL_DIR) && zip -u ../$(CERVANTES_PACKAGE) \
koreader/ota/package.index
# make gzip cervantes update for zsync OTA update
cd $(INSTALL_DIR) && \
tar --hard-dereference -I"gzip --rsyncable" -cah --no-recursion -f ../$(CERVANTES_PACKAGE_OTA) \
-T koreader/ota/package.index
$(SYMLINK) $(COMMON_DIR)/spinning_zsync $(INSTALL_DIR)/koreader/spinning_zsync.sh
$(SYMLINK) $(CERVANTES_DIR)/*.sh $(INSTALL_DIR)/koreader
$(SYMLINK) $(CERVANTES_DIR)/spinning_zsync $(INSTALL_DIR)/koreader
# Create packages.
$(strip $(call mkupdate,$(CERVANTES_PACKAGE)))
$(strip $(call mkupdate,$(CERVANTES_PACKAGE_OTA)))
PHONY += update

View File

@@ -1,18 +1,20 @@
KINDLE_DIR = $(PLATFORM_DIR)/kindle
KINDLE_PACKAGE = koreader-$(DIST)$(KODEDUG_SUFFIX)-$(VERSION).zip
# Note: the targz extension is intended to keep ISP from caching the file (Cf. koreader#1644).
KINDLE_PACKAGE_OTA = koreader-$(DIST)$(KODEDUG_SUFFIX)-$(VERSION).targz
ZIP_EXCLUDE = -x "*.swp" -x "*.swo" -x "*.orig" -x "*.un~"
# Don't bundle launchpad on touch devices..
ifeq ($(TARGET), kindle-legacy)
KINDLE_LEGACY_LAUNCHER = launchpad
endif
define UPDATE_PATH_EXCLUDES +=
tools
endef
update: all
# ensure that the binaries were built for ARM
file --dereference $(INSTALL_DIR)/koreader/luajit | grep ARM
# remove old package if any
rm -f $(KINDLE_PACKAGE)
# Kindle launching scripts
$(SYMLINK) $(KINDLE_DIR)/extensions $(INSTALL_DIR)/
$(SYMLINK) $(KINDLE_DIR)/launchpad $(INSTALL_DIR)/
@@ -21,26 +23,8 @@ update: all
$(SYMLINK) $(KINDLE_DIR)/libkohelper.sh $(INSTALL_DIR)/extensions/koreader/bin/
$(SYMLINK) $(COMMON_DIR)/spinning_zsync $(INSTALL_DIR)/koreader/
$(SYMLINK) $(KINDLE_DIR)/wmctrl $(INSTALL_DIR)/koreader/
# create new package
cd $(INSTALL_DIR) && pwd && \
zip -9 -r \
../$(KINDLE_PACKAGE) \
extensions koreader $(KINDLE_LEGACY_LAUNCHER) \
-x "koreader/resources/fonts/*" "koreader/ota/*" \
"koreader/resources/icons/src/*" "koreader/spec/*" \
$(ZIP_EXCLUDE)
# generate kindleupdate package index file
zipinfo -1 $(KINDLE_PACKAGE) > \
$(INSTALL_DIR)/koreader/ota/package.index
echo "koreader/ota/package.index" >> $(INSTALL_DIR)/koreader/ota/package.index
# update index file in zip package
cd $(INSTALL_DIR) && zip -u ../$(KINDLE_PACKAGE) \
koreader/ota/package.index
# make gzip kindleupdate for zsync OTA update
# note that the targz file extension is intended to keep ISP from caching
# the file, see koreader#1644.
cd $(INSTALL_DIR) && \
tar --hard-dereference -I"gzip --rsyncable" -cah --no-recursion -f ../$(KINDLE_PACKAGE_OTA) \
-T koreader/ota/package.index
# Create packages.
$(strip $(call mkupdate,$(KINDLE_PACKAGE))) extensions $(KINDLE_LEGACY_LAUNCHER)
$(strip $(call mkupdate,$(KINDLE_PACKAGE_OTA))) extensions $(KINDLE_LEGACY_LAUNCHER)
PHONY += update

View File

@@ -2,32 +2,19 @@ KOBO_DIR = $(PLATFORM_DIR)/kobo
KOBO_PACKAGE = koreader-$(DIST)$(KODEDUG_SUFFIX)-$(VERSION).zip
KOBO_PACKAGE_OTA = koreader-$(DIST)$(KODEDUG_SUFFIX)-$(VERSION).targz
define UPDATE_PATH_EXCLUDES +=
$(filter-out tools/kobo%,$(wildcard tools/*))
endef
update: all
# ensure that the binaries were built for ARM
file --dereference $(INSTALL_DIR)/koreader/luajit | grep ARM
# remove old package if any
rm -f $(KOBO_PACKAGE)
# Kobo launching scripts
cp $(KOBO_DIR)/koreader.png $(INSTALL_DIR)/koreader.png
cp $(KOBO_DIR)/*.sh $(INSTALL_DIR)/koreader
cp $(COMMON_DIR)/spinning_zsync $(INSTALL_DIR)/koreader
# create new package
cd $(INSTALL_DIR) && \
zip -9 -r \
../$(KOBO_PACKAGE) \
koreader -x "koreader/resources/fonts/*" \
"koreader/resources/icons/src/*" "koreader/spec/*" \
$(ZIP_EXCLUDE)
# generate koboupdate package index file
zipinfo -1 $(KOBO_PACKAGE) > \
$(INSTALL_DIR)/koreader/ota/package.index
echo "koreader/ota/package.index" >> $(INSTALL_DIR)/koreader/ota/package.index
# update index file in zip package
cd $(INSTALL_DIR) && zip -u ../$(KOBO_PACKAGE) \
koreader/ota/package.index koreader.png README_kobo.txt
# make gzip koboupdate for zsync OTA update
cd $(INSTALL_DIR) && \
tar --hard-dereference -I"gzip --rsyncable" -cah --no-recursion -f ../$(KOBO_PACKAGE_OTA) \
-T koreader/ota/package.index
$(SYMLINK) $(KOBO_DIR)/koreader.png $(INSTALL_DIR)/
$(SYMLINK) $(KOBO_DIR)/*.sh $(INSTALL_DIR)/koreader/
$(SYMLINK) $(COMMON_DIR)/spinning_zsync $(INSTALL_DIR)/koreader/
# Create packages.
$(strip $(call mkupdate,--manifest-transform=/^koreader\.png$$/d $(KOBO_PACKAGE))) koreader.png
$(strip $(call mkupdate,$(KOBO_PACKAGE_OTA)))
PHONY += update

View File

@@ -1,44 +1,36 @@
LINUX_DIR = $(PLATFORM_DIR)/linux
LINUX_PACKAGE:=koreader-linux-$(LINUX_ARCH_NAME)$(KODEDUG_SUFFIX)-$(VERSION).tar.xz
LINUX_PACKAGE = koreader-linux-$(LINUX_ARCH_NAME)$(KODEDUG_SUFFIX)-$(VERSION).tar.xz
LINUX_PACKAGE_COMPRESSION_LEVEL ?= 9
GLIBC_VERSION := $(shell ldd --version | sed -n '1s/.* \([0-9.]\+\)$$/\1/p')
GLIBC_VERSION = $(shell ldd --version | sed -n '1s/.* \([0-9.]\+\)$$/\1/p')
define UPDATE_PATH_EXCLUDES +=
plugins/SSH.koplugin
plugins/autofrontlight.koplugin
plugins/timesync.koplugin
$(filter-out tools/trace_require.lua tools/wbuilder.lua,$(wildcard tools/*))
endef
update: all
mkdir -pv \
$(INSTALL_DIR)/linux/bin \
$(INSTALL_DIR)/linux/lib \
$(INSTALL_DIR)/linux/share/pixmaps \
$(INSTALL_DIR)/linux/share/metainfo \
$(INSTALL_DIR)/linux/share/applications \
$(INSTALL_DIR)/linux/share/doc/koreader \
$(INSTALL_DIR)/linux/share/man/man1
rm -rf $(INSTALL_DIR)/linux
mkdir -p $(INSTALL_DIR)/linux/{bin,lib,share/{applications,doc/koreader,man/man1,metainfo,pixmaps}}
sed -e 's/%%VERSION%%/$(VERSION)/g' -e 's/%%DATE%%/$(RELEASE_DATE)/' $(PLATFORM_DIR)/common/koreader.metainfo.xml >$(INSTALL_DIR)/linux/share/metainfo/koreader.metainfo.xml
cp -pv resources/koreader.png $(INSTALL_DIR)/linux/share/pixmaps
cp -pv $(LINUX_DIR)/koreader.desktop $(INSTALL_DIR)/linux/share/applications
cp -pv $(LINUX_DIR)/copyright COPYING $(INSTALL_DIR)/linux/share/doc/koreader
cp -pv $(LINUX_DIR)/koreader.sh $(INSTALL_DIR)/linux/bin/koreader
cp -Lr $(INSTALL_DIR)/koreader $(INSTALL_DIR)/linux/lib
gzip -cn9 $(LINUX_DIR)/koreader.1 > $(INSTALL_DIR)/linux/share/man/man1/koreader.1.gz
chmod 644 \
$(INSTALL_DIR)/linux/share/doc/koreader/copyright \
$(INSTALL_DIR)/linux/share/man/man1/koreader.1.gz
rm -rf \
$(INSTALL_DIR)/linux/lib/koreader/{ota,cache,clipboard,screenshots,spec,tools,resources/fonts,resources/icons/src}
# remove leftovers
find $(INSTALL_DIR)/linux -type f \( -name ".git" -o -name ".gitignore" -o -name "discovery2spore" -o -name "wadl2spore" -o -name "*.txt" -o -name "LICENSE*" -o -name "NOTICE" -o -name "README.md" \) -print0 | xargs -0 rm -rf
find $(INSTALL_DIR)/linux -type d \( -name "test" -o -name ".github" \) -print0 | xargs -0 rm -rf
# add instructions
$(SYMLINK) $(LINUX_DIR)/koreader.sh $(INSTALL_DIR)/linux/bin/koreader
$(SYMLINK) $(INSTALL_DIR)/koreader $(INSTALL_DIR)/linux/lib/
$(SYMLINK) resources/koreader.png $(INSTALL_DIR)/linux/share/pixmaps/
$(SYMLINK) $(LINUX_DIR)/koreader.desktop $(INSTALL_DIR)/linux/share/applications/
$(SYMLINK) $(LINUX_DIR)/copyright COPYING $(INSTALL_DIR)/linux/share/doc/koreader/
gzip -cn9 $(LINUX_DIR)/koreader.1 >$(INSTALL_DIR)/linux/share/man/man1/koreader.1.gz
# Add instructions.
sed -e 's/%%VERSION%%/$(VERSION)/' \
-e 's/%%ARCH%%/$(LINUX_ARCH_NAME)/' \
-e 's/%%ABI%%/$(GLIBC_VERSION)/' \
$(LINUX_DIR)/instructions.txt >$(INSTALL_DIR)/linux/README.md
# fix permissions
chmod -R u=rwX,og=rX $(INSTALL_DIR)/linux
XZ_OPT=9 tar -C $(INSTALL_DIR)/linux -cvJf $(LINUX_PACKAGE) .
rm -rf $(INSTALL_DIR)/linux
# Create archive.
cd $(INSTALL_DIR)/linux && \
'$(abspath tools/mkrelease.sh)' \
$(if $(PARALLEL_JOBS),--jobs $(PARALLEL_JOBS)) \
--options=-$(LINUX_PACKAGE_COMPRESSION_LEVEL) \
'$(abspath $(LINUX_PACKAGE))' . $(call release_excludes,lib/koreader/)
PHONY += update

View File

@@ -1,14 +1,20 @@
MACOS_DIR = $(PLATFORM_DIR)/mac
define UPDATE_PATH_EXCLUDES +=
plugins/SSH.koplugin
plugins/autofrontlight.koplugin
plugins/hello.koplugin
plugins/timesync.koplugin
tools
endef
update: all
mkdir -p \
$(INSTALL_DIR)/bundle/Contents/MacOS \
$(INSTALL_DIR)/bundle/Contents/Resources
mkdir -p $(INSTALL_DIR)/bundle/Contents/{MacOS,Resources}
cp -pv $(MACOS_DIR)/koreader.icns $(INSTALL_DIR)/bundle/Contents/Resources/icon.icns
cp -LR $(INSTALL_DIR)/koreader $(INSTALL_DIR)/bundle/Contents
cp -pRv $(MACOS_DIR)/menu.xml $(INSTALL_DIR)/bundle/Contents/MainMenu.xib
ibtool --compile "$(INSTALL_DIR)/bundle/Contents/Resources/Base.lproj/MainMenu.nib" "$(INSTALL_DIR)/bundle/Contents/MainMenu.xib"
rm -rfv "$(INSTALL_DIR)/bundle/Contents/MainMenu.xib"
cd $(INSTALL_DIR)/koreader && '$(abspath tools/mkrelease.sh)' ../bundle/Contents/koreader/ . $(release_excludes)
cp -pv $(MACOS_DIR)/menu.xml $(INSTALL_DIR)/bundle/Contents/MainMenu.xib
ibtool --compile $(INSTALL_DIR)/bundle/Contents/Resources/Base.lproj/MainMenu.nib $(INSTALL_DIR)/bundle/Contents/MainMenu.xib
rm -vf $(INSTALL_DIR)/bundle/Contents/MainMenu.xib
$(CURDIR)/platform/mac/do_mac_bundle.sh $(INSTALL_DIR)
PHONY += update

View File

@@ -2,42 +2,23 @@ POCKETBOOK_DIR = $(PLATFORM_DIR)/pocketbook
PB_PACKAGE = koreader-pocketbook$(KODEDUG_SUFFIX)-$(VERSION).zip
PB_PACKAGE_OTA = koreader-pocketbook$(KODEDUG_SUFFIX)-$(VERSION).targz
define UPDATE_PATH_EXCLUDES +=
tools
endef
update: all
# ensure that the binaries were built for ARM
file --dereference $(INSTALL_DIR)/koreader/luajit | grep ARM
# remove old package if any
rm -f $(PB_PACKAGE)
# Pocketbook launching scripts
rm -rf $(INSTALL_DIR)/{applications,system}
mkdir -p $(INSTALL_DIR)/applications
mkdir -p $(INSTALL_DIR)/system/bin
cp $(POCKETBOOK_DIR)/koreader.app $(INSTALL_DIR)/applications
cp $(POCKETBOOK_DIR)/system_koreader.app $(INSTALL_DIR)/system/bin/koreader.app
cp $(COMMON_DIR)/spinning_zsync $(INSTALL_DIR)/koreader
cp -rfL $(INSTALL_DIR)/koreader $(INSTALL_DIR)/applications
find $(INSTALL_DIR)/applications/koreader \
-type f \( -name "*.gif" -o -name "*.html" -o -name "*.md" -o -name "*.txt" \) \
-exec rm -vf {} \;
# create new package
cd $(INSTALL_DIR) && \
zip -9 -r \
../$(PB_PACKAGE) \
applications -x "applications/koreader/resources/fonts/*" \
"applications/koreader/resources/icons/src/*" "applications/koreader/spec/*" \
$(ZIP_EXCLUDE)
# generate pocketbook package index file
zipinfo -1 $(PB_PACKAGE) > \
$(INSTALL_DIR)/applications/koreader/ota/package.index
echo "applications/koreader/ota/package.index" >> \
$(INSTALL_DIR)/applications/koreader/ota/package.index
# hack file path when running tar in parent directory of koreader
sed -i -e 's/^/..\//' \
$(INSTALL_DIR)/applications/koreader/ota/package.index
# update index file in zip package
cd $(INSTALL_DIR) && zip -ru ../$(PB_PACKAGE) \
applications/koreader/ota/package.index system
# make gzip pbupdate for zsync OTA update
cd $(INSTALL_DIR)/applications && \
tar --hard-dereference -I"gzip --rsyncable" -cah --no-recursion -f ../../$(PB_PACKAGE_OTA) \
-T koreader/ota/package.index
$(SYMLINK) $(POCKETBOOK_DIR)/koreader.app $(INSTALL_DIR)/applications/
$(SYMLINK) $(POCKETBOOK_DIR)/system_koreader.app $(INSTALL_DIR)/system/bin/koreader.app
$(SYMLINK) $(COMMON_DIR)/spinning_zsync $(INSTALL_DIR)/koreader/
$(SYMLINK) $(INSTALL_DIR)/koreader $(INSTALL_DIR)/applications/
# Create packages.
$(strip $(call mkupdate,--manifest-transform=/^system/d;s/^/..\// $(PB_PACKAGE),applications/koreader)) applications system
$(strip $(call mkupdate,--manifest-transform=s/^/..\// $(PB_PACKAGE_OTA),applications/koreader)) applications
PHONY += update

View File

@@ -2,31 +2,19 @@ REMARKABLE_DIR = $(PLATFORM_DIR)/remarkable
REMARKABLE_PACKAGE = koreader-remarkable$(KODEDUG_SUFFIX)-$(VERSION).zip
REMARKABLE_PACKAGE_OTA = koreader-remarkable$(KODEDUG_SUFFIX)-$(VERSION).targz
define UPDATE_PATH_EXCLUDES +=
plugins/SSH.koplugin
tools
endef
update: all
# ensure that the binaries were built for ARM
file --dereference $(INSTALL_DIR)/koreader/luajit | grep ARM
# remove old package if any
rm -f $(REMARKABLE_PACKAGE)
# Remarkable scripts
cp $(REMARKABLE_DIR)/* $(INSTALL_DIR)/koreader
cp $(COMMON_DIR)/spinning_zsync $(INSTALL_DIR)/koreader
# create new package
cd $(INSTALL_DIR) && \
zip -9 -r \
../$(REMARKABLE_PACKAGE) \
koreader -x "koreader/resources/fonts/*" \
"koreader/resources/icons/src/*" "koreader/spec/*" \
$(ZIP_EXCLUDE)
# generate update package index file
zipinfo -1 $(REMARKABLE_PACKAGE) > \
$(INSTALL_DIR)/koreader/ota/package.index
echo "koreader/ota/package.index" >> $(INSTALL_DIR)/koreader/ota/package.index
# update index file in zip package
cd $(INSTALL_DIR) && zip -u ../$(REMARKABLE_PACKAGE) \
koreader/ota/package.index
# make gzip remarkable update for zsync OTA update
cd $(INSTALL_DIR) && \
tar -I"gzip --rsyncable" -cah --no-recursion -f ../$(REMARKABLE_PACKAGE_OTA) \
-T koreader/ota/package.index
$(SYMLINK) $(REMARKABLE_DIR)/* $(INSTALL_DIR)/koreader/
$(SYMLINK) $(COMMON_DIR)/spinning_zsync $(INSTALL_DIR)/koreader/
# Create packages.
$(strip $(call mkupdate,$(REMARKABLE_PACKAGE)))
$(strip $(call mkupdate,$(REMARKABLE_PACKAGE_OTA)))
PHONY += update

View File

@@ -2,30 +2,18 @@ SONY_PRSTUX_DIR = $(PLATFORM_DIR)/sony-prstux
SONY_PRSTUX_PACKAGE = koreader-sony-prstux$(KODEDUG_SUFFIX)-$(VERSION).zip
SONY_PRSTUX_PACKAGE_OTA = koreader-sony-prstux$(KODEDUG_SUFFIX)-$(VERSION).targz
define UPDATE_PATH_EXCLUDES +=
plugins/SSH.koplugin
tools
endef
update: all
# ensure that the binaries were built for ARM
file --dereference $(INSTALL_DIR)/koreader/luajit | grep ARM
# remove old package if any
rm -f $(SONY_PRSTUX_PACKAGE)
# Sony PRSTUX launching scripts
cp $(SONY_PRSTUX_DIR)/*.sh $(INSTALL_DIR)/koreader
# create new package
cd $(INSTALL_DIR) && \
zip -9 -r \
../$(SONY_PRSTUX_PACKAGE) \
koreader -x "koreader/resources/fonts/*" \
"koreader/resources/icons/src/*" "koreader/spec/*" \
$(ZIP_EXCLUDE)
# generate update package index file
zipinfo -1 $(SONY_PRSTUX_PACKAGE) > \
$(INSTALL_DIR)/koreader/ota/package.index
echo "koreader/ota/package.index" >> $(INSTALL_DIR)/koreader/ota/package.index
# update index file in zip package
cd $(INSTALL_DIR) && zip -u ../$(SONY_PRSTUX_PACKAGE) \
koreader/ota/package.index
# make gzip sonyprstux update for zsync OTA update
cd $(INSTALL_DIR) && \
tar --hard-dereference -I"gzip --rsyncable" -cah --no-recursion -f ../$(SONY_PRSTUX_PACKAGE_OTA) \
-T koreader/ota/package.index
$(SYMLINK) $(SONY_PRSTUX_DIR)/*.sh $(INSTALL_DIR)/koreader
# Create packages.
$(strip $(call mkupdate,$(SONY_PRSTUX_PACKAGE)))
$(strip $(call mkupdate,$(SONY_PRSTUX_PACKAGE_OTA)))
PHONY += update

View File

@@ -131,11 +131,6 @@ pushd "${APP_PATH}/Contents/koreader"
lipo /usr/bin/tar -extract_family "${APP_ARCH}" -output tar
mv COPYING README.md ../Resources/
mv koreader ../MacOS/koreader
rm -rf cache clipboard history ota \
l10n/.git l10n/.tx l10n/templates l10n/LICENSE l10n/Makefile l10n/README.md \
plugins/SSH.koplugin plugins/hello.koplugin plugins/timesync.koplugin \
plugins/autofrontlight.koplugin resources/fonts resources/icons/src \
rocks/bin rocks/lib/luarocks screenshots spec tools
# Adjust reader.lua a bit.
sed '1d' reader.lua >tempfile
@@ -162,6 +157,6 @@ codesign --force --deep -s - "${APP_BUNDLE}.app"
# Package as 7z reduces size from 80MB to 30MB.
if command_exists "7z"; then
7z a -l -m0=lzma2 -mx=9 "${APP_BUNDLE}-${APP_ARCH}-${VERSION}.7z" "${APP_BUNDLE}.app"
rm -rfv "${APP_BUNDLE}.app"
7z a -l -m0=flzma2 -mx=9 "${APP_BUNDLE}-${APP_ARCH}-${VERSION}.7z" "${APP_BUNDLE}.app"
rm -rf "${APP_BUNDLE}.app"
fi

View File

@@ -1,93 +0,0 @@
#!/usr/bin/env bash
set -eo pipefail
# set -x
[[ $# -ge 3 ]]
archive="$(realpath "$1")"
epoch="$2"
shift 2
options=()
for a in "$@"; do
shift
case "${a}" in
--) break ;;
-*) options+=("${a}") ;;
*) break ;;
esac
done
[[ $# -gt 0 ]]
patterns=("$@")
# We need to use the full path to the executable to avoid
# a weird issue when using the p7zip project pre-built
# binary (`Can't load './7z.dll' (7z.so)...`).
sevenzip="$(which 7z)"
# echo "archive : ${archive}"
# echo "epoch : ${epoch}"
# echo "options : ${options[@]}"
# echo "patterns: ${patterns[@]}"
tmpdir="$(mktemp -d -t tmp7z.XXXXXXXXXX)"
trap 'rm -rf "${tmpdir}"' EXIT
manifest="${tmpdir}/manifest"
# Detect if that version of 7z deferences symlinks by default.
sevenzip_manifest_cmd=("${sevenzip}" -ba h)
ln -s /dev/null "${tmpdir}/symlink"
checksum="$("${sevenzip_manifest_cmd[@]}" "${tmpdir}/symlink" | awk '{ print $1 }')"
if [[ "${checksum}" != '00000000' ]]; then
sevenzip_manifest_cmd+=(-l)
fi
rm -f "${tmpdir}/symlink"
# Note: remove trailing `/` appended to directories in some 7z versions.
"${sevenzip_manifest_cmd[@]}" "${patterns[@]}" |
awk '{ if ($3!="") print $3, $2, $1; else { gsub("/$", "", $1); print $1 } }' |
sort >"${manifest}"
# cat "${manifest}" | less
if [[ -r "${archive}" ]]; then
if diff --brief --label 'in archive' \
<(
"${sevenzip}" -slt l "${archive}" |
awk '
/^([^=]+) = / { entry[$1] = $3; }
/^CRC =/ { if ($3!="") print entry["Path"], entry["Size"], $3; else print entry["Path"] }
' | sort
) --label 'to add' "${manifest}"; then
exit
fi
# There's no 7z option to overwrite the archive
# if it already exists (instead of updating it)…
rm -f "${archive}"
fi
# Extract list of paths from manifest.
rev <"${manifest}" | cut -f3- -d' ' | rev >"${tmpdir}/paths"
# Quick sanity check: no path outside the current directory.
if grep '^(/|\.\./)' <"${tmpdir}/paths"; then
echo "^ some paths are outside the current directory!"
exit 1
fi
# Make a copy of everything so we can later
# patch timestamp to ensure reproducibility.
mkdir "${tmpdir}/contents"
# We want to copy "empty" (with ignored files) directories.
tar --dereference --no-recursion --create \
--verbatim-files-from --files-from="${tmpdir}/paths" |
tar --extract --directory="${tmpdir}/contents"
cd "${tmpdir}/contents"
# Fix timestamps.
find . -depth -print0 | xargs -0 touch --date="${epoch}"
# And create the final archive.
"${sevenzip}" -mqs "${options[@]}" a "${archive}" .
# vim: sw=4

317
tools/mkrelease.sh Executable file
View File

@@ -0,0 +1,317 @@
#!/usr/bin/env bash
set -eo pipefail
# set -x
declare -r USAGE="
USAGE:
$0 [OPTIONS] [--] ARCHIVE_NAME|DIRECTORY/ [PATTERNS]
OPTIONS:
-j N, --jobs N use up to N processes / threads
-e EPOCH, --epoch EPOCH set contents timestamp to EPOCH
-m ENTRY, --manifest ENTRY add a manifest ENTRY to the release
--manifest-transform SCRIPT transform manifest using sed SCRIPT
-o OPTS, --options OPTS forward options to compressor
"
# shellcheck disable=SC2016
declare -r AWK_HELPERS='
function print_entry(path, size, crc) {
sub("/$", "", path)
if (crc)
print path, size, crc
else
print path"/"
}
function reverse_entry() {
$0 = $3" "$2" "$1;
}
'
if [[ "${OSTYPE}" = darwin* ]]; then
declare -r READLINK=greadlink
declare -r TAR=gtar
else
declare -r READLINK=readlink
declare -r TAR=tar
fi
if ! opt=$(getopt -o '+de:hj:m:o:' --long 'debug,epoch:,help,jobs:,manifest:,manifest-transform:,options:' --name "$0" -- "$@"); then
echo "${USAGE}"
exit 1
fi
# Arguments parsing. {{{
debug=''
epoch=''
jobs=''
manifest=''
manifest_transform=''
options=()
eval set -- "${opt}"
while [[ $# -gt 0 ]]; do
case "$1" in
-d | --debug)
debug=1
;;
-e | --epoch)
epoch="$2"
shift
;;
-h | --help)
echo "${USAGE}"
exit 0
;;
-j | --jobs)
jobs="$2"
shift
;;
-m | --manifest)
manifest="$2"
shift
;;
--manifest-transform)
manifest_transform="$2"
shift
;;
-o | --options)
declare -a "a=($2)"
options+=("${a[@]}")
shift
;;
--)
shift
break
;;
esac
shift
done
if [[ $# -lt 1 ]]; then
echo "${USAGE}"
exit 1
fi
case "$1" in
*/) format='/' ;;
*.7z | *.zip) format="${1##*.}" ;;
*.tar.gz | *.targz) format=tar.gz ;;
*.tar.xz) format=tar.xz ;;
*.tar.zstd) format=tar.zstd ;;
*)
echo "ERROR: unsupported release format: ${1##*.}" 1>&2
exit 2
;;
esac
output="$("${READLINK}" -f "$1")"
shift
patterns=("$@")
if [[ -n "${manifest}" ]]; then
patterns+=("-x!${manifest}")
fi
# }}}
if command -v pv >/dev/null; then
write_to_file() {
pv --interval=0.25 --bytes --timer --rate --output="$1"
}
else
write_to_file() {
dd bs=4096 of="$1"
}
fi
# Ensure a "traditional" sort order.
export LC_ALL=C
# We need to use the full path to the executable to avoid
# a weird issue when using the p7zip project pre-built
# binary (`Can't load './7z.dll' (7z.so)...`).
if ! sevenzip="$(which 7z)"; then
echo "ERROR: 7z executable not found!" 1>&2
exit 2
fi
sevenzip_compress_cmd=("${sevenzip}")
# Setup temporary directory.
tmpdir="$(mktemp -d -t tmp7z.XXXXXXXXXX)"
trap 'rm -rf "${tmpdir}"' EXIT
mkdir -p "${tmpdir}/contents"
# Detect if that version of 7z deferences symlinks by default.
sevenzip_manifest_cmd=("${sevenzip}" -ba h)
ln -s /dev/null "${tmpdir}/symlink"
checksum="$("${sevenzip_manifest_cmd[@]}" "${tmpdir}/symlink" | awk '{ print $1 }')"
if [[ "${checksum}" != '00000000' ]]; then
sevenzip_manifest_cmd+=(-l)
fi
rm -f "${tmpdir}/symlink"
# Prefer `pigz` over `gzip` (faster).
gzip="$(command -v pigz || command -v gzip)"
gzip_cmd=("${gzip}")
# Jobs.
if [[ -n "${jobs}" ]]; then
[[ "${gzip}" != */pigz ]] || gzip_cmd+=(--processes "${jobs}")
sevenzip_compress_cmd+=(-mmt="${jobs}")
fi
# In-place sed command.
if [[ "${OSTYPE}" = darwin* ]]; then
ised=(sed -i '' -e)
else
ised=(sed -i -e)
fi
if [[ -n "${debug}" ]]; then
echo "format : ${format}"
echo "output : ${output}"
echo "manifest : ${manifest}"
echo "manifest transform : ${manifest_transform}"
echo "epoch : ${epoch}"
echo "options : ${options[*]@Q}"
echo "patterns : ${patterns[*]@Q}"
echo "7z executable : ${sevenzip}"
echo "7z compress command : ${sevenzip_compress_cmd[*]@Q}"
echo "7z manifest command : ${sevenzip_manifest_cmd[*]@Q}"
echo "gzip executable : ${gzip}"
echo "gzip command : ${gzip_cmd[*]@Q}"
echo "sed in-place command: ${ised[*]@Q}"
[[ -t 0 ]] && read -srn 1
fi
# Build manifest.
"${sevenzip_manifest_cmd[@]}" "${patterns[@]}" |
awk "${AWK_HELPERS}"'{ reverse_entry(); print_entry($1, $2, $3) }' |
sort -o "${tmpdir}/manifest"
# Extract list of paths from manifest.
rev <"${tmpdir}/manifest" | cut -f3- -d' ' | rev >"${tmpdir}/paths"
# Quick sanity check: no path outside the current directory.
if grep '^(/|\.\./)' <"${tmpdir}/paths"; then
echo "ERROR: ^ some paths are outside the current directory!"
exit 2
fi
# Don't forget the archive's internal manifest, if requested.
if [[ -n "${manifest}" ]]; then
manifest_path=("${manifest}")
while [[ "${manifest_path[0]}" = */*[^/] ]]; do
manifest_path=("${manifest_path[0]%/*}/" "${manifest_path[@]}")
done
{
cat "${tmpdir}/paths"
printf '%s\n' "${manifest_path[@]}"
} | sort -u -o "${tmpdir}/paths_with_manifest"
install --mode=0644 -D "${tmpdir}/paths_with_manifest" "${tmpdir}/contents/${manifest}"
if [[ -n "${manifest_transform}" ]]; then
"${ised[@]}" "${manifest_transform}" "${tmpdir}/contents/${manifest}"
fi
# Can't use 7z's `-w` option in this case…
pushd "${tmpdir}/contents" >/dev/null
"${sevenzip[@]}" -ba h |
awk "${AWK_HELPERS}"'{ reverse_entry(); print_entry($1, $2, $3) }' >>"${tmpdir}/manifest"
popd >/dev/null
sort -u -o "${tmpdir}/manifest" "${tmpdir}/manifest"
fi
if [[ -n "${debug}" ]] && [[ -t 0 ]]; then
paths=("${tmpdir}/manifest" "${tmpdir}"/paths*)
[[ -z "${manifest}" ]] || paths+=("${tmpdir}/contents/${manifest}")
less "${paths[@]}"
fi
# If the output already exists, check for changes.
if [[ -r "${output}" ]]; then
previous_manifest=''
case "${format}" in
/) ;;
tar*) ;;
*)
previous_manifest="$(
"${sevenzip[@]}" -ba -slt l "${output}" |
awk "${AWK_HELPERS}"'
/^[^=]+ = / { e[$1] = $3; }
/^$/ && e["Size"] != "" { print_entry(e["Path"], e["Size"], e["CRC"]) }
' | sort
)"
;;
esac
if [[ -n "${previous_manifest}" ]] &&
diff --color${CLICOLOR_FORCE:+=always} --unified \
--label 'old' <(printf '%s\n' "${previous_manifest}") \
--label 'new' "${tmpdir}/manifest"; then
exit
fi
# There's no 7z or zip option to overwrite the output
# if it already exists (instead of updating it), and
# it may be a directory anyway…
rm -rf "${output}"
fi
# Make a copy of everything so we can later patch timestamps and
# fix permissions to ensure reproducibility.
# Note: We want to keep "empty" (with ignored files) directories.
"${TAR}" --create --dereference --hard-dereference --no-recursion \
--verbatim-files-from --files-from="${tmpdir}/paths" |
"${TAR}" --extract --directory="${tmpdir}/contents"
cd "${tmpdir}/contents"
# Fix permissions.
chmod -R u=rwX,og=rX .
# Fix timestamps.
if [[ -n "${epoch}" ]]; then
find . -depth -print0 | xargs -0 touch --date="${epoch}"
fi
# And create the final output.
if [[ -n "${manifest}" ]]; then
filelist="${tmpdir}/paths_with_manifest"
else
filelist="${tmpdir}/paths"
fi
sevenzip_compress_cmd+=("${options[@]}" a "${output}" "-i@${filelist}")
tar_compress_cmd=(
"${TAR}" --create --no-recursion --owner=0 --group=0
--verbatim-files-from --files-from="${filelist}"
)
case "${format}" in
/)
mv "${tmpdir}/contents" "${output}"
;;
7z)
# Note: sort by type (for better compression).
"${sevenzip_compress_cmd[@]}" -mqs
;;
tar.gz)
echo "Creating archive: ${output}"
# Note: create a rsyncable gzipped tar.
"${tar_compress_cmd[@]}" |
"${gzip}" --no-name --rsyncable "${options[@]}" --stdout |
write_to_file "${output}"
;;
tar.xz)
echo "Creating archive: ${output}"
"${tar_compress_cmd[@]}" |
xz ${jobs:+--threads=${jobs}} "${options[@]}" |
write_to_file "${output}"
;;
tar.zstd)
echo "Creating archive: ${output}"
"${tar_compress_cmd[@]}" |
zstd ${jobs:+--threads=${jobs}} "${options[@]}" --stdout |
write_to_file "${output}"
;;
zip)
"${sevenzip_compress_cmd[@]}" -tzip
;;
esac
# vim: foldmethod=marker foldlevel=0 sw=4