calamares/src/libcalamares/PythonJobApi.cpp
Adriaan de Groot dd8e53dc22 Copyright: update copyright lines on files touched in 2018
Contributions from:
  Adriaan de Groot <groot@kde.org>
  Gabriel Craciunescu <crazy@frugalware.org>
  AlmAck <gluca86@gmail.com>
  Andrius Štikonas <andrius@stikonas.eu>
  Caio Carvalho <caiojcarvalho@gmail.com>
  Raul Rodrigo Segura <raurodse@gmail.com>
2018-06-15 05:59:11 -04:00

293 lines
8.6 KiB
C++

/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2014-2016, Teo Mrnjavac <teo@kde.org>
* Copyright 2017-2018, Adriaan de Groot <groot@kde.org>
*
* Calamares is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Calamares is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PythonJobApi.h"
#include "PythonHelper.h"
#include "utils/Logger.h"
#include "utils/CalamaresUtilsSystem.h"
#include "utils/CalamaresUtils.h"
#include "GlobalStorage.h"
#include "JobQueue.h"
#include <QCoreApplication>
#include <QDir>
#include <QStandardPaths>
#undef slots
#include <boost/python.hpp>
namespace bp = boost::python;
static int
_handle_check_target_env_call_error( const CalamaresUtils::ProcessResult& ec, const QString& cmd )
{
if ( !ec.first )
return ec.first;
QString raise = QString( "import subprocess\n"
"e = subprocess.CalledProcessError(%1,\"%2\")\n" )
.arg( ec.first )
.arg( cmd );
if ( !ec.second.isEmpty() )
raise.append( QStringLiteral("e.output = \"\"\"%1\"\"\"\n").arg( ec.second ) );
raise.append("raise e");
bp::exec( raise.toStdString().c_str() );
bp::throw_error_already_set();
return ec.first;
}
namespace CalamaresPython
{
int
mount( const std::string& device_path,
const std::string& mount_point,
const std::string& filesystem_name,
const std::string& options )
{
return CalamaresUtils::System::instance()->
mount( QString::fromStdString( device_path ),
QString::fromStdString( mount_point ),
QString::fromStdString( filesystem_name ),
QString::fromStdString( options ) );
}
static inline QStringList
_bp_list_to_qstringlist( const bp::list& args )
{
QStringList list;
for ( int i = 0; i < bp::len( args ); ++i )
{
list.append( QString::fromStdString(
bp::extract< std::string >( args[ i ] ) ) );
}
return list;
}
static inline CalamaresUtils::ProcessResult
_target_env_command(
const QStringList& args,
const std::string& stdin,
int timeout )
{
return CalamaresUtils::System::instance()->
targetEnvCommand( args,
QString(),
QString::fromStdString( stdin ),
timeout );
}
int
target_env_call( const std::string& command,
const std::string& stdin,
int timeout )
{
return _target_env_command(
QStringList{ QString::fromStdString( command ) }, stdin, timeout ).first;
}
int
target_env_call( const bp::list& args,
const std::string& stdin,
int timeout )
{
return _target_env_command(
_bp_list_to_qstringlist( args ), stdin, timeout ).first;
}
int
check_target_env_call( const std::string& command,
const std::string& stdin,
int timeout )
{
auto ec = _target_env_command(
QStringList{ QString::fromStdString( command ) }, stdin, timeout );
return _handle_check_target_env_call_error( ec, QString::fromStdString( command ) );
}
int
check_target_env_call( const bp::list& args,
const std::string& stdin,
int timeout )
{
auto ec = _target_env_command( _bp_list_to_qstringlist( args ), stdin, timeout );
if ( !ec.first )
return ec.first;
QStringList failedCmdList = _bp_list_to_qstringlist( args );
return _handle_check_target_env_call_error( ec, failedCmdList.join( ' ' ) );
}
std::string
check_target_env_output( const std::string& command,
const std::string& stdin,
int timeout )
{
auto ec = _target_env_command(
QStringList{ QString::fromStdString( command ) }, stdin, timeout );
_handle_check_target_env_call_error( ec, QString::fromStdString( command ) );
return ec.second.toStdString();
}
std::string
check_target_env_output( const bp::list& args,
const std::string& stdin,
int timeout )
{
QStringList list = _bp_list_to_qstringlist( args );
auto ec = _target_env_command(
list, stdin, timeout );
_handle_check_target_env_call_error( ec, list.join( ' ' ) );
return ec.second.toStdString();
}
void
debug( const std::string& s )
{
cDebug() << "[PYTHON JOB]: " << QString::fromStdString( s );
}
void
warning( const std::string& s )
{
cWarning() << "[PYTHON JOB]: " << QString::fromStdString( s );
}
PythonJobInterface::PythonJobInterface( Calamares::PythonJob* parent )
: m_parent( parent )
{
auto moduleDir = QDir( m_parent->m_workingPath );
moduleName = moduleDir.dirName().toStdString();
prettyName = m_parent->prettyName().toStdString();
workingPath = m_parent->m_workingPath.toStdString();
configuration = CalamaresPython::variantMapToPyDict( m_parent->m_configurationMap );
}
void
PythonJobInterface::setprogress( qreal progress )
{
if ( progress >= 0 && progress <= 1 )
m_parent->emitProgress( progress );
}
std::string
obscure( const std::string& string )
{
return CalamaresUtils::obscure( QString::fromStdString( string ) ).toStdString();
}
static QStringList
_gettext_languages()
{
QStringList languages;
// 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();
Calamares::GlobalStorage* gs = jq ? jq->globalStorage() : CalamaresPython::GlobalStoragePythonWrapper::globalStorageInstance();
QVariant localeConf_ = gs->value( "localeConf" );
if ( localeConf_.canConvert< QVariantMap >() )
{
QVariant lang_ = localeConf_.value< QVariantMap >()[ "LANG" ];
if ( lang_.canConvert< QString >() )
{
QString lang = lang_.value< QString >();
languages.append( lang );
if ( lang.indexOf( '.' ) > 0 )
{
lang.truncate( lang.indexOf( '.' ) );
languages.append( lang );
}
if ( lang.indexOf( '_' ) > 0 )
{
lang.truncate( lang.indexOf( '_' ) );
languages.append( lang );
}
}
}
return languages;
}
bp::list
gettext_languages()
{
bp::list pyList;
for ( auto lang : _gettext_languages() )
pyList.append( lang.toStdString() );
return pyList;
}
static void
_add_localedirs( QStringList& pathList, const QString& candidate )
{
if ( !candidate.isEmpty() && !pathList.contains( candidate ) )
{
pathList.prepend( candidate );
if ( QDir( candidate ).cd( "lang" ) )
pathList.prepend( candidate + "/lang" );
}
}
bp::object
gettext_path()
{
// TODO: distinguish between -d runs and normal runs
// TODO: can we detect DESTDIR-installs?
QStringList candidatePaths = QStandardPaths::locateAll( QStandardPaths::GenericDataLocation, "locale", QStandardPaths::LocateDirectory );
QString extra = QCoreApplication::applicationDirPath();
_add_localedirs( candidatePaths, extra ); // Often /usr/local/bin
if ( !extra.isEmpty() )
{
QDir d( extra );
if ( d.cd( "../share/locale" ) ) // Often /usr/local/bin/../share/locale -> /usr/local/share/locale
_add_localedirs( candidatePaths, d.canonicalPath() );
}
_add_localedirs( candidatePaths, QDir().canonicalPath() ); // .
cDebug() << "Standard paths" << candidatePaths;
for ( auto lang : _gettext_languages() )
for ( auto localedir : candidatePaths )
{
QDir ldir( localedir );
cDebug() << "Checking" << lang << "in" <<ldir.canonicalPath();
if ( ldir.cd( lang ) )
return bp::object( localedir.toStdString() );
}
return bp::object(); // None
}
}