From 45ac91c784e764fceb452b74b8840e64fa496ded Mon Sep 17 00:00:00 2001
From: Teo Mrnjavac <teo@kde.org>
Date: Mon, 4 Aug 2014 16:03:33 +0200
Subject: [PATCH] Add check_chroot_call to libcalamares Python interface.

---
 src/libcalamares/PythonJob.cpp                | 122 ++++++++++++------
 src/libcalamares/PythonJobApi.cpp             |  56 +++++++-
 src/libcalamares/PythonJobApi.h               |  10 ++
 .../utils/CalamaresUtilsSystem.cpp            |   5 +-
 4 files changed, 149 insertions(+), 44 deletions(-)

diff --git a/src/libcalamares/PythonJob.cpp b/src/libcalamares/PythonJob.cpp
index df3a110161..0d4d1ac5b8 100644
--- a/src/libcalamares/PythonJob.cpp
+++ b/src/libcalamares/PythonJob.cpp
@@ -43,6 +43,12 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( chroot_call_str_overloads,
 BOOST_PYTHON_FUNCTION_OVERLOADS( chroot_call_list_overloads,
                                  CalamaresPython::chroot_call,
                                  1, 3 );
+BOOST_PYTHON_FUNCTION_OVERLOADS( check_chroot_call_str_overloads,
+                                 CalamaresPython::check_chroot_call,
+                                 1, 3 );
+BOOST_PYTHON_FUNCTION_OVERLOADS( check_chroot_call_list_overloads,
+                                 CalamaresPython::check_chroot_call,
+                                 1, 3 );
 BOOST_PYTHON_MODULE( libcalamares )
 {
     bp::scope().attr( "ORGANIZATION_NAME" ) = CALAMARES_ORGANIZATION_NAME;
@@ -73,43 +79,84 @@ BOOST_PYTHON_MODULE( libcalamares )
     Q_UNUSED( utilsScope );
 
     bp::def( "debug", &CalamaresPython::debug );
-    bp::def( "mount",
-             &CalamaresPython::mount,
-             mount_overloads( bp::args( "device_path",
-                                        "mount_point",
-                                        "filesystem_name",
-                                        "options" ),
-                              "Runs the mount utility with the specified parameters.\n"
-                              "Returns the program's exit code, or:\n"
-                              "-1 = QProcess crash\n"
-                              "-2 = QProcess cannot start\n"
-                              "-3 = bad arguments" ) );
-    bp::def( "chroot_call",
-             static_cast< int (*)( const std::string&,
-                                   const std::string&,
-                                   int ) >( &CalamaresPython::chroot_call ),
-             chroot_call_str_overloads( bp::args( "command",
-                                                  "stdin",
-                                                  "timeout" ),
-                                        "Runs the specified command in the chroot of the target system.\n"
-                                        "Returns the program's exit code, or:\n"
-                                        "-1 = QProcess crash\n"
-                                        "-2 = QProcess cannot start\n"
-                                        "-3 = bad arguments\n"
-                                        "-4 = QProcess timeout" ) );
-    bp::def( "chroot_call",
-             static_cast< int (*)( const bp::list&,
-                                   const std::string&,
-                                   int ) >( &CalamaresPython::chroot_call ),
-             chroot_call_list_overloads( bp::args( "args",
-                                                   "stdin",
-                                                   "timeout" ),
-                                         "Runs the specified command in the chroot of the target system.\n"
-                                         "Returns the program's exit code, or:\n"
-                                         "-1 = QProcess crash\n"
-                                         "-2 = QProcess cannot start\n"
-                                         "-3 = bad arguments\n"
-                                         "-4 = QProcess timeout" ) );
+    bp::def(
+        "mount",
+        &CalamaresPython::mount,
+        mount_overloads(
+            bp::args( "device_path",
+                      "mount_point",
+                      "filesystem_name",
+                      "options" ),
+            "Runs the mount utility with the specified parameters.\n"
+            "Returns the program's exit code, or:\n"
+            "-1 = QProcess crash\n"
+            "-2 = QProcess cannot start\n"
+            "-3 = bad arguments"
+        )
+    );
+    bp::def(
+        "chroot_call",
+        static_cast< int (*)( const std::string&,
+                              const std::string&,
+                              int ) >( &CalamaresPython::chroot_call ),
+        chroot_call_str_overloads(
+            bp::args( "command",
+                      "stdin",
+                      "timeout" ),
+            "Runs the specified command in the chroot of the target system.\n"
+            "Returns the program's exit code, or:\n"
+            "-1 = QProcess crash\n"
+            "-2 = QProcess cannot start\n"
+            "-3 = bad arguments\n"
+            "-4 = QProcess timeout"
+        )
+    );
+    bp::def(
+        "chroot_call",
+        static_cast< int (*)( const bp::list&,
+                              const std::string&,
+                              int ) >( &CalamaresPython::chroot_call ),
+        chroot_call_list_overloads(
+            bp::args( "args",
+                      "stdin",
+                      "timeout" ),
+            "Runs the specified command in the chroot of the target system.\n"
+            "Returns the program's exit code, or:\n"
+            "-1 = QProcess crash\n"
+            "-2 = QProcess cannot start\n"
+            "-3 = bad arguments\n"
+            "-4 = QProcess timeout"
+        )
+    );
+
+    bp::def(
+        "check_chroot_call",
+        static_cast< int (*)( const std::string&,
+                              const std::string&,
+                              int ) >( &CalamaresPython::check_chroot_call ),
+        check_chroot_call_str_overloads(
+            bp::args( "command",
+                      "stdin",
+                      "timeout" ),
+            "Runs the specified command in the chroot of the target system.\n"
+            "Returns 0, which is program's exit code if the program exited "
+            "successfully, or raises a subprocess.CalledProcessError."
+        )
+    );
+    bp::def(
+        "check_chroot_call",
+        static_cast< int (*)( const bp::list&,
+                              const std::string&,
+                              int ) >( &CalamaresPython::check_chroot_call ),
+        check_chroot_call_list_overloads(
+            bp::args( "args",
+                      "stdin",
+                      "timeout" ),
+            "Runs the specified command in the chroot of the target system.\n"
+            "Returns 0, which is program's exit code if the program exited "
+            "successfully, or raises a subprocess.CalledProcessError."
+        )
+    );
 }
 
 
@@ -185,7 +232,6 @@ PythonJob::exec()
 
         bp::object runResult = entryPoint();
 
-        //QString message = QString::fromStdString( bp::extract< std::string >( entryPoint() ) );
         if ( runResult.is_none() )
         {
             return JobResult::ok();
diff --git a/src/libcalamares/PythonJobApi.cpp b/src/libcalamares/PythonJobApi.cpp
index 4e302e1b48..d2532b6af8 100644
--- a/src/libcalamares/PythonJobApi.cpp
+++ b/src/libcalamares/PythonJobApi.cpp
@@ -25,8 +25,9 @@
 #include <QDir>
 
 #undef slots
-#include <boost/python/extract.hpp>
+#include <boost/python.hpp>
 
+namespace bp = boost::python;
 
 namespace CalamaresPython
 {
@@ -56,15 +57,15 @@ chroot_call( const std::string& command,
 
 
 int
-chroot_call( const boost::python::list& args,
+chroot_call( const bp::list& args,
              const std::string& stdin,
              int timeout )
 {
     QStringList list;
-    for ( int i = 0; i < boost::python::len( args ); ++i )
+    for ( int i = 0; i < bp::len( args ); ++i )
     {
         list.append( QString::fromStdString(
-            boost::python::extract< std::string >( args[ i ] ) ) );
+            bp::extract< std::string >( args[ i ] ) ) );
     }
 
     return CalamaresUtils::chrootCall( list,
@@ -73,6 +74,52 @@ chroot_call( const boost::python::list& args,
 }
 
 
+int
+check_chroot_call( const std::string& command,
+                   const std::string& stdin,
+                   int timeout )
+{
+    int ec = chroot_call( command, stdin, timeout );
+    return _handle_check_chroot_call_error( ec, QString::fromStdString( command ) );
+}
+
+
+int
+check_chroot_call( const bp::list& args,
+                   const std::string& stdin,
+                   int timeout )
+{
+    int ec = chroot_call( args, stdin, timeout );
+    if ( !ec )
+        return ec;
+
+    QStringList failedCmdList;
+    for ( int i = 0; i < bp::len( args ); ++i )
+    {
+        failedCmdList.append( QString::fromStdString(
+            bp::extract< std::string >( args[ i ] ) ) );
+    }
+
+    return _handle_check_chroot_call_error( ec, failedCmdList.join( ' ' ) );
+}
+
+
+int
+_handle_check_chroot_call_error( int ec, const QString& cmd )
+{
+    if ( !ec )
+        return ec;
+
+    QString raise = QString( "import subprocess\n"
+                             "raise subprocess.CalledProcessError(%1,\"%2\")" )
+                        .arg( ec )
+                        .arg( cmd );
+    bp::exec( raise.toStdString().c_str() );
+    bp::throw_error_already_set();
+    return ec;
+}
+
+
 void
 debug( const std::string& s )
 {
@@ -97,5 +144,4 @@ PythonJobInterface::setprogress( qreal progress )
         m_parent->emitProgress( progress );
 }
 
-
 }
diff --git a/src/libcalamares/PythonJobApi.h b/src/libcalamares/PythonJobApi.h
index 43c0657a0a..96e0d5efaa 100644
--- a/src/libcalamares/PythonJobApi.h
+++ b/src/libcalamares/PythonJobApi.h
@@ -42,6 +42,16 @@ int chroot_call( const boost::python::list& args,
                  const std::string& stdin = std::string(),
                  int timeout = 0 );
 
+int check_chroot_call( const std::string& command,
+                       const std::string& stdin = std::string(),
+                       int timeout = 0 );
+
+int check_chroot_call( const boost::python::list& args,
+                       const std::string& stdin = std::string(),
+                       int timeout = 0 );
+
+inline int _handle_check_chroot_call_error( int ec, const QString& cmd );
+
 void debug( const std::string& s );
 
 class PythonJobInterface
diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp
index dc414c974c..1cfae4a46d 100644
--- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp
+++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp
@@ -60,8 +60,11 @@ int chrootCall( const QStringList& args,
                 const QString& stdInput,
                 int timeoutSec )
 {
+    if ( !Calamares::JobQueue::instance() )
+        return -3;
+
     Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
-    if ( !gs->contains( "rootMountPoint" ) )
+    if ( !gs || !gs->contains( "rootMountPoint" ) )
     {
         cLog() << "No rootMountPoint in global storage";
         return -3;
-- 
GitLab