mirror of
https://github.com/koreader/koreader.git
synced 2025-12-13 20:36:53 +01:00
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:
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -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
|
||||
|
||||
79
Makefile
79
Makefile
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
33
make/kobo.mk
33
make/kobo.mk
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
317
tools/mkrelease.sh
Executable 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
|
||||
Reference in New Issue
Block a user