diff --git a/src/libcalamares/ProcessJob.cpp b/src/libcalamares/ProcessJob.cpp index fa467c08b..05be969af 100644 --- a/src/libcalamares/ProcessJob.cpp +++ b/src/libcalamares/ProcessJob.cpp @@ -82,7 +82,7 @@ ProcessJob::exec() QString(), m_timeoutSec ); - return explainProcess( ec, m_command, output, m_timeoutSec ); + return CalamaresUtils::ProcessResult::explainProcess( this, ec, m_command, output, m_timeoutSec ); } @@ -144,41 +144,4 @@ ProcessJob::callOutput( const QString& command, return process.exitCode(); } - -JobResult -ProcessJob::explainProcess( int ec, const QString& command, const QString& output, int timeout ) -{ - if ( ec == 0 ) - return JobResult::ok(); - - if ( ec == -1 ) //Crash! - return JobResult::error( tr( "External command crashed" ), - tr( "Command %1 crashed.\nOutput:\n%2" ) - .arg( command ) - .arg( output ) ); - - if ( ec == -2 ) - return JobResult::error( tr( "External command failed to start" ), - tr( "Command %1 failed to start." ) - .arg( command ) ); - - if ( ec == -3 ) - return JobResult::error( tr( "Internal error when starting command" ), - tr( "Bad parameters for process job call." ) ); - - if ( ec == -4 ) - return JobResult::error( tr( "External command failed to finish" ), - tr( "Command %1 failed to finish in %2s.\nOutput:\n%3" ) - .arg( command ) - .arg( timeout ) - .arg( output ) ); - - //Any other exit code - return JobResult::error( tr( "External command finished with errors" ), - tr( "Command %1 finished with exit code %2.\nOutput:\n%3" ) - .arg( command ) - .arg( ec ) - .arg( output ) ); -} - } // namespace Calamares diff --git a/src/libcalamares/ProcessJob.h b/src/libcalamares/ProcessJob.h index a18bd1e3b..59a532023 100644 --- a/src/libcalamares/ProcessJob.h +++ b/src/libcalamares/ProcessJob.h @@ -39,10 +39,6 @@ public: QString prettyStatusMessage() const override; JobResult exec() override; -protected: - /** @brief Explain a typical external process failure. */ - static JobResult explainProcess( int errorCode, const QString& command, const QString& output, int timeout ); - private: int callOutput( const QString& command, QString& output, diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 103246fad..4d70e2a78 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014, Teo Mrnjavac - * Copyright 2017, Adriaan de Groot + * Copyright 2017-2018, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -93,7 +93,8 @@ System::mount( const QString& devicePath, } ProcessResult -System::targetEnvCommand( +System::runCommand( + System::RunLocation location, const QStringList& args, const QString& workingPath, const QString& stdInput, @@ -105,8 +106,8 @@ System::targetEnvCommand( return -3; Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( !gs || - ( m_doChroot && !gs->contains( "rootMountPoint" ) ) ) + if ( ( location == System::RunLocation::RunInTarget ) && + ( !gs || !gs->contains( "rootMountPoint" ) ) ) { cLog() << "No rootMountPoint in global storage"; return -3; @@ -116,7 +117,7 @@ System::targetEnvCommand( QString program; QStringList arguments; - if ( m_doChroot ) + if ( location == System::RunLocation::RunInTarget ) { QString destDir = gs->value( "rootMountPoint" ).toString(); if ( !QDir( destDir ).exists() ) @@ -249,4 +250,42 @@ System::doChroot() const return m_doChroot; } +Calamares::JobResult +ProcessResult::explainProcess( const QObject* parent, int ec, const QString& command, const QString& output, int timeout ) +{ + using Calamares::JobResult; + + if ( ec == 0 ) + return JobResult::ok(); + + if ( ec == -1 ) //Crash! + return JobResult::error( parent->tr( "External command crashed" ), + parent->tr( "Command %1 crashed.\nOutput:\n%2" ) + .arg( command ) + .arg( output ) ); + + if ( ec == -2 ) + return JobResult::error( parent->tr( "External command failed to start" ), + parent->tr( "Command %1 failed to start." ) + .arg( command ) ); + + if ( ec == -3 ) + return JobResult::error( parent->tr( "Internal error when starting command" ), + parent->tr( "Bad parameters for process job call." ) ); + + if ( ec == -4 ) + return JobResult::error( parent->tr( "External command failed to finish" ), + parent->tr( "Command %1 failed to finish in %2s.\nOutput:\n%3" ) + .arg( command ) + .arg( timeout ) + .arg( output ) ); + + //Any other exit code + return JobResult::error( parent->tr( "External command finished with errors" ), + parent->tr( "Command %1 finished with exit code %2.\nOutput:\n%3" ) + .arg( command ) + .arg( ec ) + .arg( output ) ); +} + } // namespace diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.h b/src/libcalamares/utils/CalamaresUtilsSystem.h index bdc5afd4a..f4500f9a9 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.h +++ b/src/libcalamares/utils/CalamaresUtilsSystem.h @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014, Teo Mrnjavac - * Copyright 2017, Adriaan de Groot + * Copyright 2017-2018, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +21,8 @@ #include "DllMacro.h" +#include "Job.h" + #include #include #include @@ -33,6 +35,37 @@ public: /** @brief Implicit one-argument constructor has no output, only a return code */ ProcessResult( int r ) : QPair< int, QString >( r, QString() ) {} ProcessResult( int r, QString s ) : QPair< int, QString >( r, s ) {} + + int getExitCode() const { return first; } + QString getOutput() const { return second; } + + /** @brief Explain a typical external process failure. + * + * @param parent Used as context for translation calls. + * @param errorCode Return code from runCommand() or similar + * (negative values get special explanation). The member + * function uses the exit code stored in the ProcessResult + * @param output (error) output from the command, used when there is + * an error to report (exit code > 0). The member + * function uses the output stored in the ProcessResult. + * @param command String or split-up string of the command + * that was invoked. + * @param timeout Timeout passed to the process runner, for explaining + * error code -4 (timeout). + */ + static Calamares::JobResult explainProcess( const QObject* parent, int errorCode, const QString& command, const QString& output, int timeout ); + + /// @brief Convenience wrapper for explainProcess() + inline Calamares::JobResult explainProcess( const QObject* parent, const QString& command, int timeout ) const + { + return explainProcess( parent, getExitCode(), command, getOutput(), timeout ); + } + + /// @brief Convenience wrapper for explainProcess() + inline Calamares::JobResult explainProcess( const QObject* parent, const QStringList& command, int timeout ) const + { + return explainProcess( parent, getExitCode(), command.join( ' ' ), getOutput(), timeout ); + } } ; /** @@ -71,15 +104,20 @@ public: const QString& options = QString() ); + /** (Typed) Boolean describing where a particular command should be run, + * whether in the host (live) system or in the (chroot) target system. + */ + enum class RunLocation { RunInHost, RunInTarget }; + /** * Runs the specified command in the chroot of the target system. * @param args the command with arguments, as a string list. * @param workingPath the current working directory for the QProcess - * call (optional). + * call (optional). * @param stdInput the input string to send to the running process as - * standard input (optional). + * standard input (optional). * @param timeoutSec the timeout after which the process will be - * killed (optional, default is 0 i.e. no timeout). + * killed (optional, default is 0 i.e. no timeout). * * @returns the program's exit code and its output (if any). Special * exit codes (which will never have any output) are: @@ -88,12 +126,32 @@ public: * -3 = bad arguments * -4 = QProcess timeout */ - DLLEXPORT ProcessResult targetEnvCommand( + static DLLEXPORT ProcessResult runCommand( + RunLocation location, const QStringList &args, const QString& workingPath = QString(), const QString& stdInput = QString(), int timeoutSec = 0 ); + /** @brief Convenience wrapper for runCommand(). + * Runs the command in the location specified through the boolean + * doChroot(), which is what you usually want for running commands + * during installation. + */ + inline ProcessResult targetEnvCommand( + const QStringList &args, + const QString& workingPath = QString(), + const QString& stdInput = QString(), + int timeoutSec = 0 ) + { + return runCommand( + m_doChroot ? RunLocation::RunInTarget : RunLocation::RunInHost, + args, + workingPath, + stdInput, + timeoutSec ); + } + /** @brief Convenience wrapper for targetEnvCommand() which returns only the exit code */ inline int targetEnvCall( const QStringList& args, const QString& workingPath = QString(),