2020-08-25 16:05:56 +02:00
|
|
|
/* === This file is part of Calamares - <https://calamares.io> ===
|
|
|
|
*
|
2020-05-30 16:15:03 +02:00
|
|
|
* SPDX-FileCopyrightText: 2014-2016 Teo Mrnjavac <teo@kde.org>
|
|
|
|
* SPDX-FileCopyrightText: 2017-2020 Adriaan de Groot <groot@kde.org>
|
|
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
2020-08-25 16:05:56 +02:00
|
|
|
*
|
|
|
|
* Calamares is Free Software: see the License-Identifier above.
|
2020-05-30 16:15:03 +02:00
|
|
|
*
|
2014-07-17 17:52:02 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "PythonJobApi.h"
|
|
|
|
|
2020-02-12 11:02:38 +01:00
|
|
|
#include "GlobalStorage.h"
|
|
|
|
#include "JobQueue.h"
|
2014-07-18 14:27:59 +02:00
|
|
|
#include "PythonHelper.h"
|
2022-06-18 00:40:26 +02:00
|
|
|
#include "locale/Global.h"
|
2019-06-20 11:35:46 +02:00
|
|
|
#include "partition/Mount.h"
|
2019-08-04 22:24:55 +02:00
|
|
|
#include "utils/Logger.h"
|
2021-09-22 11:03:56 +02:00
|
|
|
#include "utils/RAII.h"
|
2021-11-03 12:23:39 +01:00
|
|
|
#include "utils/Runner.h"
|
2019-04-29 12:48:01 +02:00
|
|
|
#include "utils/String.h"
|
2023-10-17 22:24:46 +02:00
|
|
|
#include "utils/System.h"
|
2021-11-29 12:46:12 +01:00
|
|
|
#include "utils/Yaml.h"
|
2014-07-17 17:52:02 +02:00
|
|
|
|
2017-08-18 18:56:34 +02:00
|
|
|
#include <QCoreApplication>
|
2014-07-29 13:16:46 +02:00
|
|
|
#include <QDir>
|
2017-08-18 18:56:34 +02:00
|
|
|
#include <QStandardPaths>
|
2014-07-29 13:16:46 +02:00
|
|
|
|
2014-08-04 16:03:33 +02:00
|
|
|
namespace bp = boost::python;
|
2014-07-29 20:18:02 +02:00
|
|
|
|
2017-11-28 14:53:40 +01:00
|
|
|
static int
|
2023-09-11 20:13:15 +02:00
|
|
|
handle_check_target_env_call_error( const Calamares::ProcessResult& ec, const QString& cmd )
|
2017-11-28 14:53:40 +01:00
|
|
|
{
|
2017-11-28 16:55:53 +01:00
|
|
|
if ( !ec.first )
|
2019-08-04 22:24:55 +02:00
|
|
|
{
|
2017-11-28 16:55:53 +01:00
|
|
|
return ec.first;
|
2019-08-04 22:24:55 +02:00
|
|
|
}
|
2017-11-28 14:53:40 +01:00
|
|
|
|
|
|
|
QString raise = QString( "import subprocess\n"
|
|
|
|
"e = subprocess.CalledProcessError(%1,\"%2\")\n" )
|
2019-08-04 22:24:55 +02:00
|
|
|
.arg( ec.first )
|
|
|
|
.arg( cmd );
|
2017-11-28 16:55:53 +01:00
|
|
|
if ( !ec.second.isEmpty() )
|
2019-08-04 22:24:55 +02:00
|
|
|
{
|
|
|
|
raise.append( QStringLiteral( "e.output = \"\"\"%1\"\"\"\n" ).arg( ec.second ) );
|
|
|
|
}
|
|
|
|
raise.append( "raise e" );
|
2017-11-28 14:53:40 +01:00
|
|
|
bp::exec( raise.toStdString().c_str() );
|
|
|
|
bp::throw_error_already_set();
|
2017-11-28 16:55:53 +01:00
|
|
|
return ec.first;
|
2017-11-28 14:53:40 +01:00
|
|
|
}
|
|
|
|
|
2017-11-28 16:42:00 +01:00
|
|
|
static inline QStringList
|
2022-02-07 12:51:22 +01:00
|
|
|
bp_list_to_qstringlist( const bp::list& args )
|
2017-11-28 16:42:00 +01:00
|
|
|
{
|
|
|
|
QStringList list;
|
|
|
|
for ( int i = 0; i < bp::len( args ); ++i )
|
|
|
|
{
|
2019-08-04 22:24:55 +02:00
|
|
|
list.append( QString::fromStdString( bp::extract< std::string >( args[ i ] ) ) );
|
2017-11-28 16:42:00 +01:00
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2023-09-11 20:13:15 +02:00
|
|
|
static inline Calamares::ProcessResult
|
2022-02-07 12:54:16 +01:00
|
|
|
target_env_command( const QStringList& args, const std::string& input, int timeout )
|
2014-07-29 20:18:02 +02:00
|
|
|
{
|
2019-08-01 22:47:42 +02:00
|
|
|
// Since Python doesn't give us the type system for distinguishing
|
|
|
|
// seconds from other integral types, massage to seconds here.
|
2023-09-11 20:13:15 +02:00
|
|
|
return Calamares::System::instance()->targetEnvCommand(
|
2022-02-07 12:54:16 +01:00
|
|
|
args, QString(), QString::fromStdString( input ), std::chrono::seconds( timeout ) );
|
2014-07-29 20:18:02 +02:00
|
|
|
}
|
|
|
|
|
2022-02-07 12:51:22 +01:00
|
|
|
namespace CalamaresPython
|
|
|
|
{
|
|
|
|
|
|
|
|
int
|
|
|
|
mount( const std::string& device_path,
|
|
|
|
const std::string& mount_point,
|
|
|
|
const std::string& filesystem_name,
|
|
|
|
const std::string& options )
|
|
|
|
{
|
2023-09-11 00:09:31 +02:00
|
|
|
return Calamares::Partition::mount( QString::fromStdString( device_path ),
|
2023-09-11 20:13:15 +02:00
|
|
|
QString::fromStdString( mount_point ),
|
|
|
|
QString::fromStdString( filesystem_name ),
|
|
|
|
QString::fromStdString( options ) );
|
2022-02-07 12:51:22 +01:00
|
|
|
}
|
|
|
|
|
2017-11-28 16:55:53 +01:00
|
|
|
int
|
2022-02-07 12:54:16 +01:00
|
|
|
target_env_call( const std::string& command, const std::string& input, int timeout )
|
2017-11-28 16:55:53 +01:00
|
|
|
{
|
2022-02-07 12:54:16 +01:00
|
|
|
return target_env_command( QStringList { QString::fromStdString( command ) }, input, timeout ).first;
|
2017-11-28 16:55:53 +01:00
|
|
|
}
|
|
|
|
|
2014-07-29 20:18:02 +02:00
|
|
|
int
|
2022-02-07 12:54:16 +01:00
|
|
|
target_env_call( const bp::list& args, const std::string& input, int timeout )
|
2014-07-29 20:18:02 +02:00
|
|
|
{
|
2022-02-07 12:54:16 +01:00
|
|
|
return target_env_command( bp_list_to_qstringlist( args ), input, timeout ).first;
|
2014-07-29 20:18:02 +02:00
|
|
|
}
|
|
|
|
|
2014-08-04 16:03:33 +02:00
|
|
|
int
|
2022-02-07 12:54:16 +01:00
|
|
|
check_target_env_call( const std::string& command, const std::string& input, int timeout )
|
2014-08-04 16:03:33 +02:00
|
|
|
{
|
2022-02-07 12:54:16 +01:00
|
|
|
auto ec = target_env_command( QStringList { QString::fromStdString( command ) }, input, timeout );
|
2022-02-07 12:51:22 +01:00
|
|
|
return handle_check_target_env_call_error( ec, QString::fromStdString( command ) );
|
2014-08-04 16:03:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2022-02-07 12:54:16 +01:00
|
|
|
check_target_env_call( const bp::list& args, const std::string& input, int timeout )
|
2014-08-04 16:03:33 +02:00
|
|
|
{
|
2022-02-07 12:54:16 +01:00
|
|
|
auto ec = target_env_command( bp_list_to_qstringlist( args ), input, timeout );
|
2017-11-28 16:55:53 +01:00
|
|
|
if ( !ec.first )
|
2019-08-04 22:24:55 +02:00
|
|
|
{
|
2017-11-28 16:55:53 +01:00
|
|
|
return ec.first;
|
2019-08-04 22:24:55 +02:00
|
|
|
}
|
2014-08-04 16:03:33 +02:00
|
|
|
|
2022-02-07 12:51:22 +01:00
|
|
|
QStringList failedCmdList = bp_list_to_qstringlist( args );
|
|
|
|
return handle_check_target_env_call_error( ec, failedCmdList.join( ' ' ) );
|
2014-08-04 16:03:33 +02:00
|
|
|
}
|
|
|
|
|
2014-08-08 14:12:53 +02:00
|
|
|
std::string
|
2022-02-07 12:54:16 +01:00
|
|
|
check_target_env_output( const std::string& command, const std::string& input, int timeout )
|
2014-08-08 14:12:53 +02:00
|
|
|
{
|
2022-02-07 12:54:16 +01:00
|
|
|
auto ec = target_env_command( QStringList { QString::fromStdString( command ) }, input, timeout );
|
2022-02-07 12:51:22 +01:00
|
|
|
handle_check_target_env_call_error( ec, QString::fromStdString( command ) );
|
2017-11-28 16:55:53 +01:00
|
|
|
return ec.second.toStdString();
|
2014-08-08 14:12:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string
|
2022-02-07 12:54:16 +01:00
|
|
|
check_target_env_output( const bp::list& args, const std::string& input, int timeout )
|
2014-08-08 14:12:53 +02:00
|
|
|
{
|
2022-02-07 12:51:22 +01:00
|
|
|
QStringList list = bp_list_to_qstringlist( args );
|
2022-02-07 12:54:16 +01:00
|
|
|
auto ec = target_env_command( list, input, timeout );
|
2022-02-07 12:51:22 +01:00
|
|
|
handle_check_target_env_call_error( ec, list.join( ' ' ) );
|
2017-11-28 16:55:53 +01:00
|
|
|
return ec.second.toStdString();
|
2014-08-08 14:12:53 +02:00
|
|
|
}
|
|
|
|
|
2021-07-27 16:01:32 +02:00
|
|
|
static const char output_prefix[] = "[PYTHON JOB]:";
|
2021-11-29 12:22:02 +01:00
|
|
|
static inline void
|
|
|
|
log_action( unsigned int level, const std::string& s )
|
|
|
|
{
|
|
|
|
Logger::CDebug( level ) << output_prefix << QString::fromStdString( s );
|
|
|
|
}
|
2021-07-27 16:01:32 +02:00
|
|
|
|
2014-07-28 18:55:01 +02:00
|
|
|
void
|
|
|
|
debug( const std::string& s )
|
|
|
|
{
|
2021-11-29 12:22:02 +01:00
|
|
|
log_action( Logger::LOGDEBUG, s );
|
2014-07-28 18:55:01 +02:00
|
|
|
}
|
|
|
|
|
2018-02-20 10:26:59 +01:00
|
|
|
void
|
|
|
|
warning( const std::string& s )
|
|
|
|
{
|
2021-11-29 12:22:02 +01:00
|
|
|
log_action( Logger::LOGWARNING, s );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
error( const std::string& s )
|
|
|
|
{
|
|
|
|
log_action( Logger::LOGERROR, s );
|
2018-02-20 10:26:59 +01:00
|
|
|
}
|
2014-07-28 18:55:01 +02:00
|
|
|
|
2021-11-29 12:46:12 +01:00
|
|
|
boost::python::dict
|
|
|
|
load_yaml( const std::string& path )
|
|
|
|
{
|
2021-11-29 14:19:06 +01:00
|
|
|
const QString filePath = QString::fromStdString( path );
|
|
|
|
bool ok = false;
|
2023-09-11 20:13:15 +02:00
|
|
|
auto map = Calamares::YAML::load( filePath, &ok );
|
2021-11-29 14:19:06 +01:00
|
|
|
if ( !ok )
|
|
|
|
{
|
|
|
|
cWarning() << "Loading YAML from" << filePath << "failed.";
|
|
|
|
}
|
|
|
|
return variantMapToPyDict( map );
|
2021-11-29 12:46:12 +01:00
|
|
|
}
|
|
|
|
|
2014-07-23 12:54:53 +02:00
|
|
|
PythonJobInterface::PythonJobInterface( Calamares::PythonJob* parent )
|
2014-07-17 17:52:02 +02:00
|
|
|
: m_parent( parent )
|
|
|
|
{
|
2017-08-10 16:43:49 +02:00
|
|
|
auto moduleDir = QDir( m_parent->m_workingPath );
|
|
|
|
moduleName = moduleDir.dirName().toStdString();
|
2014-07-18 14:27:59 +02:00
|
|
|
prettyName = m_parent->prettyName().toStdString();
|
|
|
|
workingPath = m_parent->m_workingPath.toStdString();
|
|
|
|
configuration = CalamaresPython::variantMapToPyDict( m_parent->m_configurationMap );
|
2014-07-17 17:52:02 +02:00
|
|
|
}
|
|
|
|
|
2014-07-22 18:05:58 +02:00
|
|
|
void
|
2014-07-23 12:54:53 +02:00
|
|
|
PythonJobInterface::setprogress( qreal progress )
|
2014-07-22 18:05:58 +02:00
|
|
|
{
|
2020-03-05 03:40:40 +01:00
|
|
|
if ( progress >= 0.0 && progress <= 1.0 )
|
2019-08-04 22:24:55 +02:00
|
|
|
{
|
2014-07-22 18:05:58 +02:00
|
|
|
m_parent->emitProgress( progress );
|
2019-08-04 22:24:55 +02:00
|
|
|
}
|
2014-07-22 18:05:58 +02:00
|
|
|
}
|
|
|
|
|
2021-11-03 12:23:39 +01:00
|
|
|
static inline int
|
|
|
|
_process_output( Calamares::Utils::RunLocation location,
|
|
|
|
const boost::python::list& args,
|
2021-11-03 13:45:15 +01:00
|
|
|
const boost::python::object& callback,
|
2022-02-07 12:54:16 +01:00
|
|
|
const std::string& input,
|
2021-11-03 13:45:15 +01:00
|
|
|
int timeout )
|
2021-11-03 12:23:39 +01:00
|
|
|
{
|
2022-02-07 12:51:22 +01:00
|
|
|
Calamares::Utils::Runner r( bp_list_to_qstringlist( args ) );
|
2021-11-03 12:23:39 +01:00
|
|
|
r.setLocation( location );
|
|
|
|
if ( !callback.is_none() )
|
|
|
|
{
|
2021-11-03 13:45:15 +01:00
|
|
|
bp::extract< bp::list > x( callback );
|
|
|
|
if ( x.check() )
|
|
|
|
{
|
2022-04-12 14:15:52 +02:00
|
|
|
QObject::connect( &r,
|
|
|
|
&decltype( r )::output,
|
|
|
|
[ cb = callback.attr( "append" ) ]( const QString& s ) { cb( s.toStdString() ); } );
|
2021-11-03 13:45:15 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QObject::connect(
|
2022-04-12 14:15:52 +02:00
|
|
|
&r, &decltype( r )::output, [ &callback ]( const QString& s ) { callback( s.toStdString() ); } );
|
2021-11-03 13:45:15 +01:00
|
|
|
}
|
2021-11-03 12:23:39 +01:00
|
|
|
r.enableOutputProcessing();
|
|
|
|
}
|
2022-02-07 12:54:16 +01:00
|
|
|
if ( !input.empty() )
|
2021-11-03 13:45:15 +01:00
|
|
|
{
|
2022-02-07 12:54:16 +01:00
|
|
|
r.setInput( QString::fromStdString( input ) );
|
2021-11-03 13:45:15 +01:00
|
|
|
}
|
|
|
|
if ( timeout > 0 )
|
|
|
|
{
|
|
|
|
r.setTimeout( std::chrono::seconds( timeout ) );
|
|
|
|
}
|
|
|
|
|
2021-11-03 12:23:39 +01:00
|
|
|
auto result = r.run();
|
|
|
|
|
|
|
|
if ( result.getExitCode() )
|
|
|
|
{
|
2022-02-07 12:51:22 +01:00
|
|
|
return handle_check_target_env_call_error( result, r.executable() );
|
2021-11-03 12:23:39 +01:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-27 16:13:49 +02:00
|
|
|
int
|
2021-11-03 13:45:15 +01:00
|
|
|
target_env_process_output( const boost::python::list& args,
|
|
|
|
const boost::python::object& callback,
|
2022-02-07 12:54:16 +01:00
|
|
|
const std::string& input,
|
2021-11-03 13:45:15 +01:00
|
|
|
int timeout )
|
2021-07-27 16:13:49 +02:00
|
|
|
{
|
2022-02-07 12:54:16 +01:00
|
|
|
return _process_output( Calamares::Utils::RunLocation::RunInTarget, args, callback, input, timeout );
|
2021-11-03 12:23:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-11-03 13:45:15 +01:00
|
|
|
host_env_process_output( const boost::python::list& args,
|
|
|
|
const boost::python::object& callback,
|
2022-02-07 12:54:16 +01:00
|
|
|
const std::string& input,
|
2021-11-03 13:45:15 +01:00
|
|
|
int timeout )
|
2021-11-03 12:23:39 +01:00
|
|
|
{
|
2022-02-07 12:54:16 +01:00
|
|
|
return _process_output( Calamares::Utils::RunLocation::RunInHost, args, callback, input, timeout );
|
2021-07-27 16:13:49 +02:00
|
|
|
}
|
|
|
|
|
2016-08-19 12:47:45 +02:00
|
|
|
std::string
|
|
|
|
obscure( const std::string& string )
|
|
|
|
{
|
2022-04-12 14:15:52 +02:00
|
|
|
return Calamares::String::obscure( QString::fromStdString( string ) ).toStdString();
|
2016-08-19 12:47:45 +02:00
|
|
|
}
|
|
|
|
|
2017-08-18 18:56:34 +02:00
|
|
|
static QStringList
|
|
|
|
_gettext_languages()
|
2017-08-15 12:31:47 +02:00
|
|
|
{
|
2017-08-18 18:56:34 +02:00
|
|
|
QStringList languages;
|
2017-08-15 22:50:26 +02:00
|
|
|
|
|
|
|
// There are two ways that Python jobs can be initialised:
|
|
|
|
// - through JobQueue, in which case that has an instance which holds
|
|
|
|
// a GlobalStorage object, or
|
|
|
|
// - through the Python test-script, which initialises its
|
|
|
|
// own GlobalStoragePythonWrapper, which then holds a
|
|
|
|
// GlobalStorage object for all of Python.
|
|
|
|
Calamares::JobQueue* jq = Calamares::JobQueue::instance();
|
2019-08-04 22:24:55 +02:00
|
|
|
Calamares::GlobalStorage* gs
|
|
|
|
= jq ? jq->globalStorage() : CalamaresPython::GlobalStoragePythonWrapper::globalStorageInstance();
|
2017-08-15 22:50:26 +02:00
|
|
|
|
2023-09-10 21:58:26 +02:00
|
|
|
QString lang = Calamares::Locale::readGS( *gs, QStringLiteral( "LANG" ) );
|
2022-06-18 00:40:26 +02:00
|
|
|
if ( !lang.isEmpty() )
|
2017-08-15 12:31:47 +02:00
|
|
|
{
|
2022-06-18 00:40:26 +02:00
|
|
|
languages.append( lang );
|
|
|
|
if ( lang.indexOf( '.' ) > 0 )
|
2017-08-15 12:31:47 +02:00
|
|
|
{
|
2022-06-18 00:40:26 +02:00
|
|
|
lang.truncate( lang.indexOf( '.' ) );
|
|
|
|
languages.append( lang );
|
|
|
|
}
|
|
|
|
if ( lang.indexOf( '_' ) > 0 )
|
|
|
|
{
|
|
|
|
lang.truncate( lang.indexOf( '_' ) );
|
2017-08-21 18:36:04 +02:00
|
|
|
languages.append( lang );
|
2017-08-15 12:31:47 +02:00
|
|
|
}
|
|
|
|
}
|
2017-08-18 18:56:34 +02:00
|
|
|
return languages;
|
|
|
|
}
|
|
|
|
|
|
|
|
bp::list
|
|
|
|
gettext_languages()
|
|
|
|
{
|
|
|
|
bp::list pyList;
|
2017-08-21 18:36:04 +02:00
|
|
|
for ( auto lang : _gettext_languages() )
|
2019-08-04 22:24:55 +02:00
|
|
|
{
|
2017-08-18 18:56:34 +02:00
|
|
|
pyList.append( lang.toStdString() );
|
2019-08-04 22:24:55 +02:00
|
|
|
}
|
2017-08-15 12:31:47 +02:00
|
|
|
return pyList;
|
|
|
|
}
|
|
|
|
|
2017-08-18 18:56:34 +02:00
|
|
|
static void
|
2017-08-21 18:36:04 +02:00
|
|
|
_add_localedirs( QStringList& pathList, const QString& candidate )
|
2017-08-18 18:56:34 +02:00
|
|
|
{
|
2017-08-21 18:36:04 +02:00
|
|
|
if ( !candidate.isEmpty() && !pathList.contains( candidate ) )
|
2017-08-18 18:56:34 +02:00
|
|
|
{
|
2017-08-21 18:36:04 +02:00
|
|
|
pathList.prepend( candidate );
|
|
|
|
if ( QDir( candidate ).cd( "lang" ) )
|
2019-08-04 22:24:55 +02:00
|
|
|
{
|
2017-08-21 18:36:04 +02:00
|
|
|
pathList.prepend( candidate + "/lang" );
|
2019-08-04 22:24:55 +02:00
|
|
|
}
|
2017-08-18 18:56:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-16 16:45:34 +02:00
|
|
|
bp::object
|
2017-08-15 22:50:26 +02:00
|
|
|
gettext_path()
|
|
|
|
{
|
2021-09-22 11:03:56 +02:00
|
|
|
// Going to log informatively just once
|
|
|
|
static bool first_time = true;
|
2021-09-22 11:26:28 +02:00
|
|
|
cScopedAssignment( &first_time, false );
|
2021-09-22 11:03:56 +02:00
|
|
|
|
2017-08-15 22:50:26 +02:00
|
|
|
// TODO: distinguish between -d runs and normal runs
|
|
|
|
// TODO: can we detect DESTDIR-installs?
|
2019-08-04 22:24:55 +02:00
|
|
|
QStringList candidatePaths
|
|
|
|
= QStandardPaths::locateAll( QStandardPaths::GenericDataLocation, "locale", QStandardPaths::LocateDirectory );
|
2017-08-18 18:56:34 +02:00
|
|
|
QString extra = QCoreApplication::applicationDirPath();
|
2019-08-04 22:24:55 +02:00
|
|
|
_add_localedirs( candidatePaths, extra ); // Often /usr/local/bin
|
2017-08-21 18:34:38 +02:00
|
|
|
if ( !extra.isEmpty() )
|
|
|
|
{
|
2017-08-21 18:36:04 +02:00
|
|
|
QDir d( extra );
|
2019-08-04 22:24:55 +02:00
|
|
|
if ( d.cd( "../share/locale" ) ) // Often /usr/local/bin/../share/locale -> /usr/local/share/locale
|
|
|
|
{
|
2017-08-21 18:36:04 +02:00
|
|
|
_add_localedirs( candidatePaths, d.canonicalPath() );
|
2019-08-04 22:24:55 +02:00
|
|
|
}
|
2017-08-21 18:34:38 +02:00
|
|
|
}
|
2019-08-04 22:24:55 +02:00
|
|
|
_add_localedirs( candidatePaths, QDir().canonicalPath() ); // .
|
2017-08-18 18:56:34 +02:00
|
|
|
|
2021-09-22 11:03:56 +02:00
|
|
|
if ( first_time )
|
|
|
|
{
|
|
|
|
cDebug() << "Determining gettext path from" << candidatePaths;
|
|
|
|
}
|
2017-08-18 18:56:34 +02:00
|
|
|
|
2019-01-08 10:51:53 +01:00
|
|
|
QStringList candidateLanguages = _gettext_languages();
|
|
|
|
for ( const auto& lang : candidateLanguages )
|
2021-09-22 11:03:56 +02:00
|
|
|
{
|
2017-08-21 18:36:04 +02:00
|
|
|
for ( auto localedir : candidatePaths )
|
2017-08-18 18:56:34 +02:00
|
|
|
{
|
2017-08-21 18:36:04 +02:00
|
|
|
QDir ldir( localedir );
|
|
|
|
if ( ldir.cd( lang ) )
|
2019-01-08 10:51:53 +01:00
|
|
|
{
|
2021-09-22 11:03:56 +02:00
|
|
|
Logger::CDebug( Logger::LOGDEBUG )
|
|
|
|
<< output_prefix << "Found gettext" << lang << "in" << ldir.canonicalPath();
|
2017-08-18 18:56:34 +02:00
|
|
|
return bp::object( localedir.toStdString() );
|
2019-01-08 10:51:53 +01:00
|
|
|
}
|
2017-08-18 18:56:34 +02:00
|
|
|
}
|
2021-09-22 11:03:56 +02:00
|
|
|
}
|
|
|
|
cWarning() << "No translation found for languages" << candidateLanguages;
|
2017-08-16 16:45:34 +02:00
|
|
|
return bp::object(); // None
|
2017-08-15 22:50:26 +02:00
|
|
|
}
|
|
|
|
|
2019-08-04 22:24:55 +02:00
|
|
|
} // namespace CalamaresPython
|