diff --git a/examples/UseVault.qml b/examples/UseVault.qml new file mode 100644 index 0000000..f96691e --- /dev/null +++ b/examples/UseVault.qml @@ -0,0 +1,92 @@ +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/include/vault/vault.hpp b/include/vault/vault.hpp index 83311dc..8c4cf00 100644 --- a/include/vault/vault.hpp +++ b/include/vault/vault.hpp @@ -102,6 +102,7 @@ class Vault 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); diff --git a/qml/Vault/vault.cpp b/qml/Vault/vault.cpp index 9dfc7cd..2cc9c8f 100644 --- a/qml/Vault/vault.cpp +++ b/qml/Vault/vault.cpp @@ -224,6 +224,19 @@ class Worker : public QObject } } + 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); @@ -419,4 +432,11 @@ Q_INVOKABLE void Vault::restoreUnit(const QString &snapshot, const QString &unit , 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 index 1a837e1..8fb345d 100644 --- a/qml/Vault/vault.hpp +++ b/qml/Vault/vault.hpp @@ -29,7 +29,8 @@ class Vault : public QObject ExportImportPrepare, ExportImportExecute, Data, - Maintenance + Maintenance, + ExportSnapshot } Q_ENUMS(Operation); @@ -67,6 +68,7 @@ class Vault : public QObject 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(); diff --git a/src/unit.cpp b/src/unit.cpp index a096b9a..9a3f51f 100644 --- a/src/unit.cpp +++ b/src/unit.cpp @@ -35,8 +35,6 @@ QVariantMap options_info , {"required", true}, {"has_param", true}})} , {"home-dir", map({{"short", "H"}, {"long", "home-dir"} , {"required", true}, {"has_param", true}})} - , {"name", map({{"short", "n"}, {"long", "name"} - , {"required", true}, {"has_param", true}})} , {"action", map({{"short", "a"}, {"long", "action"} , {"required", true}, {"has_param", true}})}}; diff --git a/src/vault.cpp b/src/vault.cpp index e3ec5ed..ff243d1 100644 --- a/src/vault.cpp +++ b/src/vault.cpp @@ -797,6 +797,18 @@ bool Vault::restoreUnit(const QString &home, const QString &unit, const Progress 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 */ @@ -842,7 +854,6 @@ void Unit::execScript(const QString &action) error::raise({{"msg", "Should be executable"}, {"script", script}}); } QStringList args = { "--action", action, - "--name", m_unit, "--dir", QDir(m_data).absolutePath(), "--bin-dir", QDir(m_blobs).absolutePath(), "--home-dir", m_home }; diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 9ca062e..3f403c8 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,7 +1,7 @@ configure_file(vault-gc.service.in vault-gc.service @ONLY) install( - PROGRAMS git-vault-gc gc-default git-vault-snapshot-units + PROGRAMS git-vault-gc gc-default git-vault-snapshot-units git-vault-export DESTINATION ${TOOLS_DIR} ) diff --git a/tools/git-vault-export b/tools/git-vault-export new file mode 100755 index 0000000..9607ff8 --- /dev/null +++ b/tools/git-vault-export @@ -0,0 +1,50 @@ +#!/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 -not -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