Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package uwsm for openSUSE:Factory checked in at 2026-09-18 22:04:43 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/uwsm (Old) and /work/SRC/openSUSE:Factory/.uwsm.new.383539 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "uwsm" Fri Sep 18 22:04:43 2026 rev:9 rq:1378661 version:0.27.0 Changes: -------- --- /work/SRC/openSUSE:Factory/uwsm/uwsm.changes 2026-08-24 12:17:01.171533522 +0200 +++ /work/SRC/openSUSE:Factory/.uwsm.new.383539/uwsm.changes 2026-09-18 22:05:27.130861695 +0200 @@ -1,0 +2,19 @@ +Thu Sep 17 14:37:51 UTC 2026 - Alexey Kolos <[email protected]> + +- Update to version 0.27.0 +- Breaking changes: + * Remove deprecated UWSM_NO_TWEAKS +- Features: + * Editable export/cleanup lists + * Add UWSM_DEBUG variable to control debug +- Fixes: + * Drop timeout constant, make raise traceable + * Remove error flag in exception in app-daemon + * Pre-check shell syntax before sourcing env scripts, + discard a set of extensions + * Recover app-daemon when client dies mid-handshake + * Reap pipekiller before exec/exit in uwsm-app + * Print Varnames set modification delta + * Cancel PIPE trap when triggered in uwsm-app + +------------------------------------------------------------------- Old: ---- uwsm-0.26.7.obscpio New: ---- uwsm-0.27.0.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ uwsm.spec ++++++ --- /var/tmp/diff_new_pack.c1Navl/_old 2026-09-18 22:05:27.872892793 +0200 +++ /var/tmp/diff_new_pack.c1Navl/_new 2026-09-18 22:05:27.874892877 +0200 @@ -17,7 +17,7 @@ Name: uwsm -Version: 0.26.7 +Version: 0.27.0 Release: 0 Summary: Universal Wayland Session Manager License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.c1Navl/_old 2026-09-18 22:05:27.915894595 +0200 +++ /var/tmp/diff_new_pack.c1Navl/_new 2026-09-18 22:05:27.918894721 +0200 @@ -2,7 +2,7 @@ <service name="obs_scm" mode="manual"> <param name="url">https://github.com/Vladimir-csp/uwsm.git</param> <param name="scm">git</param> - <param name="revision">v0.26.7</param> + <param name="revision">v0.27.0</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.c1Navl/_old 2026-09-18 22:05:27.946895894 +0200 +++ /var/tmp/diff_new_pack.c1Navl/_new 2026-09-18 22:05:27.950896062 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/Vladimir-csp/uwsm.git</param> - <param name="changesrevision">ab5ec16d96ed1f77c3c7ff2e3f07ed42caf23f2d</param></service></servicedata> + <param name="changesrevision">f82dece2cedf308c897513f093f45025fbfdda4f</param></service></servicedata> (No newline at EOF) ++++++ uwsm-0.26.7.obscpio -> uwsm-0.27.0.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.7/README.md new/uwsm-0.27.0/README.md --- old/uwsm-0.26.7/README.md 2026-08-23 17:00:33.000000000 +0200 +++ new/uwsm-0.27.0/README.md 2026-09-15 21:06:40.000000000 +0200 @@ -122,7 +122,7 @@ so those vars are emptied instead (!)) - Lists of variables for export and cleanup are determined algorithmically by: - comparing environment before and after preparation procedures - - boolean operations with predefined lists + - boolean operations with predefined lists (can be configured) - manually exported vars by `uwsm finalize` action </details> @@ -176,7 +176,7 @@ Tries best to shutdown session cleanly via a net of dependencies between units. </summary> -Basic provided unit files (can be transiet if project built with +Basic provided unit files (can be transient if project built with `static-units=disabled`): ``` @@ -196,7 +196,7 @@ ``` Managed generated files (in `${XDG_RUNTIME_DIR}/systemd/user` or -`${XDG_CONFIG_HOME}/systemd/user` depending on `-U` opton): +`${XDG_CONFIG_HOME}/systemd/user` depending on `-U` option): Compositor metadata customization drop-ins: @@ -494,7 +494,7 @@ | Launcher | Via | What | Metadata | | -------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -| vicinae | gui | Vicinae settings > Extentions > Applications > Launch Prefix=`uwsm app --` | no | +| vicinae | gui | Vicinae settings > Extensions > Applications > Launch Prefix=`uwsm app --` | no | | fuzzel | command | `fuzzel "--launch-prefix=uwsm app --"` | env | | fuzzel | config | `launch-prefix=uwsm app --` | env | | albert | env var | `ALBERT_APPLICATIONS_COMMAND_PREFIX`: `uwsm;app;--` | no | @@ -653,6 +653,18 @@ itself (`/etc/profile`, `${HOME}/.profile`). Other shells compatibility with these files may vary. +Environment preloader only exports difference between initial activation +environment state and resulting environment provided by preparation process. +Exported variables are marked for cleanup. There are internal sets of +"always"/"never" overrides, which can be amended by listing names of variables +(whitespace-separated) as `VAR`, `+VAR` (to add) or `-VAR` (to +remove) in variables: + +- `UWSM_ALWAYS_EXPORT_VARNAMES` +- `UWSM_NEVER_EXPORT_VARNAMES` +- `UWSM_ALWAYS_CLEANUP_VARNAMES` +- `UWSM_NEVER_CLEANUP_VARNAMES` + ## Operation ### Syntax and behavior @@ -968,7 +980,7 @@ Environment state at the end of shell code is given back to the main process. `uwsm` is also smart enough to find login session associated with current TTY and set `$XDG_SESSION_ID`, `$XDG_VTNR` if it was not found in the context saved -by `uwsm start`. In this case the presense of `[email protected]` +by `uwsm start`. In this case the presence of `[email protected]` being active is also checked, and an instance pointing to login session leader is launched automatically if none found, as the last best effort at binding to login session lifetime. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.7/debian/changelog new/uwsm-0.27.0/debian/changelog --- old/uwsm-0.26.7/debian/changelog 2026-08-23 17:00:33.000000000 +0200 +++ new/uwsm-0.27.0/debian/changelog 2026-09-15 21:06:40.000000000 +0200 @@ -1,5 +1,5 @@ -uwsm (0.26.7-1~local0) UNRELEASED; urgency=medium +uwsm (0.27.0-1~local0) UNRELEASED; urgency=medium * Upstream build. - -- Vladimir-csp <[email protected]> Sun, 23 Aug 2026 18:00:33 +0300 + -- Vladimir-csp <[email protected]> Mon, 14 Sep 2026 22:03:58 +0300 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.7/man/uwsm.1.scd new/uwsm-0.27.0/man/uwsm.1.scd --- old/uwsm-0.26.7/man/uwsm.1.scd 2026-08-23 17:00:33.000000000 +0200 +++ new/uwsm-0.27.0/man/uwsm.1.scd 2026-09-15 21:06:40.000000000 +0200 @@ -52,7 +52,8 @@ : Environment (shell) to be sourced for the graphical session. Sourced from directories of increasing priority, in each directory common file is sourced first, then suffixed files in the order of items listed in - *XDG_CURRENT_SESSION* var (lowercased). + *XDG_CURRENT_SESSION* var (lowercased). Fragments in *.d/* subdirs are ignored + if suffixed with: *.bak*, *~*, *.disabled*, *.example*, *.sample*, *.broken*. | *uwsm/default-id* : Stores Desktop Entry ID of default compositor. @@ -66,39 +67,66 @@ | : Which rung of systemd/user/ hierarchy to manage generated unit and drop-in files in: $XDG_RUNTIME_DIR or $XDG_CONFIG_HOME. +| +: | *UWSM_TWEAKS* : (boolean value) | : Set to _False_ to remove and not generate tweak drop-ins for other software. +| +: | *UWSM_FINALIZE_VARNAMES* : (whitespace-separated names of env vars) | : Additional variables for "*uwsm finalize*". +| +: | *UWSM_WAIT_VARNAMES* : (whitespace-separated names of env vars) | : Variables to wait for in activation environment before proceeding to graphical session (in addition to *WAYLAND_DISPLAY*). +| +: | *UWSM_WAIT_VARNAMES_TIMEOUT* : (int value) | : Seconds to wait for variables to appear in activation environment. Essentially, startup timeout (default: 10). +| +: | *UWSM_WAIT_VARNAMES_SETTLETIME* : (float value) | : Seconds to pause after all expected vars found in activation environment (default: 0.2). +| +: +| *UWSM_ALWAYS_EXPORT_VARNAMES*, + *UWSM_NEVER_EXPORT_VARNAMES*, + *UWSM_ALWAYS_CLEANUP_VARNAMES*, + *UWSM_NEVER_CLEANUP_VARNAMES* +: (whitespace-separated names of env vars) +| +: Modify sets of variable names UWSM uses to filter export and cleanup. + Plain or *+*-prefixed names are added, *-*-prefixed names are removed. + "never" lists always win. +| +: | *UWSM_APP_UNIT_TYPE* : (*scope*|*service*) | : Default unit type for launching apps (default: *scope*). +| +: | *UWSM_SILENT_START* : (int or boolean value) | : _True_ or *1* to inhibit stdout messages from "*uwsm start*". *2* to also inhibit warnings. -| *DEBUG* +| +: +| *UWSM_DEBUG*, *DEBUG* : (int or boolean value) | : _True_ or positive number to dump debug info to stderr. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.7/scripts/uwsm-app.sh new/uwsm-0.27.0/scripts/uwsm-app.sh --- old/uwsm-0.26.7/scripts/uwsm-app.sh 2026-08-23 17:00:33.000000000 +0200 +++ new/uwsm-0.27.0/scripts/uwsm-app.sh 2026-09-15 21:06:40.000000000 +0200 @@ -99,7 +99,7 @@ KILLER_PID=$! # trap to errexit on SIGPIPE -trap 'error "Timed out waiting for pipes!" 141' PIPE +trap 'trap - PIPE; error "Timed out waiting for pipes!" 141' PIPE # restart server if pipes are missing or not pipes if [ ! -p "$PIPE_IN" ] || [ ! -p "$PIPE_OUT" ]; then @@ -115,7 +115,7 @@ fi # update message for errexit on SIGPIPE -trap 'error "Timed out trying to write to ${PIPE_IN}!" 141' PIPE +trap 'trap - PIPE; error "Timed out trying to write to ${PIPE_IN}!" 141' PIPE # prepend arguments if launched as a terminal case "${0##*/}" in @@ -173,7 +173,7 @@ fi # update message -trap 'error "Timed out trying to read from ${PIPE_OUT}!" 141' PIPE +trap 'trap - PIPE; error "Timed out trying to read from ${PIPE_OUT}!" 141' PIPE # read from output pipe CMDLINE= @@ -185,6 +185,9 @@ # kill timeout killer process and its sleep process kill "$KILLER_PID" +# Reap it before exec/exit, otherwise the launched long-running app +# inherits it as a zombie child. +wait "$KILLER_PID" 2>/dev/null || true case "$CMDLINE" in pong) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.7/scripts/wait-tray.sh new/uwsm-0.27.0/scripts/wait-tray.sh --- old/uwsm-0.26.7/scripts/wait-tray.sh 2026-08-23 17:00:33.000000000 +0200 +++ new/uwsm-0.27.0/scripts/wait-tray.sh 2026-09-15 21:06:40.000000000 +0200 @@ -45,7 +45,7 @@ } check_tray() { - # return 0 if any of tray serivces is active + # return 0 if any of tray services is active for service in $TRAY_NAMES; do if busctl --user status "$service" --no-pager --no-legend > /dev/null 2>&1; then return 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.7/uwsm/main.py new/uwsm-0.27.0/uwsm/main.py --- old/uwsm-0.26.7/uwsm/main.py 2026-08-23 17:00:33.000000000 +0200 +++ new/uwsm-0.27.0/uwsm/main.py 2026-09-15 21:06:40.000000000 +0200 @@ -26,6 +26,7 @@ import time import signal import stat +import errno from typing import List, Callable from urllib import parse as urlparse from select import select @@ -149,6 +150,8 @@ "XDG_SESSION_PATH", "XDG_VTNR", } + always_unset = {"DISPLAY", "WAYLAND_DISPLAY"} | session_specific + always_export = { "PATH", "XDG_CURRENT_DESKTOP", @@ -168,7 +171,6 @@ "TERM_SESSION_TYPE", "NOTIFY_SOCKET", } | session_specific - always_unset = {"DISPLAY", "WAYLAND_DISPLAY"} | session_specific always_cleanup = { "DISPLAY", "LANG", @@ -290,6 +292,43 @@ print_debug(f"Path {self.path} OK") +def update_varnames_sets(env: dict = None): + """ + Modifies Varnames.{always,never}_{export,cleanup} sets according to UWSM_*_VARNAMES vars: + Space-separated lists, plain or '+'-prefixed names are added, '-'-prefixed are removed. + """ + + if env is None: + env = os.environ + + for mod_set_name in ( + "always_export", + "never_export", + "always_cleanup", + "never_cleanup", + ): + + v_raw = env.get(f"UWSM_{mod_set_name.upper()}_VARNAMES", "").split() + v_add = filter_varnames( + {v.removeprefix("+") for v in v_raw if not v.startswith("-")} + ) + v_rem = filter_varnames( + {v.removeprefix("-") for v in v_raw if v.startswith("-")} + ) + + mod_set = getattr(Varnames, mod_set_name) + + delta = ", ".join(sorted(v_add.difference(mod_set))) + if delta: + print_normal(f"Adding to {mod_set_name} set: {delta}") + mod_set.update(v_add) + + delta = ", ".join(sorted(v_rem.intersection(mod_set))) + if delta: + print_normal(f"Removing from {mod_set_name} set: {delta}") + mod_set.difference_update(v_rem) + + def entry_expand_str(value: str): """ Expands escape sequences \\s, \\n, \\t, \\r, and \\\\ for a string from desktop entry according to @@ -1808,10 +1847,8 @@ choices=("run", "home"), help=f"Generated unit/drop-in files destination (default: %(default)s, {'was' if unit_rung_preset else 'can be'} preset by UWSM_UNIT_RUNG env var).", ) - # TODO: remove _NO_ in future release tweaks_preset = False t_raw = os.getenv("UWSM_TWEAKS", None) - nt_raw = os.getenv("UWSM_NO_TWEAKS", None) if t_raw is not None: try: tweaks_default = str2bool_plus(t_raw) @@ -1821,22 +1858,9 @@ f'Expected boolean value from UWSM_TWEAKS, got "{t_raw}" ignored, set to True.' ) tweaks_default = True - elif nt_raw is not None: - try: - tweaks_default = not str2bool_plus(nt_raw) - tweaks_preset = True - except ValueError: - print_warning( - f'Expected boolean value from UWSM_NO_TWEAKS, got "{nt_raw}" ignored, set to False.' - ) - tweaks_default = True else: tweaks_default = True - if nt_raw is not None: - print_warning( - "UWSM_NO_TWEAKS is deprecated and being replaced by UWSM_TWEAKS." - ) - del t_raw, nt_raw + del t_raw parsers["start_tw"] = parsers["start"].add_mutually_exclusive_group() parsers["start_tw"].add_argument( "-t", @@ -2259,7 +2283,7 @@ help="Waits for WAYLAND_DISPLAY and optionally other vars (for wayland-session-waitenv.service, [email protected]).", description=( "Exits successfully when WAYLAND_DISPLAY (and optionally other vars) appear in systemd user manager activation environment. " - "Optinal vars are read from command line and whitespace-separated UWSM_WAIT_VARNAMES var." + "Optional vars are read from command line and whitespace-separated UWSM_WAIT_VARNAMES var." ), epilog="Used in wayland-session-waitenv.service to delay activation of [email protected], graphical-session.target.", ) @@ -2321,6 +2345,8 @@ "env_cleanup.list", ) + update_varnames_sets() + varnames = set(filter_varnames(varnames)) - Varnames.never_cleanup # do not bother with useless cleanups @@ -2835,6 +2861,9 @@ print_debug("env_post", env_post) print_debug("set_env", set_env) + # update Varnames sets according to vars in env_post + update_varnames_sets(env_post) + # add "always_export" vars from env_post to set_env for var in sorted( Varnames.always_export - Varnames.never_export - Varnames.always_unset @@ -2883,6 +2912,8 @@ Removes found cleanup files """ + update_varnames_sets() + print_normal("Cleaning up...") bus_session = DbusInteractions("session") print_debug("bus_session initial", bus_session) @@ -3803,8 +3834,8 @@ signal.signal(signal.SIGTERM, trap_stopper) signal.signal(signal.SIGHUP, trap_stopper) - # argparse exit_on_error is faulty https://github.com/python/cpython/issues/103498 - # crudely work around it + # argparse exit_on_error was faulty https://github.com/python/cpython/issues/103498 + # crudely work around it. TODO: remove this in 2027-ish error_flag_path = os.path.join( BaseDirectory.get_runtime_dir(strict=True), "uwsm", "app_daemon_error" ) @@ -3813,8 +3844,18 @@ "Takes original args_in (list), and final args_out (str), writes to output fifo" print_normal(f"received: {shlex.join(args_in)}\nsent: {args_out}") fifo_out_path = create_fifo("uwsm-app-daemon-out") - with open(fifo_out_path, "w", encoding="UTF-8") as fifo_out: - fifo_out.write(f"{args_out}\n") + try: + fd = open_fifo_write(fifo_out_path) + except TimeoutError: + print_warning( + f"Timed out waiting for client to read {fifo_out_path}, dropping reply" + ) + return + with os.fdopen(fd, "w", encoding="UTF-8") as fifo_out: + try: + fifo_out.write(f"{args_out}\n") + except BrokenPipeError: + print_warning(f"Client closed {fifo_out_path} before reply was written") while True: # create both pipes right away and make sure they always exist @@ -3876,6 +3917,9 @@ args_in, f"error {shlex.quote('Invalid arguments: ' + str(caught_exception))} 2", ) + # remove error flag file since we are still alive + print_debug(f"removing {error_flag_path}") + os.remove(error_flag_path) continue # remove error flag file since args are parsed successfully @@ -3918,6 +3962,26 @@ continue +def open_fifo_write(path, timeout=10): + """Open FIFO for writing, waiting up to timeout seconds for a reader. + + Blocking open() waits forever. A client that dies after writing IN + would leave the daemon stuck here and block all later launches. + """ + deadline = time.monotonic() + timeout + while True: + try: + fd = os.open(path, os.O_WRONLY | os.O_NONBLOCK) + os.set_blocking(fd, True) + return fd + except OSError as err: + if err.errno != errno.ENXIO: + raise + if time.monotonic() >= deadline: + raise TimeoutError(path) from err + time.sleep(0.05) + + def create_fifo(path): "Ensures path in runtime dir is fifo, returns full path" fifo_path = os.path.join(BaseDirectory.get_runtime_dir(strict=True), path) @@ -4852,7 +4916,7 @@ # Upon receiving SIGTERM, SIGHUP, SIGINT a stopping systemctl will be # forked to stop compositor will be cleanly. # Both systemctl invocations are started with protection from - # SIGTERM/SIGHUP barrage occuring on login session termination. + # SIGTERM/SIGHUP barrage occurring on login session termination. sh_path = which(SH_BIN) if not sh_path: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.7/uwsm/misc.py new/uwsm-0.27.0/uwsm/misc.py --- old/uwsm-0.26.7/uwsm/misc.py 2026-08-23 17:00:33.000000000 +0200 +++ new/uwsm-0.27.0/uwsm/misc.py 2026-09-15 21:06:40.000000000 +0200 @@ -33,9 +33,9 @@ class DebugFlag: - "Checks for DEBUG env value and holds 'debug' boolean, 'warning' string" + "Checks for UWSM_DEBUG, DEBUG env values and holds 'debug' boolean, 'warning' string" - debug_raw = os.getenv("DEBUG", "0") + debug_raw = os.getenv("UWSM_DEBUG", os.getenv("DEBUG", "0")) warning = None try: debug = str2bool_plus(debug_raw) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.7/uwsm-libexec/prepare-env.sh new/uwsm-0.27.0/uwsm-libexec/prepare-env.sh --- old/uwsm-0.26.7/uwsm-libexec/prepare-env.sh 2026-08-23 17:00:33.000000000 +0200 +++ new/uwsm-0.27.0/uwsm-libexec/prepare-env.sh 2026-09-15 21:06:40.000000000 +0200 @@ -22,14 +22,22 @@ } source_file() { - # sources file if exists, with messaging + # sources file if exists, readable, and has proper syntax, with messaging if [ -f "${1}" ]; then - if [ -r "${1}" ]; then - printf '%s\n' "Loading environment from \"${1}\"." - . "${1}" - else - "Environment file ${1} is not readable" >&2 + if [ ! -r "${1}" ]; then + printf '%s\n' "Environment file ${1} is not readable" >&2 + return fi + if [ ! -f "${1}" ]; then + printf '%s\n' "Not a file: ${1}" >&2 + return + fi + if ! sh -n "${1}"; then + # sh would print to stderr + return + fi + printf '%s\n' "Sourcing environment file \"${1}\"." + . "${1}" fi } @@ -37,11 +45,12 @@ # applies source_file to every file in dir if [ -d "${1}" ]; then # process in standard order and visibility given by ls - while IFS='' read -r __env_file__; do - source_file "${1}/${__env_file__}" - done <<- EOF - $(ls "${1}") - EOF + for __env_file__ in "${1}/"*; do + case "${__env_file__}" in + *.bak | *~ | *.disabled | *.example | *.sample | *.broken) continue ;; + esac + source_file "${__env_file__}" + done unset __env_file__ fi } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uwsm-0.26.7/version.sh new/uwsm-0.27.0/version.sh --- old/uwsm-0.26.7/version.sh 2026-08-23 17:00:33.000000000 +0200 +++ new/uwsm-0.27.0/version.sh 2026-09-15 21:06:40.000000000 +0200 @@ -4,7 +4,7 @@ # or prints back UWSM_VERSION env if set, # or prints a fallback version if not in git repo. -VERSION=0.26.7 +VERSION=0.27.0 set -e ++++++ uwsm.obsinfo ++++++ --- /var/tmp/diff_new_pack.c1Navl/_old 2026-09-18 22:05:28.119903145 +0200 +++ /var/tmp/diff_new_pack.c1Navl/_new 2026-09-18 22:05:28.122903271 +0200 @@ -1,5 +1,5 @@ name: uwsm -version: 0.26.7 -mtime: 1787497233 -commit: ab5ec16d96ed1f77c3c7ff2e3f07ed42caf23f2d +version: 0.27.0 +mtime: 1789499200 +commit: f82dece2cedf308c897513f093f45025fbfdda4f
