Merge branch 'master' of https://github.com/calamares/calamares into development

This commit is contained in:
Philip Müller 2019-08-06 13:02:38 +02:00
commit 1d8938cc28
61 changed files with 1325 additions and 1151 deletions

View File

@ -2,6 +2,7 @@
BasedOnStyle: WebKit BasedOnStyle: WebKit
AlignAfterOpenBracket: Align AlignAfterOpenBracket: Align
AlignEscapedNewlines: Left
AllowAllParametersOfDeclarationOnNextLine: 'false' AllowAllParametersOfDeclarationOnNextLine: 'false'
AllowShortFunctionsOnASingleLine: Inline AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: 'false' AllowShortIfStatementsOnASingleLine: 'false'

View File

@ -35,7 +35,7 @@
# One special target is "show-version", which can be built # One special target is "show-version", which can be built
# to obtain the version number from here. # to obtain the version number from here.
cmake_minimum_required( VERSION 3.2 FATAL_ERROR ) cmake_minimum_required( VERSION 3.3 FATAL_ERROR )
project( CALAMARES project( CALAMARES
VERSION 3.2.12 VERSION 3.2.12
LANGUAGES C CXX ) LANGUAGES C CXX )
@ -96,10 +96,10 @@ set( CALAMARES_DESCRIPTION_SUMMARY
# (sr@latin in particular) may need special handling in CalamaresUtils.cpp. # (sr@latin in particular) may need special handling in CalamaresUtils.cpp.
# #
# TODO: drop the es_ES translation from Transifex # TODO: drop the es_ES translation from Transifex
# TODO: move eo (Esperanto) to _ok once Qt can actually create a
# locale for it.
# #
# NOTE: when updating the list from Transifex, copy these four lines # NOTE: move eo (Esperanto) to _ok once Qt can actually create a
# locale for it. (Qt 5.12.2 can, see check later on).
# NOTE: update these lines by running txstats.py, or copy these four lines
# and prefix each variable name with "p", so that the automatic # and prefix each variable name with "p", so that the automatic
# checks for new languages and misspelled ones are done (that is, # checks for new languages and misspelled ones are done (that is,
# copy these four lines to four backup lines, add "p", and then update # copy these four lines to four backup lines, add "p", and then update
@ -128,6 +128,10 @@ set( BOOSTPYTHON_VERSION 1.55.0 )
# #
set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules" ) set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules" )
# Enable IN_LIST
if( POLICY CMP0057 )
cmake_policy( SET CMP0057 NEW )
endif()
# CMake 3.9, 3.10 compatibility # CMake 3.9, 3.10 compatibility
if( POLICY CMP0071 ) if( POLICY CMP0071 )
cmake_policy( SET CMP0071 NEW ) cmake_policy( SET CMP0071 NEW )
@ -249,6 +253,15 @@ include( CMakeColors )
### DEPENDENCIES ### DEPENDENCIES
# #
find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Concurrent Core Gui Widgets LinguistTools Svg Quick QuickWidgets ) find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Concurrent Core Gui Widgets LinguistTools Svg Quick QuickWidgets )
if( Qt5_VERSION VERSION_GREATER 5.12.1 )
# At least Qt 5.12.2 seems to support Esperanto in QLocale
if( "eo" IN_LIST _tx_incomplete )
message(STATUS "Esperanto support since Qt 5.12.2, enabling Esperanto locale")
list( REMOVE_ITEM _tx_incomplete "eo" )
list( APPEND _tx_ok "eo" )
endif()
endif()
find_package( YAMLCPP ${YAMLCPP_VERSION} REQUIRED ) find_package( YAMLCPP ${YAMLCPP_VERSION} REQUIRED )
if( INSTALL_POLKIT ) if( INSTALL_POLKIT )
find_package( PolkitQt5-1 REQUIRED ) find_package( PolkitQt5-1 REQUIRED )

View File

@ -37,7 +37,7 @@ style_some()
if test "x$any_dirs" = "xyes" ; then if test "x$any_dirs" = "xyes" ; then
for d in "$@" for d in "$@"
do do
if test -d "$@" ; then if test -d "$d" ; then
style_some $( find "$d" -maxdepth 1 -type f -name '*.cpp' -o -name '*.h' ) style_some $( find "$d" -maxdepth 1 -type f -name '*.cpp' -o -name '*.h' )
else else
style_some "$d" style_some "$d"

View File

@ -24,11 +24,11 @@ namespace Calamares
CppJob::CppJob( QObject* parent ) CppJob::CppJob( QObject* parent )
: Job( parent ) : Job( parent )
{} {
}
CppJob::~CppJob() CppJob::~CppJob() {}
{}
void void
@ -44,4 +44,4 @@ CppJob::setConfigurationMap( const QVariantMap& configurationMap )
Q_UNUSED( configurationMap ) Q_UNUSED( configurationMap )
} }
} } // namespace Calamares

View File

@ -45,6 +45,6 @@ protected:
QString m_instanceKey; QString m_instanceKey;
}; };
} } // namespace Calamares
#endif // CALAMARES_CPPJOB_H #endif // CALAMARES_CPPJOB_H

View File

@ -21,8 +21,8 @@
#include "JobQueue.h" #include "JobQueue.h"
#include "utils/Logger.h" #include "utils/Logger.h"
#include "utils/Yaml.h"
#include "utils/Units.h" #include "utils/Units.h"
#include "utils/Yaml.h"
#include <QFile> #include <QFile>
#include <QJsonDocument> #include <QJsonDocument>
@ -40,7 +40,8 @@ namespace bp = boost::python;
using CalamaresUtils::operator""_MiB; using CalamaresUtils::operator""_MiB;
namespace Calamares { namespace Calamares
{
GlobalStorage::GlobalStorage() GlobalStorage::GlobalStorage()
: QObject( nullptr ) : QObject( nullptr )
@ -106,7 +107,9 @@ GlobalStorage::save(const QString& filename)
{ {
QFile f( filename ); QFile f( filename );
if ( !f.open( QFile::WriteOnly ) ) if ( !f.open( QFile::WriteOnly ) )
{
return false; return false;
}
f.write( QJsonDocument::fromVariant( m ).toJson() ); f.write( QJsonDocument::fromVariant( m ).toJson() );
f.close(); f.close();
@ -118,14 +121,20 @@ GlobalStorage::load( const QString& filename )
{ {
QFile f( filename ); QFile f( filename );
if ( !f.open( QFile::ReadOnly ) ) if ( !f.open( QFile::ReadOnly ) )
{
return false; return false;
}
QJsonParseError e; QJsonParseError e;
QJsonDocument d = QJsonDocument::fromJson( f.read( 1_MiB ), &e ); QJsonDocument d = QJsonDocument::fromJson( f.read( 1_MiB ), &e );
if ( d.isNull() ) if ( d.isNull() )
{
cWarning() << filename << e.errorString(); cWarning() << filename << e.errorString();
}
else if ( !d.isObject() ) else if ( !d.isObject() )
{
cWarning() << filename << "Not suitable JSON."; cWarning() << filename << "Not suitable JSON.";
}
else else
{ {
auto map = d.toVariant().toMap(); auto map = d.toVariant().toMap();
@ -150,7 +159,9 @@ GlobalStorage::loadYaml( const QString& filename )
bool ok = false; bool ok = false;
auto gs = CalamaresUtils::loadYaml( filename, &ok ); auto gs = CalamaresUtils::loadYaml( filename, &ok );
if ( ok ) if ( ok )
{
m = gs; m = gs;
}
return ok; return ok;
} }
@ -194,11 +205,9 @@ GlobalStoragePythonWrapper::count() const
void void
GlobalStoragePythonWrapper::insert( const std::string& key, GlobalStoragePythonWrapper::insert( const std::string& key, const bp::object& value )
const bp::object& value )
{ {
m_gs->insert( QString::fromStdString( key ), m_gs->insert( QString::fromStdString( key ), CalamaresPython::variantFromPyObject( value ) );
CalamaresPython::variantFromPyObject( value ) );
} }
bp::list bp::list
@ -207,7 +216,9 @@ GlobalStoragePythonWrapper::keys() const
bp::list pyList; bp::list pyList;
const auto keys = m_gs->keys(); const auto keys = m_gs->keys();
for ( const QString& key : keys ) for ( const QString& key : keys )
{
pyList.append( key.toStdString() ); pyList.append( key.toStdString() );
}
return pyList; return pyList;
} }

View File

@ -34,8 +34,8 @@ namespace api
class object; class object;
} }
class list; class list;
} } // namespace python
} } // namespace boost
#endif #endif
namespace Calamares namespace Calamares

View File

@ -84,7 +84,8 @@ JobResult::JobResult( const QString& message, const QString& details, int number
: m_message( message ) : m_message( message )
, m_details( details ) , m_details( details )
, m_number( number ) , m_number( number )
{} {
}
Job::Job( QObject* parent ) Job::Job( QObject* parent )
@ -93,8 +94,7 @@ Job::Job( QObject* parent )
} }
Job::~Job() Job::~Job() {}
{}
qreal qreal

View File

@ -25,7 +25,8 @@
#include <QObject> #include <QObject>
#include <QSharedPointer> #include <QSharedPointer>
namespace Calamares { namespace Calamares
{
class DLLEXPORT JobResult class DLLEXPORT JobResult
{ {

View File

@ -36,7 +36,8 @@ GoodJob::exec()
JobResult JobResult
FailJob::exec() FailJob::exec()
{ {
return JobResult::error( tr( "Job failed (%1)" ).arg( m_name ), tr( "Programmed job failure was explicitly requested." ) ); return JobResult::error( tr( "Job failed (%1)" ).arg( m_name ),
tr( "Programmed job failure was explicitly requested." ) );
} }
} // namespace } // namespace Calamares

View File

@ -21,7 +21,8 @@
#include "Job.h" #include "Job.h"
namespace Calamares { namespace Calamares
{
/** @brief A Job with a name /** @brief A Job with a name
* *
@ -39,6 +40,7 @@ public:
} }
virtual QString prettyName() const override; virtual QString prettyName() const override;
protected: protected:
const QString m_name; const QString m_name;
}; };

View File

@ -19,8 +19,8 @@
#include "JobQueue.h" #include "JobQueue.h"
#include "Job.h"
#include "GlobalStorage.h" #include "GlobalStorage.h"
#include "Job.h"
#include "utils/Logger.h" #include "utils/Logger.h"
#include "CalamaresConfig.h" #include "CalamaresConfig.h"
@ -87,12 +87,18 @@ public:
details = result.details(); details = result.details();
} }
if ( !anyFailed ) if ( !anyFailed )
{
++m_jobIndex; ++m_jobIndex;
} }
}
if ( anyFailed ) if ( anyFailed )
{
emitFailed( message, details ); emitFailed( message, details );
}
else else
{
emitProgress(); emitProgress();
}
emitFinished(); emitFinished();
} }
@ -109,49 +115,39 @@ private:
jobPercent = qBound( qreal( 0 ), jobPercent, qreal( 1 ) ); jobPercent = qBound( qreal( 0 ), jobPercent, qreal( 1 ) );
int jobCount = m_jobs.size(); int jobCount = m_jobs.size();
QString message = m_jobIndex < jobCount QString message = m_jobIndex < jobCount ? m_jobs.at( m_jobIndex )->prettyStatusMessage() : tr( "Done" );
? m_jobs.at( m_jobIndex )->prettyStatusMessage()
: tr( "Done" );
qreal cumulativeProgress = 0.0; qreal cumulativeProgress = 0.0;
for ( auto jobWeight : m_jobWeights.mid( 0, m_jobIndex ) ) for ( auto jobWeight : m_jobWeights.mid( 0, m_jobIndex ) )
{ {
cumulativeProgress += jobWeight; cumulativeProgress += jobWeight;
} }
qreal percent = m_jobIndex < jobCount qreal percent
? cumulativeProgress + ( ( m_jobWeights.at( m_jobIndex ) ) * jobPercent ) = m_jobIndex < jobCount ? cumulativeProgress + ( ( m_jobWeights.at( m_jobIndex ) ) * jobPercent ) : 1.0;
: 1.0;
if ( m_jobIndex < jobCount ) if ( m_jobIndex < jobCount )
{ {
cDebug(Logger::LOGVERBOSE) << "[JOBQUEUE]: Progress for Job[" << m_jobIndex << "]: " << ( jobPercent * 100 ) << "% completed"; cDebug( Logger::LOGVERBOSE ) << "[JOBQUEUE]: Progress for Job[" << m_jobIndex
cDebug(Logger::LOGVERBOSE) << "[JOBQUEUE]: Progress Overall: " << ( cumulativeProgress * 100 ) << "% (accumulated) + " << "]: " << ( jobPercent * 100 ) << "% completed";
<< ( ( ( m_jobWeights.at( m_jobIndex ) ) * jobPercent ) * 100 ) << "% (this job) = " cDebug( Logger::LOGVERBOSE ) << "[JOBQUEUE]: Progress Overall: " << ( cumulativeProgress * 100 )
<< ( percent * 100 ) << "% (total)"; << "% (accumulated) + "
<< ( ( ( m_jobWeights.at( m_jobIndex ) ) * jobPercent ) * 100 )
<< "% (this job) = " << ( percent * 100 ) << "% (total)";
} }
QMetaObject::invokeMethod( m_queue, "progress", Qt::QueuedConnection, QMetaObject::invokeMethod(
Q_ARG( qreal, percent ), m_queue, "progress", Qt::QueuedConnection, Q_ARG( qreal, percent ), Q_ARG( QString, message ) );
Q_ARG( QString, message )
);
} }
void emitFailed( const QString& message, const QString& details ) void emitFailed( const QString& message, const QString& details )
{ {
QMetaObject::invokeMethod( m_queue, "failed", Qt::QueuedConnection, QMetaObject::invokeMethod(
Q_ARG( QString, message ), m_queue, "failed", Qt::QueuedConnection, Q_ARG( QString, message ), Q_ARG( QString, details ) );
Q_ARG( QString, details )
);
} }
void emitFinished() void emitFinished() { QMetaObject::invokeMethod( m_queue, "finished", Qt::QueuedConnection ); }
{
QMetaObject::invokeMethod( m_queue, "finished", Qt::QueuedConnection );
}
}; };
JobThread::~JobThread() JobThread::~JobThread() {}
{
}
JobQueue* JobQueue::s_instance = nullptr; JobQueue* JobQueue::s_instance = nullptr;
@ -187,7 +183,9 @@ JobQueue::~JobQueue()
{ {
m_thread->terminate(); m_thread->terminate();
if ( !m_thread->wait( 300 ) ) if ( !m_thread->wait( 300 ) )
{
cError() << "Could not terminate job thread (expect a crash now)."; cError() << "Could not terminate job thread (expect a crash now).";
}
delete m_thread; delete m_thread;
} }

View File

@ -59,6 +59,6 @@ private:
GlobalStorage* m_storage; GlobalStorage* m_storage;
}; };
} } // namespace Calamares
#endif // CALAMARES_JOBQUEUE_H #endif // CALAMARES_JOBQUEUE_H

View File

@ -25,7 +25,8 @@
#include <QDir> #include <QDir>
#include <QProcess> #include <QProcess>
namespace Calamares { namespace Calamares
{
ProcessJob::ProcessJob( const QString& command, ProcessJob::ProcessJob( const QString& command,
@ -38,27 +39,24 @@ ProcessJob::ProcessJob( const QString& command,
, m_workingPath( workingPath ) , m_workingPath( workingPath )
, m_runInChroot( runInChroot ) , m_runInChroot( runInChroot )
, m_timeoutSec( secondsTimeout ) , m_timeoutSec( secondsTimeout )
{} {
}
ProcessJob::~ProcessJob() ProcessJob::~ProcessJob() {}
{}
QString QString
ProcessJob::prettyName() const ProcessJob::prettyName() const
{ {
return ( m_runInChroot ? tr( "Run command '%1' in target system." ) : tr( " Run command '%1'." ) ) return ( m_runInChroot ? tr( "Run command '%1' in target system." ) : tr( " Run command '%1'." ) ).arg( m_command );
.arg( m_command );
} }
QString QString
ProcessJob::prettyStatusMessage() const ProcessJob::prettyStatusMessage() const
{ {
return tr( "Running command %1 %2" ) return tr( "Running command %1 %2" ).arg( m_command ).arg( m_runInChroot ? "in chroot." : " ." );
.arg( m_command )
.arg( m_runInChroot ? "in chroot." : " ." );
} }
@ -68,15 +66,11 @@ ProcessJob::exec()
using CalamaresUtils::System; using CalamaresUtils::System;
if ( m_runInChroot ) if ( m_runInChroot )
return CalamaresUtils::System::instance()-> return CalamaresUtils::System::instance()
targetEnvCommand( { m_command }, ->targetEnvCommand( { m_command }, m_workingPath, QString(), m_timeoutSec )
m_workingPath,
QString(),
m_timeoutSec )
.explainProcess( m_command, m_timeoutSec ); .explainProcess( m_command, m_timeoutSec );
else else
return return System::runCommand( System::RunLocation::RunInHost,
System::runCommand( System::RunLocation::RunInHost,
{ "/bin/sh", "-c", m_command }, { "/bin/sh", "-c", m_command },
m_workingPath, m_workingPath,
QString(), QString(),

View File

@ -24,7 +24,8 @@
#include <chrono> #include <chrono>
namespace Calamares { namespace Calamares
{
class ProcessJob : public Job class ProcessJob : public Job
{ {

View File

@ -72,26 +72,40 @@ variantFromPyObject( const boost::python::object& pyObject )
{ {
std::string pyType = bp::extract< std::string >( pyObject.attr( "__class__" ).attr( "__name__" ) ); std::string pyType = bp::extract< std::string >( pyObject.attr( "__class__" ).attr( "__name__" ) );
if ( pyType == "dict" ) if ( pyType == "dict" )
{
return variantMapFromPyDict( bp::extract< bp::dict >( pyObject ) ); return variantMapFromPyDict( bp::extract< bp::dict >( pyObject ) );
}
else if ( pyType == "list" ) else if ( pyType == "list" )
{
return variantListFromPyList( bp::extract< bp::list >( pyObject ) ); return variantListFromPyList( bp::extract< bp::list >( pyObject ) );
}
else if ( pyType == "int" ) else if ( pyType == "int" )
{
return QVariant( bp::extract< int >( pyObject ) ); return QVariant( bp::extract< int >( pyObject ) );
}
else if ( pyType == "float" ) else if ( pyType == "float" )
{
return QVariant( bp::extract< double >( pyObject ) ); return QVariant( bp::extract< double >( pyObject ) );
}
else if ( pyType == "str" ) else if ( pyType == "str" )
{
return QVariant( QString::fromStdString( bp::extract< std::string >( pyObject ) ) ); return QVariant( QString::fromStdString( bp::extract< std::string >( pyObject ) ) );
}
else if ( pyType == "bool" ) else if ( pyType == "bool" )
{
return QVariant( bp::extract< bool >( pyObject ) ); return QVariant( bp::extract< bool >( pyObject ) );
}
else else
{
return QVariant(); return QVariant();
} }
}
boost::python::list boost::python::list
@ -99,7 +113,9 @@ variantListToPyList( const QVariantList& variantList )
{ {
bp::list pyList; bp::list pyList;
for ( const QVariant& variant : variantList ) for ( const QVariant& variant : variantList )
{
pyList.append( variantToPyObject( variant ) ); pyList.append( variantToPyObject( variant ) );
}
return pyList; return pyList;
} }
@ -109,7 +125,9 @@ variantListFromPyList( const boost::python::list& pyList )
{ {
QVariantList list; QVariantList list;
for ( int i = 0; i < bp::len( pyList ); ++i ) for ( int i = 0; i < bp::len( pyList ); ++i )
{
list.append( variantFromPyObject( pyList[ i ] ) ); list.append( variantFromPyObject( pyList[ i ] ) );
}
return list; return list;
} }
@ -119,7 +137,9 @@ variantMapToPyDict( const QVariantMap& variantMap )
{ {
bp::dict pyDict; bp::dict pyDict;
for ( auto it = variantMap.constBegin(); it != variantMap.constEnd(); ++it ) for ( auto it = variantMap.constBegin(); it != variantMap.constEnd(); ++it )
{
pyDict[ it.key().toStdString() ] = variantToPyObject( it.value() ); pyDict[ it.key().toStdString() ] = variantToPyObject( it.value() );
}
return pyDict; return pyDict;
} }
@ -152,7 +172,9 @@ variantHashToPyDict( const QVariantHash& variantHash )
{ {
bp::dict pyDict; bp::dict pyDict;
for ( auto it = variantHash.constBegin(); it != variantHash.constEnd(); ++it ) for ( auto it = variantHash.constBegin(); it != variantHash.constEnd(); ++it )
{
pyDict[ it.key().toStdString() ] = variantToPyObject( it.value() ); pyDict[ it.key().toStdString() ] = variantToPyObject( it.value() );
}
return pyDict; return pyDict;
} }
@ -181,18 +203,22 @@ variantHashFromPyDict( const boost::python::dict& pyDict )
} }
Helper* Helper::s_instance = nullptr; Helper* Helper::s_instance = nullptr;
static inline void add_if_lib_exists( const QDir& dir, const char* name, QStringList& list ) static inline void
add_if_lib_exists( const QDir& dir, const char* name, QStringList& list )
{ {
if ( !( dir.exists() && dir.isReadable() ) ) if ( !( dir.exists() && dir.isReadable() ) )
{
return; return;
}
QFileInfo fi( dir.absoluteFilePath( name ) ); QFileInfo fi( dir.absoluteFilePath( name ) );
if ( fi.exists() && fi.isReadable() ) if ( fi.exists() && fi.isReadable() )
{
list.append( fi.dir().absolutePath() ); list.append( fi.dir().absolutePath() );
} }
}
Helper::Helper( QObject* parent ) Helper::Helper( QObject* parent )
: QObject( parent ) : QObject( parent )
@ -201,7 +227,9 @@ Helper::Helper( QObject* parent )
if ( !s_instance ) if ( !s_instance )
{ {
if ( !Py_IsInitialized() ) if ( !Py_IsInitialized() )
{
Py_Initialize(); Py_Initialize();
}
m_mainModule = bp::import( "__main__" ); m_mainModule = bp::import( "__main__" );
m_mainNamespace = m_mainModule.attr( "__dict__" ); m_mainNamespace = m_mainModule.attr( "__dict__" );
@ -209,8 +237,7 @@ Helper::Helper( QObject* parent )
// If we're running from the build dir // If we're running from the build dir
add_if_lib_exists( QDir::current(), "libcalamares.so", m_pythonPaths ); add_if_lib_exists( QDir::current(), "libcalamares.so", m_pythonPaths );
QDir calaPythonPath( CalamaresUtils::systemLibDir().absolutePath() + QDir calaPythonPath( CalamaresUtils::systemLibDir().absolutePath() + QDir::separator() + "calamares" );
QDir::separator() + "calamares" );
add_if_lib_exists( calaPythonPath, "libcalamares.so", m_pythonPaths ); add_if_lib_exists( calaPythonPath, "libcalamares.so", m_pythonPaths );
bp::object sys = bp::import( "sys" ); bp::object sys = bp::import( "sys" );
@ -264,10 +291,14 @@ Helper::handleLastError()
bp::str pystr( h_type ); bp::str pystr( h_type );
bp::extract< std::string > extracted( pystr ); bp::extract< std::string > extracted( pystr );
if ( extracted.check() ) if ( extracted.check() )
{
typeMsg = QString::fromStdString( extracted() ).trimmed(); typeMsg = QString::fromStdString( extracted() ).trimmed();
}
if ( typeMsg.isEmpty() ) if ( typeMsg.isEmpty() )
{
typeMsg = tr( "Unknown exception type" ); typeMsg = tr( "Unknown exception type" );
}
debug << typeMsg << '\n'; debug << typeMsg << '\n';
} }
@ -278,10 +309,14 @@ Helper::handleLastError()
bp::str pystr( h_val ); bp::str pystr( h_val );
bp::extract< std::string > extracted( pystr ); bp::extract< std::string > extracted( pystr );
if ( extracted.check() ) if ( extracted.check() )
{
valMsg = QString::fromStdString( extracted() ).trimmed(); valMsg = QString::fromStdString( extracted() ).trimmed();
}
if ( valMsg.isEmpty() ) if ( valMsg.isEmpty() )
{
valMsg = tr( "unparseable Python error" ); valMsg = tr( "unparseable Python error" );
}
// Special-case: CalledProcessError has an attribute "output" with the command output, // Special-case: CalledProcessError has an attribute "output" with the command output,
// add that to the printed message. // add that to the printed message.
@ -318,22 +353,32 @@ Helper::handleLastError()
bp::object pystr( bp::str( "\n" ).join( tb_list ) ); bp::object pystr( bp::str( "\n" ).join( tb_list ) );
bp::extract< std::string > extracted( pystr ); bp::extract< std::string > extracted( pystr );
if ( extracted.check() ) if ( extracted.check() )
{
tbMsg = QString::fromStdString( extracted() ).trimmed(); tbMsg = QString::fromStdString( extracted() ).trimmed();
}
if ( tbMsg.isEmpty() ) if ( tbMsg.isEmpty() )
{
tbMsg = tr( "unparseable Python traceback" ); tbMsg = tr( "unparseable Python traceback" );
}
debug << tbMsg << '\n'; debug << tbMsg << '\n';
} }
if ( typeMsg.isEmpty() && valMsg.isEmpty() && tbMsg.isEmpty() ) if ( typeMsg.isEmpty() && valMsg.isEmpty() && tbMsg.isEmpty() )
{
return tr( "Unfetchable Python error." ); return tr( "Unfetchable Python error." );
}
QStringList msgList; QStringList msgList;
if ( !typeMsg.isEmpty() ) if ( !typeMsg.isEmpty() )
{
msgList.append( QString( "<strong>%1</strong>" ).arg( typeMsg.toHtmlEscaped() ) ); msgList.append( QString( "<strong>%1</strong>" ).arg( typeMsg.toHtmlEscaped() ) );
}
if ( !valMsg.isEmpty() ) if ( !valMsg.isEmpty() )
{
msgList.append( valMsg.toHtmlEscaped() ); msgList.append( valMsg.toHtmlEscaped() );
}
if ( !tbMsg.isEmpty() ) if ( !tbMsg.isEmpty() )
{ {

View File

@ -66,6 +66,6 @@ private:
QStringList m_pythonPaths; QStringList m_pythonPaths;
}; };
} // namespace Calamares } // namespace CalamaresPython
#endif // CALAMARES_PYTHONJOBHELPER_H #endif // CALAMARES_PYTHONJOBHELPER_H

View File

@ -19,10 +19,10 @@
#include "PythonJob.h" #include "PythonJob.h"
#include "PythonHelper.h"
#include "utils/Logger.h"
#include "GlobalStorage.h" #include "GlobalStorage.h"
#include "JobQueue.h" #include "JobQueue.h"
#include "PythonHelper.h"
#include "utils/Logger.h"
#include <QDir> #include <QDir>
@ -35,27 +35,19 @@
namespace bp = boost::python; namespace bp = boost::python;
BOOST_PYTHON_FUNCTION_OVERLOADS( mount_overloads, BOOST_PYTHON_FUNCTION_OVERLOADS( mount_overloads, CalamaresPython::mount, 2, 4 );
CalamaresPython::mount, BOOST_PYTHON_FUNCTION_OVERLOADS( target_env_call_str_overloads, CalamaresPython::target_env_call, 1, 3 );
2, 4 ); BOOST_PYTHON_FUNCTION_OVERLOADS( target_env_call_list_overloads, CalamaresPython::target_env_call, 1, 3 );
BOOST_PYTHON_FUNCTION_OVERLOADS( target_env_call_str_overloads, BOOST_PYTHON_FUNCTION_OVERLOADS( check_target_env_call_str_overloads, CalamaresPython::check_target_env_call, 1, 3 );
CalamaresPython::target_env_call, BOOST_PYTHON_FUNCTION_OVERLOADS( check_target_env_call_list_overloads, CalamaresPython::check_target_env_call, 1, 3 );
1, 3 );
BOOST_PYTHON_FUNCTION_OVERLOADS( target_env_call_list_overloads,
CalamaresPython::target_env_call,
1, 3 );
BOOST_PYTHON_FUNCTION_OVERLOADS( check_target_env_call_str_overloads,
CalamaresPython::check_target_env_call,
1, 3 );
BOOST_PYTHON_FUNCTION_OVERLOADS( check_target_env_call_list_overloads,
CalamaresPython::check_target_env_call,
1, 3 );
BOOST_PYTHON_FUNCTION_OVERLOADS( check_target_env_output_str_overloads, BOOST_PYTHON_FUNCTION_OVERLOADS( check_target_env_output_str_overloads,
CalamaresPython::check_target_env_output, CalamaresPython::check_target_env_output,
1, 3 ); 1,
3 );
BOOST_PYTHON_FUNCTION_OVERLOADS( check_target_env_output_list_overloads, BOOST_PYTHON_FUNCTION_OVERLOADS( check_target_env_output_list_overloads,
CalamaresPython::check_target_env_output, CalamaresPython::check_target_env_output,
1, 3 ); 1,
3 );
BOOST_PYTHON_MODULE( libcalamares ) BOOST_PYTHON_MODULE( libcalamares )
{ {
bp::object package = bp::scope(); bp::object package = bp::scope();
@ -72,15 +64,14 @@ BOOST_PYTHON_MODULE( libcalamares )
.def_readonly( "pretty_name", &CalamaresPython::PythonJobInterface::prettyName ) .def_readonly( "pretty_name", &CalamaresPython::PythonJobInterface::prettyName )
.def_readonly( "working_path", &CalamaresPython::PythonJobInterface::workingPath ) .def_readonly( "working_path", &CalamaresPython::PythonJobInterface::workingPath )
.def_readonly( "configuration", &CalamaresPython::PythonJobInterface::configuration ) .def_readonly( "configuration", &CalamaresPython::PythonJobInterface::configuration )
.def( .def( "setprogress",
"setprogress",
&CalamaresPython::PythonJobInterface::setprogress, &CalamaresPython::PythonJobInterface::setprogress,
bp::args( "progress" ), bp::args( "progress" ),
"Reports the progress status of this job to Calamares, " "Reports the progress status of this job to Calamares, "
"as a real number between 0 and 1." "as a real number between 0 and 1." );
);
bp::class_< CalamaresPython::GlobalStoragePythonWrapper >( "GlobalStorage", bp::init< Calamares::GlobalStorage* >() ) bp::class_< CalamaresPython::GlobalStoragePythonWrapper >( "GlobalStorage",
bp::init< Calamares::GlobalStorage* >() )
.def( "contains", &CalamaresPython::GlobalStoragePythonWrapper::contains ) .def( "contains", &CalamaresPython::GlobalStoragePythonWrapper::contains )
.def( "count", &CalamaresPython::GlobalStoragePythonWrapper::count ) .def( "count", &CalamaresPython::GlobalStoragePythonWrapper::count )
.def( "insert", &CalamaresPython::GlobalStoragePythonWrapper::insert ) .def( "insert", &CalamaresPython::GlobalStoragePythonWrapper::insert )
@ -95,151 +86,88 @@ BOOST_PYTHON_MODULE( libcalamares )
Q_UNUSED( utilsScope ) Q_UNUSED( utilsScope )
bp::def( bp::def(
"debug", "debug", &CalamaresPython::debug, bp::args( "s" ), "Writes the given string to the Calamares debug stream." );
&CalamaresPython::debug, bp::def( "warning",
bp::args( "s" ),
"Writes the given string to the Calamares debug stream."
);
bp::def(
"warning",
&CalamaresPython::warning, &CalamaresPython::warning,
bp::args( "s" ), bp::args( "s" ),
"Writes the given string to the Calamares warning stream." "Writes the given string to the Calamares warning stream." );
);
bp::def( bp::def( "mount",
"mount",
&CalamaresPython::mount, &CalamaresPython::mount,
mount_overloads( mount_overloads( bp::args( "device_path", "mount_point", "filesystem_name", "options" ),
bp::args( "device_path",
"mount_point",
"filesystem_name",
"options" ),
"Runs the mount utility with the specified parameters.\n" "Runs the mount utility with the specified parameters.\n"
"Returns the program's exit code, or:\n" "Returns the program's exit code, or:\n"
"-1 = QProcess crash\n" "-1 = QProcess crash\n"
"-2 = QProcess cannot start\n" "-2 = QProcess cannot start\n"
"-3 = bad arguments" "-3 = bad arguments" ) );
)
);
bp::def( bp::def(
"target_env_call", "target_env_call",
static_cast< int (*)( const std::string&, static_cast< int ( * )( const std::string&, const std::string&, int ) >( &CalamaresPython::target_env_call ),
const std::string&, target_env_call_str_overloads( bp::args( "command", "stdin", "timeout" ),
int ) >( &CalamaresPython::target_env_call ),
target_env_call_str_overloads(
bp::args( "command",
"stdin",
"timeout" ),
"Runs the specified command in the chroot of the target system.\n" "Runs the specified command in the chroot of the target system.\n"
"Returns the program's exit code, or:\n" "Returns the program's exit code, or:\n"
"-1 = QProcess crash\n" "-1 = QProcess crash\n"
"-2 = QProcess cannot start\n" "-2 = QProcess cannot start\n"
"-3 = bad arguments\n" "-3 = bad arguments\n"
"-4 = QProcess timeout" "-4 = QProcess timeout" ) );
) bp::def( "target_env_call",
); static_cast< int ( * )( const bp::list&, const std::string&, int ) >( &CalamaresPython::target_env_call ),
bp::def( target_env_call_list_overloads( bp::args( "args", "stdin", "timeout" ),
"target_env_call",
static_cast< int (*)( const bp::list&,
const std::string&,
int ) >( &CalamaresPython::target_env_call ),
target_env_call_list_overloads(
bp::args( "args",
"stdin",
"timeout" ),
"Runs the specified command in the chroot of the target system.\n" "Runs the specified command in the chroot of the target system.\n"
"Returns the program's exit code, or:\n" "Returns the program's exit code, or:\n"
"-1 = QProcess crash\n" "-1 = QProcess crash\n"
"-2 = QProcess cannot start\n" "-2 = QProcess cannot start\n"
"-3 = bad arguments\n" "-3 = bad arguments\n"
"-4 = QProcess timeout" "-4 = QProcess timeout" ) );
)
);
bp::def( bp::def( "check_target_env_call",
"check_target_env_call", static_cast< int ( * )( const std::string&, const std::string&, int ) >(
static_cast< int (*)( const std::string&, &CalamaresPython::check_target_env_call ),
const std::string&, check_target_env_call_str_overloads( bp::args( "command", "stdin", "timeout" ),
int ) >( &CalamaresPython::check_target_env_call ),
check_target_env_call_str_overloads(
bp::args( "command",
"stdin",
"timeout" ),
"Runs the specified command in the chroot of the target system.\n" "Runs the specified command in the chroot of the target system.\n"
"Returns 0, which is program's exit code if the program exited " "Returns 0, which is program's exit code if the program exited "
"successfully, or raises a subprocess.CalledProcessError." "successfully, or raises a subprocess.CalledProcessError." ) );
)
);
bp::def( bp::def(
"check_target_env_call", "check_target_env_call",
static_cast< int (*)( const bp::list&, static_cast< int ( * )( const bp::list&, const std::string&, int ) >( &CalamaresPython::check_target_env_call ),
const std::string&, check_target_env_call_list_overloads( bp::args( "args", "stdin", "timeout" ),
int ) >( &CalamaresPython::check_target_env_call ),
check_target_env_call_list_overloads(
bp::args( "args",
"stdin",
"timeout" ),
"Runs the specified command in the chroot of the target system.\n" "Runs the specified command in the chroot of the target system.\n"
"Returns 0, which is program's exit code if the program exited " "Returns 0, which is program's exit code if the program exited "
"successfully, or raises a subprocess.CalledProcessError." "successfully, or raises a subprocess.CalledProcessError." ) );
)
);
bp::def( bp::def( "check_target_env_output",
"check_target_env_output", static_cast< std::string ( * )( const std::string&, const std::string&, int ) >(
static_cast< std::string (*)( const std::string&, &CalamaresPython::check_target_env_output ),
const std::string&, check_target_env_output_str_overloads( bp::args( "command", "stdin", "timeout" ),
int ) >( &CalamaresPython::check_target_env_output ),
check_target_env_output_str_overloads(
bp::args( "command",
"stdin",
"timeout" ),
"Runs the specified command in the chroot of the target system.\n" "Runs the specified command in the chroot of the target system.\n"
"Returns the program's standard output, and raises a " "Returns the program's standard output, and raises a "
"subprocess.CalledProcessError if something went wrong." "subprocess.CalledProcessError if something went wrong." ) );
) bp::def( "check_target_env_output",
); static_cast< std::string ( * )( const bp::list&, const std::string&, int ) >(
bp::def( &CalamaresPython::check_target_env_output ),
"check_target_env_output", check_target_env_output_list_overloads( bp::args( "args", "stdin", "timeout" ),
static_cast< std::string (*)( const bp::list&,
const std::string&,
int ) >( &CalamaresPython::check_target_env_output ),
check_target_env_output_list_overloads(
bp::args( "args",
"stdin",
"timeout" ),
"Runs the specified command in the chroot of the target system.\n" "Runs the specified command in the chroot of the target system.\n"
"Returns the program's standard output, and raises a " "Returns the program's standard output, and raises a "
"subprocess.CalledProcessError if something went wrong." "subprocess.CalledProcessError if something went wrong." ) );
) bp::def( "obscure",
);
bp::def(
"obscure",
&CalamaresPython::obscure, &CalamaresPython::obscure,
bp::args( "s" ), bp::args( "s" ),
"Simple string obfuscation function based on KStringHandler::obscure.\n" "Simple string obfuscation function based on KStringHandler::obscure.\n"
"Returns a string, generated using a simple symmetric encryption.\n" "Returns a string, generated using a simple symmetric encryption.\n"
"Applying the function to a string obscured by this function will result " "Applying the function to a string obscured by this function will result "
"in the original string." "in the original string." );
);
bp::def( bp::def( "gettext_languages",
"gettext_languages",
&CalamaresPython::gettext_languages, &CalamaresPython::gettext_languages,
"Returns list of languages (most to least-specific) for gettext." "Returns list of languages (most to least-specific) for gettext." );
);
bp::def( bp::def( "gettext_path", &CalamaresPython::gettext_path, "Returns path for gettext search." );
"gettext_path",
&CalamaresPython::gettext_path,
"Returns path for gettext search."
);
} }
namespace Calamares { namespace Calamares
{
PythonJob::PythonJob( const QString& scriptFile, PythonJob::PythonJob( const QString& scriptFile,
@ -255,8 +183,7 @@ PythonJob::PythonJob( const QString& scriptFile,
} }
PythonJob::~PythonJob() PythonJob::~PythonJob() {}
{}
QString QString
@ -270,11 +197,14 @@ QString
PythonJob::prettyStatusMessage() const PythonJob::prettyStatusMessage() const
{ {
if ( m_description.isEmpty() ) if ( m_description.isEmpty() )
return tr( "Running %1 operation." ) {
.arg( QDir( m_workingPath ).dirName() ); return tr( "Running %1 operation." ).arg( QDir( m_workingPath ).dirName() );
}
else else
{
return m_description; return m_description;
} }
}
JobResult JobResult
@ -282,19 +212,15 @@ PythonJob::exec()
{ {
// We assume m_scriptFile to be relative to m_workingPath. // We assume m_scriptFile to be relative to m_workingPath.
QDir workingDir( m_workingPath ); QDir workingDir( m_workingPath );
if ( !workingDir.exists() || if ( !workingDir.exists() || !workingDir.isReadable() )
!workingDir.isReadable() )
{ {
return JobResult::error( tr( "Bad working directory path" ), return JobResult::error(
tr( "Working directory %1 for python job %2 is not readable." ) tr( "Bad working directory path" ),
.arg( m_workingPath ) tr( "Working directory %1 for python job %2 is not readable." ).arg( m_workingPath ).arg( prettyName() ) );
.arg( prettyName() ) );
} }
QFileInfo scriptFI( workingDir.absoluteFilePath( m_scriptFile ) ); QFileInfo scriptFI( workingDir.absoluteFilePath( m_scriptFile ) );
if ( !scriptFI.exists() || if ( !scriptFI.exists() || !scriptFI.isFile() || !scriptFI.isReadable() )
!scriptFI.isFile() ||
!scriptFI.isReadable() )
{ {
return JobResult::error( tr( "Bad main script file" ), return JobResult::error( tr( "Bad main script file" ),
tr( "Main script file %1 for python job %2 is not readable." ) tr( "Main script file %1 for python job %2 is not readable." )
@ -310,12 +236,11 @@ PythonJob::exec()
bp::dict calamaresNamespace = bp::extract< bp::dict >( calamaresModule.attr( "__dict__" ) ); bp::dict calamaresNamespace = bp::extract< bp::dict >( calamaresModule.attr( "__dict__" ) );
calamaresNamespace[ "job" ] = CalamaresPython::PythonJobInterface( this ); calamaresNamespace[ "job" ] = CalamaresPython::PythonJobInterface( this );
calamaresNamespace[ "globalstorage" ] = CalamaresPython::GlobalStoragePythonWrapper( calamaresNamespace[ "globalstorage" ]
JobQueue::instance()->globalStorage() ); = CalamaresPython::GlobalStoragePythonWrapper( JobQueue::instance()->globalStorage() );
bp::object execResult = bp::exec_file( scriptFI.absoluteFilePath().toLocal8Bit().data(), bp::object execResult
scriptNamespace, = bp::exec_file( scriptFI.absoluteFilePath().toLocal8Bit().data(), scriptNamespace, scriptNamespace );
scriptNamespace );
bp::object entryPoint = scriptNamespace[ "run" ]; bp::object entryPoint = scriptNamespace[ "run" ];
bp::object prettyNameFunc = scriptNamespace.get( "pretty_name", bp::object() ); bp::object prettyNameFunc = scriptNamespace.get( "pretty_name", bp::object() );
@ -344,7 +269,9 @@ PythonJob::exec()
m_description = QString::fromStdString( entryPoint_doc_attr() ).trimmed(); m_description = QString::fromStdString( entryPoint_doc_attr() ).trimmed();
auto i_newline = m_description.indexOf( '\n' ); auto i_newline = m_description.indexOf( '\n' );
if ( i_newline > 0 ) if ( i_newline > 0 )
{
m_description.truncate( i_newline ); m_description.truncate( i_newline );
}
cDebug() << "Job description from __doc__" << prettyName() << "=" << m_description; cDebug() << "Job description from __doc__" << prettyName() << "=" << m_description;
emit progress( 0 ); emit progress( 0 );
} }
@ -374,9 +301,7 @@ PythonJob::exec()
bp::handle_exception(); bp::handle_exception();
PyErr_Clear(); PyErr_Clear();
return JobResult::internalError( return JobResult::internalError(
tr( "Boost.Python error in job \"%1\"." ).arg( prettyName() ), tr( "Boost.Python error in job \"%1\"." ).arg( prettyName() ), msg, JobResult::PythonUncaughtException );
msg,
JobResult::PythonUncaughtException );
} }
} }
@ -393,7 +318,9 @@ PythonJob::helper()
{ {
auto ptr = CalamaresPython::Helper::s_instance; auto ptr = CalamaresPython::Helper::s_instance;
if ( !ptr ) if ( !ptr )
{
ptr = new CalamaresPython::Helper; ptr = new CalamaresPython::Helper;
}
return ptr; return ptr;
} }

View File

@ -27,9 +27,10 @@ namespace CalamaresPython
{ {
class PythonJobInterface; class PythonJobInterface;
class Helper; class Helper;
} } // namespace CalamaresPython
namespace Calamares { namespace Calamares
{
class PythonJob : public Job class PythonJob : public Job
{ {

View File

@ -20,8 +20,8 @@
#include "PythonJobApi.h" #include "PythonJobApi.h"
#include "PythonHelper.h" #include "PythonHelper.h"
#include "utils/Logger.h"
#include "utils/CalamaresUtilsSystem.h" #include "utils/CalamaresUtilsSystem.h"
#include "utils/Logger.h"
#include "utils/String.h" #include "utils/String.h"
#include "GlobalStorage.h" #include "GlobalStorage.h"
@ -40,14 +40,18 @@ static int
_handle_check_target_env_call_error( const CalamaresUtils::ProcessResult& ec, const QString& cmd ) _handle_check_target_env_call_error( const CalamaresUtils::ProcessResult& ec, const QString& cmd )
{ {
if ( !ec.first ) if ( !ec.first )
{
return ec.first; return ec.first;
}
QString raise = QString( "import subprocess\n" QString raise = QString( "import subprocess\n"
"e = subprocess.CalledProcessError(%1,\"%2\")\n" ) "e = subprocess.CalledProcessError(%1,\"%2\")\n" )
.arg( ec.first ) .arg( ec.first )
.arg( cmd ); .arg( cmd );
if ( !ec.second.isEmpty() ) if ( !ec.second.isEmpty() )
{
raise.append( QStringLiteral( "e.output = \"\"\"%1\"\"\"\n" ).arg( ec.second ) ); raise.append( QStringLiteral( "e.output = \"\"\"%1\"\"\"\n" ).arg( ec.second ) );
}
raise.append( "raise e" ); raise.append( "raise e" );
bp::exec( raise.toStdString().c_str() ); bp::exec( raise.toStdString().c_str() );
bp::throw_error_already_set(); bp::throw_error_already_set();
@ -63,8 +67,7 @@ mount( const std::string& device_path,
const std::string& filesystem_name, const std::string& filesystem_name,
const std::string& options ) const std::string& options )
{ {
return CalamaresUtils::System::instance()-> return CalamaresUtils::System::instance()->mount( QString::fromStdString( device_path ),
mount( QString::fromStdString( device_path ),
QString::fromStdString( mount_point ), QString::fromStdString( mount_point ),
QString::fromStdString( filesystem_name ), QString::fromStdString( filesystem_name ),
QString::fromStdString( options ) ); QString::fromStdString( options ) );
@ -77,66 +80,50 @@ _bp_list_to_qstringlist( const bp::list& args )
QStringList list; QStringList list;
for ( int i = 0; i < bp::len( args ); ++i ) for ( int i = 0; i < bp::len( args ); ++i )
{ {
list.append( QString::fromStdString( list.append( QString::fromStdString( bp::extract< std::string >( args[ i ] ) ) );
bp::extract< std::string >( args[ i ] ) ) );
} }
return list; return list;
} }
static inline CalamaresUtils::ProcessResult static inline CalamaresUtils::ProcessResult
_target_env_command( _target_env_command( const QStringList& args, const std::string& stdin, int timeout )
const QStringList& args,
const std::string& stdin,
int timeout )
{ {
// Since Python doesn't give us the type system for distinguishing // Since Python doesn't give us the type system for distinguishing
// seconds from other integral types, massage to seconds here. // seconds from other integral types, massage to seconds here.
return CalamaresUtils::System::instance()-> return CalamaresUtils::System::instance()->targetEnvCommand(
targetEnvCommand( args, args, QString(), QString::fromStdString( stdin ), std::chrono::seconds( timeout ) );
QString(),
QString::fromStdString( stdin ),
std::chrono::seconds( timeout ) );
} }
int int
target_env_call( const std::string& command, target_env_call( const std::string& command, const std::string& stdin, int timeout )
const std::string& stdin,
int timeout )
{ {
return _target_env_command( return _target_env_command( QStringList { QString::fromStdString( command ) }, stdin, timeout ).first;
QStringList{ QString::fromStdString( command ) }, stdin, timeout ).first;
} }
int int
target_env_call( const bp::list& args, target_env_call( const bp::list& args, const std::string& stdin, int timeout )
const std::string& stdin,
int timeout )
{ {
return _target_env_command( return _target_env_command( _bp_list_to_qstringlist( args ), stdin, timeout ).first;
_bp_list_to_qstringlist( args ), stdin, timeout ).first;
} }
int int
check_target_env_call( const std::string& command, check_target_env_call( const std::string& command, const std::string& stdin, int timeout )
const std::string& stdin,
int timeout )
{ {
auto ec = _target_env_command( auto ec = _target_env_command( QStringList { QString::fromStdString( command ) }, stdin, timeout );
QStringList{ QString::fromStdString( command ) }, stdin, timeout );
return _handle_check_target_env_call_error( ec, QString::fromStdString( command ) ); return _handle_check_target_env_call_error( ec, QString::fromStdString( command ) );
} }
int int
check_target_env_call( const bp::list& args, check_target_env_call( const bp::list& args, const std::string& stdin, int timeout )
const std::string& stdin,
int timeout )
{ {
auto ec = _target_env_command( _bp_list_to_qstringlist( args ), stdin, timeout ); auto ec = _target_env_command( _bp_list_to_qstringlist( args ), stdin, timeout );
if ( !ec.first ) if ( !ec.first )
{
return ec.first; return ec.first;
}
QStringList failedCmdList = _bp_list_to_qstringlist( args ); QStringList failedCmdList = _bp_list_to_qstringlist( args );
return _handle_check_target_env_call_error( ec, failedCmdList.join( ' ' ) ); return _handle_check_target_env_call_error( ec, failedCmdList.join( ' ' ) );
@ -144,25 +131,19 @@ check_target_env_call( const bp::list& args,
std::string std::string
check_target_env_output( const std::string& command, check_target_env_output( const std::string& command, const std::string& stdin, int timeout )
const std::string& stdin,
int timeout )
{ {
auto ec = _target_env_command( auto ec = _target_env_command( QStringList { QString::fromStdString( command ) }, stdin, timeout );
QStringList{ QString::fromStdString( command ) }, stdin, timeout );
_handle_check_target_env_call_error( ec, QString::fromStdString( command ) ); _handle_check_target_env_call_error( ec, QString::fromStdString( command ) );
return ec.second.toStdString(); return ec.second.toStdString();
} }
std::string std::string
check_target_env_output( const bp::list& args, check_target_env_output( const bp::list& args, const std::string& stdin, int timeout )
const std::string& stdin,
int timeout )
{ {
QStringList list = _bp_list_to_qstringlist( args ); QStringList list = _bp_list_to_qstringlist( args );
auto ec = _target_env_command( auto ec = _target_env_command( list, stdin, timeout );
list, stdin, timeout );
_handle_check_target_env_call_error( ec, list.join( ' ' ) ); _handle_check_target_env_call_error( ec, list.join( ' ' ) );
return ec.second.toStdString(); return ec.second.toStdString();
} }
@ -194,8 +175,10 @@ void
PythonJobInterface::setprogress( qreal progress ) PythonJobInterface::setprogress( qreal progress )
{ {
if ( progress >= 0 && progress <= 1 ) if ( progress >= 0 && progress <= 1 )
{
m_parent->emitProgress( progress ); m_parent->emitProgress( progress );
} }
}
std::string std::string
@ -216,7 +199,8 @@ _gettext_languages()
// own GlobalStoragePythonWrapper, which then holds a // own GlobalStoragePythonWrapper, which then holds a
// GlobalStorage object for all of Python. // GlobalStorage object for all of Python.
Calamares::JobQueue* jq = Calamares::JobQueue::instance(); Calamares::JobQueue* jq = Calamares::JobQueue::instance();
Calamares::GlobalStorage* gs = jq ? jq->globalStorage() : CalamaresPython::GlobalStoragePythonWrapper::globalStorageInstance(); Calamares::GlobalStorage* gs
= jq ? jq->globalStorage() : CalamaresPython::GlobalStoragePythonWrapper::globalStorageInstance();
QVariant localeConf_ = gs->value( "localeConf" ); QVariant localeConf_ = gs->value( "localeConf" );
if ( localeConf_.canConvert< QVariantMap >() ) if ( localeConf_.canConvert< QVariantMap >() )
@ -246,7 +230,9 @@ gettext_languages()
{ {
bp::list pyList; bp::list pyList;
for ( auto lang : _gettext_languages() ) for ( auto lang : _gettext_languages() )
{
pyList.append( lang.toStdString() ); pyList.append( lang.toStdString() );
}
return pyList; return pyList;
} }
@ -257,24 +243,29 @@ _add_localedirs( QStringList& pathList, const QString& candidate )
{ {
pathList.prepend( candidate ); pathList.prepend( candidate );
if ( QDir( candidate ).cd( "lang" ) ) if ( QDir( candidate ).cd( "lang" ) )
{
pathList.prepend( candidate + "/lang" ); pathList.prepend( candidate + "/lang" );
} }
} }
}
bp::object bp::object
gettext_path() gettext_path()
{ {
// TODO: distinguish between -d runs and normal runs // TODO: distinguish between -d runs and normal runs
// TODO: can we detect DESTDIR-installs? // TODO: can we detect DESTDIR-installs?
QStringList candidatePaths = QStandardPaths::locateAll( QStandardPaths::GenericDataLocation, "locale", QStandardPaths::LocateDirectory ); QStringList candidatePaths
= QStandardPaths::locateAll( QStandardPaths::GenericDataLocation, "locale", QStandardPaths::LocateDirectory );
QString extra = QCoreApplication::applicationDirPath(); QString extra = QCoreApplication::applicationDirPath();
_add_localedirs( candidatePaths, extra ); // Often /usr/local/bin _add_localedirs( candidatePaths, extra ); // Often /usr/local/bin
if ( !extra.isEmpty() ) if ( !extra.isEmpty() )
{ {
QDir d( extra ); QDir d( extra );
if ( d.cd( "../share/locale" ) ) // Often /usr/local/bin/../share/locale -> /usr/local/share/locale if ( d.cd( "../share/locale" ) ) // Often /usr/local/bin/../share/locale -> /usr/local/share/locale
{
_add_localedirs( candidatePaths, d.canonicalPath() ); _add_localedirs( candidatePaths, d.canonicalPath() );
} }
}
_add_localedirs( candidatePaths, QDir().canonicalPath() ); // . _add_localedirs( candidatePaths, QDir().canonicalPath() ); // .
cDebug() << "Determining gettext path from" << candidatePaths; cDebug() << "Determining gettext path from" << candidatePaths;
@ -296,4 +287,4 @@ gettext_path()
} }
} } // namespace CalamaresPython

View File

@ -35,29 +35,19 @@ int mount( const std::string& device_path,
const std::string& filesystem_name = std::string(), const std::string& filesystem_name = std::string(),
const std::string& options = std::string() ); const std::string& options = std::string() );
int target_env_call( const std::string& command, int target_env_call( const std::string& command, const std::string& stdin = std::string(), int timeout = 0 );
const std::string& stdin = std::string(),
int timeout = 0 );
int target_env_call( const boost::python::list& args, int target_env_call( const boost::python::list& args, const std::string& stdin = std::string(), int timeout = 0 );
const std::string& stdin = std::string(),
int timeout = 0 );
int check_target_env_call( const std::string& command, int check_target_env_call( const std::string& command, const std::string& stdin = std::string(), int timeout = 0 );
const std::string& stdin = std::string(),
int timeout = 0 );
int check_target_env_call( const boost::python::list& args, int check_target_env_call( const boost::python::list& args, const std::string& stdin = std::string(), int timeout = 0 );
const std::string& stdin = std::string(),
int timeout = 0 );
std::string check_target_env_output( const std::string& command, std::string
const std::string& stdin = std::string(), check_target_env_output( const std::string& command, const std::string& stdin = std::string(), int timeout = 0 );
int timeout = 0 );
std::string check_target_env_output( const boost::python::list& args, std::string
const std::string& stdin = std::string(), check_target_env_output( const boost::python::list& args, const std::string& stdin = std::string(), int timeout = 0 );
int timeout = 0 );
std::string obscure( const std::string& string ); std::string obscure( const std::string& string );
@ -85,6 +75,6 @@ private:
Calamares::PythonJob* m_parent; Calamares::PythonJob* m_parent;
}; };
} } // namespace CalamaresPython
#endif // PYTHONJOBAPI_H #endif // PYTHONJOBAPI_H

View File

@ -41,7 +41,9 @@ requireString( const YAML::Node& config, const char* key )
{ {
auto v = config[ key ]; auto v = config[ key ];
if ( hasValue( v ) ) if ( hasValue( v ) )
{
return QString::fromStdString( v.as< std::string >() ); return QString::fromStdString( v.as< std::string >() );
}
else else
{ {
cWarning() << Logger::SubEntry << "Required settings.conf key" << key << "is missing."; cWarning() << Logger::SubEntry << "Required settings.conf key" << key << "is missing.";
@ -55,7 +57,9 @@ requireBool( const YAML::Node& config, const char* key, bool d )
{ {
auto v = config[ key ]; auto v = config[ key ];
if ( hasValue( v ) ) if ( hasValue( v ) )
{
return v.as< bool >(); return v.as< bool >();
}
else else
{ {
cWarning() << Logger::SubEntry << "Required settings.conf key" << key << "is missing."; cWarning() << Logger::SubEntry << "Required settings.conf key" << key << "is missing.";
@ -86,17 +90,17 @@ interpretModulesSearch( const bool debugMode, const QStringList& rawPaths, QStri
// module search path in the build dir. // module search path in the build dir.
if ( debugMode ) if ( debugMode )
{ {
QString buildDirModules = QDir::current().absolutePath() + QString buildDirModules
QDir::separator() + "src" + = QDir::current().absolutePath() + QDir::separator() + "src" + QDir::separator() + "modules";
QDir::separator() + "modules";
if ( QDir( buildDirModules ).exists() ) if ( QDir( buildDirModules ).exists() )
{
output.append( buildDirModules ); output.append( buildDirModules );
} }
}
// Install path is set in CalamaresAddPlugin.cmake // Install path is set in CalamaresAddPlugin.cmake
output.append( CalamaresUtils::systemLibDir().absolutePath() + output.append( CalamaresUtils::systemLibDir().absolutePath() + QDir::separator() + "calamares"
QDir::separator() + "calamares" + + QDir::separator() + "modules" );
QDir::separator() + "modules" );
} }
else else
{ {
@ -106,10 +110,12 @@ interpretModulesSearch( const bool debugMode, const QStringList& rawPaths, QStri
output.append( d.absolutePath() ); output.append( d.absolutePath() );
} }
else else
{
cDebug() << Logger::SubEntry << "module-search entry non-existent" << path; cDebug() << Logger::SubEntry << "module-search entry non-existent" << path;
} }
} }
} }
}
static void static void
interpretInstances( const YAML::Node& node, Settings::InstanceDescriptionList& customInstances ) interpretInstances( const YAML::Node& node, Settings::InstanceDescriptionList& customInstances )
@ -124,15 +130,17 @@ interpretInstances( const YAML::Node& node, Settings::InstanceDescriptionList& c
for ( const QVariant& instancesVListItem : instances ) for ( const QVariant& instancesVListItem : instances )
{ {
if ( instancesVListItem.type() != QVariant::Map ) if ( instancesVListItem.type() != QVariant::Map )
{
continue; continue;
QVariantMap instancesVListItemMap = }
instancesVListItem.toMap(); QVariantMap instancesVListItemMap = instancesVListItem.toMap();
Settings::InstanceDescription instanceMap; Settings::InstanceDescription instanceMap;
for ( auto it = instancesVListItemMap.constBegin(); for ( auto it = instancesVListItemMap.constBegin(); it != instancesVListItemMap.constEnd(); ++it )
it != instancesVListItemMap.constEnd(); ++it )
{ {
if ( it.value().type() != QVariant::String ) if ( it.value().type() != QVariant::String )
{
continue; continue;
}
instanceMap.insert( it.key(), it.value().toString() ); instanceMap.insert( it.key(), it.value().toString() );
} }
customInstances.append( instanceMap ); customInstances.append( instanceMap );
@ -149,37 +157,43 @@ interpretSequence( const YAML::Node& node, Settings::ModuleSequence& moduleSeque
{ {
QVariant sequenceV = CalamaresUtils::yamlToVariant( node ); QVariant sequenceV = CalamaresUtils::yamlToVariant( node );
if ( !( sequenceV.type() == QVariant::List ) ) if ( !( sequenceV.type() == QVariant::List ) )
{
throw YAML::Exception( YAML::Mark(), "sequence key does not have a list-value" ); throw YAML::Exception( YAML::Mark(), "sequence key does not have a list-value" );
}
const auto sequence = sequenceV.toList(); const auto sequence = sequenceV.toList();
for ( const QVariant& sequenceVListItem : sequence ) for ( const QVariant& sequenceVListItem : sequence )
{ {
if ( sequenceVListItem.type() != QVariant::Map ) if ( sequenceVListItem.type() != QVariant::Map )
{
continue; continue;
}
QString thisActionS = sequenceVListItem.toMap().firstKey(); QString thisActionS = sequenceVListItem.toMap().firstKey();
ModuleAction thisAction; ModuleAction thisAction;
if ( thisActionS == "show" ) if ( thisActionS == "show" )
{
thisAction = ModuleAction::Show; thisAction = ModuleAction::Show;
}
else if ( thisActionS == "exec" ) else if ( thisActionS == "exec" )
{
thisAction = ModuleAction::Exec; thisAction = ModuleAction::Exec;
}
else else
{
continue; continue;
}
QStringList thisActionRoster = sequenceVListItem QStringList thisActionRoster = sequenceVListItem.toMap().value( thisActionS ).toStringList();
.toMap() moduleSequence.append( qMakePair( thisAction, thisActionRoster ) );
.value( thisActionS )
.toStringList();
moduleSequence.append( qMakePair( thisAction,
thisActionRoster ) );
} }
} }
else else
{
throw YAML::Exception( YAML::Mark(), "sequence key is missing" ); throw YAML::Exception( YAML::Mark(), "sequence key is missing" );
} }
}
Settings::Settings( const QString& settingsFilePath, Settings::Settings( const QString& settingsFilePath, bool debugMode, QObject* parent )
bool debugMode,
QObject* parent )
: QObject( parent ) : QObject( parent )
, m_debug( debugMode ) , m_debug( debugMode )
, m_doChroot( true ) , m_doChroot( true )
@ -198,7 +212,8 @@ Settings::Settings( const QString& settingsFilePath,
YAML::Node config = YAML::Load( ba.constData() ); YAML::Node config = YAML::Load( ba.constData() );
Q_ASSERT( config.IsMap() ); Q_ASSERT( config.IsMap() );
interpretModulesSearch( debugMode, CalamaresUtils::yamlToStringList( config[ "modules-search" ] ), m_modulesSearchPaths ); interpretModulesSearch(
debugMode, CalamaresUtils::yamlToStringList( config[ "modules-search" ] ), m_modulesSearchPaths );
interpretInstances( config[ "instances" ], m_customModuleInstances ); interpretInstances( config[ "instances" ], m_customModuleInstances );
interpretSequence( config[ "sequence" ], m_modulesSequence ); interpretSequence( config[ "sequence" ], m_modulesSequence );
@ -283,4 +298,4 @@ Settings::disableCancelDuringExec() const
} }
} } // namespace Calamares

View File

@ -36,9 +36,7 @@ class DLLEXPORT Settings : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit Settings( const QString& settingsFilePath, explicit Settings( const QString& settingsFilePath, bool debugMode, QObject* parent = nullptr );
bool debugMode,
QObject* parent = nullptr );
static Settings* instance(); static Settings* instance();
@ -88,6 +86,6 @@ private:
bool m_disableCancelDuringExec; bool m_disableCancelDuringExec;
}; };
} } // namespace Calamares
#endif // SETTINGS_H #endif // SETTINGS_H

View File

@ -16,6 +16,8 @@
*/ */
// BEGIN Generated from CLDR data // BEGIN Generated from CLDR data
// *INDENT-OFF*
// clang-format off
struct CountryData struct CountryData

View File

@ -50,18 +50,24 @@ Label::setLabels( const QString& locale, LabelFormat format )
QString countryName; QString countryName;
if ( languageName.isEmpty() ) if ( languageName.isEmpty() )
{
languageName = QString( "* %1 (%2)" ).arg( locale, englishName ); languageName = QString( "* %1 (%2)" ).arg( locale, englishName );
bool needsCountryName = ( format == LabelFormat::AlwaysWithCountry ) ||
(locale.contains( '_' ) && QLocale::countriesForLanguage( m_locale.language() ).count() > 1 );
if ( needsCountryName )
countryName = m_locale.nativeCountryName();
m_label = needsCountryName ? longFormat.arg( languageName, countryName ) : languageName;
m_englishLabel = needsCountryName ? longFormat.arg( englishName, QLocale::countryToString( m_locale.country() ) ) : englishName;
} }
QLocale Label::getLocale( const QString& localeName ) bool needsCountryName = ( format == LabelFormat::AlwaysWithCountry )
|| ( locale.contains( '_' ) && QLocale::countriesForLanguage( m_locale.language() ).count() > 1 );
if ( needsCountryName )
{
countryName = m_locale.nativeCountryName();
}
m_label = needsCountryName ? longFormat.arg( languageName, countryName ) : languageName;
m_englishLabel = needsCountryName ? longFormat.arg( englishName, QLocale::countryToString( m_locale.country() ) )
: englishName;
}
QLocale
Label::getLocale( const QString& localeName )
{ {
if ( localeName.contains( "@latin" ) ) if ( localeName.contains( "@latin" ) )
{ {
@ -69,8 +75,10 @@ QLocale Label::getLocale( const QString& localeName )
return QLocale( loc.language(), QLocale::Script::LatinScript, loc.country() ); return QLocale( loc.language(), QLocale::Script::LatinScript, loc.country() );
} }
else else
{
return QLocale( localeName ); return QLocale( localeName );
} }
} }
} // namespace
} // namespace Locale
} // namespace CalamaresUtils

View File

@ -39,7 +39,11 @@ class Label
{ {
public: public:
/** @brief Formatting option for label -- add (country) to label. */ /** @brief Formatting option for label -- add (country) to label. */
enum class LabelFormat { AlwaysWithCountry, IfNeededWithCountry } ; enum class LabelFormat
{
AlwaysWithCountry,
IfNeededWithCountry
};
/** @brief Empty locale. This uses the system-default locale. */ /** @brief Empty locale. This uses the system-default locale. */
Label(); Label();
@ -56,54 +60,30 @@ public:
* *
* English (@see isEnglish() -- it means en_US) is sorted at the top. * English (@see isEnglish() -- it means en_US) is sorted at the top.
*/ */
bool operator <( const Label& other ) const bool operator<( const Label& other ) const { return m_localeId < other.m_localeId; }
{
return m_localeId < other.m_localeId;
}
/** @brief Is this locale English? /** @brief Is this locale English?
* *
* en_US and en (American English) is defined as English. The Queen's * en_US and en (American English) is defined as English. The Queen's
* English -- proper English -- is relegated to non-English status. * English -- proper English -- is relegated to non-English status.
*/ */
bool isEnglish() const bool isEnglish() const { return m_localeId == QLatin1Literal( "en_US" ) || m_localeId == QLatin1Literal( "en" ); }
{
return m_localeId == QLatin1Literal( "en_US" ) || m_localeId == QLatin1Literal( "en" );
}
/** @brief Get the human-readable name for this locale. */ /** @brief Get the human-readable name for this locale. */
QString label() const QString label() const { return m_label; }
{
return m_label;
}
/** @brief Get the *English* human-readable name for this locale. */ /** @brief Get the *English* human-readable name for this locale. */
QString englishLabel() const QString englishLabel() const { return m_englishLabel; }
{
return m_englishLabel;
}
/** @brief Get the Qt locale. */ /** @brief Get the Qt locale. */
QLocale locale() const QLocale locale() const { return m_locale; }
{
return m_locale;
}
QString name() const QString name() const { return m_locale.name(); }
{
return m_locale.name();
}
/// @brief Convenience accessor to the language part of the locale /// @brief Convenience accessor to the language part of the locale
QLocale::Language language() const QLocale::Language language() const { return m_locale.language(); }
{
return m_locale.language();
}
/// @brief Convenience accessor to the country part (if any) of the locale /// @brief Convenience accessor to the country part (if any) of the locale
QLocale::Country country() const QLocale::Country country() const { return m_locale.country(); }
{
return m_locale.country();
}
/** @brief Get a Qt locale for the given @p localeName /** @brief Get a Qt locale for the given @p localeName
* *
@ -121,7 +101,7 @@ protected:
QString m_englishLabel; QString m_englishLabel;
}; };
} } // namespace Locale
} // namespace } // namespace CalamaresUtils
#endif #endif

View File

@ -34,13 +34,13 @@ LabelModel::LabelModel( const QStringList& locales, QObject* parent )
m_locales.reserve( locales.count() ); m_locales.reserve( locales.count() );
for ( const auto& l : locales ) for ( const auto& l : locales )
{
m_locales.push_back( Label( l ) ); m_locales.push_back( Label( l ) );
} }
LabelModel::~LabelModel()
{
} }
LabelModel::~LabelModel() {}
int int
LabelModel::rowCount( const QModelIndex& ) const LabelModel::rowCount( const QModelIndex& ) const
{ {
@ -51,10 +51,14 @@ QVariant
LabelModel::data( const QModelIndex& index, int role ) const LabelModel::data( const QModelIndex& index, int role ) const
{ {
if ( ( role != LabelRole ) && ( role != EnglishLabelRole ) ) if ( ( role != LabelRole ) && ( role != EnglishLabelRole ) )
{
return QVariant(); return QVariant();
}
if ( !index.isValid() ) if ( !index.isValid() )
{
return QVariant(); return QVariant();
}
const auto& locale = m_locales.at( index.row() ); const auto& locale = m_locales.at( index.row() );
switch ( role ) switch ( role )
@ -75,7 +79,9 @@ LabelModel::locale( int row ) const
{ {
for ( const auto& l : m_locales ) for ( const auto& l : m_locales )
if ( l.isEnglish() ) if ( l.isEnglish() )
{
return l; return l;
}
return m_locales[ 0 ]; return m_locales[ 0 ];
} }
return m_locales[ row ]; return m_locales[ row ];
@ -87,47 +93,48 @@ LabelModel::find( std::function<bool ( const Label& )> predicate ) const
for ( int row = 0; row < m_locales.count(); ++row ) for ( int row = 0; row < m_locales.count(); ++row )
{ {
if ( predicate( m_locales[ row ] ) ) if ( predicate( m_locales[ row ] ) )
{
return row; return row;
} }
}
return -1; return -1;
} }
int int
LabelModel::find( std::function< bool( const QLocale& ) > predicate ) const LabelModel::find( std::function< bool( const QLocale& ) > predicate ) const
{ {
return find( [&]( const Label& l ) return find( [&]( const Label& l ) { return predicate( l.locale() ); } );
{
return predicate( l.locale() );
} );
} }
int int
LabelModel::find( const QLocale& locale ) const LabelModel::find( const QLocale& locale ) const
{ {
return find( [&]( const Label& l ) return find( [&]( const Label& l ) { return locale == l.locale(); } );
{
return locale == l.locale();
} );
} }
int int
LabelModel::find( const QString& countryCode ) const LabelModel::find( const QString& countryCode ) const
{ {
if ( countryCode.length() != 2 ) if ( countryCode.length() != 2 )
{
return -1; return -1;
}
auto c_l = countryData( countryCode ); auto c_l = countryData( countryCode );
int r = find( [&]( const Label& l ) { return ( l.language() == c_l.second ) && ( l.country() == c_l.first ); } ); int r = find( [&]( const Label& l ) { return ( l.language() == c_l.second ) && ( l.country() == c_l.first ); } );
if ( r >= 0 ) if ( r >= 0 )
{
return r; return r;
}
return find( [&]( const Label& l ) { return l.language() == c_l.second; } ); return find( [&]( const Label& l ) { return l.language() == c_l.second; } );
} }
LabelModel* availableTranslations() LabelModel*
availableTranslations()
{ {
static LabelModel* model = new LabelModel( QString( CALAMARES_TRANSLATION_LANGUAGES ).split( ';' ) ); static LabelModel* model = new LabelModel( QString( CALAMARES_TRANSLATION_LANGUAGES ).split( ';' ) );
return model; return model;
} }
} } // namespace Locale
} // namespace } // namespace CalamaresUtils

View File

@ -80,6 +80,6 @@ private:
* NOTE: While the model is not typed const, it should be. Do not modify. * NOTE: While the model is not typed const, it should be. Do not modify.
*/ */
DLLEXPORT LabelModel* availableTranslations(); DLLEXPORT LabelModel* availableTranslations();
} } // namespace Locale
} // namespace } // namespace CalamaresUtils
#endif #endif

View File

@ -42,52 +42,65 @@ struct TwoChar
char cc2; char cc2;
}; };
static const CountryData* lookup( TwoChar c ) static const CountryData*
lookup( TwoChar c )
{ {
if ( !c.cc1 ) if ( !c.cc1 )
{
return nullptr; return nullptr;
}
const CountryData* p = std::find_if(country_data_table, country_data_table + country_data_size, const CountryData* p
[c=c]( const CountryData& d ){ return (d.cc1 == c.cc1) && (d.cc2 == c.cc2); } = std::find_if( country_data_table, country_data_table + country_data_size, [c = c]( const CountryData& d ) {
); return ( d.cc1 == c.cc1 ) && ( d.cc2 == c.cc2 );
} );
if ( p == country_data_table + country_data_size ) if ( p == country_data_table + country_data_size )
{
return nullptr; return nullptr;
}
return p; return p;
} }
QLocale::Country countryForCode(const QString& code) QLocale::Country
countryForCode( const QString& code )
{ {
const CountryData* p = lookup( TwoChar( code ) ); const CountryData* p = lookup( TwoChar( code ) );
return p ? p->c : QLocale::Country::AnyCountry; return p ? p->c : QLocale::Country::AnyCountry;
} }
QLocale::Language languageForCountry(const QString& code) QLocale::Language
languageForCountry( const QString& code )
{ {
const CountryData* p = lookup( TwoChar( code ) ); const CountryData* p = lookup( TwoChar( code ) );
return p ? p->l : QLocale::Language::AnyLanguage; return p ? p->l : QLocale::Language::AnyLanguage;
} }
QPair<QLocale::Country, QLocale::Language> countryData(const QString& code) QPair< QLocale::Country, QLocale::Language >
countryData( const QString& code )
{ {
const CountryData* p = lookup( TwoChar( code ) ); const CountryData* p = lookup( TwoChar( code ) );
return p ? qMakePair( p->c, p->l ) : qMakePair( QLocale::Country::AnyCountry, QLocale::Language::AnyLanguage ); return p ? qMakePair( p->c, p->l ) : qMakePair( QLocale::Country::AnyCountry, QLocale::Language::AnyLanguage );
} }
QLocale countryLocale(const QString& code) QLocale
countryLocale( const QString& code )
{ {
auto p = countryData( code ); auto p = countryData( code );
return QLocale( p.second, p.first ); return QLocale( p.second, p.first );
} }
QLocale::Language languageForCountry(QLocale::Country country) QLocale::Language
languageForCountry( QLocale::Country country )
{ {
const CountryData* p = std::find_if(country_data_table, country_data_table + country_data_size, const CountryData* p = std::find_if( country_data_table,
[c=country]( const CountryData& d ){ return d.c == c; } country_data_table + country_data_size,
); [c = country]( const CountryData& d ) { return d.c == c; } );
if ( p == country_data_table + country_data_size ) if ( p == country_data_table + country_data_size )
{
return QLocale::Language::AnyLanguage; return QLocale::Language::AnyLanguage;
}
return p->l; return p->l;
} }
} } // namespace Locale
} // namespace } // namespace CalamaresUtils

View File

@ -49,7 +49,7 @@ namespace Locale
DLLEXPORT QPair< QLocale::Country, QLocale::Language > countryData( const QString& code ); DLLEXPORT QPair< QLocale::Country, QLocale::Language > countryData( const QString& code );
/// @brief Get a likely locale for a 2-letter country code /// @brief Get a likely locale for a 2-letter country code
DLLEXPORT QLocale countryLocale( const QString& code ); DLLEXPORT QLocale countryLocale( const QString& code );
} } // namespace Locale
} // namespace } // namespace CalamaresUtils
#endif #endif

View File

@ -25,13 +25,9 @@
QTEST_GUILESS_MAIN( LocaleTests ) QTEST_GUILESS_MAIN( LocaleTests )
LocaleTests::LocaleTests() LocaleTests::LocaleTests() {}
{
}
LocaleTests::~LocaleTests() LocaleTests::~LocaleTests() {}
{
}
void void
LocaleTests::initTestCase() LocaleTests::initTestCase()
@ -82,6 +78,9 @@ LocaleTests::testEsperanto()
QVERIFY( locale.language() == QLocale::Lithuanian ? locale.country() == QLocale::Lithuania : true ); QVERIFY( locale.language() == QLocale::Lithuanian ? locale.country() == QLocale::Lithuania : true );
QVERIFY( locale.language() != QLocale::C ); QVERIFY( locale.language() != QLocale::C );
} }
#if QT_VERSION < QT_VERSION_CHECK( 5, 12, 2 )
QCOMPARE( QLocale( "eo" ).language(), QLocale::C ); QCOMPARE( QLocale( "eo" ).language(), QLocale::C );
#else
QCOMPARE( QLocale( "eo" ).language(), QLocale::Esperanto );
#endif
} }

View File

@ -231,6 +231,8 @@ cpp_header_comment = """/* GENERATED FILE DO NOT EDIT
*/ */
// BEGIN Generated from CLDR data // BEGIN Generated from CLDR data
// *INDENT-OFF*
// clang-format off
""" """

View File

@ -30,12 +30,9 @@ static const NamedEnumTable<SizeUnit>&
unitSuffixes() unitSuffixes()
{ {
static const NamedEnumTable< SizeUnit > names { static const NamedEnumTable< SizeUnit > names {
{ QStringLiteral( "%" ), SizeUnit::Percent }, { QStringLiteral( "%" ), SizeUnit::Percent }, { QStringLiteral( "K" ), SizeUnit::KiB },
{ QStringLiteral( "K" ), SizeUnit::KiB }, { QStringLiteral( "KiB" ), SizeUnit::KiB }, { QStringLiteral( "M" ), SizeUnit::MiB },
{ QStringLiteral( "KiB" ), SizeUnit::KiB }, { QStringLiteral( "MiB" ), SizeUnit::MiB }, { QStringLiteral( "G" ), SizeUnit::GiB },
{ QStringLiteral( "M" ), SizeUnit::MiB },
{ QStringLiteral( "MiB" ), SizeUnit::MiB },
{ QStringLiteral( "G" ), SizeUnit::GiB },
{ QStringLiteral( "GiB" ), SizeUnit::GiB } { QStringLiteral( "GiB" ), SizeUnit::GiB }
}; };
@ -55,8 +52,10 @@ PartitionSize::PartitionSize( const QString& s )
{ {
m_value = s.toInt(); m_value = s.toInt();
if ( m_value > 0 ) if ( m_value > 0 )
{
m_unit = SizeUnit::Byte; m_unit = SizeUnit::Byte;
} }
}
if ( m_value <= 0 ) if ( m_value <= 0 )
{ {
@ -69,9 +68,13 @@ qint64
PartitionSize::toSectors( qint64 totalSectors, qint64 sectorSize ) const PartitionSize::toSectors( qint64 totalSectors, qint64 sectorSize ) const
{ {
if ( !isValid() ) if ( !isValid() )
{
return -1; return -1;
}
if ( totalSectors < 1 || sectorSize < 1 ) if ( totalSectors < 1 || sectorSize < 1 )
{
return -1; return -1;
}
switch ( m_unit ) switch ( m_unit )
{ {
@ -79,9 +82,13 @@ PartitionSize::toSectors( qint64 totalSectors, qint64 sectorSize ) const
return -1; return -1;
case SizeUnit::Percent: case SizeUnit::Percent:
if ( value() == 100 ) if ( value() == 100 )
{
return totalSectors; // Common-case, avoid futzing around return totalSectors; // Common-case, avoid futzing around
}
else else
{
return totalSectors * value() / 100; return totalSectors * value() / 100;
}
case SizeUnit::Byte: case SizeUnit::Byte:
case SizeUnit::KiB: case SizeUnit::KiB:
case SizeUnit::MiB: case SizeUnit::MiB:
@ -96,7 +103,9 @@ qint64
PartitionSize::toBytes( qint64 totalSectors, qint64 sectorSize ) const PartitionSize::toBytes( qint64 totalSectors, qint64 sectorSize ) const
{ {
if ( !isValid() ) if ( !isValid() )
{
return -1; return -1;
}
switch ( m_unit ) switch ( m_unit )
{ {
@ -104,11 +113,17 @@ PartitionSize::toBytes( qint64 totalSectors, qint64 sectorSize ) const
return -1; return -1;
case SizeUnit::Percent: case SizeUnit::Percent:
if ( totalSectors < 1 || sectorSize < 1 ) if ( totalSectors < 1 || sectorSize < 1 )
{
return -1; return -1;
}
if ( value() == 100 ) if ( value() == 100 )
{
return totalSectors * sectorSize; // Common-case, avoid futzing around return totalSectors * sectorSize; // Common-case, avoid futzing around
}
else else
{
return totalSectors * value() / 100; return totalSectors * value() / 100;
}
case SizeUnit::Byte: case SizeUnit::Byte:
case SizeUnit::KiB: case SizeUnit::KiB:
case SizeUnit::MiB: case SizeUnit::MiB:
@ -124,7 +139,9 @@ qint64
PartitionSize::toBytes( qint64 totalBytes ) const PartitionSize::toBytes( qint64 totalBytes ) const
{ {
if ( !isValid() ) if ( !isValid() )
{
return -1; return -1;
}
switch ( m_unit ) switch ( m_unit )
{ {
@ -132,11 +149,17 @@ PartitionSize::toBytes( qint64 totalBytes ) const
return -1; return -1;
case SizeUnit::Percent: case SizeUnit::Percent:
if ( totalBytes < 1 ) if ( totalBytes < 1 )
{
return -1; return -1;
}
if ( value() == 100 ) if ( value() == 100 )
{
return totalBytes; // Common-case, avoid futzing around return totalBytes; // Common-case, avoid futzing around
}
else else
{
return totalBytes * value() / 100; return totalBytes * value() / 100;
}
case SizeUnit::Byte: case SizeUnit::Byte:
case SizeUnit::KiB: case SizeUnit::KiB:
case SizeUnit::MiB: case SizeUnit::MiB:
@ -152,7 +175,9 @@ qint64
PartitionSize::toBytes() const PartitionSize::toBytes() const
{ {
if ( !isValid() ) if ( !isValid() )
{
return -1; return -1;
}
switch ( m_unit ) switch ( m_unit )
{ {
@ -175,7 +200,9 @@ bool
PartitionSize::operator<( const PartitionSize& other ) const PartitionSize::operator<( const PartitionSize& other ) const
{ {
if ( !unitsComparable( m_unit, other.m_unit ) ) if ( !unitsComparable( m_unit, other.m_unit ) )
{
return false; return false;
}
switch ( m_unit ) switch ( m_unit )
{ {
@ -196,7 +223,9 @@ bool
PartitionSize::operator>( const PartitionSize& other ) const PartitionSize::operator>( const PartitionSize& other ) const
{ {
if ( !unitsComparable( m_unit, other.m_unit ) ) if ( !unitsComparable( m_unit, other.m_unit ) )
{
return false; return false;
}
switch ( m_unit ) switch ( m_unit )
{ {
@ -217,7 +246,9 @@ bool
PartitionSize::operator==( const PartitionSize& other ) const PartitionSize::operator==( const PartitionSize& other ) const
{ {
if ( !unitsComparable( m_unit, other.m_unit ) ) if ( !unitsComparable( m_unit, other.m_unit ) )
{
return false; return false;
}
switch ( m_unit ) switch ( m_unit )
{ {
@ -234,5 +265,5 @@ PartitionSize::operator== ( const PartitionSize& other ) const
NOTREACHED return false; NOTREACHED return false;
} }
} } // namespace Partition
} // namespace } // namespace CalamaresUtils

View File

@ -20,8 +20,8 @@
#ifndef PARTITION_PARTITIONSIZE_H #ifndef PARTITION_PARTITIONSIZE_H
#define PARTITION_PARTITIONSIZE_H #define PARTITION_PARTITIONSIZE_H
#include "utils/Units.h"
#include "utils/NamedSuffix.h" #include "utils/NamedSuffix.h"
#include "utils/Units.h"
// Qt // Qt
#include <QString> #include <QString>
@ -50,14 +50,17 @@ enum class SizeUnit
class PartitionSize : public NamedSuffix< SizeUnit, SizeUnit::None > class PartitionSize : public NamedSuffix< SizeUnit, SizeUnit::None >
{ {
public: public:
PartitionSize() : NamedSuffix() { } PartitionSize()
PartitionSize( int v, SizeUnit u ) : NamedSuffix( v, u ) { } : NamedSuffix()
{
}
PartitionSize( int v, SizeUnit u )
: NamedSuffix( v, u )
{
}
PartitionSize( const QString& ); PartitionSize( const QString& );
bool isValid() const bool isValid() const { return ( unit() != SizeUnit::None ) && ( value() > 0 ); }
{
return ( unit() != SizeUnit::None ) && ( value() > 0 );
}
bool operator<( const PartitionSize& other ) const; bool operator<( const PartitionSize& other ) const;
bool operator>( const PartitionSize& other ) const; bool operator>( const PartitionSize& other ) const;
@ -109,14 +112,13 @@ public:
*/ */
static constexpr bool unitsComparable( const SizeUnit u1, const SizeUnit u2 ) static constexpr bool unitsComparable( const SizeUnit u1, const SizeUnit u2 )
{ {
return !( ( u1 == SizeUnit::None || u2 == SizeUnit::None ) || return !( ( u1 == SizeUnit::None || u2 == SizeUnit::None )
( u1 == SizeUnit::Percent && u2 != SizeUnit::Percent ) || || ( u1 == SizeUnit::Percent && u2 != SizeUnit::Percent )
( u1 != SizeUnit::Percent && u2 == SizeUnit::Percent ) ); || ( u1 != SizeUnit::Percent && u2 == SizeUnit::Percent ) );
} }
}; };
} } // namespace Partition
} // namespace } // namespace CalamaresUtils
#endif // PARTITION_PARTITIONSIZE_H #endif // PARTITION_PARTITIONSIZE_H

View File

@ -31,13 +31,9 @@ Q_DECLARE_METATYPE( SizeUnit )
QTEST_GUILESS_MAIN( PartitionSizeTests ) QTEST_GUILESS_MAIN( PartitionSizeTests )
PartitionSizeTests::PartitionSizeTests() PartitionSizeTests::PartitionSizeTests() {}
{
}
PartitionSizeTests::~PartitionSizeTests() PartitionSizeTests::~PartitionSizeTests() {}
{
}
void void
PartitionSizeTests::initTestCase() PartitionSizeTests::initTestCase()
@ -73,10 +69,12 @@ PartitionSizeTests::testUnitComparison_data()
static bool static bool
original_compare( SizeUnit m_unit, SizeUnit other_m_unit ) original_compare( SizeUnit m_unit, SizeUnit other_m_unit )
{ {
if ( ( m_unit == SizeUnit::None || other_m_unit == SizeUnit::None ) || if ( ( m_unit == SizeUnit::None || other_m_unit == SizeUnit::None )
( m_unit == SizeUnit::Percent && other_m_unit != SizeUnit::Percent ) || || ( m_unit == SizeUnit::Percent && other_m_unit != SizeUnit::Percent )
( m_unit != SizeUnit::Percent && other_m_unit == SizeUnit::Percent ) ) || ( m_unit != SizeUnit::Percent && other_m_unit == SizeUnit::Percent ) )
{
return false; return false;
}
return true; return true;
} }

View File

@ -19,10 +19,10 @@
#include "CalamaresUtilsSystem.h" #include "CalamaresUtilsSystem.h"
#include "utils/Logger.h"
#include "GlobalStorage.h" #include "GlobalStorage.h"
#include "JobQueue.h" #include "JobQueue.h"
#include "Settings.h" #include "Settings.h"
#include "utils/Logger.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QDir> #include <QDir>
@ -34,8 +34,11 @@
#endif #endif
#ifdef Q_OS_FREEBSD #ifdef Q_OS_FREEBSD
// clang-format off
// these includes need to stay in-order (that's a FreeBSD thing)
#include <sys/types.h> #include <sys/types.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
// clang-format on
#endif #endif
/** @brief When logging commands, don't log everything. /** @brief When logging commands, don't log everything.
@ -63,12 +66,18 @@ operator<<( QDebug& s, const RedactedList& l )
{ {
for ( const auto& item : l.list ) for ( const auto& item : l.list )
if ( item.startsWith( "$6$" ) ) if ( item.startsWith( "$6$" ) )
{
s << "<password>"; s << "<password>";
else
s << item;
} }
else else
{
s << item;
}
}
else
{
s << l.list; s << l.list;
}
return s; return s;
} }
@ -92,8 +101,7 @@ System::System( bool doChroot, QObject* parent )
} }
System::~System() System::~System() {}
{}
System* System*
@ -118,9 +126,13 @@ System::mount( const QString& devicePath,
if ( devicePath.isEmpty() || mountPoint.isEmpty() ) if ( devicePath.isEmpty() || mountPoint.isEmpty() )
{ {
if ( devicePath.isEmpty() ) if ( devicePath.isEmpty() )
{
cWarning() << "Can't mount an empty device."; cWarning() << "Can't mount an empty device.";
}
if ( mountPoint.isEmpty() ) if ( mountPoint.isEmpty() )
{
cWarning() << "Can't mount on an empty mountpoint."; cWarning() << "Can't mount on an empty mountpoint.";
}
return static_cast< int >( ProcessResult::Code::NoWorkingDirectory ); return static_cast< int >( ProcessResult::Code::NoWorkingDirectory );
} }
@ -140,17 +152,20 @@ System::mount( const QString& devicePath,
QStringList args = { devicePath, mountPoint }; QStringList args = { devicePath, mountPoint };
if ( !filesystemName.isEmpty() ) if ( !filesystemName.isEmpty() )
{
args << "-t" << filesystemName; args << "-t" << filesystemName;
}
if ( !options.isEmpty() ) if ( !options.isEmpty() )
{
args << "-o" << options; args << "-o" << options;
}
return QProcess::execute( program, args ); return QProcess::execute( program, args );
} }
ProcessResult ProcessResult
System::runCommand( System::runCommand( System::RunLocation location,
System::RunLocation location,
const QStringList& args, const QStringList& args,
const QString& workingPath, const QString& workingPath,
const QString& stdInput, const QString& stdInput,
@ -158,10 +173,10 @@ System::runCommand(
{ {
QString output; QString output;
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; Calamares::GlobalStorage* gs
= Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr;
if ( ( location == System::RunLocation::RunInTarget ) && if ( ( location == System::RunLocation::RunInTarget ) && ( !gs || !gs->contains( "rootMountPoint" ) ) )
( !gs || !gs->contains( "rootMountPoint" ) ) )
{ {
cWarning() << "No rootMountPoint in global storage"; cWarning() << "No rootMountPoint in global storage";
return ProcessResult::Code::NoWorkingDirectory; return ProcessResult::Code::NoWorkingDirectory;
@ -197,7 +212,9 @@ System::runCommand(
if ( !workingPath.isEmpty() ) if ( !workingPath.isEmpty() )
{ {
if ( QDir( workingPath ).exists() ) if ( QDir( workingPath ).exists() )
{
process.setWorkingDirectory( QDir( workingPath ).absolutePath() ); process.setWorkingDirectory( QDir( workingPath ).absolutePath() );
}
else else
{ {
cWarning() << "Invalid working directory:" << workingPath; cWarning() << "Invalid working directory:" << workingPath;
@ -219,10 +236,10 @@ System::runCommand(
} }
process.closeWriteChannel(); process.closeWriteChannel();
if ( !process.waitForFinished( timeoutSec > std::chrono::seconds::zero() ? ( std::chrono::milliseconds( timeoutSec ).count() ) : -1 ) ) if ( !process.waitForFinished(
timeoutSec > std::chrono::seconds::zero() ? ( std::chrono::milliseconds( timeoutSec ).count() ) : -1 ) )
{ {
cWarning().noquote().nospace() << "Timed out. Output so far:\n" << cWarning().noquote().nospace() << "Timed out. Output so far:\n" << process.readAllStandardOutput();
process.readAllStandardOutput();
return ProcessResult::Code::TimedOut; return ProcessResult::Code::TimedOut;
} }
@ -252,7 +269,8 @@ System::targetPath( const QString& path ) const
if ( doChroot() ) if ( doChroot() )
{ {
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; Calamares::GlobalStorage* gs
= Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr;
if ( !gs || !gs->contains( "rootMountPoint" ) ) if ( !gs || !gs->contains( "rootMountPoint" ) )
{ {
@ -317,7 +335,9 @@ System::getTotalMemoryB() const
int r = sysinfo( &i ); int r = sysinfo( &i );
if ( r ) if ( r )
{
return qMakePair( 0, 0.0 ); return qMakePair( 0, 0.0 );
}
return qMakePair( quint64( i.mem_unit ) * quint64( i.totalram ), 1.1 ); return qMakePair( quint64( i.mem_unit ) * quint64( i.totalram ), 1.1 );
#elif defined( Q_OS_FREEBSD ) #elif defined( Q_OS_FREEBSD )
@ -326,7 +346,9 @@ System::getTotalMemoryB() const
int r = sysctlbyname( "vm.kmem_size", &memsize, &s, NULL, 0 ); int r = sysctlbyname( "vm.kmem_size", &memsize, &s, NULL, 0 );
if ( r ) if ( r )
{
return qMakePair( 0, 0.0 ); return qMakePair( 0, 0.0 );
}
return qMakePair( memsize, 1.01 ); return qMakePair( memsize, 1.01 );
#else #else
@ -376,40 +398,45 @@ ProcessResult::explainProcess( int ec, const QString& command, const QString& ou
using Calamares::JobResult; using Calamares::JobResult;
if ( ec == 0 ) if ( ec == 0 )
{
return JobResult::ok(); return JobResult::ok();
}
QString outputMessage = output.isEmpty() QString outputMessage = output.isEmpty()
? QCoreApplication::translate( "ProcessResult", "\nThere was no output from the command." ) ? QCoreApplication::translate( "ProcessResult", "\nThere was no output from the command." )
: ( QCoreApplication::translate( "ProcessResult", "\nOutput:\n" ) + output ); : ( QCoreApplication::translate( "ProcessResult", "\nOutput:\n" ) + output );
if ( ec == static_cast< int >( ProcessResult::Code::Crashed ) ) //Crash! if ( ec == static_cast< int >( ProcessResult::Code::Crashed ) ) //Crash!
return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command crashed." ), return JobResult::error(
QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> crashed." ) QCoreApplication::translate( "ProcessResult", "External command crashed." ),
.arg( command ) QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> crashed." ).arg( command )
+ outputMessage ); + outputMessage );
if ( ec == static_cast< int >( ProcessResult::Code::FailedToStart ) ) if ( ec == static_cast< int >( ProcessResult::Code::FailedToStart ) )
return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to start." ), return JobResult::error(
QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> failed to start." ) QCoreApplication::translate( "ProcessResult", "External command failed to start." ),
.arg( command ) ); QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> failed to start." ).arg( command ) );
if ( ec == static_cast< int >( ProcessResult::Code::NoWorkingDirectory ) ) if ( ec == static_cast< int >( ProcessResult::Code::NoWorkingDirectory ) )
return JobResult::error( QCoreApplication::translate( "ProcessResult", "Internal error when starting command." ), return JobResult::error(
QCoreApplication::translate( "ProcessResult", "Internal error when starting command." ),
QCoreApplication::translate( "ProcessResult", "Bad parameters for process job call." ) ); QCoreApplication::translate( "ProcessResult", "Bad parameters for process job call." ) );
if ( ec == static_cast< int >( ProcessResult::Code::TimedOut ) ) if ( ec == static_cast< int >( ProcessResult::Code::TimedOut ) )
return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to finish." ), return JobResult::error(
QCoreApplication::translate( "ProcessResult", "External command failed to finish." ),
QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> failed to finish in %2 seconds." ) QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> failed to finish in %2 seconds." )
.arg( command ) .arg( command )
.arg( timeout.count() ) .arg( timeout.count() )
+ outputMessage ); + outputMessage );
//Any other exit code //Any other exit code
return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command finished with errors." ), return JobResult::error(
QCoreApplication::translate( "ProcessResult", "External command finished with errors." ),
QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> finished with exit code %2." ) QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> finished with exit code %2." )
.arg( command ) .arg( command )
.arg( ec ) .arg( ec )
+ outputMessage ); + outputMessage );
} }
} // namespace } // namespace CalamaresUtils

View File

@ -43,8 +43,14 @@ public:
}; };
/** @brief Implicit one-argument constructor has no output, only a return code */ /** @brief Implicit one-argument constructor has no output, only a return code */
ProcessResult( Code r ) : QPair< int, QString >( static_cast<int>(r), QString() ) {} ProcessResult( Code r )
ProcessResult( int r, QString s ) : QPair< int, QString >( r, s ) {} : QPair< int, QString >( static_cast< int >( r ), QString() )
{
}
ProcessResult( int r, QString s )
: QPair< int, QString >( r, s )
{
}
int getExitCode() const { return first; } int getExitCode() const { return first; }
QString getOutput() const { return second; } QString getOutput() const { return second; }
@ -62,7 +68,8 @@ public:
* @param timeout Timeout passed to the process runner, for explaining * @param timeout Timeout passed to the process runner, for explaining
* error code -4 (timeout). * error code -4 (timeout).
*/ */
static Calamares::JobResult explainProcess( int errorCode, const QString& command, const QString& output, std::chrono::seconds timeout ); static Calamares::JobResult
explainProcess( int errorCode, const QString& command, const QString& output, std::chrono::seconds timeout );
/// @brief Convenience wrapper for explainProcess() /// @brief Convenience wrapper for explainProcess()
inline Calamares::JobResult explainProcess( const QString& command, std::chrono::seconds timeout ) const inline Calamares::JobResult explainProcess( const QString& command, std::chrono::seconds timeout ) const
@ -116,7 +123,11 @@ public:
/** (Typed) Boolean describing where a particular command should be run, /** (Typed) Boolean describing where a particular command should be run,
* whether in the host (live) system or in the (chroot) target system. * whether in the host (live) system or in the (chroot) target system.
*/ */
enum class RunLocation { RunInHost, RunInTarget }; enum class RunLocation
{
RunInHost,
RunInTarget
};
/** /**
* Runs the specified command in the chroot of the target system. * Runs the specified command in the chroot of the target system.
@ -135,8 +146,7 @@ public:
* NoWorkingDirectory = bad arguments * NoWorkingDirectory = bad arguments
* TimedOut = QProcess timeout * TimedOut = QProcess timeout
*/ */
static DLLEXPORT ProcessResult runCommand( static DLLEXPORT ProcessResult runCommand( RunLocation location,
RunLocation location,
const QStringList& args, const QStringList& args,
const QString& workingPath = QString(), const QString& workingPath = QString(),
const QString& stdInput = QString(), const QString& stdInput = QString(),
@ -147,18 +157,13 @@ public:
* doChroot(), which is what you usually want for running commands * doChroot(), which is what you usually want for running commands
* during installation. * during installation.
*/ */
inline ProcessResult targetEnvCommand( inline ProcessResult targetEnvCommand( const QStringList& args,
const QStringList &args,
const QString& workingPath = QString(), const QString& workingPath = QString(),
const QString& stdInput = QString(), const QString& stdInput = QString(),
std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) ) std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) )
{ {
return runCommand( return runCommand(
m_doChroot ? RunLocation::RunInTarget : RunLocation::RunInHost, m_doChroot ? RunLocation::RunInTarget : RunLocation::RunInHost, args, workingPath, stdInput, timeoutSec );
args,
workingPath,
stdInput,
timeoutSec );
} }
/** @brief Convenience wrapper for targetEnvCommand() which returns only the exit code */ /** @brief Convenience wrapper for targetEnvCommand() which returns only the exit code */
@ -279,6 +284,6 @@ private:
bool m_doChroot; bool m_doChroot;
}; };
} // namespace } // namespace CalamaresUtils
#endif #endif

View File

@ -32,34 +32,44 @@
namespace CalamaresUtils namespace CalamaresUtils
{ {
static CommandLine get_variant_object( const QVariantMap& m ) static CommandLine
get_variant_object( const QVariantMap& m )
{ {
QString command = CalamaresUtils::getString( m, "command" ); QString command = CalamaresUtils::getString( m, "command" );
int timeout = CalamaresUtils::getInteger( m, "timeout", -1 ); int timeout = CalamaresUtils::getInteger( m, "timeout", -1 );
if ( !command.isEmpty() ) if ( !command.isEmpty() )
{
return CommandLine( command, timeout >= 0 ? std::chrono::seconds( timeout ) : CommandLine::TimeoutNotSet() ); return CommandLine( command, timeout >= 0 ? std::chrono::seconds( timeout ) : CommandLine::TimeoutNotSet() );
}
cWarning() << "Bad CommandLine element" << m; cWarning() << "Bad CommandLine element" << m;
return CommandLine(); return CommandLine();
} }
static CommandList_t get_variant_stringlist( const QVariantList& l ) static CommandList_t
get_variant_stringlist( const QVariantList& l )
{ {
CommandList_t retl; CommandList_t retl;
unsigned int count = 0; unsigned int count = 0;
for ( const auto& v : l ) for ( const auto& v : l )
{ {
if ( v.type() == QVariant::String ) if ( v.type() == QVariant::String )
{
retl.append( CommandLine( v.toString(), CommandLine::TimeoutNotSet() ) ); retl.append( CommandLine( v.toString(), CommandLine::TimeoutNotSet() ) );
}
else if ( v.type() == QVariant::Map ) else if ( v.type() == QVariant::Map )
{ {
auto command( get_variant_object( v.toMap() ) ); auto command( get_variant_object( v.toMap() ) );
if ( command.isValid() ) if ( command.isValid() )
{
retl.append( command ); retl.append( command );
}
// Otherwise warning is already given // Otherwise warning is already given
} }
else else
{
cWarning() << "Bad CommandList element" << count << v.type() << v; cWarning() << "Bad CommandList element" << count << v.type() << v;
}
++count; ++count;
} }
return retl; return retl;
@ -78,37 +88,48 @@ CommandList::CommandList::CommandList( const QVariant& v, bool doChroot, std::ch
{ {
const auto v_list = v.toList(); const auto v_list = v.toList();
if ( v_list.count() ) if ( v_list.count() )
{
append( get_variant_stringlist( v_list ) ); append( get_variant_stringlist( v_list ) );
}
else else
{
cWarning() << "Empty CommandList"; cWarning() << "Empty CommandList";
} }
}
else if ( v.type() == QVariant::String ) else if ( v.type() == QVariant::String )
{
append( v.toString() ); append( v.toString() );
}
else if ( v.type() == QVariant::Map ) else if ( v.type() == QVariant::Map )
{ {
auto c( get_variant_object( v.toMap() ) ); auto c( get_variant_object( v.toMap() ) );
if ( c.isValid() ) if ( c.isValid() )
{
append( c ); append( c );
}
// Otherwise warning is already given // Otherwise warning is already given
} }
else else
{
cWarning() << "CommandList does not understand variant" << v.type(); cWarning() << "CommandList does not understand variant" << v.type();
} }
CommandList::~CommandList()
{
} }
CommandList::~CommandList() {}
static inline bool static inline bool
findInCommands( const CommandList& l, const QString& needle ) findInCommands( const CommandList& l, const QString& needle )
{ {
for ( CommandList::const_iterator i = l.cbegin(); i != l.cend(); ++i ) for ( CommandList::const_iterator i = l.cbegin(); i != l.cend(); ++i )
if ( i->command().contains( needle ) ) if ( i->command().contains( needle ) )
{
return true; return true;
}
return false; return false;
} }
Calamares::JobResult CommandList::run() Calamares::JobResult
CommandList::run()
{ {
QLatin1Literal rootMagic( "@@ROOT@@" ); QLatin1Literal rootMagic( "@@ROOT@@" );
QLatin1Literal userMagic( "@@USER@@" ); QLatin1Literal userMagic( "@@USER@@" );
@ -125,8 +146,11 @@ Calamares::JobResult CommandList::run()
if ( !gs || !gs->contains( "rootMountPoint" ) ) if ( !gs || !gs->contains( "rootMountPoint" ) )
{ {
cError() << "No rootMountPoint defined."; cError() << "No rootMountPoint defined.";
return Calamares::JobResult::error( QCoreApplication::translate( "CommandList", "Could not run command." ), return Calamares::JobResult::error(
QCoreApplication::translate( "CommandList", "The command runs in the host environment and needs to know the root path, but no rootMountPoint is defined." ) ); QCoreApplication::translate( "CommandList", "Could not run command." ),
QCoreApplication::translate( "CommandList",
"The command runs in the host environment and needs to know the root "
"path, but no rootMountPoint is defined." ) );
} }
root = gs->value( "rootMountPoint" ).toString(); root = gs->value( "rootMountPoint" ).toString();
} }
@ -137,7 +161,8 @@ Calamares::JobResult CommandList::run()
cError() << "No username defined."; cError() << "No username defined.";
return Calamares::JobResult::error( return Calamares::JobResult::error(
QCoreApplication::translate( "CommandList", "Could not run command." ), QCoreApplication::translate( "CommandList", "Could not run command." ),
QCoreApplication::translate( "CommandList", "The command needs to know the user's name, but no username is defined." ) ); QCoreApplication::translate( "CommandList",
"The command needs to know the user's name, but no username is defined." ) );
} }
QString user = gs->value( "username" ).toString(); // may be blank if unset QString user = gs->value( "username" ).toString(); // may be blank if unset
@ -156,17 +181,20 @@ Calamares::JobResult CommandList::run()
shell_cmd << processed_cmd; shell_cmd << processed_cmd;
std::chrono::seconds timeout = i->timeout() >= std::chrono::seconds::zero() ? i->timeout() : m_timeout; std::chrono::seconds timeout = i->timeout() >= std::chrono::seconds::zero() ? i->timeout() : m_timeout;
ProcessResult r = System::runCommand( ProcessResult r = System::runCommand( location, shell_cmd, QString(), QString(), timeout );
location, shell_cmd, QString(), QString(), timeout );
if ( r.getExitCode() != 0 ) if ( r.getExitCode() != 0 )
{ {
if ( suppress_result ) if ( suppress_result )
{
cDebug() << "Error code" << r.getExitCode() << "ignored by CommandList configuration."; cDebug() << "Error code" << r.getExitCode() << "ignored by CommandList configuration.";
}
else else
{
return r.explainProcess( processed_cmd, timeout ); return r.explainProcess( processed_cmd, timeout );
} }
} }
}
return Calamares::JobResult::ok(); return Calamares::JobResult::ok();
} }
@ -177,4 +205,4 @@ CommandList::append( const QString& s )
append( CommandLine( s, m_timeout ) ); append( CommandLine( s, m_timeout ) );
} }
} // namespace } // namespace CalamaresUtils

View File

@ -53,20 +53,11 @@ struct CommandLine : public QPair< QString, std::chrono::seconds >
{ {
} }
QString command() const QString command() const { return first; }
{
return first;
}
std::chrono::seconds timeout() const std::chrono::seconds timeout() const { return second; }
{
return second;
}
bool isValid() const bool isValid() const { return !first.isEmpty(); }
{
return !first.isEmpty();
}
}; };
/** @brief Abbreviation, used internally. */ /** @brief Abbreviation, used internally. */
@ -88,19 +79,16 @@ public:
CommandList( const QVariant& v, bool doChroot = true, std::chrono::seconds timeout = std::chrono::seconds( 10 ) ); CommandList( const QVariant& v, bool doChroot = true, std::chrono::seconds timeout = std::chrono::seconds( 10 ) );
~CommandList(); ~CommandList();
bool doChroot() const bool doChroot() const { return m_doChroot; }
{
return m_doChroot;
}
Calamares::JobResult run(); Calamares::JobResult run();
using CommandList_t::isEmpty; using CommandList_t::at;
using CommandList_t::count;
using CommandList_t::cbegin; using CommandList_t::cbegin;
using CommandList_t::cend; using CommandList_t::cend;
using CommandList_t::const_iterator; using CommandList_t::const_iterator;
using CommandList_t::at; using CommandList_t::count;
using CommandList_t::isEmpty;
protected: protected:
using CommandList_t::append; using CommandList_t::append;
@ -111,5 +99,5 @@ private:
std::chrono::seconds m_timeout; std::chrono::seconds m_timeout;
}; };
} // namespace } // namespace CalamaresUtils
#endif #endif

View File

@ -101,18 +101,26 @@ mungeEnvironment( QStringList& l, const char* name, const char* defaultDirs )
QStringList dirs = QString( qgetenv( name ) ).split( ':' ); QStringList dirs = QString( qgetenv( name ) ).split( ':' );
if ( dirs.isEmpty() ) if ( dirs.isEmpty() )
{
dirs = QString( defaultDirs ).split( ':' ); dirs = QString( defaultDirs ).split( ':' );
}
for ( auto s : dirs ) for ( auto s : dirs )
{ {
if ( s.isEmpty() ) if ( s.isEmpty() )
{
continue; continue;
}
if ( s.endsWith( '/' ) ) if ( s.endsWith( '/' ) )
{
l << ( s + calamaresSubdir ) << s; l << ( s + calamaresSubdir ) << s;
}
else else
{
l << ( s + '/' + calamaresSubdir ) << ( s + '/' ); l << ( s + '/' + calamaresSubdir ) << ( s + '/' );
} }
} }
}
void void
setXdgDirs() setXdgDirs()
@ -127,7 +135,9 @@ QStringList
extraConfigDirs() extraConfigDirs()
{ {
if ( s_haveExtraDirs ) if ( s_haveExtraDirs )
{
return s_extraConfigDirs; return s_extraConfigDirs;
}
return QStringList(); return QStringList();
} }
@ -135,7 +145,9 @@ QStringList
extraDataDirs() extraDataDirs()
{ {
if ( s_haveExtraDirs ) if ( s_haveExtraDirs )
{
return s_extraDataDirs; return s_extraDataDirs;
}
return QStringList(); return QStringList();
} }
@ -173,12 +185,16 @@ appLogDir()
QString path = QStandardPaths::writableLocation( QStandardPaths::CacheLocation ); QString path = QStandardPaths::writableLocation( QStandardPaths::CacheLocation );
QDir dir( path ); QDir dir( path );
if ( isWritableDir( dir ) ) if ( isWritableDir( dir ) )
{
return dir; return dir;
}
cerr << "warning: Could not find a standard writable location for log dir, falling back to $HOME\n"; cerr << "warning: Could not find a standard writable location for log dir, falling back to $HOME\n";
dir = QDir::home(); dir = QDir::home();
if ( isWritableDir( dir ) ) if ( isWritableDir( dir ) )
{
return dir; return dir;
}
cerr << "warning: Found no writable location for log dir, falling back to the temp dir\n"; cerr << "warning: Found no writable location for log dir, falling back to the temp dir\n";
return QDir::temp(); return QDir::temp();
@ -191,4 +207,4 @@ setQmlModulesDir( const QDir& dir )
s_qmlModulesDir = dir; s_qmlModulesDir = dir;
} }
} // namespace } // namespace CalamaresUtils

View File

@ -68,6 +68,6 @@ namespace CalamaresUtils
DLLEXPORT QStringList extraConfigDirs(); DLLEXPORT QStringList extraConfigDirs();
/** @brief XDG_DATA_DIRS, each guaranteed to end with / */ /** @brief XDG_DATA_DIRS, each guaranteed to end with / */
DLLEXPORT QStringList extraDataDirs(); DLLEXPORT QStringList extraDataDirs();
} // namespace } // namespace CalamaresUtils
#endif #endif

View File

@ -20,8 +20,8 @@
#include "Logger.h" #include "Logger.h"
#include <iostream>
#include <fstream> #include <fstream>
#include <iostream>
#include <QCoreApplication> #include <QCoreApplication>
#include <QDir> #include <QDir>
@ -30,8 +30,8 @@
#include <QTime> #include <QTime>
#include <QVariant> #include <QVariant>
#include "utils/Dirs.h"
#include "CalamaresVersion.h" #include "CalamaresVersion.h"
#include "utils/Dirs.h"
#define LOGFILE_SIZE 1024 * 256 #define LOGFILE_SIZE 1024 * 256
@ -51,7 +51,9 @@ void
setupLogLevel( unsigned int level ) setupLogLevel( unsigned int level )
{ {
if ( level > LOGVERBOSE ) if ( level > LOGVERBOSE )
{
level = LOGVERBOSE; level = LOGVERBOSE;
}
s_threshold = level + 1; // Comparison is < in log() function s_threshold = level + 1; // Comparison is < in log() function
} }
@ -77,11 +79,9 @@ log( const char* msg, unsigned int debugLevel )
// If we don't format the date as a Qt::ISODate then we get a crash when // If we don't format the date as a Qt::ISODate then we get a crash when
// logging at exit as Qt tries to use QLocale to format, but QLocale is // logging at exit as Qt tries to use QLocale to format, but QLocale is
// on its way out. // on its way out.
logfile << QDate::currentDate().toString( Qt::ISODate ).toUtf8().data() logfile << QDate::currentDate().toString( Qt::ISODate ).toUtf8().data() << " - "
<< " - " << QTime::currentTime().toString().toUtf8().data() << " ["
<< QTime::currentTime().toString().toUtf8().data() << QString::number( debugLevel ).toUtf8().data() << "]: " << msg << std::endl;
<< " [" << QString::number( debugLevel ).toUtf8().data() << "]: "
<< msg << std::endl;
logfile.flush(); logfile.flush();
} }
@ -90,9 +90,8 @@ log( const char* msg, unsigned int debugLevel )
{ {
QMutexLocker lock( &s_mutex ); QMutexLocker lock( &s_mutex );
std::cout << QTime::currentTime().toString().toUtf8().data() std::cout << QTime::currentTime().toString().toUtf8().data() << " ["
<< " [" << QString::number( debugLevel ).toUtf8().data() << "]: " << QString::number( debugLevel ).toUtf8().data() << "]: " << msg << std::endl;
<< msg << std::endl;
std::cout.flush(); std::cout.flush();
} }
} }
@ -164,7 +163,9 @@ setupLogfile()
QMutexLocker lock( &s_mutex ); QMutexLocker lock( &s_mutex );
logfile.open( logFile().toLocal8Bit(), std::ios::app ); logfile.open( logFile().toLocal8Bit(), std::ios::app );
if ( logfile.tellp() ) if ( logfile.tellp() )
{
logfile << "\n\n" << std::endl; logfile << "\n\n" << std::endl;
}
logfile << "=== START CALAMARES " << CALAMARES_VERSION << std::endl; logfile << "=== START CALAMARES " << CALAMARES_VERSION << std::endl;
} }
@ -183,14 +184,13 @@ CLog::~CLog()
log( m_msg.toUtf8().data(), m_debugLevel ); log( m_msg.toUtf8().data(), m_debugLevel );
} }
CDebug::~CDebug() CDebug::~CDebug() {}
{
}
const char Continuation[] = "\n "; const char Continuation[] = "\n ";
const char SubEntry[] = " .. "; const char SubEntry[] = " .. ";
QString toString( const QVariant& v ) QString
toString( const QVariant& v )
{ {
auto t = v.type(); auto t = v.type();
@ -199,11 +199,15 @@ QString toString( const QVariant& v )
QStringList s; QStringList s;
auto l = v.toList(); auto l = v.toList();
for ( auto lit = l.constBegin(); lit != l.constEnd(); ++lit ) for ( auto lit = l.constBegin(); lit != l.constEnd(); ++lit )
{
s << lit->toString(); s << lit->toString();
}
return s.join( ", " ); return s.join( ", " );
} }
else else
{
return v.toString(); return v.toString();
} }
}
} // namespace } // namespace Logger

View File

@ -55,13 +55,18 @@ namespace Logger
class DLLEXPORT CDebug : public CLog class DLLEXPORT CDebug : public CLog
{ {
public: public:
CDebug( unsigned int debugLevel = LOGDEBUG ) : CLog( debugLevel ) CDebug( unsigned int debugLevel = LOGDEBUG )
: CLog( debugLevel )
{ {
if ( debugLevel <= LOGERROR ) if ( debugLevel <= LOGERROR )
{
*this << "ERROR:"; *this << "ERROR:";
}
else if ( debugLevel <= LOGWARNING ) else if ( debugLevel <= LOGWARNING )
{
*this << "WARNING:"; *this << "WARNING:";
} }
}
virtual ~CDebug(); virtual ~CDebug();
}; };
@ -113,7 +118,8 @@ namespace Logger
explicit DebugRow( const T& t, const U& u ) explicit DebugRow( const T& t, const U& u )
: first( t ) : first( t )
, second( u ) , second( u )
{} {
}
const T& first; const T& first;
const U& second; const U& second;
@ -132,7 +138,8 @@ namespace Logger
{ {
explicit DebugList( const QStringList& l ) explicit DebugList( const QStringList& l )
: list( l ) : list( l )
{} {
}
const QStringList& list; const QStringList& list;
}; };
@ -152,7 +159,8 @@ namespace Logger
public: public:
explicit DebugMap( const QVariantMap& m ) explicit DebugMap( const QVariantMap& m )
: map( m ) : map( m )
{} {
}
const QVariantMap& map; const QVariantMap& map;
}; };
@ -171,7 +179,9 @@ namespace Logger
operator<<( QDebug& s, const DebugList& c ) operator<<( QDebug& s, const DebugList& c )
{ {
for ( const auto& i : c.list ) for ( const auto& i : c.list )
{
s << Continuation << i; s << Continuation << i;
}
return s; return s;
} }
@ -183,10 +193,12 @@ namespace Logger
operator<<( QDebug& s, const DebugMap& t ) operator<<( QDebug& s, const DebugMap& t )
{ {
for ( auto it = t.map.constBegin(); it != t.map.constEnd(); ++it ) for ( auto it = t.map.constBegin(); it != t.map.constEnd(); ++it )
{
s << Continuation << it.key().toUtf8().constData() << ':' << ' ' << toString( it.value() ).toUtf8().constData(); s << Continuation << it.key().toUtf8().constData() << ':' << ' ' << toString( it.value() ).toUtf8().constData();
}
return s; return s;
} }
} // namespace } // namespace Logger
#define cDebug Logger::CDebug #define cDebug Logger::CDebug
#define cWarning() Logger::CDebug( Logger::LOGWARNING ) #define cWarning() Logger::CDebug( Logger::LOGWARNING )

View File

@ -31,9 +31,9 @@
#include <QString> #include <QString>
#include <vector>
#include <type_traits>
#include <initializer_list> #include <initializer_list>
#include <type_traits>
#include <vector>
/** @brief Type for collecting parts of a named enum. */ /** @brief Type for collecting parts of a named enum. */
template < typename T > template < typename T >
@ -53,7 +53,11 @@ struct NamedEnumTable
* *
* static const NamedEnumTable<Colors> c{ {"red", Colors::Red } }; * static const NamedEnumTable<Colors> c{ {"red", Colors::Red } };
*/ */
NamedEnumTable( const std::initializer_list< pair_t >& v ) : table( v ) { /* static_assert( v.size() > 0 ); */ } NamedEnumTable( const std::initializer_list< pair_t >& v )
: table( v )
{
/* static_assert( v.size() > 0 ); */
}
/** @brief Find a name @p s in the table. /** @brief Find a name @p s in the table.
* *
@ -103,7 +107,8 @@ struct NamedEnumTable
/** @brief Smashes an enum value to its underlying type. */ /** @brief Smashes an enum value to its underlying type. */
template < typename E > template < typename E >
constexpr typename std::underlying_type<E>::type smash( const E e ) constexpr typename std::underlying_type< E >::type
smash( const E e )
{ {
return static_cast< typename std::underlying_type< E >::type >( e ); return static_cast< typename std::underlying_type< E >::type >( e );
} }

View File

@ -24,8 +24,11 @@
#include "PluginFactory.h" #include "PluginFactory.h"
#include "PluginFactory_p.h" #include "PluginFactory_p.h"
#include <QObjectCleanupHandler>
#include <QDebug> #include <QDebug>
#include <QObjectCleanupHandler>
// *INDENT-OFF*
// clang-format off
Q_GLOBAL_STATIC( QObjectCleanupHandler, factorycleanup ) Q_GLOBAL_STATIC( QObjectCleanupHandler, factorycleanup )

View File

@ -27,8 +27,11 @@
#include "DllMacro.h" #include "DllMacro.h"
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QVariant>
#include <QtCore/QStringList> #include <QtCore/QStringList>
#include <QtCore/QVariant>
// *INDENT-OFF*
// clang-format off
namespace Calamares namespace Calamares
{ {

View File

@ -39,7 +39,8 @@ protected:
PluginFactoryPrivate() PluginFactoryPrivate()
: catalogInitialized( false ) : catalogInitialized( false )
, q_ptr( nullptr ) , q_ptr( nullptr )
{} {
}
~PluginFactoryPrivate() {} ~PluginFactoryPrivate() {}
QHash< QString, Plugin > createInstanceHash; QHash< QString, Plugin > createInstanceHash;
@ -49,6 +50,6 @@ protected:
PluginFactory* q_ptr; PluginFactory* q_ptr;
}; };
} // namespace } // namespace Calamares
#endif #endif

View File

@ -26,27 +26,30 @@
#include <QTranslator> #include <QTranslator>
namespace CalamaresUtils { namespace CalamaresUtils
{
static QTranslator* s_brandingTranslator = nullptr; static QTranslator* s_brandingTranslator = nullptr;
static QTranslator* s_translator = nullptr; static QTranslator* s_translator = nullptr;
static QString s_translatorLocaleName; static QString s_translatorLocaleName;
void void
installTranslator( const QLocale& locale, installTranslator( const QLocale& locale, const QString& brandingTranslationsPrefix, QObject* parent )
const QString& brandingTranslationsPrefix,
QObject* parent )
{ {
QString localeName = locale.name(); QString localeName = locale.name();
localeName.replace( "-", "_" ); localeName.replace( "-", "_" );
if ( localeName == "C" ) if ( localeName == "C" )
{
localeName = "en"; localeName = "en";
}
// Special case of sr@latin // Special case of sr@latin
// //
// See top-level CMakeLists.txt about special cases for translation loading. // See top-level CMakeLists.txt about special cases for translation loading.
if ( locale.language() == QLocale::Language::Serbian && locale.script() == QLocale::Script::LatinScript ) if ( locale.language() == QLocale::Language::Serbian && locale.script() == QLocale::Script::LatinScript )
{
localeName = QStringLiteral( "sr@latin" ); localeName = QStringLiteral( "sr@latin" );
}
cDebug() << "Looking for translations for" << localeName; cDebug() << "Looking for translations for" << localeName;
@ -56,19 +59,14 @@ installTranslator( const QLocale& locale,
if ( !brandingTranslationsPrefix.isEmpty() ) if ( !brandingTranslationsPrefix.isEmpty() )
{ {
QString brandingTranslationsDirPath( brandingTranslationsPrefix ); QString brandingTranslationsDirPath( brandingTranslationsPrefix );
brandingTranslationsDirPath.truncate( brandingTranslationsPrefix.lastIndexOf( brandingTranslationsDirPath.truncate( brandingTranslationsPrefix.lastIndexOf( QDir::separator() ) );
QDir::separator() ) );
QDir brandingTranslationsDir( brandingTranslationsDirPath ); QDir brandingTranslationsDir( brandingTranslationsDirPath );
if ( brandingTranslationsDir.exists() ) if ( brandingTranslationsDir.exists() )
{ {
QString filenameBase( brandingTranslationsPrefix ); QString filenameBase( brandingTranslationsPrefix );
filenameBase.remove( 0, brandingTranslationsPrefix.lastIndexOf( filenameBase.remove( 0, brandingTranslationsPrefix.lastIndexOf( QDir::separator() ) + 1 );
QDir::separator() ) + 1 );
translator = new QTranslator( parent ); translator = new QTranslator( parent );
if ( translator->load( locale, if ( translator->load( locale, filenameBase, "_", brandingTranslationsDir.absolutePath() ) )
filenameBase,
"_",
brandingTranslationsDir.absolutePath() ) )
{ {
cDebug() << Logger::SubEntry << "Branding using locale:" << localeName; cDebug() << Logger::SubEntry << "Branding using locale:" << localeName;
} }
@ -121,19 +119,22 @@ translatorLocaleName()
} }
void void
Retranslator::attachRetranslator( QObject* parent, Retranslator::attachRetranslator( QObject* parent, std::function< void( void ) > retranslateFunc )
std::function< void ( void ) > retranslateFunc )
{ {
Retranslator* r = nullptr; Retranslator* r = nullptr;
for ( QObject* child : parent->children() ) for ( QObject* child : parent->children() )
{ {
r = qobject_cast< Retranslator* >( child ); r = qobject_cast< Retranslator* >( child );
if ( r ) if ( r )
{
break; break;
} }
}
if ( !r ) if ( !r )
{
r = new Retranslator( parent ); r = new Retranslator( parent );
}
r->m_retranslateFuncList.append( retranslateFunc ); r->m_retranslateFuncList.append( retranslateFunc );
retranslateFunc(); retranslateFunc();
@ -155,9 +156,11 @@ Retranslator::eventFilter( QObject* obj, QEvent* e )
if ( e->type() == QEvent::LanguageChange ) if ( e->type() == QEvent::LanguageChange )
{ {
foreach ( std::function< void() > func, m_retranslateFuncList ) foreach ( std::function< void() > func, m_retranslateFuncList )
{
func(); func();
} }
} }
}
// pass the event on to the base // pass the event on to the base
return QObject::eventFilter( obj, e ); return QObject::eventFilter( obj, e );
} }

View File

@ -38,9 +38,7 @@ namespace CalamaresUtils
* @param brandingTranslationsPrefix the branding path prefix, from Calamares::Branding. * @param brandingTranslationsPrefix the branding path prefix, from Calamares::Branding.
* @param parent the parent QObject. * @param parent the parent QObject.
*/ */
DLLEXPORT void installTranslator( const QLocale& locale, DLLEXPORT void installTranslator( const QLocale& locale, const QString& brandingTranslationsPrefix, QObject* parent );
const QString& brandingTranslationsPrefix,
QObject* parent );
DLLEXPORT QString translatorLocaleName(); DLLEXPORT QString translatorLocaleName();
@ -48,8 +46,7 @@ class Retranslator : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
static void attachRetranslator( QObject* parent, static void attachRetranslator( QObject* parent, std::function< void( void ) > retranslateFunc );
std::function< void( void ) > retranslateFunc );
void addRetranslateFunc( std::function< void( void ) > retranslateFunc ); void addRetranslateFunc( std::function< void( void ) > retranslateFunc );
@ -63,10 +60,9 @@ private:
}; };
} // namespace } // namespace CalamaresUtils
#define CALAMARES_RETRANSLATE(body) \ #define CALAMARES_RETRANSLATE( body ) CalamaresUtils::Retranslator::attachRetranslator( this, [=] { body } );
CalamaresUtils::Retranslator::attachRetranslator( this, [=] { body } );
#define CALAMARES_RETRANSLATE_WIDGET( widget, body ) \ #define CALAMARES_RETRANSLATE_WIDGET( widget, body ) \
CalamaresUtils::Retranslator::attachRetranslator( widget, [=] { body } ); CalamaresUtils::Retranslator::attachRetranslator( widget, [=] { body } );

View File

@ -31,6 +31,11 @@ namespace CalamaresUtils
QString QString
removeDiacritics( const QString& string ) removeDiacritics( const QString& string )
{ {
// *INDENT-OFF*
// clang-format off
// Map these extended-Latin characters to ASCII; keep the
// layout so that one line in *diacriticLetters* corresponds
// to one line of replacements in *noDiacriticLetters*.
static const QString diacriticLetters = QString::fromUtf8( static const QString diacriticLetters = QString::fromUtf8(
"ŠŒŽšœžŸ¥µÀ" "ŠŒŽšœžŸ¥µÀ"
"ÁÂÃÄÅÆÇÈÉÊ" "ÁÂÃÄÅÆÇÈÉÊ"
@ -65,6 +70,8 @@ removeDiacritics( const QString& string )
"r", "A", "a", "E", "e", "L", "l", "N", "n", "S", "r", "A", "a", "E", "e", "L", "l", "N", "n", "S",
"s", "Z", "z", "Z", "z" "s", "Z", "z", "Z", "z"
}; };
// clang-format on
// *INDENT-ON*
QString output; QString output;
for ( const QChar& c : string ) for ( const QChar& c : string )
@ -116,10 +123,10 @@ obscure( const QString& string )
for ( int i = 0; i < string.length(); ++i ) for ( int i = 0; i < string.length(); ++i )
// yes, no typo. can't encode ' ' or '!' because // yes, no typo. can't encode ' ' or '!' because
// they're the unicode BOM. stupid scrambling. stupid. // they're the unicode BOM. stupid scrambling. stupid.
result += ( unicode[ i ].unicode() <= 0x21 ) ? {
unicode[ i ] : result += ( unicode[ i ].unicode() <= 0x21 ) ? unicode[ i ] : QChar( 0x1001F - unicode[ i ].unicode() );
QChar( 0x1001F - unicode[ i ].unicode() ); }
return result; return result;
} }
} } // namespace CalamaresUtils

View File

@ -48,6 +48,6 @@ namespace CalamaresUtils
* @return the obfuscated string. * @return the obfuscated string.
*/ */
DLLEXPORT QString obscure( const QString& string ); DLLEXPORT QString obscure( const QString& string );
} // namespace } // namespace CalamaresUtils
#endif #endif

View File

@ -43,59 +43,71 @@ constexpr qint64 operator ""_GiB( unsigned long long m )
return operator""_MiB(m)*1024; return operator""_MiB(m)*1024;
} }
constexpr qint64 KiBtoBytes( unsigned long long m ) constexpr qint64
KiBtoBytes( unsigned long long m )
{ {
return operator""_KiB( m ); return operator""_KiB( m );
} }
constexpr qint64 MiBtoBytes( unsigned long long m ) constexpr qint64
MiBtoBytes( unsigned long long m )
{ {
return operator""_MiB( m ); return operator""_MiB( m );
} }
constexpr qint64 GiBtoBytes( unsigned long long m ) constexpr qint64
GiBtoBytes( unsigned long long m )
{ {
return operator""_GiB( m ); return operator""_GiB( m );
} }
constexpr qint64 KiBtoBytes( double m ) constexpr qint64
KiBtoBytes( double m )
{ {
return qint64( m * 1024 ); return qint64( m * 1024 );
} }
constexpr qint64 MiBtoBytes( double m ) constexpr qint64
MiBtoBytes( double m )
{ {
return qint64( m * 1024 * 1024 ); return qint64( m * 1024 * 1024 );
} }
constexpr qint64 GiBtoBytes( double m ) constexpr qint64
GiBtoBytes( double m )
{ {
return qint64( m * 1024 * 1024 * 1024 ); return qint64( m * 1024 * 1024 * 1024 );
} }
constexpr int BytesToMiB( qint64 b ) constexpr int
BytesToMiB( qint64 b )
{ {
return int( b / 1024 / 1024 ); return int( b / 1024 / 1024 );
} }
constexpr int BytesToGiB( qint64 b ) constexpr int
BytesToGiB( qint64 b )
{ {
return int( b / 1024 / 1024 / 1024 ); return int( b / 1024 / 1024 / 1024 );
} }
constexpr qint64 alignBytesToBlockSize( qint64 bytes, qint64 blocksize ) constexpr qint64
alignBytesToBlockSize( qint64 bytes, qint64 blocksize )
{ {
qint64 blocks = bytes / blocksize; qint64 blocks = bytes / blocksize;
if ( blocks * blocksize != bytes ) if ( blocks * blocksize != bytes )
{
++blocks; ++blocks;
}
return blocks * blocksize; return blocks * blocksize;
} }
constexpr qint64 bytesToSectors( qint64 bytes, qint64 blocksize ) constexpr qint64
bytesToSectors( qint64 bytes, qint64 blocksize )
{ {
return alignBytesToBlockSize( alignBytesToBlockSize( bytes, blocksize ), MiBtoBytes( 1ULL ) ) / blocksize; return alignBytesToBlockSize( alignBytesToBlockSize( bytes, blocksize ), MiBtoBytes( 1ULL ) ) / blocksize;
} }
} // namespace } // namespace CalamaresUtils
#endif #endif

View File

@ -39,8 +39,10 @@ getBool( const QVariantMap& map, const QString& key, bool d )
{ {
auto v = map.value( key ); auto v = map.value( key );
if ( v.type() == QVariant::Bool ) if ( v.type() == QVariant::Bool )
{
result = v.toBool(); result = v.toBool();
} }
}
return result; return result;
} }
@ -52,8 +54,10 @@ getString(const QVariantMap& map, const QString& key)
{ {
auto v = map.value( key ); auto v = map.value( key );
if ( v.type() == QVariant::String ) if ( v.type() == QVariant::String )
{
return v.toString(); return v.toString();
} }
}
return QString(); return QString();
} }
@ -65,8 +69,10 @@ getInteger( const QVariantMap& map, const QString& key, int d )
{ {
auto v = map.value( key ); auto v = map.value( key );
if ( v.type() == QVariant::Int ) if ( v.type() == QVariant::Int )
{
result = v.toInt(); result = v.toInt();
} }
}
return result; return result;
} }
@ -79,10 +85,14 @@ getDouble( const QVariantMap& map, const QString& key, double d )
{ {
auto v = map.value( key ); auto v = map.value( key );
if ( v.type() == QVariant::Int ) if ( v.type() == QVariant::Int )
{
result = v.toInt(); result = v.toInt();
}
else if ( v.type() == QVariant::Double ) else if ( v.type() == QVariant::Double )
{
result = v.toDouble(); result = v.toDouble();
} }
}
return result; return result;
} }
@ -104,4 +114,4 @@ getSubMap( const QVariantMap& map, const QString& key, bool& success )
return QVariantMap(); return QVariantMap();
} }
} } // namespace CalamaresUtils

View File

@ -57,6 +57,6 @@ namespace CalamaresUtils
* (e.g. if @p success is false). * (e.g. if @p success is false).
*/ */
DLLEXPORT QVariantMap getSubMap( const QVariantMap& map, const QString& key, bool& success ); DLLEXPORT QVariantMap getSubMap( const QVariantMap& map, const QString& key, bool& success );
} // namespace } // namespace CalamaresUtils
#endif #endif

View File

@ -70,13 +70,21 @@ yamlScalarToVariant( const YAML::Node& scalarNode )
std::string stdScalar = scalarNode.as< std::string >(); std::string stdScalar = scalarNode.as< std::string >();
QString scalarString = QString::fromStdString( stdScalar ); QString scalarString = QString::fromStdString( stdScalar );
if ( _yamlScalarTrueValues.exactMatch( scalarString ) ) if ( _yamlScalarTrueValues.exactMatch( scalarString ) )
{
return QVariant( true ); return QVariant( true );
}
if ( _yamlScalarFalseValues.exactMatch( scalarString ) ) if ( _yamlScalarFalseValues.exactMatch( scalarString ) )
{
return QVariant( false ); return QVariant( false );
}
if ( QRegExp( "[-+]?\\d+" ).exactMatch( scalarString ) ) if ( QRegExp( "[-+]?\\d+" ).exactMatch( scalarString ) )
{
return QVariant( scalarString.toInt() ); return QVariant( scalarString.toInt() );
}
if ( QRegExp( "[-+]?\\d*\\.?\\d+" ).exactMatch( scalarString ) ) if ( QRegExp( "[-+]?\\d*\\.?\\d+" ).exactMatch( scalarString ) )
{
return QVariant( scalarString.toDouble() ); return QVariant( scalarString.toDouble() );
}
return QVariant( scalarString ); return QVariant( scalarString );
} }
@ -85,8 +93,7 @@ QVariant
yamlSequenceToVariant( const YAML::Node& sequenceNode ) yamlSequenceToVariant( const YAML::Node& sequenceNode )
{ {
QVariantList vl; QVariantList vl;
for ( YAML::const_iterator it = sequenceNode.begin(); for ( YAML::const_iterator it = sequenceNode.begin(); it != sequenceNode.end(); ++it )
it != sequenceNode.end(); ++it )
{ {
vl << yamlToVariant( *it ); vl << yamlToVariant( *it );
} }
@ -98,11 +105,9 @@ QVariant
yamlMapToVariant( const YAML::Node& mapNode ) yamlMapToVariant( const YAML::Node& mapNode )
{ {
QVariantMap vm; QVariantMap vm;
for ( YAML::const_iterator it = mapNode.begin(); for ( YAML::const_iterator it = mapNode.begin(); it != mapNode.end(); ++it )
it != mapNode.end(); ++it )
{ {
vm.insert( QString::fromStdString( it->first.as< std::string >() ), vm.insert( QString::fromStdString( it->first.as< std::string >() ), yamlToVariant( it->second ) );
yamlToVariant( it->second ) );
} }
return vm; return vm;
} }
@ -142,7 +147,9 @@ explainYamlException( const YAML::Exception& e, const QByteArray& yamlData )
linestart = yamlData.indexOf( '\n', linestart ); linestart = yamlData.indexOf( '\n', linestart );
// No more \ns found, weird // No more \ns found, weird
if ( linestart < 0 ) if ( linestart < 0 )
{
break; break;
}
linestart += 1; // Skip that \n linestart += 1; // Skip that \n
} }
int lineend = linestart; int lineend = linestart;
@ -150,20 +157,27 @@ explainYamlException( const YAML::Exception& e, const QByteArray& yamlData )
{ {
lineend = yamlData.indexOf( '\n', linestart ); lineend = yamlData.indexOf( '\n', linestart );
if ( lineend < 0 ) if ( lineend < 0 )
{
lineend = yamlData.length(); lineend = yamlData.length();
} }
}
int rangestart = linestart; int rangestart = linestart;
int rangeend = lineend; int rangeend = lineend;
// Adjust range (linestart..lineend) so it's not too long // Adjust range (linestart..lineend) so it's not too long
if ( ( linestart >= 0 ) && ( e.mark.column > 30 ) ) if ( ( linestart >= 0 ) && ( e.mark.column > 30 ) )
{
rangestart += ( e.mark.column - 30 ); rangestart += ( e.mark.column - 30 );
}
if ( ( linestart >= 0 ) && ( rangeend - rangestart > 40 ) ) if ( ( linestart >= 0 ) && ( rangeend - rangestart > 40 ) )
{
rangeend = rangestart + 40; rangeend = rangestart + 40;
}
if ( linestart >= 0 ) if ( linestart >= 0 )
{
cWarning() << "offending YAML data:" << yamlData.mid( rangestart, rangeend - rangestart ).constData(); cWarning() << "offending YAML data:" << yamlData.mid( rangestart, rangeend - rangestart ).constData();
}
} }
} }
@ -177,7 +191,9 @@ QVariantMap
loadYaml( const QString& filename, bool* ok ) loadYaml( const QString& filename, bool* ok )
{ {
if ( ok ) if ( ok )
{
*ok = false; *ok = false;
}
QFile yamlFile( filename ); QFile yamlFile( filename );
QVariant yamlContents; QVariant yamlContents;
@ -197,12 +213,12 @@ loadYaml(const QString& filename, bool* ok)
} }
if ( yamlContents.isValid() && if ( yamlContents.isValid() && !yamlContents.isNull() && yamlContents.type() == QVariant::Map )
!yamlContents.isNull() &&
yamlContents.type() == QVariant::Map )
{ {
if ( ok ) if ( ok )
{
*ok = true; *ok = true;
}
return yamlContents.toMap(); return yamlContents.toMap();
} }
@ -214,8 +230,10 @@ static void
writeIndent( QFile& f, int indent ) writeIndent( QFile& f, int indent )
{ {
while ( indent-- > 0 ) while ( indent-- > 0 )
{
f.write( " " ); f.write( " " );
} }
}
// forward declaration // forward declaration
static bool dumpYaml( QFile& f, const QVariantMap& map, int indent ); static bool dumpYaml( QFile& f, const QVariantMap& map, int indent );
@ -229,7 +247,9 @@ static void
dumpYamlElement( QFile& f, const QVariant& value, int indent ) dumpYamlElement( QFile& f, const QVariant& value, int indent )
{ {
if ( value.type() == QVariant::Type::Bool ) if ( value.type() == QVariant::Type::Bool )
{
f.write( value.toBool() ? "true" : "false" ); f.write( value.toBool() ? "true" : "false" );
}
else if ( value.type() == QVariant::Type::String ) else if ( value.type() == QVariant::Type::String )
{ {
f.write( quote ); f.write( quote );
@ -256,8 +276,10 @@ dumpYamlElement( QFile& f, const QVariant& value, int indent )
dumpYamlElement( f, it, indent + 1 ); dumpYamlElement( f, it, indent + 1 );
} }
if ( !c ) // i.e. list was empty if ( !c ) // i.e. list was empty
{
f.write( "[]" ); f.write( "[]" );
} }
}
else if ( value.type() == QVariant::Type::Map ) else if ( value.type() == QVariant::Type::Map )
{ {
f.write( newline ); f.write( newline );
@ -293,12 +315,13 @@ saveYaml( const QString& filename, const QVariantMap& map )
{ {
QFile f( filename ); QFile f( filename );
if ( !f.open( QFile::WriteOnly ) ) if ( !f.open( QFile::WriteOnly ) )
{
return false; return false;
}
f.write( "# YAML dump\n---\n" ); f.write( "# YAML dump\n---\n" );
return dumpYaml( f, map, 0 ); return dumpYaml( f, map, 0 );
} }
} // namespace CalamaresUtils
} // namespace

View File

@ -77,6 +77,6 @@ void explainYamlException( const YAML::Exception& e, const QByteArray& data, con
void explainYamlException( const YAML::Exception& e, const QByteArray& data, const QString& label ); void explainYamlException( const YAML::Exception& e, const QByteArray& data, const QString& label );
void explainYamlException( const YAML::Exception& e, const QByteArray& data ); void explainYamlException( const YAML::Exception& e, const QByteArray& data );
} // namespace } // namespace CalamaresUtils
#endif #endif

View File

@ -57,7 +57,7 @@ Utils::target_env_call( const QString& command,
int timeout ) const int timeout ) const
{ {
return CalamaresUtils::System::instance()-> return CalamaresUtils::System::instance()->
targetEnvCall( command, QString(), stdin, timeout ); targetEnvCall( command, QString(), stdin, std::chrono::seconds( timeout > 0 ? timeout : 0 ) );
} }
@ -67,7 +67,7 @@ Utils::target_env_call( const QStringList& args,
int timeout ) const int timeout ) const
{ {
return CalamaresUtils::System::instance()-> return CalamaresUtils::System::instance()->
targetEnvCall( args, QString(), stdin, timeout ); targetEnvCall( args, QString(), stdin, std::chrono::seconds( timeout > 0 ? timeout : 0 ) );
} }
@ -102,7 +102,7 @@ Utils::check_target_env_output( const QString& command,
output, output,
QString(), QString(),
stdin, stdin,
timeout ); std::chrono::seconds( timeout > 0 ? timeout : 0 ) );
_handle_check_target_env_call_error( ec, command ); _handle_check_target_env_call_error( ec, command );
return output; return output;
} }
@ -119,7 +119,7 @@ Utils::check_target_env_output( const QStringList& args,
output, output,
QString(), QString(),
stdin, stdin,
timeout ); std::chrono::seconds( timeout > 0 ? timeout : 0 ) );
_handle_check_target_env_call_error( ec, args.join( ' ' ) ); _handle_check_target_env_call_error( ec, args.join( ' ' ) );
return output; return output;
} }