source: calamares/trunk/fuentes/src/libcalamares/PythonJobApi.cpp @ 7538

Last change on this file since 7538 was 7538, checked in by kbut, 13 months ago

sync with github

File size: 8.5 KB
Line 
1/* === This file is part of Calamares - <https://github.com/calamares> ===
2 *
3 *   Copyright 2014-2016, Teo Mrnjavac <teo@kde.org>
4 *   Copyright 2017, Adriaan de Groot <groot@kde.org>
5 *
6 *   Calamares is free software: you can redistribute it and/or modify
7 *   it under the terms of the GNU General Public License as published by
8 *   the Free Software Foundation, either version 3 of the License, or
9 *   (at your option) any later version.
10 *
11 *   Calamares is distributed in the hope that it will be useful,
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 *   GNU General Public License for more details.
15 *
16 *   You should have received a copy of the GNU General Public License
17 *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "PythonJobApi.h"
21
22#include "PythonHelper.h"
23#include "utils/Logger.h"
24#include "utils/CalamaresUtilsSystem.h"
25#include "utils/CalamaresUtils.h"
26
27#include "GlobalStorage.h"
28#include "JobQueue.h"
29
30#include <QCoreApplication>
31#include <QDir>
32#include <QStandardPaths>
33
34#undef slots
35#include <boost/python.hpp>
36
37namespace bp = boost::python;
38
39static int
40_handle_check_target_env_call_error( const CalamaresUtils::ProcessResult& ec, const QString& cmd )
41{
42    if ( !ec.first )
43        return ec.first;
44
45    QString raise = QString( "import subprocess\n"
46                             "e = subprocess.CalledProcessError(%1,\"%2\")\n" )
47                    .arg( ec.first )
48                    .arg( cmd );
49    if ( !ec.second.isEmpty() )
50        raise.append( QStringLiteral("e.output = \"\"\"%1\"\"\"\n").arg( ec.second ) );
51    raise.append("raise e");
52    bp::exec( raise.toStdString().c_str() );
53    bp::throw_error_already_set();
54    return ec.first;
55}
56
57namespace CalamaresPython
58{
59
60int
61mount( const std::string& device_path,
62       const std::string& mount_point,
63       const std::string& filesystem_name,
64       const std::string& options )
65{
66    return CalamaresUtils::System::instance()->
67           mount( QString::fromStdString( device_path ),
68                  QString::fromStdString( mount_point ),
69                  QString::fromStdString( filesystem_name ),
70                  QString::fromStdString( options ) );
71}
72
73
74static inline QStringList
75_bp_list_to_qstringlist( const bp::list& args )
76{
77    QStringList list;
78    for ( int i = 0; i < bp::len( args ); ++i )
79    {
80        list.append( QString::fromStdString(
81                         bp::extract< std::string >( args[ i ] ) ) );
82    }
83    return list;
84}
85
86static inline CalamaresUtils::ProcessResult
87_target_env_command(
88    const QStringList& args,
89    const std::string& stdin,
90    int timeout )
91{
92    return CalamaresUtils::System::instance()->
93        targetEnvCommand( args,
94                          QString(),
95                          QString::fromStdString( stdin ),
96                          timeout );
97}
98
99int
100target_env_call( const std::string& command,
101                 const std::string& stdin,
102                 int timeout )
103{
104    return _target_env_command(
105        QStringList{ QString::fromStdString( command ) }, stdin, timeout ).first;
106}
107
108
109int
110target_env_call( const bp::list& args,
111                 const std::string& stdin,
112                 int timeout )
113{
114    return _target_env_command(
115        _bp_list_to_qstringlist( args ), stdin, timeout ).first;
116}
117
118
119int
120check_target_env_call( const std::string& command,
121                       const std::string& stdin,
122                       int timeout )
123{
124    auto ec = _target_env_command(
125        QStringList{ QString::fromStdString( command ) }, stdin, timeout );
126    return _handle_check_target_env_call_error( ec, QString::fromStdString( command ) );
127}
128
129
130int
131check_target_env_call( const bp::list& args,
132                       const std::string& stdin,
133                       int timeout )
134{
135    auto ec = _target_env_command( _bp_list_to_qstringlist( args ), stdin, timeout );
136    if ( !ec.first )
137        return ec.first;
138
139    QStringList failedCmdList = _bp_list_to_qstringlist( args );
140    return _handle_check_target_env_call_error( ec, failedCmdList.join( ' ' ) );
141}
142
143
144std::string
145check_target_env_output( const std::string& command,
146                         const std::string& stdin,
147                         int timeout )
148{
149    auto ec = _target_env_command(
150        QStringList{ QString::fromStdString( command ) }, stdin, timeout );
151    _handle_check_target_env_call_error( ec, QString::fromStdString( command ) );
152    return ec.second.toStdString();
153}
154
155
156std::string
157check_target_env_output( const bp::list& args,
158                         const std::string& stdin,
159                         int timeout )
160{
161    QStringList list = _bp_list_to_qstringlist( args );
162    auto ec = _target_env_command(
163        list, stdin, timeout );
164    _handle_check_target_env_call_error( ec, list.join( ' ' ) );
165    return ec.second.toStdString();
166}
167
168void
169debug( const std::string& s )
170{
171    cDebug() << "[PYTHON JOB]: " << QString::fromStdString( s );
172}
173
174void
175warning( const std::string& s )
176{
177    cWarning() << "[PYTHON JOB]: " << QString::fromStdString( s );
178}
179
180PythonJobInterface::PythonJobInterface( Calamares::PythonJob* parent )
181    : m_parent( parent )
182{
183    auto moduleDir = QDir( m_parent->m_workingPath );
184    moduleName = moduleDir.dirName().toStdString();
185    prettyName = m_parent->prettyName().toStdString();
186    workingPath = m_parent->m_workingPath.toStdString();
187    configuration = CalamaresPython::variantMapToPyDict( m_parent->m_configurationMap );
188}
189
190
191void
192PythonJobInterface::setprogress( qreal progress )
193{
194    if ( progress >= 0 && progress <= 1 )
195        m_parent->emitProgress( progress );
196}
197
198
199std::string
200obscure( const std::string& string )
201{
202    return CalamaresUtils::obscure( QString::fromStdString( string ) ).toStdString();
203}
204
205static QStringList
206_gettext_languages()
207{
208    QStringList languages;
209
210    // There are two ways that Python jobs can be initialised:
211    //  - through JobQueue, in which case that has an instance which holds
212    //    a GlobalStorage object, or
213    //  - through the Python test-script, which initialises its
214    //    own GlobalStoragePythonWrapper, which then holds a
215    //    GlobalStorage object for all of Python.
216    Calamares::JobQueue* jq = Calamares::JobQueue::instance();
217    Calamares::GlobalStorage* gs = jq ? jq->globalStorage() : CalamaresPython::GlobalStoragePythonWrapper::globalStorageInstance();
218
219    QVariant localeConf_ = gs->value( "localeConf" );
220    if ( localeConf_.canConvert< QVariantMap >() )
221    {
222        QVariant lang_ = localeConf_.value< QVariantMap >()[ "LANG" ];
223        if ( lang_.canConvert< QString >() )
224        {
225            QString lang = lang_.value< QString >();
226            languages.append( lang );
227            if ( lang.indexOf( '.' ) > 0 )
228            {
229                lang.truncate( lang.indexOf( '.' ) );
230                languages.append( lang );
231            }
232            if ( lang.indexOf( '_' ) > 0 )
233            {
234                lang.truncate( lang.indexOf( '_' ) );
235                languages.append( lang );
236            }
237        }
238    }
239    return languages;
240}
241
242bp::list
243gettext_languages()
244{
245    bp::list pyList;
246    for ( auto lang : _gettext_languages() )
247        pyList.append( lang.toStdString() );
248    return pyList;
249}
250
251static void
252_add_localedirs( QStringList& pathList, const QString& candidate )
253{
254    if ( !candidate.isEmpty() && !pathList.contains( candidate ) )
255    {
256        pathList.prepend( candidate );
257        if ( QDir( candidate ).cd( "lang" ) )
258            pathList.prepend( candidate + "/lang" );
259    }
260}
261
262bp::object
263gettext_path()
264{
265    // TODO: distinguish between -d runs and normal runs
266    // TODO: can we detect DESTDIR-installs?
267    QStringList candidatePaths = QStandardPaths::locateAll( QStandardPaths::GenericDataLocation, "locale", QStandardPaths::LocateDirectory );
268    QString extra = QCoreApplication::applicationDirPath();
269    _add_localedirs( candidatePaths, extra ); // Often /usr/local/bin
270    if ( !extra.isEmpty() )
271    {
272        QDir d( extra );
273        if ( d.cd( "../share/locale" ) ) // Often /usr/local/bin/../share/locale -> /usr/local/share/locale
274            _add_localedirs( candidatePaths, d.canonicalPath() );
275    }
276    _add_localedirs( candidatePaths, QDir().canonicalPath() ); // .
277
278    cDebug() << "Standard paths" << candidatePaths;
279
280    for ( auto lang : _gettext_languages() )
281        for ( auto localedir : candidatePaths )
282        {
283            QDir ldir( localedir );
284            cDebug() << "Checking" << lang << "in" <<ldir.canonicalPath();
285            if ( ldir.cd( lang ) )
286                return bp::object( localedir.toStdString() );
287        }
288    return bp::object();  // None
289}
290
291
292}
Note: See TracBrowser for help on using the repository browser.