diff --git a/src/modules/contextualprocess/Binding.h b/src/modules/contextualprocess/Binding.h new file mode 100644 index 000000000..fce43a65c --- /dev/null +++ b/src/modules/contextualprocess/Binding.h @@ -0,0 +1,95 @@ +/* === This file is part of Calamares - === + * + * Copyright 2017-2020, Adriaan de Groot + * + * 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 . + */ + +/* This file isn't public API, but is used to express the API that + * the tests for ContextualProcess can work with. + */ +#ifndef CONTEXTUALPROCESSJOB_BINDING_H +#define CONTEXTUALPROCESSJOB_BINDING_H + +#include +#include +#include + +namespace CalamaresUtils +{ +class CommandList; +} +namespace Calamares +{ +class GlobalStorage; +} + +struct ValueCheck : public QPair< QString, CalamaresUtils::CommandList* > +{ + ValueCheck( const QString& value, CalamaresUtils::CommandList* commands ) + : QPair< QString, CalamaresUtils::CommandList* >( value, commands ) + { + } + + // ~ValueCheck() + // + // There is no destructor. + // + // We don't own the commandlist, the binding holding this valuecheck + // does, so don't delete. This is closely tied to (temporaries created + // by) pass-by-value in QList::append(). + + QString value() const { return first; } + CalamaresUtils::CommandList* commands() const { return second; } +}; + +class ContextualProcessBinding +{ +public: + ContextualProcessBinding( const QString& varname ) + : m_variable( varname ) + { + } + + ~ContextualProcessBinding(); + + QString variable() const { return m_variable; } + int count() const { return m_checks.count(); } + + /** + * @brief add commands to be executed when @p value is matched. + * + * Ownership of the CommandList passes to this binding. + */ + void append( const QString& value, CalamaresUtils::CommandList* commands ); + + ///@brief The bound variable has @p value , run the associated commands. + Calamares::JobResult run( const QString& value ) const; + + /** @brief Tries to obtain this binding's value from GS + * + * Stores the value in @p value and returns true if a value + * was found (e.g. @p storage contains the variable this binding + * is for) and false otherwise. + */ + bool fetch( Calamares::GlobalStorage* storage, QString& value ) const; + +private: + QString m_variable; + QList< ValueCheck > m_checks; + CalamaresUtils::CommandList* m_wildcard = nullptr; +}; + + +#endif diff --git a/src/modules/contextualprocess/ContextualProcessJob.cpp b/src/modules/contextualprocess/ContextualProcessJob.cpp index a2aa507ea..b0d7a6743 100644 --- a/src/modules/contextualprocess/ContextualProcessJob.cpp +++ b/src/modules/contextualprocess/ContextualProcessJob.cpp @@ -18,9 +18,7 @@ #include "ContextualProcessJob.h" -#include -#include -#include +#include "Binding.h" #include "CalamaresVersion.h" #include "GlobalStorage.h" @@ -30,120 +28,6 @@ #include "utils/Logger.h" #include "utils/Variant.h" -struct ValueCheck : public QPair< QString, CalamaresUtils::CommandList* > -{ - ValueCheck( const QString& value, CalamaresUtils::CommandList* commands ) - : QPair< QString, CalamaresUtils::CommandList* >( value, commands ) - { - } - - // ~ValueCheck() - // - // There is no destructor. - // - // We don't own the commandlist, the binding holding this valuecheck - // does, so don't delete. This is closely tied to (temporaries created - // by) pass-by-value in QList::append(). - - QString value() const { return first; } - CalamaresUtils::CommandList* commands() const { return second; } -}; - -class ContextualProcessBinding -{ -public: - ContextualProcessBinding( const QString& varname ) - : m_variable( varname ) - { - } - - ~ContextualProcessBinding(); - - QString variable() const { return m_variable; } - int count() const { return m_checks.count(); } - - /** - * @brief add commands to be executed when @p value is matched. - * - * Ownership of the CommandList passes to this binding. - */ - void append( const QString& value, CalamaresUtils::CommandList* commands ) - { - m_checks.append( ValueCheck( value, commands ) ); - if ( value == QString( "*" ) ) - { - m_wildcard = commands; - } - } - - Calamares::JobResult run( const QString& value ) const - { - for ( const auto& c : m_checks ) - { - if ( value == c.value() ) - { - return c.commands()->run(); - } - } - - if ( m_wildcard ) - { - return m_wildcard->run(); - } - - return Calamares::JobResult::ok(); - } - - /** @brief Tries to obtain this binding's value from GS - * - * Stores the value in @p value and returns true if a value - * was found (e.g. @p storage contains the variable this binding - * is for) and false otherwise. - */ - bool fetch( Calamares::GlobalStorage* storage, QString& value ) const - { - value.clear(); - if ( !storage ) - { - return false; - } - if ( m_variable.contains( '.' ) ) - { - QStringList steps = m_variable.split( '.' ); - return fetch( value, steps, 1, storage->value( steps.first() ) ); - } - else - { - value = storage->value( m_variable ).toString(); - return storage->contains( m_variable ); - } - } - -private: - static bool fetch( QString& value, QStringList& selector, int index, const QVariant& v ) - { - if ( !v.canConvert( QMetaType::QVariantMap ) ) - { - return false; - } - const QVariantMap map = v.toMap(); - const QString& key = selector.at( index ); - if ( index == selector.length() ) - { - value = map.value( key ).toString(); - return map.contains( key ); - } - else - { - return fetch( value, selector, index + 1, map.value( key ) ); - } - } - - QString m_variable; - QList< ValueCheck > m_checks; - CalamaresUtils::CommandList* m_wildcard = nullptr; -}; - ContextualProcessBinding::~ContextualProcessBinding() { @@ -154,6 +38,78 @@ ContextualProcessBinding::~ContextualProcessBinding() } } +void +ContextualProcessBinding::append( const QString& value, CalamaresUtils::CommandList* commands ) +{ + m_checks.append( ValueCheck( value, commands ) ); + if ( value == QString( "*" ) ) + { + m_wildcard = commands; + } +} + +Calamares::JobResult +ContextualProcessBinding::run( const QString& value ) const +{ + for ( const auto& c : m_checks ) + { + if ( value == c.value() ) + { + return c.commands()->run(); + } + } + + if ( m_wildcard ) + { + return m_wildcard->run(); + } + + return Calamares::JobResult::ok(); +} + +///@brief Implementation of fetch() for recursively looking up dotted selector parts. +static bool +fetch( QString& value, QStringList& selector, int index, const QVariant& v ) +{ + if ( !v.canConvert( QMetaType::QVariantMap ) ) + { + return false; + } + const QVariantMap map = v.toMap(); + const QString& key = selector.at( index ); + if ( index == selector.length() ) + { + value = map.value( key ).toString(); + return map.contains( key ); + } + else + { + return fetch( value, selector, index + 1, map.value( key ) ); + } +} + + +bool +ContextualProcessBinding::fetch( Calamares::GlobalStorage* storage, QString& value ) const +{ + value.clear(); + if ( !storage ) + { + return false; + } + if ( m_variable.contains( '.' ) ) + { + QStringList steps = m_variable.split( '.' ); + return ::fetch( value, steps, 1, storage->value( steps.first() ) ); + } + else + { + value = storage->value( m_variable ).toString(); + return storage->contains( m_variable ); + } +} + + ContextualProcessJob::ContextualProcessJob( QObject* parent ) : Calamares::CppJob( parent ) { diff --git a/src/modules/contextualprocess/ContextualProcessJob.h b/src/modules/contextualprocess/ContextualProcessJob.h index 3a252d2d3..5ab4b935e 100644 --- a/src/modules/contextualprocess/ContextualProcessJob.h +++ b/src/modules/contextualprocess/ContextualProcessJob.h @@ -27,7 +27,7 @@ #include "utils/PluginFactory.h" -struct ContextualProcessBinding; +class ContextualProcessBinding; class PLUGINDLLEXPORT ContextualProcessJob : public Calamares::CppJob { diff --git a/src/modules/contextualprocess/Tests.cpp b/src/modules/contextualprocess/Tests.cpp index f62726775..8e7000f17 100644 --- a/src/modules/contextualprocess/Tests.cpp +++ b/src/modules/contextualprocess/Tests.cpp @@ -59,6 +59,6 @@ ContextualProcessTests::testProcessListSampleConfig() ContextualProcessJob job; job.setConfigurationMap( CalamaresUtils::yamlMapToVariant( doc ).toMap() ); - QCOMPARE( job.count(), 1 ); // Only "firmwareType" + QCOMPARE( job.count(), 2 ); // Only "firmwareType" and "branding.shortVersion" QCOMPARE( job.count( "firmwareType" ), 4 ); }