mirror of
https://github.com/lutris/lutris
synced 2024-11-02 08:20:51 +00:00
Refactor check_output usage + remove disks module + move terminal functions to linux module
This commit is contained in:
parent
9938a856c4
commit
d4324b9646
23 changed files with 147 additions and 187 deletions
|
@ -21,7 +21,7 @@ from lutris.exceptions import GameConfigError, watch_lutris_errors
|
|||
from lutris.gui import dialogs
|
||||
from lutris.runner_interpreter import export_bash_script, get_launch_parameters
|
||||
from lutris.runners import InvalidRunner, import_runner, wine
|
||||
from lutris.util import audio, jobs, strings, system, xdgshortcuts
|
||||
from lutris.util import audio, jobs, linux, strings, system, xdgshortcuts
|
||||
from lutris.util.display import (
|
||||
DISPLAY_MANAGER, SCREEN_SAVER_INHIBITOR, disable_compositing, enable_compositing, restore_gamma
|
||||
)
|
||||
|
@ -293,7 +293,7 @@ class Game(GObject.Object):
|
|||
if runtime_updater.is_updating():
|
||||
logger.warning("Runtime updates: %s", runtime_updater.current_updates)
|
||||
dialogs.ErrorDialog(_("Runtime currently updating"), _("Game might not work as expected"))
|
||||
if ("wine" in self.runner_name and not wine.get_system_wine_version() and not LINUX_SYSTEM.is_flatpak):
|
||||
if ("wine" in self.runner_name and not wine.get_wine_version() and not LINUX_SYSTEM.is_flatpak):
|
||||
# TODO find a reference to the root window or better yet a way not
|
||||
# to have Gtk dependent code in this class.
|
||||
root_window = None
|
||||
|
@ -375,7 +375,7 @@ class Game(GObject.Object):
|
|||
Remember that only games using text mode should use the terminal.
|
||||
"""
|
||||
if self.runner.system_config.get("terminal"):
|
||||
terminal = self.runner.system_config.get("terminal_app", system.get_default_terminal())
|
||||
terminal = self.runner.system_config.get("terminal_app", linux.get_default_terminal())
|
||||
if terminal and not system.find_executable(terminal):
|
||||
raise GameConfigError(_("The selected terminal application could not be launched:\n%s") % terminal)
|
||||
return terminal
|
||||
|
|
|
@ -3,12 +3,12 @@ from gettext import gettext as _
|
|||
from gi.repository import GObject, Gtk
|
||||
|
||||
from lutris import runners
|
||||
from lutris.util.log import logger
|
||||
from lutris.gui.config.runner import RunnerConfigDialog
|
||||
from lutris.gui.dialogs import ErrorDialog, QuestionDialog
|
||||
from lutris.gui.dialogs.download import simple_downloader
|
||||
from lutris.gui.dialogs.runner_install import RunnerInstallDialog
|
||||
from lutris.gui.widgets.utils import ICON_SIZE, get_icon
|
||||
from lutris.util.log import logger
|
||||
|
||||
|
||||
class RunnerBox(Gtk.Box):
|
||||
|
|
|
@ -14,7 +14,7 @@ from lutris.cache import get_cache_path
|
|||
from lutris.command import MonitoredCommand
|
||||
from lutris.installer.errors import ScriptingError
|
||||
from lutris.runners import import_task
|
||||
from lutris.util import disks, extract, selective_merge, system
|
||||
from lutris.util import extract, linux, selective_merge, system
|
||||
from lutris.util.fileio import EvilConfigParser, MultiOrderedDict
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.wine.wine import WINE_DEFAULT_ARCH, get_wine_version_exe
|
||||
|
@ -131,7 +131,7 @@ class CommandsMixin:
|
|||
raise ScriptingError("Unable to find executable %s" % file_ref)
|
||||
|
||||
if terminal:
|
||||
terminal = system.get_default_terminal()
|
||||
terminal = linux.get_default_terminal()
|
||||
|
||||
if not working_dir or not os.path.exists(working_dir):
|
||||
working_dir = self.target_path
|
||||
|
@ -223,7 +223,7 @@ class CommandsMixin:
|
|||
if extra_path:
|
||||
drives = [extra_path]
|
||||
else:
|
||||
drives = disks.get_mounted_discs()
|
||||
drives = system.get_mounted_discs()
|
||||
for drive in drives:
|
||||
required_abspath = os.path.join(drive, requires)
|
||||
required_abspath = system.fix_path_case(required_abspath)
|
||||
|
|
|
@ -20,7 +20,7 @@ from lutris.util.display import DISPLAY_MANAGER
|
|||
from lutris.util.jobs import AsyncCall
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.strings import unpack_dependencies
|
||||
from lutris.util.wine.wine import get_system_wine_version, get_wine_version_exe
|
||||
from lutris.util.wine.wine import get_wine_version, get_wine_version_exe
|
||||
|
||||
|
||||
class ScriptInterpreter(GObject.Object, CommandsMixin):
|
||||
|
@ -233,7 +233,7 @@ class ScriptInterpreter(GObject.Object, CommandsMixin):
|
|||
logger.info("Runner %s needs to be installed", runner)
|
||||
runners_to_install.append(runner)
|
||||
|
||||
if self.installer.runner.startswith("wine") and not get_system_wine_version():
|
||||
if self.installer.runner.startswith("wine") and not get_wine_version():
|
||||
WineNotInstalledWarning(parent=self.parent)
|
||||
return runners_to_install
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from lutris.util import system
|
||||
from lutris.util import linux
|
||||
|
||||
|
||||
def get_game_launcher(script):
|
||||
|
@ -8,7 +8,7 @@ def get_game_launcher(script):
|
|||
added.
|
||||
"""
|
||||
launcher_value = None
|
||||
exe = "exe64" if "exe64" in script and system.LINUX_SYSTEM.is_64_bit else "exe"
|
||||
exe = "exe64" if "exe64" in script and linux.LINUX_SYSTEM.is_64_bit else "exe"
|
||||
for launcher in (exe, "iso", "rom", "disk", "main_file"):
|
||||
if launcher not in script:
|
||||
continue
|
||||
|
|
|
@ -8,7 +8,7 @@ from lutris import runtime, settings
|
|||
from lutris.command import MonitoredCommand
|
||||
from lutris.config import LutrisConfig
|
||||
from lutris.runners import import_runner
|
||||
from lutris.util import system
|
||||
from lutris.util import linux, system
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.shell import get_shell_command
|
||||
from lutris.util.strings import split_arguments
|
||||
|
@ -408,5 +408,5 @@ def open_wine_terminal(terminal, wine_path, prefix, env):
|
|||
}
|
||||
env["WINEPREFIX"] = prefix
|
||||
shell_command = get_shell_command(prefix, env, aliases)
|
||||
terminal = terminal or system.get_default_terminal()
|
||||
system.execute([system.get_default_terminal(), "-e", shell_command])
|
||||
terminal = terminal or linux.get_default_terminal()
|
||||
system.execute([linux.get_default_terminal(), "-e", shell_command])
|
||||
|
|
|
@ -316,7 +316,7 @@ class Runner: # pylint: disable=too-many-public-methods
|
|||
return
|
||||
|
||||
versions = runner_info.get("versions") or []
|
||||
arch = system.LINUX_SYSTEM.arch
|
||||
arch = LINUX_SYSTEM.arch
|
||||
if version:
|
||||
if version.endswith("-i386") or version.endswith("-x86_64"):
|
||||
version, arch = version.rsplit("-", 1)
|
||||
|
@ -329,9 +329,9 @@ class Runner: # pylint: disable=too-many-public-methods
|
|||
default_version = [v for v in versions_for_arch if v["default"] is True]
|
||||
if default_version:
|
||||
return default_version[0]
|
||||
elif len(versions) == 1 and system.LINUX_SYSTEM.is_64_bit:
|
||||
elif len(versions) == 1 and LINUX_SYSTEM.is_64_bit:
|
||||
return versions[0]
|
||||
elif len(versions) > 1 and system.LINUX_SYSTEM.is_64_bit:
|
||||
elif len(versions) > 1 and LINUX_SYSTEM.is_64_bit:
|
||||
default_version = [v for v in versions if v["default"] is True]
|
||||
if default_version:
|
||||
return default_version[0]
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
"""Steam for Linux runner"""
|
||||
# Standard Library
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
from gettext import gettext as _
|
||||
|
||||
# Lutris Modules
|
||||
from lutris.command import MonitoredCommand
|
||||
from lutris.runners import NonInstallableRunnerError
|
||||
from lutris.runners.runner import Runner
|
||||
from lutris.util import system
|
||||
from lutris.util import linux, system
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.steam.appmanifest import get_appmanifest_from_appid, get_path_from_appmanifest
|
||||
from lutris.util.steam.config import STEAM_DATA_DIRS, get_default_acf, get_steam_dir, read_config
|
||||
|
@ -136,7 +134,7 @@ class steam(Runner):
|
|||
|
||||
@property
|
||||
def runnable_alone(self):
|
||||
return not system.LINUX_SYSTEM.is_flatpak
|
||||
return not linux.LINUX_SYSTEM.is_flatpak
|
||||
|
||||
@property
|
||||
def appid(self):
|
||||
|
@ -175,7 +173,7 @@ class steam(Runner):
|
|||
return appmanifests[0]
|
||||
|
||||
def get_executable(self):
|
||||
if system.LINUX_SYSTEM.is_flatpak:
|
||||
if linux.LINUX_SYSTEM.is_flatpak:
|
||||
# Use xdg-open for Steam URIs in Flatpak
|
||||
return system.find_executable("xdg-open")
|
||||
if self.runner_config.get("lsi_steam") and system.find_executable("lsi-steam"):
|
||||
|
@ -198,7 +196,7 @@ class steam(Runner):
|
|||
def launch_args(self):
|
||||
"""Provide launch arguments for Steam"""
|
||||
args = [self.get_executable()]
|
||||
if system.LINUX_SYSTEM.is_flatpak:
|
||||
if linux.LINUX_SYSTEM.is_flatpak:
|
||||
return args
|
||||
if self.runner_config.get("start_in_big_picture"):
|
||||
args.append("-bigpicture")
|
||||
|
@ -309,8 +307,7 @@ class steam(Runner):
|
|||
command = [binary_path]
|
||||
else:
|
||||
# Start through steam
|
||||
|
||||
if system.LINUX_SYSTEM.is_flatpak:
|
||||
if linux.LINUX_SYSTEM.is_flatpak:
|
||||
if game_args:
|
||||
steam_uri = "steam://run/%s//%s/" % (self.appid, game_args)
|
||||
else:
|
||||
|
|
|
@ -7,7 +7,7 @@ from urllib.parse import urlparse
|
|||
from lutris import settings
|
||||
from lutris.database.games import get_game_by_field
|
||||
from lutris.runners.runner import Runner
|
||||
from lutris.util import datapath, resources, system
|
||||
from lutris.util import datapath, linux, resources, system
|
||||
from lutris.util.strings import split_arguments
|
||||
|
||||
DEFAULT_ICON = os.path.join(datapath.get(), "media/default_icon.png")
|
||||
|
@ -258,7 +258,7 @@ class web(Runner):
|
|||
if self.runner_config.get("user_agent"):
|
||||
command.append("--user-agent")
|
||||
command.append(self.runner_config.get("user_agent"))
|
||||
if system.LINUX_SYSTEM.is_flatpak:
|
||||
if linux.LINUX_SYSTEM.is_flatpak:
|
||||
command.append("--no-sandbox")
|
||||
|
||||
return {"command": command, "env": self.get_env(False)}
|
||||
|
|
|
@ -26,8 +26,8 @@ from lutris.util.wine.prefix import DEFAULT_DLL_OVERRIDES, WinePrefixManager, fi
|
|||
from lutris.util.wine.wine import (
|
||||
POL_PATH, WINE_DIR, WINE_PATHS, detect_arch, display_vulkan_error, esync_display_limit_warning,
|
||||
esync_display_version_warning, fsync_display_support_warning, fsync_display_version_warning, get_default_version,
|
||||
get_overrides_env, get_proton_paths, get_real_executable, get_system_wine_version, get_wine_versions,
|
||||
is_esync_limit_set, is_fsync_supported, is_gstreamer_build, is_version_esync, is_version_fsync
|
||||
get_overrides_env, get_proton_paths, get_real_executable, get_wine_version, get_wine_versions, is_esync_limit_set,
|
||||
is_fsync_supported, is_gstreamer_build, is_version_esync, is_version_fsync
|
||||
)
|
||||
from lutris.util.wine.x360ce import X360ce
|
||||
|
||||
|
@ -123,7 +123,7 @@ class wine(Runner):
|
|||
versions = get_wine_versions()
|
||||
for version in versions:
|
||||
if version in labels.keys():
|
||||
version_number = get_system_wine_version(WINE_PATHS[version])
|
||||
version_number = get_wine_version(WINE_PATHS[version])
|
||||
label = labels[version].format(version_number)
|
||||
else:
|
||||
label = version
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
# Standard Library
|
||||
import os
|
||||
from gettext import gettext as _
|
||||
|
||||
# Lutris Modules
|
||||
from lutris.runners.runner import Runner
|
||||
from lutris.util import display, system
|
||||
from lutris.util.linux import LINUX_SYSTEM
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.strings import split_arguments
|
||||
|
||||
|
@ -107,7 +106,7 @@ class zdoom(Runner):
|
|||
return executable
|
||||
|
||||
def prelaunch(self):
|
||||
if not system.LINUX_SYSTEM.get_soundfonts():
|
||||
if not LINUX_SYSTEM.get_soundfonts():
|
||||
logger.warning("FluidSynth is not installed, you might not have any music")
|
||||
return True
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ from lutris import settings
|
|||
from lutris.util import http, jobs, system
|
||||
from lutris.util.downloader import Downloader
|
||||
from lutris.util.extract import extract_archive
|
||||
from lutris.util.linux import LINUX_SYSTEM
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.system import LINUX_SYSTEM
|
||||
|
||||
RUNTIME_DISABLED = os.environ.get("LUTRIS_RUNTIME", "").lower() in ("0", "off")
|
||||
DEFAULT_RUNTIME = "Ubuntu-18.04"
|
||||
|
@ -220,7 +220,7 @@ class RuntimeUpdater:
|
|||
|
||||
# Skip 32bit runtimes on 64 bit systems except the main runtime
|
||||
if (
|
||||
runtime["architecture"] == "i386" and system.LINUX_SYSTEM.is_64_bit
|
||||
runtime["architecture"] == "i386" and LINUX_SYSTEM.is_64_bit
|
||||
and not runtime["name"].startswith(("Ubuntu", "lib32"))
|
||||
):
|
||||
logger.debug(
|
||||
|
@ -231,7 +231,7 @@ class RuntimeUpdater:
|
|||
continue
|
||||
|
||||
# Skip 64bit runtimes on 32 bit systems
|
||||
if runtime["architecture"] == "x86_64" and not system.LINUX_SYSTEM.is_64_bit:
|
||||
if runtime["architecture"] == "x86_64" and not LINUX_SYSTEM.is_64_bit:
|
||||
logger.debug(
|
||||
"Skipping runtime %s for %s",
|
||||
runtime["name"],
|
||||
|
@ -299,7 +299,7 @@ def get_runtime_paths(version=None, prefer_system_libs=True, wine_path=None):
|
|||
"steam/i386/usr/lib",
|
||||
]
|
||||
|
||||
if system.LINUX_SYSTEM.is_64_bit:
|
||||
if LINUX_SYSTEM.is_64_bit:
|
||||
if version == "legacy":
|
||||
lutris_runtime_path = "lib64"
|
||||
else:
|
||||
|
|
|
@ -11,7 +11,7 @@ from lutris.installer.installer_file import InstallerFile
|
|||
from lutris.services.base import OnlineService
|
||||
from lutris.services.service_game import ServiceGame
|
||||
from lutris.services.service_media import ServiceMedia
|
||||
from lutris.util import system
|
||||
from lutris.util import linux
|
||||
from lutris.util.http import HTTPError, Request
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.strings import slugify
|
||||
|
@ -331,7 +331,7 @@ def pick_download_url_from_download_info(download_info):
|
|||
bonus = 1
|
||||
if "deb" not in name:
|
||||
bonus = 2
|
||||
if system.LINUX_SYSTEM.is_64_bit:
|
||||
if linux.LINUX_SYSTEM.is_64_bit:
|
||||
if "386" in name or "32" in name:
|
||||
return -1
|
||||
else:
|
||||
|
|
|
@ -5,7 +5,7 @@ from collections import OrderedDict
|
|||
from gettext import gettext as _
|
||||
|
||||
from lutris import runners
|
||||
from lutris.util import system
|
||||
from lutris.util import linux, system
|
||||
from lutris.util.display import DISPLAY_MANAGER, SCREEN_SAVER_INHIBITOR, USE_DRI_PRIME
|
||||
|
||||
VULKAN_DATA_DIRS = [
|
||||
|
@ -236,8 +236,8 @@ system_options = [ # pylint: disable=invalid-name
|
|||
{
|
||||
"option": "gamemode",
|
||||
"type": "bool",
|
||||
"default": system.LINUX_SYSTEM.gamemode_available(),
|
||||
"condition": system.LINUX_SYSTEM.gamemode_available,
|
||||
"default": linux.LINUX_SYSTEM.gamemode_available(),
|
||||
"condition": linux.LINUX_SYSTEM.gamemode_available,
|
||||
"label": _("Enable Feral GameMode"),
|
||||
"help": _("Request a set of optimisations be temporarily applied to the host OS"),
|
||||
},
|
||||
|
@ -309,8 +309,8 @@ system_options = [ # pylint: disable=invalid-name
|
|||
"option": "terminal_app",
|
||||
"label": _("Text based games emulator"),
|
||||
"type": "choice_with_entry",
|
||||
"choices": system.get_terminal_apps,
|
||||
"default": system.get_default_terminal(),
|
||||
"choices": linux.get_terminal_apps,
|
||||
"default": linux.get_default_terminal(),
|
||||
"advanced": True,
|
||||
"help": _("The terminal emulator used with the CLI mode. "
|
||||
"Choose from the list of detected terminal apps or enter "
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
"""Filesystem utilities"""
|
||||
# Standard Library
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
# Third Party Libraries
|
||||
from gi.repository import Gio
|
||||
|
||||
# Lutris Modules
|
||||
from lutris.util.log import logger
|
||||
|
||||
|
||||
def get_mounted_discs():
|
||||
"""Return a list of mounted discs and ISOs
|
||||
|
||||
:rtype: list of Gio.Mount
|
||||
"""
|
||||
volumes = Gio.VolumeMonitor.get()
|
||||
drives = []
|
||||
|
||||
for mount in volumes.get_mounts():
|
||||
if mount.get_volume():
|
||||
device = mount.get_volume().get_identifier("unix-device")
|
||||
if not device:
|
||||
logger.debug("No device for mount %s", mount.get_name())
|
||||
continue
|
||||
|
||||
# Device is a disk drive or ISO image
|
||||
if "/dev/sr" in device or "/dev/loop" in device:
|
||||
drives.append(mount.get_root().get_path())
|
||||
return drives
|
||||
|
||||
|
||||
def find_mount_point(path):
|
||||
"""Return the mount point a file is located on"""
|
||||
path = os.path.abspath(path)
|
||||
while not os.path.ismount(path):
|
||||
path = os.path.dirname(path)
|
||||
return path
|
||||
|
||||
|
||||
def get_mountpoint_drives():
|
||||
"""Return a mapping of mount points with their corresponding drives"""
|
||||
mounts = subprocess.check_output(["mount", "-v"]).decode("utf-8").split("\n")
|
||||
mount_map = []
|
||||
for mount in mounts:
|
||||
mount_parts = mount.split()
|
||||
if len(mount_parts) < 3:
|
||||
continue
|
||||
mount_map.append((mount_parts[2], mount_parts[0]))
|
||||
return dict(mount_map)
|
||||
|
||||
|
||||
def get_drive_for_path(path):
|
||||
"""Return the physical drive a file is located on"""
|
||||
return get_mountpoint_drives().get(find_mount_point(path))
|
|
@ -257,7 +257,7 @@ def check_inno_exe(path):
|
|||
|
||||
def get_innoextract_list(file_path):
|
||||
"""Return the list of files contained in a GOG archive"""
|
||||
output = subprocess.check_output([get_innoextract_path(), "-lmq", file_path])
|
||||
output = system.read_process_output([get_innoextract_path(), "-lmq", file_path])
|
||||
return [line[3:] for line in output.decode().split("\n") if line]
|
||||
|
||||
|
||||
|
|
|
@ -1,18 +1,13 @@
|
|||
"""Parser for the glxinfo utility"""
|
||||
# Standard Library
|
||||
import subprocess
|
||||
|
||||
# Lutris Modules
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.system import read_process_output
|
||||
|
||||
|
||||
class Container: # pylint: disable=too-few-public-methods
|
||||
|
||||
"""A dummy container for data"""
|
||||
|
||||
|
||||
class GlxInfo:
|
||||
|
||||
"""Give access to the glxinfo information"""
|
||||
|
||||
def __init__(self, output=None):
|
||||
|
@ -30,11 +25,7 @@ class GlxInfo:
|
|||
@staticmethod
|
||||
def get_glxinfo_output():
|
||||
"""Return the glxinfo -B output"""
|
||||
try:
|
||||
return subprocess.check_output(["glxinfo", "-B"]).decode()
|
||||
except subprocess.CalledProcessError as ex:
|
||||
logger.error("glxinfo call failed: %s", ex)
|
||||
return ""
|
||||
return read_process_output(["glxinfo", "-B"])
|
||||
|
||||
def as_dict(self):
|
||||
"""Return the attributes as a dict"""
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
"""XrandR based display management"""
|
||||
# Standard Library
|
||||
import re
|
||||
import subprocess
|
||||
from collections import namedtuple
|
||||
|
||||
# Lutris Modules
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.system import read_process_output
|
||||
|
||||
Output = namedtuple("Output", ("name", "mode", "position", "rotation", "primary", "rate"))
|
||||
|
||||
|
@ -13,13 +12,7 @@ Output = namedtuple("Output", ("name", "mode", "position", "rotation", "primary"
|
|||
def _get_vidmodes():
|
||||
"""Return video modes from XrandR"""
|
||||
logger.debug("Retrieving video modes from XrandR")
|
||||
try:
|
||||
xrandr_output = subprocess.check_output(["xrandr"])
|
||||
except subprocess.CalledProcessError as ex:
|
||||
logger.error("Unable to read xrandr: %s", ex)
|
||||
return ""
|
||||
|
||||
return xrandr_output.decode().split("\n")
|
||||
return read_process_output(["xrandr"]).split("\n")
|
||||
|
||||
|
||||
def get_outputs(): # pylint: disable=too-many-locals
|
||||
|
|
|
@ -5,12 +5,10 @@ import platform
|
|||
import re
|
||||
import resource
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from collections import Counter, defaultdict
|
||||
|
||||
from lutris.util import system
|
||||
from lutris.util.disks import get_drive_for_path
|
||||
from lutris.util.graphics import drivers, glxinfo, vkquery
|
||||
from lutris.util.log import logger
|
||||
|
||||
|
@ -160,12 +158,12 @@ class LinuxSystem: # pylint: disable=too-many-public-methods
|
|||
@staticmethod
|
||||
def get_drives():
|
||||
"""Return a list of drives with their filesystems"""
|
||||
try:
|
||||
output = subprocess.check_output(["lsblk", "-f", "--json"]).decode()
|
||||
except subprocess.CalledProcessError as ex:
|
||||
logger.error("Failed to get drive information: %s", ex)
|
||||
return None
|
||||
return [drive for drive in json.loads(output)["blockdevices"] if drive["fstype"] != "squashfs"]
|
||||
lsblk_output = system.read_process_output(["lsblk", "-f", "--json"])
|
||||
return [
|
||||
drive
|
||||
for drive in json.loads(lsblk_output)["blockdevices"]
|
||||
if drive["fstype"] != "squashfs"
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def get_ram_info():
|
||||
|
@ -243,7 +241,7 @@ class LinuxSystem: # pylint: disable=too-many-public-methods
|
|||
|
||||
def get_fs_type_for_path(self, path):
|
||||
"""Return the filesystem type a given path uses"""
|
||||
path_drive = get_drive_for_path(path)
|
||||
path_drive = system.get_drive_for_path(path)
|
||||
for drive in self.get_drives():
|
||||
for partition in drive.get("children", []):
|
||||
if "/dev/%s" % partition["name"] == path_drive:
|
||||
|
@ -312,11 +310,7 @@ class LinuxSystem: # pylint: disable=too-many-public-methods
|
|||
if not ldconfig:
|
||||
logger.error("Could not detect ldconfig on this system")
|
||||
return []
|
||||
try:
|
||||
output = (subprocess.check_output([ldconfig, "-p"]).decode("utf-8", errors="ignore").split("\n"))
|
||||
except subprocess.CalledProcessError as ex:
|
||||
logger.error("Failed to get libraries from ldconfig: %s", ex)
|
||||
return []
|
||||
output = system.read_process_output([ldconfig, "-p"]).split("\n")
|
||||
return [line.strip("\t") for line in output if line.startswith("\t")]
|
||||
|
||||
def get_shared_libraries(self):
|
||||
|
@ -490,3 +484,16 @@ def gather_system_info_str():
|
|||
output += '{}{}{}\n'.format(key + ":", tabs, dictionary[key])
|
||||
output += '\n'
|
||||
return output
|
||||
|
||||
|
||||
def get_terminal_apps():
|
||||
"""Return the list of installed terminal emulators"""
|
||||
return LINUX_SYSTEM.get_terminals()
|
||||
|
||||
|
||||
def get_default_terminal():
|
||||
"""Return the default terminal emulator"""
|
||||
terms = get_terminal_apps()
|
||||
if terms:
|
||||
return terms[0]
|
||||
logger.error("Couldn't find a terminal emulator.")
|
||||
|
|
|
@ -8,10 +8,9 @@ import stat
|
|||
import string
|
||||
import subprocess
|
||||
|
||||
from gi.repository import GLib
|
||||
from gi.repository import Gio, GLib
|
||||
|
||||
from lutris import settings
|
||||
from lutris.util.linux import LINUX_SYSTEM
|
||||
from lutris.util.log import logger
|
||||
|
||||
# Home folders that should never get deleted. This should be localized and return the
|
||||
|
@ -79,6 +78,18 @@ def execute(command, env=None, cwd=None, log_errors=False, quiet=False, shell=Fa
|
|||
return stdout.decode(errors="replace").strip()
|
||||
|
||||
|
||||
def read_process_output(command, timeout=2):
|
||||
"""Return the output of a command as a string"""
|
||||
try:
|
||||
return subprocess.check_output(
|
||||
command,
|
||||
timeout=timeout
|
||||
).decode("utf-8", errors="ignore").strip()
|
||||
except (OSError, subprocess.CalledProcessError) as ex:
|
||||
logger.error("%s command failed: %s", command, ex)
|
||||
return ""
|
||||
|
||||
|
||||
def get_md5_hash(filename):
|
||||
"""Return the md5 hash of a file."""
|
||||
md5 = hashlib.md5()
|
||||
|
@ -115,9 +126,6 @@ def find_executable(exec_name):
|
|||
"""Return the absolute path of an executable"""
|
||||
if not exec_name:
|
||||
return None
|
||||
cached = LINUX_SYSTEM.get(exec_name)
|
||||
if cached:
|
||||
return cached
|
||||
return shutil.which(exec_name)
|
||||
|
||||
|
||||
|
@ -298,19 +306,6 @@ def get_pids_using_file(path):
|
|||
return set(fuser_output.split())
|
||||
|
||||
|
||||
def get_terminal_apps():
|
||||
"""Return the list of installed terminal emulators"""
|
||||
return LINUX_SYSTEM.get_terminals()
|
||||
|
||||
|
||||
def get_default_terminal():
|
||||
"""Return the default terminal emulator"""
|
||||
terms = get_terminal_apps()
|
||||
if terms:
|
||||
return terms[0]
|
||||
logger.error("Couldn't find a terminal emulator.")
|
||||
|
||||
|
||||
def reverse_expanduser(path):
|
||||
"""Replace '/home/username' with '~' in given path."""
|
||||
if not path:
|
||||
|
@ -387,3 +382,49 @@ def get_disk_size(path):
|
|||
def get_running_pid_list():
|
||||
"""Return the list of PIDs from processes currently running"""
|
||||
return [p for p in os.listdir("/proc") if p[0].isdigit()]
|
||||
|
||||
|
||||
def get_mounted_discs():
|
||||
"""Return a list of mounted discs and ISOs
|
||||
|
||||
:rtype: list of Gio.Mount
|
||||
"""
|
||||
volumes = Gio.VolumeMonitor.get()
|
||||
drives = []
|
||||
|
||||
for mount in volumes.get_mounts():
|
||||
if mount.get_volume():
|
||||
device = mount.get_volume().get_identifier("unix-device")
|
||||
if not device:
|
||||
logger.debug("No device for mount %s", mount.get_name())
|
||||
continue
|
||||
|
||||
# Device is a disk drive or ISO image
|
||||
if "/dev/sr" in device or "/dev/loop" in device:
|
||||
drives.append(mount.get_root().get_path())
|
||||
return drives
|
||||
|
||||
|
||||
def find_mount_point(path):
|
||||
"""Return the mount point a file is located on"""
|
||||
path = os.path.abspath(path)
|
||||
while not os.path.ismount(path):
|
||||
path = os.path.dirname(path)
|
||||
return path
|
||||
|
||||
|
||||
def get_mountpoint_drives():
|
||||
"""Return a mapping of mount points with their corresponding drives"""
|
||||
mounts = read_process_output(["mount", "-v"]).split("\n")
|
||||
mount_map = []
|
||||
for mount in mounts:
|
||||
mount_parts = mount.split()
|
||||
if len(mount_parts) < 3:
|
||||
continue
|
||||
mount_map.append((mount_parts[2], mount_parts[0]))
|
||||
return dict(mount_map)
|
||||
|
||||
|
||||
def get_drive_for_path(path):
|
||||
"""Return the physical drive a file is located on"""
|
||||
return get_mountpoint_drives().get(find_mount_point(path))
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
# pylint: disable=missing-docstring
|
||||
# Standard Library
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
|
@ -7,12 +5,11 @@ import subprocess
|
|||
import tempfile
|
||||
import xml.etree.ElementTree
|
||||
|
||||
# Lutris Modules
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.system import execute, read_process_output
|
||||
|
||||
|
||||
class CabInstaller:
|
||||
|
||||
"""Extract and install contents of cab files
|
||||
|
||||
Based on an implementation by tonix64: https://github.com/tonix64/python-installcab
|
||||
|
@ -45,7 +42,7 @@ class CabInstaller:
|
|||
|
||||
@staticmethod
|
||||
def get_arch_from_dll(dll_path):
|
||||
if "x86-64" in subprocess.check_output(["file", dll_path]).decode():
|
||||
if "x86-64" in read_process_output(["file", dll_path]):
|
||||
return "win64"
|
||||
return "win32"
|
||||
|
||||
|
@ -197,7 +194,7 @@ class CabInstaller:
|
|||
Returns:
|
||||
list: Files extracted from the cab file
|
||||
"""
|
||||
subprocess.check_output(["cabextract", "-F", "*%s*" % component, "-d", self.tmpdir, cabfile])
|
||||
execute(["cabextract", "-F", "*%s*" % component, "-d", self.tmpdir, cabfile])
|
||||
return [os.path.join(r, file) for r, d, f in os.walk(self.tmpdir) for file in f]
|
||||
|
||||
def install(self, cabfile, component):
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
"""Gallium Nine helper module"""
|
||||
# Standard Library
|
||||
import os
|
||||
import shutil
|
||||
|
||||
# Lutris Modules
|
||||
from lutris.runners.commands.wine import wineexec
|
||||
from lutris.util import system
|
||||
from lutris.util import linux, system
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.wine.cabinstall import CabInstaller
|
||||
|
||||
|
@ -37,7 +35,7 @@ class NineManager:
|
|||
"""
|
||||
for mesa_file in NineManager.mesa_files:
|
||||
if not any(
|
||||
[os.path.exists(os.path.join(lib, "d3d", mesa_file)) for lib in system.LINUX_SYSTEM.iter_lib_folders()]
|
||||
[os.path.exists(os.path.join(lib, "d3d", mesa_file)) for lib in linux.LINUX_SYSTEM.iter_lib_folders()]
|
||||
):
|
||||
return False
|
||||
|
||||
|
@ -53,7 +51,7 @@ class NineManager:
|
|||
if not any(
|
||||
[
|
||||
os.path.exists(os.path.join(lib, "wine/fakedlls", nine_file))
|
||||
for lib in system.LINUX_SYSTEM.iter_lib_folders()
|
||||
for lib in linux.LINUX_SYSTEM.iter_lib_folders()
|
||||
]
|
||||
):
|
||||
return False
|
||||
|
@ -95,7 +93,7 @@ class NineManager:
|
|||
|
||||
def prepare_prefix(self):
|
||||
for nine_file in NineManager.nine_files:
|
||||
for lib in system.LINUX_SYSTEM.iter_lib_folders():
|
||||
for lib in linux.LINUX_SYSTEM.iter_lib_folders():
|
||||
nine_file_path = os.path.join(lib, "wine/fakedlls", nine_file)
|
||||
|
||||
if (os.path.exists(nine_file_path) and CabInstaller.get_arch_from_dll(nine_file_path) == "win32"):
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
"""Utilities for manipulating Wine"""
|
||||
import os
|
||||
import subprocess
|
||||
from collections import OrderedDict
|
||||
from functools import lru_cache
|
||||
from gettext import gettext as _
|
||||
|
@ -8,13 +7,13 @@ from gettext import gettext as _
|
|||
from lutris import runtime, settings
|
||||
from lutris.gui.dialogs import DontShowAgainDialog, ErrorDialog
|
||||
from lutris.runners.steam import steam
|
||||
from lutris.util import system
|
||||
from lutris.util import linux, system
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.strings import parse_version, version_sort
|
||||
from lutris.util.wine import fsync
|
||||
|
||||
WINE_DIR = os.path.join(settings.RUNNER_DIR, "wine")
|
||||
WINE_DEFAULT_ARCH = "win64" if system.LINUX_SYSTEM.is_64_bit else "win32"
|
||||
WINE_DEFAULT_ARCH = "win64" if linux.LINUX_SYSTEM.is_64_bit else "win32"
|
||||
WINE_PATHS = {
|
||||
"winehq-devel": "/opt/wine-devel/bin/wine",
|
||||
"winehq-staging": "/opt/wine-staging/bin/wine",
|
||||
|
@ -157,7 +156,7 @@ def get_system_wine_versions():
|
|||
"""Return the list of wine versions installed on the system"""
|
||||
versions = []
|
||||
for build in sorted(WINE_PATHS.keys()):
|
||||
version = get_system_wine_version(WINE_PATHS[build])
|
||||
version = get_wine_version(WINE_PATHS[build])
|
||||
if version:
|
||||
versions.append(build)
|
||||
return versions
|
||||
|
@ -230,7 +229,7 @@ def is_esync_limit_set():
|
|||
if ESYNC_LIMIT_CHECK in ("0", "off"):
|
||||
logger.info("fd limit check for esync was manually disabled")
|
||||
return True
|
||||
return system.LINUX_SYSTEM.has_enough_file_descriptors()
|
||||
return linux.LINUX_SYSTEM.has_enough_file_descriptors()
|
||||
|
||||
|
||||
def is_fsync_supported():
|
||||
|
@ -252,9 +251,10 @@ def get_default_version():
|
|||
return
|
||||
|
||||
|
||||
def get_system_wine_version(wine_path="wine"):
|
||||
def get_wine_version(wine_path="wine"):
|
||||
"""Return the version of Wine installed on the system."""
|
||||
if wine_path != "wine" and not system.path_exists(wine_path):
|
||||
logger.warning("Non existent Wine path: %s", wine_path)
|
||||
return
|
||||
if wine_path == "wine" and not system.find_executable("wine"):
|
||||
return
|
||||
|
@ -263,16 +263,13 @@ def get_system_wine_version(wine_path="wine"):
|
|||
if wine_stats.st_size < 2000:
|
||||
# This version is a script, ignore it
|
||||
return
|
||||
try:
|
||||
version = subprocess.check_output([wine_path, "--version"]).decode().strip()
|
||||
except (OSError, subprocess.CalledProcessError) as ex:
|
||||
logger.exception("Error reading wine version for %s: %s", wine_path, ex)
|
||||
version = system.read_process_output([wine_path, "--version"])
|
||||
if not version:
|
||||
logger.error("Error reading wine version for %s", wine_path)
|
||||
return
|
||||
else:
|
||||
if version.startswith("wine-"):
|
||||
version = version[5:]
|
||||
return version
|
||||
return
|
||||
if version.startswith("wine-"):
|
||||
version = version[5:]
|
||||
return version
|
||||
|
||||
|
||||
def is_version_esync(path):
|
||||
|
@ -294,8 +291,8 @@ def is_version_esync(path):
|
|||
for esync_version in esync_compatible_versions:
|
||||
if esync_version in version_prefix or esync_version in version_suffix:
|
||||
return True
|
||||
wine_ver = str(subprocess.check_output([path, "--version"])).lower()
|
||||
return "esync" in wine_ver or "staging" in wine_ver
|
||||
wine_version = get_wine_version(path).lower()
|
||||
return "esync" in wine_version or "staging" in wine_version
|
||||
|
||||
|
||||
def is_version_fsync(path):
|
||||
|
@ -317,11 +314,7 @@ def is_version_fsync(path):
|
|||
for fsync_version in fsync_compatible_versions:
|
||||
if fsync_version in version_prefix or fsync_version in version_suffix:
|
||||
return True
|
||||
|
||||
wine_ver = str(subprocess.check_output([path, "--version"])).lower()
|
||||
if "fsync" in wine_ver:
|
||||
return True
|
||||
return False
|
||||
return "fsync" in get_wine_version(path).lower()
|
||||
|
||||
|
||||
def get_real_executable(windows_executable, working_dir=None):
|
||||
|
|
Loading…
Reference in a new issue