Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package protontricks for openSUSE:Factory checked in at 2024-01-06 17:29:25 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/protontricks (Old) and /work/SRC/openSUSE:Factory/.protontricks.new.28375 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "protontricks" Sat Jan 6 17:29:25 2024 rev:2 rq:1137169 version:1.11.0 Changes: -------- --- /work/SRC/openSUSE:Factory/protontricks/protontricks.changes 2023-11-09 21:34:56.155862975 +0100 +++ /work/SRC/openSUSE:Factory/.protontricks.new.28375/protontricks.changes 2024-01-06 17:29:28.368267979 +0100 @@ -1,0 +2,12 @@ +Fri Jan 5 22:51:47 UTC 2024 - Ralf Habacker <ralf.habac...@freenet.de> + +- Update to version 1.11.0: + * Show app icons for custom shortcuts in the app selector + * Verbose flag can be enabled with -vv for additional debug logging + * Fix Protontricks not recognizing supported Steam Runtime + installation due to changed name + * Fix Protontricks not recognizing default Proton installation for + games with different Proton preselected by Valve testing + * Fix Protontricks crash when app has an unidentifiable app icon + +------------------------------------------------------------------- Old: ---- protontricks-1.10.5.tar.xz New: ---- protontricks-1.11.0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ protontricks.spec ++++++ --- /var/tmp/diff_new_pack.pG4EPd/_old 2024-01-06 17:29:29.324302899 +0100 +++ /var/tmp/diff_new_pack.pG4EPd/_new 2024-01-06 17:29:29.324302899 +0100 @@ -1,7 +1,7 @@ # # spec file for package protontricks # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2024 SUSE LLC # Copyright (c) 2019 Matthias Fehring <buschman...@opensuse.org> # # All modifications and additions to the file contributed by third parties @@ -19,7 +19,7 @@ %{!?python_sitelib: %global python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} Name: protontricks -Version: 1.10.5 +Version: 1.11.0 Release: 0 Summary: Winetricks for Proton-enabled Games License: GPL-3.0-only ++++++ _service ++++++ --- /var/tmp/diff_new_pack.pG4EPd/_old 2024-01-06 17:29:29.356304068 +0100 +++ /var/tmp/diff_new_pack.pG4EPd/_new 2024-01-06 17:29:29.360304214 +0100 @@ -2,7 +2,7 @@ <service name="tar_scm" mode="manual"> <param name="scm">git</param> <param name="url">https://github.com/Matoking/protontricks.git</param> - <param name="revision">1.10.5</param> + <param name="revision">1.11.0</param> <param name="versionformat">@PARENT_TAG@</param> <param name="package-meta">yes</param> </service> ++++++ protontricks-1.10.5.tar.xz -> protontricks-1.11.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/.git/FETCH_HEAD new/protontricks-1.11.0/.git/FETCH_HEAD --- old/protontricks-1.10.5/.git/FETCH_HEAD 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/.git/FETCH_HEAD 1970-01-01 01:00:00.000000000 +0100 @@ -1,41 +0,0 @@ -dea5c89fd6a856bee1e961ab946ba25945dc89cf not-for-merge branch 'add_sniper' of https://github.com/Matoking/protontricks -19778ae5962f00f6983eb272f46b185660dd81ad not-for-merge branch 'app_type' of https://github.com/Matoking/protontricks -9bb35cbdd6f29a16cf8364160f5d09cd64683087 not-for-merge branch 'clean_imports' of https://github.com/Matoking/protontricks -03df9c3cba9c69411fdb34dc1252137ebb99c539 not-for-merge branch 'debug_logging' of https://github.com/Matoking/protontricks -db1876d40d592959eee62a3b57aff191c85587a5 not-for-merge branch 'detect_custom_icon' of https://github.com/Matoking/protontricks -fd93e458aacb7cb423a96947eae50f187c83d382 not-for-merge branch 'detect_xdg_perms' of https://github.com/Matoking/protontricks -15d3d099669fb9d6af1fd8da42e82ec56caf2dd6 not-for-merge branch 'disable_background_wineserver' of https://github.com/Matoking/protontricks -db2796b04aada41e8940698ada152f43c9aa778f not-for-merge branch 'duplicate_fix' of https://github.com/Matoking/protontricks -a041b89af0a8f6f505f9676d80d8eb79d7aa68f8 not-for-merge branch 'fix_appinfo' of https://github.com/Matoking/protontricks -425b954f4c3b25e295339f4f6df2c7e64de5705d not-for-merge branch 'fix_bg_wineserver_output' of https://github.com/Matoking/protontricks -392a07cadaa2055551a9fa0509e85034a8019bb7 not-for-merge branch 'fix_bwrap_launcher' of https://github.com/Matoking/protontricks -064f3a91dec219918ff9194d69f47d5190f0d59a not-for-merge branch 'fix_deprecated_socket' of https://github.com/Matoking/protontricks -f54e1fc5867807b4b5601ae785007d182f3396aa not-for-merge branch 'fix_help' of https://github.com/Matoking/protontricks -7a2e3eb47ef3af0083babf0b80c952c29c99215b not-for-merge branch 'fix_icon_size' of https://github.com/Matoking/protontricks -52e6e31b229ddca1f0683a6a0329297db4995421 not-for-merge branch 'fix_jpeg_convert' of https://github.com/Matoking/protontricks -db988c57c48987914964bf164b07d598b6f27b63 not-for-merge branch 'fix_locale' of https://github.com/Matoking/protontricks -be3805b62297e096582302034b661ca1680c3591 not-for-merge branch 'fix_nonsteam_shortcuts' of https://github.com/Matoking/protontricks -3b2f77427354c462ef2b799271700824d6d2c708 not-for-merge branch 'fix_proton_discovery' of https://github.com/Matoking/protontricks -124fc7a85ee099fecf8cd2ada7a9b86221f417fa not-for-merge branch 'fix_steamapps_discovery' of https://github.com/Matoking/protontricks -aea43f7245ce3a99a750813f2b62bc372e142a47 not-for-merge branch 'fix_wineserver_race' of https://github.com/Matoking/protontricks -308fb280237445a5c1b4c50c9890adb361599b99 not-for-merge branch 'fix_xauthority_crash' of https://github.com/Matoking/protontricks -ab4d7f61231620f7339188ffeceaa376982a3a9d not-for-merge branch 'flatpak' of https://github.com/Matoking/protontricks -11eb97e6c79c8b0827786a243d871c07ee18de46 not-for-merge branch 'flatpak_fix' of https://github.com/Matoking/protontricks -6ad27720e8c475a0f3361e0dd506b0a1cc186da7 not-for-merge branch 'ignore_permission' of https://github.com/Matoking/protontricks -12e427c570e39d0dc383edef7aa319460f46496c not-for-merge branch 'ignore_remaining_vdf' of https://github.com/Matoking/protontricks -1d03f022f0db99896dfed23fa50ed0caac6f60aa not-for-merge branch 'interoperable_flatpak' of https://github.com/Matoking/protontricks -9f35f4dbd72643756a4804da0f03039afaed2373 not-for-merge branch 'keep_wineserver_alive' of https://github.com/Matoking/protontricks -d73477db34728b598f721c524032427b3571d566 not-for-merge branch 'master' of https://github.com/Matoking/protontricks -ace41890f10b6e075916a48e510b8f51335350b4 not-for-merge branch 'name_update' of https://github.com/Matoking/protontricks -0b884635a48a2ec8cc4ffb2ae04aa3dd584e16ff not-for-merge branch 'no_wine_launcher_poll' of https://github.com/Matoking/protontricks -65218290c7638ac4f9cf00e6d4a318d0272b32c0 not-for-merge branch 'pressure_vessel_launcher' of https://github.com/Matoking/protontricks -490faf58d7ed54c25158bb46e0af489c795c10a5 not-for-merge branch 'prompt_steam_dir' of https://github.com/Matoking/protontricks -cdc8414e09fe2db34aecc2f90c180cf5b90df073 not-for-merge branch 'python311' of https://github.com/Matoking/protontricks -55bd0ee04b64d9bbf2fc2e3e5e4fd436a5df4a7c not-for-merge branch 'python35_fix' of https://github.com/Matoking/protontricks -6572ba3b3bacf5e6b3e09cf88f4d9cb8f0873938 not-for-merge branch 'remove_old_appinfo' of https://github.com/Matoking/protontricks -c8dd5d41a4b677542ef91fed919f5e5c692f07ca not-for-merge branch 'return_status' of https://github.com/Matoking/protontricks -b78f098793c38308529bb9c641a1284ffffa1889 not-for-merge branch 'revert_dbus' of https://github.com/Matoking/protontricks -4c9c8d4270f66961ffe53c532fa2fdeeb14ac19b not-for-merge branch 'secure_ci' of https://github.com/Matoking/protontricks -3a57bc6bbfb039abd7fe623b25a29c277e064f9c not-for-merge branch 'standalone_flatpak' of https://github.com/Matoking/protontricks -8c5a41f9d3e25bb031b753b0b2f07d37f2b85c70 not-for-merge branch 'steam_find_fix' of https://github.com/Matoking/protontricks -d73477db34728b598f721c524032427b3571d566 not-for-merge branch 'update_template' of https://github.com/Matoking/protontricks diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/.git/HEAD new/protontricks-1.11.0/.git/HEAD --- old/protontricks-1.10.5/.git/HEAD 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/.git/HEAD 2023-12-30 17:52:23.000000000 +0100 @@ -1 +1 @@ -77afe738935a56fc629a88593999bf52534723ea +3bb249616cf528bdb83e3a2f511e1c8fb1edb681 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/.git/ORIG_HEAD new/protontricks-1.11.0/.git/ORIG_HEAD --- old/protontricks-1.10.5/.git/ORIG_HEAD 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/.git/ORIG_HEAD 2023-12-30 17:52:23.000000000 +0100 @@ -1 +1 @@ -77afe738935a56fc629a88593999bf52534723ea +3bb249616cf528bdb83e3a2f511e1c8fb1edb681 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/.git/config new/protontricks-1.11.0/.git/config --- old/protontricks-1.10.5/.git/config 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/.git/config 2023-12-30 17:52:23.000000000 +0100 @@ -9,4 +9,3 @@ [branch "master"] remote = origin merge = refs/heads/master - rebase = true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/.git/hooks/fsmonitor-watchman.sample new/protontricks-1.11.0/.git/hooks/fsmonitor-watchman.sample --- old/protontricks-1.10.5/.git/hooks/fsmonitor-watchman.sample 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/.git/hooks/fsmonitor-watchman.sample 2023-12-30 17:52:23.000000000 +0100 @@ -86,13 +86,12 @@ # recency index to select candidate nodes and "fields" to limit the # output to file names only. Then we're using the "expression" term to # further constrain the results. - my $last_update_line = ""; if (substr($last_update_token, 0, 1) eq "c") { $last_update_token = "\"$last_update_token\""; - $last_update_line = qq[\n"since": $last_update_token,]; } my $query = <<" END"; - ["query", "$git_work_tree", {$last_update_line + ["query", "$git_work_tree", { + "since": $last_update_token, "fields": ["name"], "expression": ["not", ["dirname", ".git"]] }] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/.git/hooks/sendemail-validate.sample new/protontricks-1.11.0/.git/hooks/sendemail-validate.sample --- old/protontricks-1.10.5/.git/hooks/sendemail-validate.sample 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/.git/hooks/sendemail-validate.sample 1970-01-01 01:00:00.000000000 +0100 @@ -1,77 +0,0 @@ -#!/bin/sh - -# An example hook script to validate a patch (and/or patch series) before -# sending it via email. -# -# The hook should exit with non-zero status after issuing an appropriate -# message if it wants to prevent the email(s) from being sent. -# -# To enable this hook, rename this file to "sendemail-validate". -# -# By default, it will only check that the patch(es) can be applied on top of -# the default upstream branch without conflicts in a secondary worktree. After -# validation (successful or not) of the last patch of a series, the worktree -# will be deleted. -# -# The following config variables can be set to change the default remote and -# remote ref that are used to apply the patches against: -# -# sendemail.validateRemote (default: origin) -# sendemail.validateRemoteRef (default: HEAD) -# -# Replace the TODO placeholders with appropriate checks according to your -# needs. - -validate_cover_letter () { - file="$1" - # TODO: Replace with appropriate checks (e.g. spell checking). - true -} - -validate_patch () { - file="$1" - # Ensure that the patch applies without conflicts. - git am -3 "$file" || return - # TODO: Replace with appropriate checks for this patch - # (e.g. checkpatch.pl). - true -} - -validate_series () { - # TODO: Replace with appropriate checks for the whole series - # (e.g. quick build, coding style checks, etc.). - true -} - -# main ------------------------------------------------------------------------- - -if test "$GIT_SENDEMAIL_FILE_COUNTER" = 1 -then - remote=$(git config --default origin --get sendemail.validateRemote) && - ref=$(git config --default HEAD --get sendemail.validateRemoteRef) && - worktree=$(mktemp --tmpdir -d sendemail-validate.XXXXXXX) && - git worktree add -fd --checkout "$worktree" "refs/remotes/$remote/$ref" && - git config --replace-all sendemail.validateWorktree "$worktree" -else - worktree=$(git config --get sendemail.validateWorktree) -fi || { - echo "sendemail-validate: error: failed to prepare worktree" >&2 - exit 1 -} - -unset GIT_DIR GIT_WORK_TREE -cd "$worktree" && - -if grep -q "^diff --git " "$1" -then - validate_patch "$1" -else - validate_cover_letter "$1" -fi && - -if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" -then - git config --unset-all sendemail.validateWorktree && - trap 'git worktree remove -ff "$worktree"' EXIT && - validate_series -fi Binary files old/protontricks-1.10.5/.git/index and new/protontricks-1.11.0/.git/index differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/.git/logs/HEAD new/protontricks-1.11.0/.git/logs/HEAD --- old/protontricks-1.10.5/.git/logs/HEAD 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/.git/logs/HEAD 2023-12-30 17:52:23.000000000 +0100 @@ -1,2 +1,2 @@ -0000000000000000000000000000000000000000 d73477db34728b598f721c524032427b3571d566 Ralf Habacker <ralf.habac...@freenet.de> 1698054006 +0200 clone: from https://github.com/Matoking/protontricks.git -d73477db34728b598f721c524032427b3571d566 77afe738935a56fc629a88593999bf52534723ea Ralf Habacker <ralf.habac...@freenet.de> 1698054006 +0200 checkout: moving from master to 1.10.5 +0000000000000000000000000000000000000000 de708dca61eaf7c79db100b6703516bb2f89801b Ralf Habacker <ralf.habac...@freenet.de> 1704495096 +0100 clone: from https://github.com/Matoking/protontricks.git +de708dca61eaf7c79db100b6703516bb2f89801b 3bb249616cf528bdb83e3a2f511e1c8fb1edb681 Ralf Habacker <ralf.habac...@freenet.de> 1704495096 +0100 checkout: moving from master to 1.11.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/.git/logs/refs/heads/master new/protontricks-1.11.0/.git/logs/refs/heads/master --- old/protontricks-1.10.5/.git/logs/refs/heads/master 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/.git/logs/refs/heads/master 2023-12-30 17:52:23.000000000 +0100 @@ -1 +1 @@ -0000000000000000000000000000000000000000 d73477db34728b598f721c524032427b3571d566 Ralf Habacker <ralf.habac...@freenet.de> 1698054006 +0200 clone: from https://github.com/Matoking/protontricks.git +0000000000000000000000000000000000000000 de708dca61eaf7c79db100b6703516bb2f89801b Ralf Habacker <ralf.habac...@freenet.de> 1704495096 +0100 clone: from https://github.com/Matoking/protontricks.git diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/.git/logs/refs/remotes/origin/HEAD new/protontricks-1.11.0/.git/logs/refs/remotes/origin/HEAD --- old/protontricks-1.10.5/.git/logs/refs/remotes/origin/HEAD 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/.git/logs/refs/remotes/origin/HEAD 2023-12-30 17:52:23.000000000 +0100 @@ -1 +1 @@ -0000000000000000000000000000000000000000 d73477db34728b598f721c524032427b3571d566 Ralf Habacker <ralf.habac...@freenet.de> 1698054006 +0200 clone: from https://github.com/Matoking/protontricks.git +0000000000000000000000000000000000000000 de708dca61eaf7c79db100b6703516bb2f89801b Ralf Habacker <ralf.habac...@freenet.de> 1704495096 +0100 clone: from https://github.com/Matoking/protontricks.git Binary files old/protontricks-1.10.5/.git/objects/pack/pack-2b55d5325ea91c6b8981a2d2b3f6b654533f2e0d.idx and new/protontricks-1.11.0/.git/objects/pack/pack-2b55d5325ea91c6b8981a2d2b3f6b654533f2e0d.idx differ Binary files old/protontricks-1.10.5/.git/objects/pack/pack-2b55d5325ea91c6b8981a2d2b3f6b654533f2e0d.pack and new/protontricks-1.11.0/.git/objects/pack/pack-2b55d5325ea91c6b8981a2d2b3f6b654533f2e0d.pack differ Binary files old/protontricks-1.10.5/.git/objects/pack/pack-a6f1382eee0a6eb5ec1588d6409c8f9a8eb078e2.idx and new/protontricks-1.11.0/.git/objects/pack/pack-a6f1382eee0a6eb5ec1588d6409c8f9a8eb078e2.idx differ Binary files old/protontricks-1.10.5/.git/objects/pack/pack-a6f1382eee0a6eb5ec1588d6409c8f9a8eb078e2.pack and new/protontricks-1.11.0/.git/objects/pack/pack-a6f1382eee0a6eb5ec1588d6409c8f9a8eb078e2.pack differ Binary files old/protontricks-1.10.5/.git/objects/pack/pack-a6f1382eee0a6eb5ec1588d6409c8f9a8eb078e2.rev and new/protontricks-1.11.0/.git/objects/pack/pack-a6f1382eee0a6eb5ec1588d6409c8f9a8eb078e2.rev differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/.git/packed-refs new/protontricks-1.11.0/.git/packed-refs --- old/protontricks-1.10.5/.git/packed-refs 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/.git/packed-refs 2023-12-30 17:52:23.000000000 +0100 @@ -1,12 +1,14 @@ # pack-refs with: peeled fully-peeled sorted dea5c89fd6a856bee1e961ab946ba25945dc89cf refs/remotes/origin/add_sniper 19778ae5962f00f6983eb272f46b185660dd81ad refs/remotes/origin/app_type +6bea9ae5fc90b7588d87a17acb2b83b6e15469f1 refs/remotes/origin/better_error_messages 9bb35cbdd6f29a16cf8364160f5d09cd64683087 refs/remotes/origin/clean_imports 03df9c3cba9c69411fdb34dc1252137ebb99c539 refs/remotes/origin/debug_logging db1876d40d592959eee62a3b57aff191c85587a5 refs/remotes/origin/detect_custom_icon fd93e458aacb7cb423a96947eae50f187c83d382 refs/remotes/origin/detect_xdg_perms 15d3d099669fb9d6af1fd8da42e82ec56caf2dd6 refs/remotes/origin/disable_background_wineserver db2796b04aada41e8940698ada152f43c9aa778f refs/remotes/origin/duplicate_fix +96f253d1e3d7684c97cec1e8fbeb1f3f78a3155e refs/remotes/origin/fix_app_mapping_detection a041b89af0a8f6f505f9676d80d8eb79d7aa68f8 refs/remotes/origin/fix_appinfo 425b954f4c3b25e295339f4f6df2c7e64de5705d refs/remotes/origin/fix_bg_wineserver_output 392a07cadaa2055551a9fa0509e85034a8019bb7 refs/remotes/origin/fix_bwrap_launcher @@ -22,12 +24,16 @@ 308fb280237445a5c1b4c50c9890adb361599b99 refs/remotes/origin/fix_xauthority_crash ab4d7f61231620f7339188ffeceaa376982a3a9d refs/remotes/origin/flatpak 11eb97e6c79c8b0827786a243d871c07ee18de46 refs/remotes/origin/flatpak_fix +de708dca61eaf7c79db100b6703516bb2f89801b refs/remotes/origin/ignore_empty_compatibilitytool 6ad27720e8c475a0f3361e0dd506b0a1cc186da7 refs/remotes/origin/ignore_permission 12e427c570e39d0dc383edef7aa319460f46496c refs/remotes/origin/ignore_remaining_vdf 1d03f022f0db99896dfed23fa50ed0caac6f60aa refs/remotes/origin/interoperable_flatpak 9f35f4dbd72643756a4804da0f03039afaed2373 refs/remotes/origin/keep_wineserver_alive -d73477db34728b598f721c524032427b3571d566 refs/remotes/origin/master +68af8545189748b3342691302ee1718a75963b07 refs/remotes/origin/lenient_jpeg_parse +26952aeeb961ec09499a7923da7a51fc9695f852 refs/remotes/origin/log_compatibilitytool +de708dca61eaf7c79db100b6703516bb2f89801b refs/remotes/origin/master ace41890f10b6e075916a48e510b8f51335350b4 refs/remotes/origin/name_update +68f965f2876bb532cb68447ac4be248cd39b9c76 refs/remotes/origin/new_runtime_names 0b884635a48a2ec8cc4ffb2ae04aa3dd584e16ff refs/remotes/origin/no_wine_launcher_poll 65218290c7638ac4f9cf00e6d4a318d0272b32c0 refs/remotes/origin/pressure_vessel_launcher 490faf58d7ed54c25158bb46e0af489c795c10a5 refs/remotes/origin/prompt_steam_dir @@ -55,6 +61,8 @@ ^52e780b7297a2eb8d6ec9dba946df28eb798c9f7 d548a36e1d58ac0774b823a0c47bdbc5d64c53e1 refs/tags/1.10.5 ^77afe738935a56fc629a88593999bf52534723ea +94ef1e9d7e78182c1b6e82dc6e9b119e21bddd81 refs/tags/1.11.0 +^3bb249616cf528bdb83e3a2f511e1c8fb1edb681 be279a8a51a361b8177a2b806f233baa2b2fd584 refs/tags/1.2 f62eeab4f10e5a6a3370202556b8f171b41f20f4 refs/tags/1.2.1 7f90359eb6fbbc84b57b2e6ef374535c7a9ecf95 refs/tags/1.2.2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/.git/refs/heads/master new/protontricks-1.11.0/.git/refs/heads/master --- old/protontricks-1.10.5/.git/refs/heads/master 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/.git/refs/heads/master 2023-12-30 17:52:23.000000000 +0100 @@ -1 +1 @@ -d73477db34728b598f721c524032427b3571d566 +de708dca61eaf7c79db100b6703516bb2f89801b diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/.github/ISSUE_TEMPLATE/bug_report.md new/protontricks-1.11.0/.github/ISSUE_TEMPLATE/bug_report.md --- old/protontricks-1.10.5/.github/ISSUE_TEMPLATE/bug_report.md 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/.github/ISSUE_TEMPLATE/bug_report.md 2023-12-30 17:52:23.000000000 +0100 @@ -22,7 +22,7 @@ - Distro: [e.g. Ubuntu 20.04, Arch Linux, ...] - Protontricks installation method: [e.g. community package, Flatpak, pipx or pip] - Protontricks version: run `protontricks --version` to print the version - - Steam version: check if you're running Steam beta; this can be checked in _Steam_ -> _Settings_ -> _Account_ -> _Beta participation_ + - Steam version: check if you're running Steam beta; this can be checked in _Steam_ -> _Settings_ -> _Interface_ -> _Client Beta Participation_ **Additional context** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/.github/workflows/tests.yml new/protontricks-1.11.0/.github/workflows/tests.yml --- old/protontricks-1.10.5/.github/workflows/tests.yml 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/.github/workflows/tests.yml 2023-12-30 17:52:23.000000000 +0100 @@ -5,6 +5,8 @@ on: [push, pull_request] +permissions: read-all + jobs: test: runs-on: ubuntu-20.04 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/CHANGELOG.md new/protontricks-1.11.0/CHANGELOG.md --- old/protontricks-1.10.5/CHANGELOG.md 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/CHANGELOG.md 2023-12-30 17:52:23.000000000 +0100 @@ -4,6 +4,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## [1.11.0] - 2023-12-30 +### Added + - Show app icons for custom shortcuts in the app selector + - Verbose flag can be enabled with `-vv` for additional debug logging + +### Fixed + - Fix Protontricks not recognizing supported Steam Runtime installation due to changed name + - Fix Protontricks not recognizing default Proton installation for games with different Proton preselected by Valve testing + - Fix Protontricks crash when app has an unidentifiable app icon + ## [1.10.5] - 2023-09-05 ### Fixed - Fix crash caused by custom app icons with non-RGB mode @@ -268,7 +278,8 @@ ### Added - The last release of Protontricks maintained by [@Sirmentio](https://github.com/Sirmentio). -[Unreleased]: https://github.com/Matoking/protontricks/compare/1.10.5...HEAD +[Unreleased]: https://github.com/Matoking/protontricks/compare/1.11.0...HEAD +[1.11.0]: https://github.com/Matoking/protontricks/compare/1.10.5...1.11.0 [1.10.5]: https://github.com/Matoking/protontricks/compare/1.10.4...1.10.5 [1.10.4]: https://github.com/Matoking/protontricks/compare/1.10.3...1.10.4 [1.10.3]: https://github.com/Matoking/protontricks/compare/1.10.2...1.10.3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/data/com.github.Matoking.protontricks.metainfo.xml new/protontricks-1.11.0/data/com.github.Matoking.protontricks.metainfo.xml --- old/protontricks-1.10.5/data/com.github.Matoking.protontricks.metainfo.xml 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/data/com.github.Matoking.protontricks.metainfo.xml 2023-12-30 17:52:23.000000000 +0100 @@ -36,6 +36,7 @@ <metadata_license>CC0-1.0</metadata_license> <update_contact>janne.pulkki...@protonmail.com</update_contact> <releases> + <release version="1.11.0" date="2023-12-30"/> <release version="1.10.5" date="2023-09-05"/> <release version="1.10.4" date="2023-08-26"/> <release version="1.10.3" date="2023-05-06"/> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/requirements.txt new/protontricks-1.11.0/requirements.txt --- old/protontricks-1.10.5/requirements.txt 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/requirements.txt 2023-12-30 17:52:23.000000000 +0100 @@ -1 +1,2 @@ vdf==3.4 +Pillow diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/src/protontricks/cli/launch.py new/protontricks-1.11.0/src/protontricks/cli/launch.py --- old/protontricks-1.10.5/src/protontricks/cli/launch.py 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/src/protontricks/cli/launch.py 2023-12-30 17:52:23.000000000 +0100 @@ -57,8 +57,12 @@ ) ) parser.add_argument( - "--verbose", "-v", action="store_true", - help="Print debug information") + "--verbose", "-v", action="count", default=0, + help=( + "Increase log verbosity. Can be supplied twice for " + "maximum verbosity." + ) + ) parser.add_argument( "--no-runtime", action="store_true", default=False, help="Disable Steam Runtime") @@ -155,7 +159,7 @@ exec_args = [shlex.quote(arg) for arg in args.exec_args] if args.verbose: - cli_args += ["--verbose"] + cli_args += ["-" + ("v" * args.verbose)] if args.no_runtime: cli_args += ["--no-runtime"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/src/protontricks/cli/main.py new/protontricks-1.11.0/src/protontricks/cli/main.py --- old/protontricks-1.10.5/src/protontricks/cli/main.py 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/src/protontricks/cli/main.py 2023-12-30 17:52:23.000000000 +0100 @@ -75,8 +75,11 @@ formatter_class=argparse.RawTextHelpFormatter ) parser.add_argument( - "--verbose", "-v", action="store_true", - help="Print debug information" + "--verbose", "-v", action="count", default=0, + help=( + "Increase log verbosity. Can be supplied twice for " + "maximum verbosity." + ) ) parser.add_argument( "--no-term", action="store_true", @@ -383,6 +386,8 @@ shell=True ) + logger.info("Command returned %d", returncode) + sys.exit(returncode) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/src/protontricks/cli/util.py new/protontricks-1.11.0/src/protontricks/cli/util.py --- old/protontricks-1.10.5/src/protontricks/cli/util.py 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/src/protontricks/cli/util.py 2023-12-30 17:52:23.000000000 +0100 @@ -8,7 +8,7 @@ import traceback from pathlib import Path -from ..gui import get_gui_provider, show_text_dialog +from ..gui import show_text_dialog def _get_log_file_path(): @@ -34,23 +34,29 @@ pass -def enable_logging(info=False, record_to_file=True): +def enable_logging(level=0, record_to_file=True): """ Enables logging. - If info is True, print INFO messages in addition to WARNING and ERROR - messages + :param int level: Level of logging. 0 = WARNING, 1 = INFO, 2 = DEBUG. :param bool record_to_file: Whether to log the generated log messages to a temporary file. This is used for the error dialog containing log records. """ - level = logging.INFO if info else logging.WARNING + if level >= 2: + level = logging.DEBUG + label = "DEBUG" + elif level >= 1: + level = logging.INFO + label = "INFO" + else: + level = logging.WARNING + label = "WARNING" # 'PROTONTRICKS_LOG_LEVEL' env var allows separate Bash scripts # to detect when logging is enabled. - os.environ["PROTONTRICKS_LOG_LEVEL"] = \ - "INFO" if level == logging.INFO else "WARNING" + os.environ["PROTONTRICKS_LOG_LEVEL"] = label logger = logging.getLogger("protontricks") @@ -69,9 +75,11 @@ logging.Formatter("%(name)s (%(levelname)s): %(message)s") ) - logger.setLevel(logging.INFO) + logger.setLevel(logging.DEBUG) logger.addHandler(stream_handler) + logger.debug("Stream log handler added") + if not record_to_file: return @@ -82,8 +90,8 @@ if not file_handler_added: # Record log files to temporary file. This means log messages can be # printed at the end of the session in an error dialog. - # *All* log messages are written into this file whether `--verbose` - # is enabled or not. + # INFO and WARNING log messages are written into this file whether + # `--verbose` is enabled or not. log_file_path = _get_log_file_path() try: log_file_path.unlink() @@ -98,6 +106,8 @@ # Ensure the log file is removed before the process exits atexit.register(_delete_log_file) + logger.debug("File log handler added") + def exit_with_error(error, desktop=False): """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/src/protontricks/config.py new/protontricks-1.11.0/src/protontricks/config.py --- old/protontricks-1.10.5/src/protontricks/config.py 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/src/protontricks/config.py 2023-12-30 17:52:23.000000000 +0100 @@ -1,9 +1,10 @@ import configparser - +import logging import os - from pathlib import Path +logger = logging.getLogger("protontricks") + class Config: def __init__(self): @@ -30,6 +31,10 @@ Set the configuration value in the given section and its field, and save the configuration file """ + logger.debug( + "Setting configuration field [%s][%s] = %s", + section, option, value + ) self._parser.setdefault(section, {}) self._parser[section][option] = value diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/src/protontricks/data/scripts/bwrap_launcher.sh new/protontricks-1.11.0/src/protontricks/data/scripts/bwrap_launcher.sh --- old/protontricks-1.10.5/src/protontricks/data/scripts/bwrap_launcher.sh 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/src/protontricks/data/scripts/bwrap_launcher.sh 2023-12-30 17:52:23.000000000 +0100 @@ -2,8 +2,16 @@ # Helper script set -o errexit +function log_debug () { + if [[ "$PROTONTRICKS_LOG_LEVEL" != "DEBUG" ]]; then + return + fi + + log "$@" +} + function log_info () { - if [[ "$PROTONTRICKS_LOG_LEVEL" != "INFO" ]]; then + if [[ "$PROTONTRICKS_LOG_LEVEL" = "WARNING" ]]; then return fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/src/protontricks/data/scripts/wine_launch.sh new/protontricks-1.11.0/src/protontricks/data/scripts/wine_launch.sh --- old/protontricks-1.10.5/src/protontricks/data/scripts/wine_launch.sh 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/src/protontricks/data/scripts/wine_launch.sh 2023-12-30 17:52:23.000000000 +0100 @@ -2,8 +2,14 @@ # Helper script created by Protontricks to run Wine binaries using Steam Runtime set -o errexit +function log_debug () { + if [[ "$PROTONTRICKS_LOG_LEVEL" != "DEBUG" ]]; then + return + fi +} + function log_info () { - if [[ "$PROTONTRICKS_LOG_LEVEL" != "INFO" ]]; then + if [[ "$PROTONTRICKS_LOG_LEVEL" = "WARNING" ]]; then return fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/src/protontricks/flatpak.py new/protontricks-1.11.0/src/protontricks/flatpak.py --- old/protontricks-1.10.5/src/protontricks/flatpak.py 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/src/protontricks/flatpak.py 2023-12-30 17:52:23.000000000 +0100 @@ -64,6 +64,7 @@ ) path = path.strip() path = os.fsdecode(path) + logger.debug("XDG path for %s is %s", permission, path) return Path(path) return None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/src/protontricks/gui.py new/protontricks-1.11.0/src/protontricks/gui.py --- old/protontricks-1.10.5/src/protontricks/gui.py 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/src/protontricks/gui.py 2023-12-30 17:52:23.000000000 +0100 @@ -54,7 +54,7 @@ ) from exc -def _get_appid2icon(steam_apps, steam_path): +def _get_appid2icon(steam_apps): """ Get icons for Steam apps to show in the app selection dialog. Return a {appid: icon_path} dict. @@ -65,9 +65,6 @@ ) ) - steam_icon_dir = steam_path / "appcache" / "librarycache" - existing_names = [path.name for path in steam_icon_dir.glob("*")] - protontricks_icon_dir = get_cache_dir() / "app_icons" protontricks_icon_dir.mkdir(exist_ok=True) @@ -77,39 +74,43 @@ # Use library icon for Steam apps, fallback to placeholder icon # for non-Steam shortcuts and missing icons icon_cache_path = protontricks_icon_dir / f"{app.appid}.jpg" - original_icon_path = steam_icon_dir / f"{app.appid}_icon.jpg" # What path to actually use for the app selector icon final_icon_path = placeholder_path - icon_exists = f"{app.appid}_icon.jpg" in existing_names - resize_icon = False - - # Resize icons that have a non-standard size to ensure they can be - # displayed consistently in the app selector - if icon_exists: - final_icon_path = original_icon_path - - with Image.open(original_icon_path) as img: - resize_icon = img.size != APP_ICON_SIZE - - # Resize icons that have a non-standard size to ensure they can - # be displayed consistently in the app selector - if resize_icon: - logger.info( - "App icon %s has unusual size, resizing", - original_icon_path - ) - try: + if app.icon_path: + # Resize icons that have a non-standard size to ensure they can be + # displayed consistently in the app selector + try: + with Image.open(app.icon_path) as img: + # Icon exists, so use the current icon instead of the + # default placeholder. + final_icon_path = app.icon_path + + resize_icon = img.size != APP_ICON_SIZE + + # Resize icons that have a non-standard size to ensure they can + # be displayed consistently in the app selector + if resize_icon: + logger.info( + "App icon %s has unusual size, resizing", + app.icon_path + ) resized_img = img.resize(APP_ICON_SIZE).convert("RGB") resized_img.save(icon_cache_path) final_icon_path = icon_cache_path - except Exception: - logger.warning( - "Could not resize %s, ignoring", - original_icon_path, - exc_info=True - ) + except FileNotFoundError: + # Icon does not exist, the placeholder will be used + pass + except Exception: + # Multitude of reasons can cause image parsing or resizing + # to fail. Instead of trying to catch everything, log the error + # and move on. + logger.warning( + "Could not resize %s, ignoring", + app.icon_path, + exc_info=True + ) appid2icon[app.appid] = final_icon_path @@ -270,7 +271,9 @@ # No installation was selected choice = b"" else: - raise RuntimeError(f"{gui_provider} returned an error") + raise RuntimeError( + f"{gui_provider} returned an error. Stderr: {exc.stderr}" + ) if choice in (b"", b" \n"): return None, None @@ -322,7 +325,7 @@ args = _get_yad_args() # YAD implementation has icons for app selection - appid2icon = _get_appid2icon(steam_apps, steam_path=steam_path) + appid2icon = _get_appid2icon(steam_apps) cmd_input = [ [ @@ -368,7 +371,9 @@ # No game was selected choice = b"" else: - raise RuntimeError(f"{gui_provider} returned an error") + raise RuntimeError( + f"{gui_provider} returned an error. Stderr: {exc.stderr}" + ) if choice in (b"", b" \n"): print("No game was selected. Quitting...") @@ -411,11 +416,17 @@ inaccessible_paths = get_inaccessible_paths(paths) inaccessible_paths = set(map(str, inaccessible_paths)) + logger.debug( + "Following inaccessible paths were found: %s", inaccessible_paths + ) + # Check what paths the user has ignored previously ignored_paths = set( json.loads(config.get("Dialog", "DismissedPaths", "[]")) ) + logger.debug("Following paths have been ignored: %s", ignored_paths) + # Remaining paths that are inaccessible and that haven't been dismissed # by the user remaining_paths = inaccessible_paths - ignored_paths diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/src/protontricks/steam.py new/protontricks-1.11.0/src/protontricks/steam.py --- old/protontricks-1.10.5/src/protontricks/steam.py 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/src/protontricks/steam.py 2023-12-30 17:52:23.000000000 +0100 @@ -1,4 +1,3 @@ -import functools import logging import os import string @@ -9,7 +8,6 @@ import vdf -from .flatpak import is_flatpak_sandbox from .util import lower_dict, is_steam_deck __all__ = ( @@ -48,19 +46,21 @@ Proton prefix) """ __slots__ = ( - "appid", "name", "prefix_path", "install_path", "required_tool_appid", - "required_tool_app" + "appid", "name", "prefix_path", "install_path", "icon_path", + "required_tool_appid", "required_tool_app" ) def __init__( - self, name, install_path, prefix_path=None, appid=None, - required_tool_appid=None): + self, name, install_path, icon_path=None, prefix_path=None, + appid=None, required_tool_appid=None): """ :appid: App's appid :name: The app's human-readable name :prefix_path: Absolute path to where the app's Wine prefix *might* exist. :app_path: Absolute path to app's installation directory + :icon_path: Absolute path to app's icon, whether Steam's own or custom + one configured by user :required_tool_appid: App ID required to run this application. Usually corresponds to a Steam Runtime for Proton installations. @@ -76,6 +76,11 @@ else: self.prefix_path = None + if icon_path: + self.icon_path = Path(icon_path) + else: + self.icon_path = None + self.install_path = Path(install_path) # Reference to another SteamApp will be added later if necessary, @@ -181,11 +186,17 @@ return None @classmethod - def from_appmanifest(cls, path, steam_lib_paths): + def from_appmanifest(cls, path, steam_lib_paths, steam_path=None): """ Parse appmanifest_X.acf file containing Steam app installation metadata and return a SteamApp object + + If 'steam_path' is provided, icon path is also populated """ + logger.debug( + "Creating SteamApp from manifest file in %s", path + ) + try: content = path.read_text(encoding="utf-8") except UnicodeDecodeError: @@ -240,6 +251,13 @@ install_path = Path(path).parent / "common" / app_state["installdir"] + icon_path = None + + # If Steam path was provided, also populate the icon path + if steam_path: + icon_path = \ + steam_path / "appcache" / "librarycache" / f"{appid}_icon.jpg" + # Check if the app requires another app. This is the case with # newer versions of Proton, which use Steam Runtimes installed as # normal Steam apps @@ -255,7 +273,8 @@ return cls( appid=appid, name=name, prefix_path=prefix_path, - install_path=install_path, required_tool_appid=required_tool_appid + install_path=install_path, icon_path=icon_path, + required_tool_appid=required_tool_appid ) @@ -451,7 +470,6 @@ APPINFO_STRUCT_HEADER = "<4sL" -APPINFO_V27_STRUCT_SECTION = "<LLLLQ20sL" APPINFO_V28_STRUCT_SECTION = "<LLLLQ20sL20s" @@ -460,34 +478,6 @@ Parse an appinfo.vdf file and iterate through all the binary VDF objects inside it """ - def _iter_v27_appinfo(data, start): - """ - Parse and iterate appinfo.vdf version 27 - """ - i = start - section_size = struct.calcsize(APPINFO_V27_STRUCT_SECTION) - - while True: - # We don't need any of the fields besides 'entry_size', - # which is used to determine the length of the variable-length VDF - # field. - # Still, here they are for posterity's sake. - (appid, entry_size, infostate, last_updated, access_token, - sha_hash, change_number) = struct.unpack( - APPINFO_V27_STRUCT_SECTION, data[i:i+section_size]) - vdf_section_size = entry_size - (section_size - 8) - - i += section_size - - vdf_d = vdf.binary_loads(data[i:i+vdf_section_size]) - vdf_d = lower_dict(vdf_d) - yield vdf_d - - i += vdf_section_size - - if i == len(data) - 4: - return - def _iter_v28_appinfo(data, start): """ Parse and iterate appinfo.vdf version 28. @@ -516,6 +506,8 @@ if i == len(data) - 4: return + logger.debug("Loading appinfo.vdf in %s", path) + # appinfo.vdf is not actually a (binary) VDF file, but a binary file # containing multiple binary VDF sections. # File structure based on comment from vdf developer: @@ -531,13 +523,16 @@ i += header_size - if magic == b"'DV\x07": - # TODO: Remove this once V28 is used in stable version of Steam - yield from _iter_v27_appinfo(data, i) - elif magic == b'(DV\x07': + logger.debug("appinfo.vdf has magic number %s", magic) + + if magic == b'(DV\x07': yield from _iter_v28_appinfo(data, i) else: - raise SyntaxError("Invalid file magic number") + raise SyntaxError( + "Invalid file magic number. The appinfo.vdf version might not be " + "supported by the current version of Protontricks - please " + "check for updates." + ) def get_appinfo_sections(path): @@ -565,6 +560,8 @@ if "aliases" in entry: aliases += entry["aliases"].split(",") + logger.debug("%s has compat tool aliases %s", default_name, aliases) + if compat_tool_name in aliases: return entry["appid"] @@ -596,6 +593,8 @@ except StopIteration: return None + logger.debug("Finding Steam compat tool name for appid %s", appid) + # Determine which Proton version to use (either globally or for # a specific app if `appid` was provided) by checking # `<steam_dir>/config/config.vdf` and `<steam_dir>/appcache/appinfo.vdf`. @@ -625,12 +624,23 @@ # App ID was most likely not provided app_section = None + try: + manifest_app_compat_section = next( + entry for mapping_appid, entry in + steam_play_manifest["appinfo"]["extended"]["app_mappings"].items() + if int(mapping_appid) == appid + ) + except StopIteration: + # App doesn't have a default compatibility tool mapping + manifest_app_compat_section = None + # ToolMapping seems to be used in older Steam beta releases try: tool_mapping = ( vdf_data["installconfigstore"]["software"]["valve"]["steam"] ["toolmapping"] ) + logger.debug("Found ToolMapping entry") except KeyError: tool_mapping = {} @@ -641,6 +651,7 @@ vdf_data["installconfigstore"]["software"]["valve"]["steam"] ["compattoolmapping"] ) + logger.debug("Found CompatToolMapping entry") except KeyError: compat_tool_mapping = {} @@ -678,7 +689,19 @@ ) potential_names.append(recommended_runtime) - # Global user settings have the 3rd highest priority + # Game specific default compatibility tool mapping in Steam Play 2.0 + # manifest has the 3rd highest priority + if manifest_app_compat_section: + if "tool" in manifest_app_compat_section: + tool = manifest_app_compat_section["tool"] + logger.info( + "App has default compatibility tool mapping in the Steam Play " + "manifest: %s", + tool + ) + potential_names.append(tool) + + # Global user settings have the 4th highest priority if compat_tool_mapping.get("0", {}).get("name"): tool_name = compat_tool_mapping["0"]["name"] logger.info( @@ -688,7 +711,7 @@ ) potential_names.append(tool_name) - # Legacy user settings (ToolMapping) have the 4th highest priority + # Legacy user settings (ToolMapping) have the 5th highest priority if tool_mapping.get(str(appid), {}).get("name", {}): tool_name = tool_mapping[str(appid)]["name"] logger.info( @@ -779,6 +802,10 @@ if prefix_path.is_dir(): candidates.append(prefix_path) + logger.debug( + "Found compatdata directories for app %s: %s", appid, candidates + ) + if len(candidates) > 1: # If we have more than one possible prefix path, use the one # with the most recent modification date @@ -883,6 +910,12 @@ if is_library_folder_xdg_steam and is_flatpak_steam: path = flatpak_steam_path + logger.debug( + "Found Steam library folder %s. Is Flatpak path: %s, " + "Is XDG Steam path: %s.", + path, is_flatpak_steam, is_library_folder_xdg_steam + ) + library_folders.append(path) logger.info( @@ -934,6 +967,10 @@ ] extra_ct_paths_env = os.getenv("STEAM_EXTRA_COMPAT_TOOLS_PATHS") if extra_ct_paths_env: + logger.debug( + "Including extra compat tool paths provided via env var: %s", + extra_ct_paths_env + ) paths += [Path(path) for path in extra_ct_paths_env.split(os.pathsep)] paths += [steam_root / "compatibilitytools.d"] @@ -956,6 +993,10 @@ for vdf_path in comptool_files: content = vdf_path.read_text() + logger.debug( + "Parsing custom compatibility tool manifest at %s", vdf_path + ) + try: vdf_data = vdf.loads(content) except SyntaxError: @@ -1009,6 +1050,11 @@ ) continue + logger.debug( + "Found custom compatibility tool %s at %s", + internal_name, install_path + ) + custom_tool_apps.append( SteamApp( name=internal_name, install_path=install_path, @@ -1069,6 +1115,8 @@ for user_id, user_data in user_datas ] + logger.debug("Found Steam user entries: %s", users) + # Return the user with the highest timestamp, as that's likely to be the # currently logged-in user if users: @@ -1175,11 +1223,23 @@ ) continue + icon_path = None + + if shortcut_data.get("icon", None): + icon_path = Path(shortcut_data["icon"]) + + logger.debug( + "Creating SteamApp from non-Steam shortcut in %s", install_path + ) + steam_apps.append( SteamApp( appid=appid, name=f"Non-Steam shortcut: {shortcut_data['appname']}", - prefix_path=prefix_path, install_path=install_path + prefix_path=prefix_path, + install_path=install_path, + icon_path=icon_path + ) ) @@ -1251,7 +1311,8 @@ for manifest_path in appmanifest_paths: try: steam_app = SteamApp.from_appmanifest( - manifest_path, steam_lib_paths=steam_lib_paths + manifest_path, steam_lib_paths=steam_lib_paths, + steam_path=steam_path ) except PermissionError as exc: logger.warning( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/src/protontricks/util.py new/protontricks-1.11.0/src/protontricks/util.py --- old/protontricks-1.10.5/src/protontricks/util.py 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/src/protontricks/util.py 2023-12-30 17:52:23.000000000 +0100 @@ -21,8 +21,13 @@ logger = logging.getLogger("protontricks") SUPPORTED_STEAM_RUNTIMES = [ + # Old names "Steam Linux Runtime - Soldier", - "Steam Linux Runtime - Sniper" + "Steam Linux Runtime - Sniper", + + # New names + "Steam Linux Runtime 2.0 (soldier)", + "Steam Linux Runtime 3.0 (sniper)" ] OS_RELEASE_PATHS = [ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/tests/cli/test_launch.py new/protontricks-1.11.0/tests/cli/test_launch.py --- old/protontricks-1.10.5/tests/cli/test_launch.py 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/tests/cli/test_launch.py 2023-12-30 17:52:23.000000000 +0100 @@ -119,7 +119,7 @@ # CLI flags are passed through to the main CLI entrypoint assert cli_args[0:6] == [ - "--verbose", "--no-runtime", "--no-bwrap", + "-v", "--no-runtime", "--no-bwrap", "--no-background-wineserver", "--no-term", "-c" ] assert cli_args[6].startswith("wine ") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/tests/cli/test_main.py new/protontricks-1.11.0/tests/cli/test_main.py --- old/protontricks-1.10.5/tests/cli/test_main.py 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/tests/cli/test_main.py 2023-12-30 17:52:23.000000000 +0100 @@ -929,3 +929,36 @@ assert "[-h] [--verbose]" in stderr # Help message assert "positional arguments:" in stderr + + +@pytest.mark.parametrize( + "parameter,log_levels", + [ + (None, []), + ("-v", ["INFO"]), + ("-vv", ["INFO", "DEBUG"]) + ] +) +def test_cli_enable_logging(cli, parameter, log_levels): + """ + Run the CLI interface with different logging levels and ensure + that log messages with corresponding log levels are printed + """ + if parameter: + _, stderr = cli( + [parameter, "-s", "nothing"], + expect_returncode=1, # We don't care whether the command succeeds + include_stderr=True + ) + + for log_level in log_levels: + assert log_level in stderr + elif not parameter: + _, stderr = cli( + ["-s", "nothing"], + expect_returncode=1, + include_stderr=True + ) + + assert "DEBUG" not in stderr + assert "INFO" not in stderr diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/tests/conftest.py new/protontricks-1.11.0/tests/conftest.py --- old/protontricks-1.10.5/tests/conftest.py 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/tests/conftest.py 2023-12-30 17:52:23.000000000 +0100 @@ -19,6 +19,7 @@ from protontricks.steam import (APPINFO_STRUCT_HEADER, APPINFO_V28_STRUCT_SECTION, SteamApp, get_appid_from_shortcut) +from protontricks.steam import iter_appinfo_sections @pytest.fixture(scope="function", autouse=True) @@ -45,12 +46,12 @@ @pytest.fixture(scope="function") -def verbose_logging(): +def info_logging(): """ - Enable verbose logging to ensure INFO messages are captured by - the caplog fixture as well + Enable logging to ensure INFO messages are captured by the caplog fixture + as well """ - enable_logging(info=True) + enable_logging(level=1) @pytest.fixture(scope="function", autouse=True) @@ -225,7 +226,8 @@ shortcuts_by_user = defaultdict(list) def func( - install_dir, name, steamid64=None, appid_in_vdf=False, appid=None): + install_dir, name, steamid64=None, appid_in_vdf=False, appid=None, + icon_path=None): if not steamid64: steamid64 = steam_user @@ -270,6 +272,9 @@ # Lutris, use them as-is entry["appid"] = appid_ + if icon_path: + entry["icon"] = icon_path + data["shortcuts"][str(shortcut_id)] = entry shortcut_path.write_bytes(vdf.binary_dumps(data)) @@ -315,41 +320,61 @@ @pytest.fixture(scope="function", autouse=True) -def appinfo_compat_tool_factory(appinfo_factory): +def appinfo_compat_tool_factory(appinfo_factory, steam_dir): """ Factory function to add compat tool entries to the appinfo.vdf binary file """ - compat_tools = [] - def func(proton_app, compat_tool_name, aliases=None): + manifest_appinfo = next( + section["appinfo"] for section + in iter_appinfo_sections(steam_dir / "appcache" / "appinfo.vdf") + if section["appinfo"]["appid"] == 891390 + ) + if not aliases: aliases = [] aliases.append(compat_tool_name) - compat_tools.append({ + manifest_appinfo["extended"]["compat_tools"][compat_tool_name] = { "appid": proton_app.appid, "compat_tool_name": compat_tool_name, - "aliases": [compat_tool_name] + aliases - }) + "aliases": ",".join(aliases) + } - compat_tool_entries = {} + # Update the appinfo.vdf with the compat tools that have been + # added so far. + appinfo_factory( + appid=891390, # Steam Play 2.0 Manifests app ID, + appinfo=manifest_appinfo + ) - for compat_tool in compat_tools: - compat_tool_entries[compat_tool["compat_tool_name"]] = { - "aliases": ",".join(compat_tool["aliases"]), - "appid": compat_tool["appid"] - } + return func + + +@pytest.fixture(scope="function") +def appinfo_app_mapping_factory(appinfo_factory, steam_dir): + """ + Factory function to add Steam app specific compat tool app mappings + to the appinfo.vdf binary file + """ + def func(steam_app, compat_tool_name): + manifest_appinfo = next( + section["appinfo"] for section + in iter_appinfo_sections(steam_dir / "appcache" / "appinfo.vdf") + if section["appinfo"]["appid"] == 891390 + ) + + manifest_appinfo["extended"]["app_mappings"][str(steam_app.appid)] = { + "appid": steam_app.appid, + "tool": compat_tool_name + } # Update the appinfo.vdf with the compat tools that have been # added so far. appinfo_factory( appid=891390, # Steam Play 2.0 Manifests app ID, - appinfo={ - "extended": { - "compat_tools": compat_tool_entries - } - } + appinfo=manifest_appinfo ) return func @@ -367,7 +392,8 @@ "appinfo": { "appid": 891390, "extended": { - "compat_tools": {} + "compat_tools": {}, + "app_mappings": {} } } } @@ -508,6 +534,9 @@ prefix_path=str( steamapps_dir / "compatdata" / str(appid) / "pfx" + ), + icon_path=( + steam_dir / "appcache" / "librarycache" / f"{appid}_icon.jpg" ) ) if required_tool_app: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/tests/test_gui.py new/protontricks-1.11.0/tests/test_gui.py --- old/protontricks-1.10.5/tests/test_gui.py 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/tests/test_gui.py 2023-12-30 17:52:23.000000000 +0100 @@ -149,6 +149,30 @@ with Image.open(resized_icon_path) as img: assert img.size == (32, 32) + def test_select_game_unidentifiable_icon_skipped( + self, gui_provider, steam_app_factory, steam_dir, home_dir, caplog): + """ + Select a game using the GUI. Ensure a custom icon that's not + identifiable by Pillow is skipped. + """ + steam_apps = [ + steam_app_factory(name="Fake game 1", appid=10) + ] + + icon_path = steam_dir / "appcache" / "librarycache" / "10_icon.jpg" + icon_path.write_bytes(b"") + + gui_provider.mock_stdout = "Fake game 1: 10" + selected_app = select_steam_app_with_gui( + steam_apps=steam_apps, steam_path=steam_dir + ) + + # Warning about icon was logged, but the app was selected successfully + record = caplog.records[-1] + assert record.message.startswith(f"Could not resize {icon_path}") + + assert selected_app.appid == 10 + def test_select_game_no_choice( self, gui_provider, steam_app_factory, steam_dir): """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/protontricks-1.10.5/tests/test_steam.py new/protontricks-1.11.0/tests/test_steam.py --- old/protontricks-1.10.5/tests/test_steam.py 2023-09-05 17:40:52.000000000 +0200 +++ new/protontricks-1.11.0/tests/test_steam.py 2023-12-30 17:52:23.000000000 +0100 @@ -32,6 +32,28 @@ assert steam_app.name == "Fake game" assert steam_app.appid == 10 + assert not steam_app.icon_path + + def test_steam_app_from_appmanifest_and_steam_path( + self, steam_app_factory, steam_dir): + """ + Create a SteamApp from an appmanifest file and Steam path + """ + steam_app = steam_app_factory(name="Fake game", appid=10) + + appmanifest_path = \ + Path(steam_app.install_path).parent.parent / "appmanifest_10.acf" + + steam_app = SteamApp.from_appmanifest( + path=appmanifest_path, + steam_lib_paths=[steam_dir / "steam" / "steamapps"], + steam_path=steam_dir + ) + + assert steam_app.name == "Fake game" + assert steam_app.appid == 10 + assert steam_app.icon_path \ + == steam_dir / "appcache" / "librarycache" / "10_icon.jpg" @pytest.mark.parametrize( "content", @@ -212,7 +234,7 @@ # version for this game assert proton_app.name == "Proton 6.66" - @pytest.mark.usefixtures("verbose_logging") + @pytest.mark.usefixtures("info_logging") def test_find_legacy_tool_mapping_global( self, steam_dir, steam_config_path, proton_factory, steam_app_factory): @@ -263,9 +285,7 @@ ) assert proton_app.name == "Proton B" - - - @pytest.mark.usefixtures("steam_deck", "verbose_logging") + @pytest.mark.usefixtures("steam_deck", "info_logging") def test_find_steam_deck_profile( self, steam_app_factory, proton_factory, appinfo_factory, default_proton, steam_config_path, steam_dir): @@ -314,7 +334,7 @@ assert proton_app.name == "Proton 7.77" - @pytest.mark.usefixtures("verbose_logging") + @pytest.mark.usefixtures("info_logging") def test_find_steam_default_proton( self, steam_app_factory, steam_dir, default_proton, proton_factory, steam_config_path, caplog): @@ -347,8 +367,53 @@ assert proton_app.name == "Proton 4.20" - record = caplog.records[-2] - assert "Using stable version of Proton" in record.message + assert any( + record for record in caplog.records + if "Using stable version of Proton" in record.message + ) + + @pytest.mark.usefixtures("info_logging") + def test_find_steam_steamplay_manifest_app_mapping( + self, steam_app_factory, steam_dir, proton_factory, + appinfo_app_mapping_factory, steam_config_path, caplog): + """ + Ensure the function returns the Proton version defined in the + Steam Play manifest if one is defined + """ + steam_app = steam_app_factory(name="Fake game", appid=10) + proton_app = proton_factory( + name="Test Proton", appid=123450, compat_tool_name="test-proton" + ) + + appinfo_app_mapping_factory( + steam_app=steam_app, compat_tool_name="test-proton" + ) + + steam_config_path.write_text( + vdf.dumps({ + "InstallConfigStore": { + "Software": { + "Valve": { + "Steam": {} + } + } + } + }) + ) + + proton_app = find_steam_compat_tool_app( + steam_path=steam_dir, + steam_apps=[steam_app, proton_app], + appid=10 + ) + + assert proton_app.appid == 123450 + + assert any( + record for record in caplog.records + if "App has default compatibility tool mapping in the Steam Play" + in record.message + ) class TestFindLibraryPaths: @@ -930,7 +995,27 @@ assert shortcut_apps[0].name == "Non-Steam shortcut: fakegame.exe" assert shortcut_apps[0].appid == 4149337689 - @pytest.mark.usefixtures("verbose_logging") + def test_get_custom_windows_shortcuts_populate_icon_path( + self, steam_dir, shortcut_factory): + """ + Retrieve custom Windows shortcut. The 'icon_path' property is populated + if the icon path is found in `shortcuts.vdf`. + """ + shortcut_factory( + install_dir="fake/path/", name="fakegame.exe", + icon_path="/fake/icon/path.png" + ) + + shortcut_apps = get_custom_windows_shortcuts( + steam_dir, steam_lib_paths=[steam_dir] + ) + + assert len(shortcut_apps) == 1 + assert shortcut_apps[0].name == "Non-Steam shortcut: fakegame.exe" + assert shortcut_apps[0].appid == 4149337689 + assert shortcut_apps[0].icon_path == Path("/fake/icon/path.png") + + @pytest.mark.usefixtures("info_logging") def test_get_custom_windows_shortcuts_non_numeric_appid( self, steam_dir, shortcut_factory, caplog): """ @@ -966,7 +1051,7 @@ "app ID 'lutris-fake-game'" in record.message ) - @pytest.mark.usefixtures("verbose_logging") + @pytest.mark.usefixtures("info_logging") def test_get_custom_windows_shortcuts_no_prefix( self, steam_dir, shortcut_factory, caplog): """