diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..56e3a87 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Line out sections +53d45d3de51c20d134e62146a0ff82a3114cdeda diff --git a/.gitignore b/.gitignore index 0c75929..c1a85b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,62 +1,2 @@ -/bottles-2.0.9.7.tar.gz -/bottles-2.0.9.8.tar.gz -/bottles-2.0.9.9.tar.gz -/bottles-2.1.0.tar.gz -/bottles-2.1.0.2.tar.gz -/bottles-2.1.0.4.tar.gz -/bottles-2.1.0.5.tar.gz -/bottles-2.1.0.6.tar.gz -/bottles-2.1.0.7.tar.gz -/bottles-2.1.1.tar.gz -/bottles-2.1.2.tar.gz -/bottles-3.0.1.1.tar.gz -/bottles-3.0.2.tar.gz -/bottles-3.0.5.tar.gz -/bottles-3.0.6.tar.gz -/bottles-3.0.8.tar.gz -/bottles-3.0.9.tar.gz -/bottles-3.1.0.tar.gz -/bottles-3.1.1.tar.gz -/bottles-3.1.2.tar.gz -/bottles-3.1.3.tar.gz -/bottles-3.1.4.tar.gz -/bottles-3.1.5.tar.gz -/bottles-3.1.6.tar.gz -/bottles-3.1.7.tar.gz -/bottles-3.1.8.tar.gz -/bottles-3.1.9.tar.gz -/bottles-3.1.10.tar.gz -/bottles-3.1.11.tar.gz -/bottles-3.1.12.tar.gz -/bottles-3.1.13.tar.gz -/bottles-3.1.14.tar.gz -/bottles-3.1.15.tar.gz -/bottles-2021.7.3.tar.gz -/bottles-2021.7.14.tar.gz -/bottles-2021.7.28.tar.gz -/bottles-2021.8.14.tar.gz -/bottles-2021.8.28.tar.gz -/bottles-2021.9.14.tar.gz -/bottles-2021.9.28.tar.gz -/bottles-2021.10.14.tar.gz -/bottles-2021.10.28.tar.gz -/bottles-2021.11.14.tar.gz -/bottles-2021.11.28.tar.gz -/bottles-2021.12.14.tar.gz -/bottles-2021.12.28.tar.gz -/bottles-2022.1.14.tar.gz -/bottles-2022.1.28.tar.gz -/bottles-2022.2.14.tar.gz -/bottles-2022.2.28.tar.gz -/bottles-2022.3.14.tar.gz -/bottles-2022.3.28.tar.gz -/bottles-2022.4.14.tar.gz -/bottles-2022.4.28.tar.gz -/bottles-2022.5.2.tar.gz -/bottles-2022.5.14.tar.gz -/bottles-2022.5.28-trento-3.tar.gz -/bottles-2022.6.14-brescia-1.tar.gz -/bottles-2022.7.14-brescia-3.tar.gz -/Bottles-51.6.tar.gz -/Bottles-51.9.tar.gz -/Bottles-51.10.tar.gz +/Bottles*tar.gz +require*.txt diff --git a/0001-Make-sure-Paths.bottles-exists.patch b/0001-Make-sure-Paths.bottles-exists.patch new file mode 100644 index 0000000..6f75c95 --- /dev/null +++ b/0001-Make-sure-Paths.bottles-exists.patch @@ -0,0 +1,34 @@ +From cb8cd4567cd34aac692672362cb87e5f021660cf Mon Sep 17 00:00:00 2001 +From: Sandro +Date: Mon, 4 Mar 2024 20:28:49 +0100 +Subject: [PATCH 1/2] Make sure Paths.bottles exists + +When calling `bottles foo.exe` either from the command line or by +opening the executable from the file browser with Bottles, Bottles will +throw a FileNotFoundError if Paths.bottles does not exist. + +It seems check_app_dirs() is never called in that situation. +--- + bottles/backend/managers/manager.py | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/bottles/backend/managers/manager.py b/bottles/backend/managers/manager.py +index 2a923ec8..42a87167 100644 +--- a/bottles/backend/managers/manager.py ++++ b/bottles/backend/managers/manager.py +@@ -812,7 +812,11 @@ class Manager(metaclass=Singleton): + Check for local bottles and update the local_bottles list. + Will also mark the broken ones if the configuration file is missing + """ +- bottles = os.listdir(Paths.bottles) ++ try: ++ bottles = os.listdir(Paths.bottles) ++ except FileNotFoundError: ++ self.check_app_dirs() ++ bottles = [] + + # Empty local bottles + self.local_bottles = {} +-- +2.47.0 + diff --git a/0002-Catch-AttributeError-in-set_manager.patch b/0002-Catch-AttributeError-in-set_manager.patch new file mode 100644 index 0000000..8e93336 --- /dev/null +++ b/0002-Catch-AttributeError-in-set_manager.patch @@ -0,0 +1,33 @@ +From 5302231bc20db5912349bd3bce27df5a4acf9256 Mon Sep 17 00:00:00 2001 +From: Sandro +Date: Mon, 4 Mar 2024 21:45:51 +0100 +Subject: [PATCH 2/2] Catch AttributeError in set_manager() + +Return empty list if AttributeError is raised. +--- + bottles/frontend/windows/main_window.py | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/bottles/frontend/windows/main_window.py b/bottles/frontend/windows/main_window.py +index 5fb9a15c..cd26408b 100644 +--- a/bottles/frontend/windows/main_window.py ++++ b/bottles/frontend/windows/main_window.py +@@ -178,9 +178,12 @@ class MainWindow(Adw.ApplicationWindow): + def set_manager(result: Manager, error=None): + self.manager = result + +- tmp_runners = [ +- x for x in self.manager.runners_available if not x.startswith("sys-") +- ] ++ try: ++ tmp_runners = [ ++ x for x in self.manager.runners_available if not x.startswith("sys-") ++ ] ++ except AttributeError: ++ tmp_runners = [] + if len(tmp_runners) == 0: + self.show_onboard_view() + +-- +2.47.0 + diff --git a/0003-Catch-AttributeError-when-window-is-closed.patch b/0003-Catch-AttributeError-when-window-is-closed.patch new file mode 100644 index 0000000..da815cb --- /dev/null +++ b/0003-Catch-AttributeError-when-window-is-closed.patch @@ -0,0 +1,33 @@ +From 25ca897f6a04187cec0e06e4740abf8378cf0d43 Mon Sep 17 00:00:00 2001 +From: Sandro +Date: Sat, 9 Nov 2024 13:42:00 +0100 +Subject: [PATCH] Catch AttributeError when window is closed + +In certain situations Bottles crashes with: + +__quit:AttributeError: 'Bottles' object has no attribute 'win' + +This should allow Bottles to exit without error. +--- + bottles/frontend/main.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/bottles/frontend/main.py b/bottles/frontend/main.py +index 5616ab22..7c44b585 100644 +--- a/bottles/frontend/main.py ++++ b/bottles/frontend/main.py +@@ -260,7 +260,10 @@ class Bottles(Adw.Application): + logging.info( + _("[Quit] request received."), + ) +- self.win.on_close_request() ++ try: ++ self.win.on_close_request() ++ except AttributeError: ++ pass + quit() + + @staticmethod +-- +2.47.0 + diff --git a/0004-Use-FileDialog-for-all-file-path-pickers.patch b/0004-Use-FileDialog-for-all-file-path-pickers.patch new file mode 100644 index 0000000..31fa7f0 --- /dev/null +++ b/0004-Use-FileDialog-for-all-file-path-pickers.patch @@ -0,0 +1,79 @@ +From 77bc57c6a2468d4c28f9c8e80ca20fd4e2e48dfb Mon Sep 17 00:00:00 2001 +From: Sandro +Date: Sat, 9 Nov 2024 16:59:50 +0100 +Subject: [PATCH] Use FileDialog for all file/path pickers + +- Use `FileDialog` throughout +- Handle whatever `GLib.Error` throws our way +- Handle it the same way regardless of dialog +--- + bottles/frontend/windows/launchoptions.py | 43 ++++++++++++++--------- + 1 file changed, 27 insertions(+), 16 deletions(-) + +diff --git a/bottles/frontend/windows/launchoptions.py b/bottles/frontend/windows/launchoptions.py +index adb122a3..79dbedd6 100644 +--- a/bottles/frontend/windows/launchoptions.py ++++ b/bottles/frontend/windows/launchoptions.py +@@ -279,6 +279,7 @@ class LaunchOptionsDialog(Adw.Window): + else: + # something else happened... + logging.warning("Error selecting post-run script: %s" % error) ++ pass + + dialog = Gtk.FileDialog.new() + dialog.set_title("Select Post-run Script") +@@ -296,25 +297,35 @@ class LaunchOptionsDialog(Adw.Window): + self.btn_post_script_reset.set_visible(False) + + def __choose_cwd(self, *_args): +- def set_path(dialog, response): +- if response != Gtk.ResponseType.ACCEPT: +- self.action_cwd.set_subtitle(self.__default_cwd_msg) +- return +- +- directory_path = dialog.get_file().get_path() +- self.program["folder"] = directory_path +- self.action_cwd.set_subtitle(directory_path) +- self.btn_cwd_reset.set_visible(True) ++ def set_path(dialog, result): + +- dialog = Gtk.FileChooserNative.new( +- title=_("Select Working Directory"), +- parent=self.window, +- action=Gtk.FileChooserAction.SELECT_FOLDER, +- ) ++ try: ++ directory = dialog.select_folder_finish(result) ++ ++ if directory is None: ++ self.action_cwd.set_subtitle( ++ self.__default_cwd_msg) ++ return + ++ directory_path = directory.get_path() ++ self.program["folder"] = directory_path ++ self.action_cwd.set_subtitle(directory_path) ++ self.btn_cwd_reset.set_visible(True) ++ except GLib.Error as error: ++ # also thrown when dialog has been cancelled ++ if error.code == 2: ++ # error 2 seems to be 'dismiss' or 'cancel' ++ if self.program["folder"] is None or self.program["folder"] == "": ++ self.action_cwd.set_subtitle(self.__default_cwd_msg) ++ else: ++ # something else happened... ++ logging.warning("Error selecting folder: %s" % error) ++ raise ++ ++ dialog = Gtk.FileDialog.new() ++ dialog.set_title("Select Working Directory") + dialog.set_modal(True) +- dialog.connect("response", set_path) +- dialog.show() ++ dialog.select_folder(parent=self.window, callback=set_path) + + def __reset_cwd(self, *_args): + """ +-- +2.47.0 + diff --git a/README.packit b/README.packit new file mode 100644 index 0000000..2bd3f40 --- /dev/null +++ b/README.packit @@ -0,0 +1,3 @@ +This repository is maintained by packit. +https://packit.dev/ +The file was generated using packit 0.102.1.post1.dev6+g64f7460b. diff --git a/bottles.spec b/bottles.spec index c94071a..7392373 100644 --- a/bottles.spec +++ b/bottles.spec @@ -2,7 +2,7 @@ Name: bottles Epoch: 1 -Version: 51.10 +Version: 51.15 Release: %autorelease Summary: Run Windows in a Bottle @@ -15,45 +15,80 @@ Summary: Run Windows in a Bottle License: GPL-3.0-or-later AND MIT URL: %{forgeurl} Source0: %{forgesource} +# Make sure bottles dir exists when opening executable directly +# https://bugzilla.redhat.com/show_bug.cgi?id=2249922 +# https://bugzilla.redhat.com/show_bug.cgi?id=2257180 +Patch: 0001-Make-sure-Paths.bottles-exists.patch +# Don't fail on AttributeError +# https://bugzilla.redhat.com/show_bug.cgi?id=2260135 +Patch: 0002-Catch-AttributeError-in-set_manager.patch +# Catch AttributeError when closing window +# https://bugzilla.redhat.com/show_bug.cgi?id=2313567 +Patch: 0003-Catch-AttributeError-when-window-is-closed.patch +# Attempt to prevent segfaults when picking files +# https://bugzilla.redhat.com/show_bug.cgi?id=2296214 +Patch: 0004-Use-FileDialog-for-all-file-path-pickers.patch -BuildArch: noarch -# blueprint-compiler does not work on s390x: -# https://gitlab.gnome.org/jwestman/blueprint-compiler/-/issues/96 -ExcludeArch: s390x +BuildArch: noarch -BuildRequires: desktop-file-utils -BuildRequires: libappstream-glib -BuildRequires: meson -BuildRequires: python3 +BuildRequires: desktop-file-utils +BuildRequires: libappstream-glib +BuildRequires: meson +BuildRequires: python3 +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(gtk4) +BuildRequires: pkgconfig(libadwaita-1) >= 1.1.99 +BuildRequires: blueprint-compiler -BuildRequires: pkgconfig(glib-2.0) -BuildRequires: pkgconfig(gtk4) -BuildRequires: pkgconfig(libadwaita-1) >= 1.1.99 +Requires: cabextract +Requires: glibc(x86-32) %dnl # https://github.com/bottlesdevs/Bottles/issues/601#issuecomment-936772762 +Requires: gtk4 +Requires: gtksourceview5 +Requires: hicolor-icon-theme +Requires: libadwaita >= 1.1.99 +Requires: p7zip p7zip-plugins %dnl # needed by the dependencies manager +Requires: patool +Requires: xdpyinfo %dnl # needed by the display util +Requires: ImageMagick %dnl # https://bugzilla.redhat.com/show_bug.cgi?id=2227538 -BuildRequires: blueprint-compiler +# Use `generate_requires.sh` to generate Python runtime dependencies +# using upstream's `requirements.txt`, which is included in the tarball, +# but not used by Meson. +Requires: python3dist(pyyaml) +Requires: python3dist(pycurl) +Requires: python3dist(chardet) +Requires: python3dist(requests) +Requires: python3dist(markdown) +Requires: python3dist(icoextract) +Requires: python3dist(patool) +Requires: python3dist(pathvalidate) +Requires: python3dist(fvs) +Requires: python3dist(orjson) +Requires: python3dist(pycairo) +Requires: python3dist(pygobject) +Requires: python3dist(charset-normalizer) +Requires: python3dist(idna) +Requires: python3dist(urllib3) +Requires: python3dist(certifi) +Requires: python3dist(pefile) -Requires: cabextract -Requires: glibc(x86-32) %dnl # https://github.com/bottlesdevs/Bottles/issues/601#issuecomment-936772762 -Requires: gtk4 -Requires: gtksourceview5 -Requires: hicolor-icon-theme -Requires: libadwaita >= 1.1.99 -Requires: p7zip p7zip-plugins %dnl # needed by the dependencies manager -Requires: patool -Requires: python3-gobject -Requires: python3-icoextract %dnl # icons support -Requires: python3-markdown -Requires: python3-patool -Requires: python3-pefile %dnl # icons support -Requires: python3-pyyaml -Requires: python3-requests %dnl # needed by the download manager -Requires: python3-urllib3 %dnl # needed by the download manager -Requires: xdpyinfo %dnl # needed by the display util -Requires: python3-pathvalidate -Requires: python3-fvs -Requires: python3-vkbasalt-cli -Requires: ImageMagick %dnl # https://bugzilla.redhat.com/show_bug.cgi?id=2227538 -Requires: python3-chardet %dnl # https://bugzilla.redhat.com/show_bug.cgi?id=2240292 +# Requirements not listed in upstream's `requirements.txt` +Requires: python3dist(vkbasalt-cli) + +# Optional dependencies which may be required for running 32-bit bottles. +# We recommend those in order to allow users to opt out. +Recommends: freetype.i686 +Recommends: mesa-dri-drivers.i686 +Recommends: mesa-filesystem.i686 +Recommends: mesa-libEGL.i686 +Recommends: mesa-libgbm.i686 +Recommends: mesa-libglapi.i686 +Recommends: mesa-libGL.i686 +Recommends: mesa-libGLU.i686 +Recommends: mesa-va-drivers.i686 +Recommends: mesa-vulkan-drivers.i686 +Recommends: SDL2.i686 +Recommends: vulkan-loader.i686 %description Bottles lets you run Windows software on Linux, such as applications diff --git a/generate_requires.sh b/generate_requires.sh new file mode 100755 index 0000000..99fe46e --- /dev/null +++ b/generate_requires.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +SPEC_FILE="bottles.spec" +REQUIREMENTS_FILE="requirements.txt" +REQUIREMENTS_SPEC="requires.txt" +# Remove file(s) from previous run +[ -f ${REQUIREMENTS_SPEC} ] && rm -vf ${REQUIREMENTS_SPEC} +[ -f ${REQUIREMENTS_FILE} ] && rm -vf ${REQUIREMENTS_FILE} +# Make sure sources are present +spectool -gSf ${SPEC_FILE} 2>/dev/null +TARBALL="$(rpmspec --parse bottles.spec 2>/dev/null | grep Source0 | sed -r 's/^.*(Bottles.*)/\1/')" +TAR_REQ_FILE="$(tar tzf ${TARBALL} | grep ${REQUIREMENTS_FILE})" +tar -x ${TAR_REQ_FILE} --strip-components=1 -zf ${TARBALL} + +# Remove version pinning from listed dependencies +# Require `requests`. The `use_chardet_on_py3` extra is not packaged in +# Fedora, but we have the required version of `chardet` present. +# Remove `wheel` from list - not a runtime requirement. +sed -r -i \ + -e 's/(^.*)==.*$/\1/g' \ + -e 's/(^requests)\[.*\]/\1/' \ + -e '/wheel/d' \ + requirements.txt + +# Transform requirements for inclusion in spec file +for REQ in $(grep -v '^#' ${REQUIREMENTS_FILE}); do + echo "Requires: python3dist(${REQ@L})" >> ${REQUIREMENTS_SPEC} +done diff --git a/sources b/sources index e89f76e..a420eac 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (Bottles-51.10.tar.gz) = a5d27f70d580cc115f797370437a41a0eeb7335e8278618415f7ba7268aae8102ba9ee8417723a731f677b7bf346773e5851f9021ff12bdec4305b436e589c24 +SHA512 (Bottles-51.15.tar.gz) = 8917e519c6b537e54a2492b8b0955589e3d0ee2eddf59ba801e84a9f9790187e9f9d3dce990b90a7eb4fe612aaa59f98bc3368e9f43a298a59825b74b74e7ac2