1 /** 2 Copyright: Copyright (c) 2019, Joakim Brännström. All rights reserved. 3 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 */ 6 module dsnapshot.cmdgroup.restore; 7 8 import logger = std.experimental.logger; 9 import std.algorithm : map, filter, canFind; 10 import std.array : empty, array; 11 import std.exception : collectException; 12 13 import dsnapshot.backend; 14 import dsnapshot.config : Config; 15 import dsnapshot.exception; 16 import dsnapshot.from; 17 import dsnapshot.layout_utils; 18 import dsnapshot.process; 19 import dsnapshot.types; 20 21 version (unittest) { 22 import unit_threaded.assertions; 23 } 24 25 int cmdRestore(SnapshotConfig[] snapshots, const Config.Restore conf) nothrow { 26 import dsnapshot.layout; 27 28 if (conf.name.value.empty) { 29 logger.error("No snapshot name specified (-s|--snapshot)").collectException; 30 return 1; 31 } 32 if (conf.restoreTo.empty) { 33 logger.error("No destination is specified (--dst)").collectException; 34 return 1; 35 } 36 37 foreach (snapshot; snapshots.filter!(a => a.name == conf.name.value)) { 38 try { 39 return restore(snapshot, conf); 40 } catch (SnapshotException e) { 41 e.errMsg.match!(a => a.print).collectException; 42 logger.error(e.msg).collectException; 43 } catch (Exception e) { 44 logger.error(e.msg).collectException; 45 break; 46 } 47 } 48 49 logger.errorf("No snapshot with the name %s found", conf.name.value).collectException; 50 logger.infof("Available snapshots are: %-(%s, %)", 51 snapshots.map!(a => a.name)).collectException; 52 return 1; 53 } 54 55 private: 56 57 int restore(SnapshotConfig snapshot, const Config.Restore rconf) { 58 auto backend = makeSyncBackend(snapshot); 59 60 auto crypt = makeCrypBackend(snapshot.crypt); 61 open(crypt, backend.flow); 62 scope (exit) 63 crypt.close; 64 65 // Extract an updated layout of the snapshots at the destination. 66 auto layout = backend.update(snapshot.layout); 67 logger.trace("Updated layout with information from destination: ", layout); 68 69 backend.restore(layout, snapshot, rconf.time, rconf.restoreTo); 70 71 return 0; 72 }