diff options
| author | Stanislaw Halik <sthalik@misaki.pl> | 2016-09-09 08:51:25 +0200 | 
|---|---|---|
| committer | Stanislaw Halik <sthalik@misaki.pl> | 2016-09-09 15:00:58 +0200 | 
| commit | 6bc3fe31a3f354afc7be870a4a2d375ab6c746b6 (patch) | |
| tree | 39b439b16cb872b3d982a6083a546456001d0f8e /migration | |
| parent | cc6fc6577940df89c57db08743b181291c2a4b43 (diff) | |
add support for migrations
They're run from the UI thread so can even be interactive.
Diffstat (limited to 'migration')
| -rw-r--r-- | migration/20160906_0-mappings.cpp | 14 | ||||
| -rw-r--r-- | migration/20160906_1-axis-signs.cpp | 0 | ||||
| -rw-r--r-- | migration/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | migration/export.hpp | 28 | ||||
| -rw-r--r-- | migration/migration.cpp | 129 | ||||
| -rw-r--r-- | migration/migration.hpp | 72 | 
6 files changed, 245 insertions, 0 deletions
| diff --git a/migration/20160906_0-mappings.cpp b/migration/20160906_0-mappings.cpp new file mode 100644 index 00000000..0ff3095a --- /dev/null +++ b/migration/20160906_0-mappings.cpp @@ -0,0 +1,14 @@ +#include "migration.hpp" + +#include <QDebug> + +using namespace migrations; + +struct foo : migration +{ +    const QString& unique_date() const override { qDebug() << "foo"; static QString ret(""); return ret; } +    bool should_run() const override { qDebug() << "bar"; return false; } +    bool run() override { return false; } +}; + +OPENTRACK_MIGRATION(foo); diff --git a/migration/20160906_1-axis-signs.cpp b/migration/20160906_1-axis-signs.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/migration/20160906_1-axis-signs.cpp diff --git a/migration/CMakeLists.txt b/migration/CMakeLists.txt new file mode 100644 index 00000000..d220b002 --- /dev/null +++ b/migration/CMakeLists.txt @@ -0,0 +1,2 @@ +opentrack_boilerplate(opentrack-migration BIN) +target_link_libraries(opentrack-migration opentrack-logic opentrack-spline-widget) diff --git a/migration/export.hpp b/migration/export.hpp new file mode 100644 index 00000000..800ddf35 --- /dev/null +++ b/migration/export.hpp @@ -0,0 +1,28 @@ +#pragma once + +#ifdef BUILD_migration +#   ifdef _WIN32 +#       define OPENTRACK_MIGRATION_LINKAGE __declspec(dllexport) +#   else +#       define OPENTRACK_MIGRATION_LINKAGE +#   endif + +#   ifndef _MSC_VER +#       define OPENTRACK_MIGRATION_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_MIGRATION_LINKAGE +#   else +#       define OPENTRACK_MIGRATION_EXPORT OPENTRACK_MIGRATION_LINKAGE +#   endif + +#else +    #ifdef _WIN32 +    #    define OPENTRACK_MIGRATION_LINKAGE __declspec(dllimport) +    #else +    #    define OPENTRACK_MIGRATION_LINKAGE +    #endif + +    #ifndef _MSC_VER +    #    define OPENTRACK_MIGRATION_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_MIGRATION_LINKAGE +    #else +    #    define OPENTRACK_MIGRATION_EXPORT OPENTRACK_MIGRATION_LINKAGE +    #endif +#endif diff --git a/migration/migration.cpp b/migration/migration.cpp new file mode 100644 index 00000000..6e54de19 --- /dev/null +++ b/migration/migration.cpp @@ -0,0 +1,129 @@ +#include "migration.hpp" + +#include "options/options.hpp" +#include "compat/util.hpp" + +#include <QString> +#include <QSettings> +#include <QDebug> + +#include <memory> + +namespace migrations { + +namespace detail { + +void migrator::register_migration(migration* m) +{ +    migrations().push_back(m); +} + +migrator::vec& migrator::migrations() +{ +    static vec ret; +    return ret; +} + +QString migrator::last_migration_time() +{ +    QString ret; + +    std::shared_ptr<QSettings> s(options::group::ini_file()); + +    s->beginGroup("migrations"); +    ret = s->value("last-migration-at", "19700101_00").toString(); +    s->endGroup(); + +    return ret; +} + +QString migrator::time_after_migrations() +{ +    const vec list = sorted_migrations(); + +    if (list.size() == 0u) +        return QStringLiteral("19700101_00"); + +    QString ret = list[list.size() - 1]->unique_date(); +    ret += QStringLiteral("~"); + +    return ret; +} + +void migrator::set_last_migration_time(const QString& val) +{ +    std::shared_ptr<QSettings> s(options::group::ini_file()); + +    s->beginGroup("migrations"); +    s->setValue("last-migration-at", val); +    s->endGroup(); +} + +migrator::vec migrator::sorted_migrations() +{ +    vec list(migrations()); +    std::sort(list.begin(), list.end(), [](const mm x, const mm y) { return x->unique_date() < y->unique_date(); }); +    return list; +} + +std::vector<QString> migrator::run() +{ +    vec migrations = sorted_migrations(); +    vstr done; + +    const QString last_migration = last_migration_time(); + +    qDebug() << "migration: config" << options::group::ini_filename() << "time" << last_migration; + +    for (migration* m_ : migrations) +    { +        migration& m(*m_); + +        const QString date = m.unique_date(); + +        if (date <= last_migration) +            continue; + +        if (m.should_run()) +        { +            m.run(); +            done.push_back(m.name()); +        } +    } + +    mark_config_as_not_needing_migration(); + +    if (done.size()) +    { +        qDebug() << "migration: done" << done.size() << "units"; +        for (const QString& name : done) +            qDebug() << "--" << name; +        qDebug() << ""; +    } + +    return done; +} + +} + +migration::migration() {} +migration::~migration() {} + +} // ns + +std::vector<QString> run_migrations() +{ +    return migrations::detail::migrator::run(); +} + +void mark_config_as_not_needing_migration() +{ +    using m = migrations::detail::migrator; + +    m::mark_config_as_not_needing_migration(); +} + +void migrations::detail::migrator::mark_config_as_not_needing_migration() +{ +    set_last_migration_time(time_after_migrations()); +} diff --git a/migration/migration.hpp b/migration/migration.hpp new file mode 100644 index 00000000..b9c20f15 --- /dev/null +++ b/migration/migration.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include <QString> +#include <vector> + +#include "export.hpp" + +namespace migrations { + +class migration; +class registrator; + +namespace detail { +    class migrator final +    { +        using mm = migration*; +        template<typename t> using vec_ = std::vector<t>; +        using vstr = vec_<QString>; +        using vec = vec_<mm>; +        static vec& migrations(); +        static QString last_migration_time(); +        static QString time_after_migrations(); +        static void set_last_migration_time(const QString& val); +        migrator() = delete; +        static vec sorted_migrations(); +    public: +        static vstr run(); +        static void register_migration(migration* m); +        static void mark_config_as_not_needing_migration(); +    }; + +    template<typename t> +    struct registrator final +    { +        registrator() +        { +            static t m; +            migrator::register_migration(static_cast<migration*>(&m)); +        } +    }; +} + +#ifndef __COUNTER__ +#   error "oops, need __COUNTER__ extension for preprocessor" +#endif + +#define OPENTRACK_MIGRATION(type) static ::migrations::detail::registrator<type> opentrack_migration_registrator__ ## __COUNTER__ ## _gensym; + +#ifdef Q_CREATOR_RUN +#   pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +class migration +{ +    migration& operator=(const migration&) = delete; +    migration(const migration&) = delete; +    migration& operator=(migration&&) = delete; +    migration(migration&&) = delete; + +public: +    migration(); +    virtual ~migration(); +    virtual QString unique_date() const = 0; +    virtual QString name() const = 0; +    virtual bool should_run() const = 0; +    virtual void run() = 0; +}; + +} + +OPENTRACK_MIGRATION_EXPORT std::vector<QString> run_migrations(); +OPENTRACK_MIGRATION_EXPORT void mark_config_as_not_needing_migration(); | 
