From 05108205946fdbe4213eac1961b2aceda47ef8e7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 30 Sep 2019 12:22:14 +0200 Subject: [PATCH 1/7] [displaymanager] Document what the list of DE's is for --- src/modules/displaymanager/main.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index fdb802fef..8f68803ea 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -96,6 +96,19 @@ class DesktopEnvironment: self.find_tryexec(root_mount_point, desktop_file) is not None) +# This is the list of desktop environments that Calamares looks +# for; if no default environment is **explicitly** configured +# in the `displaymanager.conf` then the first one from this list +# that is found, is used. +# +# Each DE has a sample executable to look for, and a .desktop filename. +# If the executable exists, the DE is assumed to be installed +# and to use the given .desktop filename. +# +# If the .desktop file exists and contains a TryExec line and that +# TryExec executable exists (searched in /bin, /usr/bin, /sbin and +# /usr/local/bin) then the DE is assumed to be installed +# and to use that .desktop filename. desktop_environments = [ DesktopEnvironment('/usr/bin/startplasma-x11', 'plasma'), # KDE Plasma 5.17+ DesktopEnvironment('/usr/bin/startkde', 'plasma'), # KDE Plasma 5 From fb07757aaba47674542b7e7f8741ef3125d477ed Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 30 Sep 2019 12:33:42 +0200 Subject: [PATCH 2/7] [displaymanager] Document *defaultDesktopEnvironment* - while the keys are mandatory, their meaning is entirely optional. --- src/modules/displaymanager/displaymanager.conf | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/modules/displaymanager/displaymanager.conf b/src/modules/displaymanager/displaymanager.conf index 8f8e9c704..366e074ab 100644 --- a/src/modules/displaymanager/displaymanager.conf +++ b/src/modules/displaymanager/displaymanager.conf @@ -13,7 +13,21 @@ displaymanagers: - lxdm - kdm -#Enable the following settings to force a desktop environment in your displaymanager configuration file: +# Enable the following settings to force a desktop environment +# in your displaymanager configuration file. This will attempt +# to configure the given DE (without checking if it is installed). +# The DM configuration for each potential DM may **or may not** +# support configuring a default DE, so the keys are mandatory +# but their interpretation is up to the DM configuration. +# +# Subkeys of *defaultDesktopEnvironment* are: +# - *executable* a full path to an executable (manda) +# - *desktopFile* a .desktop filename (optional) +# +# If this is **not** set, then Calamares will look for installed +# DE's and pick the first one it finds. +# + #defaultDesktopEnvironment: # executable: "startkde" # desktopFile: "plasma" From a3666cabe0e76e9fdc69ec9101d72fdb91761c89 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 30 Sep 2019 12:41:05 +0200 Subject: [PATCH 3/7] [displaymanager] Fix naming - Having a global and a class-local function with the same name that do very different things is confusing. --- src/modules/displaymanager/displaymanager.conf | 6 +++--- src/modules/displaymanager/main.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/displaymanager/displaymanager.conf b/src/modules/displaymanager/displaymanager.conf index 366e074ab..fe1d2bc14 100644 --- a/src/modules/displaymanager/displaymanager.conf +++ b/src/modules/displaymanager/displaymanager.conf @@ -20,9 +20,9 @@ displaymanagers: # support configuring a default DE, so the keys are mandatory # but their interpretation is up to the DM configuration. # -# Subkeys of *defaultDesktopEnvironment* are: -# - *executable* a full path to an executable (manda) -# - *desktopFile* a .desktop filename (optional) +# Subkeys of *defaultDesktopEnvironment* are (all mandatory): +# - *executable* a full path to an executable +# - *desktopFile* a .desktop filename # # If this is **not** set, then Calamares will look for installed # DE's and pick the first one it finds. diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 8f68803ea..d08b1f049 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -83,7 +83,7 @@ class DesktopEnvironment: return candidate return None - def find_desktop_environment(self, root_mount_point): + def is_installed(self, root_mount_point): """ Check if this environment is installed in the target system at @p root_mount_point. @@ -144,7 +144,7 @@ def find_desktop_environment(root_mount_point): """ libcalamares.utils.debug("Using rootMountPoint {!r}".format(root_mount_point)) for desktop_environment in desktop_environments: - if desktop_environment.find_desktop_environment(root_mount_point): + if desktop_environment.is_installed(root_mount_point): libcalamares.utils.debug(".. selected DE {!s}".format(desktop_environment.desktop_file)) return desktop_environment return None From fe339527336b7067e5c0a107f4350a844b095945 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 30 Sep 2019 12:58:56 +0200 Subject: [PATCH 4/7] [displaymanager] Document the internal functions for DE finding - rename find_* to _search_* to make clear they're internal. --- src/modules/displaymanager/main.py | 43 +++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index d08b1f049..abbd6b7e8 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -51,31 +51,59 @@ class DesktopEnvironment: self.executable = exec self.desktop_file = desktop - def find_executable(self, root_mount_point, command): - if command.startswith("/"): + def _search_executable(self, root_mount_point, pathname): + """ + Search for @p pathname within @p root_mount_point . + If the pathname is absolute, just check there inside + the target, otherwise earch in a sort-of-sensible $PATH. + + Returns the full (including @p root_mount_point) path + to that executable, or None. + """ + if pathname.startswith("/"): path = [""] else: path = ["/bin/", "/usr/bin/", "/sbin/", "/usr/local/bin/"] for p in path: - absolute_path = "{!s}{!s}{!s}".format(root_mount_point, p, command) + absolute_path = "{!s}{!s}{!s}".format(root_mount_point, p, pathname) if os.path.exists(absolute_path): return absolute_path return None - def find_tryexec(self, root_mount_point, absolute_desktop_file): + def _search_tryexec(self, root_mount_point, absolute_desktop_file): + """ + Check @p absolute_desktop_file for a TryExec line and, if that is + found, search for the command (executable pathname) within + @p root_mount_point. The .desktop file must live within the + target root. + + Returns the full (including @p root_mount_point) for the executable + from TryExec, or None. + """ assert absolute_desktop_file.startswith(root_mount_point) with open(absolute_desktop_file, "r") as f: for tryexec_line in [x for x in f.readlines() if x.startswith("TryExec")]: try: key, value = tryexec_line.split("=") if key.strip() == "TryExec": - return self.find_executable(root_mount_point, value.strip()) + return self._search_executable(root_mount_point, value.strip()) except: pass return None + def find_executable(self, root_mount_point): + """ + Returns the full path of the configured executable within @p root_mount_point, + or None if it isn't found. May search in a semi-sensible $PATH. + """ + return self._search_executable(root_mount_point, self.executable) + def find_desktop_file(self, root_mount_point): + """ + Returns the full path of the .desktop file within @p root_mount_point, + or None if it isn't found. Searches both X11 and Wayland sessions. + """ x11_sessions = "{!s}/usr/share/xsessions/{!s}.desktop".format(root_mount_point, self.desktop_file) wayland_sessions = "{!s}/usr/share/wayland-sessions/{!s}.desktop".format(root_mount_point, self.desktop_file) for candidate in (x11_sessions, wayland_sessions): @@ -92,8 +120,9 @@ class DesktopEnvironment: if desktop_file is None: return False - return (self.find_executable(root_mount_point, self.executable) is not None or - self.find_tryexec(root_mount_point, desktop_file) is not None) + return (self.find_executable(root_mount_point) is not None or + self._search_tryexec(root_mount_point, desktop_file) is not None) + # This is the list of desktop environments that Calamares looks From 290a0698d89df6bb5258325ab61a4f1911cfdce4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 30 Sep 2019 14:47:05 +0200 Subject: [PATCH 5/7] [displaymanager] Add DE.find() which believes .desktop files - for a DE entry which has a bad executable setting, update the entry from the .desktop file using TryExec. This assumes that the TryExec command is actually something you might want to run. --- src/modules/displaymanager/main.py | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index abbd6b7e8..313c679fa 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -123,6 +123,41 @@ class DesktopEnvironment: return (self.find_executable(root_mount_point) is not None or self._search_tryexec(root_mount_point, desktop_file) is not None) + def find(self, root_mount_point): + """ + Find thie DE in the target system at @p root_mount_point. + This can update the *executable* configuration value if + the configured executable isn't found but the TryExec line + from the .desktop file is. + + The .desktop file is mandatory for a DE. + + Returns True if the DE is installed. + """ + desktop_file = self.find_desktop_file(root_mount_point) + if desktop_file is None: + return False + + executable_file = self.find_executable(root_mount_point) + if executable_file is not None: + # .desktop found and executable as well. + return True + + executable_file = self._search_tryexec(root_mount_point, desktop_file) + if executable_file is not None: + # Found from the .desktop file, so update own executable config + if root_mount_point and executable_file.startswith(root_mount_point): + executable_file = executable_file[len(root_mount_point):] + if not executable_file: + # Somehow chopped down to nothing + return False + + if executable_file[0] != "/": + executable_file = "/" + executable_file + self.executable = executable_file + return True + # This is to double-check + return self.is_installed(root_mount_point) # This is the list of desktop environments that Calamares looks From 1beadee2a75b20b2719e2e62afc29d51074eb053 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 30 Sep 2019 14:53:05 +0200 Subject: [PATCH 6/7] [displaymanager] Believe the .desktop file - if a default DE is configured but the executable doesn't exist, believe the .desktop file. Then use that, and warn if the whole thing can not be found. --- src/modules/displaymanager/main.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 313c679fa..ca42e6204 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -123,7 +123,7 @@ class DesktopEnvironment: return (self.find_executable(root_mount_point) is not None or self._search_tryexec(root_mount_point, desktop_file) is not None) - def find(self, root_mount_point): + def update_from_desktop_file(self, root_mount_point): """ Find thie DE in the target system at @p root_mount_point. This can update the *executable* configuration value if @@ -924,6 +924,11 @@ def run(): default_desktop_environment = DesktopEnvironment( entry["executable"], entry["desktopFile"] ) + # Adjust if executable is bad, but desktopFile isn't. + if not default_desktop_environment.update_from_desktop_file(root_mount_point): + libcalamares.utils.warning( + "The configured default desktop environment, {!s}, " + "can not be found.".format(default_desktop_environment.desktop_file)) else: default_desktop_environment = find_desktop_environment( root_mount_point From 7ffe25fca0ee4dacf34dba4f720cdb531fddb4aa Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 30 Sep 2019 15:40:44 +0200 Subject: [PATCH 7/7] [displaymanager] Document that TryExec can supplant executable --- src/modules/displaymanager/displaymanager.conf | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/modules/displaymanager/displaymanager.conf b/src/modules/displaymanager/displaymanager.conf index fe1d2bc14..c3e0e1160 100644 --- a/src/modules/displaymanager/displaymanager.conf +++ b/src/modules/displaymanager/displaymanager.conf @@ -25,7 +25,11 @@ displaymanagers: # - *desktopFile* a .desktop filename # # If this is **not** set, then Calamares will look for installed -# DE's and pick the first one it finds. +# DE's and pick the first one it finds that is actually installed. +# +# If this **is** set, and the *executable* key doesn't point to +# an installed file, then the .desktop file's TryExec key is +# used instead. # #defaultDesktopEnvironment: