From 2ddf5ad9f1fdb871fbc0651cdb02106c7bd87c1e Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Mon, 5 Jul 2021 11:09:40 -0500 Subject: [PATCH 01/20] Add format entry to AppImage section --- appimagebuilder/recipe/schema.py | 1 + 1 file changed, 1 insertion(+) diff --git a/appimagebuilder/recipe/schema.py b/appimagebuilder/recipe/schema.py index 2d198c91..4fd5f01e 100644 --- a/appimagebuilder/recipe/schema.py +++ b/appimagebuilder/recipe/schema.py @@ -93,6 +93,7 @@ def __init__(self): Optional("update-information"): str, Optional("sign-key"): str, Optional("file_name"): str, + Optional("format"): Or(2, 3), } ) From 097798757129dc2f1b75bde8def9fc704bc3b3f7 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Mon, 5 Jul 2021 11:31:07 -0500 Subject: [PATCH 02/20] Move AppImage module into prime package and rename it as type_2 This would allow us to support new types of AppImages --- appimagebuilder/commands/create_appimage.py | 4 ++-- appimagebuilder/modules/prime/__init__.py | 11 +++++++++++ .../modules/{appimage.py => prime/type_2.py} | 14 +++++++++++++- 3 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 appimagebuilder/modules/prime/__init__.py rename appimagebuilder/modules/{appimage.py => prime/type_2.py} (85%) diff --git a/appimagebuilder/commands/create_appimage.py b/appimagebuilder/commands/create_appimage.py index c9137a50..b34f1573 100644 --- a/appimagebuilder/commands/create_appimage.py +++ b/appimagebuilder/commands/create_appimage.py @@ -9,7 +9,7 @@ # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. -from appimagebuilder.modules.appimage import AppImageCreator +from appimagebuilder.modules.prime.type_2 import Type2Creator from appimagebuilder.commands.command import Command from appimagebuilder.recipe.roamer import Roamer @@ -23,5 +23,5 @@ def id(self): super().id() def __call__(self, *args, **kwargs): - creator = AppImageCreator(self.recipe) + creator = Type2Creator(self.recipe) creator.create() diff --git a/appimagebuilder/modules/prime/__init__.py b/appimagebuilder/modules/prime/__init__.py new file mode 100644 index 00000000..6f1f3c22 --- /dev/null +++ b/appimagebuilder/modules/prime/__init__.py @@ -0,0 +1,11 @@ +# Copyright 2021 Alexis Lopez Zubieta +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. diff --git a/appimagebuilder/modules/appimage.py b/appimagebuilder/modules/prime/type_2.py similarity index 85% rename from appimagebuilder/modules/appimage.py rename to appimagebuilder/modules/prime/type_2.py index e7722695..a0249beb 100644 --- a/appimagebuilder/modules/appimage.py +++ b/appimagebuilder/modules/prime/type_2.py @@ -1,3 +1,15 @@ +# Copyright 2021 Alexis Lopez Zubieta +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + # Copyright 2020 Alexis Lopez Zubieta # # Permission is hereby granted, free of charge, to any person obtaining a @@ -16,7 +28,7 @@ from appimagebuilder.gateways.appimagetool import AppImageToolCommand -class AppImageCreator: +class Type2Creator: def __init__(self, recipe): self.app_dir = recipe.AppDir.path() self.target_arch = recipe.AppImage.arch() From 320d90d9b7bb1bcd3b49c655e0749e6dfe4274d4 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Mon, 5 Jul 2021 11:52:39 -0500 Subject: [PATCH 03/20] Use format entry from AppImage section in recipe --- appimagebuilder/commands/create_appimage.py | 27 ++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/appimagebuilder/commands/create_appimage.py b/appimagebuilder/commands/create_appimage.py index b34f1573..dfae94d3 100644 --- a/appimagebuilder/commands/create_appimage.py +++ b/appimagebuilder/commands/create_appimage.py @@ -23,5 +23,30 @@ def id(self): super().id() def __call__(self, *args, **kwargs): - creator = Type2Creator(self.recipe) + appimage_format = self.recipe.AppImage.format() or 2 + if appimage_format == 2: + self._create_type_2_appimage() + return + + raise RuntimeError(f"Unknown AppImage format {appimage_format}") + + def _create_type_2_appimage(self): + app_dir = self.recipe.AppDir.path() + target_arch = self.recipe.AppImage.arch() + app_name = self.recipe.AppDir.app_info.name() + app_version = self.recipe.AppDir.app_info.version() + update_information = self.recipe.AppImage["update-information"]() or "None" + file_name = self.recipe.AppDir.app_info.file_name() + sign_key = self.recipe.AppImage["sign-key"] or "None" + if sign_key == "None": + sign_key = None + creator = Type2Creator( + app_dir, + app_name, + app_version, + target_arch, + update_information, + sign_key, + file_name, + ) creator.create() From c75f462ad107618fac285d48d52d53670006f4be Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Mon, 5 Jul 2021 12:17:18 -0500 Subject: [PATCH 04/20] Draft type 3 AppImage creator --- appimagebuilder/commands/create_appimage.py | 15 +++++++++++++-- appimagebuilder/modules/prime/type_3.py | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 appimagebuilder/modules/prime/type_3.py diff --git a/appimagebuilder/commands/create_appimage.py b/appimagebuilder/commands/create_appimage.py index dfae94d3..09faf0cb 100644 --- a/appimagebuilder/commands/create_appimage.py +++ b/appimagebuilder/commands/create_appimage.py @@ -11,6 +11,7 @@ # all copies or substantial portions of the Software. from appimagebuilder.modules.prime.type_2 import Type2Creator from appimagebuilder.commands.command import Command +from appimagebuilder.modules.prime.type_3 import Type3Creator from appimagebuilder.recipe.roamer import Roamer @@ -24,14 +25,20 @@ def id(self): def __call__(self, *args, **kwargs): appimage_format = self.recipe.AppImage.format() or 2 + self.app_dir = self.recipe.AppDir.path() + if appimage_format == 2: self._create_type_2_appimage() return + if appimage_format == 3: + self._create_type_3_appimage() + return + raise RuntimeError(f"Unknown AppImage format {appimage_format}") def _create_type_2_appimage(self): - app_dir = self.recipe.AppDir.path() + target_arch = self.recipe.AppImage.arch() app_name = self.recipe.AppDir.app_info.name() app_version = self.recipe.AppDir.app_info.version() @@ -41,7 +48,7 @@ def _create_type_2_appimage(self): if sign_key == "None": sign_key = None creator = Type2Creator( - app_dir, + self.app_dir, app_name, app_version, target_arch, @@ -50,3 +57,7 @@ def _create_type_2_appimage(self): file_name, ) creator.create() + + def _create_type_3_appimage(self): + creator = Type3Creator(self.app_dir) + creator.create() diff --git a/appimagebuilder/modules/prime/type_3.py b/appimagebuilder/modules/prime/type_3.py new file mode 100644 index 00000000..23006487 --- /dev/null +++ b/appimagebuilder/modules/prime/type_3.py @@ -0,0 +1,21 @@ +# Copyright 2021 Alexis Lopez Zubieta +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +import logging + + +class Type3Creator: + def __init__(self, app_dir): + self.logger = logging.getLogger() + self.app_dir = app_dir + + def create(self): + self.logger.warning("Type 3 AppImages are still experimental and under development!") From c8803ccdffa8c6c65fcea96659bde11df1f8d62a Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Thu, 8 Jul 2021 11:56:41 -0500 Subject: [PATCH 05/20] refactor: move setup operations out of the type 2 appimage creator --- appimagebuilder/commands/create_appimage.py | 25 ++++++---- appimagebuilder/modules/prime/type_3.py | 55 +++++++++++++++++++-- 2 files changed, 68 insertions(+), 12 deletions(-) diff --git a/appimagebuilder/commands/create_appimage.py b/appimagebuilder/commands/create_appimage.py index 09faf0cb..5b4be3b5 100644 --- a/appimagebuilder/commands/create_appimage.py +++ b/appimagebuilder/commands/create_appimage.py @@ -9,6 +9,8 @@ # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. +import os + from appimagebuilder.modules.prime.type_2 import Type2Creator from appimagebuilder.commands.command import Command from appimagebuilder.modules.prime.type_3 import Type3Creator @@ -27,6 +29,16 @@ def __call__(self, *args, **kwargs): appimage_format = self.recipe.AppImage.format() or 2 self.app_dir = self.recipe.AppDir.path() + self.target_arch = self.recipe.AppImage.arch() + self.app_name = self.recipe.AppDir.app_info.name() + self.app_version = self.recipe.AppDir.app_info.version() + + fallback_file_name = os.path.join( + os.getcwd(), + "%s-%s-%s.AppImage" % (self.app_name, self.app_version, self.target_arch), + ) + self.file_name = self.recipe.AppDir.app_info.file_name() or fallback_file_name + if appimage_format == 2: self._create_type_2_appimage() return @@ -39,25 +51,20 @@ def __call__(self, *args, **kwargs): def _create_type_2_appimage(self): - target_arch = self.recipe.AppImage.arch() - app_name = self.recipe.AppDir.app_info.name() - app_version = self.recipe.AppDir.app_info.version() update_information = self.recipe.AppImage["update-information"]() or "None" - file_name = self.recipe.AppDir.app_info.file_name() + sign_key = self.recipe.AppImage["sign-key"] or "None" if sign_key == "None": sign_key = None creator = Type2Creator( self.app_dir, - app_name, - app_version, - target_arch, + self.target_arch, update_information, sign_key, - file_name, + self.file_name, ) creator.create() def _create_type_3_appimage(self): creator = Type3Creator(self.app_dir) - creator.create() + creator.create(self.file_name) diff --git a/appimagebuilder/modules/prime/type_3.py b/appimagebuilder/modules/prime/type_3.py index 23006487..026e0cce 100644 --- a/appimagebuilder/modules/prime/type_3.py +++ b/appimagebuilder/modules/prime/type_3.py @@ -10,12 +10,61 @@ # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. import logging +import os +import pathlib +import shutil +import subprocess + +from appimagebuilder.utils import shell, elf class Type3Creator: def __init__(self, app_dir): self.logger = logging.getLogger() - self.app_dir = app_dir + self.app_dir = pathlib.Path(app_dir).absolute() + + self.required_tool_paths = shell.resolve_commands_paths(["mksquashfs"]) + + def create(self, filename): + self.logger.warning( + "Type 3 AppImages are still experimental and under development!" + ) + + squashfs_path = self._squash_appdir() + + executable_path = self._resolve_executable() + + self._merge_parts(executable_path, squashfs_path, filename) + + def _squash_appdir(self): + squashfs_path = "./AppDir.sqfs" + + self.logger.info("Squashing AppDir") + command = "{mksquashfs} {AppDir} {squashfs_path}".format( + AppDir=self.app_dir, squashfs_path=squashfs_path, **self.required_tool_paths + ) + _proc = subprocess.run( + command, + stderr=subprocess.PIPE, + shell=True, + ) + + shell.assert_successful_result(_proc) + return squashfs_path + + def _resolve_executable(self): + launcher_arch = elf.get_arch(self.app_dir / "AppRun") + return "appimage-builder-cache/runtime-experimental" + + def _merge_parts(self, executable_path, squashfs_path, filename): + shutil.copyfile(executable_path, filename) + + with open(filename, "r+b") as exec_fd: + payload_offset = exec_fd.seek(0, 2) + + with open(squashfs_path, "rb") as sqfs_fd: + sqfs_data = sqfs_fd.read() + exec_fd.write(memoryview(sqfs_data)) - def create(self): - self.logger.warning("Type 3 AppImages are still experimental and under development!") + sqfs_fd.seek(0, 0) + shutil.copyfileobj(sqfs_fd, exec_fd) From eb4e6b1311b823f63f86ccc7468574397f0db2c6 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Mon, 26 Jul 2021 19:37:47 -0500 Subject: [PATCH 06/20] feature: write type 3 header --- appimagebuilder/modules/prime/type_3.py | 20 ++++++++++++++++---- examples/kcalc/AppImageBuilder.yml | 1 + 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/appimagebuilder/modules/prime/type_3.py b/appimagebuilder/modules/prime/type_3.py index 026e0cce..c379f498 100644 --- a/appimagebuilder/modules/prime/type_3.py +++ b/appimagebuilder/modules/prime/type_3.py @@ -25,16 +25,21 @@ def __init__(self, app_dir): self.required_tool_paths = shell.resolve_commands_paths(["mksquashfs"]) - def create(self, filename): + def create(self, output_filename): self.logger.warning( "Type 3 AppImages are still experimental and under development!" ) squashfs_path = self._squash_appdir() - executable_path = self._resolve_executable() + runtime_path = self._resolve_executable() - self._merge_parts(executable_path, squashfs_path, filename) + self._merge_parts(runtime_path, squashfs_path, output_filename) + + payload_offset = os.path.getsize(runtime_path) + resources_offset = os.path.getsize(output_filename) + + self._fill_header(output_filename, payload_offset, resources_offset, 0) def _squash_appdir(self): squashfs_path = "./AppDir.sqfs" @@ -54,7 +59,7 @@ def _squash_appdir(self): def _resolve_executable(self): launcher_arch = elf.get_arch(self.app_dir / "AppRun") - return "appimage-builder-cache/runtime-experimental" + return "/home/alexis/Workspace/AppImage/type3-runtime/cmake-build-debug/src/runtime/runtime" def _merge_parts(self, executable_path, squashfs_path, filename): shutil.copyfile(executable_path, filename) @@ -68,3 +73,10 @@ def _merge_parts(self, executable_path, squashfs_path, filename): sqfs_fd.seek(0, 0) shutil.copyfileobj(sqfs_fd, exec_fd) + + def _fill_header(self, output_filename, payload_offset, resources_offset, signature_offset): + with open(output_filename, "r+b") as f: + f.seek(0x410, 0) + f.write(payload_offset.to_bytes(8, 'little')) + f.write(resources_offset.to_bytes(8, 'little')) + f.write(signature_offset.to_bytes(8, 'little')) diff --git a/examples/kcalc/AppImageBuilder.yml b/examples/kcalc/AppImageBuilder.yml index 889974c8..70a109d5 100644 --- a/examples/kcalc/AppImageBuilder.yml +++ b/examples/kcalc/AppImageBuilder.yml @@ -73,3 +73,4 @@ AppImage: update-information: None sign-key: None arch: x86_64 + format: 3 From 2b782712770a617899519dfe8e93ba7303196738 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Thu, 29 Jul 2021 17:38:44 -0500 Subject: [PATCH 07/20] feat: use AppImageCrafters runtime on type 3 builds --- appimagebuilder/modules/prime/common.py | 20 ++++++++++++++++++++ appimagebuilder/modules/prime/type_2.py | 8 ++------ appimagebuilder/modules/prime/type_3.py | 22 ++++++++++++++++++++-- 3 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 appimagebuilder/modules/prime/common.py diff --git a/appimagebuilder/modules/prime/common.py b/appimagebuilder/modules/prime/common.py new file mode 100644 index 00000000..11f53782 --- /dev/null +++ b/appimagebuilder/modules/prime/common.py @@ -0,0 +1,20 @@ +# Copyright 2021 Alexis Lopez Zubieta +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +import logging +import os +from urllib import request + + +def download_if_required(url, path): + if not os.path.exists(path): + logging.info("Downloading: %s" % url) + request.urlretrieve(url, path) diff --git a/appimagebuilder/modules/prime/type_2.py b/appimagebuilder/modules/prime/type_2.py index a0249beb..592f0029 100644 --- a/appimagebuilder/modules/prime/type_2.py +++ b/appimagebuilder/modules/prime/type_2.py @@ -26,6 +26,7 @@ from urllib import request from appimagebuilder.gateways.appimagetool import AppImageToolCommand +from appimagebuilder.modules.prime import common class Type2Creator: @@ -61,7 +62,7 @@ def create(self): runtime_url = self._get_runtime_url() runtime_path = self._get_runtime_path() - self._download_runtime_if_required(runtime_path, runtime_url) + common.download_if_required(runtime_url, runtime_path) self._generate_appimage(runtime_path) @@ -74,11 +75,6 @@ def _generate_appimage(self, runtime_path): appimage_tool.runtime_file = runtime_path appimage_tool.run() - def _download_runtime_if_required(self, runtime_path, runtime_url): - if not os.path.exists(runtime_path): - logging.info("Downloading runtime: %s" % runtime_url) - request.urlretrieve(runtime_url, runtime_path) - def _get_runtime_path(self): os.makedirs("appimage-builder-cache", exist_ok=True) runtime_path = "appimage-builder-cache/runtime-%s" % self.target_arch diff --git a/appimagebuilder/modules/prime/type_3.py b/appimagebuilder/modules/prime/type_3.py index c379f498..95e68a6f 100644 --- a/appimagebuilder/modules/prime/type_3.py +++ b/appimagebuilder/modules/prime/type_3.py @@ -15,13 +15,16 @@ import shutil import subprocess +from appimagebuilder.modules.prime import common from appimagebuilder.utils import shell, elf class Type3Creator: - def __init__(self, app_dir): + def __init__(self, app_dir, cache_dir="appimage-builder-cache"): self.logger = logging.getLogger() self.app_dir = pathlib.Path(app_dir).absolute() + self.cache_dir = pathlib.Path(cache_dir) + self.runtime_project_url = "https://github.com/AppImageCrafters/appimage-runtime" self.required_tool_paths = shell.resolve_commands_paths(["mksquashfs"]) @@ -59,7 +62,11 @@ def _squash_appdir(self): def _resolve_executable(self): launcher_arch = elf.get_arch(self.app_dir / "AppRun") - return "/home/alexis/Workspace/AppImage/type3-runtime/cmake-build-debug/src/runtime/runtime" + url = self._get_runtime_url(launcher_arch) + path = self._get_runtime_path(launcher_arch) + common.download_if_required(url, path.__str__()) + + return path def _merge_parts(self, executable_path, squashfs_path, filename): shutil.copyfile(executable_path, filename) @@ -80,3 +87,14 @@ def _fill_header(self, output_filename, payload_offset, resources_offset, signat f.write(payload_offset.to_bytes(8, 'little')) f.write(resources_offset.to_bytes(8, 'little')) f.write(signature_offset.to_bytes(8, 'little')) + + def _get_runtime_path(self, arch): + self.cache_dir.parent.mkdir(parents=True, exist_ok=True) + runtime_path = self.cache_dir / f"runtime-{arch}" + + return runtime_path + + def _get_runtime_url(self, arch): + runtime_url_template = self.runtime_project_url + "/releases/download/continuous/runtime-Release-%s" + runtime_url = runtime_url_template % arch + return runtime_url From 63fa099a6d70d9aa7e6f42e42cb1a4c38cfdcc3c Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Thu, 29 Jul 2021 17:49:53 -0500 Subject: [PATCH 08/20] fix: regression on type 2 prime --- appimagebuilder/modules/prime/type_2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appimagebuilder/modules/prime/type_2.py b/appimagebuilder/modules/prime/type_2.py index 592f0029..29de1a60 100644 --- a/appimagebuilder/modules/prime/type_2.py +++ b/appimagebuilder/modules/prime/type_2.py @@ -67,7 +67,7 @@ def create(self): self._generate_appimage(runtime_path) def _generate_appimage(self, runtime_path): - appimage_tool = AppImageToolCommand(self.app_dir, self.target_file) + appimage_tool = AppImageToolCommand(self.app_dir, self.file_name) appimage_tool.target_arch = self.target_arch appimage_tool.update_information = self.update_information appimage_tool.guess_update_information = self.guess_update_information From 83d85a7060ec6bd67f0b502041ec519411480083 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Thu, 29 Jul 2021 17:56:56 -0500 Subject: [PATCH 09/20] ref: store AppDir.sqsf into the build cache dir --- appimagebuilder/modules/prime/type_3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appimagebuilder/modules/prime/type_3.py b/appimagebuilder/modules/prime/type_3.py index 95e68a6f..76c36d44 100644 --- a/appimagebuilder/modules/prime/type_3.py +++ b/appimagebuilder/modules/prime/type_3.py @@ -45,7 +45,7 @@ def create(self, output_filename): self._fill_header(output_filename, payload_offset, resources_offset, 0) def _squash_appdir(self): - squashfs_path = "./AppDir.sqfs" + squashfs_path = self.cache_dir / "AppDir.sqfs" self.logger.info("Squashing AppDir") command = "{mksquashfs} {AppDir} {squashfs_path}".format( From 12118d58e554216ce1adfd6a8d3e82f0b43682a3 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Thu, 29 Jul 2021 17:57:26 -0500 Subject: [PATCH 10/20] feat: remove AppDir.sqfs after build --- appimagebuilder/modules/prime/type_3.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appimagebuilder/modules/prime/type_3.py b/appimagebuilder/modules/prime/type_3.py index 76c36d44..3edc30f8 100644 --- a/appimagebuilder/modules/prime/type_3.py +++ b/appimagebuilder/modules/prime/type_3.py @@ -44,6 +44,9 @@ def create(self, output_filename): self._fill_header(output_filename, payload_offset, resources_offset, 0) + # remove squashfs + squashfs_path.unlink() + def _squash_appdir(self): squashfs_path = self.cache_dir / "AppDir.sqfs" From 1701ac0d938c4af323d22e5aa5f2e195de858d48 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Thu, 29 Jul 2021 17:57:54 -0500 Subject: [PATCH 11/20] feat: use "-reproducible" option while creating the AppDir.sqfs --- appimagebuilder/modules/prime/type_3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appimagebuilder/modules/prime/type_3.py b/appimagebuilder/modules/prime/type_3.py index 3edc30f8..1ad99ffe 100644 --- a/appimagebuilder/modules/prime/type_3.py +++ b/appimagebuilder/modules/prime/type_3.py @@ -51,7 +51,7 @@ def _squash_appdir(self): squashfs_path = self.cache_dir / "AppDir.sqfs" self.logger.info("Squashing AppDir") - command = "{mksquashfs} {AppDir} {squashfs_path}".format( + command = "{mksquashfs} {AppDir} {squashfs_path} -reproducible".format( AppDir=self.app_dir, squashfs_path=squashfs_path, **self.required_tool_paths ) _proc = subprocess.run( From 913c5abbe58b8238749a477be6f7544e67a7e959 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Thu, 29 Jul 2021 18:15:27 -0500 Subject: [PATCH 12/20] drop noop --- appimagebuilder/modules/prime/type_3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appimagebuilder/modules/prime/type_3.py b/appimagebuilder/modules/prime/type_3.py index 1ad99ffe..1e47c6e1 100644 --- a/appimagebuilder/modules/prime/type_3.py +++ b/appimagebuilder/modules/prime/type_3.py @@ -75,7 +75,7 @@ def _merge_parts(self, executable_path, squashfs_path, filename): shutil.copyfile(executable_path, filename) with open(filename, "r+b") as exec_fd: - payload_offset = exec_fd.seek(0, 2) + exec_fd.seek(0, 2) with open(squashfs_path, "rb") as sqfs_fd: sqfs_data = sqfs_fd.read() From f23eb080f8c61a23fbf3452cfffc34509107ffbf Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Thu, 29 Jul 2021 18:19:26 -0500 Subject: [PATCH 13/20] ref: move extend_file from type_3 to file_utils --- appimagebuilder/modules/prime/type_3.py | 16 ++-------------- appimagebuilder/utils/file_utils.py | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/appimagebuilder/modules/prime/type_3.py b/appimagebuilder/modules/prime/type_3.py index 1e47c6e1..1e71ab68 100644 --- a/appimagebuilder/modules/prime/type_3.py +++ b/appimagebuilder/modules/prime/type_3.py @@ -17,6 +17,7 @@ from appimagebuilder.modules.prime import common from appimagebuilder.utils import shell, elf +from appimagebuilder.utils import file_utils class Type3Creator: @@ -37,7 +38,7 @@ def create(self, output_filename): runtime_path = self._resolve_executable() - self._merge_parts(runtime_path, squashfs_path, output_filename) + file_utils.extend_file(runtime_path, squashfs_path, output_filename) payload_offset = os.path.getsize(runtime_path) resources_offset = os.path.getsize(output_filename) @@ -71,19 +72,6 @@ def _resolve_executable(self): return path - def _merge_parts(self, executable_path, squashfs_path, filename): - shutil.copyfile(executable_path, filename) - - with open(filename, "r+b") as exec_fd: - exec_fd.seek(0, 2) - - with open(squashfs_path, "rb") as sqfs_fd: - sqfs_data = sqfs_fd.read() - exec_fd.write(memoryview(sqfs_data)) - - sqfs_fd.seek(0, 0) - shutil.copyfileobj(sqfs_fd, exec_fd) - def _fill_header(self, output_filename, payload_offset, resources_offset, signature_offset): with open(output_filename, "r+b") as f: f.seek(0x410, 0) diff --git a/appimagebuilder/utils/file_utils.py b/appimagebuilder/utils/file_utils.py index 9389a5d1..4227ad8e 100644 --- a/appimagebuilder/utils/file_utils.py +++ b/appimagebuilder/utils/file_utils.py @@ -10,6 +10,7 @@ # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. import os +import shutil import stat @@ -24,3 +25,17 @@ def set_permissions_rx_all(path): | stat.S_IXOTH | stat.S_IWUSR, ) + + +def extend_file(base_filename, extension_filename, output_filename): + shutil.copyfile(base_filename, output_filename) + + with open(output_filename, "r+b") as exec_fd: + exec_fd.seek(0, 2) + + with open(extension_filename, "rb") as sqfs_fd: + sqfs_data = sqfs_fd.read() + exec_fd.write(memoryview(sqfs_data)) + + sqfs_fd.seek(0, 0) + shutil.copyfileobj(sqfs_fd, exec_fd) From 1d9ae1a6d13f219c7ac64f56cc385eaa2626426c Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Wed, 11 Aug 2021 13:38:56 -0500 Subject: [PATCH 14/20] feat: allow signing type 3 AppImages --- Pipfile | 1 + appimagebuilder/__main__.py | 12 -- appimagebuilder/commands/create_appimage.py | 9 +- appimagebuilder/modules/prime/type_3.py | 115 ++++++++++++++++-- .../modules/setup/executables_wrapper.py | 10 +- appimagebuilder/modules/setup/generator.py | 6 +- appimagebuilder/utils/file_utils.py | 14 +-- 7 files changed, 126 insertions(+), 41 deletions(-) diff --git a/Pipfile b/Pipfile index 2c820966..19207778 100644 --- a/Pipfile +++ b/Pipfile @@ -16,6 +16,7 @@ emrichen = "*" shutils = "*" "ruamel.yaml" = "*" "roam" = "*" +bson = "*" [requires] python_version = "3.8" diff --git a/appimagebuilder/__main__.py b/appimagebuilder/__main__.py index d81cae47..18842660 100755 --- a/appimagebuilder/__main__.py +++ b/appimagebuilder/__main__.py @@ -12,18 +12,6 @@ # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. -# Copyright 2020 Alexis Lopez Zubieta -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - import logging from appimagebuilder import recipe diff --git a/appimagebuilder/commands/create_appimage.py b/appimagebuilder/commands/create_appimage.py index 5b4be3b5..bfe687ab 100644 --- a/appimagebuilder/commands/create_appimage.py +++ b/appimagebuilder/commands/create_appimage.py @@ -67,4 +67,11 @@ def _create_type_2_appimage(self): def _create_type_3_appimage(self): creator = Type3Creator(self.app_dir) - creator.create(self.file_name) + creator.create( + self.file_name, + { + "update-information": self.recipe.AppImage["update-information"]() + or "None" + }, + [self.recipe.AppImage["sign-key"]() or "None"], + ) diff --git a/appimagebuilder/modules/prime/type_3.py b/appimagebuilder/modules/prime/type_3.py index 1e71ab68..2586c52e 100644 --- a/appimagebuilder/modules/prime/type_3.py +++ b/appimagebuilder/modules/prime/type_3.py @@ -12,12 +12,14 @@ import logging import os import pathlib -import shutil import subprocess +import tempfile + +import bson from appimagebuilder.modules.prime import common -from appimagebuilder.utils import shell, elf from appimagebuilder.utils import file_utils +from appimagebuilder.utils import shell, elf class Type3Creator: @@ -25,11 +27,19 @@ def __init__(self, app_dir, cache_dir="appimage-builder-cache"): self.logger = logging.getLogger() self.app_dir = pathlib.Path(app_dir).absolute() self.cache_dir = pathlib.Path(cache_dir) - self.runtime_project_url = "https://github.com/AppImageCrafters/appimage-runtime" + self.runtime_project_url = ( + "https://github.com/AppImageCrafters/appimage-runtime" + ) + + self.required_tool_paths = shell.resolve_commands_paths(["mksquashfs", "gpg"]) - self.required_tool_paths = shell.resolve_commands_paths(["mksquashfs"]) + def create(self, output_filename, metadata=None, gnupg_keys=None): + if metadata is None: + metadata = {} + + if gnupg_keys is None: + gnupg_keys = [] - def create(self, output_filename): self.logger.warning( "Type 3 AppImages are still experimental and under development!" ) @@ -41,10 +51,14 @@ def create(self, output_filename): file_utils.extend_file(runtime_path, squashfs_path, output_filename) payload_offset = os.path.getsize(runtime_path) - resources_offset = os.path.getsize(output_filename) - - self._fill_header(output_filename, payload_offset, resources_offset, 0) + metadata_offset = os.path.getsize(output_filename) + self._append_metadata(output_filename, metadata) + signatures_offset = os.path.getsize(output_filename) + self._fill_header( + output_filename, payload_offset, metadata_offset, signatures_offset + ) + self._sign_bundle(output_filename, gnupg_keys, signatures_offset) # remove squashfs squashfs_path.unlink() @@ -72,12 +86,14 @@ def _resolve_executable(self): return path - def _fill_header(self, output_filename, payload_offset, resources_offset, signature_offset): + def _fill_header( + self, output_filename, payload_offset, metadata_offset, signature_offset + ): with open(output_filename, "r+b") as f: f.seek(0x410, 0) - f.write(payload_offset.to_bytes(8, 'little')) - f.write(resources_offset.to_bytes(8, 'little')) - f.write(signature_offset.to_bytes(8, 'little')) + f.write(payload_offset.to_bytes(8, "little")) + f.write(metadata_offset.to_bytes(8, "little")) + f.write(signature_offset.to_bytes(8, "little")) def _get_runtime_path(self, arch): self.cache_dir.parent.mkdir(parents=True, exist_ok=True) @@ -86,6 +102,79 @@ def _get_runtime_path(self, arch): return runtime_path def _get_runtime_url(self, arch): - runtime_url_template = self.runtime_project_url + "/releases/download/continuous/runtime-Release-%s" + runtime_url_template = ( + self.runtime_project_url + + "/releases/download/continuous/runtime-Release-%s" + ) runtime_url = runtime_url_template % arch return runtime_url + + def _append_metadata(self, output_filename, metadata): + raw = bson.dumps(metadata) + + with open(output_filename, "r+b") as fd: + fd.seek(0, 2) + fd.write(raw) + + def _sign_bundle(self, output_filename, gnupg_keys, signatures_offset): + signatures = [] + + for keyid in gnupg_keys: + signature = self._generate_bundle_signature_using_gpg( + keyid, output_filename, signatures_offset + ) + signatures.append( + { + "method": "gpg", + "keyid": keyid, + "data": signature, + } + ) + + encoded_signatures = bson.dumps({"signatures": signatures}) + with open(output_filename, "r+b") as fd: + fd.seek(signatures_offset, 0) + fd.write(encoded_signatures) + + def _generate_bundle_signature_using_gpg(self, keyid, filename, limit): + # file chunks will be written here + input_path = tempfile.NamedTemporaryFile().name + os.mkfifo(input_path) + + # sign the file with out including the signatures section + output_path = tempfile.NamedTemporaryFile().name + + # call gpg + args = [ + self.required_tool_paths["gpg"], + "--detach-sign", + "--armor", + "--default-key", + keyid, + "--output", + output_path, + input_path, + ] + + with subprocess.Popen(args) as _proc: + # read file contents up to limit + with open(input_path, "wb") as input_pipe: + chunk_size = 1024 + n_chunks = int(limit / chunk_size) + with open(filename, "rb") as input_file: + for chunk_id in range(n_chunks): + input_pipe.write(input_file.read(chunk_size)) + + final_chunk_size = limit - (n_chunks * chunk_size) + if final_chunk_size != 0: + input_pipe.write(input_file.read(final_chunk_size)) + + input_pipe.close() + + # read output + with open(output_path, "rb") as output: + signature = output.read().decode() + + os.unlink(output_path) + os.unlink(input_path) + return signature diff --git a/appimagebuilder/modules/setup/executables_wrapper.py b/appimagebuilder/modules/setup/executables_wrapper.py index 5e3682ad..dfad20ec 100644 --- a/appimagebuilder/modules/setup/executables_wrapper.py +++ b/appimagebuilder/modules/setup/executables_wrapper.py @@ -30,10 +30,10 @@ class ExecutablesWrapper: EXPORTED_FILES_PREFIX = "/tmp/appimage-" def __init__( - self, - appdir_path: str, - binaries_resolver: AppRunBinariesResolver, - env: Environment, + self, + appdir_path: str, + binaries_resolver: AppRunBinariesResolver, + env: Environment, ): self.appdir_path = Path(appdir_path) self.binaries_resolver = binaries_resolver @@ -131,7 +131,7 @@ def _write_rel_shebang(self, executable, local_env_path, output): output.write(b"#!%s" % local_env_path.encode()) shebang_main = executable.shebang[0] if shebang_main.startswith("/usr/bin/env") or shebang_main.startswith( - self.EXPORTED_FILES_PREFIX + self.EXPORTED_FILES_PREFIX ): args_start = 2 else: diff --git a/appimagebuilder/modules/setup/generator.py b/appimagebuilder/modules/setup/generator.py index 024a0332..6b3b3627 100644 --- a/appimagebuilder/modules/setup/generator.py +++ b/appimagebuilder/modules/setup/generator.py @@ -187,9 +187,9 @@ def parse_env_input(self, user_env_input): v = v.replace("${APPDIR}", self.appdir_path.__str__()) if ( - k == "PATH" - or k == "APPDIR_LIBRARY_PATH" - or k == "LIBC_LIBRARY_PATH" + k == "PATH" + or k == "APPDIR_LIBRARY_PATH" + or k == "LIBC_LIBRARY_PATH" ): v = v.split(":") diff --git a/appimagebuilder/utils/file_utils.py b/appimagebuilder/utils/file_utils.py index 4227ad8e..7b1a4fc8 100644 --- a/appimagebuilder/utils/file_utils.py +++ b/appimagebuilder/utils/file_utils.py @@ -30,12 +30,12 @@ def set_permissions_rx_all(path): def extend_file(base_filename, extension_filename, output_filename): shutil.copyfile(base_filename, output_filename) - with open(output_filename, "r+b") as exec_fd: - exec_fd.seek(0, 2) + with open(output_filename, "r+b") as base_fd: + base_fd.seek(0, 2) - with open(extension_filename, "rb") as sqfs_fd: - sqfs_data = sqfs_fd.read() - exec_fd.write(memoryview(sqfs_data)) + with open(extension_filename, "rb") as extensions_fd: + raw_data = extensions_fd.read() + base_fd.write(memoryview(raw_data)) - sqfs_fd.seek(0, 0) - shutil.copyfileobj(sqfs_fd, exec_fd) + extensions_fd.seek(0, 0) + shutil.copyfileobj(extensions_fd, base_fd) From dd22744e38c368f58bd9f862755608f1321bd136 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Wed, 11 Aug 2021 14:39:58 -0500 Subject: [PATCH 15/20] fix: add bson to the install_requires --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 94b01d44..fe9ca961 100644 --- a/setup.py +++ b/setup.py @@ -52,6 +52,7 @@ "emrichen", "ruamel.yaml", "roam", + "bson", ], python_requires=">=3.6", package_data={"": []}, From 4a953c54c8622f3ed6988edba82d5f757be35b16 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Thu, 12 Aug 2021 16:39:01 -0500 Subject: [PATCH 16/20] ref: use zstd as default compression method --- appimagebuilder/commands/create_appimage.py | 7 +-- appimagebuilder/modules/prime/type_3.py | 53 +++++++++++---------- appimagebuilder/recipe/schema.py | 3 ++ 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/appimagebuilder/commands/create_appimage.py b/appimagebuilder/commands/create_appimage.py index bfe687ab..1c024722 100644 --- a/appimagebuilder/commands/create_appimage.py +++ b/appimagebuilder/commands/create_appimage.py @@ -66,12 +66,13 @@ def _create_type_2_appimage(self): creator.create() def _create_type_3_appimage(self): + update_information = self.recipe.AppImage["update-information"]() or "None" creator = Type3Creator(self.app_dir) creator.create( self.file_name, { - "update-information": self.recipe.AppImage["update-information"]() - or "None" + "update-information": update_information }, - [self.recipe.AppImage["sign-key"]() or "None"], + gnupg_key=self.recipe.AppImage["sign-key"]() or None, + compression_method="zstd", ) diff --git a/appimagebuilder/modules/prime/type_3.py b/appimagebuilder/modules/prime/type_3.py index 2586c52e..4ffb5069 100644 --- a/appimagebuilder/modules/prime/type_3.py +++ b/appimagebuilder/modules/prime/type_3.py @@ -33,18 +33,17 @@ def __init__(self, app_dir, cache_dir="appimage-builder-cache"): self.required_tool_paths = shell.resolve_commands_paths(["mksquashfs", "gpg"]) - def create(self, output_filename, metadata=None, gnupg_keys=None): + def create( + self, output_filename, metadata=None, gnupg_key=None, compression_method="gzip" + ): if metadata is None: metadata = {} - if gnupg_keys is None: - gnupg_keys = [] - self.logger.warning( "Type 3 AppImages are still experimental and under development!" ) - squashfs_path = self._squash_appdir() + squashfs_path = self._squash_appdir(compression_method) runtime_path = self._resolve_executable() @@ -58,16 +57,19 @@ def create(self, output_filename, metadata=None, gnupg_keys=None): output_filename, payload_offset, metadata_offset, signatures_offset ) - self._sign_bundle(output_filename, gnupg_keys, signatures_offset) + self._sign_bundle(output_filename, gnupg_key, signatures_offset) # remove squashfs squashfs_path.unlink() - def _squash_appdir(self): + def _squash_appdir(self, compression_method): squashfs_path = self.cache_dir / "AppDir.sqfs" self.logger.info("Squashing AppDir") - command = "{mksquashfs} {AppDir} {squashfs_path} -reproducible".format( - AppDir=self.app_dir, squashfs_path=squashfs_path, **self.required_tool_paths + command = "{mksquashfs} {AppDir} {squashfs_path} -reproducible -comp {compression} ".format( + AppDir=self.app_dir, + squashfs_path=squashfs_path, + compression=compression_method, + **self.required_tool_paths, ) _proc = subprocess.run( command, @@ -116,22 +118,23 @@ def _append_metadata(self, output_filename, metadata): fd.seek(0, 2) fd.write(raw) - def _sign_bundle(self, output_filename, gnupg_keys, signatures_offset): - signatures = [] - - for keyid in gnupg_keys: - signature = self._generate_bundle_signature_using_gpg( - keyid, output_filename, signatures_offset - ) - signatures.append( - { - "method": "gpg", - "keyid": keyid, - "data": signature, - } - ) - - encoded_signatures = bson.dumps({"signatures": signatures}) + def _sign_bundle(self, output_filename, keyid, signatures_offset): + signature = self._generate_bundle_signature_using_gpg( + keyid, output_filename, signatures_offset + ) + + encoded_signatures = bson.dumps( + { + "signatures": [ + { + "method": "gpg", + "keyid": keyid, + "data": signature, + } + ] + } + ) + with open(output_filename, "r+b") as fd: fd.seek(signatures_offset, 0) fd.write(encoded_signatures) diff --git a/appimagebuilder/recipe/schema.py b/appimagebuilder/recipe/schema.py index 4fd5f01e..df49a8dc 100644 --- a/appimagebuilder/recipe/schema.py +++ b/appimagebuilder/recipe/schema.py @@ -92,6 +92,9 @@ def __init__(self): "arch": str, Optional("update-information"): str, Optional("sign-key"): str, + Optional("compression-method"): Or( + "gzip", "lzma", "lzo", "lz4", "xz", "zstd" + ), Optional("file_name"): str, Optional("format"): Or(2, 3), } From 3c81f00c4cd2e6bfea501188ad67f18a5bc93a4b Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Mon, 16 Aug 2021 16:35:55 -0500 Subject: [PATCH 17/20] fix: only sign bundles if a key is provided --- appimagebuilder/modules/prime/type_3.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/appimagebuilder/modules/prime/type_3.py b/appimagebuilder/modules/prime/type_3.py index 4ffb5069..9b6ddcd0 100644 --- a/appimagebuilder/modules/prime/type_3.py +++ b/appimagebuilder/modules/prime/type_3.py @@ -34,7 +34,7 @@ def __init__(self, app_dir, cache_dir="appimage-builder-cache"): self.required_tool_paths = shell.resolve_commands_paths(["mksquashfs", "gpg"]) def create( - self, output_filename, metadata=None, gnupg_key=None, compression_method="gzip" + self, output_filename, metadata=None, gnupg_key=None, compression_method="gzip" ): if metadata is None: metadata = {} @@ -57,7 +57,9 @@ def create( output_filename, payload_offset, metadata_offset, signatures_offset ) - self._sign_bundle(output_filename, gnupg_key, signatures_offset) + if gnupg_key: + self._sign_bundle(output_filename, gnupg_key, signatures_offset) + # remove squashfs squashfs_path.unlink() @@ -89,7 +91,7 @@ def _resolve_executable(self): return path def _fill_header( - self, output_filename, payload_offset, metadata_offset, signature_offset + self, output_filename, payload_offset, metadata_offset, signature_offset ): with open(output_filename, "r+b") as f: f.seek(0x410, 0) @@ -105,8 +107,8 @@ def _get_runtime_path(self, arch): def _get_runtime_url(self, arch): runtime_url_template = ( - self.runtime_project_url - + "/releases/download/continuous/runtime-Release-%s" + self.runtime_project_url + + "/releases/download/continuous/runtime-Release-%s" ) runtime_url = runtime_url_template % arch return runtime_url From 2c33c3336b40300436de5b9fcc90f0ec7320010b Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Mon, 16 Aug 2021 22:16:00 -0500 Subject: [PATCH 18/20] fix: don't duplicate payload --- appimagebuilder/utils/file_utils.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/appimagebuilder/utils/file_utils.py b/appimagebuilder/utils/file_utils.py index 7b1a4fc8..b1144937 100644 --- a/appimagebuilder/utils/file_utils.py +++ b/appimagebuilder/utils/file_utils.py @@ -31,11 +31,8 @@ def extend_file(base_filename, extension_filename, output_filename): shutil.copyfile(base_filename, output_filename) with open(output_filename, "r+b") as base_fd: + # seek until the end of the base file base_fd.seek(0, 2) - with open(extension_filename, "rb") as extensions_fd: - raw_data = extensions_fd.read() - base_fd.write(memoryview(raw_data)) - - extensions_fd.seek(0, 0) - shutil.copyfileobj(extensions_fd, base_fd) + with open(extension_filename, "rb") as extension_fd: + shutil.copyfileobj(extension_fd, base_fd) From 31cc0b88f9ca85d5dd40371c11e26d9de4b97619 Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Mon, 16 Aug 2021 22:30:47 -0500 Subject: [PATCH 19/20] fix: regression on type_2 format --- appimagebuilder/commands/create_appimage.py | 1 - appimagebuilder/modules/prime/type_2.py | 20 +++++++------------- examples/kcalc/AppImageBuilder.yml | 3 --- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/appimagebuilder/commands/create_appimage.py b/appimagebuilder/commands/create_appimage.py index 1c024722..a2b243f1 100644 --- a/appimagebuilder/commands/create_appimage.py +++ b/appimagebuilder/commands/create_appimage.py @@ -50,7 +50,6 @@ def __call__(self, *args, **kwargs): raise RuntimeError(f"Unknown AppImage format {appimage_format}") def _create_type_2_appimage(self): - update_information = self.recipe.AppImage["update-information"]() or "None" sign_key = self.recipe.AppImage["sign-key"] or "None" diff --git a/appimagebuilder/modules/prime/type_2.py b/appimagebuilder/modules/prime/type_2.py index 29de1a60..f45d6d4d 100644 --- a/appimagebuilder/modules/prime/type_2.py +++ b/appimagebuilder/modules/prime/type_2.py @@ -30,12 +30,10 @@ class Type2Creator: - def __init__(self, recipe): - self.app_dir = recipe.AppDir.path() - self.target_arch = recipe.AppImage.arch() - self.app_name = recipe.AppDir.app_info.name() - self.app_version = recipe.AppDir.app_info.version() - self.update_information = recipe.AppImage["update-information"]() or "None" + def __init__(self, appdir, target_arch, update_information, sign_key, output_filename): + self.app_dir = appdir + self.target_arch = target_arch + self.update_information = update_information self.guess_update_information = False if self.update_information == "None": @@ -47,15 +45,11 @@ def __init__(self, recipe): self.update_information = None self.guess_update_information = True - self.sing_key = recipe.AppImage["sign-key"]() or "None" + self.sing_key = sign_key if self.sing_key == "None": self.sing_key = None - fallback_file_name = os.path.join( - os.getcwd(), - "%s-%s-%s.AppImage" % (self.app_name, self.app_version, self.target_arch), - ) - self.target_file = recipe.AppImage.file_name() or fallback_file_name + self.target_file = output_filename def create(self): self._assert_target_architecture() @@ -67,7 +61,7 @@ def create(self): self._generate_appimage(runtime_path) def _generate_appimage(self, runtime_path): - appimage_tool = AppImageToolCommand(self.app_dir, self.file_name) + appimage_tool = AppImageToolCommand(self.app_dir, self.target_file) appimage_tool.target_arch = self.target_arch appimage_tool.update_information = self.update_information appimage_tool.guess_update_information = self.guess_update_information diff --git a/examples/kcalc/AppImageBuilder.yml b/examples/kcalc/AppImageBuilder.yml index 70a109d5..69ff0bb7 100644 --- a/examples/kcalc/AppImageBuilder.yml +++ b/examples/kcalc/AppImageBuilder.yml @@ -70,7 +70,4 @@ AppDir: AppImage: - update-information: None - sign-key: None arch: x86_64 - format: 3 From c40655ebe70daef235e89aaf424cb79ba986559f Mon Sep 17 00:00:00 2001 From: Alexis Lopez Zubieta Date: Tue, 17 Aug 2021 12:43:15 -0500 Subject: [PATCH 20/20] fix: set execution permissions on the resulting AppImage --- appimagebuilder/modules/prime/type_3.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appimagebuilder/modules/prime/type_3.py b/appimagebuilder/modules/prime/type_3.py index 9b6ddcd0..c5bb187e 100644 --- a/appimagebuilder/modules/prime/type_3.py +++ b/appimagebuilder/modules/prime/type_3.py @@ -63,6 +63,8 @@ def create( # remove squashfs squashfs_path.unlink() + file_utils.set_permissions_rx_all(output_filename) + def _squash_appdir(self, compression_method): squashfs_path = self.cache_dir / "AppDir.sqfs"