Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package xdg-terminal-exec for openSUSE:Factory checked in at 2023-10-08 12:18:46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/xdg-terminal-exec (Old) and /work/SRC/openSUSE:Factory/.xdg-terminal-exec.new.28202 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "xdg-terminal-exec" Sun Oct 8 12:18:46 2023 rev:2 rq:1116205 version:20231003+git.e5c20d0 Changes: -------- --- /work/SRC/openSUSE:Factory/xdg-terminal-exec/xdg-terminal-exec.changes 2023-08-01 14:15:42.339549597 +0200 +++ /work/SRC/openSUSE:Factory/.xdg-terminal-exec.new.28202/xdg-terminal-exec.changes 2023-10-08 12:22:17.062712916 +0200 @@ -1,0 +2,23 @@ +Sat Oct 07 12:58:52 UTC 2023 - mc...@cepl.eu + +- Update to version 20231003+git.e5c20d0: + * test/tests.bats: Add a TODO for additional tests + * Add myself as a contributor + * xdg-terminal-exec: Remove now unused code + * xdg-terminal-exec: Move entry ID loops out to main + * xdg-terminal-exec: Use globals set by `find*entry` + * xdg-terminal-exec: Parse config file using `case` + * xdg-terminal-exec: Check entries using `case` + * xdg-terminal-exec: Parse entry file using `case` + * xdg-terminal-exec: set `errexit` and `nounset` + * README: Small fixes and changes + * default debug value (fixes #24) + * xdg-terminal-exec: Remove empty variable assignments + * xdg-terminal-exec: Normalise printing + * xdg-terminal-exec: Normalise string quotes + * xdg-terminal-exec: Indent here documents + * tests: Make `tests.bats` executable + * xdg-terminal-exec: run `shfmt` + * xdg-terminal-exec: don't use `find -printf` + +------------------------------------------------------------------- Old: ---- xdg-terminal-exec-20230731+git.6426085.tar.xz New: ---- xdg-terminal-exec-20231003+git.e5c20d0.obscpio xdg-terminal-exec-20231003+git.e5c20d0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ xdg-terminal-exec.spec ++++++ --- /var/tmp/diff_new_pack.0fRt5T/_old 2023-10-08 12:22:18.234755056 +0200 +++ /var/tmp/diff_new_pack.0fRt5T/_new 2023-10-08 12:22:18.234755056 +0200 @@ -17,7 +17,7 @@ Name: xdg-terminal-exec -Version: 20230731+git.6426085 +Version: 20231003+git.e5c20d0 Release: 0 Summary: XDG terminal execution utility and default terminal specification # FIXME: Select a correct license from https://github.com/openSUSE/spec-cleaner#spdx-licenses ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.0fRt5T/_old 2023-10-08 12:22:18.278756637 +0200 +++ /var/tmp/diff_new_pack.0fRt5T/_new 2023-10-08 12:22:18.282756781 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/Vladimir-csp/xdg-terminal-exec</param> - <param name="changesrevision">6426085370a3adafea933d53c123d813d7c7ab44</param></service></servicedata> + <param name="changesrevision">e5c20d043bd34bde671a4344e2147da9360f6fc2</param></service></servicedata> (No newline at EOF) ++++++ xdg-terminal-exec-20230731+git.6426085.tar.xz -> xdg-terminal-exec-20231003+git.e5c20d0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-terminal-exec-20230731+git.6426085/README.md new/xdg-terminal-exec-20231003+git.e5c20d0/README.md --- old/xdg-terminal-exec-20230731+git.6426085/README.md 2023-07-31 12:20:18.000000000 +0200 +++ new/xdg-terminal-exec-20231003+git.e5c20d0/README.md 2023-10-03 21:12:13.000000000 +0200 @@ -3,10 +3,10 @@ The configuration spec is crafted in image of [mime-apps-spec](https://specifications.freedesktop.org/mime-apps-spec/latest/ar01s02.html) using different names in similar structure, governed by [basedir-spec](https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html). -Terminal emulators with their exec arguments are be described by desktop entries placed in directories named `xdg-terminals` provided via XDG_DATA hierarchy. +Terminal emulators with their exec arguments are described by desktop entries placed in directories named `xdg-terminals` provided via XDG_DATA hierarchy. -Preferred terminal is configured in config files named `xdg-terminals.list` provided via XDG_CONFIG hierarchy. -Format for config file is a a simple newline-separated list of desktop entries. #Comments, dangling whitespaces are trimmed. +Preferred terminals are configured in config files named `xdg-terminals.list` provided via XDG_CONFIG hierarchy. +Format for config file is a a simple newline-separated list of desktop entries. #Comments and dangling whitespaces are trimmed. Default paths are resolved into: @@ -22,7 +22,8 @@ - `/usr/local/share/xdg-terminals` - `/usr/share/xdg-terminals` -where `$desktop` is lowercase list of colon-separated names of current DE. +Where `$desktop` is a lowercased string derived from `$XDG_CURRENT_DESKTOP`. +If `$XDG_CURRENT_DESKTOP` is set then it contains a colon-separated list of names for the current DE. ## Priority of selecting entry: - Read configs throughout XDG_CONFIG hierarchy. @@ -32,7 +33,9 @@ - If all of the above fails, `xterm` and `-e` are used. ## Desktop entry for terminal -For defining terminals usual desktop entries may be used. The only addition is the key `X-ExecArg` which defines the exection argument for the terminal emulator. It defaults to `-e` if unset, but may be specifically set to an empty string. With this behavior stock entries for terminals that use `-e` as execution argument may be used unaltered. +When defining terminals usual desktop entries may be used. The only addition is the key `X-ExecArg` which defines the execution argument for the terminal emulator. +It defaults to `-e` if unset, but may be specifically set to an empty string. +With this behavior stock entries for terminals that use `-e` as execution argument may be used unaltered. ## syntax ``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-terminal-exec-20230731+git.6426085/test/tests.bats new/xdg-terminal-exec-20231003+git.e5c20d0/test/tests.bats --- old/xdg-terminal-exec-20230731+git.6426085/test/tests.bats 2023-07-31 12:20:18.000000000 +0200 +++ new/xdg-terminal-exec-20231003+git.e5c20d0/test/tests.bats 2023-10-03 21:12:13.000000000 +0200 @@ -1,5 +1,8 @@ #!/usr/bin/env bats +# TODO: Add following tests: +# Ensure that duplicates are removed + setup() { : "${XTE:=$BATS_TEST_DIRNAME/../xdg-terminal-exec}" unset XDG_CURRENT_DESKTOP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-terminal-exec-20230731+git.6426085/xdg-terminal-exec new/xdg-terminal-exec-20231003+git.e5c20d0/xdg-terminal-exec --- old/xdg-terminal-exec-20230731+git.6426085/xdg-terminal-exec 2023-07-31 12:20:18.000000000 +0200 +++ new/xdg-terminal-exec-20231003+git.e5c20d0/xdg-terminal-exec 2023-10-03 21:12:13.000000000 +0200 @@ -10,336 +10,263 @@ # (at your option) any later version. See <http://www.gnu.org/licenses/>. # # Contributors: -# Roman Chistokhodov https://github.com/FreeSlave/ +# Roman Chistokhodov https://github.com/FreeSlave/ +# fluvf https://github.com/fluvf -# some transitional variables for desktop entries used here: -# ENTRY_FILE - desktop entry path relative to it's data directory -# ENTRY_ID - ENTRY_FILE with '/' swapped for '-' (see section E of Desktop Entry Spec) -# ENTRY_PATH - full path of specific desktop entry file - - -DATA_PREFIX_DIR=xdg-terminals -CONFIG_NAME=xdg-terminals.list - -DATA_HIERARCHY="${XDG_DATA_HOME:-$HOME/.local/share}:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}" -CONF_HIERARCHY="${XDG_CONFIG_HOME:-$HOME/.config}:${XDG_CONFIG_DIRS:-/etc/xdg:/usr/etc/xdg}" - -DATA='' -BLACKLIST='' -EXEC='' -EXECARG='' +# Treat non-zero exit status from simple commands as an error +# Treat unset variables as errors when performing parameter expansion +set -eu +# Backup original IFS value +# It is assumed that $OIFS contains the default IFS value OIFS="$IFS" +# Newline, utility variable used throughout the script +N=' +' -debug(){ - [ "$DEBUG" = "1" ] && printf "%s\n" "$1" >&2 -} - -trim_spaces(){ - TRIMVAR="$*" - TRIMVAR="${TRIMVAR#"${TRIMVAR%%[![:space:]]*}"}" - TRIMVAR="${TRIMVAR%"${TRIMVAR##*[![:space:]]}"}" - printf "%s" "$TRIMVAR" -} - -trim_comment(){ - TRIMVAR="$*" - TRIMVAR="${TRIMVAR%%#*}" - printf "%s" "$TRIMVAR" -} - -generate_config_list(){ - # Generate list of possible config files for current DE - DESKTOPS_LC="$(printf "%s" "$XDG_CURRENT_DESKTOP" | tr '[:upper:]' '[:lower:]')" - IFS=":" - debug "lower case desktops are: \"${DESKTOPS_LC}\"" - for CONFIG_DIR in $CONF_HIERARCHY - do - for DESKTOP in $DESKTOPS_LC - do - printf "%s\n" "${CONFIG_DIR}/${DESKTOP}${DESKTOP:+-}${CONFIG_NAME}" - done - printf "%s\n" "${CONFIG_DIR}/${CONFIG_NAME}" - done | uniq - IFS="$OIFS" -} - -find_preferred_entry(){ - # Read entries listed in config files until a valid one is found - ENTRY_ID= - CONFIG_LIST= - - CONFIG_LIST="$(generate_config_list)" - - debug "finding preferred entry in configs" - - while read -r CONFIG_FILE - do - debug "looking for config \"${CONFIG_FILE}\"" - if [ -f "${CONFIG_FILE}" ] - then - debug "reading config \"${CONFIG_FILE}\"" - while read -r LINE - do - debug "parsing line \"$LINE\"" - LINE="$(trim_comment "$LINE")" - LINE="$(trim_spaces "$LINE")" - [ -z "$LINE" ] && continue || ENTRY_ID="$LINE" - debug "retrieved entry ID \"$ENTRY_ID\"" - check_entry_id "$ENTRY_ID" || continue - - debug "finding path for entry ID \"$ENTRY_ID\"" - ENTRY_PATH="$(find_entry_path "$ENTRY_ID")" - if [ -n "$ENTRY_PATH" ] && check_entry_path "$ENTRY_PATH" - then - debug "file at path \"$ENTRY_PATH\" checks out" - printf "%s" "$ENTRY_PATH" - return 0 - else - debug "entry ID \"$ENTRY_ID\" failed check at path \"$ENTRY_PATH\", blacklisting" - BLACKLIST="${BLACKLIST}${BLACKLIST:+;}$ENTRY_ID" - continue - fi - done < "${CONFIG_FILE}" - fi - done << EOF -$CONFIG_LIST -EOF -} - -find_any_entry(){ - # Read entries in data dirs until a valid one is found - ENTRY_ID= - ENTRY_PATH= - ENTRY_FILES= - debug "looking for first available entry in data hierarchy" - IFS=":" - for DATA_DIR in $DATA_HIERARCHY - do - IFS="$OIFS" - if [ -d "${DATA_DIR}/${DATA_PREFIX_DIR}" ] - then - debug "searching in \"${DATA_DIR}/${DATA_PREFIX_DIR}\"" - ENTRY_FILES="$(find -L "${DATA_DIR}/${DATA_PREFIX_DIR}" -type f -iname "*.desktop" -printf "%P\n")" - while read -r ENTRY_FILE - do - [ -z "$ENTRY_FILE" ] && continue - ENTRY_ID="$(printf "%s" "$ENTRY_FILE" | tr '/' '-')" - ENTRY_PATH="${DATA_DIR}/${DATA_PREFIX_DIR}/$ENTRY_FILE" - check_entry_id "$ENTRY_ID" || continue - if check_entry_path "$ENTRY_PATH" - then - debug "file at path \"$ENTRY_PATH\" checks out" - printf "%s" "$ENTRY_PATH" - return 0 - else - debug "entry ID \"$ENTRY_ID\" failed check at path \"$ENTRY_PATH\", blacklisting" - BLACKLIST="${BLACKLIST}${BLACKLIST:+;}$ENTRY_ID" - debug "current blacklist: \"$BLACKLIST\"" - fi - done << EOF -$ENTRY_FILES -EOF - fi - done - IFS="$OIFS" -} +if [ "${DEBUG-0}" = '1' ]; then + debug() { printf '%s\n' "$1" >&2; } +else + debug() { :; } +fi -find_entry_path(){ - # For given desktop entry ID find an actual file path - ENTRY_FILE= - ENTRY_PATH= - DATA_DIR= - FILE_LIST= - ID_LIST= - ID_NUM= - - ENTRY_ID="$1" - - IFS=":" - for DATA_DIR in $DATA_HIERARCHY - do - IFS="$OIFS" - if [ -d "${DATA_DIR}/${DATA_PREFIX_DIR}" ] - then - debug "looking in \"${DATA_DIR}/${DATA_PREFIX_DIR}\"" - FILE_LIST="$(find -L "${DATA_DIR}/${DATA_PREFIX_DIR}" -type f -iname "*.desktop" -printf "%P\n")" - ID_LIST="$(printf "%s" "$FILE_LIST" | tr '/' '-')" - ID_NUM="$(printf "%s" "$ID_LIST" | grep -n "^${ENTRY_ID}$" | head -n 1 | cut -d : -f 1)" - ENTRY_FILE="$(printf "%s" "$FILE_LIST" | head -n "${ID_NUM:-0}" | tail -n 1)" - if [ -n "$ENTRY_FILE" ] - then - ENTRY_PATH="${DATA_DIR}/${DATA_PREFIX_DIR}/${ENTRY_FILE}" - else - continue - fi - debug "got entry path \"$ENTRY_PATH\"" - printf "%s" "$ENTRY_PATH" - return 0 - fi +trim_start() { + # Remove all but leading whitespace, and trim that from the given string + printf '%s' "${1#"${1%%[![:space:]]*}"}" +} + +# Read config from given path, print sanitised entries +read_config_path() { + config_path="$1" + + debug "reading config '$config_path'" + [ -f "$config_path" ] || return 0 + # Let `read` trim leading/trailing whitespace from the line + while read -r line; do + debug "read line '$line'" + case $line in + # `[The extensionless entry filename] should be a valid D-Bus well-known name.` + [A-Za-z_]*) printf '%s\n' "$line" ;; + esac + # By default empty lines and comments get ignored + done < "$config_path" +} + +# Find a matching file path for a given entry ID +find_entry_path() { + entry_id="$1" + debug "finding path for entry id '$entry_id'" + + # Loop through paths, any empty lines should be discarded by word splitting + IFS="$N" + for entry_path in $ENTRY_PATHS; do + debug "checking entry '$entry_path'" + # ID is path without '$data_dir/$DATA_PREFIX_DIR//' + found_entry_id="${entry_path#*//}" + # Remove '//' from desktop entry path + entry_path="${entry_path%//*}"/"$found_entry_id" + found_entry_id="$(printf '%s' "$found_entry_id" | tr '/' '-')" + debug "checking entry id '$found_entry_id'" + [ "$found_entry_id" != "$entry_id" ] && continue + debug "found entry path '$entry_path'" + printf '%s' "$entry_path" + return 0 done IFS="$OIFS" - debug "path not found for entry ID \"$ENTRY_ID\"" + debug 'no matching entry path found' return 1 } -check_entry_id(){ - # Check if entry ID is blacklisted by previous checks - ENTRY_ID="$1" - - debug "checking if ID \"$ENTRY_ID\" is in blacklist \"$BLACKLIST\"" - IFS=';' - for ITEM in $BLACKLIST - do +# Check validity of a given entry line +# Modifies following global variables: +# EXEC : Program to execute, possibly with arguments. See spec for details. +# EXECARG : Execution argument for the terminal emulator. +check_entry() { + # Order of checks is important + case $1 in + 'OnlyShowIn'*=*) + onlyShowIn=$(trim_start "${1#*=}") + debug "read OnlyShowIn '$onlyShowIn'" + IFS=';' + for name in $onlyShowIn; do + IFS=':' + for desktop in ${XDG_CURRENT_DESKTOP-}; do + IFS="$OIFS" + debug "checking OnlyShowIn match '$desktop'='$name'" + [ "$desktop" = "$name" ] && return 0 + done + done + IFS="$OIFS" + # Default in this case is to fail + return 1 + ;; + 'NotShowIn'*=*) + notShowIn=$(trim_start "${1#*=}") + debug "read NotShowIn '$notShowIn'" + IFS=';' + for name in $notShowIn; do + IFS=':' + for desktop in ${XDG_CURRENT_DESKTOP-}; do + IFS="$OIFS" + debug "checking NotShowIn match '$desktop'='$name'" + [ "$desktop" = "$name" ] && return 1 + done + done IFS="$OIFS" - if [ "$ENTRY_ID" = "$ITEM" ] - then - debug "blacklist positive" + # Default in this case is to succeed + return 0 + ;; + 'X-ExecArg'*=*) + # Set global variable + EXECARG=$(trim_start "${1#*=}") + debug "read execution argument '$EXECARG'" + ;; + 'ExecArg'*=*) + # Set global variable + EXECARG=$(trim_start "${1#*=}") + debug "read execution argument '$EXECARG'" + ;; + 'TryExec'*=*) + executable=$(trim_start "${1#*=}") + debug "checking TryExec executable '$executable'" + command -v "$executable" > /dev/null || return 1 + ;; + 'Hidden'*=*) + hidden=$(trim_start "${1#*=}") + debug "checking Hidden boolean '$hidden'" + [ "$hidden" = 'true' ] && return 1 + ;; + 'Exec'*=*) + # Set global variable + EXEC=$(trim_start "${1#*=}") + # Get first word from read Exec value + eval "set -- $EXEC" + exec0="$1" + debug "checking Exec[0] executable '$exec0'" + command -v "$exec0" > /dev/null || return 1 + ;; + esac + # By default unrecognised keys, empty lines and comments get ignored +} + +# Read entry from given path, only parse 'Desktop Entry' group +read_entry_path() { + entry_path="$1" + + debug "reading desktop entry '$entry_path'" + # Let `read` trim leading/trailing whitespace from the line + while read -r line; do + case $line in + # `There should be nothing preceding [the Desktop Entry group] in the desktop entry file but [comments]` + '[Desktop Entry]'*) ;; + # A `Key=Value` pair, check it + [A-Za-z0-9-]*) + check_entry "$line" && continue + # Reset values that might have been set + unset EXEC + unset EXECARG return 1 - fi - done - IFS="$OIFS" + ;; + # Start of the next group header, stop + '['*) break ;; + esac + # By default empty lines and comments get ignored + done < "$entry_path" return 0 } -get_first_arg(){ - # from complex arg string return first arg - eval "set -- $1" - echo "$1" -} - -check_entry_path(){ - # Determine if entry in given path is valid for execution in current DE - DATA= - TRYEXEC= - EXEC0= - NOTSHOWIN= - ONLYSHOWIN= - HIDDEN= - FAIL=0 - - ENTRY_PATH="$1" - DATA="$(read_entry_path "$ENTRY_PATH")" - - debug "checking TryExec" - TRYEXEC="$(printf "%s\n" "$DATA" | grep '^[[:space:]]*TryExec[[:space:]]*=' | head -n 1 | cut -d = -f 2-)" - TRYEXEC="$(trim_spaces "$TRYEXEC")" - if [ -n "$TRYEXEC" ] - then - debug "TryExec is defined" - if command -v "$TRYEXEC" > /dev/null - then - debug "TryExec command $TRYEXEC exists" - else - debug "TryExec command $TRYEXEC not found" - return 1 - fi - else - debug "TryExec not defined" - fi +# Subfolder within $XDG_DATA_*, analoguous to 'applications/' used with desktop entry files +DATA_PREFIX_DIR=xdg-terminals +# Name of config files to search and read +CONFIG_NAME=xdg-terminals.list - debug "checking Exec[0]" - EXEC0="$(printf "%s\n" "$DATA" | grep '^[[:space:]]*Exec[[:space:]]*=' | head -n 1 | cut -d = -f 2-)" - EXEC0="$(trim_spaces "$EXEC0")" - EXEC0="$(get_first_arg "$EXEC0")" - if [ -n "$EXEC0" ] && command -v "$EXEC0" > /dev/null - then - debug "Exec[0] command $EXEC0 exists" - else - debug "Exec[0] command $EXEC0 not found" - return 1 - fi +# Directory hierarchy searched for terminal config and desktop entry files +DATA_HIERARCHY="${XDG_DATA_HOME:-$HOME/.local/share}:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}" +CONF_HIERARCHY="${XDG_CONFIG_HOME:-$HOME/.config}:${XDG_CONFIG_DIRS:-/etc/xdg:/usr/etc/xdg}" - debug "checking Hidden" - HIDDEN="$(printf "%s\n" "$DATA" | grep '^[[:space:]]*Hidden[[:space:]]*=' | head -n 1 | cut -d = -f 2-)" - HIDDEN="$(trim_spaces "$HIDDEN")" - [ "$HIDDEN" = "true" ] && return 1 - - debug "checking NotShowIn" - NOTSHOWIN="$(printf "%s\n" "$DATA" | grep '^[[:space:]]*NotShowIn[[:space:]]*=' | head -n 1 | cut -d = -f 2-)" - NOTSHOWIN="$(trim_spaces "$NOTSHOWIN")" - IFS=';' - for ITEM in $NOTSHOWIN - do - IFS=: - for DESKTOP in $XDG_CURRENT_DESKTOP - do - IFS="$OIFS" - debug "checking NotShowIn against \"$DESKTOP\"=\"$ITEM\"" - [ "$DESKTOP" = "$ITEM" ] && return 1 - done +# All desktop entry paths in descending order of preference +ENTRY_PATHS='' +# All desktop entry ids in descending order of preference +ENTRY_IDS='' + +# Generate list of possible config files for current DE +# TODO: Should this be case insensitive? Desktop entry checks that also use $XDG_CURRENT_DESKTOP are not +lowercase_desktops="$(printf '%s' "${XDG_CURRENT_DESKTOP-}" | tr '[:upper:]' '[:lower:]')" +debug "lowercase desktops are: '$lowercase_desktops'" +# All config files are searched for, and read immediatelly, rather than when out of IDs +# This way all possible IDs are know before iterating over them, and are in order of preference +# Further down, duplicate IDs are then removed using `awk` +# This avoids having to use cumbersome blacklists, or fragile string operations, to deal with them +IFS=':' +for config_dir in $CONF_HIERARCHY; do + # Append read ID(s) to list, using brace expansion for better readability + IFS=':' + for desktop in $lowercase_desktops; do + IFS="$OIFS" + ENTRY_IDS="${ENTRY_IDS}${N}$(read_config_path "$config_dir"/"$desktop"-"$CONFIG_NAME")" done IFS="$OIFS" + ENTRY_IDS="${ENTRY_IDS}${N}$(read_config_path "$config_dir"/"$CONFIG_NAME")" +done - debug "checking OnlyShowIn" - ONLYSHOWIN="$(printf "%s\n" "$DATA" | grep '^[[:space:]]*OnlyShowIn[[:space:]]*=' | head -n 1 | cut -d = -f 2-)" - ONLYSHOWIN="$(trim_spaces "$ONLYSHOWIN")" - IFS=';' - for ITEM in $ONLYSHOWIN - do - FAIL=1 - IFS=: - for DESKTOP in $XDG_CURRENT_DESKTOP - do - IFS="$OIFS" - debug "checking OnlyShowIn against \"$DESKTOP\"=\"$ITEM\"" - [ "$DESKTOP" = "$ITEM" ] && { FAIL=0 ; break ; } - done - [ "$FAIL" = "0" ] && break - done +# Generate list of possible terminal entry files and also add their IDs to +IFS=':' +for data_dir in $DATA_HIERARCHY; do IFS="$OIFS" - [ "$FAIL" = "1" ] && return 1 - - return 0 -} - -read_entry_path(){ - # read entry, only "Desktop Entry" section - DE="0" - ENTRY_PATH="$1" - while read -r LINE - do - if printf "%s" "$LINE" | grep -q "^[[:space:]]*\[" - then - printf "%s" "$LINE" | grep -qi "^[[:space:]]*\[Desktop Entry\]" && DE=1 || DE=0 - fi - [ "$DE" = "1" ] && printf "%s\n" "$LINE" - done < "${ENTRY_PATH}" -} - -ENTRY_PATH="$(find_preferred_entry)" -[ -z "$ENTRY_PATH" ] && ENTRY_PATH="$(find_any_entry)" + if [ -d "$data_dir"/"$DATA_PREFIX_DIR" ]; then + debug "searching in '$data_dir/$DATA_PREFIX_DIR'" + while read -r entry_path; do + debug "found desktop entry '$entry_path'" + # Remove data directory path + entry_path="${entry_path#"$data_dir"/"$DATA_PREFIX_DIR"/}" + # Create entry ID from path + entry_id="$(printf '%s' "$entry_path" | tr '/' '-')" + debug "adding matching id '$entry_id'" + # Append found ID to list, using brace expansion for better readability + ENTRY_IDS="${ENTRY_IDS}${N}${entry_id}" + # Prepend data directory path, and delimit its end using an extra '/' character + # This is done so the ID can be recreated in `find_entry_path` + # Other possible way of storing the data direcotry could be: + # $data_dir/$DATA_PREFIX_DIR/$entry_path/$entry_id + # Where '.desktop/' is the delimiter, as IDs do not contain '/', and entry files must end in '.desktop' + entry_path="$data_dir"/"$DATA_PREFIX_DIR"//"$entry_path" + # Append found path to list, using brace expansion for better readability + ENTRY_PATHS="${ENTRY_PATHS}${N}${entry_path}" + # Print order of found files is unpredictable, sort them + done <<- EOF + $(find -L "$data_dir"/"$DATA_PREFIX_DIR" -type f -iname '*.desktop' -print0 | sort -z | xargs -0rn 1) + EOF + fi +done -if [ -n "$ENTRY_PATH" ] -then - DATA="$(read_entry_path "$ENTRY_PATH")" - EXEC="$(printf "%s\n" "$DATA" | grep '^[[:space:]]*Exec[[:space:]]*=' | head -n 1 | cut -d = -f 2-)" - EXEC="$(trim_spaces "$EXEC")" - EXECARG="$(printf "%s\n" "$DATA" | grep '^[[:space:]]*ExecArg[[:space:]]*=' | head -n 1)" - EXECARG="$(trim_spaces "$EXECARG")" - if [ -z "$EXECARG" ] - then - EXECARG="$(printf "%s\n" "$DATA" | grep '^[[:space:]]*X-ExecArg[[:space:]]*=' | head -n 1)" - EXECARG="$(trim_spaces "$EXECARG")" +# Remove duplicate IDs +ENTRY_IDS="$(printf '%s' "$ENTRY_IDS" | awk '!seen[$0]++')" +debug "final entry ID list '$ENTRY_IDS'" + +# Loop through IDs, any empty lines should be discarded by word splitting +IFS="$N" +for entry_id in $ENTRY_IDS; do + # See read_entry_path and check_entry + if read_entry_path "$(find_entry_path "$entry_id")"; then + # Default to '-e' if unset + EXECARG=${EXECARG-'-e'} + break fi - [ -z "$EXECARG" ] && EXECARG="ExecArg=-e" - EXECARG="$(printf "%s\n" "$EXECARG" | cut -d = -f 2-)" - EXECARG="$(trim_spaces "$EXECARG")" -else - EXEC="xterm" - EXECARG="-e" +done +IFS="$OIFS" + +if [ -z "${EXEC-}" ]; then + # Set defaults + EXEC='xterm' + EXECARG='-e' fi +# Store original argument list, before it's modified ORIG_ARGV="$*" -if [ "$#" -gt 0 ] -then - if [ -n "$EXECARG" ] - then - eval "set -- $EXEC \"\$EXECARG\" \"\$@\"" - else - eval "set -- $EXEC \"\$@\"" - fi +# `Implementations must undo quoting [in the Exec argument(s)][...]` +if [ "$#" -gt 0 ]; then + eval "set -- $EXEC ${EXECARG:+'"$EXECARG"'} \"\$@\"" else eval "set -- $EXEC" fi @@ -348,12 +275,7 @@ EXECARG=$EXECARG ARGV=$ORIG_ARGV Final argv (>arg< per line): -$( - for ARG in "$@" - do - echo ">$ARG<" - done -) +$(printf '>%s<\n' "$@") End of final argv" exec "$@" ++++++ xdg-terminal-exec.obsinfo ++++++ --- /var/tmp/diff_new_pack.0fRt5T/_old 2023-10-08 12:22:18.374760089 +0200 +++ /var/tmp/diff_new_pack.0fRt5T/_new 2023-10-08 12:22:18.378760233 +0200 @@ -1,5 +1,5 @@ name: xdg-terminal-exec -version: 20230731+git.6426085 -mtime: 1690798818 -commit: 6426085370a3adafea933d53c123d813d7c7ab44 +version: 20231003+git.e5c20d0 +mtime: 1696360333 +commit: e5c20d043bd34bde671a4344e2147da9360f6fc2