diff --git a/CHANGES b/CHANGES index cf963361c..5fdba303f 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,26 @@ contributors are listed. Note that Calamares does not have a historical changelog -- this log starts with version 3.2.0. The release notes on the website will have to do for older versions. +# 3.2.10 (unreleased) # + +This release contains contributions from (alphabetically by first name): + +## Core ## + + - With this release, option *WITH_PYTHONQT* changes default to **off**. + There does not seem to be any serious use of the PythonQt API and + the UI opportunities it offers, so begin the process of deprecating + and removing that. Sometime in the future, QML pages will fill the + gap for easily-prototyped-yet-slick UI elements. + - A crash when no *finished* page (or rather, no page at all) is + configured after the last *exec* section of the sequence has been + solved. The *finished* page can be left out (but then you don't get + the restart-now functionality). + +## Modules ## + + + # 3.2.9 (2019-06-03) # This release contains contributions from (alphabetically by first name): diff --git a/CMakeLists.txt b/CMakeLists.txt index 8dce0c904..cd3d73a28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,10 +37,10 @@ cmake_minimum_required( VERSION 3.2 FATAL_ERROR ) project( CALAMARES - VERSION 3.2.9 + VERSION 3.2.10 LANGUAGES C CXX ) -set( CALAMARES_VERSION_RC 0 ) # Set to 0 during release cycle, 1 during development +set( CALAMARES_VERSION_RC 1 ) # Set to 0 during release cycle, 1 during development ### OPTIONS # @@ -48,7 +48,7 @@ option( INSTALL_CONFIG "Install configuration files" OFF ) option( INSTALL_POLKIT "Install Polkit configuration" ON ) option( BUILD_TESTING "Build the testing tree." ON ) option( WITH_PYTHON "Enable Python modules API (requires Boost.Python)." ON ) -option( WITH_PYTHONQT "Enable next generation Python modules API (experimental, requires PythonQt)." ON ) +option( WITH_PYTHONQT "Enable next generation Python modules API (experimental, requires PythonQt)." OFF ) option( WITH_KF5Crash "Enable crash reporting with KCrash." ON ) diff --git a/lang/calamares_es_MX.ts b/lang/calamares_es_MX.ts index 5b1556a12..f3411597f 100644 --- a/lang/calamares_es_MX.ts +++ b/lang/calamares_es_MX.ts @@ -854,17 +854,17 @@ El instalador terminará y se perderán todos los cambios. Deactivate volume group named %1. - + Desactivar el grupo de volúmenes llamado%1. Deactivate volume group named <strong>%1</strong>. - + Desactivar el grupo de volúmenes llamado<strong>% 1</strong>. The installer failed to deactivate a volume group named %1. - + El instalador no pudo desactivar un grupo de volúmenes llamado%1. @@ -1098,7 +1098,7 @@ El instalador terminará y se perderán todos los cambios. <Restart checkbox tooltip> - + <Restart checkbox tooltip> @@ -1108,12 +1108,12 @@ El instalador terminará y se perderán todos los cambios. <h1>All done.</h1><br/>%1 has been set up on your computer.<br/>You may now start using your new system. - + <h1>Todo listo.</h1><br/>% 1 se ha configurado en su computadora. <br/>Ahora puede comenzar a usar su nuevo sistema. <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the setup program.</p></body></html> - + <html><head/><body><p>Cuando esta casilla está marcada, su sistema se reiniciará inmediatamente cuando haga clic en <span style="font-style:italic;">Listo</span> o cierre el programa de instalación.</p></body></html> diff --git a/lang/calamares_fi_FI.ts b/lang/calamares_fi_FI.ts index e85ee3b06..c2868130d 100644 --- a/lang/calamares_fi_FI.ts +++ b/lang/calamares_fi_FI.ts @@ -63,7 +63,7 @@ GlobalStorage - + Globaali-tallennus @@ -1392,63 +1392,63 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. <strong>%1 driver</strong><br/>by %2 %1 is an untranslatable product name, example: Creative Audigy driver - + <strong>%1 ajuri</strong><br/>- %2 <strong>%1 graphics driver</strong><br/><font color="Grey">by %2</font> %1 is usually a vendor name, example: Nvidia graphics driver - + <strong>%1 näytönohjaimet</strong><br/><font color="Grey">- %2</font> <strong>%1 browser plugin</strong><br/><font color="Grey">by %2</font> - + <strong>%1 selaimen laajennus</strong><br/><font color="Grey">- %2</font> <strong>%1 codec</strong><br/><font color="Grey">by %2</font> - + <strong>%1 kodekki</strong><br/><font color="Grey">- %2</font> <strong>%1 package</strong><br/><font color="Grey">by %2</font> - + <strong>%1 paketti</strong><br/><font color="Grey">- %2</font> <strong>%1</strong><br/><font color="Grey">by %2</font> - + <strong>%1</strong><br/><font color="Grey">- %2</font> Shows the complete license text - + Näyttää täydellisen lisenssin tekstin Hide license text - + Piilota lisenssin teksti Show license agreement - + Näytä lisenssisopimus Hide license agreement - + Piilota lisenssisopimus Opens the license agreement in a browser window. - + Avaa lisenssisopimus selaimessa. <a href="%1">View license agreement</a> - + <a href="%1">Näytä lisenssisopimus</a> @@ -1456,12 +1456,12 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. The system language will be set to %1. - + Järjestelmän kielen asetuksena on %1. The numbers and dates locale will be set to %1. - + Numerot ja päivämäärät, paikallinen asetus on %1. @@ -1513,12 +1513,12 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. Network Installation. (Disabled: Unable to fetch package lists, check your network connection) - + Verkkoasennus. (Ei käytössä: Pakettiluetteloita ei voi hakea, tarkista verkkoyhteys) Network Installation. (Disabled: Received invalid groups data) - + Verkkoasennus. (Ei käytössä: Vastaanotettiin virheellisiä ryhmän tietoja) @@ -1534,17 +1534,17 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. Ba&tch: - + Ba&tch: <html><head/><body><p>Enter a batch-identifier here. This will be stored in the target system.</p></body></html> - + <html><head/><body><p>Syötä erän tunniste tähän. Tämä tallennetaan kohdejärjestelmään.</p></body></html> <html><head/><body><h1>OEM Configuration</h1><p>Calamares will use OEM settings while configuring the target system.</p></body></html> - + <html><head/><body><h1>OEM asetukset</h1><p>Calamares käyttää OEM-asetuksia määritettäessä kohdejärjestelmää.</p></body></html> @@ -1557,7 +1557,7 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. Set the OEM Batch Identifier to <code>%1</code>. - + Aseta OEM valmistajan erän tunnus <code>%1</code>. @@ -1580,92 +1580,92 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. Memory allocation error when setting '%1' - + Muistin varausvirhe asetettaessa '%1' Memory allocation error - + Muistin varausvirhe The password is the same as the old one - + Salasana on sama kuin vanha The password is a palindrome - + Salasana on palindromi The password differs with case changes only - + Salasana eroaa vain vähäisin muutoksin The password is too similar to the old one - + Salasana on liian samanlainen kuin vanha The password contains the user name in some form - + Salasana sisältää jonkin käyttäjänimen The password contains words from the real name of the user in some form - + Salasana sisältää sanoja käyttäjän todellisesta nimestä jossain muodossa The password contains forbidden words in some form - + Salasana sisältää kiellettyjä sanoja The password contains less than %1 digits - + Salasana sisältää vähemmän kuin %1 numeroa The password contains too few digits - + Salasana sisältää liian vähän numeroita The password contains less than %1 uppercase letters - + Salasana sisältää vähemmän kuin %1 isoja kirjaimia The password contains too few uppercase letters - + Salasana sisältää liian vähän isoja kirjaimia The password contains less than %1 lowercase letters - + Salasana sisältää vähemmän kuin %1 pieniä kirjaimia The password contains too few lowercase letters - + Salasana sisältää liian vähän pieniä kirjaimia The password contains less than %1 non-alphanumeric characters - + Salasanassa on vähemmän kuin %1 erikoismerkkiä The password contains too few non-alphanumeric characters - + Salasana sisältää liian vähän erikoismerkkejä The password is shorter than %1 characters - + Salasana on lyhyempi kuin %1 merkkiä @@ -1675,47 +1675,47 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. The password is just rotated old one - + Salasana on vain vanhan pyöritystä The password contains less than %1 character classes - + Salasana sisältää vähemmän kuin %1 merkkiluokkaa The password does not contain enough character classes - + Salasana ei sisällä tarpeeksi merkkiluokkia The password contains more than %1 same characters consecutively - + Salasana sisältää enemmän kuin %1 samaa merkkiä peräkkäin The password contains too many same characters consecutively - + Salasana sisältää liian monta samaa merkkiä peräkkäin The password contains more than %1 characters of the same class consecutively - + Salasana sisältää enemmän kuin %1 merkkiä samasta luokasta peräkkäin The password contains too many characters of the same class consecutively - + Salasana sisältää liian monta saman luokan merkkiä peräkkäin The password contains monotonic sequence longer than %1 characters - + Salasana sisältää monotonisen merkkijonon, joka on pidempi kuin %1 merkkiä The password contains too long of a monotonic character sequence - + Salasanassa on liian pitkä monotoninen merkkijono @@ -1725,72 +1725,72 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. Cannot obtain random numbers from the RNG device - + Satunnaislukuja ei voi saada RNG-laitteesta Password generation failed - required entropy too low for settings - + Salasanojen luonti epäonnistui - pakollinen vähimmäistaso liian alhainen asetuksia varten The password fails the dictionary check - %1 - + Salasana epäonnistui sanaston tarkistuksessa -%1 The password fails the dictionary check - + Salasana epäonnistui sanaston tarkistuksessa Unknown setting - %1 - + Tuntematon asetus - %1 Unknown setting - + Tuntematon asetus Bad integer value of setting - %1 - + Asetuksen virheellinen kokonaisluku - %1 Bad integer value - + Virheellinen kokonaisluku Setting %1 is not of integer type - + Asetus %1 ei ole kokonaisluku Setting is not of integer type - + Asetus ei ole kokonaisluku Setting %1 is not of string type - + Asetus %1 ei ole merkkijono Setting is not of string type - + Asetus ei ole merkkijono Opening the configuration file failed - + Määritystiedoston avaaminen epäonnistui The configuration file is malformed - + Määritystiedosto on väärin muotoiltu @@ -1861,12 +1861,12 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. Log in automatically without asking for the password. - + Kirjaudu automaattisesti ilman salasanaa. Use the same password for the administrator account. - + Käytä pääkäyttäjän tilillä samaa salasanaa. @@ -1968,7 +1968,7 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. Storage de&vice: - + Tallennus&laite: @@ -1983,7 +1983,7 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. Cre&ate - + Luo& @@ -1998,27 +1998,27 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. New Volume Group - + Uusi aseman ryhmä Resize Volume Group - + Muuta kokoa aseman-ryhmässä Deactivate Volume Group - + Poista asemaryhmä käytöstä Remove Volume Group - + Poista asemaryhmä I&nstall boot loader on: - + A&senna käynnistyslatain: @@ -2028,12 +2028,12 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. Can not create new partition - + Ei voi luoda uutta osiota The partition table on %1 already has %2 primary partitions, and no more can be added. Please remove one primary partition and add an extended partition, instead. - + %1 osio-taulukossa on jo %2 ensisijaista osiota, eikä sitä voi lisätä. Poista yksi ensisijainen osio ja lisää laajennettu osio. @@ -2518,7 +2518,7 @@ Ulostulo: Resize Volume Group - + Muuta kokoa aseman-ryhmässä diff --git a/lang/python/fi_FI/LC_MESSAGES/python.mo b/lang/python/fi_FI/LC_MESSAGES/python.mo index cc21c37d4..02ef2d1f4 100644 Binary files a/lang/python/fi_FI/LC_MESSAGES/python.mo and b/lang/python/fi_FI/LC_MESSAGES/python.mo differ diff --git a/lang/python/fi_FI/LC_MESSAGES/python.po b/lang/python/fi_FI/LC_MESSAGES/python.po index 3905c909a..4348bb437 100644 --- a/lang/python/fi_FI/LC_MESSAGES/python.po +++ b/lang/python/fi_FI/LC_MESSAGES/python.po @@ -120,7 +120,7 @@ msgstr "" #: src/modules/unpackfs/main.py:326 msgid "Bad mount point for root partition" -msgstr "" +msgstr "Huono kiinnityspiste root-osioon" #: src/modules/unpackfs/main.py:327 msgid "rootMountPoint is \"{}\", which does not exist, doing nothing" @@ -129,7 +129,7 @@ msgstr "" #: src/modules/unpackfs/main.py:340 src/modules/unpackfs/main.py:347 #: src/modules/unpackfs/main.py:352 msgid "Bad unsquash configuration" -msgstr "" +msgstr "Huono epäpuhdas kokoonpano" #: src/modules/unpackfs/main.py:341 msgid "The filesystem for \"{}\" ({}) is not supported" @@ -169,19 +169,19 @@ msgstr "" #: src/modules/displaymanager/main.py:602 msgid "Cannot configure LightDM" -msgstr "" +msgstr "LightDM määritysvirhe" #: src/modules/displaymanager/main.py:603 msgid "No LightDM greeter installed." -msgstr "" +msgstr "LightDM ei ole asennettu." #: src/modules/displaymanager/main.py:634 msgid "Cannot write SLIM configuration file" -msgstr "" +msgstr "SLIM-määritystiedostoa ei voi kirjoittaa" #: src/modules/displaymanager/main.py:635 msgid "SLIM config file {!s} does not exist" -msgstr "" +msgstr "SLIM-määritystiedostoa {!s} ei ole olemassa" #: src/modules/displaymanager/main.py:750 msgid "No display managers selected for the displaymanager module." @@ -195,11 +195,11 @@ msgstr "" #: src/modules/displaymanager/main.py:831 msgid "Display manager configuration was incomplete" -msgstr "" +msgstr "Näytönhallinnan kokoonpano oli puutteellinen" #: src/modules/initcpiocfg/main.py:36 msgid "Configuring mkinitcpio." -msgstr "" +msgstr "Määritetään mkinitcpio." #: src/modules/initcpiocfg/main.py:192 #: src/modules/luksopenswaphookcfg/main.py:100 @@ -215,7 +215,7 @@ msgstr "" #: src/modules/initcpio/main.py:47 msgid "Process Failed" -msgstr "" +msgstr "Prosessi epäonnistui" #: src/modules/initcpio/main.py:48 msgid "" @@ -229,7 +229,7 @@ msgstr "" #: src/modules/rawfs/main.py:35 msgid "Installing data." -msgstr "" +msgstr "Asennetaan tietoja." #: src/modules/services-openrc/main.py:38 msgid "Configure OpenRC services" diff --git a/src/libcalamares/JobQueue.cpp b/src/libcalamares/JobQueue.cpp index 6ef055ffc..3a76aa099 100644 --- a/src/libcalamares/JobQueue.cpp +++ b/src/libcalamares/JobQueue.cpp @@ -44,7 +44,7 @@ public: } virtual ~JobThread() override; - + void setJobs( const JobList& jobs ) { m_jobs = jobs; @@ -157,6 +157,14 @@ JobQueue::JobQueue( QObject* parent ) JobQueue::~JobQueue() { + if ( m_thread->isRunning() ) + { + m_thread->terminate(); + if ( !m_thread->wait(300) ) + cError() << "Could not terminate job thread (expect a crash now)."; + delete m_thread; + } + delete m_storage; } diff --git a/src/libcalamares/ProcessJob.cpp b/src/libcalamares/ProcessJob.cpp index 3cf4eec49..47fcee05d 100644 --- a/src/libcalamares/ProcessJob.cpp +++ b/src/libcalamares/ProcessJob.cpp @@ -48,10 +48,8 @@ ProcessJob::~ProcessJob() QString ProcessJob::prettyName() const { - //TODO: show something more meaningful - return tr( "Run command %1 %2" ) - .arg( m_command ) - .arg( m_runInChroot ? "in chroot." : " ." ); + return ( m_runInChroot ? tr( "Run command '%1' in target system." ) : tr( " Run command '%1'." ) ) + .arg( m_command ); } @@ -67,83 +65,23 @@ ProcessJob::prettyStatusMessage() const JobResult ProcessJob::exec() { - int ec = 0; - QString output; + using CalamaresUtils::System; + if ( m_runInChroot ) - ec = CalamaresUtils::System::instance()-> - targetEnvOutput( m_command, - output, + return CalamaresUtils::System::instance()-> + targetEnvCommand( { m_command }, m_workingPath, QString(), - m_timeoutSec ); + m_timeoutSec ) + .explainProcess( m_command, m_timeoutSec ); else - ec = callOutput( m_command, - output, - m_workingPath, - QString(), - m_timeoutSec ); - - return CalamaresUtils::ProcessResult::explainProcess( ec, m_command, output, m_timeoutSec ); -} - - -int -ProcessJob::callOutput( const QString& command, - QString& output, - const QString& workingPath, - const QString& stdInput, - int timeoutSec ) -{ - output.clear(); - - QProcess process; - process.setProgram( "/bin/sh" ); - process.setArguments( { "-c", command } ); - process.setProcessChannelMode( QProcess::MergedChannels ); - - if ( !workingPath.isEmpty() ) - { - if ( QDir( workingPath ).exists() ) - process.setWorkingDirectory( QDir( workingPath ).absolutePath() ); - else - { - cWarning() << "Invalid working directory:" << workingPath; - return -3; - } - } - - cDebug() << "Running" << command; - process.start(); - if ( !process.waitForStarted() ) - { - cWarning() << "Process failed to start" << process.error(); - return -2; - } - - if ( !stdInput.isEmpty() ) - { - process.write( stdInput.toLocal8Bit() ); - process.closeWriteChannel(); - } - - if ( !process.waitForFinished( timeoutSec ? ( timeoutSec * 1000 ) : -1 ) ) - { - cWarning() << "Timed out. output so far:"; - output.append( QString::fromLocal8Bit( process.readAllStandardOutput() ).trimmed() ); - cWarning() << output; - return -4; - } - - output.append( QString::fromLocal8Bit( process.readAllStandardOutput() ).trimmed() ); - - if ( process.exitStatus() == QProcess::CrashExit ) - { - cWarning() << "Process crashed"; - return -1; - } - - cDebug() << "Finished. Exit code:" << process.exitCode(); - return process.exitCode(); + return + System::runCommand( System::RunLocation::RunInHost, + { "/bin/sh", "-c", m_command }, + m_workingPath, + QString(), + m_timeoutSec ) + .explainProcess( m_command, m_timeoutSec ); } } // namespace Calamares diff --git a/src/libcalamares/ProcessJob.h b/src/libcalamares/ProcessJob.h index d01dbb676..224ebdaf0 100644 --- a/src/libcalamares/ProcessJob.h +++ b/src/libcalamares/ProcessJob.h @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014, Teo Mrnjavac - * Copyright 2017-2018, Adriaan de Groot + * Copyright 2017-2019, 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 @@ -40,11 +40,6 @@ public: JobResult exec() override; private: - int callOutput( const QString& command, - QString& output, - const QString& workingPath = QString(), - const QString& stdInput = QString(), - int timeoutSec = 0 ); QString m_command; QString m_workingPath; bool m_runInChroot; diff --git a/src/libcalamares/Tests.cpp b/src/libcalamares/Tests.cpp index 615cb51a7..3b7624537 100644 --- a/src/libcalamares/Tests.cpp +++ b/src/libcalamares/Tests.cpp @@ -18,9 +18,12 @@ #include "Tests.h" +#include "utils/CalamaresUtilsSystem.h" #include "utils/Logger.h" #include "utils/Yaml.h" +#include + #include QTEST_GUILESS_MAIN( LibCalamaresTests ) @@ -113,3 +116,45 @@ LibCalamaresTests::testLoadSaveYamlExtended() } QFile::remove( "out.yaml" ); } + +void +LibCalamaresTests::testCommands() +{ + using CalamaresUtils::System; + auto r = System::runCommand( + System::RunLocation::RunInHost, + { "/bin/ls", "/tmp" } + ); + + QVERIFY( r.getExitCode() == 0 ); + + QTemporaryFile tf( "/tmp/calamares-test-XXXXXX" ); + QVERIFY( tf.open() ); + QVERIFY( !tf.fileName().isEmpty() ); + + QFileInfo tfn( tf.fileName() ); + QVERIFY( !r.getOutput().contains( tfn.fileName() ) ); + + // Run ls again, now that the file exists + r = System::runCommand( + System::RunLocation::RunInHost, + { "/bin/ls", "/tmp" } + ); + QVERIFY( r.getOutput().contains( tfn.fileName() ) ); + + // .. and without a working directory set, assume builddir != /tmp + r = System::runCommand( + System::RunLocation::RunInHost, + { "/bin/ls" } + ); + QVERIFY( !r.getOutput().contains( tfn.fileName() ) ); + + r = System::runCommand( + System::RunLocation::RunInHost, + { "/bin/ls" }, + "/tmp" + ); + QVERIFY( r.getOutput().contains( tfn.fileName() ) ); + + +} diff --git a/src/libcalamares/Tests.h b/src/libcalamares/Tests.h index 8d0aee1ff..5cdb3912b 100644 --- a/src/libcalamares/Tests.h +++ b/src/libcalamares/Tests.h @@ -34,6 +34,8 @@ private Q_SLOTS: void testLoadSaveYaml(); // Just settings.conf void testLoadSaveYamlExtended(); // Do a find() in the src dir + + void testCommands(); }; #endif diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 1b603a7e7..5990fbc42 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -114,14 +114,24 @@ System::mount( const QString& devicePath, const QString& options ) { if ( devicePath.isEmpty() || mountPoint.isEmpty() ) - return -3; + { + if ( devicePath.isEmpty() ) + cWarning() << "Can't mount an empty device."; + if ( mountPoint.isEmpty() ) + cWarning() << "Can't mount on an empty mountpoint."; + + return static_cast(ProcessResult::Code::NoWorkingDirectory); + } QDir mountPointDir( mountPoint ); if ( !mountPointDir.exists() ) { bool ok = mountPointDir.mkpath( mountPoint ); if ( !ok ) - return -3; + { + cWarning() << "Could not create mountpoint" << mountPoint; + return static_cast(ProcessResult::Code::NoWorkingDirectory); + } } QString program( "mount" ); @@ -146,15 +156,13 @@ System::runCommand( { QString output; - if ( !Calamares::JobQueue::instance() ) - return -3; + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); if ( ( location == System::RunLocation::RunInTarget ) && ( !gs || !gs->contains( "rootMountPoint" ) ) ) { cWarning() << "No rootMountPoint in global storage"; - return -3; + return ProcessResult::Code::NoWorkingDirectory; } QProcess process; @@ -167,7 +175,7 @@ System::runCommand( if ( !QDir( destDir ).exists() ) { cWarning() << "rootMountPoint points to a dir which does not exist"; - return -3; + return ProcessResult::Code::NoWorkingDirectory; } program = "chroot"; @@ -189,8 +197,10 @@ System::runCommand( if ( QDir( workingPath ).exists() ) process.setWorkingDirectory( QDir( workingPath ).absolutePath() ); else + { cWarning() << "Invalid working directory:" << workingPath; - return -3; + return ProcessResult::Code::NoWorkingDirectory; + } } cDebug() << "Running" << program << RedactedList( arguments ); @@ -198,20 +208,20 @@ System::runCommand( if ( !process.waitForStarted() ) { cWarning() << "Process failed to start" << process.error(); - return -2; + return ProcessResult::Code::FailedToStart; } if ( !stdInput.isEmpty() ) { process.write( stdInput.toLocal8Bit() ); - process.closeWriteChannel(); } + process.closeWriteChannel(); if ( !process.waitForFinished( timeoutSec ? ( timeoutSec * 1000 ) : -1 ) ) { cWarning().noquote().nospace() << "Timed out. Output so far:\n" << process.readAllStandardOutput(); - return -4; + return ProcessResult::Code::TimedOut; } output.append( QString::fromLocal8Bit( process.readAllStandardOutput() ).trimmed() ); @@ -219,12 +229,13 @@ System::runCommand( if ( process.exitStatus() == QProcess::CrashExit ) { cWarning().noquote().nospace() << "Process crashed. Output so far:\n" << output; - return -1; + return ProcessResult::Code::Crashed; } auto r = process.exitCode(); cDebug() << "Finished. Exit code:" << r; - if ( ( r != 0 ) || Calamares::Settings::instance()->debugMode() ) + bool showDebug = ( !Calamares::Settings::instance() ) || ( Calamares::Settings::instance()->debugMode() ); + if ( ( r != 0 ) || showDebug ) { cDebug() << "Target cmd:" << RedactedList( args ); cDebug().noquote().nospace() << "Target output:\n" << output; @@ -306,22 +317,22 @@ ProcessResult::explainProcess( int ec, const QString& command, const QString& ou ? QCoreApplication::translate( "ProcessResult", "\nThere was no output from the command.") : (QCoreApplication::translate( "ProcessResult", "\nOutput:\n") + output); - if ( ec == -1 ) //Crash! + if ( ec == static_cast(ProcessResult::Code::Crashed) ) //Crash! return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command crashed." ), QCoreApplication::translate( "ProcessResult", "Command %1 crashed." ) .arg( command ) + outputMessage ); - if ( ec == -2 ) + if ( ec == static_cast(ProcessResult::Code::FailedToStart) ) return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to start." ), QCoreApplication::translate( "ProcessResult", "Command %1 failed to start." ) .arg( command ) ); - if ( ec == -3 ) + if ( ec == static_cast(ProcessResult::Code::NoWorkingDirectory) ) return JobResult::error( QCoreApplication::translate( "ProcessResult", "Internal error when starting command." ), QCoreApplication::translate( "ProcessResult", "Bad parameters for process job call." ) ); - if ( ec == -4 ) + if ( ec == static_cast(ProcessResult::Code::TimedOut) ) return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to finish." ), QCoreApplication::translate( "ProcessResult", "Command %1 failed to finish in %2 seconds." ) .arg( command ) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.h b/src/libcalamares/utils/CalamaresUtilsSystem.h index 6809859ee..c17d52e93 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.h +++ b/src/libcalamares/utils/CalamaresUtilsSystem.h @@ -32,8 +32,16 @@ namespace CalamaresUtils class ProcessResult : public QPair< int, QString > { public: + enum class Code : int + { + Crashed = -1, // Must match special return values from QProcess + FailedToStart = -2, // Must match special return values from QProcess + NoWorkingDirectory = -3, + TimedOut = -4 + } ; + /** @brief Implicit one-argument constructor has no output, only a return code */ - ProcessResult( int r ) : QPair< int, QString >( r, QString() ) {} + ProcessResult( Code r ) : QPair< int, QString >( static_cast(r), QString() ) {} ProcessResult( int r, QString s ) : QPair< int, QString >( r, s ) {} int getExitCode() const { return first; } @@ -93,9 +101,9 @@ public: * @param filesystemName the name of the filesystem (optional). * @param options any additional options as passed to mount -o (optional). * @returns the program's exit code, or: - * -1 = QProcess crash - * -2 = QProcess cannot start - * -3 = bad arguments + * Crashed = QProcess crash + * FailedToStart = QProcess cannot start + * NoWorkingDirectory = bad arguments */ DLLEXPORT int mount( const QString& devicePath, const QString& mountPoint, @@ -120,10 +128,10 @@ public: * * @returns the program's exit code and its output (if any). Special * exit codes (which will never have any output) are: - * -1 = QProcess crash - * -2 = QProcess cannot start - * -3 = bad arguments - * -4 = QProcess timeout + * Crashed = QProcess crash + * FailedToStart = QProcess cannot start + * NoWorkingDirectory = bad arguments + * TimedOut = QProcess timeout */ static DLLEXPORT ProcessResult runCommand( RunLocation location, diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index 508581b4e..3a5d24feb 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -283,18 +283,35 @@ ViewManager::next() } m_currentStep++; - m_stack->setCurrentIndex( m_currentStep ); + + m_stack->setCurrentIndex( m_currentStep ); // Does nothing if out of range step->onLeave(); - m_steps.at( m_currentStep )->onActivate(); - executing = qobject_cast< ExecutionViewStep* >( m_steps.at( m_currentStep ) ) != nullptr; - emit currentStepChanged(); + + if ( m_currentStep < m_steps.count() ) + { + m_steps.at( m_currentStep )->onActivate(); + executing = qobject_cast< ExecutionViewStep* >( m_steps.at( m_currentStep ) ) != nullptr; + emit currentStepChanged(); + } + else + { + // Reached the end in a weird state (e.g. no finished step after an exec) + executing = false; + m_next->setEnabled( false ); + m_back->setEnabled( false ); + } updateCancelEnabled( !settings->disableCancel() && !(executing && settings->disableCancelDuringExec() ) ); } else + { step->next(); + } - m_next->setEnabled( !executing && m_steps.at( m_currentStep )->isNextEnabled() ); - m_back->setEnabled( !executing && m_steps.at( m_currentStep )->isBackEnabled() ); + if ( m_currentStep < m_steps.count() ) + { + m_next->setEnabled( !executing && m_steps.at( m_currentStep )->isNextEnabled() ); + m_back->setEnabled( !executing && m_steps.at( m_currentStep )->isBackEnabled() ); + } updateButtonLabels(); } @@ -320,7 +337,7 @@ ViewManager::updateButtonLabels() else m_next->setText( tr( "&Next" ) ); - if ( m_currentStep == m_steps.count() -1 && m_steps.last()->isAtEnd() ) + if ( isAtVeryEnd() ) { m_quit->setText( tr( "&Done" ) ); m_quit->setToolTip( complete ); @@ -368,7 +385,7 @@ bool ViewManager::confirmCancelInstallation() const auto* const settings = Calamares::Settings::instance(); // When we're at the very end, then it's always OK to exit. - if ( m_currentStep == m_steps.count() -1 && m_steps.last()->isAtEnd() ) + if ( isAtVeryEnd() ) return true; // Not at the very end, cancel/quit might be disabled diff --git a/src/libcalamaresui/ViewManager.h b/src/libcalamaresui/ViewManager.h index 50e8d1dc4..c9f554ee8 100644 --- a/src/libcalamaresui/ViewManager.h +++ b/src/libcalamaresui/ViewManager.h @@ -130,7 +130,12 @@ private: void insertViewStep( int before, ViewStep* step ); void updateButtonLabels(); void updateCancelEnabled( bool enabled ); - + + bool isAtVeryEnd() const + { + return ( m_currentStep >= m_steps.count() ) || ( m_currentStep == m_steps.count() - 1 && m_steps.last()->isAtEnd() ); + } + static ViewManager* s_instance; ViewStepList m_steps; diff --git a/src/modules/dummypythonqt/lang/be/LC_MESSAGES/dummypythonqt.mo b/src/modules/dummypythonqt/lang/be/LC_MESSAGES/dummypythonqt.mo index 42cb16abd..2a7ecc372 100644 Binary files a/src/modules/dummypythonqt/lang/be/LC_MESSAGES/dummypythonqt.mo and b/src/modules/dummypythonqt/lang/be/LC_MESSAGES/dummypythonqt.mo differ diff --git a/src/modules/dummypythonqt/lang/be/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/be/LC_MESSAGES/dummypythonqt.po index 0c0d09be7..c14151114 100644 --- a/src/modules/dummypythonqt/lang/be/LC_MESSAGES/dummypythonqt.po +++ b/src/modules/dummypythonqt/lang/be/LC_MESSAGES/dummypythonqt.po @@ -4,16 +4,16 @@ # FIRST AUTHOR , YEAR. # # Translators: -# Zmicer Turok , 2018 +# Zmicer Turok , 2018 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" +"POT-Creation-Date: 2019-05-10 19:18-0400\n" "PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Zmicer Turok , 2018\n" +"Last-Translator: Zmicer Turok , 2018\n" "Language-Team: Belarusian (https://www.transifex.com/calamares/teams/20061/be/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n"