Git commit 301b9b4caf1b84bf2e14bd616fec06683f5a2d18 by Andrew Shark.
Committed on 17/02/2024 at 17:50.
Pushed by ashark into branch 'master'.

Merge kdesrc-build --run and kdesrc-run

This fixes multiple issues with kdesrc-run and kdesrc-build --run

When using the --run parameter, the environment variables of global module were 
applied (from set-env options). But this is incorrect, since global cannot be 
treated as usual module. Its build system is defined as generic. In its 
prepareModuleBuildEnvironment these variables were setted:
- PKG_CONFIG_PATH
- LD_LIBRARY_PATH
- PATH
They have nothing to do with launched module's variables, except PATH, but even 
that was because of global install-dir matches the module's install-dir in most 
cases.

The kdesrc-run did sourced module's prefix.sh instead (located in its 
build-dir). That setted the following variables:
- PATH (the correct, from module)
- XDG_DATA_DIRS
- XDG_CONFIG_DIRS
- QT_PLUGIN_PATH
- QML2_IMPORT_PATH
- QT_QUICK_CONTROLS_STYLE_PATH

This commit fixes the broken behavior of --run, and the broken behavior of 
kdesrc-run.

Fixes: #145
Fixes: #114

Other fixes:
- Now the parameters after --run that starts with minuses are passed to the 
start-program, and not considered as options of kdesrc-build
- When setting parameters to the runned executable, they are actually applied. 
Previously the run script surrounded the $@ in the quotes.
- Fixed indentation and unnecessary semicolons in executable script.
- Made more clear note information when launching. The debug level controls if 
it will be displayed.

M  +0    -1    CMakeLists.txt
M  +0    -1    README.md
M  +0    -1    completions/zsh/_kdesrc-build
M  +4    -4    data/kdesrc-run-completions.sh
M  +1    -1    doc/man-kdesrc-build.1.docbook
M  +3    -23   doc/supported-cmdline-params.docbook
D  +0    -134  kdesrc-run
M  +2    -40   modules/ksb/Application.pm
M  +22   -5    modules/ksb/Cmdline.pm
A  +122  -0    modules/ksb/StartProgram.pm
M  +2    -2    modules/ksb/TaskManager.pm
M  +1    -1    scripts/gen_zsh_completions.py

https://invent.kde.org/sdk/kdesrc-build/-/commit/301b9b4caf1b84bf2e14bd616fec06683f5a2d18

diff --git a/CMakeLists.txt b/CMakeLists.txt
index bae5fd53..03047adb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -46,7 +46,6 @@ endif()
 
 # Currently, kdesrc-build real file (not a symlink) expects to be near its 
data and modules. Need to make a symlink in PKGBUILD then.
 install(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/kdesrc-build DESTINATION 
${KDE_INSTALL_DATADIR}/kdesrc-build)
-install(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/kdesrc-run DESTINATION 
${KDE_INSTALL_DATADIR}/kdesrc-build)
 
 install(DIRECTORY data/ DESTINATION ${KDE_INSTALL_DATADIR}/kdesrc-build/data)
 
diff --git a/README.md b/README.md
index c95e6d8b..8f253dcc 100644
--- a/README.md
+++ b/README.md
@@ -32,7 +32,6 @@ For other distributions, you will need to make a local 
installation:
 $ cd ~/.local/share
 $ git clone https://invent.kde.org/sdk/kdesrc-build.git
 $ ln -sf ~/.local/share/kdesrc-build/kdesrc-build ~/.local/bin
-$ ln -sf ~/.local/share/kdesrc-build/kdesrc-run ~/.local/bin
 ```
 
 - Make sure it works by running:
diff --git a/completions/zsh/_kdesrc-build b/completions/zsh/_kdesrc-build
index bc8202e4..600811e8 100644
--- a/completions/zsh/_kdesrc-build
+++ b/completions/zsh/_kdesrc-build
@@ -75,7 +75,6 @@ _arguments \
   "(--run-tests --no-run-tests)"{--run-tests,--no-run-tests}"[Built the 
modules with support for running their test suite]" \
   "--set-module-option-value""[Override an option in your configuration file 
for a specific module]"":argument:" \
   "--source-dir""[Directory that stores the KDE sources]"":argument:" \
-  "(--run --start-program)"{--run,--start-program}"[A program to run with 
kdesrc-build]"":arguments:" \
   "(--stop-on-failure 
--no-stop-on-failure)"{--stop-on-failure,--no-stop-on-failure}"[Stops/Does not 
stop the build as soon as a package fails to build]" \
   "--tag""[Download a specific release of a module]"":argument:" \
   "--uninstall""[Uninstalls the module]" \
diff --git a/data/kdesrc-run-completions.sh b/data/kdesrc-run-completions.sh
index 47e222ff..820259e2 100644
--- a/data/kdesrc-run-completions.sh
+++ b/data/kdesrc-run-completions.sh
@@ -1,5 +1,5 @@
-## Autocomplete for kdesrc-run
-function _comp_kdesrc_run
+## Autocomplete for kdesrc-build --run
+function _comp_kdesrc_build_run
 {
   local cur
   COMPREPLY=()
@@ -10,7 +10,7 @@ function _comp_kdesrc_run
     return 0
   fi
 
-  # Retrieve build modules through kdesrc-run
+  # Retrieve build modules through kdesrc-build
   # If the exit status indicates failure, set the wordlist empty to avoid
   # unrelated messages.
   local modules
@@ -26,4 +26,4 @@ function _comp_kdesrc_run
 }
 
 ## Register autocomplete function
-complete -o nospace -F _comp_kdesrc_run kdesrc-run
+complete -o nospace -F _comp_kdesrc_build_run kdesrc-build
diff --git a/doc/man-kdesrc-build.1.docbook b/doc/man-kdesrc-build.1.docbook
index f97209c9..5483e425 100644
--- a/doc/man-kdesrc-build.1.docbook
+++ b/doc/man-kdesrc-build.1.docbook
@@ -623,7 +623,7 @@ Generate the &kdesrc-build; configuration file.
 <listitem>
 <para>
     Runs the program named by <replaceable>foo</replaceable> using
-    <command>kdesrc-build</command>'s normal build environment. All command
+    prefix.sh environment variables. All command
     line arguments present after this option are passed to
     <replaceable>foo</replaceable> as it is run.
 </para>
diff --git a/doc/supported-cmdline-params.docbook 
b/doc/supported-cmdline-params.docbook
index fb02d2d3..2a8014b6 100644
--- a/doc/supported-cmdline-params.docbook
+++ b/doc/supported-cmdline-params.docbook
@@ -59,31 +59,11 @@ a few).
 </varlistentry>
 
 <varlistentry id="cmdline-run">
-<term><option><link linkend="cmdline-run">--run</link></option> (or 
<option>--start-program</option>) <parameter>program [parameters 
...]</parameter></term>
+<term><option><link linkend="cmdline-run">--run</link></option> (or 
<option>--start-program</option>) [-e|--exec name] [-f|--fork] 
<parameter>program [parameters ...]</parameter></term>
 <listitem><para>
 This option interprets the next item on the command line as a program to run,
-and &kdesrc-build; will then finish reading the configuration file, update the
-environment as normal, and then execute the given program.</para>
-
-<para>This will not work to start a shell with the &kdesrc-build; environment
-in most cases however, since interactive shells typically reset at least part
-of the environment variables (such as <envar>PATH</envar> and
-${install-dir}) in the startup sequence.
-</para>
-
-<tip><para>If you want to see the environment used by &kdesrc-build;, you
-can run the <command>printenv</command> command:</para>
-<informalexample>
-<screen>$ <command>kdesrc-build</command> <parameter>--run</parameter> 
<parameter>printenv</parameter>
-KDE_SESSION_VERSION=4
-SDL_AUDIODRIVER=alsa
-LANGUAGE=
-XCURSOR_THEME=Oxygen_Blue
-LESS=-R -M --shift 5
-QMAIL_CONTROLDIR=/var/qmail/control
-... etc.
-</screen>
-</informalexample></tip>
+and &kdesrc-build; will then finish reading the configuration file, source the
+prefix.sh to apply environment variables, and then execute the given 
program.</para>
 </listitem>
 </varlistentry>
 
diff --git a/kdesrc-run b/kdesrc-run
deleted file mode 100755
index 90c55560..00000000
--- a/kdesrc-run
+++ /dev/null
@@ -1,134 +0,0 @@
-#!/usr/bin/env perl
-
-=pod
-
-=encoding UTF-8
-
-=head1 NAME
-
-kdesrc-run - Run KDE applications built with kdesrc-build.
-
-=head1 SYNOPSIS
-
-kdesrc-run [options] <module-name> [arguments]
-
-=head1 OPTIONS
-
-  -e, --exec <program>    Specify program of the module. Default to module 
name.
-  -f, --fork              Launch the program in a new session.
-  -q, --quiet             Do not print run information.
-  -h, --help              Print usage information and exit.
-
-=head1 EXAMPLES
-
-B<kdesrc-run -f kate -l 5 file1.txt>
-
-  Launch kate in a new session with '-l 5 file1.txt' arguments.
-
-B<kdesrc-run -e kate-syntax-highlighter kate --list-themes>
-
-  Launch kate-syntax-highlighter of module kate with '--list-themes' argument.
-
-=cut
-
-use 5.014;
-use strict;
-use warnings;
-use autodie;
-
-use Pod::Usage;
-use Getopt::Long qw(:config pass_through require_order);
-use JSON::PP;
-use List::Util qw(first);
-
-binmode STDOUT, 'encoding(UTF-8)';
-binmode STDERR, 'encoding(UTF-8)';
-
-our $optExec;
-our $optFork          = 0;
-our $optHelp          = 0;
-our $optQuiet         = 0;
-
-GetOptions(
-    'exec|e=s'       => \$optExec,
-    'fork|f'         => \$optFork,
-    'help|h'         => sub { pod2usage(0); },
-    'quiet|q'        => \$optQuiet,
-);
-
-if ($#ARGV == -1) {
-    pod2usage(0);
-}
-
-my $module = shift @ARGV;
-my $exec   = $optExec // $module;
-
-# According to XDG spec, if $XDG_STATE_HOME is not set, then we should default
-# to ~/.local/state
-my $xdgStateHome = $ENV{XDG_STATE_HOME} // "$ENV{HOME}/.local/state";
-my $dataFileName = "kdesrc-build-data";
-my @possibleDataPaths = ("./.$dataFileName", "$xdgStateHome/$dataFileName");
-my $buildDataFile = first { -e $_ } (@possibleDataPaths);
-
-if (not defined $buildDataFile) {
-    say qq("$dataFileName" file is not available. Exit now.);
-    exit 1;
-}
-
-my $buildData = do {
-    open my $fh, '<', $buildDataFile;
-    local $/ = undef;
-    decode_json(<$fh>);
-};
-
-if (not defined $buildData->{$module}) {
-    say qq(Module "$module" has not been built yet.);
-    exit 1;
-}
-
-my $buildDir   = $buildData->{$module}{'build-dir'};
-my $installDir = $buildData->{$module}{'install-dir'};
-my $revision   = $buildData->{$module}{'last-build-rev'};
-my $execPath   = "$installDir/bin/$exec";
-
-if (not -e $execPath) {
-    say qq(Program "$exec" does not exist.);
-    say qq(Try to set executable name with -e option.);
-    exit 127;    # Command not found
-}
-
-# Most of the logic is done by Perl, so the shell script here should be POSIX
-# compliant. Consider using ShellCheck to make sure of that.
-my $script = qq{
-    #!/bin/sh
-
-    # Set up environment variables (dot command).
-    . "$buildDir/prefix.sh";
-
-    # Launch the program with optional arguments.
-    if [ "$optFork" = 1 ]; then
-        setsid -f "$execPath" "\$@";
-    else
-        "$execPath" "\$@";
-    fi;
-};
-
-# Print run information
-if (not $optQuiet) {
-    print '#' x 80, "\n";
-    print ' ' x 35, 'kdesrc-run', "\n";
-    say "Module:             $module";
-    say "Program:            $exec";
-    say "Revision:           $revision";
-    say "Arguments:          @ARGV";
-    print '#' x 80, "\n";
-    print "\n";
-}
-
-# Instead of embedding @ARGV in shell script with string interpolation, pass
-# them as arguments of the script. Let the shell handle the list through "$@",
-# so it will do the quoting on each one of them.
-#
-# Run the script with sh options specification:
-#     sh -c command_string command_name $1 $2 $3...
-exec('/bin/sh', '-c', $script, $exec, @ARGV);
diff --git a/modules/ksb/Application.pm b/modules/ksb/Application.pm
index 952f3f8f..fd17662f 100644
--- a/modules/ksb/Application.pm
+++ b/modules/ksb/Application.pm
@@ -38,6 +38,7 @@ use ksb::ModuleSet 0.20;
 use ksb::ModuleSet::KDEProjects;
 use ksb::ModuleSet::Qt;
 use ksb::RecursiveFH;
+use ksb::StartProgram;
 use ksb::TaskManager;
 use ksb::Updater::Git;
 use ksb::Util;
@@ -324,13 +325,8 @@ EOF
     # For user convenience, cmdline ignored selectors would not override the 
config selectors. Instead, they will be merged.
     my %ignoredSelectors = (%ignored_in_cmdline, %ignored_in_global_section);
 
-    # Check if we're supposed to drop into an interactive shell instead.  If 
so,
-    # here's the stop off point.
-
     if (@startProgramAndArgs) {
-        $ctx->setupEnvironment(); # Read options from set-env
-        $ctx->commitEnvironmentChanges(); # Apply env options to environment
-        _executeCommandLineProgram(@startProgramAndArgs); # noreturn
+        StartProgram::executeCommandLineProgram($ctx, @startProgramAndArgs); # 
noreturn
     }
 
     if (!isTesting()) {
@@ -1198,40 +1194,6 @@ sub _readConfigurationOptions ($ctx, $fh, 
$cmdlineGlobalOptions, $deferredOption
     return @module_list;
 }
 
-# Exits out of kdesrc-build, executing the user's preferred shell instead.  The
-# difference is that the environment variables should be as set in kdesrc-build
-# instead of as read from .bashrc and friends.
-#
-# You should pass in the options to run the program with as a list.
-#
-# Meant to implement the --run command line option.
-sub _executeCommandLineProgram
-{
-    my ($program, @args) = @_;
-
-    if (!$program)
-    {
-        error ("You need to specify a program with the --run option.");
-        exit 1; # Can't use finish here.
-    }
-
-    if (($< != $>) && ($> == 0))
-    {
-        error ("kdesrc-build will not run a program as root unless you really 
are root.");
-        exit 1;
-    }
-
-    debug ("Executing b[r[$program] ", join(' ', @args));
-
-    exit 0 if pretending();
-
-    exec $program, @args or do {
-        # If we get to here, that sucks, but don't continue.
-        error ("Error executing $program: $!");
-        exit 1;
-    };
-}
-
 # Function: _handle_install
 #
 # Handles the installation process.  Simply calls 'make install' in the build
diff --git a/modules/ksb/Cmdline.pm b/modules/ksb/Cmdline.pm
index 2950c890..cb1666e4 100644
--- a/modules/ksb/Cmdline.pm
+++ b/modules/ksb/Cmdline.pm
@@ -232,7 +232,6 @@ sub readCommandLineOptionsAndSelectors (@options)
 
         # Getopt::Long doesn't set these up for us even though we specify an
         # array. Set them up ourselves.
-        'start-program'  => [ ],
         'ignore-modules' => [ ],
 
         # Module selectors, the <> is Getopt::Long shortcut for an
@@ -256,6 +255,26 @@ sub readCommandLineOptionsAndSelectors (@options)
     # build options for Getopt::Long
     my @supportedOptions = _supportedOptions();
 
+    # If we have --run option, grab all the rest arguments to pass to the 
corresponding parser.
+    # This way the arguments after --run could start with "-" or "--".
+    my $run_index = -1;
+    foreach my $i (0 .. $#options) {
+        if ($options[$i] eq "--run" or $options[$i] eq "--start-program") {
+            $run_index = $i;
+            last;
+        }
+    }
+
+    if ($run_index != -1) {
+        @{ $opts->{"start-program"} } = @options[$run_index+1 .. $#options];
+        @options = @options[0 .. $run_index-1]; # remove all after --run, and 
the --run itself
+
+        if (! @{ $opts->{"start-program"} }){ # check this here, because later 
the empty list will be treated as not wanting to start program
+            error ("You need to specify a module with the --run option");
+            exit 1; # Do not continue
+        }
+    }
+
     # Actually read the options.
     my $optsSuccess = GetOptionsFromArray(\@options, \%foundOptions,
         # Options here should not duplicate the flags and options defined below
@@ -269,9 +288,8 @@ sub readCommandLineOptionsAndSelectors (@options)
         croak_runtime("Error reading command-line options.");
     }
 
-    # Don't get ignore-modules and start-program (i.e. --run) confused with
-    # global options
-    my @protectedKeys = ('ignore-modules', 'start-program');
+    # Don't get ignore-modules confused with global options
+    my @protectedKeys = ('ignore-modules');
     @{$opts}{@protectedKeys} = @foundOptions{@protectedKeys};
     delete @foundOptions{@protectedKeys};
 
@@ -438,7 +456,6 @@ sub _supportedOptions
         'set-module-option-value=s',
         'show-info',
         'show-options-specifiers',
-        'start-program|run=s{,}',
         'stop-after|to=s',
         'stop-before|until=s',
         'version|v',
diff --git a/modules/ksb/StartProgram.pm b/modules/ksb/StartProgram.pm
new file mode 100644
index 00000000..9e97b5a4
--- /dev/null
+++ b/modules/ksb/StartProgram.pm
@@ -0,0 +1,122 @@
+package StartProgram;
+
+use ksb;
+use ksb::Debug;
+
+=pod
+
+=encoding UTF-8
+
+=head1 SYNOPSIS
+
+kdesrc-build --run [options] <module-name> [arguments]
+
+=head1 OPTIONS
+
+  -e, --exec <program>    Specify program of the module. Default to module 
name.
+  -f, --fork              Launch the program in a new session.
+
+=head1 EXAMPLES
+
+B<kdesrc-build --run -f kate -l 5 file1.txt>
+
+  Launch kate in a new session with '-l 5 file1.txt' arguments.
+
+B<kdesrc-build --run -e kate-syntax-highlighter kate --list-themes>
+
+  Launch kate-syntax-highlighter of module kate with '--list-themes' argument.
+
+=cut
+
+sub executeCommandLineProgram
+{
+    my ($ctx, @args) = @_;
+
+    my $optExec = undef;
+    my $optFork = 0;
+
+    # We cannot use GetOptionsFromArray here, because -e or -f could be meant 
to be arguments of module executable. But that would steal them.
+    # We manually care of them, they can only appear in front of 
module/executable name.
+    my $arg;
+    while ($arg = shift @args) {
+        if ($arg eq "-f" || $arg eq "--fork") {
+            $optFork = 1;
+            next;
+        } elsif ($arg eq "-e" || $arg eq "--exec") {
+            $optExec = shift @args;
+            if (not defined $optExec){
+                error("-e option requires a name of executable");
+                exit(1)
+            }
+            next;
+        }
+        last;
+    }
+
+    my $module = $arg;
+    if (not defined $module) { # the case when user specified -e 
executable_name and/or -f, but then did not specified the module name
+        error("The module name is missing");
+        exit 1;
+    }
+    my $executable = $optExec // $module;
+    my $buildData = $ctx->{persistent_options};
+
+    if (not defined $buildData->{$module}) {
+        say qq(Module "$module" has not been built yet.);
+        exit 1;
+    }
+
+    my $buildDir   = $buildData->{$module}{'build-dir'};
+    my $installDir = $buildData->{$module}{'install-dir'};
+    my $revision   = $buildData->{$module}{'last-build-rev'};
+    my $execPath   = "$installDir/bin/$executable";
+
+    if (not -e $execPath) {
+        say qq(Executable "$executable" does not exist.);
+        say qq(Try to set executable name with -e option.);
+        exit 127;    # Command not found
+    }
+
+    # Most of the logic is done by Perl, so the shell script here should be 
POSIX
+    # compliant. Consider using ShellCheck to make sure of that.
+    my $script = <<~EOF;
+        #!/bin/sh
+
+        # Set up environment variables (dot command).
+        . "$buildDir/prefix.sh"
+
+        # Launch the program with optional arguments.
+        if [ "$optFork" = 1 ]; then
+            setsid -f "$execPath" \$@
+        else
+            "$execPath" \$@
+        fi
+        EOF
+
+    # Print run information
+    note (
+        "#" x 80, "\n",
+        "Module:             $module\n",
+        "Executable:         $executable\n",
+        "Revision:           $revision\n",
+        "Arguments:          @args\n",
+        "#" x 80, "\n",
+        "\n"
+    );
+
+    exit 0 if pretending();
+
+    # Instead of embedding @args in shell script with string interpolation, 
pass
+    # them as arguments of the script. Let the shell handle the list through 
"$@",
+    # so it will do the quoting on each one of them.
+    #
+    # Run the script with sh options specification:
+    #        sh      -c command_string  command_name        $1 $2 $3...
+    exec('/bin/sh', '-c', $script, "kdesrc-build run script", @args) or do {
+        # If we get to here, that sucks, but don't continue.
+        error ("Error executing $executable: $!");
+        exit 1;
+    };
+}
+
+1;
diff --git a/modules/ksb/TaskManager.pm b/modules/ksb/TaskManager.pm
index b97269b8..765fcf4c 100644
--- a/modules/ksb/TaskManager.pm
+++ b/modules/ksb/TaskManager.pm
@@ -153,7 +153,7 @@ sub _handle_updates ($ipc, $ctx)
         # running ->update() from short-circuiting if an error is noted.
         $hadError = !$module->update($ipc, $ctx) || $hadError;
 
-        # Cache module directories, e.g. to be consumed in kdesrc-run
+        # Cache module directories, e.g. to be consumed in kdesrc-build --run
         # This is needed for --no-async mode where the buildSingleModule won't 
run
         # But the other one is needed for --async mode since persistent options
         # only work from within the build process
@@ -173,7 +173,7 @@ sub _buildSingleModule ($ipc, $ctx, $module, $startTimeRef)
     $ctx->resetEnvironment();
     $module->setupEnvironment();
 
-    # Cache module directories, e.g. to be consumed in kdesrc-run
+    # Cache module directories, e.g. to be consumed in kdesrc-build --run
     $module->setPersistentOption('source-dir',  $module->fullpath('source'));
     $module->setPersistentOption('build-dir',   $module->fullpath('build'));
     $module->setPersistentOption('install-dir', $module->installationPath());
diff --git a/scripts/gen_zsh_completions.py b/scripts/gen_zsh_completions.py
index 64a392c5..7895130c 100644
--- a/scripts/gen_zsh_completions.py
+++ b/scripts/gen_zsh_completions.py
@@ -178,7 +178,7 @@ short_descriptions = {  # contains one of the options (any 
of them) from set, an
     "--resume": "Resume after a build failure",
     "--resume-from": "Skips modules until just before or after the given 
package, then operates as normal",
     "--revision": "Checkout a specific numbered revision",
-    "--run": "A program to run with kdesrc-build",
+    # "--run": "A program to run with kdesrc-build",  # Todo Needs to be added 
separately
     "--run-tests": "Built the modules with support for running their test 
suite",
     "--set-module-option-value": "Override an option in your configuration 
file for a specific module",
     "--source-dir": "Directory that stores the KDE sources",

Reply via email to