From 1419af0acbff716a2773dc563bd5d93db8f6bd91 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Mon, 19 Aug 2019 15:37:16 +1000 Subject: [PATCH] [vault] Remove everything except unit helpers. This removes the gittin dependency. Contributes to JB#36999 The git-related features are no longer required, so remove them and avoid the gittin dependency. Keep unit.hpp/cpp in the devel library as it is still required to build backup/restore units. Also build with qmake and rename unit.hpp to unit.h for consistency with other Sailfish middleware libraries. --- CMakeLists.txt | 64 -- README.org | 61 -- examples/CMakeLists.txt | 3 - examples/UseVault.qml | 92 --- examples/data.json | 11 - examples/test_cutes.cpp | 55 -- include/vault/config.hpp | 98 --- include/vault/vault.hpp | 129 ---- lib/lib.pro | 31 + {src => lib}/unit.cpp | 8 +- include/vault/unit.hpp => lib/unit.h | 3 +- qml/Vault/CMakeLists.txt | 16 - qml/Vault/plugin.cpp | 32 - qml/Vault/plugin.h | 0 qml/Vault/qmldir | 2 - qml/Vault/vault.cpp | 442 ------------ qml/Vault/vault.hpp | 92 --- rpm/vault.spec | 73 +- src/CMakeLists.txt | 54 -- src/config.hpp.in | 6 - src/transfer.cpp | 294 -------- src/transfer.hpp | 82 --- src/vault-cli.cpp | 72 -- src/vault.cpp | 972 --------------------------- src/vault_config.cpp | 262 -------- tests/.gitignore | 2 - tests/CMakeLists.txt | 48 -- tests/basic_unit.cpp.in | 23 - tests/check_dirs_similar.sh | 7 - tests/main.cpp | 42 -- tests/qml/CMakeLists.txt | 8 - tests/qml/main.cpp | 16 - tests/qml/tst_vault.qml | 56 -- tests/test-unit-text-only | 19 - tests/test-vault-basic | 168 ----- tests/test-vault-move | 118 ---- tests/test-vault-split-uri | 49 -- tests/testing-common-unit.sh | 45 -- tests/testing-common-vault.sh | 64 -- tests/tests.xml.in | 14 - tests/tests_common.cpp | 14 - tests/tests_common.hpp | 54 -- tests/transfer.cpp | 179 ----- tests/unit.cpp | 161 ----- tests/unit1_vault_test.cpp | 30 - tests/unit_all.cpp | 40 -- tests/unit_fail_vault_test | 4 - tests/vault.cpp | 352 ---------- tests/vault_context.hpp | 131 ---- tools/CMakeLists.txt | 11 - tools/gc-default | 2 - tools/git-vault-export | 50 -- tools/git-vault-gc | 145 ---- tools/git-vault-move | 133 ---- tools/git-vault-rebase-generate.awk | 113 ---- tools/git-vault-rebase-prepare.awk | 51 -- tools/git-vault-root | 6 - tools/git-vault-snapshot-units | 26 - tools/git-vault-sync | 161 ----- tools/vault-gc.service.in | 5 - tools/vault-misc | 245 ------- vault-unit.pc.in | 9 - vault.pro | 5 + 63 files changed, 56 insertions(+), 5504 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 examples/CMakeLists.txt delete mode 100644 examples/UseVault.qml delete mode 100644 examples/data.json delete mode 100644 examples/test_cutes.cpp delete mode 100644 include/vault/config.hpp delete mode 100644 include/vault/vault.hpp create mode 100644 lib/lib.pro rename {src => lib}/unit.cpp (98%) rename include/vault/unit.hpp => lib/unit.h (95%) delete mode 100644 qml/Vault/CMakeLists.txt delete mode 100644 qml/Vault/plugin.cpp delete mode 100644 qml/Vault/plugin.h delete mode 100644 qml/Vault/qmldir delete mode 100644 qml/Vault/vault.cpp delete mode 100644 qml/Vault/vault.hpp delete mode 100644 src/CMakeLists.txt delete mode 100644 src/config.hpp.in delete mode 100644 src/transfer.cpp delete mode 100644 src/transfer.hpp delete mode 100644 src/vault-cli.cpp delete mode 100644 src/vault.cpp delete mode 100644 src/vault_config.cpp delete mode 100644 tests/.gitignore delete mode 100644 tests/CMakeLists.txt delete mode 100644 tests/basic_unit.cpp.in delete mode 100755 tests/check_dirs_similar.sh delete mode 100644 tests/main.cpp delete mode 100644 tests/qml/CMakeLists.txt delete mode 100644 tests/qml/main.cpp delete mode 100644 tests/qml/tst_vault.qml delete mode 100755 tests/test-unit-text-only delete mode 100755 tests/test-vault-basic delete mode 100755 tests/test-vault-move delete mode 100755 tests/test-vault-split-uri delete mode 100644 tests/testing-common-unit.sh delete mode 100644 tests/testing-common-vault.sh delete mode 100644 tests/tests.xml.in delete mode 100644 tests/tests_common.cpp delete mode 100644 tests/tests_common.hpp delete mode 100644 tests/transfer.cpp delete mode 100644 tests/unit.cpp delete mode 100644 tests/unit1_vault_test.cpp delete mode 100644 tests/unit_all.cpp delete mode 100755 tests/unit_fail_vault_test delete mode 100644 tests/vault.cpp delete mode 100644 tests/vault_context.hpp delete mode 100644 tools/CMakeLists.txt delete mode 100644 tools/gc-default delete mode 100755 tools/git-vault-export delete mode 100755 tools/git-vault-gc delete mode 100755 tools/git-vault-move delete mode 100644 tools/git-vault-rebase-generate.awk delete mode 100644 tools/git-vault-rebase-prepare.awk delete mode 100755 tools/git-vault-root delete mode 100755 tools/git-vault-snapshot-units delete mode 100755 tools/git-vault-sync delete mode 100644 tools/vault-gc.service.in delete mode 100644 tools/vault-misc delete mode 100644 vault-unit.pc.in create mode 100644 vault.pro diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index c815baf..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,64 +0,0 @@ -PROJECT(VAULT) -cmake_minimum_required(VERSION 2.8.8) - -message(STATUS "Tools go to ${TOOLS_DIR}") -set(prefix ${CMAKE_INSTALL_PREFIX}) - -IF(NOT DEFINED VERSION OR VERSION STREQUAL "") -message(FATAL_ERROR "Define VERSION") -ENDIF(NOT DEFINED VERSION OR VERSION STREQUAL "") - -IF(NOT DEFINED LONG_VERSION OR LONG_VERSION STREQUAL "") -set(LONG_VERSION ${VERSION}) -ENDIF(NOT DEFINED LONG_VERSION OR LONG_VERSION STREQUAL "") - -message(STATUS "Version ${VERSION}") -message(STATUS "Long version is ${LONG_VERSION}") - -find_package(PkgConfig REQUIRED) -find_package(Qt5Core REQUIRED) -find_package(Cor REQUIRED) - -set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -fPIC -W -Wall -Wextra -g -O2 -std=c++0x") - -#-Wno-psabi is to remove next g++ warning/note: -#the mangling of 'va_list' has changed in GCC 4.4 -set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -Wno-psabi") - -# fix for gcc 4.6 specific compiling/linking issues, no dwarf-4 -set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -gdwarf-3" - ) - -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${CMAKE_CURRENT_SOURCE_DIR}/src -) - -pkg_check_modules(QTAROUND qtaround REQUIRED) -include_directories( - ${COR_INCLUDE_DIRS} - ${QTAROUND_INCLUDE_DIRS} -) -link_directories( - ${COR_LIBRARY_DIRS} - ${QTAROUND_LIBRARY_DIRS} -) - -add_subdirectory(src) -add_subdirectory(examples) -add_subdirectory(tests) -add_subdirectory(qml/Vault) -add_subdirectory(tools) - -configure_install_pkgconfig(vault-unit) - -install( - DIRECTORY include/vault - DESTINATION include - FILES_MATCHING - PATTERN "*.hpp" - PATTERN "*.h" -) diff --git a/README.org b/README.org index 56e9f7d..3c337ea 100644 --- a/README.org +++ b/README.org @@ -1,51 +1,5 @@ * vault -Set of tools to perform backup/restoration of the data. This is the -rewrite of [[https://github.com/nemomobile/the-vault][the-vault]] in C++. - -It uses git for data and metadata management. Binaries are stored -separately now inside .git repository. Some ideas are borrowed from -git-annex but this framework has more permissive license. - -** Rationale - -Application developers ordinary understand backup as a process of -performing a snapshots of an application state and restoration as a -replacement of application state with a previously saved state. So, -the common strategy of backup is to freeze application workflow, make -a snapshot of application data and continue to work. Restoration is -the reverse process. - -This is the bad practice: imagine, application database is damaged as -a result of some bug in application code (this is becomes more and -more common) and initially there is no any visible changes in -application behaviour, user performs backup, but later user notices -issues in application/system behaviour and want to restore its state -from backup was done eariler. But because database was corrupted -before, restoring data from this backup will result in the same issues -to reappear soon. Also, maybe user added some data in the mean time, -so restoration also will result in this data will be lost. Finally, -user still has damaged database while one lost data he/she added in -the meantime. - -The proper and flexible way to backup/restore application data is to -work with exporting/importing structured data and saving/restoring -opaque data. So, like in relational databases world application data -can be separated: - -- data (structured) can be represented in human-readable form - (e.g. for relational database this is SQL, for contacts database it - can be vCard files, maybe, EXIF information from images, MP3 tags - etc.). Also small binary files can be put here - -- opaque, binary data aka blobs (e.g. images, videos, audio files, can - be also something like PDF files (potentially can be exported but it - is hard to do it and can result in some data loss), maybe documents - in binary formats etc. - -So, application communication with backup world is described in terms -of the following operations: export/import/clear - ** Backup API Each application should register path to executable to be invoked for @@ -63,18 +17,3 @@ Options: - --action -- which action should be executed. Possible values are: import, export, clear. -** TODO Examples - -** Planned features - -- Huge files should be detected and managed automatically in many - cases. - -- It looks like it is possible to improve usability replacing separate - storage for BLOBs (.git/blobs) with git submodule with - pack.windowmemory set to finite value - multiply of device RAM and - splitting BLOBs to smaller chunks. So, it will be possible to clone - repo and submodule using standard git w/o any enhancements. - - - diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt deleted file mode 100644 index b4bb061..0000000 --- a/examples/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_executable(use_cutes test_cutes.cpp) -qt5_use_modules(use_cutes Core) -target_link_libraries(use_cutes qtaround) diff --git a/examples/UseVault.qml b/examples/UseVault.qml deleted file mode 100644 index f96691e..0000000 --- a/examples/UseVault.qml +++ /dev/null @@ -1,92 +0,0 @@ -import QtQuick 2.0 -import NemoMobile.Vault 1.1 - -QtObject { - property Vault vault: Vault { - onDone: vaultOperationDone(operation, data) - onProgress: vaultOperationProgress(operation, data) - onError: vaultOperationError(operation, error) - onData: vaultData(id, context) - } - - // event handlers - - function vaultOperationDone(operation, data) { - console.log("vault operation", operation, "done") - var action - switch (operation) { - case Vault.Connect: - break - case Vault.Maintenance: - break - case Vault.Backup: - break - case Vault.Restore: - break - case Vault.RemoveSnapshot: - break - case Vault.ExportSnapshot: - console.log("snapshot exporting is done" - , data.rc, data.snapshot, data.dst - , data.stdout, data.stderr) - break - case Vault.ExportImportPrepare: - break - case Vault.ExportImportExecute: - break - default: - break - } - } - - function vaultData(operation, context) { - switch (operation) { - case Vault.SnapshotUnits: - break - case Vault.Snapshots: - break - case Vault.Units: - break - default: - break - } - } - - function vaultOperationProgress(operation, data) { - switch (operation) { - case Vault.Backup: - break - case Vault.Restore: - break - case Vault.ExportImportExecute: - break - default: - break - } - } - - function vaultOperationError(operation, error) { - console.log("vault operation", operation, "error") - switch (operation) { - case Vault.Connect: - break - case Vault.Backup: - break - case Vault.Restore: - break - case Vault.RemoveSnapshot: - break - case Vault.ExportImportPrepare: - break - case Vault.ExportImportExecute: - break - case Vault.ExportSnapshot: - console.log("error exporting snapshot" - , error.rc, error.snapshot, error.dst - , error.stdout, error.stderr) - default: - break - } - } - -} diff --git a/examples/data.json b/examples/data.json deleted file mode 100644 index fa3c5c9..0000000 --- a/examples/data.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "Accounts", - "group": "organizer", - "icon": "icon-launcher-accounts", - "script": "/usr/share/jolla-vault/units/accounts.js", - "aux" : { - "a" : 1, - "b" : "c" - }, - "array" : [ "x1", "y2" ] -} diff --git a/examples/test_cutes.cpp b/examples/test_cutes.cpp deleted file mode 100644 index ca12742..0000000 --- a/examples/test_cutes.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include - -namespace os = qtaround::os; -namespace error = qtaround::error; -namespace sys = qtaround::sys; -namespace json = qtaround::json; -namespace debug = qtaround::debug; - -int main(int argc, char *argv[]) -{ - QCoreApplication app(argc, argv); - try { - qDebug() << os::path::exists(".") - << os::mkdir("./tmp1", {{"parent", true}}) - << os::mkdir("./tmp2/tmp3", {{"parent", true}}) - << os::mkdir("tmp4") - - ; - debug::print(1, map({{"w", 2}})); - debug::debug("w", "e"); - debug::error("error", "more info", 1); - - auto v = json::read("data.json"); - debug::print(v, get(v, "name"), get(v, "array", 0)); - // is movable - auto v2 = std::move(v); - debug::print(v2); - - QVariantMap options_info - = {{"data_dir", map({{"short", "d"}, {"long", "dir"} - , {"required", true}, {"has_param", true}})} - , {"bin_dir", map({{"short", "b"}, {"long", "bin-dir"} - , {"required", true}, {"has_param", true}})} - , {"home", map({{"short", "H"}, {"long", "home-dir"} - , {"required", true}, {"has_param", true}})} - , {"action", map({{"short", "a"}, {"long", "action"} - , {"required", true}, {"has_param", true}})}}; - - sys::getopt(options_info); - - } catch(error::Error const &e) { - qDebug() << "E:" << e.m; - } catch (std::exception const &e) { - qDebug() << "E:" << e.what(); - } - - return 0; -} diff --git a/include/vault/config.hpp b/include/vault/config.hpp deleted file mode 100644 index 42575eb..0000000 --- a/include/vault/config.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef _VAULT_CONFIG_HPP_ -#define _VAULT_CONFIG_HPP_ -/** - * @file config.hpp - * @brief Vault configuration - * @author Giulio Camuffo - * @copyright (C) 2014 Jolla Ltd. - * @par License: LGPL 2.1 http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html - */ - -#include -#include -#include - -#include - -namespace Gittin { -class Repo; -} - -namespace vault { namespace config { - -namespace { - -namespace os = qtaround::os; - -const QString prefix = ".f8b52b7481393a3e6ade051ecfb549fa"; - -static inline QString units_path(QString const &vaultDir) -{ - return os::path::join(vaultDir, ".units"); -} - -} - -class Unit -{ -public: - Unit(); - explicit Unit(const QVariantMap &data); - - Unit &read(const QString &fname); - ssize_t write(const QString &fname); - bool update(const QVariantMap &src); - - QString name() const; - QString script() const; - inline QVariantMap data() const { return m_data; } - - bool isLocal() const { return is(m_data.value("local", QVariant(false))); } -private: - QVariantMap m_data; -}; - -class Config -{ -public: - explicit Config(const QString &unitsDir); - ~Config(); - - void load(); - bool set(const QVariantMap &data); - QString rm(const QString &name); - - void setUnitsDir(const QString &unitsDir); - - QMap units() const; - QString path(const QString &fname) const; - QString root() const; - -private: - QString m_unitsDir; - QMap m_units; -}; - -Config *global(); - -class Vault -{ -public: - explicit Vault(Gittin::Repo *vcs); - ~Vault(); - - bool set(const QVariantMap &data); - bool rm(const QString &name); - bool update(const QMap &src); - bool update(const QVariantMap &src); - - QMap units() const; - -private: - Config m_config; - Gittin::Repo *m_vcs; -}; - -}} - -#endif // _VAULT_CONFIG_HPP_ diff --git a/include/vault/vault.hpp b/include/vault/vault.hpp deleted file mode 100644 index 8c4cf00..0000000 --- a/include/vault/vault.hpp +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef _VAULT_VAULT_HPP_ -#define _VAULT_VAULT_HPP_ -/** - * @file vault.hpp - * @brief Vault management API - * @author Giulio Camuffo - * @copyright (C) 2014 Jolla Ltd. - * @par License: LGPL 2.1 http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html - */ - -#include -#include - -#include - -#include - -#include - -namespace vault { - -enum class File { Message, VersionTree, VersionRepo, State, Lock - , Last_ = Lock }; - -QString fileName(File); - -class Snapshot -{ -public: - explicit Snapshot(const Gittin::Tag &commit); - explicit Snapshot(Gittin::Repo *repo, const QString &name); - inline Gittin::Tag tag() const { return m_tag; } - - QString name() const; - void remove(); - -private: - Gittin::Tag m_tag; -}; - -typedef std::shared_ptr Lock; -typedef std::weak_ptr Barrier; - - -class Vault -{ -public: - struct Result { - QStringList succededUnits; - QStringList failedUnits; - Result() {} - Result(Result &&from) - : succededUnits(std::move(from.succededUnits)) - , failedUnits(std::move(from.failedUnits)) - {} - Result(Result const &) = delete; - Result & operator = (Result const &) = delete; - }; - struct UnitPath { - QString path; - QString bin; - QString data; - bool exists() const; - }; - - typedef std::function ProgressCallback; - Vault(const QString &path); - - bool init(const QVariantMap &config = QVariantMap()); - Result backup(const QString &home, const QStringList &units, const QString &message, const ProgressCallback &callback = nullptr); - Result restore(const Snapshot &snapshot, const QString &home, const QStringList &units, const ProgressCallback &callback = nullptr); - Result restore(const QString &snapshot, const QString &home, const QStringList &units, const ProgressCallback &callback = nullptr); - bool clear(const QVariantMap &options); - - QList snapshots() const; - QList units(QString const & snapshotName) const; - Snapshot snapshot(const QByteArray &tag) const; - QString notes(const QString &snapshotName); - - bool exists() const; - bool isInvalid(); - config::Vault config(); - UnitPath unitPath(const QString &name) const; - inline QString root() const { return m_path; } - - void registerConfig(const QVariantMap &config); - void unregisterUnit(const QString &unit); - - bool writeFile(const QString &file, const QString &content); - - static int execute(const QVariantMap &options); - bool ensureValid(); - void reset(const QByteArray &treeish = QByteArray()); - - Lock lock() const; - - void resetLastSnapshot(); - - std::tuple backupUnit(const QString &, const QString &); - QString tagSnapshot(const QString &message); - - std::tuple restoreUnit - (const QString &, const QString &, const QString &); - - std::tuple exportSnapshot(QString const &, QString const&); -private: - bool setState(const QString &state); - bool backupUnit(const QString &home, const QString &unit, const ProgressCallback &callback); - bool restoreUnit(const QString &home, const QString &unit, const ProgressCallback &callback); - void checkout(const QString &); - void resetMaster(); - - void setup(const QVariantMap *config); - QString absolutePath(QString const &) const; - QString readFile(const QString &relPath); - - void setVersion(File, int); - int getVersion(File); - - const QString m_path; - const QString m_blobStorage; - Gittin::Repo m_vcs; - config::Vault m_config; - mutable Barrier m_barrier; -}; - -} - -#endif // _VAULT_VAULT_HPP_ diff --git a/lib/lib.pro b/lib/lib.pro new file mode 100644 index 0000000..bd1edc6 --- /dev/null +++ b/lib/lib.pro @@ -0,0 +1,31 @@ +TEMPLATE = lib +TARGET = vault +TARGET = $$qtLibraryTarget($$TARGET) +TARGETPATH = $$[QT_INSTALL_LIBS] + +CONFIG += create_pc create_prl no_install_prl link_pkgconfig +PKGCONFIG += qtaround + +MOC_DIR = $$OUT_PWD/.moc +OBJECTS_DIR = $$OUT_PWD/.obj +RCC_DIR = $$OUT_PWD/.rcc + +SOURCES += unit.cpp +HEADERS += unit.h + +develheaders.path = /usr/include/vault +develheaders.files = unit.h + +target.path = $$[QT_INSTALL_LIBS] +pkgconfig.files = $$TARGET.pc +pkgconfig.path = $$target.path/pkgconfig + +QMAKE_PKGCONFIG_NAME = lib$$TARGET +QMAKE_PKGCONFIG_DESCRIPTION = Vault development files +QMAKE_PKGCONFIG_LIBDIR = $$target.path +QMAKE_PKGCONFIG_INCDIR = $$develheaders.path +QMAKE_PKGCONFIG_DESTDIR = pkgconfig +QMAKE_PKGCONFIG_REQUIRES = Qt5Core +QMAKE_PKGCONFIG_VERSION = $$VERSION + +INSTALLS += target develheaders pkgconfig diff --git a/src/unit.cpp b/lib/unit.cpp similarity index 98% rename from src/unit.cpp rename to lib/unit.cpp index 9a3f51f..0ba1d22 100644 --- a/src/unit.cpp +++ b/lib/unit.cpp @@ -6,7 +6,7 @@ * @par License: LGPL 2.1 http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html */ -#include +#include "unit.h" #include #include @@ -27,6 +27,8 @@ namespace vault { namespace unit { static const unsigned current_version = 1; static const QString default_preserve = "mode,ownership,timestamps"; +static const QString config_prefix = ".f8b52b7481393a3e6ade051ecfb549fa"; + namespace { QVariantMap options_info = {{"dir", map({{"short", "d"}, {"long", "dir"} @@ -52,7 +54,7 @@ typedef QList list_type; class Version { public: Version(QString const &root) - : fname(os::path::join(root, vault::config::prefix + ".unit.version")) + : fname(os::path::join(root, config_prefix + ".unit.version")) {} unsigned get() { @@ -131,7 +133,7 @@ class Operation static QString get_link_info_fname(QString const &root) { - return os::path::join(root, vault::config::prefix + ".links"); + return os::path::join(root, config_prefix + ".links"); } Version version(QString const &root) diff --git a/include/vault/unit.hpp b/lib/unit.h similarity index 95% rename from include/vault/unit.hpp rename to lib/unit.h index fede10e..0fc8ed5 100644 --- a/include/vault/unit.hpp +++ b/lib/unit.h @@ -8,9 +8,10 @@ * @par License: LGPL 2.1 http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html */ -#include #include +#include + namespace qtaround { namespace sys { class GetOpt; }} namespace vault { namespace unit { diff --git a/qml/Vault/CMakeLists.txt b/qml/Vault/CMakeLists.txt deleted file mode 100644 index b0e3868..0000000 --- a/qml/Vault/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ - -set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(CMAKE_AUTOMOC TRUE) - -find_package(Qt5Qml REQUIRED) - -add_library(vault-declarative SHARED plugin.cpp vault.cpp) -qt5_use_modules(vault-declarative Qml) -target_link_libraries(vault-declarative vault-core vault-transfer) - -set_target_properties(vault-declarative PROPERTIES - SOVERSION 0 - VERSION ${VERSION} - ) -install(TARGETS vault-declarative DESTINATION ${DST_LIB}/qt5/qml/NemoMobile/Vault) -install(FILES qmldir DESTINATION ${DST_LIB}/qt5/qml/NemoMobile/Vault) diff --git a/qml/Vault/plugin.cpp b/qml/Vault/plugin.cpp deleted file mode 100644 index f54fa02..0000000 --- a/qml/Vault/plugin.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include -#include -#include - -#include "vault.hpp" - -QT_BEGIN_NAMESPACE - -class VaultPlugin : public QQmlExtensionPlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") - -public: - virtual void registerTypes(const char *uri) - { - Q_ASSERT(QLatin1String(uri) == QLatin1String("NemoMobile.Vault")); - qmlRegisterType(uri, 1, 0, "Vault"); - qmlRegisterType(uri, 1, 1, "Vault"); - } - - void initializeEngine(QQmlEngine *engine, const char *uri) - { - Q_UNUSED(uri); - Q_UNUSED(engine); - } -}; - -QT_END_NAMESPACE - -#include "plugin.moc" diff --git a/qml/Vault/plugin.h b/qml/Vault/plugin.h deleted file mode 100644 index e69de29..0000000 diff --git a/qml/Vault/qmldir b/qml/Vault/qmldir deleted file mode 100644 index 4d2210a..0000000 --- a/qml/Vault/qmldir +++ /dev/null @@ -1,2 +0,0 @@ -module NemoMobile.Vault -plugin vault-declarative diff --git a/qml/Vault/vault.cpp b/qml/Vault/vault.cpp deleted file mode 100644 index 2cc9c8f..0000000 --- a/qml/Vault/vault.cpp +++ /dev/null @@ -1,442 +0,0 @@ -#include -#include -#include -#include -#include - -#include - -#include "vault.hpp" - -namespace os = qtaround::os; -namespace error = qtaround::error; -namespace debug = qtaround::debug; - -Q_DECLARE_METATYPE(Vault::Operation) -static const int _vault_operation_ __attribute__((unused)) -= qRegisterMetaType(); -Q_DECLARE_METATYPE(Vault::ImportExportAction) -static const int _vault_importexportaction_ __attribute__((unused)) -= qRegisterMetaType(); -Q_DECLARE_METATYPE(Vault::DataType) -static const int _vault_datatype__ __attribute__((unused)) -= qRegisterMetaType(); - -class Worker : public QObject -{ - Q_OBJECT -public: - Worker() - : QObject() - , m_vault(nullptr) - , m_transfer(nullptr) - { - } - - ~Worker() - { - delete m_vault; - delete m_transfer; - } - - Q_INVOKABLE void init(const QString &root) - { - m_vault = new vault::Vault(root); - QVariantMap options = {{ "user.name", "Some Sailor"}, {"user.email", "sailor@jolla.com"}}; - if (!m_vault->init(options)) { - error::raise({{"msg", "Can't init vault"}, {"path", root}}); - } - syncConfig(); - } - - void syncConfig() - { - vault::config::Config *global = vault::config::global(); - m_vault->config().update(global->units()); - } - - Q_INVOKABLE void restore(const QString &home, const QStringList &units, const QString &snapshot) - { - debug::debug("Restore: home", home); - m_vault->restore(snapshot, home, units, [this](const QString unit, const QString &status) { - emit progress(Vault::Restore, {{"unit", unit}, {"status", status}}); - }); - emit done(Vault::Restore, QVariantMap()); - } - - Q_INVOKABLE void reset() - { - debug::debug("Reset storage master to the last snapshot"); - m_vault->resetLastSnapshot(); - emit done(Vault::Maintenance, {{"operation", "reset"}}); - } - - Q_INVOKABLE void backupUnit(const QString &home, const QString &unit) - { - debug::debug(home, "- backup unit", unit); - auto res = m_vault->backupUnit(home, unit); - emit progress(Vault::Backup, {{"unit", unit}, {"status", std::get<2>(res)}}); - } - - Q_INVOKABLE void restoreUnit(const QString &snapshot - , const QString &home - , const QString &unit) - { - debug::debug(home, "- restore unit", unit, "snapshot", snapshot); - auto res = m_vault->restoreUnit(snapshot, home, unit); - emit progress(Vault::Restore, {{"unit", unit}, {"status", std::get<2>(res)}}); - } - - Q_INVOKABLE void tagSnapshot(const QString &message) - { - debug::debug("Tag snapshot, message:", message); - auto tag = m_vault->tagSnapshot(message); - emit done(Vault::Backup, {{"tag", tag}}); - } - - Q_INVOKABLE void backup(const QString &home, const QStringList &units, const QString &message) - { - debug::debug("Backup: home", home); - auto res = m_vault->backup(home, units, message, [this](const QString unit, const QString &status) { - emit progress(Vault::Backup, {{"unit", unit}, {"status", status}}); - }); - if (res.failedUnits.size() == 0) { - emit done(Vault::Backup, QVariantMap()); - } else { - QVariantMap info{{"msg", "Backup of some units is failed"} - , {"reason", "Backup"} - , {"succeeded", res.succededUnits} - , {"failed", res.failedUnits}}; - emit error(Vault::Backup, info); - } - } - - QStringList snapshots() const - { - auto snapshots = m_vault->snapshots(); - QStringList snaps; - for (const vault::Snapshot &ss: snapshots) { - snaps << ss.name(); - } - return snaps; - } - - Q_INVOKABLE bool destroy() - { - debug::debug("Destroy vault"); - QVariantMap msg = {{"destroy", true}, {"ignore_snapshots", true}}; - return m_vault->clear(msg); - } - - Q_INVOKABLE void eiPrepare(Vault::ImportExportAction action, const QString &path) - { - if (!m_transfer) { - m_transfer = new CardTransfer; - } - try { - CardTransfer::Action ac = action == Vault::Import ? CardTransfer::Import : CardTransfer::Export; - m_transfer->init(m_vault, ac, path); - QVariantMap data; - data["action"] = action ==Vault:: Import ? "import" : "export"; - data["src"] = m_transfer->getSrc(); - emit done(Vault::ExportImportPrepare, data); - } catch (error::Error e) { - emit error(Vault::ExportImportPrepare, e.m); - } - } - - Q_INVOKABLE void eiExecute() - { - if (!m_transfer) { - emit error(Vault::ExportImportExecute - , map({{"message", "exportImportPrepare was not called"} - , {"reason", "Logic"}})); - return; - } - try { - m_transfer->execute([this](QVariantMap &&map) { - emit progress(Vault::ExportImportExecute, map); - }); - emit done(Vault::ExportImportExecute, QVariantMap()); - } catch (error::Error e) { - emit error(Vault::ExportImportExecute, e.m); - } - } - - Q_INVOKABLE void rmSnapshot(const QString &name) - { - debug::debug("Requesting snapshot removal:", name); - for (vault::Snapshot ss: m_vault->snapshots()) { - if (ss.name() == name) { - ss.remove(); - break; - } - } - - if (snapshots().size() == 0) { - // TODO This action should be done only until proper - // garbage collection will be introduced - debug::warning("Last snapshot is removed, destroy storage to conserve space"); - QString root = m_vault->root(); - destroy(); - try { - init(root); - } catch (error::Error e) { - debug::error("Error reconnecting", e.what()); - emit error(Vault::RemoveSnapshot, e.m); - } - } else { - debug::debug("There are some snapshots, continue"); - } - emit done(Vault::RemoveSnapshot, QVariantMap()); - } - - QVariantMap units() - { - QVariantMap res; - for (auto &u: m_vault->config().units()) - res.insert(u.name(), u.data()); - - return res; - } - - Q_INVOKABLE void requestData(Vault::DataType dataType - , QVariantMap const &context) - { - try { - if (dataType == Vault::SnapshotUnits) { - auto snapshotName = str(context["snapshot"]); - auto reply = context; - auto unitNames = m_vault->units(snapshotName).toSet(); - auto allUnits = units(); - for (auto it = allUnits.begin(); it != allUnits.end(); ++it) { - auto info = it.value().toMap(); - info["snapshot"] = unitNames.contains(it.key()) ? snapshotName : ""; - it.value() = info; - } - reply["units"] = allUnits; - emit data(dataType, reply); - } - } catch (error::Error const &e) { - emit error(Vault::Data, e.m); - } catch (...) { - emit error(Vault::Data, map({{"Exception", "unknown"}})); - } - } - - Q_INVOKABLE void exportSnapshot(const QString &snapshot, const QString &dstDir) - { - auto res = m_vault->exportSnapshot(snapshot, dstDir); - int rc = std::get<0>(res); - auto data = map({{"snapshot", snapshot}, {"dst", dstDir} - , {"rc", std::get<0>(res)}, {"stdout", std::get<1>(res)} - , {"stderr", std::get<2>(res)}}); - if (!rc) - emit done(Vault::ExportSnapshot, data); - else - emit error(Vault::ExportSnapshot, data); - } - -signals: - void progress(Vault::Operation op, const QVariantMap &map); - void error(Vault::Operation op, const QVariantMap &error); - void done(Vault::Operation op, const QVariantMap &); - void data(Vault::DataType id, const QVariantMap &data); - -public: - vault::Vault *m_vault; - CardTransfer *m_transfer; -}; - - -Vault::Vault(QObject *p) - : QObject(p) - , m_worker(nullptr) - , m_home(os::home()) - , m_root(os::path::join(m_home, ".vault")) -{ -} - -Vault::~Vault() -{ - m_workerThread.quit(); - m_workerThread.wait(); - delete m_worker; -} - -QString Vault::root() const -{ - return m_root; -} - -QString Vault::backupHome() const -{ - return m_home; -} - -void Vault::setRoot(const QString &root) -{ - if (m_root != root) { - m_root = root; - emit rootChanged(); - } -} - -void Vault::setBackupHome(const QString &home) -{ - if (m_home != home) { - m_home = home; - emit backupHomeChanged(); - } -} - -void Vault::initWorker(bool reload) -{ - debug::info((reload ? "re" : ""), "connect to vault"); - debug::debug("Vault in", m_root, ", Home is", m_home); - debug::info("Init vault actor, exist", m_worker, "reload=", reload); - if (!m_worker) { - m_worker = new Worker; - m_worker->moveToThread(&m_workerThread); - m_workerThread.start(); - reload = false; - connect(m_worker, &Worker::progress, this, &Vault::progress); - connect(m_worker, &Worker::error, this, &Vault::error); - connect(m_worker, &Worker::done, this, &Vault::done); - connect(m_worker, &Worker::data, this, &Vault::data); - } - try { - m_worker->init(m_root); - emit done(Vault::Connect, QVariantMap()); - } catch (error::Error e) { - emit error(Vault::Connect, e.m); - } -} - -void Vault::connectVault(bool reconnect) -{ - if (m_worker && !reconnect) { - emit done(Vault::Connect, QVariantMap()); - return; - } - - initWorker(reconnect); -} - -void Vault::startRestore(const QString &snapshot, const QStringList &units) -{ - if (units.isEmpty()) { - debug::info("Nothing to restore"); - emit done(Vault::Restore, QVariantMap()); - return; - } - - QMetaObject::invokeMethod(m_worker, "restore", Q_ARG(QString, m_home), Q_ARG(QStringList, units), Q_ARG(QString, snapshot)); -} - -void Vault::startBackup(const QString &message, const QStringList &units) -{ - if (units.isEmpty()) { - debug::info("Nothing to backup"); - emit done(Vault::Backup, QVariantMap()); - return; - } - - QMetaObject::invokeMethod(m_worker, "backup", Q_ARG(QString, m_home), Q_ARG(QStringList, units), Q_ARG(QString, message)); -} - -QStringList Vault::snapshots() const -{ - return m_worker->snapshots(); -} - -QVariantMap Vault::units() const -{ - return m_worker->units(); -} - -void Vault::resetHead() -{ - m_worker->m_vault->reset(); -} - -void Vault::removeSnapshot(const QString &name) -{ - QMetaObject::invokeMethod(m_worker, "rmSnapshot", Q_ARG(QString, name)); -} - -void Vault::exportImportPrepare(ImportExportAction action, const QString &path) -{ - QMetaObject::invokeMethod(m_worker, "eiPrepare", Q_ARG(Vault::ImportExportAction, action), Q_ARG(QString, path)); -} - -void Vault::exportImportExecute() -{ - QMetaObject::invokeMethod(m_worker, "eiExecute"); -} - -QString Vault::notes(const QString &snapshot) const -{ - return m_worker->m_vault->notes(">" + snapshot); -} - -void Vault::registerUnit(const QJSValue &unit, bool global) -{ - QVariantMap map = unit.toVariant().toMap(); - if (global) { - vault::config::global()->set(map); - } else { - if (!m_worker) { - initWorker(false); - } - m_worker->m_vault->registerConfig(map); - } -} - -void Vault::startGc() -{ - if (os::system("systemctl", {"--user", "start", "vault-gc.service"}) != 0) - debug::error("Can't start vault-gc.service"); -} - -void Vault::requestData(DataType dataType, QVariantMap const &context) -{ - QMetaObject::invokeMethod(m_worker, "requestData" - , Q_ARG(Vault::DataType, dataType) - , Q_ARG(QVariantMap, context)); -} - -/// reset storage to the master head, cleanup tree -void Vault::reset() -{ - QMetaObject::invokeMethod(m_worker, "reset"); -} - -Q_INVOKABLE void Vault::backupUnit(const QString &unit) -{ - QMetaObject::invokeMethod(m_worker, "backupUnit" - , Q_ARG(QString, m_home) - , Q_ARG(QString, unit)); -} - -Q_INVOKABLE void Vault::tagSnapshot(const QString &message) -{ - QMetaObject::invokeMethod(m_worker, "tagSnapshot", Q_ARG(QString, message)); -} - -Q_INVOKABLE void Vault::restoreUnit(const QString &snapshot, const QString &unit) -{ - QMetaObject::invokeMethod(m_worker, "restoreUnit" - , Q_ARG(QString, snapshot) - , Q_ARG(QString, m_home) - , Q_ARG(QString, unit)); -} - -void Vault::exportSnapshot(const QString &snapshot, const QString &dstDir) -{ - QMetaObject::invokeMethod(m_worker, "exportSnapshot" - , Q_ARG(QString, snapshot) - , Q_ARG(QString, dstDir)); -} - -#include "vault.moc" diff --git a/qml/Vault/vault.hpp b/qml/Vault/vault.hpp deleted file mode 100644 index 8fb345d..0000000 --- a/qml/Vault/vault.hpp +++ /dev/null @@ -1,92 +0,0 @@ - -#ifndef QML_VAULT_H -#define QML_VAULT_H - -#include -#include -#include -#include - -class QJSValue; -class Worker; - -class Vault : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString root READ root WRITE setRoot NOTIFY rootChanged) - Q_PROPERTY(QString backupHome READ backupHome WRITE setBackupHome NOTIFY backupHomeChanged) -public: - enum ImportExportAction { - Export, - Import - }; - Q_ENUMS(ImportExportAction); - enum Operation { - Connect, - Backup, - Restore, - RemoveSnapshot, - ExportImportPrepare, - ExportImportExecute, - Data, - Maintenance, - ExportSnapshot - } - Q_ENUMS(Operation); - - enum DataType { - SnapshotUnits - } - Q_ENUMS(DataType); - - explicit Vault(QObject *parent = nullptr); - ~Vault(); - - QString root() const; - QString backupHome() const; - - void setRoot(const QString &root); - void setBackupHome(const QString &home); - - Q_INVOKABLE void connectVault(bool reconnect); - Q_INVOKABLE void startBackup(const QString &message, const QStringList &units); - Q_INVOKABLE void startRestore(const QString &snapshot, const QStringList &units); - Q_INVOKABLE QStringList snapshots() const; - Q_INVOKABLE QVariantMap units() const; - Q_INVOKABLE void resetHead(); - Q_INVOKABLE void removeSnapshot(const QString &name); - Q_INVOKABLE void exportImportPrepare(ImportExportAction action, const QString &path); - Q_INVOKABLE void exportImportExecute(); - Q_INVOKABLE QString notes(const QString &snapshot) const; - - Q_INVOKABLE void registerUnit(const QJSValue &unit, bool global); - Q_INVOKABLE void startGc(); - Q_INVOKABLE void requestData(DataType, QVariantMap const &); - - Q_INVOKABLE void reset(); - Q_INVOKABLE void backupUnit(const QString &unit); - Q_INVOKABLE void tagSnapshot(const QString &message); - - Q_INVOKABLE void restoreUnit(const QString &, const QString &); - Q_INVOKABLE void exportSnapshot(const QString &, const QString &); - -signals: - void rootChanged(); - void backupHomeChanged(); - - void done(Operation operation, const QVariantMap &data); - void progress(Operation operation, const QVariantMap &data); - void error(Operation operation, const QVariantMap &error); - - void data(DataType id, const QVariantMap &context); - -private: - void initWorker(bool reload); - - QThread m_workerThread; - Worker *m_worker; - QString m_home; - QString m_root; -}; - -#endif diff --git a/rpm/vault.spec b/rpm/vault.spec index 25006ed..31f6930 100644 --- a/rpm/vault.spec +++ b/rpm/vault.spec @@ -1,95 +1,48 @@ -%{!?_with_usersession: %{!?_without_usersession: %define _with_usersession --with-usersession}} -%{!?cmake_install: %global cmake_install make install DESTDIR=%{buildroot}} - Summary: Incremental backup/restore framework -Name: vault -Version: 0.1.0 +Name: vault +Version: 1.0.0 Release: 1 -License: LGPLv2 -Group: Development/Libraries -URL: https://git.sailfishos.org/mer-core/vault +License: LGPLv2.1 +Group: Development/Libraries +URL: https://github.com/nemomobile/vault Source0: %{name}-%{version}.tar.bz2 -BuildRequires: cmake >= 2.8 -BuildRequires: pkgconfig(cor) >= 0.1.14 -BuildRequires: pkgconfig(gittin) -BuildRequires: pkgconfig(tut) >= 0.0.3 BuildRequires: pkgconfig(Qt5Core) >= 5.2.0 -BuildRequires: pkgconfig(Qt5Qml) BuildRequires: pkgconfig(qtaround) >= 0.2.3 -%{?_with_usersession:Requires: systemd-user-session-targets} Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig %description Incremental backup/restore framework -%{?_with_usersession:%define _userunitdir %{_libdir}/systemd/user/} - %package devel Summary: vault headers etc. Requires: %{name} = %{version}-%{release} %description devel vault library header files etc. -%package tests -Summary: Tests for vault -Requires: %{name} = %{version}-%{release} -%description tests -%summary - %prep -%setup -q - -%define tools_dir %{_libexecdir}/vault +%setup -q -n %{name}-%{version} %build -%cmake -DVERSION=%{version} %{?_with_multiarch:-DENABLE_MULTIARCH=ON} -DTOOLS_DIR=%{tools_dir} -make %{?jobs:-j%jobs} +%qmake5 "VERSION=%{version}" +make %{?_smp_mflags} %install -rm -rf $RPM_BUILD_ROOT -%cmake_install - -%if 0%{?_with_usersession:1} -install -D -p -m644 tools/vault-gc.service %{buildroot}%{_userunitdir}/vault-gc.service -%endif - -%clean -rm -rf $RPM_BUILD_ROOT +rm -rf %{buildroot} +%qmake5_install %files %defattr(-,root,root,-) -%{_libdir}/libvault-core.so* -%{_libdir}/libvault-transfer.so* -%{_libdir}/libvault-unit.so* -%dir %{_libdir}/qt5/qml/NemoMobile/Vault -%{_libdir}/qt5/qml/NemoMobile/Vault/* -%{_bindir}/vault -%dir %{tools_dir} -%{tools_dir}/* -%if 0%{?_with_usersession:1} -%{_userunitdir}/vault-gc.service -%endif +%{_libdir}/libvault.so* %files devel %defattr(-,root,root,-) -%{_libdir}/pkgconfig/vault-unit.pc +%{_libdir}/pkgconfig/vault.pc %dir %{_includedir}/vault -%{_includedir}/vault/*.hpp - -%files tests -%defattr(-,root,root,-) -%dir /opt/tests/vault -/opt/tests/vault/* +%{_includedir}/vault/*.h %post /sbin/ldconfig || : -%if 0%{?_with_usersession:1} - systemctl-user daemon-reload || : -%endif %postun /sbin/ldconfig || : -%if 0%{?_with_usersession:1} - systemctl-user daemon-reload || : -%endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index 0293fda..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,54 +0,0 @@ -pkg_check_modules(GITTIN gittin REQUIRED) - -include_directories( - ${GITTIN_INCLUDE_DIRS} -) -link_directories( - ${GITTIN_LIBRARY_DIRS} -) - -set(CMAKE_AUTOMOC TRUE) - -configure_file(config.hpp.in ${CMAKE_CURRENT_SOURCE_DIR}/config.hpp @ONLY) - -add_library(vault-core SHARED vault.cpp vault_config.cpp) -qt5_use_modules(vault-core Core) -target_link_libraries(vault-core - ${QTAROUND_LIBRARIES} - ${GITTIN_LIBRARIES} -) -set_target_properties(vault-core PROPERTIES - SOVERSION 0 - VERSION ${VERSION} - ) -install(TARGETS vault-core DESTINATION ${DST_LIB}) - -add_executable(vault-cli vault-cli.cpp) -target_link_libraries(vault-cli vault-core) -set_target_properties(vault-cli PROPERTIES OUTPUT_NAME vault) -install(TARGETS vault-cli DESTINATION bin) - -add_library(vault-unit SHARED unit.cpp) -qt5_use_modules(vault-unit Core) -target_link_libraries(vault-unit - ${COR_LIBRARIES} - ${QTAROUND_LIBRARIES} -) -set_target_properties(vault-unit PROPERTIES - SOVERSION 0 - VERSION ${VERSION} - ) -install(TARGETS vault-unit DESTINATION ${DST_LIB}) - -add_library(vault-transfer SHARED transfer.cpp) -qt5_use_modules(vault-transfer Core) -target_link_libraries(vault-transfer - ${COR_LIBRARIES} - ${QTAROUND_LIBRARIES} - vault-core -) -set_target_properties(vault-transfer PROPERTIES - SOVERSION 0 - VERSION ${VERSION} - ) -install(TARGETS vault-transfer DESTINATION ${DST_LIB}) diff --git a/src/config.hpp.in b/src/config.hpp.in deleted file mode 100644 index 16956c5..0000000 --- a/src/config.hpp.in +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _SRC_VAULT_CONFIG_HPP_ -#define _SRC_VAULT_CONFIG_HPP_ - -#define VAULT_LIBEXEC_PATH "@prefix@/libexec/vault" - -#endif // _SRC_VAULT_CONFIG_HPP_ diff --git a/src/transfer.cpp b/src/transfer.cpp deleted file mode 100644 index 000bd16..0000000 --- a/src/transfer.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/** - * @file transfer.cpp - * @brief API to support storage transfer - * @author Denis Zalevskiy - * @copyright (C) 2014 Jolla Ltd. - * @par License: LGPL 2.1 http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html - */ - -#include "transfer.hpp" - -#include -#include -#include -#include -#include - -#include "QString" -#include "QVariant" -#include "QMap" - -namespace os = qtaround::os; -namespace subprocess = qtaround::subprocess; -namespace error = qtaround::error; -namespace debug = qtaround::debug; -using qtaround::subprocess::Process; - -namespace { - -using vault::File; - - -} - -using debug::Level; - -template -void trace(Level l, Args &&...args) -{ - debug::print_ge(l, "Vault.transfer:", std::forward(args)...); -} - -static inline QString str(CardTransfer::Action a) -{ - std::array names - = {{"export", "import"}}; - return names.at(static_cast(a)); -} - -static QDebug & operator <<(QDebug &d, CardTransfer::Action a) -{ - d << str(a); - return d; -} - -vault::Vault *CardTransfer::getVault() -{ - if (!vault_) - error::raise({{"msg", "Vault should be initialized first"}}); - return vault_; -} - -void CardTransfer::invalidateVault() -{ - vault_ = nullptr; - emit vaultChanged(); -} - -void CardTransfer::init(vault::Vault *v, Action action, QString const &dump_path) -{ - trace(Level::Info, "Prepare", action, dump_path); - vault_ = v; - - if (!hasType(dump_path, QMetaType::QString)) - error::raise({{"reason", "Logic"} - , {"message", "Export/import path is bad"} - , {"path", dump_path}}); - - auto path = os::path::join(dump_path, "Backup.tar"); - auto storage = getVault(); - trace(Level::Info, "Working with", storage->root()); - - QString dst_dir; - if (action == Action::Import) { - if (!os::path::exists(path)) - error::raise({{"reason", "NoSource"} - , {"message", "There is nothing to import"} - , {"path", path}}); - src_ = path; - dst_dir = storage->root(); - dst_ = dst_dir; - if (!os::path::isDir(dst_dir)) - dst_dir = os::path::dirName(dst_dir); - } else if (action == Action::Export) { - if (!os::path::exists(storage->root()) || !storage->ensureValid()) - error::raise({{"reason", "NoSource"}, {"message", "Invalid vault"} - , {"path", storage->root()}}); - src_ = storage->root(); - dst_ = path; - dst_dir = os::path::dirName(path); - } else { - error::raise({{"reason", "Logic"}, {"message", "Unknown action"} - , {"action", str(action)}}); - } - space_free_ = os::diskFree(dst_dir); - action_ = action; - trace(Level::Info, "dst=", dst_dir, "free space=", space_free_); -} - - -Process CardTransfer::doIO(IoCmd const &info) -{ - debug::debug("Io", info); - Process ps; - ps.start(info.get(), info.get()); - auto is_finished = false; - auto dst_size = 0; - auto dtime = 1000; - - auto calculateDTime = [&info, dst_size](double dtime) { - auto dst = info.get(); - auto dtime_now = dtime; - auto dst_size_now = os::du(dst, {{"summarize", true}}).toDouble(); - auto dsize = dst_size_now - dst_size; - info.get()({{"type", "dst_size"} - , {"size", dst_size_now}}); - - if (info.get() > 0 && dsize > 0) { - auto size_fraction = dsize / info.get(); - if (size_fraction > 0.2) { - dtime_now = 1000; - } else if (size_fraction < 0.02) { - dtime_now = 5000; - } else { - dtime_now = 2000; - } - if (dtime_now != dtime) - trace(Level::Debug, "New dT=", dtime); - } - - return std::make_tuple(dtime_now, dst_size_now); - }; - - if (!info.get()) { - ps.wait(-1); - return std::move(ps); - } - - is_finished = ps.wait(dtime); - while (!is_finished) { - std::tie(dtime, dst_size) = calculateDTime(dtime); - is_finished = ps.wait(dtime); - } - return std::move(ps); -} - -void CardTransfer::estimateSpace() -{ - if (!space_required_) { - trace(Level::Info, "Check required space"); - auto is_src_dir = os::path::isDir(src_); - // if source is directory - it is .vault, so only .git is packed - auto real_src = is_src_dir ? os::path::join(src_, ".git") : src_; - space_required_ = get(os::du(real_src, {{"summarize", is_src_dir}})); - trace(Level::Info, "Need", space_required_, "kb"); - if (!is_src_dir) { - // empiric multiplier: unpacked - // files can take more space, - // it depends on fs - space_required_ *= 1.2; - } - if (os::path::exists(dst_)) { - auto to_be_freed = get - (os::du(dst_, {{"summarize", !is_src_dir}})); - space_free_ += to_be_freed; - } - trace(Level::Info, "total required=", space_required_ - , "free=", space_free_); - } - if (space_required_ > space_free_) - error::raise({{"reason", "NoSpace"}, {"free", space_free_} - , {"required", space_required_}}); -} - -void CardTransfer::validateDump(QString const &archive, QVariantMap const &err) -{ - trace(Level::Info, "Validate dump", archive); - QString prefix(".git/"); - auto prefix_len = prefix.size(); - auto tag_fname = vault::fileName(File::State); - auto tag_len = tag_fname.size(); - auto is_full_dump = false; - - auto out = str(subprocess::check_output - ("tar", {{"-tf", archive}}, {{"reason", "Archive"}})); - auto lines = filterEmpty(out.split("\n")); - for (auto it = lines.begin(); it != lines.end(); ++it) { - auto const &fname = *it; - if (fname.left(prefix_len) != prefix) { - if (fname.left(tag_len) != tag_fname) { - error::raise(err, map({{"msg", "Unexpected file name"} - , {"fname", fname}, {"dump", archive}})); - } - is_full_dump = true; - } - } - if (!is_full_dump) - error::raise(err, map({{"message", "No tag file found"} - , {"dump", archive}})); -} - -void CardTransfer::exportStorage(CardTransfer::progressCallback onProgress) -{ - auto v = getVault(); - auto l = v ? v->lock() : nullptr; - auto tag_fname = vault::fileName(File::State); - QStringList options = {"-cf", dst_, "-C", src_, ".git", tag_fname}; - onProgress({{"type", "stage"}, {"stage", "Copy"}}); - try { - IoCmd cmd("tar", options, onProgress, space_required_, dst_); - auto ps = doIO(cmd); - ps.check_error({{"reason", "Export"}}); - - onProgress({{"type", "stage"}, {"stage", "Flush"}}); - subprocess::check_call("sync", {}, {{"reason", "Export"}}); - - onProgress({{"type", "stage"}, {"stage", "Validate"}}); - validateDump(dst_, {{"reason", "Export"}}); - - } catch (...) { - if (os::path::exists(dst_)) - os::rm(dst_); - throw; - } -} - -void CardTransfer::importStorage(CardTransfer::progressCallback onProgress) -{ - auto root = getVault()->root(); - if (dst_ != root) - error::raise({{"reason", "Logic"}, {"message", "Invalid destination"} - , {"path", dst_}}); - - if (os::path::exists(root) && !getVault()->ensureValid()) - error::raise({{"reason", "Logic"}, {"message", "Invalid vault"} - , {"path", root}}); - - onProgress({{"type", "stage"}, {"stage", "Validate"}}); - validateDump(src_, {{"reason", "BadSource"}}); - trace(Level::Info, "Clean destination tree"); - os::rmtree(dst_); - invalidateVault(); - if (os::path::exists(dst_)) - error::raise({{"reason", "unknown"}, {"message", "Can't remove destination"} - , {"dst", dst_}}); - - try { - os::mkdir(dst_); - QStringList options = {"-xpf", src_, "-C", dst_}; - onProgress({{"type", "stage"}, {"stage", "Copy"}}); - IoCmd cmd("tar", options, onProgress, space_required_, dst_); - auto res = doIO(cmd); - res.check_error({{"reason", "Archive"}}); - } catch(...) { - if (os::path::exists(dst_)) - os::rmtree(dst_); - throw; - } -} - -void CardTransfer::execute(CardTransfer::progressCallback onProgress) -{ - trace(Level::Info, "Export/import", "action", str(action_)); - - if (!os::path::exists(src_)) - error::raise({{"reason", "Logic"} - , {"message", "Source does not exist"} - , {"src", src_}}); - - estimateSpace(); - onProgress({{"type", "estimated_size"}, {"size", space_required_}}); - - switch (action_) { - case Action::Export: - exportStorage(onProgress); - break; - case Action::Import: - importStorage(onProgress); - break; - default: - error::raise({{"reason", "Logic"}, {"message", "Unknown action"} - , {"action", str(action_)}}); - break; - } -} diff --git a/src/transfer.hpp b/src/transfer.hpp deleted file mode 100644 index 44805f1..0000000 --- a/src/transfer.hpp +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef _VAULT_TRANSFER_HPP_ -#define _VAULT_TRANSFER_HPP_ -/** - * @file transfer.hpp - * @brief API to support storage transfer - * @author Denis Zalevskiy - * @copyright (C) 2014 Jolla Ltd. - * @par License: LGPL 2.1 http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html - */ - -#include -#include - -#include -#include -#include - -enum class Io { Exec, Options, OnProgress, EstSize, Dst, EOE }; -template <> struct StructTraits -{ - typedef std::tuple - , long, QString> type; - - STRUCT_NAMES(Io, "Exec", "Options", "OnProgress", "EstSize", "Dst"); -}; - -typedef Struct IoCmd; - -namespace vault { class Vault; } - -class CardTransfer : public QObject -{ - Q_OBJECT - Q_ENUMS(Actions) - Q_PROPERTY(QString src READ getSrc); - Q_PROPERTY(QString dst READ getDst); - Q_PROPERTY(Action action READ getAction); - Q_PROPERTY(double spaceFree READ getSpace); - Q_PROPERTY(double spaceRequired READ getRequired); - -public: - enum Action { Export, Import, ActionsEnd }; - - CardTransfer() - : vault_(nullptr) - , action_(ActionsEnd) - , space_free_(0) - , space_required_(0) - {} - - typedef std::function progressCallback; - void init(vault::Vault *, Action, QString const &); - void execute(progressCallback); - - inline QString getSrc() const { return src_; } - inline QString getDst() const { return dst_; } - inline Action getAction() const { return action_; } - inline double getSpace() const { return space_free_; } - inline double getRequired() const { return space_required_; } - -signals: - void vaultChanged(); -private: - static qtaround::subprocess::Process doIO(IoCmd const &info); - static void validateDump(QString const &archive, QVariantMap const &err); - void estimateSpace(); - void exportStorage(progressCallback); - void importStorage(progressCallback); - - vault::Vault *getVault(); - void invalidateVault(); - - vault::Vault *vault_; - Action action_; - QString src_; - QString dst_; - double space_free_; - double space_required_; -}; - -#endif // _VAULT_TRANSFER_HPP_ diff --git a/src/vault-cli.cpp b/src/vault-cli.cpp deleted file mode 100644 index 61170b9..0000000 --- a/src/vault-cli.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @file vault-cli.cpp - * @brief Vault command line tool - * @author Giulio Camuffo - * @copyright (C) 2014 Jolla Ltd. - * @par License: LGPL 2.1 http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html - */ - -#include -#include -#include - -#include -#include - -namespace debug = qtaround::debug; - -void set(QVariantMap &map, const QCommandLineParser &parser, const QString &option, bool optional = false) -{ - if (!optional || parser.isSet(option)) { - map.insert(option, parser.value(option)); - } -} - -int main_(int argc, char **argv) -{ - QCoreApplication app(argc, argv); - QCommandLineParser parser; - parser.setApplicationDescription("The Vault"); - parser.addHelpOption(); - - parser.addOption(QCommandLineOption(QStringList() << "a" << "action", "action", "action")); - parser.addOption(QCommandLineOption(QStringList() << "V" << "vault", "vault", "path")); - parser.addOption(QCommandLineOption(QStringList() << "H" << "home", "home", "home")); - parser.addOption(QCommandLineOption(QStringList() << "G" << "global", "global")); - parser.addOption(QCommandLineOption(QStringList() << "d" << "data", "data", "data")); - parser.addOption(QCommandLineOption(QStringList() << "M" << "unit", "unit", "unit")); - parser.addOption(QCommandLineOption(QStringList() << "c" << "config-path", "config-path", "config-path", "/etc/the-vault.json")); - parser.addOption(QCommandLineOption(QStringList() << "g" << "git-config", "git-config", "git-config")); - parser.addOption(QCommandLineOption(QStringList() << "m" << "message", "message", "message")); - parser.addOption(QCommandLineOption(QStringList() << "t" << "tag", "tag", "tag")); - - parser.process(app); - - QVariantMap options; - set(options, parser, "action"); - set(options, parser, "vault", true); - set(options, parser, "home", true); - set(options, parser, "data", true); - set(options, parser, "unit", true); - set(options, parser, "config-path", true); - set(options, parser, "git-config", true); - set(options, parser, "message", true); - set(options, parser, "tag", true); - - options.insert("global", parser.isSet("global")); - - return vault::Vault::execute(options); -} - -int main(int argc, char **argv) -{ - int res = 1; - try { - res = main_(argc, argv); - } catch (std::exception const &e) { - debug::error("Error:", e.what()); - } catch (...) { - debug::error("Unknown error"); - } - return res; -} diff --git a/src/vault.cpp b/src/vault.cpp deleted file mode 100644 index ff243d1..0000000 --- a/src/vault.cpp +++ /dev/null @@ -1,972 +0,0 @@ -/** - * @file vault.cpp - * @brief Vault management API - * @author Giulio Camuffo - * @copyright (C) 2014 Jolla Ltd. - * @par License: LGPL 2.1 http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html - */ - -#include "config.hpp" -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -namespace os = qtaround::os; -namespace subprocess = qtaround::subprocess; -namespace error = qtaround::error; -namespace debug = qtaround::debug; - -namespace vault { - -static const QMap fileNames = { - {File::Message, ".message"} - , {File::VersionTree, ".vault"} - , {File::VersionRepo, os::path::join(".git", "vault.version")} - , {File::State, ".vault.state"} - , {File::Lock, ".vault.lock"} -}; - -QString fileName(File id) -{ - return fileNames[id]; -}; - -using Gittin::CleanOptions; -using Gittin::ResetOptions; -using Gittin::CheckoutOptions; - -namespace version { - static const int tree = 3; - static const int repository = 2; -} - -Snapshot::Snapshot(const Gittin::Tag &tag) - : m_tag(tag) -{ -} - -Snapshot::Snapshot(Gittin::Repo *repo, const QString &name) - : m_tag(repo, QString(">") + name) -{ -} - -QString Snapshot::name() const -{ - return m_tag.name().mid(1); -} - -void Snapshot::remove() -{ - m_tag.destroy(); -} - -Vault::Vault(const QString &path) - : m_path(path) - , m_blobStorage(os::path::join(path, ".git", "blobs")) - , m_vcs(path) - , m_config(&m_vcs) -{ - setup(nullptr); -} - -static QVariantMap parseKvPairs(const QString &cfg) -{ - QVariantMap data; - for (const QString v: cfg.split(',')) { - QStringList kv = v.split('='); - if (kv.size() == 2 && !kv.at(0).isEmpty()) { - data[kv.at(0)] = kv.at(1); - } - } - return data; -} - -config::Vault Vault::config() -{ - return config::Vault(&m_vcs); -} - -Vault::UnitPath Vault::unitPath(const QString &name) const -{ - UnitPath res; - res.path = os::path::join(m_vcs.path(), name); - res.bin = os::path::join(res.path, "blobs"); - res.data = os::path::join(res.path, "data"); - return res; -}; - -bool Vault::UnitPath::exists() const -{ - return os::path::isDir(path); -} - -template -std::tuple executeIn -(QString const &dir, QString const &vaultUtilName, Args && ... args) -{ - auto p = subprocess::Process(); - p.setWorkingDirectory(dir); - p.start(os::path::join(VAULT_LIBEXEC_PATH, vaultUtilName) - , {std::forward(args)...}); - p.wait(-1); - return std::make_tuple(p.rc(), p.stdout(), p.stderr()); -} - -int Vault::execute(const QVariantMap &options) -{ - debug::debug("Executing", options); - QString action = options.value("action").toString(); - if (options.value("global").toBool()) { - debug::debug("Global action"); - if (action == "register") { - if (!options.contains("data")) { - error::raise({{"action", action}, {"msg", "Needs data" }}); - } - - QString cfg = options.value("data").toString(); - QVariantMap data = parseKvPairs(cfg); - if (options.contains("unit")) { - data["name"] = options.value("unit"); - } - config::global()->set(data); - } else if (action == "unregister") { - if (!options.contains("unit")) { - error::raise({{"action", action}, {"msg", "Needs unit name"}}); - } - - config::global()->rm(options.value("unit").toString()); - } else { - error::raise({{"msg", "Unknown action"}, {"action", action}}); - } - return 0; - } - - if (!options.contains("vault")) { - error::raise({{"msg", "Missing option"}, {"name", "vault"}}); - } - - Vault vault(options.value("vault").toString()); - auto l = vault.lock(); - QStringList units{str(options.value("unit")).split(",", QString::SkipEmptyParts)}; - - auto unitsResult = [](Result &&res) { - debug::info("Succeeded units:", res.succededUnits.join(",")); - auto failedCount = res.failedUnits.size(); - if (failedCount) - debug::warning("Failed units:", res.failedUnits.join(",")); - - return failedCount; - }; - - if (action == "init") { - vault.init(parseKvPairs(options.value("git-config").toString())); - } else if (action == "export" || action == "backup") { - return unitsResult(vault.backup - (options.value("home").toString(), units - , options.value("message").toString())); - } else if (action == "import" || action == "restore") { - if (!options.contains("tag")) { - error::raise({{"msg", "tag should be provided to restore"}}); - } - return unitsResult(vault.restore - (vault.snapshot(options.value("tag").toByteArray()) - , options.value("home").toString(), units)); - } else if (action == "list-snapshots") { - auto snapshots = vault.snapshots(); - QTextStream cout{stdout}; - for (const Snapshot &s: snapshots) { - cout << s.tag().name() << '\n'; - } - } else if (action == "register") { - if (!options.contains("data")) { - error::raise({{"action", action}, {"msg", "Needs data"}}); - } - auto data = parseKvPairs(str(options["data"])); - if (options.contains("unit")) - data["unit"] = options["unit"]; - data["local"] = true; - debug::info("Register local unit:", data); - vault.registerConfig(data); - } else if (action == "unregister") { - if (!options.contains("unit")) { - error::raise({{"action", action}, {"msg", "Needs unit name"}}); - } - vault.unregisterUnit(options.value("unit").toString()); - } else if (action == "gc") { - auto res = executeIn(vault.root(), "git-vault-gc"); - QTextStream out(stdout, QIODevice::WriteOnly); - QTextStream err(stderr, QIODevice::WriteOnly); - out << std::get<1>(res) << endl; - err << std::get<2>(res) << endl; - return std::get<0>(res); - } else { - error::raise({{"msg", "Unknown action"}, {"action", action}}); - } - return 0; -} - -void Vault::registerConfig(const QVariantMap &config) -{ - m_vcs.checkout("master", Gittin::CheckoutOptions::Force); - reset("master"); - m_config.set(config); -} - -void Vault::unregisterUnit(const QString &unit) -{ - m_vcs.checkout("master", Gittin::CheckoutOptions::Force); - reset("master"); - m_config.rm(unit); -} - -void Vault::setVersion(File dst, int ver) -{ - auto fname = fileName(dst); - if (!writeFile(fname, str(ver))) - error::raise({{"msg", "Can't save version"}, {"path", fname}}); -} - -QString Vault::readFile(const QString &relPath) -{ - return QString::fromUtf8(os::read_file(os::path::join(m_path, relPath))); -} - -int Vault::getVersion(File src) -{ - return readFile(fileName(src)).toInt(); -} - -QString Vault::absolutePath(QString const &relativePath) const -{ - return os::path::join(m_path, relativePath); -} - -void Vault::setup(const QVariantMap *config) -{ - debug::debug("Setup vault", config ? *config : QVariantMap{}); - auto l = lock(); - auto createRepo = [this, &l]() { - debug::debug("Creating repo at", m_path); - if (!os::path::exists(m_path)) - if (!os::mkdir(m_path)) - error::raise({{"msg", "Can't create repo dir"}, {"path", m_path}}); - - l = lock(); - if (!m_vcs.init()) - error::raise({{"msg", "Can't init git repo"}, {"path", m_path}}); - }; - - auto setupGitConfig = [this, config]() { - debug::debug("Setup git config", *config); - m_vcs.setConfigValue("status.showUntrackedFiles", "all"); - for (auto it = config->begin(); it != config->end(); ++it) - m_vcs.setConfigValue(it.key(), it.value().toString()); - }; - - auto excludeServiceFiles = [this]() { - auto path = ".git/info/exclude"; - if (!writeFile(path, ".vault.*\n.units/")) - error::raise({{"msg", "Can't write exclude info"}, {"path", path}}); - }; - - auto initVersions = [this]() { - debug::debug("Init vault versions"); - setVersion(File::VersionTree, version::tree); - m_vcs.add(fileName(File::VersionTree)); - m_vcs.commit("anchor"); - m_vcs.tag("anchor"); - - if (!os::path::exists(m_blobStorage)) - if (!os::mkdir(m_blobStorage)) - error::raise({{"msg", "Can't create blob storage"}, - {"path", m_blobStorage}}); - - setVersion(File::VersionRepo, version::repository); - }; - - auto updateTreeVersion = [this](unsigned current) { - debug::info("Updating tree version from", current, "to", version::tree); - - if (current < 2) { - debug::info("since v2 there is no 'latest' tag"); - snapshot("latest").remove(); - } - - if (current < 3) { - debug::info("Since v3 information about units is not " - "under version control and moved to the .units dir." - "Old .modules is deprecated."); - } - - setVersion(File::VersionTree, version::tree); - m_vcs.add(fileName(File::VersionTree)); - m_vcs.commit("vault format version"); - }; - - auto updateRepoVersion = [this, &excludeServiceFiles](unsigned current) { - debug::info("Updating repo version from", current, "to", version::repository); - if (current < 1) { - // state tracking file is appeared in version 1 - // all .vault.* are also going to be ignored - excludeServiceFiles(); - } - setVersion(File::VersionRepo, version::repository); - }; - - auto syncConfigGlobal = [this]() { - auto global = vault::config::global(); - if (global) - this->config().update(global->units()); - }; - - if (exists() && !isInvalid()) { - debug::debug("Repository exists and it is not invalid, setup"); - - auto v = getVersion(File::VersionTree); - if (v < version::tree) - updateTreeVersion(v); - - v = getVersion(File::VersionRepo); - if (v < version::repository) - updateRepoVersion(v); - - excludeServiceFiles(); - setState("new"); - if (config) - setupGitConfig(); - - syncConfigGlobal(); - } else if (config) { - debug::info("Repository initialization is requested"); - - if (os::path::exists(m_path)) { - QDir d(m_path); - if (!d.entryList(QDir::NoDotAndDotDot).isEmpty()) - error::raise({ - {"msg", "Vault dir already exists and not empty"} - , {"path", m_path}}); - } - - try { - createRepo(); - setupGitConfig(); - excludeServiceFiles(); - initVersions(); - syncConfigGlobal(); - setState("new"); - } catch (...) { - os::rmtree(m_path); - throw; - } - } -} - -bool Vault::init(const QVariantMap &config) -{ - try { - auto l = lock(); - setup(&config); - return true; - } catch (std::exception const &e) { - debug::error("Error:", e.what(), ", initializing repository", m_path); - } catch (...) { - debug::error("Unknown error initializing repository", m_path); - } - return false; -} - -bool Vault::ensureValid() -{ - auto l = lock(); - if (!os::path::exists(absolutePath(".git"))) { - debug::info("Can't find .git", m_path); - return false; - } - if (!os::path::exists(m_blobStorage)) { - debug::info("Can't find blobs storage", m_blobStorage); - return false; - } - - auto versionTreeFile = absolutePath(fileName(File::VersionTree)); - if (!os::path::isFile(versionTreeFile)) { - resetMaster(); - if (!os::path::isFile(versionTreeFile)) { - debug::info("Can't find .vault anchor in ", m_path); - return false; - } - } - return true; -} - -Vault::Result Vault::backup(const QString &home, const QStringList &units, const QString &message, const ProgressCallback &callback) -{ - debug::info("Backup units", units, ", home", home); - auto l = lock(); - Result res; - - if (!os::path::isDir(home)) { - qWarning("Home is not a dir: %s", qPrintable(home)); - return std::move(res); - } - - ProgressCallback progress = callback ? callback : [](const QString &name, const QString &status) { - qDebug() << "Progress" << name << status; - }; - - resetLastSnapshot(); - Gittin::Commit head = Gittin::Branch(&m_vcs, "master").head(); - - QStringList usedUnits = units; - if (units.isEmpty()) { - debug::info("Units list is not supplied, backup all units"); - QMap units = config().units(); - for (auto i = units.begin(); i != units.end(); ++i) { - usedUnits << i.key(); - } - } - for (const QString &unit: usedUnits) { - if (backupUnit(home, unit, progress)) { - res.succededUnits << unit; - } else { - res.failedUnits << unit; - break; - } - } - - if (res.succededUnits.size() == usedUnits.size()) { - tagSnapshot(message); - } else { - debug::warning("Some unit backup is failed, no tag"); - reset(head.sha()); - } - return res; -} - -/// \return snapshot tag name -QString Vault::tagSnapshot(const QString &message) -{ - static const QString timeFormat{"yyyy-MM-ddTHH-mm-ss.zzzZ"}; - - auto l = lock(); - // TODO error checking - m_vcs.checkout("master"); - - auto timeTag = QDateTime::currentDateTimeUtc().toString(timeFormat); - debug::info("Tag", timeTag, message); - auto metadata = message.isEmpty() ? timeTag : message + '\n' + timeTag; - writeFile(fileName(File::Message), metadata); - m_vcs.add(fileName(File::Message)); - Gittin::Commit commit = m_vcs.commit(metadata); - // message can be theoretically updated later and it should not - // change commit id, so add it as a not. Initial message is saved - // in the commit and message file - commit.addNote(message); - - Snapshot snapshot{&m_vcs, timeTag}; - auto tagName = snapshot.tag().name(); - m_vcs.tag(tagName); - return tagName; -} - -bool Vault::clear(const QVariantMap &options) -{ - auto l = lock(); - if (!os::path::isDir(m_path)) { - debug::info("vault.clear:", "Path", m_path, "is not a dir"); - return false; - } - - auto destroy = [this]() { - return !os::rmtree(m_path) && !os::path::exists(m_path); - }; - - if (isInvalid()) { - if (!options.value("clear_invalid").toBool()) { - debug::info("vault.clear:", "Can't clean invalid vault implicitely"); - return false; - } - if (options.value("destroy").toBool()) { - debug::info("vault.clear:", "Destroying invalid vault at", m_path); - return destroy(); - } - } - if (options.value("destroy").toBool()) { - if (!options.value("ignore_snapshots").toBool() && snapshots().size()) { - debug::info("vault.clear:", "Can't ignore snapshots", m_path); - return false; - } - debug::info("vault.clear:", "Destroying vault storage at", m_path); - return destroy(); - } - return false; -} - -void Vault::reset(const QByteArray &treeish) -{ - auto l = lock(); - m_vcs.clean(CleanOptions::Force | CleanOptions::RemoveDirectories); - if (!treeish.isEmpty()) { - m_vcs.reset(ResetOptions::Hard, treeish); - } else { - m_vcs.reset(ResetOptions::Hard); - } -} - -void Vault::resetMaster() -{ - reset(); - m_vcs.checkout("master", CheckoutOptions::Force); -} - -/** - * Reset master branch to the last snapshot commit - * - * This action should be done before doing backup to avoid inclusion - * of any traces/remnants of previous backup tryouts - */ -void Vault::resetLastSnapshot() -{ - auto l = lock(); - resetMaster(); - - QString lastSnapshot = "anchor"; - auto snaps = snapshots(); - if (!snaps.isEmpty()) - lastSnapshot = snaps.back().tag().name(); - - m_vcs.reset(ResetOptions::Hard, lastSnapshot); -} - -Vault::Result Vault::restore(const QString &snapshot, const QString &home, const QStringList &units, const ProgressCallback &callback) -{ - auto l = lock(); - Snapshot ss(&m_vcs, snapshot); - return restore(ss, home, units, callback); -} - -Vault::Result Vault::restore(const Snapshot &snapshot, const QString &home, const QStringList &units, const ProgressCallback &callback) -{ - auto l = lock(); - debug::info("Restore units", units, ", home", home); - Result res; - res.failedUnits << units; - - if (!os::path::isDir(home)) { - qWarning("Home is not a dir: %s", qPrintable(home)); - return res; - } - - ProgressCallback progress = callback ? callback : [](const QString &name, const QString &status) { - qDebug() << "Progress" << name << status; - }; - - m_vcs.checkout(snapshot.tag()); - QStringList usedUnits = units; - if (units.isEmpty()) { - QMap units = config().units(); - for (auto i = units.begin(); i != units.end(); ++i) { - usedUnits << i.key(); - } - } - - debug::debug("Restore units:", usedUnits); - for (const QString &unit: usedUnits) { - if (restoreUnit(home, unit, progress)) { - res.failedUnits.removeOne(unit); - res.succededUnits << unit; - } - } - - m_vcs.checkout("master"); - return res; -} - -void Vault::checkout(const QString &snapshotName) -{ - auto name = snapshotName.startsWith('>') - ? snapshotName - : '>' + snapshotName; - Snapshot snapshot(&m_vcs, name); - m_vcs.checkout(snapshot.tag(), CheckoutOptions::Force); -} - -QList Vault::snapshots() const -{ - auto l = lock(); - auto tags = m_vcs.tags(); - QList list; - for (const Gittin::Tag &tag: tags) { - if (!tag.name().isEmpty() && tag.name().startsWith('>')) { - list << Snapshot(tag); - } - } - return list; -} - -Snapshot Vault::snapshot(const QByteArray &tagName) const -{ - auto l = lock(); - auto tags = m_vcs.tags(); - for (const Gittin::Tag &tag: tags) { - if (tag.name() == tagName) { - return Snapshot(tag); - } - } - error::raise({{"msg", "Wrong snapshot tag"}, {"tag", tagName}}); - return Snapshot(m_vcs.tags().first()); -} - -QString Vault::notes(const QString &snapshot) -{ - auto l = lock(); - Gittin::Tag tag(&m_vcs, snapshot); - return tag.notes(); -} - -QList Vault::units(QString const & snapshotName) const -{ - auto l = lock(); - QList result; - auto res = executeIn(root(), "git-vault-snapshot-units", snapshotName); - if (!std::get<0>(res)) { - auto data = str(std::get<1>(res)); - result = data.split("\n", QString::SkipEmptyParts); - } else { - QTextStream err(stderr, QIODevice::WriteOnly); - err << "Error while running git-vault-snapshot-units\n"; - err << std::get<1>(res); - err << std::get<2>(res); - } - return result; -} - -bool Vault::exists() const -{ - return os::path::isDir(m_path); -} - -bool Vault::isInvalid() -{ - QString storage(absolutePath(".git")); - QString blob_storage(os::path::join(storage, "blobs")); - if (!os::path::exists(storage) || !os::path::exists(blob_storage)) { - return true; - } - - QString anchor(absolutePath(fileName(File::VersionTree))); - if (!os::path::isFile(anchor)) { - resetMaster(); - if (!os::path::isFile(anchor)) - return true; - } - return false; -}; - -bool Vault::writeFile(const QString &path, const QString &content) -{ - QFile file(absolutePath(path)); - if (!content.endsWith('\n')) { - return os::write_file(absolutePath(path), content + '\n'); - } - return os::write_file(absolutePath(path), content); -} - -bool Vault::setState(const QString &state) -{ - return writeFile(fileName(File::State), state); -} - -// TODO move to the library -Gittin::Commit commitEvenIfClean(Gittin::Repo &vcs, QString const &msg) -{ - auto options = QStringList() << "--allow-empty" << "-m" << msg; - vcs.command("commit", options); - auto log_opts = QStringList() << "-n1" << "--oneline" << "--no-abbrev-commit"; - auto commit = vcs.command("log", log_opts)->stdout(); - // TODO: FIX: object takes unsafe pointer to another object - return Gittin::Commit(&vcs, commit.split(' ').first()); -} - -struct Unit -{ - Unit(const QString &unit, const QString &home - , Gittin::Repo *vcs, const config::Unit &config); - - void execScript(const QString &action); - void linkBlob(const QString &file); - void backup(); - void restore(); - - QString m_home; - QString m_unit; - QDir m_root; - Gittin::Repo *m_vcs; - QString m_blobs; - QString m_data; - config::Unit m_config; -}; - -/// \return (unit, isOk, reason) -std::tuple Vault::backupUnit -(const QString &home, const QString &unit) -{ - auto l = lock(); - QString reason; - auto onDone = [&reason](const QString &, const QString &result) { - reason = result; - }; - // TODO error check - m_vcs.checkout("master"); - auto isOk = backupUnit(home, unit, onDone); - return std::make_tuple(unit, isOk, reason); -} - -bool Vault::backupUnit(const QString &home, const QString &unit, const ProgressCallback &callback) -{ - Gittin::Commit head = Gittin::Branch(&m_vcs, "master").head(); - - try { - debug::info("Backup unit", unit); - if (unit.isEmpty()) - error::raise({{"msg", "Trying to backup unit w/o name"}}); - - callback(unit, "begin"); - Unit u(unit, home, &m_vcs, config().units().value(unit)); - u.backup(); - callback(unit, "ok"); - } catch (error::Error const &err) { - debug::error("Unit backup error:", err.m); - callback(unit, str(err.m.value("reason", "fail"))); - m_vcs.clean(CleanOptions::Force | CleanOptions::RemoveDirectories | CleanOptions::IgnoreIgnores, unit); - m_vcs.reset(ResetOptions::Hard, head.sha()); - return false; - } - - return true; -} - -/// \return (unit, isOk, reason) -std::tuple Vault::restoreUnit -(const QString &snapshot, const QString &home, const QString &unit) -{ - auto l = lock(); - QString reason; - auto onDone = [&reason](const QString &, const QString &result) { - reason = result; - }; - // TODO error check - checkout(snapshot); - auto isOk = restoreUnit(home, unit, onDone); - return std::make_tuple(unit, isOk, reason); -} - -bool Vault::restoreUnit(const QString &home, const QString &unit, const ProgressCallback &callback) -{ - try { - debug::info("Restore unit", unit); - if (unit.isEmpty()) - error::raise({{"msg", "Trying to restore unit w/o name"}}); - - callback(unit, "begin"); - Unit u(unit, home, &m_vcs, config().units().value(unit)); - u.restore(); - callback(unit, "ok"); - } catch (error::Error err) { - debug::error(err.what(), "\n"); - callback(unit, err.m.contains("reason") ? err.m.value("reason").toString() : "fail"); - return false; - } - - return true; -} - -std::tuple -Vault::exportSnapshot(const QString &snapshot, const QString &dstDir) -{ - debug::debug("Export snapshot", snapshot, "to", dstDir); - auto l = lock(); - auto snapshotName = snapshot; - if (snapshotName[0] != '>') - snapshotName = QString(">") + snapshot; - - return executeIn(root(), "git-vault-export", snapshotName, dstDir); -} - -/** - * \note thread-unsafe - */ -Lock Vault::lock() const -{ - if (!exists()) - return Lock{}; - auto handle = m_barrier.lock(); - if (!handle) { - int timeout = 1 * 1000; - auto lock_fname = absolutePath(fileName(File::Lock)); - auto gotLock = [&handle](os::FileLock l) { handle = box(std::move(l)); }; - auto locker = os::tryLock(lock_fname, gotLock, timeout); - while (locker) { - // max 8s timeout - if (timeout <= 4 * 1000) - timeout *= 2; - locker = os::tryLock(std::move(locker), gotLock, timeout); - } - m_barrier = handle; - } - return handle; -} - - -Unit::Unit(const QString &unit, const QString &home - , Gittin::Repo *vcs, const config::Unit &config) - : m_home(home) - , m_unit(unit) - , m_root(QDir(os::path::join(vcs->path(), unit))) - , m_vcs(vcs) - , m_config(config) -{ - m_blobs = os::path::join(m_root.absolutePath(), "blobs"); - m_data = os::path::join(m_root.absolutePath(), "data"); -} - -void Unit::execScript(const QString &action) -{ - QString script = m_config.script(); - debug::info("SCRIPT>>>", script, "action", action); - if (!QFileInfo(script).isExecutable()) { - error::raise({{"msg", "Should be executable"}, {"script", script}}); - } - QStringList args = { "--action", action, - "--dir", QDir(m_data).absolutePath(), - "--bin-dir", QDir(m_blobs).absolutePath(), - "--home-dir", m_home }; - - subprocess::Process ps; - ps.start(script, args); - ps.wait(-1); - - debug::Level level = ps.rc() ? debug::Level::Error : debug::Level::Info; - - debug::print_ge(level, "RC", ps.rc()); - debug::print_ge(level, "STDOUT", ps.stdout()); - debug::print_ge(level, "<path(), ".git", "blobs"); - QByteArray sha = m_vcs->hashObject(file); - if (sha.length() != sha1HashLength) - error::raise({{"msg", "Can't hash object"}, - {"file", file}, {"hash", str(sha)}}); - - QString blobDir = os::path::join(blobStorage, sha.left(2)); - QString blobFName = os::path::join(blobDir, sha.mid(2)); - QString linkFName = os::path::join(m_vcs->path(), file); - - if (!os::path::exists(blobDir)) { - os::mkdir(blobDir); - } - - QDateTime origTime = os::lastModified(linkFName); - if (os::path::isFile(blobFName)) { - os::unlink(linkFName); - } else { - os::rename(linkFName, blobFName); - } - os::setLastModified(blobFName, origTime); - QString target = os::path::relative(blobFName, os::path::dirName(linkFName)); - os::symlink(target, linkFName); - if (!os::path::isSymLink(linkFName) && os::path::isFile(blobFName)) { - error::raise({{"msg", "Blob should be symlinked"}, - {"link", linkFName}, {"target", target}}); - } - m_vcs->add(file); -} - -void Unit::backup() -{ - QString name = m_config.name(); - - // cleanup directories for data and blobs in - // the repository - os::rmtree(m_blobs); - os::rmtree(m_data); - os::mkdir(m_root.absolutePath()); - os::mkdir(m_blobs); - os::mkdir(m_data); - - execScript("export"); - - Gittin::RepoStatus status = m_vcs->status(os::path::join(m_root.path(), "blobs")); - for (const Gittin::RepoStatus::File &file: status.files()) { - if (file.index == ' ' && file.workTree == 'D') { - m_vcs->rm(file.file); - continue; - } - - QString fname = QFileInfo(file.file).fileName(); - QString prefix = config::prefix; - if (fname.length() >= prefix.length() && fname.startsWith(prefix)) { - m_vcs->add(file.file); - continue; - } - - linkBlob(file.file); - } - - if (m_vcs->status(m_root.path()).isClean()) { - debug::info("No changes for the unit ", name); - // but still commit to track user's intention to backup unit - } else { - // add all only in data dir to avoid blobs to get into git - // objects storage - m_vcs->add(os::path::join(m_root.path(), "data"), Gittin::AddOptions::All); - status = m_vcs->status(m_root.path()); - if (status.hasDirtyFiles()) { - error::raise({{"msg", "Dirty tree"}, {"dir", m_root.path()}/*, {"status", status_dump(status)}*/}); - } - } - commitEvenIfClean(*m_vcs, Snapshot(m_vcs, name).tag().name()); - status = m_vcs->status(m_root.path()); - if (!status.isClean()) { - error::raise({{"msg", "Not fully commited"}, {"dir", m_root.path()}/*, {"status", status_dump(status)}*/}); - } -} - -void Unit::restore() -{ - if (!m_root.exists()) { - error::raise({{"reason", "absent"}, {"name", m_unit}}); - } - execScript("import"); -} - - -} diff --git a/src/vault_config.cpp b/src/vault_config.cpp deleted file mode 100644 index 0803d1b..0000000 --- a/src/vault_config.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/** - * @file config.cpp - * @brief Vault configuration - * @author Giulio Camuffo - * @copyright (C) 2014 Jolla Ltd. - * @par License: LGPL 2.1 http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html - */ - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace os = qtaround::os; -namespace error = qtaround::error; -namespace json = qtaround::json; -namespace debug = qtaround::debug; - -namespace vault { namespace config { - -Unit::Unit() -{ - -} - -Unit::Unit(const QVariantMap &data) - : m_data(data) -{ - m_data["is_unit_config"] = true; - if (!data.isEmpty()) { - update(data); - } -} - -Unit &Unit::read(const QString &fname) -{ - update(json::read(fname).toVariantMap()); - return *this; -} - -ssize_t Unit::write(const QString &fname) -{ - return json::write(m_data, fname); -} - -bool Unit::update(const QVariantMap &data) -{ - QVariantMap src = data; - bool updated = false; - if (!src.value("is_unit_config").toBool()) { - if (!src.contains("name") || !src.contains("script")) { - error::raise({{"msg", "Unit description should contain name and script"}}); - } - auto script = str(src["script"]); - auto script_path = os::path::canonical(script); - if (!script_path.isEmpty()) { - debug::debug("Full script path:", script_path); - script = script_path; - } - debug::info("Script:", script); - src["script"] = script; - } - for (auto i = src.begin(); i != src.end(); ++i) { - if (!m_data.contains(i.key()) || i.value() != m_data.value(i.key())) { - m_data[i.key()] = i.value(); - updated = true; - } - } - return updated; -} - -QString Unit::name() const -{ - return m_data.value("name").toString(); -} - -QString Unit::script() const -{ - return m_data.value("script").toString(); -} - - - -static Config mkGlobal() -{ - static const char *envName = "VAULT_GLOBAL_CONFIG_DIR"; - QString unitsDir = qEnvironmentVariableIsSet(envName) ? qgetenv(envName) : "/var/lib/the-vault"; - return Config(unitsDir); -} - -static const char *moduleExt = ".json"; -static Config s_global = mkGlobal(); - -Config::Config(const QString &unitsDir) - : m_unitsDir(unitsDir) -{ - if (unitsDir.isEmpty()) { - error::raise({{"msg", "Empty configuration path"}}); - } - - load(); -} - -Config::~Config() -{ -} - -Config *global() -{ - return &s_global; -} - -void Config::load() -{ - if (!os::path::exists(m_unitsDir)) { - return; - } - - QDir d(m_unitsDir); - for (const QString &fname: d.entryList({ QLatin1String("*") + moduleExt })) { - try { - Unit unit; - unit.read(d.filePath(fname)); - m_units[unit.name()] = unit; - } catch (error::Error e) { - debug::error("Loading config ", fname); - debug::error("Error", e.what()); - } - } -} - -bool Config::set(const QVariantMap &data) -{ - bool updated = false; - Unit unit(data); - - QString name = unit.name(); - QString configPath = path(name); - - if (!os::path::exists(m_unitsDir)) { - os::mkdir(m_unitsDir); - m_units[name] = unit; - updated = true; - } else if (m_units.contains(name)) { - updated = m_units[name].update(data); - } else if (os::path::exists(configPath)) { - Unit actual = Unit().read(configPath); - updated = actual.update(data); - m_units[name] = actual; - } else { - m_units[name] = unit; - updated = true; - } - - return updated && m_units[name].write(configPath); -} - -QString Config::rm(const QString &name) -{ - QString fname = path(name); - if (!os::path::exists(fname)) { - return QString(); - } - os::rm(fname); - m_units.remove(name); - return name + moduleExt; -} - -void Config::setUnitsDir(const QString &dir) -{ - m_unitsDir = dir; - if (dir.isEmpty()) { - error::raise({{"msg", "Wrong configuration"}, {"cfg", dir}}); - } -} - -QString Config::path(const QString &fname) const -{ - return m_unitsDir + "/" + fname + moduleExt; -} - -QMap Config::units() const -{ - return m_units; -} - -QString Config::root() const -{ - return m_unitsDir; -} - - - -Vault::Vault(Gittin::Repo *vcs) - : m_config(units_path(vcs->path())) - , m_vcs(vcs) -{ - -} - -Vault::~Vault() -{ -} - -bool Vault::set(const QVariantMap &data) -{ - return m_config.set(data); -} - -bool Vault::rm(const QString &name) -{ - auto fname = m_config.rm(name); - return !fname.isEmpty(); -} - -bool Vault::update(const QMap &src) -{ - QVariantMap map; - for (auto i = src.begin(); i != src.end(); ++i) { - map[i.key()] = i.value().data(); - } - return update(map); -} - -bool Vault::update(const QVariantMap &src) -{ - bool updated = false; - auto before = m_config.units(); - for (auto i = src.begin(); i != src.end(); ++i) { - if (set(i.value().toMap())) { - updated = true; - } - } - // remove local copy of the global unit if there is no global - // counterpart - for (auto it = before.cbegin(); it != before.cend(); ++it) { - auto name = it.key(); - if (it.value().isLocal() || src.contains(name)) - continue; - - debug::info("Global unit", name, "is not registered, removing"); - if (!rm(name)) - error::raise({{"msg", name + " is not removed??"}}); - - updated = true; - } - return updated; -} - -QMap Vault::units() const -{ - return m_config.units(); -} - -}} diff --git a/tests/.gitignore b/tests/.gitignore deleted file mode 100644 index 836d083..0000000 --- a/tests/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -unit_all -test_* diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt deleted file mode 100644 index 538ab58..0000000 --- a/tests/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -pkg_check_modules(TUT REQUIRED tut>=0.0.3) -include_directories(${TUT_INCLUDES}) - -find_package(Qt5Core REQUIRED) -set(CMAKE_AUTOMOC TRUE) - -testrunner_project(vault) -set(UNIT_TESTS unit vault transfer) - -add_executable(unit_all unit_all.cpp) -target_link_libraries(unit_all vault-unit) -qt5_use_modules(unit_all Core) -testrunner_install(TARGETS unit_all) - -MACRO(UNIT_TEST _name) - set(_exe_name test_${_name}) - add_executable(${_exe_name} main.cpp ${_name}.cpp tests_common.cpp) - target_link_libraries(${_exe_name} - ${QTAROUND_LIBRARIES} - ${COR_LIBRARIES} - vault-core - ) - qt5_use_modules(${_exe_name} Core) - testrunner_install(TARGETS ${_exe_name}) -ENDMACRO(UNIT_TEST) - -foreach(t ${UNIT_TESTS}) - UNIT_TEST(${t}) -endforeach(t) - -target_link_libraries(test_transfer vault-transfer) - -MACRO(UNIT_IMPL _name) - set(_exe_name ${_name}_vault_test) - set(UNIT_NAME ${_name}) - configure_file(basic_unit.cpp.in ${CMAKE_CURRENT_SOURCE_DIR}/${_name}_unit.cpp @ONLY) - add_executable(${_exe_name} ${_name}_unit.cpp) - target_link_libraries(${_exe_name} vault-unit) - qt5_use_modules(${_exe_name} Core) - testrunner_install(TARGETS ${_exe_name}) -ENDMACRO(UNIT_IMPL) - -UNIT_IMPL(unit1) -UNIT_IMPL(unit2) -testrunner_install(PROGRAMS unit_fail_vault_test) -testrunner_install(PROGRAMS check_dirs_similar.sh) - -add_subdirectory(qml) diff --git a/tests/basic_unit.cpp.in b/tests/basic_unit.cpp.in deleted file mode 100644 index 3600437..0000000 --- a/tests/basic_unit.cpp.in +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include "vault_context.hpp" - -#include -#include -#include - -#include -#include - -int main(int argc, char *argv[]) -{ - try { - QCoreApplication app(argc, argv); - using namespace vault::unit; - execute(getopt(), get(context, "@UNIT_NAME@").toMap()); - } catch (error::Error const &e) { - qDebug() << e; - } catch (std::exception const &e) { - qDebug() << e.what(); - } - return 0; -} diff --git a/tests/check_dirs_similar.sh b/tests/check_dirs_similar.sh deleted file mode 100755 index a058fec..0000000 --- a/tests/check_dirs_similar.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -cd $1 2>/dev/null && find -P . | sort > /tmp/.check-similar-1 -cd $2 2>/dev/null && find -P | sort > /tmp/.check-similar-2 -diff /tmp/.check-similar-1 /tmp/.check-similar-2 > /tmp/.check-similar-diff -cat /tmp/.check-similar-diff - diff --git a/tests/main.cpp b/tests/main.cpp deleted file mode 100644 index 1eaf84c..0000000 --- a/tests/main.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include -#include -#include -#include - - -namespace tut -{ - test_runner_singleton runner; -} - - -int main(int argc, const char *argv[]) -{ - tut::console_reporter reporter; - tut::runner.get().set_callback(&reporter); - try - { - if(tut::tut_main(argc, argv)) - { - if(reporter.all_ok()) { - return 0; - } else { - std::cerr << std::endl; - std::cerr << "tests are failed" << std::endl; - } - } - } - catch(const tut::no_such_group &ex) { - std::cerr << "No such group: " << ex.what() << std::endl; - } - catch(const tut::no_such_test &ex) { - std::cerr << "No such test: " << ex.what() << std::endl; - } - catch(const tut::tut_error &ex) { - std::cout << "General error: " << ex.what() << std::endl; - } - - return -1; -} diff --git a/tests/qml/CMakeLists.txt b/tests/qml/CMakeLists.txt deleted file mode 100644 index b26cf01..0000000 --- a/tests/qml/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -add_executable(test_vault_qml main.cpp) -set_target_properties(test_vault_qml - PROPERTIES COMPILE_DEFINITIONS - "TEST_DIR=\"${TESTS_DIR}\"; IMPORT_DIR=\"${CMAKE_INSTALL_PREFIX}/lib/vault/qml\"" - ) -qt5_use_modules(test_vault_qml Core) -testrunner_install(TARGETS test_vault_qml) -testrunner_install(FILES tst_vault.qml) diff --git a/tests/qml/main.cpp b/tests/qml/main.cpp deleted file mode 100644 index a44d015..0000000 --- a/tests/qml/main.cpp +++ /dev/null @@ -1,16 +0,0 @@ - -#include -#include - -int main(int argc, char **argv) -{ - QCoreApplication app(argc, argv); - - const char *dir = "/tmp/vault-test"; - int ret = system(qPrintable(QLatin1String("mkdir ") + dir)); - if (!ret) ret = system(qPrintable(QLatin1String("mkdir ") + dir + "/home")); - if (!ret) ret = system("qmltestrunner -input " TEST_DIR " -import " IMPORT_DIR); - if (!ret) ret = system(qPrintable(QLatin1String("rm -rf ") + dir)); - - return ret; -} diff --git a/tests/qml/tst_vault.qml b/tests/qml/tst_vault.qml deleted file mode 100644 index cdef4bf..0000000 --- a/tests/qml/tst_vault.qml +++ /dev/null @@ -1,56 +0,0 @@ - -import QtTest 1.0 -import QtQuick 2.0 -import NemoMobile.Vault 1.0 - -Item { - width: 200 - height: 200 - - Vault { - id: vault - } - SignalSpy { - id: doneSpy - target: vault - signalName: "done" - } - SignalSpy { - id: errorSpy - target: vault - signalName: "error" - } - SignalSpy { - id: progressSpy - target: vault - signalName: "progress" - } - - resources: TestCase { - name: "vault" - when: windowShown - function test_init() { - vault.root = "/tmp/vault-test/root" - vault.backupHome = "/tmp/vault-test/home" - - vault.connectVault(false) - tryCompare(doneSpy, "count", 1) - verify(errorSpy.count == 0) - verify(vault.snapshots().length == 0) - } - function test_units() { - vault.root = "/tmp/vault-test/root" - vault.backupHome = "/tmp/vault-test/home" - - var unit_script_fname = "unit1_vault"; - vault.registerUnit({name: "unit1", script: "./" + unit_script_fname}, false) - var units = vault.units() - verify(units.length == 1) - verify('unit1' === units[0]) //Why does "'unit1' in units" fail??? - - verify(doneSpy.count == 1) - vault.startBackup("", ["unit1"]) - tryCompare(doneSpy, "count", 2) - } - } -} diff --git a/tests/test-unit-text-only b/tests/test-unit-text-only deleted file mode 100755 index fbd05b5..0000000 --- a/tests/test-unit-text-only +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -initial_dir=$(pwd) - -src=$(dirname $0) -src=$(cd $src;pwd) -source $src/testing-common-unit.sh - -if [ "$action" == "export" ]; then - trace "Exporting" - echo "first: $(date): $(uuidgen)" > $data_dir/1.txt - echo "second: $(date): $(uuidgen)" > $data_dir/2.txt -elif [ "$action" == "import" ]; then - trace "Importing" - for src in $data_dir/1.txt $data_dir/2.txt; do - [ -f $src ] || error 77 "There is no source file $src" - cp $src $home_dir || error 78 "Can't copy $src to $home_dir" - done -fi diff --git a/tests/test-vault-basic b/tests/test-vault-basic deleted file mode 100755 index e37d87b..0000000 --- a/tests/test-vault-basic +++ /dev/null @@ -1,168 +0,0 @@ -#!/bin/bash - -initial_dir=$(pwd) - -src=$(dirname $0) -src=$(cd $src;pwd) -source $src/testing-common-vault.sh - -create_test_dir - -test_home= -storage= - -user_name=User1 -email=mail@user - -function cd_vault_and_check_it { - cd $storage || failed 2 "No vault dir $storage" - init_root_and_enter - check_is_vault_storage $storage/.git - cd .git || failed 4 "No .git" - [ "$(git config user.name)" == "$user_name" ] || test_failed 5 "User name is wrong" - [ "$(git config user.email)" == "$email" ] || test_failed 5 "User email is wrong" - cd .. || test_failed 6 "Can't cd .." -} - -NEXT_TEST "Create empty vault" -create_test_dirs 1 -vault -V $storage -H $test_home -a init -g user.name=$user_name,user.email=$email \ - || test_failed 1 "Vault init is failed" -cd_vault_and_check_it - -NEXT_TEST "Create empty vault, long options" -create_test_dirs 2 -vault --vault $storage --home $test_home --action init --git-config user.name=$user_name,user.email=$email \ - || test_failed 1 "Vault init is failed" -cd_vault_and_check_it - -function check_unit { - unit_name=$1 - fname=$storage/.units/$unit_name.json - [ -f $fname ] || test_failed 7 "There is no unit conf file $fname" -} - -function check_no_unit { - unit_name=$1 - fname=$storage/.units/$unit_name.json - [ -f $fname ] && test_failed 7 "There shoudn't be unit conf file $fname" -} - -unit= -unit_group= - -function reg_unit { - ensure_param_count_exit_usage $# 3 "Use: reg_unit name group script" - unit=$1 - unit_group=$2 - script=$3 - # move outside of repo to be sure it does not depend on location - cd $test_dir - vault -V $storage --H $test_home -a register \ - -d name=$unit,group=$unit_group,icon=first-icon,script=$script \ - || test_failed 1 "Vault init is failed" -} - -function unreg_unit { - unit=$1 - # move outside of repo to be sure it does not depend on location - cd $test_dir - vault -V $storage --H $test_home -a unregister -M $unit \ - || test_failed 1 "Vault init is failed" -} - -script=vault-test-script-generic - -NEXT_TEST "Register local units" -reg_unit U0 G0 $script -check_unit $unit - -reg_unit U1 G0 $script -check_unit $unit -check_unit U0 - -reg_unit U2 G1 $script -check_unit $unit -check_unit U0 -check_unit U1 - -NEXT_TEST "Unregister local units" -unreg_unit U0 -check_no_unit $unit -check_unit U1 -check_unit U2 - -NEXT_TEST "Unit with readable data" -create_test_dirs text_unit -vault -V $storage -H $test_home -a init -g user.name=$user_name,user.email=$email \ - || test_failed 1 "Vault init is failed" -cd_vault_and_check_it -reg_unit UData GReadable $src/test-unit-text-only -vault -a export -M $unit -V $storage -H $test_home || - test_failed 40 "Export of the unit $unit is failed" -[[ $(find $test_home | wc -l) -eq 1 ]] || - test_failed 43 "There shouldn't be anything in the test home $test_home" - -cd $storage -[[ $(git log --oneline | wc -l) -eq 3 ]] || - test_failed 44 "Log should have 3 lines" -git_tag=$(git describe --tags HEAD) -[[ "$git_tag" =~ \>.* ]] || test_failed "Tag >... is expected, got $git_tag" -snap=$(get_snapshots $storage) -[[ "$snap" == "$git_tag" ]] || test_failed "Expected $snap == $git_tag" -#git_log=$(git log --oneline) -#echo "$git_log" -#[[ "$git_log" =~ ""]] - -expected_data_dir=$(get_data_dir $storage $unit) -[[ $(find $expected_data_dir | wc -l) -eq 3 ]] || - test_failed 43 "There shouldn't be files in the dir $expected_data_dir" - -expected_blobs_dir=$(get_blobs_dir $storage $unit) -[[ $(find $expected_blobs_dir | wc -l) -eq 1 ]] || - test_failed 43 "There shouldn't be anything in the dir $expected_blobs_dir" - -vault -a import -M $unit -V $storage -H $test_home -t $snap || - test_failed 40 "Import of the unit $unit is failed" - -[[ $(find $test_home | wc -l) -eq 3 ]] || - test_failed 43 "Check home $test_home contents" -expected_file=$test_home/1.txt -[ -f $expected_file ] || test_failed 41 "No file $expected_file" -[[ "$(cat $expected_file)" =~ first:.* ]] || test_failed "Check data in $expected_file" -expected_file=$test_home/2.txt -[ -f $expected_file ] || test_failed 42 "No file $expected_file" -[[ "$(cat $expected_file)" =~ second:.* ]] || test_failed "Check data in $expected_file" - -NEXT_TEST "Second backup for the same unit" -vault -a export -M $unit -V $storage -H $test_home || - test_failed 40 "Export of the unit $unit is failed" - - -snap_count=$(get_snapshots $storage | wc -l) -[[ $snap_count -eq 2 ]] || test_failed 43 "Expected 2 snapshots, got $snap_count" - -home_copy=$test_dir/home_copy -cp -r $test_home $home_copy || test_failed 44 "Can't copy $test_home as $home_copy" - -NEXT_TEST "Restore Second backup, get updated content" -snap=$(get_snapshots $storage | tail -n 1) -vault -a import -M $unit -V $storage -H $test_home -t $snap || - test_failed 40 "Import of the unit $unit is failed" - -ls $home_copy > $test_dir/before.txt -ls $test_home > $test_dir/after.txt -diff $test_dir/before.txt $test_dir/after.txt || test_failed 45 "ls should be the same" -diff -r $home_copy $test_home > $test_dir/diff.txt && test_failed 46 "content should change" - -NEXT_TEST "Restore 1st backup, get content back" -snap_before=$(get_snapshots $storage | head -n 1) -[[ "$snap_before" != "$snap" ]] || test_failed 47 "Snapshot ids are equal: $snap_before $snap" -snap=$snap_before -vault -a import -M $unit -V $storage -H $test_home -t $snap || - test_failed 40 "Import of the unit $unit is failed" -ls $home_copy > $test_dir/before.txt -ls $test_home > $test_dir/after.txt -diff $test_dir/before.txt $test_dir/after.txt || test_failed 48 "ls should be the same" -diff -r $home_copy $test_home > $test_dir/diff.txt || test_failed 49 "1st state should be restored" - diff --git a/tests/test-vault-move b/tests/test-vault-move deleted file mode 100755 index af05d00..0000000 --- a/tests/test-vault-move +++ /dev/null @@ -1,118 +0,0 @@ -#!/bin/bash - -initial_dir=$(pwd) - -src=$(dirname $0) -src=$(cd $src;pwd) -source $src/testing-common-vault.sh - -trace "Test run in $TOP_PID" - -empty_repo_archive=$src/../tests/empty-repo.tar.gz -[ -f $empty_repo_archive ] || test_failed 1 "No test vault archive" - -create_test_dir - -r1=$test_dir/v1 -rout=$test_dir/external1 -rout2=$test_dir/external2 - -NEXT_TEST "Prepare $test_dir" -mkdir $r1 || test_failed 2 "Can't create $r1" -tar xf $empty_repo_archive -C $r1 || test_failed 4 "Can't extract archive" -cd $r1 || test_failed 5 "Can't enter $r1" -init_root_and_enter -storage_now=$r1/.git - -NEXT_TEST "Move to exiting dir" -mkdir $rout || test_failed 10 "Can't create $rout" -git-vault-move $rout 1>$test_out 2>$test_err \ - && test_failed 6 "Move to existing $rout shouldn't succeed" - -NEXT_TEST "Move to read-only dir" -chmod ug-w $rout || test_failed 12 "Can't chown $rout" -ro_dir=$rout/inaccessible -git-vault-move $ro_dir 1>$test_out 2>$test_err \ - && test_failed 6 "Move to RO dir $ro_dir shouldn't succeed" -[ -d $r1/.git ] || test_failed 7 "Not a dir $r1/.git" -check_is_vault_storage $storage_now -rmdir $rout || test_failed 11 "Dir $rout is not empty?" - -NEXT_TEST "Move out" -git-vault-move $rout \ - || test_failed 6 "Move to $rout" -storage_now=$rout -[ -f $r1/.git ] || test_failed 7 "Not a file $r1/.git" -check_is_vault_storage $storage_now - -NEXT_TEST "Move out-of-tree dir to itself" -git-vault-move $rout 1>$test_out 2>$test_err \ - && test_failed 14 "Moving into self shouldn't succeed for $rout" - -NEXT_TEST "Move out to another dir" -git-vault-move $rout2 \ - || test_failed 6 "Move to $rout2" -storage_now=$rout2 -[ -f $r1/.git ] || test_failed 7 "Not a file $r1/.git" -check_is_vault_storage $storage_now - -NEXT_TEST "Move to read-only in-tree .git" -chmod ug-w $r1/.git || test_failed 12 "Can't chown $r1/.git" -git-vault-move $r1/.git 1>$test_out 2>$test_err \ - && test_failed 16 "Move to RO $r1/.git shouldn't succeed" -[ -f $r1/.git ] || test_failed 7 "Not a file $r1/.git" -check_is_vault_storage $storage_now -chmod ug+w $r1/.git || test_failed 12 "Can't chown back $r1/.git" - -NEXT_TEST "Move in" -git-vault-move $r1/.git \ - || test_failed 6 "Move to $r1/.git" -storage_now=$r1/.git -[ -d $rout ] && test_failed 7 "Dir $rout is left" -[ -d $r1/.git ] || test_failed 7 "Not a dir $r1/.git" -check_is_vault_storage $storage_now - -NEXT_TEST "Move in-tree dir to itself" -git-vault-move $r1 1>$test_out 2>$test_err \ - && test_failed 8 "Moving into self shouldn't succeed $r1.git" - -NEXT_TEST "Setup to check moving between filesystems" -other_fs=/dev/shm -[ -d /dev/shm ] || error 20 "Can't test further w/o /dev/shm used as other fs" -other_test_dir=$other_fs/$(basename $test_dir) -mkdir $other_test_dir || error 20 "Can't create $other_test_dir" -normal_cleanup="$normal_cleanup; rm -rf $other_test_dir" -failed_cleanup="warn 'Dir $other_test_dir is left';$failed_cleanup" - -NEXT_TEST "Move to other fs" - -out_repo=$other_test_dir/v1 - -git-vault-move $out_repo \ - || test_failed 6 "Move to $out_repo" -storage_now=$out_repo -[ -f $r1/.git ] || test_failed 7 "Not a file $r1/.git" -check_is_vault_storage $storage_now - -NEXT_TEST "Move from other fs" -git-vault-move $r1/.git \ - || test_failed 6 "Move from $out_repo" -[ -d $out_repo ] && error 23 "Dir should not be left: $out_repo" -storage_now=$r1/.git -[ -d $r1/.git ] || test_failed 7 "Not a dir $r1/.git" -check_is_vault_storage $storage_now - -NEXT_TEST "Move back to other fs" -git-vault-move $out_repo \ - || test_failed 6 "Move to $out_repo" -storage_now=$out_repo -[ -f $r1/.git ] || test_failed 7 "Not a file $r1/.git" -check_is_vault_storage $storage_now - -NEXT_TEST "Move from other fs to out-of-tree" -git-vault-move $rout \ - || test_failed 6 "Move to $rout" -storage_now=$rout -[ -d $out_repo ] && test_failed 7 "Out dir is left: $out_repo" -[ -f $r1/.git ] || test_failed 7 "Not a file $r1/.git" -check_is_vault_storage $storage_now diff --git a/tests/test-vault-split-uri b/tests/test-vault-split-uri deleted file mode 100755 index ed353e6..0000000 --- a/tests/test-vault-split-uri +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -exec=./vault-clone-blobs - -src=$(dirname $0) -src=$(cd $src;pwd) -source $src/vault-testing.sh - -function assert_split { - pattern=$1 - src_repo= - port= - user= - host= - src_type= - - split_git_uri $pattern - - res= - case "$src_type" in - ssh) - res="SRC:user=$user,host=$host,port=$port,path=$src_repo" - ;; - local) - res="SRC:path=$src_repo" - ;; - *) - error 4 "Unsupported uri: $uri" - esac - - if [ "$res" != "$2" ]; then - error "FOR '$pattern': $res != $2" - exit 1 - fi -} - -# ssh:// form -assert_split ssh://user0@host1:/home/dir2 "SRC:user=user0,host=host1,port=,path=/home/dir2" -assert_split ssh://user0@host1:1/home/dir2 "SRC:user=user0,host=host1,port=1,path=/home/dir2" -assert_split ssh://user0@host1:12/home/dir2 "SRC:user=user0,host=host1,port=12,path=/home/dir2" -assert_split ssh://user0@host1.org:/home/dir2 "SRC:user=user0,host=host1.org,port=,path=/home/dir2" -assert_split ssh://host1.org:/home/dir2 "SRC:user=$(whoami),host=host1.org,port=,path=/home/dir2" - -# user@host form -assert_split user0@host1:/home/dir2 "SRC:user=user0,host=host1,port=,path=/home/dir2" -assert_split user0@host1:1/home/dir2 "SRC:user=user0,host=host1,port=1,path=/home/dir2" -assert_split user0@host1:12/home/dir2 "SRC:user=user0,host=host1,port=12,path=/home/dir2" -assert_split user0@host1.org:/home/dir2 "SRC:user=user0,host=host1.org,port=,path=/home/dir2" -assert_split host1.org:/home/dir2 "SRC:user=$(whoami),host=host1.org,port=,path=/home/dir2" -assert_split host1.org\\:/home/dir2 "SRC:path=host1.org\\:/home/dir2" diff --git a/tests/testing-common-unit.sh b/tests/testing-common-unit.sh deleted file mode 100644 index e2c27c8..0000000 --- a/tests/testing-common-unit.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -initial_dir=$(pwd) - -src=$(dirname $0) -src=$(cd $src;pwd) -source $src/testing-common-vault.sh - -OPTS=$(getopt -o A:D:B:H: --long action:,dir:,bin-dir:,home-dir: -n "$0" -- "$@") -[ $? -eq 0 ] || error 3 "Error parsing options $@" - -eval set -- "$OPTS" - -while true; do - case "$1" in - -A | --action) - action=$2 - shift 2 - ;; - -D | --dir) - data_dir=$2 - shift 2 - ;; - -B | --bin-dir) - blobs_dir=$2 - shift 2 - ;; - -H | --home-dir) - home_dir=$2 - shift 2 - ;; - -- ) - shift; break ;; - *) - shift; break ;; - esac -done - -trace "Options: action=$action, data=$data_dir, blobs=$blobs_dir, home=$home_dir" - -[[ "$action" =~ ^import|export$ ]] || error 31 "Unknown action: $action" -for d in data_dir blobs_dir home_dir; do - [ -d ${!d} ] || error 32 "Dir doesn't exist: $d=${!d}" -done - diff --git a/tests/testing-common-vault.sh b/tests/testing-common-vault.sh deleted file mode 100644 index 8ea7ce1..0000000 --- a/tests/testing-common-vault.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash - -initial_dir=$(pwd) - -src=$(dirname $0) -src=$(cd $src;pwd) -lib_dir=$src -if [ "x$VAULT_LIB_DIR" != "x" ]; then - if ! [ -d $VAULT_LIB_DIR ]; then - echo "No such dir $VAULT_LIB_DIR" - exit 1 - fi - lib_dir="$VAULT_LIB_DIR" -elif [ -d "$src/../tools" ]; then - export VAULT_LIB_DIR=$src/../tools - lib_dir="$VAULT_LIB_DIR" -fi -source $lib_dir/vault-misc - -cur_test="Begin" -function NEXT_TEST { - trace $@ - cur_test=$1 -} - -function test_failed { - echo 'stdout {' >&2; - cat $test_out >&2; - echo '} stderr {' >&2; - cat $test_err >&2; - echo '}' >&2; - error $1 "Test: $cur_test." ${@:2} -} - -function check_is_vault_storage { - d=$1 - [ -d $d ] || test_failed 7 "Not a dir $d" - [ -f $d/config ] || test_failed 7 "Not a git storage" - [ -d $d/blobs ] || test_failed 7 "Not a vault storage $d?" -} - - -function create_test_dir { - test_dir=$(mktemp -t -d vault.XXXXXXXXXX) - test_out=$test_dir/stdout.txt - test_err=$test_dir/stderr.txt - touch $test_out - touch $test_err - cd $test_dir || test_failed 1 "Can't enter $test_dir" - normal_cleanup="$normal_cleanup; echo 'OK' 1>&2; cd $initial_dir; rm -rf $test_dir" - failed_cleanup="warn 'Dir $test_dir is left';$failed_cleanup;" -} - -test_home= -storage= - -function create_test_dirs { - ensure_param_count_exit_usage $# 1 "create_test_dirs prefix" - prefix=$1 - test_home=$test_dir/$prefix/home - storage=$test_dir/$prefix/vault - mkdir -p $test_home || test_failed 1 "Can't create $test_home" - mkdir -p $storage || test_failed 1 "Can't create $storage" -} diff --git a/tests/tests.xml.in b/tests/tests.xml.in deleted file mode 100644 index fe6369a..0000000 --- a/tests/tests.xml.in +++ /dev/null @@ -1,14 +0,0 @@ - - - - Vault automatic tests - - Testing vault - - cd @TESTS_DIR@ && VAULT_GLOBAL_CONFIG_DIR=/tmp/vault-test-unit/config VAULT_TEST_TMP_DIR=/tmp/vault-test-unit ./test_unit - cd @TESTS_DIR@ && VAULT_GLOBAL_CONFIG_DIR=/tmp/vault-test-unit/config VAULT_TEST_TMP_DIR=/tmp/vault-test-vault ./test_vault - cd @TESTS_DIR@ && VAULT_GLOBAL_CONFIG_DIR=/tmp/vault-test-unit/config VAULT_TEST_TMP_DIR=/tmp/vault-test-transfer ./test_transfer - - - - diff --git a/tests/tests_common.cpp b/tests/tests_common.cpp deleted file mode 100644 index 86e7413..0000000 --- a/tests/tests_common.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include - -int register_unit(QString const &vault_dir, const QString &name, bool is_global) -{ - QVariantMap data = {{"action", "register"}, - {"data", "name=" + name + ",group=group1," - + "script=./" + name + "_vault_test"}}; - if (is_global) { - data["global"] = true; - } else { - data["vault"] = vault_dir; - } - return vault::Vault::execute(data); -}; diff --git a/tests/tests_common.hpp b/tests/tests_common.hpp deleted file mode 100644 index b328102..0000000 --- a/tests/tests_common.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef _VAULT_TESTS_COMMON_HPP_ -#define _VAULT_TESTS_COMMON_HPP_ - -#include -#include - -namespace { - -template -std::basic_ostream& operator << -(std::basic_ostream &dst, QStringList const &src) -{ - for (auto v : src) - dst << v.toStdString() << ","; - return dst; -} - -template -std::basic_ostream& operator << -(std::basic_ostream &dst, QSet const &src) -{ - for (auto v : src) - dst << str(v) << ","; - return dst; -} - -template -std::basic_ostream& operator << -(std::basic_ostream &dst, QString const &src) -{ - dst << src.toStdString(); - return dst; -} - -QStringList strings() -{ - return QStringList(); -} - -template -QStringList strings(QString const &s, A &&...args) -{ - return QStringList(s) + strings(std::forward(args)...); -} - -} - -#define S_(...) strings(__VA_ARGS__).join(' ').toStdString() - -#define STRINGIFY(x) #x -#define TOSTRING(x) STRINGIFY(x) -#define AT __FILE__ ":" TOSTRING(__LINE__) - -#endif // _VAULT_TESTS_COMMON_HPP_ diff --git a/tests/transfer.cpp b/tests/transfer.cpp deleted file mode 100644 index 2c87caf..0000000 --- a/tests/transfer.cpp +++ /dev/null @@ -1,179 +0,0 @@ -#include -#include "vault_context.hpp" -#include "tests_common.hpp" - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -//#include "tests_common.hpp" - -#include -#include - -#include -#include - -namespace subprocess = qtaround::subprocess; - -namespace tut -{ - -struct transfer_test -{ - virtual ~transfer_test() - { - } -}; - -typedef test_group tf; -typedef tf::object object; -tf vault_transfer_test("transfer"); - -enum test_ids { - tid_setup = 1 - , tid_export - , tid_import -}; - -namespace { - -using vault::Vault; -std::unique_ptr the_vault; - -void init_vault(QString const &vault_dir) -{ - tut::ensure("Vault dir is path", !vault_dir.isEmpty()); - the_vault.reset(new Vault(vault_dir)); - the_vault->init(map({{"user.name", "NAME"}, {"user.email", "email@domain.to"}})); -} - - -void create_backup() -{ - auto home = str(get(context, "home")); - auto vault_dir = str(get(context, "vault_dir")); - init_vault(vault_dir); - mktree(unit1_tree, str(get(context, "unit1_dir"))); - register_unit(vault_dir, "unit1", false); - - bool is_started = false, is_failed = false; - the_vault->backup(home, {}, "", [&](const QString &, const QString &status) { - if (status == "fail") - is_failed = true; - else if (status == "begin") - is_started = true; - }); - tut::ensure("backup was not started", is_started); - tut::ensure("backup is failed", !is_failed); -} - -QString home; -QString vault_dir; -QString archive_dir; -QString git_dir; -QSet ftree_git_before_export; - -std::unique_ptr export_ctx; -std::unique_ptr import_ctx; - -QStringList stages; -void on_progress(QVariantMap &&data) -{ - tut::ensure("There should be progress report type" - , data.find("type") != data.end()); - auto t = str(data["type"]); - if (t == "stage") { - auto stage = str(data["stage"]); - stages.push_back(stage); - } -} - -} - -template<> template<> -void object::test() -{ - home = str(get(context, "home")); - archive_dir = os::path::join(str(get(context, "home")), "sd"); - os::mkdir(archive_dir); - create_backup(); -} - -template<> template<> -void object::test() -{ - vault_dir = str(get(context, "vault_dir")); - git_dir = os::path::join(vault_dir, ".git"); - export_ctx = cor::make_unique(); - export_ctx->init(the_vault.get(), CardTransfer::Export, archive_dir); - ftree_git_before_export = get_ftree(git_dir); - - auto dst = export_ctx->getDst(), src = export_ctx->getSrc(); - ensure_eq("Source", src, vault_dir); - ensure_eq("Dst", os::path::dirName(dst), archive_dir); - ensure_eq("Export Action", export_ctx->getAction() - , CardTransfer::Export); - auto space_before = export_ctx->getSpace(); - ensure_ge("Export Space", (int)space_before, 1); - - stages.clear(); - export_ctx->execute(on_progress); - ensure_eq("Expected stages", stages - , QStringList({"Copy", "Flush", "Validate"})); - ensure(("Dst file should exist" + dst).toStdString() - , os::path::isFile(dst)); - auto out = str(subprocess::check_output("tar", {"tf", dst})); - auto names = filterEmpty(out.split("\n")); - auto tag_fname = vault::fileName(vault::File::State); - for (auto it = names.begin(); it != names.end(); ++it) { - auto const &name = *it; - static QRegExp const git_file_re("^\\.git/.*$"); - auto is_git_file = git_file_re.exactMatch(name); - auto is_tag = (name == tag_fname); - ensure(("Unexpected file:" + name).toStdString() - , is_git_file || is_tag); - } - ensure_trees_equal("Export" - , ftree_git_before_export - , get_ftree(git_dir)); -} - -template<> template<> -void object::test() -{ - vault_dir = os::path::join(home, "vault_imported"); - git_dir = os::path::join(vault_dir, ".git"); - init_vault(vault_dir); - - import_ctx = cor::make_unique(); - import_ctx->init(the_vault.get(), CardTransfer::Import, archive_dir); - - auto dst = import_ctx->getDst(), src = import_ctx->getSrc(); - ensure_eq("Import Dst", dst, vault_dir); - ensure_eq("Import Src", os::path::dirName(src), archive_dir); - ensure_eq("Import Action", import_ctx->getAction() - , CardTransfer::Import); - auto space_before = import_ctx->getSpace(); - ensure_ge("Import Space", space_before, 1); - - stages.clear(); - import_ctx->execute(on_progress); - ensure_eq("Expected stages", stages - , QStringList({"Validate", "Copy"})); - - ensure_trees_equal("Import" - , ftree_git_before_export - , get_ftree(git_dir)); -} - - -} diff --git a/tests/unit.cpp b/tests/unit.cpp deleted file mode 100644 index d7fb2f1..0000000 --- a/tests/unit.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include -#include - -#include - -#include "tests_common.hpp" -#include - -#include -#include - -#include -#include - -namespace os = qtaround::os; -namespace subprocess = qtaround::subprocess; -namespace error = qtaround::error; -namespace sys = qtaround::sys; - -namespace tut -{ - -struct unit_test -{ - virtual ~unit_test() - { - } -}; - -typedef test_group tf; -typedef tf::object object; -tf vault_unit_test("unit"); - -enum test_ids { - tid_export = 1, - tid_import, - tid_suite_teardown -}; - -namespace { - -const string_map_type short_options = { -}; - -const string_map_type long_options = { - {"bin-dir", "bin-dir"}, {"dir", "dir"} - , {"home-dir", "home-dir"}, {"action", "action"} -}; - -const QSet options_has_param = { - {"bin-dir", "dir", "home-dir", "action"} -}; - -const QString root = "/tmp/test-the-vault-unit"; -const QString home = os::path::join(root, "home"); -const QString vault = os::path::join(root, "vault"); -const QString home_out = os::path::join(root, "home_out"); - -typedef std::function teardown_type; -std::list suite_teardowns_; -void setup() -{ - auto mkdir = [](QString const &p) { - ensure(std::string("Dir should not exist:") + p.toStdString() - , !os::path::exists(p)); - if (!os::mkdir(p, {{"parent", true}})) - error::raise({{"msg", "Can't create"}, {"path", p}}); - }; - mkdir(home); - mkdir(home_out); - mkdir(vault); - suite_teardowns_.push_back([]() { - os::rmtree(root); - }); - - - QMap home_dirs = {{ "data", os::path::join(home, "data")} - , {"bin", os::path::join(home, "bin")}}; - for (auto it = home_dirs.begin(); it != home_dirs.end(); ++it) { - auto t = it.key(); - auto root_path = it.value(); - - mkdir(root_path); - namespace path = os::path; - auto dir_content = path::join(root_path, "content"); - mkdir(dir_content); - mkdir(path::join(dir_content, "content_subdir")); - for (int i = 0; i < 3; ++i) { - QString s = str(i); - os::write_file(path::join(dir_content, "a" + s), s); - } - - auto dir_self = path::join(root_path, ".hidden_dir_self"); - mkdir(dir_self); - for (int i = 0; i < 4; ++i) { - QString s = str(i); - os::write_file(path::join(dir_self, "b" + s), s); - } - - os::write_file(path::join(root_path, "file1"), "c1"); - auto in_dir = path::join(root_path, "in_dir"); - mkdir(in_dir); - os::write_file(path::join(in_dir, "file2"), "d2"); - - auto linked_dir = path::join(root_path, "linked_dir"); - mkdir(linked_dir); - os::write_file(path::join(linked_dir, "e1"), "1"); - os::symlink("./linked_dir", path::join(root_path, "symlink_to_dir")); - - } -} - -} // namespace - -template<> template<> -void object::test() -{ - setup(); - QVariantMap options = {{"dir", vault}, {"bin-dir", vault} - , {"home-dir", home}, {"action", "export"}}; - auto args = sys::command_line_options - (options, short_options, long_options, options_has_param); - subprocess::check_output("./unit_all", args); - auto out = str(subprocess::check_output("./check_dirs_similar.sh", QStringList({home, vault}))); - auto lines = out.split("\n").filter(QRegExp("^[<>]")); - QStringList expected = {"< ./bin/symlink_to_dir", "< ./data/symlink_to_dir" - , "> ./" + vault::config::prefix + ".links" - , "> ./" + vault::config::prefix + ".unit.version"}; - lines.sort(); - expected.sort(); - ensure_eq("Unexpected structure difference", lines, expected); -} - -template<> template<> -void object::test() -{ - QVariantMap options = { - {"dir", vault}, {"bin-dir", vault} - , {"home-dir", home_out}, {"action", "import"}}; - auto args = sys::command_line_options - (options, short_options, long_options, options_has_param); - subprocess::check_output("./unit_all", args); - - auto out = str(subprocess::check_output - ("./check_dirs_similar.sh", QStringList({home, home_out}))); - auto lines = out.split("\n").filter(QRegExp("^[<>]")); - QStringList expected; // no difference - lines.sort(); - expected.sort(); - ensure_eq("Unexpected structure difference", lines, expected); -} - -template<> template<> -void object::test() -{ - for (auto const &fn : suite_teardowns_) - fn(); -} - -} diff --git a/tests/unit1_vault_test.cpp b/tests/unit1_vault_test.cpp deleted file mode 100644 index 4644a8a..0000000 --- a/tests/unit1_vault_test.cpp +++ /dev/null @@ -1,30 +0,0 @@ - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -const QVariantMap info = { - {"home", map({{"bin", list({"unit1"})}})} -}; - -int main(int argc, char *argv[]) -{ - try { - QCoreApplication app(argc, argv); - using namespace vault::unit; - execute(getopt(), info); - } catch (qtaround::error::Error const &e) { - qDebug() << e; - } catch (std::exception const &e) { - qDebug() << e.what(); - } - return 0; -} diff --git a/tests/unit_all.cpp b/tests/unit_all.cpp deleted file mode 100644 index 964a3fe..0000000 --- a/tests/unit_all.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include - -#include -#include -#include - -#include -#include - -namespace { -QVariantMap info = { - {"home" , map({ - {"data", list({ - map({{"path", "data/.hidden_dir_self"}}) - , "data/content/." - , map({{"path", "data/file1" }}) - , map({{"path", "data/in_dir/file2" }}) - , map({{"path", "data/symlink_to_dir" }})})} - , {"bin", list({ - map({{"path", "bin/content/."}}) - , map({{"path", "bin/.hidden_dir_self" }}) - , map({{"path", "bin/file1" }}) - , "bin/in_dir/file2" - , "bin/symlink_to_dir"})}})} -}; -} - -int main(int argc, char *argv[]) -{ - try { - QCoreApplication app(argc, argv); - using namespace vault::unit; - execute(getopt(), info); - } catch (qtaround::error::Error const &e) { - qDebug() << e; - } catch (std::exception const &e) { - qDebug() << e.what(); - } - return 0; -} diff --git a/tests/unit_fail_vault_test b/tests/unit_fail_vault_test deleted file mode 100755 index 9cef0f0..0000000 --- a/tests/unit_fail_vault_test +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -echo "SHOULD FAIL" -echo "FAIL UNIT is FAILED" >&2 -exit 1 diff --git a/tests/vault.cpp b/tests/vault.cpp deleted file mode 100644 index c19994c..0000000 --- a/tests/vault.cpp +++ /dev/null @@ -1,352 +0,0 @@ -#include "vault_context.hpp" - -#include -#include -#include - -#include -#include - -#include - -//#include "tests_common.hpp" - -#include -#include - -#include -#include - -namespace os = qtaround::os; -namespace subprocess = qtaround::subprocess; -namespace error = qtaround::error; - -namespace tut -{ - -struct unit_vault -{ - virtual ~unit_vault() - { - } -}; - -typedef test_group tf; -typedef tf::object object; -tf vault_unit_vault("vault"); - -enum test_ids { - tid_init = 1, - tid_config_global, - tid_config_local, - tid_config_update, - tid_simple_blobs, - tid_clear, - tid_cli_backup_restore_several_units, - tid_backup_fail -}; - -namespace { - -const string_map_type short_options = { -}; - -const string_map_type long_options = { - {"bin-dir", "bin-dir"}, {"dir", "dir"} - , {"home-dir", "home-dir"}, {"action", "action"} -}; - -const QSet options_has_param = { - {"bin-dir", "dir", "home-dir", "action"} -}; - -// separate home for each test -QString home; -QString vault_dir = os::path::join(home, ".vault"); -QString global_mod_dir = os::path::join(home, ".units"); -std::unique_ptr vlt; - -std::function setup(test_ids id) -{ - reinitContext(QString::number(id)); - home = str(context["home"]); - if (os::path::exists(home)) - error::raise({{"dir", home}, {"msg", "Shouldn't exists"}}); - - if (!os::mkdir(home)) - error::raise({{"dir", home}, {"msg", "Can't create"}}); - vault_dir = os::path::join(home, ".vault"); - global_mod_dir = os::path::join(home, ".units"); - vlt.reset(new vault::Vault(vault_dir)); - - vault::config::global()->setUnitsDir(global_mod_dir); - os::rmtree(global_mod_dir); - os::mkdir(global_mod_dir); - - return []() { os::rmtree(home); }; -} - -} // namespace - -void vault_init() -{ - QVariantMap git_cfg = {{"user.name", "NAME"}, {"user.email", "email@domain.to"}}; - vlt->init(git_cfg); - ensure(S_("No vault dir", vault_dir), os::path::isDir(vault_dir)); - ensure(S_("Vault doesn't exists", vault_dir), vlt->exists()); - ensure(S_("Vault is invalid", vault_dir), !vlt->isInvalid()); -} - -template<> template<> -void object::test() -{ - auto on_exit = setup(tid_init); - vault_init(); - on_exit(); -} - - -template<> template<> -void object::test() -{ - auto on_exit = setup(tid_config_global); - register_unit(vault_dir, "unit1", true); - QString unit1_fname = os::path::join(global_mod_dir, "unit1.json"); - ensure("unit 1 global config", os::path::isFile(unit1_fname)); - - QMap units = vault::config::global()->units(); - int mod_count = 0; - ensure("Unit in config", units.contains("unit1")); - mod_count += units.size(); - ensure("One unit/member", mod_count == 1); - - register_unit(vault_dir, "unit2", true); - units = vault::config::global()->units(); - mod_count = 0; - QString unit2_fname = os::path::join(global_mod_dir, "unit2.json"); - ensure("unit 2 global config", os::path::isFile(unit2_fname)); - mod_count += units.size(); - ensure("Unit2 in config", units.contains("unit2")); - ensure("One unit/member", mod_count == 2); - ensure("unit 1 global config", os::path::isFile(unit1_fname)); - - vault::Vault::execute({{"action", "unregister"}, {"global", true}, {"unit", "unit1"}}); - vault::Vault::execute({{"action", "unregister"}, {"global", true}, {"unit", "unit2"}}); - units = vault::config::global()->units(); - ensure("global config is removed", !os::path::exists(unit1_fname)); - ensure("no unit1 in global config", !units.contains("unit1")); - ensure("no unit2 in global config", !units.contains("unit2")); - on_exit(); -} - -template<> template<> -void object::test() -{ - auto on_exit = setup(tid_config_local); - vault_init(); - register_unit(vault_dir, "unit1", false); - QString config_dir = vault::config::units_path(vault_dir); - vault::config::Config config(config_dir); - ensure("unit1 config file", os::path::isFile(config.path("unit1"))); - QMap units = vlt->config().units(); - ensure("no unit1 in vault config", units.contains("unit1")); - - vault::Vault::execute({{"action", "unregister"}, {"vault", vault_dir}, {"unit", "unit1"}}); - units = vlt->config().units(); - ensure("no unit1 in vault config", !units.contains("unit1")); - on_exit(); -}; - -template<> template<> -void object::test() -{ - auto on_exit = setup(tid_config_update); - os::rmtree(home); - os::mkdir(home); - vault_init(); - register_unit(vault_dir, "unit1", true); - QMap units = vault::config::global()->units(); - ensure("no unit1 in global config", units.contains("unit1")); - - register_unit(vault_dir, "unit2", false); - vault::config::Vault config = vlt->config(); - units = config.units(); - ensure("no unit2 in vault config", units.contains("unit2")); - config.update(vault::config::global()->units()); - - units = vlt->config().units(); - ensure("no unit1 in vault config", units.contains("unit1")); - ensure("local unit2 should not be removed", units.contains("unit2")); - on_exit(); -} - -void do_backup() -{ - bool is_started = false, is_failed = false; - vlt->backup(home, {}, "", [&](const QString &, const QString &status) { - if (status == "fail") - is_failed = true; - else if (status == "begin") - is_started = true; - }); - ensure("backup was not started", is_started); - ensure("backup is failed", !is_failed); -} - -void do_restore() -{ - bool is_started = false, is_failed = false; - ensure("no snapshot", !vlt->snapshots().isEmpty()); - vlt->restore(vlt->snapshots().last(), home, {}, [&](const QString &, const QString &status) { - if (status == "fail") - is_failed = true; - else if (status == "begin") - is_started = true; - }); - ensure("backup was not started", is_started); - ensure("backup is failed", !is_failed); -} - -template<> template<> -void object::test() -{ - auto on_exit = setup(tid_simple_blobs); - os::rmtree(home); - os::mkdir(home); - vault_init(); - register_unit(vault_dir, "unit1", false); - QMap units = vlt->config().units(); - ensure("no unit1 in vault config", units.contains("unit1")); - - auto unit1_dir = str(get(context, "unit1_dir")); - mktree(unit1_tree, unit1_dir); - auto ftree_git_before_export = get_ftree(unit1_dir); - - ensure("No snapshots yet", vlt->snapshots().length() == 0); - do_backup(); - ensure("Added 1 snapshot", vlt->snapshots().length() == 1); - auto ftree_git_after_export = get_ftree(unit1_dir); - ensure_trees_equal("Src is modified?" - , ftree_git_before_export - , get_ftree(unit1_dir)); - - vault::Vault::UnitPath unit1_vault = vlt->unitPath("unit1"); - QString unit1_vault_path = os::path::canonical(unit1_vault.bin); - ensure(S_("dir is not created", unit1_vault_path) - , os::path::isDir(unit1_vault_path)); - QString unit1_vault_blob = os::path::join(unit1_vault_path, "unit1" - , "binaries", "b1"); - ensure(S_("should be symlink", unit1_vault_blob) - , os::path::isSymLink(unit1_vault_blob)); - - os::rmtree(unit1_dir); - ensure(AT, !os::path::exists(unit1_dir)); - do_restore(); - ensure_trees_equal("Src is not restored?" - , ftree_git_before_export - , get_ftree(unit1_dir)); - - on_exit(); -} - -template<> template<> -void object::test() -{ - auto on_exit = setup(tid_clear); - os::rmtree(home); - - // valid vault - os::mkdir(home); - vault_init(); - ensure("No vault before", os::path::exists(vlt->root())); - ensure("W/o params do nothing", !vlt->clear(QVariantMap())); - ensure("Vault should not be removed", os::path::exists(vlt->root())); - ensure("Should destroy valid valut", vlt->clear({{"destroy", true}})); - ensure("Vault should be removed", !os::path::exists(vlt->root())); - - // invalid vault - ensure(os::mkdir(vault_dir)); - ensure("Should not destroy invalid vault", !vlt->clear({{"destroy", true}})); - ensure("Invalid vault should not be removed", os::path::exists(vlt->root())); - ensure("Should destroy invalid vault", vlt->clear({{"destroy", true}, {"clear_invalid", true}})); - ensure("Invalid vault should be removed", !os::path::exists(vlt->root())); - - // vault with snapshots - os::mkdir(home); - vault_init(); - register_unit(vault_dir, "unit1", false); - - QString unit1_dir = os::path::join(home, "unit1"); - os::mkdir(unit1_dir); - QString unit1_blob = os::path::join(unit1_dir, "blob1"); - os::write_file(unit1_blob, "1\n2\n3\n"); - ensure("No snapshots yet", vlt->snapshots().length() == 0); - do_backup(); - ensure("Added 1 snapshot", vlt->snapshots().length() == 1); - ensure("Should not destroy vault with snapshots", !vlt->clear({{"destroy", true}})); - ensure("Should destroy vault with snapshots", vlt->clear({{"destroy", true}, {"ignore_snapshots", true}})); - ensure("Vault should be removed", !os::path::exists(vlt->root())); - - on_exit(); -} - - -template<> template<> -void object::test() -{ - auto on_exit = setup(tid_cli_backup_restore_several_units); - os::rmtree(home); - os::mkdir(home); - vault_init(); - register_unit(vault_dir, "unit1", false); - register_unit(vault_dir, "unit2", false); - auto rc = vault::Vault::execute({{"action", "export"} - , {"vault", vault_dir} - , {"home", home} - , {"unit", "unit1,unit2"}}); - ensure_eq("Should succeed", rc, 0); - on_exit(); -} - -template<> template<> -void object::test() -{ - using vault::Vault; - auto on_exit = setup(tid_backup_fail); - auto describe = []() { - subprocess::Process ps; - ps.setWorkingDirectory(vault_dir); - ps.start("git", {"describe", "--tags", "--exact-match"}); - return std::move(ps); - }; - auto last_snapshot = []() { - return vlt->snapshots().last().name(); - }; - os::rmtree(home); - os::mkdir(home); - vault_init(); - register_unit(vault_dir, "unit1", false); - register_unit(vault_dir, "unit2", false); - auto rc = Vault::execute({{"action", "export"} - , {"vault", vault_dir} - , {"home", home} - , {"unit", "unit1,unit2"}}); - ensure_eq("These units should proceed", rc, 0); - - auto snap1 = last_snapshot(); - - register_unit(vault_dir, "unit_fail", false); - rc = Vault::execute({{"action", "export"} - , {"vault", vault_dir} - , {"home", home} - , {"unit", "unit1,unit2,unit_fail"}}); - ensure_eq("With failed unit it should fail", rc, 1); - - auto ps = describe(); - ensure("Git is not found", ps.wait(10)); - ensure_eq("There should be a previous tag on top", ps.rc(), 0); - ensure_eq("Should be the same snapshot as before", snap1, last_snapshot()); - on_exit(); -} - -} diff --git a/tests/vault_context.hpp b/tests/vault_context.hpp deleted file mode 100644 index 4e454b5..0000000 --- a/tests/vault_context.hpp +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef _VAULT_TESTS_VAULT_CONTEXT_HPP_ -#define _VAULT_TESTS_VAULT_CONTEXT_HPP_ - -#include "tests_common.hpp" - -#include -#include - -#include - -#include - -namespace os = qtaround::os; -namespace error = qtaround::error; -namespace util = qtaround::util; - -namespace { - -using qtaround::subprocess::Process; - -QSet get_ftree(QString const &root) -{ - Process ps; - ps.setWorkingDirectory(root); - auto ftree = filterEmpty(str(ps.check_output("find", {"."})).split("\n")); - ftree.sort(); - return QSet::fromList(ftree); -} - -void ensure_trees_equal(QString const &msg - , QSet const &before - , QSet const &after) -{ - using tut::ensure_eq; - auto before_wo_after = before - after; - auto after_wo_before = after - before; - // compare to see difference on failure - ensure_eq(S_(msg + ": something is appeared") - , after_wo_before, QSet()); - ensure_eq(S_(msg, ": something was removed") - , before_wo_after, QSet()); -} - -QVariant mktree(QVariantMap const &tree, QString const &root) -{ - using tut::ensure; - auto fn = [](QVariant const &path_v, QVariant const &key, QVariant const &data) { - auto path = str(path_v); - if (!key.isValid()) { - if (!os::path::isDir(path)) - os::mkdir(path); - return path; - } - auto name = str(key); - - auto cur_path = os::path::join(path, name); - if (hasType(data, QMetaType::QVariantMap)) { - os::mkdir(cur_path); - ensure("Dir doesn't exists", os::path::isDir(cur_path)); - } else if (hasType(data, QMetaType::QString)) { - os::write_file(cur_path, str(data)); - ensure("File is written", os::path::isFile(cur_path)); - } - return cur_path; - }; - return util::visit(fn, tree, root); -} - -QVariantMap initContext(QString const &home_subdir = "") -{ - QVariantMap context; - auto home = os::environ("VAULT_TEST_TMP_DIR"); - if (home.isEmpty()) - home = os::mkTemp({{"dir", true}}); - - if (home.isEmpty()) - error::raise({{"msg", "Empty tests home path"}}); - - if (home == ".." || home == "." || home == os::home()) - error::raise({{"msg", "Can't use directory"}, {"dir", home }}); - - if (!(os::path::isDir(home) || os::mkdir(home, {{"parent", true}}))) - error::raise({{"msg", "Can't create tmp dir"}, {"dir", home}}); - - if (!home_subdir.isEmpty()) - home = os::path::join(home, home_subdir); - - auto config_dir = os::environ("VAULT_GLOBAL_CONFIG_DIR"); - // global config_dir should be set from environment, it will be - // used instead of standard global config dir - if (config_dir.isEmpty()) - error::raise({{"msg", "Need own global config dir for testing"}}); - - context = { - {"home", home} - , {"config_dir", config_dir} - , {"vault_dir", os::path::join(home, ".vault")} - , {"unit1_dir", os::path::join(home, "unit1")} - , {"unit2_dir", os::path::join(home, "unit2")} - , {"unit1" - , map({{"home", map({{"bin", os::path::join("unit1", "binaries")}, - {"data", os::path::join("unit1", "data")}})}})} - , {"unit2" - , map({{"home", map({{"bin", os::path::join("unit2", "unit2_binaries")}, - {"data", os::path::join("unit2", "unit2_data")}})}})} - }; - return context; -} - -QVariantMap context = initContext(); - -void reinitContext(QString const &home_subdir) -{ - context = initContext(home_subdir); -}; - -const QVariantMap unit1_tree = { - {"data", map({{"f1", "data1"}})}, - {"binaries", map({{"b1", "bin data"}, {"b2", "bin data 2"}})} -}; - -const QVariantMap unit2_tree = { - {"unit2_data", map({{"f2", "data2"}, {"f3", "data3"}})}, - {"unit2_binaries", map({{"b1", "bin data"}, {"b2", "bin data 2"}})} -}; - -} - -int register_unit(QString const &vault_dir, const QString &name, bool is_global); - -#endif // _VAULT_TESTS_VAULT_CONTEXT_HPP_ diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt deleted file mode 100644 index 3f403c8..0000000 --- a/tools/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -configure_file(vault-gc.service.in vault-gc.service @ONLY) - -install( - PROGRAMS git-vault-gc gc-default git-vault-snapshot-units git-vault-export - DESTINATION ${TOOLS_DIR} - ) - -install( - FILES git-vault-rebase-generate.awk git-vault-rebase-prepare.awk vault-misc - DESTINATION ${TOOLS_DIR} - ) diff --git a/tools/gc-default b/tools/gc-default deleted file mode 100644 index 9c357f9..0000000 --- a/tools/gc-default +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -/usr/bin/vault -H $HOME -V $HOME/.vault -a gc diff --git a/tools/git-vault-export b/tools/git-vault-export deleted file mode 100755 index d95db28..0000000 --- a/tools/git-vault-export +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -trace () { - echo "`basename $0`: ${@:1}" 1>&2; -} - -error() { - trace $@ - exit 1 -} - -[ $# -eq 2 ] || error "Usage: $0 snapshot dst_dir" - -SNAP=$1 -DST=$2 - -if [ "${SNAP:0:1}" != ">" ]; then - SNAP=">$SNAP" -fi - -git rev-parse --show-toplevel || error "Not a git dir $(pwd)" -git rev-parse "$SNAP" >/dev/null || error "There is no snapshot $SNAP" -[ -d $DST ] || error "There is no destination dir $DST" - -# only $DST itself is expected -COUNT=$(find $DST -maxdepth 1 '!' -name '.' | wc -l) -if [ "x$COUNT" != "x1" ]; then - error "Dst dir $DST should be empty, found $COUNT entries" -fi - -trace "Export $SNAP to the $DST" - -GIT_DIR=$(pwd) -(git archive --format=tar "$SNAP" | tar -C $DST -xf -) || \ - error "Export of $SNAP to the $DST is failed" - -find $DST -type l | grep '/blobs/' | while read -r LINK -do - NAME=$(readlink "$LINK") - # match minimal relative blob ref (path inside the tree is unit/blobs/link) - if [[ $NAME =~ \.\./\.\./\.git/blobs/ ]]; then - FNAME=$(basename $NAME) - DNAME="$GIT_DIR/.git/blobs/$(basename $(dirname $NAME))" - [ -d $DNAME ] || error "There is no blob dir $DNAME for $LINK" - FNAME="$DNAME/$FNAME" - [ -f $FNAME ] || error "There is no blob file $FNAME for $LINK" - unlink "$LINK" || error "Can't unlink $LINK" - cp $FNAME "$LINK" || error "Can't copy $FNAME to $LINK" - fi -done diff --git a/tools/git-vault-gc b/tools/git-vault-gc deleted file mode 100755 index 8f4d93f..0000000 --- a/tools/git-vault-gc +++ /dev/null @@ -1,145 +0,0 @@ -#!/bin/bash - -function error { - echo "`basename $0`: Error: ${@:1}" 1>&2; - exit 1 -} - -ARGS=$(getopt -o fdD -- "$@"); - -if [ $? -ne 0 ]; then - exit 1 -fi - -force=false -dump=false -dump_intention=false - -while true; do - case "$1" in - -f) - force=true - shift; - ;; - -d) - dump=true - shift; - ;; - -D) - dump_intention=true - shift; - ;; - *) - if [ $# -eq 0 ]; then - break; - fi - error "Unknown option $1" - break; - esac -done - -src=$(dirname $0) -src=$(cd $src;pwd) - -root=$(git rev-parse --show-toplevel) -rc=$? - -if [ $rc -ne 0 ] || [ "x$root" == "x" ]; then - error "Not a git $root" -fi - -test -d "$root" || error "Not a dir $root" -test -e "$root/.vault" || error "Not a vault $root" - -cd $root || error "Can't enter $root" - -cmd_file=$(mktemp) -git log --pretty=format:%H$%d$%s \ - | gawk -f $src/git-vault-rebase-prepare.awk \ - | tac > $cmd_file -trap "rm $cmd_file" EXIT - -function gen_cmd { - cat $cmd_file | gawk -f $src/git-vault-rebase-generate.awk -} - -function git_gc { - echo "GC" - git prune - git gc --aggressive - echo "PRUNE+" - git prune -} - -function git_clear_reflog { - echo "CLEAR REFLOG" - git reflog expire --expire=now --all || error "clearing reflog" -} - -function git_rm_dangling_blobs { - echo "REMOVING DANGLING BLOBS" - for obj in $(git fsck --unreachable master \ - | grep '^unreachable blob' \ - | sed 's/unreachable blob //'); do - for blob in $(git show $obj \ - | head -n 1 \ - | grep '\.\./\.git/blobs' \ - | sed 's:^[./]*\.git/blobs:.git/blobs:'); do - echo "Orphan $blob" - (test -f $blob && (rm $blob -f || echo "Can't remove $blob")) \ - || echo "No such blob $blob" - done - done -} - -function git_prune_all_unreferenced { - git_clear_reflog - git_rm_dangling_blobs - git_gc -} - -if ($dump || $dump_intention); then - $dump_intention && cat $cmd_file - $dump && gen_cmd - exit 0 -fi - -if ! grep '^\(old_tag\|skip\)' $cmd_file; then - echo "There is no need in tree clean-up for the $root" - if ! $force; then - echo "Just checking for dangling blobs and doing gc" - git_prune_all_unreferenced - exit 0 - fi - echo "Forcing tree clean-up and gc" -fi - -cmd=$(gen_cmd) - -function rollback { - echo "ROLLBACK" - git reset --hard - git clean -fd - git checkout master - git branch -D migrate - for t in $(git tag | grep '^migrate/'); do - git tag -d "$t" - done - git_gc - error "during migration" -} - -export -f rollback - -eval "$cmd" || error "$cmd" - -echo "REPLACE MASTER" -# do it separetely to be on the safe side and keep old master until the last moment -(git branch -m migrate migrated && \ - git branch -m master old-master && \ - git branch -m migrated master && \ - git branch -D old-master) || error "replacing master" - -git_prune_all_unreferenced - -echo "OK" diff --git a/tools/git-vault-move b/tools/git-vault-move deleted file mode 100755 index f49b044..0000000 --- a/tools/git-vault-move +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/bash - -src=$(dirname $0) -src=$(cd $src;pwd) -source $src/vault-misc $src - -init_root_and_enter -ensure_param_count_exit_usage $# 1 "" $@ - -dst=$1 - -out_of_tree="out" -in_the_tree="in" -src_location= -src= -dotgit=$(readlink -f $root/.git) - -if [ -f $dotgit ]; then - re="s|gitdir: \(.*\)$|\1|" - src=$(cat $root/.git | sed -e "$re") - [ -d $src ] || error 42 "Current src isn't a dir: $src" - src_location=$out_of_tree - trace "External source: $src" -elif [ -d $dotgit ]; then - src_location=$in_the_tree - src=$dotgit - trace "Internal source: $src" -else - error 10 "Not dir|file $src/.git" -fi - -dst=$(readlink -f $dst) -src=$(readlink -f $src) - -[ "$dst" == "$src" ] && error 23 "$src=$dst" - -dst_location= -if [ "$dotgit" == "$dst" ]; then - trace "Moving .git into the tree" - [ -f "$dotgit" ] || error 48 "Destination $dotgit should be file" - dst_location=$in_the_tree -else - [ -e "$dst" ] && error 22 "Dst should not exist: $dst" - dst_location=$out_of_tree -fi - -for f in "$dotgit.old" "$dotgit.new"; do - [ -e "$f" ] && (rm "$f" || error 15 "Can't rm $f") -done - -if [ $dst_location == $out_of_tree ]; then - mkdir -p $dst || error 24 "Can't create dst dir: $dst" -fi - -for d in "$root" "$src" "$dst" "$dotgit"; do - [ -w "$d" ] || error 29 "'$d' is not writable" -done - -src_dev=$(stat -c "%d" $src) -dst_dev=$(stat -c "%d" $dst) -is_same_dev=false -if [ $src_dev -eq $dst_dev ]; then - trace "Same device" - is_same_dev=true -fi - -trace "Going to do: $src->$dst, .git=$dotgit" - -function rollback_dotgit { - trace "Rollback .git" - if [ $dst_location == $in_the_tree ]; then - [ -d "$dotgit" ] && rmdir "$dotgit" - [ -e "$dotgit.old" ] && mv "$dotgit.old" "$dotgit" - [ -e "$dotgit.new" ] && rm "$dotgit.new" - fi - error $@ -} - -function prepare_dotgit { - if [ -e $dotgit ]; then - mv $dotgit $dotgit.old || error 13 "Can't mv $dotgit $dotgit.old" - fi - echo "gitdir: $dst" > $dotgit.new || rollback_dotgit 31 "Can't write gitdir to $dotgit.new" -} - -if [ $dst_location == $in_the_tree ]; then - prepare_dotgit - mkdir $dotgit || rollback_dotgit 32 "Can't create dir $gitdir" -fi - -([ -d "$src" ] && [ -d "$dst" ]) || rollback_dotgit 33 "$src and $dst should be dirs" - -cmd=false -if $is_same_dev; then - trace "Same device, move" - cmd="mv -T '$src' '$dst'" -else - trace "Different devices, copy" - cmd="cp -rTLpuf '$src' '$dst'" -fi - -trace "Command: $cmd" - -function rollback { - msg="$1. Aux info:" - if $is_same_dev; then - msg="$msg Can't move $src, check $dst" - else - if ! rm -rf "$dst"; then - msg="$msg Can't rm $dst" - fi - fi - rollback_dotgit 55 $msg -} - -if eval "$cmd"; then - if [ $dst_location == $out_of_tree ]; then - prepare_dotgit - fi - mv $dotgit.new $dotgit || rollback "Failed to mv $dotgit.new $dotgit" - if [ $src_location == $out_of_tree ] && ! $is_same_dev; then - if [ -d "$src" ]; then - rm -rf "$src" || warn "Can't remove $src" - else - warn "Source should still exists but it doesn't: $src" - fi - fi - [ -e $dotgit.old ] && rm $dotgit.old -rf -else - rollback "Failed to execute $cmd" - exit 1 # just to be sure it exits -fi -trace "Successfully moved $src->$dst" diff --git a/tools/git-vault-rebase-generate.awk b/tools/git-vault-rebase-generate.awk deleted file mode 100644 index 4f6c1e6..0000000 --- a/tools/git-vault-rebase-generate.awk +++ /dev/null @@ -1,113 +0,0 @@ -BEGIN { - ok=0 - # prepare empty arrays - split("", commits); - split("", commands); - split("", old_tags); - split("", move_tags); -} - -function array_clear(arr) { - delete arr; - split("", arr); -} - -# buggy gawk 3.1.5 used in mer -# see https://lists.gnu.org/archive/html/bug-gnu-utils/2008-03/msg00029.html -# so pass also len -function push(arr, len, data) { - arr[len + 1] = data; -} - -function push_command(cmd) { - push(commands, length(commands), cmd); -} - -function push_step(message) { - push_command("echo 'STEP:" message "'"); -} - -function prepare_commands() { - for (name in commits) { - split(commits[name], ids, SUBSEP); - push_step("data:" name); - if (length(ids) == 1) { - push_command("git cherry-pick --allow-empty " ids[1]); - } else { - cmd="git cherry-pick --allow-empty " ids[1]; - for (i = 1; i <= length(ids); i++) { - cmd = cmd " && git cherry-pick --no-commit " ids[i] \ - " && git commit --no-edit --amend --allow-empty"; - } - push_command(cmd); - } - } - array_clear(commits); - - # tags - id = $2 - tag = $3 - if (length(old_tags) != 0) { - push_step("squash:" tag " with " length(old_tags) " old tags"); - for (i = 1; i <= length(old_tags); i++) { - push_command(old_tags[i]); - } - array_clear(old_tags); - push_command("git cherry-pick --no-commit " id); - push_command("git commit --no-edit --amend --allow-empty"); - } else { - push_step("tag:" tag); - push_command("git cherry-pick --allow-empty " id); - } - tmp_tag = "migrate/" tag - push_command(sprintf("git tag -f '%s'", tmp_tag)); - push_command("(git notes copy " id " HEAD || :)"); - cmd = sprintf("(git tag -f '%s' '%s' && git tag -d '%s')", tag, tmp_tag, tmp_tag); - push(move_tags, length(move_tags), cmd); -} - -$1 == "add" { - if (commits[$3] != "") { - commits[$3] = commits[$3] SUBSEP $2; - } else { - commits[$3] = $2; - } -} - -$1 == "old_tag" { - push_step("old_tag:" $3); - if (length(old_tags) == 0) { - push(old_tags, length(old_tags), "git cherry-pick --allow-empty " $2); - } else { - push(old_tags, length(old_tags), "git cherry-pick --no-commit " $2); - push(old_tags, length(old_tags), "git commit --no-edit --amend --allow-empty"); - } -} - -$1 == "tag" { - prepare_commands(); -} - -$1 == "copy" { - push_step("copy:" $2); - push_command("git cherry-pick --allow-empty " $2); -} - -$1 == "start" { - push_command("(git checkout master && (git reset --hard && git clean -fd))"); - push_command("git checkout -b migrate " $2); -} - -END { - res = "((" - sep = "" - for (i = 1; i <= length(commands); i++) { - res = res sep commands[i]; - sep = " && \\\n\t" - } - res = res ") || rollback)" - for (i = 1; i <= length(move_tags); i++) { - res = res sep move_tags[i]; - } - print res; -} diff --git a/tools/git-vault-rebase-prepare.awk b/tools/git-vault-rebase-prepare.awk deleted file mode 100644 index d294cb5..0000000 --- a/tools/git-vault-rebase-prepare.awk +++ /dev/null @@ -1,51 +0,0 @@ -BEGIN { - # expects the list of git log entries in the format %H$%d$%s - # so fields are [hash, csv of refs, subject] - FS="$"; - date_tag_re = /^[0-9]+-[0-9]+-[0-9]+T[0-9]+-[0-9]+-.*/; -} - -# skipping unit add/remove commit - deprecated -$2 == "" && substr($3, 1, 1) ~ "[+-]" { - print "skip", $1 -} - -# unit backup commit -$2 == "" && substr($3, 1, 1) == ">" { - print "add", $1, $3; -} - -$2 != "" && $3 !~ date_tag_re && $3 != "anchor" { - print "copy", $1 -} - -# backup tag commit subject starts with the iso date -$2 != "" && $3 ~ date_tag_re { - split($2, refs, ","); - is_found=0 - for (i in refs) { - # backup tag is '>' + transformed iso date - if (match(refs[i], /[(]?tag: (>.+Z)[)]?/, found) != 0) { - tag=found[1]; - print "tag", $1, tag - is_found=1 - break - } - } - # tag was removed, so this backup commit should be - # squashed/removed. Unit commits will be squashed with the - # following ones (if any) or removed - if (!is_found) { - print "old_tag", $1 - } -} - -# branch should be grown starting from the anchor -$3 == "anchor" { - print "start", $1 -} - -# some commit w/o any refs - for the vault this is removed backup -$2 == "" && $3 ~ date_tag_re { - print "old_tag", $1 -} diff --git a/tools/git-vault-root b/tools/git-vault-root deleted file mode 100755 index b2da3c8..0000000 --- a/tools/git-vault-root +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -src=$(dirname $0) -src=$(cd $src;pwd) -source $src/vault-misc -get_root $(pwd) diff --git a/tools/git-vault-snapshot-units b/tools/git-vault-snapshot-units deleted file mode 100755 index e6d392a..0000000 --- a/tools/git-vault-snapshot-units +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -src=$(dirname $0) -src=$(cd $src;pwd) -source $src/vault-misc || exit 1 - -ensure_param_count_exit_usage $# 1 "" -tag=">$1" - -tag_describe() { - git describe --tags "$1" || error 33 "No tag '$1'" -} - -tag=$(tag_describe "$tag") -tag_prev=$((tag_describe "$tag^" | sed -e 's|\(.*\)-[0-9]*-g[0-9a-f]*|\1|') || error 44 "No previous tag") -units= -for c in $(git log --format=%s "$tag_prev..$tag" | grep '^>'); do - unit=$(echo $c | sed -e 's|^>||') - if [[ "x$units" != "x" ]]; then - units+=" $unit" - else - units=$unit - fi -done -echo $units | tr " " "\n" | sort -u | grep -v "^$" - diff --git a/tools/git-vault-sync b/tools/git-vault-sync deleted file mode 100755 index d19af6d..0000000 --- a/tools/git-vault-sync +++ /dev/null @@ -1,161 +0,0 @@ -#!/bin/bash - -src=$(dirname $0) -src=$(cd $src;pwd) -source $src/vault-misc $src - -init_root_and_enter - -full_uri=$1 - -if [ "x$full_uri" == "x" ]; then - full_uri=$(git config --get remote.origin.url) -fi - -src_repo= -port= -user= -host= -src_type= - -split_git_uri $full_uri - -sync_tool= -cp_tool= - -has_rsync=0 -if which rsync 1>/dev/null; then has_rsync=1; fi - -case "$src_type" in - ssh) - trace "SRC:user=$user,host=$host,port=$port,path=$src_repo" - has_scp=0 - if which scp 1>/dev/null; then has_scp=1; fi - if [ $has_scp ]; then - if [ $has_rsync ]; then - sync_tool=rsync - else - sync_tool=scp - fi - cp_tool=scp - elif [ $has_rsync ]; then - sync_tool=rsync - cp_tool=rsync - else - error 51 "No rsync, no scp" - fi - ;; - local) - trace "SRC:path=$src_repo" - if ! [ -d "$path" ]; then - error 3 "Local path doesn't exists: $path" - fi - if [ $has_rsync ]; then - sync_tool=rsync - else - sync_tool=cp - fi - cp_tool=cp - ;; - *) - error 4 "Unsupported uri: $uri" -esac - -trace "Tools: sync=$sync_tool, cp=$cp_tool" - -if [ $tree_version -ge 3 ]; then - trace "Sync .git/info" -fi - -case $sync_tool in - rsync) - if [ $src_type == "local" ]; then - sync_cmd="$sync_tool -avz" - src_prefix=$src_repo/ - else - src_prefix=$user@$host:$src_repo/ - if [ "x$port" == "x" ]; then - sync_cmd='$sync_tool -avz' - else - sync_cmd="$sync_tool -avz -e 'ssh -p $port'" - fi - fi - ;; - scp) - src_prefix=$user@$host:$src_repo/ - if [ "x$port" == "x" ]; then - sync_cmd='scp' - else - sync_cmd="scp -r -p -P $port" - fi - - ;; - cp) - src_prefix=$src_repo/ - sync_cmd="cp -rLpuf" - ;; - *) - -esac - -if [ "x$sync_cmd" == "x" ]; then - error 66 "No sync command defined" -fi - -cp_cmd= - -case $cp_tool in - rsync) - if [ $src_type == "local" ]; then - cp_cmd="$cp_tool -avz" - src_prefix="$src_repo/" - else - src_prefix=$user@$host:$src_repo/ - if [ "x$port" == "x" ]; then - cp_cmd='$sync_tool -avz' - else - cp_cmd="$sync_tool -avz -e 'ssh -p $port'" - fi - fi - ;; - scp) - src_prefix=$user@$host:$src_repo/ - if [ "x$port" == "x" ]; then - cp_cmd='scp' - else - cp_cmd="scp -r -p -P $port" - fi - - ;; - cp) - src_prefix=$src_repo/ - cp_cmd="cp -rLpuf" - ;; - *) - esac - -if [ "x$cp_cmd" == "x" ]; then - error 66 "No cp command defined" -fi - -cmd=$(get_vault_lock_cmd "$cmd $sync_cmd ${src_prefix}.git/blobs/. .git/blobs/") -trace "Sync blobs: $cmd" -eval "$cmd" || error 27 "Error executing '$cmd'" - -if ! git config user.name 1>/dev/null; then - tmp_config=$(mktemp) - trap "rm $tmp_config" EXIT - cmd=$(get_vault_lock_cmd "$cp_cmd ${src_prefix}.git/config $tmp_config") - trace "Copy config through $tmp_config" - eval "$cmd" || error 27 "Error executing '$cmd'" - git config user.name $(git config --file $tmp_config user.name) - git config user.email $(git config --file $tmp_config user.email) - rm $tmp_config; trap "echo" EXIT -fi -git config status.showUntrackedFiles all -cmd=$(get_vault_lock_cmd "$cp_cmd ${src_prefix}.git/info $(repo_version_path ${src_prefix}) $(units_path ${src_prefix}) .git") -trace "Duplicate storage metadata: $cmd" -eval "$cmd" || error 27 "Error executing '$cmd'" -cmd=$(get_vault_lock_cmd "$sync_cmd $(units_path ${src_prefix}) $(units_path $root)") -trace "Sync units : $cmd" -eval "$cmd" || error 27 "Error executing '$cmd'" diff --git a/tools/vault-gc.service.in b/tools/vault-gc.service.in deleted file mode 100644 index b9d435a..0000000 --- a/tools/vault-gc.service.in +++ /dev/null @@ -1,5 +0,0 @@ -[Unit] -Description=Vault garbage collection - -[Service] -ExecStart=@prefix@/libexec/vault/gc-default diff --git a/tools/vault-misc b/tools/vault-misc deleted file mode 100644 index 862bf27..0000000 --- a/tools/vault-misc +++ /dev/null @@ -1,245 +0,0 @@ -#!/bin/bash - -master_branch=vault -scripts_branch=scripts -root_version=3 -root= - -export TOP_PID=$$ - -is_trace=false -if [ "x$VAULT_TRACE" != "x" ]; then - is_trace=true -fi - -function trace { - if $is_trace; then - echo "`basename $0`: ${@:1}" 1>&2; - fi -} - - -normal_cleanup="true" -failed_cleanup="true" -is_failed=false - -function on_normal_exit -{ - if $is_failed; then - exit 1 - else - trace "Normal exit from $BASHPID" - trace "Exec: $normal_cleanup" - eval "$normal_cleanup" - exit 0 - fi -} - -is_exit_on_failure=true -is_expect_success=true -function on_failure -{ - if $is_expect_success; then - trace "Failure cleanup in $BASHPID" - trace "Exec: $failed_cleanup" - is_failed=true - eval "$failed_cleanup" - $is_exit_on_failure && exit 1 - else - trace "Failure is expected" - is_failed=true - fi -} -trap on_failure TERM -trap on_normal_exit EXIT -#trap on_failure ERR - -function warn { - echo "`basename $0`: Warning: ${@:1}" 1>&2; -} - -function error { - TOP_RC=$1 - echo "`basename $0`: Error #$1: ${@:2}" 1>&2; - if [ $BASHPID -ne $TOP_PID ]; then - trace "Not a top script" - is_exit_on_failure=false - on_failure - fi - warn "Killing $TOP_PID" - kill -s TERM $TOP_PID -} - -update_path () { - local my_path=$(dirname $1) - my_path=$(readlink -f $(cd $my_path;pwd)) - if ! (echo $PATH | grep "^$my_path:.*" 1>/dev/null); then - export PATH=$my_path:$PATH - fi - if [ "x$VAULT_LIB_DIR" != "x" ]; then - [ -d $VAULT_LIB_DIR ] || error 6 "No such dir $VAULT_LIB_DIR" - local lib_path=$(readlink -f $VAULT_LIB_DIR) - if [ "$my_path" != "$lib_path" ]; then - export PATH=$lib_path:$PATH - fi - fi - trace "SCRIPTS PATH: $PATH" -} -update_path $0 - -function ensure_param_count_op_exit_usage { - [ $# -ge 3 ] || error 22 "Call as Num#0 OP Num#1" - if ! [ $1 $2 $3 ]; then - local name=`basename $0` - echo "Expecting param count: $1 $2 $3" 1>&2; - echo "Params was: ${@:5}" 1>&2; - echo "Usage: $name $4" 1>&2; - exit $1 - fi -} - -function ensure_param_count_exit_usage { - ensure_param_count_op_exit_usage $1 -eq $2 ${@:3} -} - -function tree_version_path { - [ $@ ] || error 22 "Call with root" - echo $1/.vault -} - -function repo_version_path { - [ $@ ] || error 22 "Call with root" - echo $1/.git/vault.version -} - -function units_path { - [ $@ ] || error 22 "Call with root" - echo $1/.units/ -} - -function get_root { - current_root=$1 - while true; do - current_root=$(cd $current_root && git rev-parse --show-toplevel) - if [ $? -ne 0 ] || [ "x$current_root" == "x" ] || - ! [ -d "$current_root" ] ; then - error 1 "Not a git $1" - fi - if [ -f $current_root/.vault ]; then - echo $current_root - break - else - [ "$(readlink -f $current_root)" == "/" ] && - error 33 "Reached /, vault is not found" - current_root=$(dirname $current_root) - fi - done -} - -function init_root { - if [ "x$root" == "x" ]; then - root=$(get_root $(pwd)) - if [ $? -ne 0 ]; then - error $? "Not inside vault? $(pwd)" - fi - if [ "x$root" == "x" ]; then - error 54 "Root is empty" - fi - fi - version_file=$(tree_version_path $root) - test -f "$version_file" || error 44 "Not a vault tree $root?" - - tree_version=$(cat $version_file) - if [ "x$tree_version" == "x" ]; then - error 10 "Empty tree version for $root" - fi - trace "Tree version $tree_version" -} - -function init_root_and_enter { - init_root - cd $root || error 2 "Can't enter $root" -} - -function get_vid { - init_root - git config --file $root/.git/config vault.id -} - -function get_current_branch { - echo $(git rev-parse --abbrev-ref HEAD) -} - -function vault_exec { - init_root - local fname=$1 - local log_file=$root/.vault/logs/$2 - test -x $fname || error 77 "File is not an exec: $fname" - local cur_dir=$(pwd) - trace "Exec: ls -al $fname" - local out_file=$log_file-out.txt - local err_file=$log_file-err.txt - touch $out_file - touch $err_file - $fname 1>$out_file 2> $err_file || error $? "File execution is failed: $fname" - if [ "$(pwd)" != "$cur_dir" ]; then - error 54 "Executable changed cwd to $(pwd)" - fi -} - -function date_tag { - echo $(date +%Y-%m/%d/%Z/%H-%M/%S.%N) -} - -function unique_tag { - echo $(uuidgen) -} - -function units { - find .units -type f -name '*.json' -exec basename {} '.json' \; -} - -function split_git_uri { - local uri=$1 - trace "split $uri" - # parsing is too dumb now, it should be stricter - ssh_re='(ssh://)?((.*)@)?(.*[^\\]):([0-9]*)(.*)' - if [[ "$uri" =~ $ssh_re ]]; then - trace "Remote URI is ssh" - user="${BASH_REMATCH[3]}" - host="${BASH_REMATCH[4]}" - port="${BASH_REMATCH[5]}" - src_repo="${BASH_REMATCH[6]}" - src_type=ssh - elif [[ $uri =~ (file://)?(.*) ]]; then - trace "Assume URI is the local path" - path="${BASH_REMATCH[2]}" - src_repo=$path - src_type=local - fi - if [ "x$user" == "x" ]; then - user=$(whoami) - fi -} - -function get_data_dir { - ensure_param_count_exit_usage $# 2 "get_data_dir " - echo $1/$2/data -} - -function get_blobs_dir { - ensure_param_count_exit_usage $# 2 "get_blobs_dir " - echo $1/$2/blobs -} - -function get_snapshots { - ensure_param_count_exit_usage $# 1 "get_snapshots " - vault -a list-snapshots -V $1 -} - -vault_misc=1 -function get_vault_lock_cmd { - # wait for 30s - echo "flock -w 30 -x $root/.vault.lock $@" -} -export -f get_vault_lock_cmd diff --git a/vault-unit.pc.in b/vault-unit.pc.in deleted file mode 100644 index 80cedf7..0000000 --- a/vault-unit.pc.in +++ /dev/null @@ -1,9 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -libdir=${prefix}/@DST_LIB@ -includedir=${prefix}/include - -Name: vault-unit -Description: vault-unit library -Version: @VERSION@ -Libs: -lvault-unit -L${libdir} -Cflags: -I${includedir} \ No newline at end of file diff --git a/vault.pro b/vault.pro new file mode 100644 index 0000000..15f2766 --- /dev/null +++ b/vault.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs + +SUBDIRS = lib + +OTHER_FILES += rpm/*.spec