mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-09 09:54:14 +02:00
[appimage] fix: missing **Exec** parameters on generated desktop entries
This commit is contained in:
@@ -25,6 +25,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
- AppImage
|
||||||
|
- missing **Exec** parameters on generated desktop entries [#152](https://github.com/vinifmor/bauh/issues/152)
|
||||||
- Core
|
- Core
|
||||||
- bauh release notification not working properly
|
- bauh release notification not working properly
|
||||||
- Web:
|
- Web:
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ from bauh.gems.appimage import query, INSTALLATION_PATH, LOCAL_PATH, SUGGESTIONS
|
|||||||
CONFIG_DIR, UPDATES_IGNORED_FILE, util, get_default_manual_installation_file_dir
|
CONFIG_DIR, UPDATES_IGNORED_FILE, util, get_default_manual_installation_file_dir
|
||||||
from bauh.gems.appimage.config import read_config
|
from bauh.gems.appimage.config import read_config
|
||||||
from bauh.gems.appimage.model import AppImage
|
from bauh.gems.appimage.model import AppImage
|
||||||
|
from bauh.gems.appimage.util import replace_desktop_entry_exec_command
|
||||||
from bauh.gems.appimage.worker import DatabaseUpdater, SymlinksVerifier
|
from bauh.gems.appimage.worker import DatabaseUpdater, SymlinksVerifier
|
||||||
|
|
||||||
DB_APPS_PATH = '{}/{}'.format(str(Path.home()), '.local/share/bauh/appimage/apps.db')
|
DB_APPS_PATH = '{}/{}'.format(str(Path.home()), '.local/share/bauh/appimage/apps.db')
|
||||||
@@ -39,7 +40,6 @@ DB_RELEASES_PATH = '{}/{}'.format(str(Path.home()), '.local/share/bauh/appimage/
|
|||||||
|
|
||||||
DESKTOP_ENTRIES_PATH = '{}/.local/share/applications'.format(str(Path.home()))
|
DESKTOP_ENTRIES_PATH = '{}/.local/share/applications'.format(str(Path.home()))
|
||||||
|
|
||||||
RE_DESKTOP_EXEC = re.compile(r'Exec\s*=\s*.+\n')
|
|
||||||
RE_DESKTOP_ICON = re.compile(r'Icon\s*=\s*.+\n')
|
RE_DESKTOP_ICON = re.compile(r'Icon\s*=\s*.+\n')
|
||||||
RE_ICON_ENDS_WITH = re.compile(r'.+\.(png|svg)$')
|
RE_ICON_ENDS_WITH = re.compile(r'.+\.(png|svg)$')
|
||||||
RE_APPIMAGE_NAME = re.compile(r'(.+)\.appimage', flags=re.IGNORECASE)
|
RE_APPIMAGE_NAME = re.compile(r'(.+)\.appimage', flags=re.IGNORECASE)
|
||||||
@@ -530,7 +530,9 @@ class AppImageManager(SoftwareManager):
|
|||||||
with open('{}/{}'.format(extracted_folder, desktop_entry)) as f:
|
with open('{}/{}'.format(extracted_folder, desktop_entry)) as f:
|
||||||
de_content = f.read()
|
de_content = f.read()
|
||||||
|
|
||||||
de_content = RE_DESKTOP_EXEC.sub('Exec="{}"\n'.format(file_path), de_content)
|
de_content = replace_desktop_entry_exec_command(desktop_entry=de_content,
|
||||||
|
appname=pkg.name,
|
||||||
|
file_path=file_path)
|
||||||
|
|
||||||
extracted_icon = self._find_icon_file(extracted_folder)
|
extracted_icon = self._find_icon_file(extracted_folder)
|
||||||
|
|
||||||
@@ -675,7 +677,7 @@ class AppImageManager(SoftwareManager):
|
|||||||
else:
|
else:
|
||||||
self.logger.error("Could not find the AppImage file of '{}' in '{}'".format(pkg.name, installation_dir))
|
self.logger.error("Could not find the AppImage file of '{}' in '{}'".format(pkg.name, installation_dir))
|
||||||
|
|
||||||
def cache_to_disk(self, pkg: SoftwarePackage, icon_bytes: bytes, only_icon: bool):
|
def cache_to_disk(self, pkg: SoftwarePackage, icon_bytes: Optional[bytes], only_icon: bool):
|
||||||
self.serialize_to_disk(pkg, icon_bytes, only_icon)
|
self.serialize_to_disk(pkg, icon_bytes, only_icon)
|
||||||
|
|
||||||
def get_screenshots(self, pkg: AppImage) -> List[str]:
|
def get_screenshots(self, pkg: AppImage) -> List[str]:
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
RE_DESKTOP_EXEC = re.compile(r'(Exec\s*=(.+)(\n?))')
|
||||||
|
RE_MANY_SPACES = re.compile(r'\s+')
|
||||||
|
|
||||||
|
|
||||||
def find_appimage_file(folder: str) -> str:
|
def find_appimage_file(folder: str) -> str:
|
||||||
@@ -6,3 +10,27 @@ def find_appimage_file(folder: str) -> str:
|
|||||||
for f in files:
|
for f in files:
|
||||||
if f.lower().endswith('.appimage'):
|
if f.lower().endswith('.appimage'):
|
||||||
return '{}/{}'.format(folder, f)
|
return '{}/{}'.format(folder, f)
|
||||||
|
|
||||||
|
|
||||||
|
def replace_desktop_entry_exec_command(desktop_entry: str, appname: str, file_path: str) -> str:
|
||||||
|
execs = RE_DESKTOP_EXEC.findall(desktop_entry)
|
||||||
|
|
||||||
|
if not execs:
|
||||||
|
return desktop_entry
|
||||||
|
|
||||||
|
final_entry = desktop_entry
|
||||||
|
treated_name = appname.strip().lower()
|
||||||
|
|
||||||
|
for exec_groups in execs:
|
||||||
|
full_match = exec_groups[0]
|
||||||
|
cmd = RE_MANY_SPACES.sub(' ', exec_groups[1].strip())
|
||||||
|
if cmd:
|
||||||
|
words = cmd.split(' ')
|
||||||
|
|
||||||
|
for idx in range(len(words)):
|
||||||
|
if words[idx].lower() == treated_name:
|
||||||
|
words[idx] = '"{}"'.format(file_path)
|
||||||
|
|
||||||
|
final_entry = final_entry.replace(full_match, full_match.replace(exec_groups[1], ' '.join(words)))
|
||||||
|
|
||||||
|
return final_entry
|
||||||
|
|||||||
0
tests/gems/appimage/__init__.py
Normal file
0
tests/gems/appimage/__init__.py
Normal file
239
tests/gems/appimage/test_util.py
Normal file
239
tests/gems/appimage/test_util.py
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
from bauh.gems.appimage.util import replace_desktop_entry_exec_command
|
||||||
|
|
||||||
|
|
||||||
|
class TestUtil(TestCase):
|
||||||
|
|
||||||
|
def test_replace_desktop_entry_exec_command__only_one_exec_field_no_spaces_and_no_params(self):
|
||||||
|
desktop_entry = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
Exec=myapp
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = replace_desktop_entry_exec_command(desktop_entry=desktop_entry,
|
||||||
|
appname='myapp',
|
||||||
|
file_path='/path/to/myapp.appimage')
|
||||||
|
|
||||||
|
expected = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
Exec="/path/to/myapp.appimage"
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
|
def test_replace_desktop_entry_exec_command__only_one_exec_field_command_with_different_cases(self):
|
||||||
|
desktop_entry = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
Exec=MyApP
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = replace_desktop_entry_exec_command(desktop_entry=desktop_entry,
|
||||||
|
appname='myapp',
|
||||||
|
file_path='/path/to/myapp.appimage')
|
||||||
|
|
||||||
|
expected = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
Exec="/path/to/myapp.appimage"
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
|
def test_replace_desktop_entry_exec_command__only_one_exec_field_no_spaces_and_params(self):
|
||||||
|
desktop_entry = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
Exec=myapp %f
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = replace_desktop_entry_exec_command(desktop_entry=desktop_entry,
|
||||||
|
appname='myapp',
|
||||||
|
file_path='/path/to/myapp.appimage')
|
||||||
|
|
||||||
|
expected = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
Exec="/path/to/myapp.appimage" %f
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
|
def test_replace_desktop_entry_exec_command__only_one_exec_field_no_line_jump_in_the_end(self):
|
||||||
|
desktop_entry = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
Exec=myapp %f"""
|
||||||
|
|
||||||
|
res = replace_desktop_entry_exec_command(desktop_entry=desktop_entry,
|
||||||
|
appname='myapp',
|
||||||
|
file_path='/path/to/myapp.appimage')
|
||||||
|
|
||||||
|
expected = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
Exec="/path/to/myapp.appimage" %f"""
|
||||||
|
|
||||||
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
|
def test_replace_desktop_entry_exec_command__only_one_exec_field_with_spaces_and_params(self):
|
||||||
|
desktop_entry = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
Exec = myapp %f --a
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = replace_desktop_entry_exec_command(desktop_entry=desktop_entry,
|
||||||
|
appname='myapp',
|
||||||
|
file_path='/path/to/myapp.appimage')
|
||||||
|
|
||||||
|
expected = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
Exec ="/path/to/myapp.appimage" %f --a
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
|
def test_replace_desktop_entry_exec_command__param_with_the_same_app_name(self):
|
||||||
|
desktop_entry = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
Exec=myapp %f --myapp
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = replace_desktop_entry_exec_command(desktop_entry=desktop_entry,
|
||||||
|
appname='myapp',
|
||||||
|
file_path='/path/to/myapp.appimage')
|
||||||
|
|
||||||
|
expected = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
Exec="/path/to/myapp.appimage" %f --myapp
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
|
def test_replace_desktop_entry_exec_command__evvar_with_same_app_name(self):
|
||||||
|
desktop_entry = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
Exec=MYAPP=123 myapp
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = replace_desktop_entry_exec_command(desktop_entry=desktop_entry,
|
||||||
|
appname='myapp',
|
||||||
|
file_path='/path/to/myapp.appimage')
|
||||||
|
|
||||||
|
expected = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
Exec=MYAPP=123 "/path/to/myapp.appimage"
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
|
def test_replace_desktop_entry_exec_command__only_one_tryexec_field_with_spaces_and_params(self):
|
||||||
|
desktop_entry = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
TryExec = myapp %f --a
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = replace_desktop_entry_exec_command(desktop_entry=desktop_entry,
|
||||||
|
appname='myapp',
|
||||||
|
file_path='/path/to/myapp.appimage')
|
||||||
|
|
||||||
|
expected = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
TryExec ="/path/to/myapp.appimage" %f --a
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
|
def test_replace_desktop_entry_exec_command__exec_and_tryexec_fields(self):
|
||||||
|
desktop_entry = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
TryExec = myapp %f
|
||||||
|
Exec=myapp --a
|
||||||
|
Terminal=false
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = replace_desktop_entry_exec_command(desktop_entry=desktop_entry,
|
||||||
|
appname='myapp',
|
||||||
|
file_path='/path/to/myapp.appimage')
|
||||||
|
|
||||||
|
expected = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
TryExec ="/path/to/myapp.appimage" %f
|
||||||
|
Exec="/path/to/myapp.appimage" --a
|
||||||
|
Terminal=false
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
|
def test_replace_desktop_entry_exec_command__exec_and_tryexec_fields_with_envvars_and_params(self):
|
||||||
|
desktop_entry = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
TryExec=__MY_VAR=1 myapp %f
|
||||||
|
Exec=NEW_VAR=abc myapp --a
|
||||||
|
Terminal=false
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = replace_desktop_entry_exec_command(desktop_entry=desktop_entry,
|
||||||
|
appname='myapp',
|
||||||
|
file_path='/path/to/myapp.appimage')
|
||||||
|
|
||||||
|
expected = """
|
||||||
|
Name=MyApp
|
||||||
|
Icon=MyApp
|
||||||
|
TryExec=__MY_VAR=1 "/path/to/myapp.appimage" %f
|
||||||
|
Exec=NEW_VAR=abc "/path/to/myapp.appimage" --a
|
||||||
|
Terminal=false
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.assertEqual(expected, res)
|
||||||
|
|
||||||
|
def test_replace_desktop_entry_exec_command__rpcs3(self):
|
||||||
|
desktop_entry = """
|
||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Name=RPCS3
|
||||||
|
GenericName=PlayStation 3 Emulator
|
||||||
|
Comment=An open-source PlayStation 3 emulator/debugger written in C++.
|
||||||
|
Icon=rpcs3
|
||||||
|
TryExec=rpcs3
|
||||||
|
Exec=rpcs3 %f
|
||||||
|
Terminal=false
|
||||||
|
Categories=Game;Emulator;
|
||||||
|
Keywords=PS3;Playstation;
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = replace_desktop_entry_exec_command(desktop_entry=desktop_entry,
|
||||||
|
appname='rpcs3',
|
||||||
|
file_path='/path/to/rpcs3.appimage')
|
||||||
|
|
||||||
|
expected = """
|
||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Name=RPCS3
|
||||||
|
GenericName=PlayStation 3 Emulator
|
||||||
|
Comment=An open-source PlayStation 3 emulator/debugger written in C++.
|
||||||
|
Icon=rpcs3
|
||||||
|
TryExec="/path/to/rpcs3.appimage"
|
||||||
|
Exec="/path/to/rpcs3.appimage" %f
|
||||||
|
Terminal=false
|
||||||
|
Categories=Game;Emulator;
|
||||||
|
Keywords=PS3;Playstation;
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.assertEqual(expected, res)
|
||||||
Reference in New Issue
Block a user