[contextualprocess] Implement contextual processes

Allow running one or more commands based on the value of
a global configuration variable. This could, of course,
be done in a Python module with some custom code,
but for simple cases this is more straightforward
to configure through module instances.

Uses the CommandList developed for the ShellProcess
module to do the actual work.

FIXES #874
This commit is contained in:
Adriaan de Groot 2018-01-15 08:57:34 -05:00
parent f01c7cda6b
commit d6cbda5ed7
3 changed files with 100 additions and 8 deletions

View File

@ -1,6 +1,6 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2017, Adriaan de Groot <groot@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
@ -26,8 +26,37 @@
#include "JobQueue.h"
#include "GlobalStorage.h"
#include "utils/CalamaresUtils.h"
#include "utils/CommandList.h"
#include "utils/Logger.h"
struct ContextualProcessBinding
{
ContextualProcessBinding( const QString& _n, const QString& _v, CalamaresUtils::CommandList* _c )
: variable( _n )
, value( _v )
, commands( _c )
{
}
~ContextualProcessBinding();
int count() const
{
return commands ? commands->count() : 0;
}
QString variable;
QString value;
CalamaresUtils::CommandList* commands;
} ;
ContextualProcessBinding::~ContextualProcessBinding()
{
delete commands;
}
ContextualProcessJob::ContextualProcessJob( QObject* parent )
: Calamares::CppJob( parent )
{
@ -36,6 +65,7 @@ ContextualProcessJob::ContextualProcessJob( QObject* parent )
ContextualProcessJob::~ContextualProcessJob()
{
qDeleteAll( m_commands );
}
@ -49,8 +79,17 @@ ContextualProcessJob::prettyName() const
Calamares::JobResult
ContextualProcessJob::exec()
{
QThread::sleep( 3 );
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
for ( const ContextualProcessBinding* binding : m_commands )
{
if ( gs->contains( binding->variable ) && ( gs->value( binding->variable ).toString() == binding->value ) )
{
Calamares::JobResult r = binding->commands->run( this );
if ( !r )
return r;
}
}
return Calamares::JobResult::ok();
}
@ -58,7 +97,41 @@ ContextualProcessJob::exec()
void
ContextualProcessJob::setConfigurationMap( const QVariantMap& configurationMap )
{
m_configurationMap = configurationMap;
m_dontChroot = CalamaresUtils::getBool( configurationMap, "dontChroot", false );
for ( QVariantMap::const_iterator iter = configurationMap.cbegin(); iter != configurationMap.cend(); ++iter )
{
QString variableName = iter.key();
if ( variableName.isEmpty() || ( variableName == "dontChroot" ) )
continue;
if ( iter.value().type() != QVariant::Map )
{
cDebug() << "WARNING:" << moduleInstanceKey() << "bad configuration values for" << variableName;
continue;
}
QVariantMap values = iter.value().toMap();
for ( QVariantMap::const_iterator valueiter = values.cbegin(); valueiter != values.cend(); ++valueiter )
{
QString valueString = valueiter.key();
if ( variableName.isEmpty() )
{
cDebug() << "WARNING:" << moduleInstanceKey() << "variable" << variableName << "unrecognized value" << valueiter.key();
continue;
}
CalamaresUtils::CommandList* commands = new CalamaresUtils::CommandList( valueiter.value(), !m_dontChroot );
if ( commands->count() > 0 )
{
m_commands.append( new ContextualProcessBinding( variableName, valueString, commands ) );
cDebug() << variableName << '=' << valueString << "will execute" << commands->count() << "commands";
}
else
delete commands;
}
}
}
CALAMARES_PLUGIN_FACTORY_DEFINITION( ContextualProcessJobFactory, registerPlugin<ContextualProcessJob>(); )

View File

@ -1,6 +1,6 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2017, Adriaan de Groot <groot@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
@ -22,11 +22,12 @@
#include <QObject>
#include <QVariantMap>
#include <CppJob.h>
#include "CppJob.h"
#include "PluginDllMacro.h"
#include <utils/PluginFactory.h>
#include "utils/PluginFactory.h"
#include <PluginDllMacro.h>
struct ContextualProcessBinding;
class PLUGINDLLEXPORT ContextualProcessJob : public Calamares::CppJob
{
@ -43,7 +44,8 @@ public:
void setConfigurationMap( const QVariantMap& configurationMap ) override;
private:
QVariantMap m_configurationMap;
QList<ContextualProcessBinding*> m_commands;
bool m_dontChroot;
};
CALAMARES_PLUGIN_FACTORY_DECLARATION( ContextualProcessJobFactory )

View File

@ -9,11 +9,28 @@
# If the variable has that particular value, the corresponding
# value is executed as a shell command in the target environment.
#
# You can check for an empty value with "".
#
# The special configuration key *dontChroot* specifies whether
# the commands are run in the target system (default, value *false*),
# or in the host system. This key is not used for comparisons
# with global configuration values.
#
# If a command starts with "-" (a single minus sign), then the
# return value of the command following the - is ignored; otherwise,
# a failing command will abort the installation. This is much like
# make's use of - in a command.
#
# Global configuration variables are not checked in a deterministic
# order, so do not rely on commands from one variable-check to
# always happen before (or after) checks on another
# variable. Similarly, the value-equality checks are not
# done in a deterministic order, but all of the value-checks
# for a given variable happen together.
#
---
dontChroot: false
firmwareType:
efi: "-pkg remove efi-firmware"
bios: "-pkg remove bios-firmware"
"": "/bin/false no-firmware-type-set"