fix: backup merge

This commit is contained in:
lollipopkit
2024-01-27 21:11:40 +08:00
parent dacf8f0864
commit b08265221f
13 changed files with 115 additions and 130 deletions

View File

@@ -183,29 +183,22 @@ abstract final class ICloud {
}
static Future<void> sync() async {
var dlSuccess = false;
try {
final result = await download(relativePath: Paths.bakName);
if (result != null) {
throw result;
}
dlSuccess = true;
} catch (e, s) {
_logger.warning('Download backup failed', e, s);
}
if (!dlSuccess) {
await Backup.backup();
final uploadResult = await upload(relativePath: Paths.bakName);
if (uploadResult != null) {
_logger.warning('Upload backup failed: $uploadResult');
} else {
_logger.info('Upload backup success');
}
final result = await download(relativePath: Paths.bakName);
if (result != null) {
_logger.warning('Download backup failed: $result');
await backup();
return;
}
final dlFile = await File(await Paths.bak).readAsString();
final dlBak = await Computer.shared.start(Backup.fromJsonString, dlFile);
await dlBak.restore();
final dlFile = await File(await Paths.bak).readAsString();
final dlBak = await Computer.shared.start(Backup.fromJsonString, dlFile);
await dlBak.restore();
await backup();
}
static Future<void> backup() async {
await Backup.backup();
final uploadResult = await upload(relativePath: Paths.bakName);
if (uploadResult != null) {

View File

@@ -98,26 +98,19 @@ abstract final class Webdav {
static Future<void> sync() async {
final result = await download(relativePath: Paths.bakName);
if (result != null) {
_logger.warning('Download failed: $result');
await backup();
return;
}
final dlFile = await Computer.shared.start(
(message) async {
try {
final file = await File(message).readAsString();
final bak = Backup.fromJsonString(file);
return bak;
} catch (_) {
return null;
}
},
await Paths.bak,
);
if (dlFile == null) {
await backup();
return;
try {
final dlFile = await File(await Paths.bak).readAsString();
final dlBak = await Computer.shared.start(Backup.fromJsonString, dlFile);
await dlBak.restore();
} catch (e) {
_logger.warning('Restore failed: $e');
}
await dlFile.restore();
await backup();
}

View File

@@ -1,6 +1,7 @@
import 'dart:convert';
import 'dart:io';
import 'package:logging/logging.dart';
import 'package:toolbox/core/persistant_store.dart';
import 'package:toolbox/data/model/server/private_key_info.dart';
import 'package:toolbox/data/model/server/server_private_info.dart';
@@ -13,6 +14,8 @@ import 'package:toolbox/data/res/store.dart';
const backupFormatVersion = 1;
final _logger = Logger('Backup');
class Backup {
// backup format version
final int version;
@@ -77,19 +80,20 @@ class Backup {
history = Stores.history.box.toJson();
static Future<String> backup([String? name]) async {
final result = _diyEncrypt(json.encode(Backup.loadFromStore()));
final result = _diyEncrypt(json.encode(Backup.loadFromStore().toJson()));
final path = '${await Paths.doc}/${name ?? Paths.bakName}';
await File(path).writeAsString(result);
return path;
}
/// - Return null if same time
/// - Return false if local is newer
/// - Return true if restore success
Future<void> restore({bool force = false}) async {
final curTime = Stores.lastModTime ?? 0;
final bakTime = lastModTime ?? 0;
final shouldRestore = force || curTime < bakTime;
if (!shouldRestore) {
_logger.info('No need to restore, local is newer');
return;
}
// Settings
final nowSettingsKeys = Stores.setting.box.keys.toSet();
@@ -100,67 +104,59 @@ class Backup {
for (final k in newSettingsKeys) {
Stores.setting.box.put(k, settings[k]);
}
if (shouldRestore) {
for (final k in delSettingsKeys) {
Stores.setting.box.delete(k);
}
for (final k in updateSettingsKeys) {
Stores.setting.box.put(k, settings[k]);
}
for (final k in delSettingsKeys) {
Stores.setting.box.delete(k);
}
for (final k in updateSettingsKeys) {
Stores.setting.box.put(k, settings[k]);
}
// Snippets
final nowSnippets = Stores.snippet.fetch().toSet();
final bakSnippets = snippets.toSet();
final nowSnippets = Stores.snippet.box.keys.toSet();
final bakSnippets = snippets.map((e) => e.name).toSet();
final newSnippets = bakSnippets.difference(nowSnippets);
final delSnippets = nowSnippets.difference(bakSnippets);
final updateSnippets = nowSnippets.intersection(bakSnippets);
for (final s in newSnippets) {
Stores.snippet.put(s);
Stores.snippet.box.put(s, snippets.firstWhere((e) => e.name == s));
}
if (shouldRestore) {
for (final s in delSnippets) {
Stores.snippet.delete(s);
}
for (final s in updateSnippets) {
Stores.snippet.put(s);
}
for (final s in delSnippets) {
Stores.snippet.box.delete(s);
}
for (final s in updateSnippets) {
Stores.snippet.box.put(s, snippets.firstWhere((e) => e.name == s));
}
// ServerPrivateInfo
final nowSpis = Stores.server.fetch().toSet();
final bakSpis = spis.toSet();
final nowSpis = Stores.server.box.keys.toSet();
final bakSpis = spis.map((e) => e.id).toSet();
final newSpis = bakSpis.difference(nowSpis);
final delSpis = nowSpis.difference(bakSpis);
final updateSpis = nowSpis.intersection(bakSpis);
for (final s in newSpis) {
Stores.server.put(s);
Stores.server.box.put(s, spis.firstWhere((e) => e.id == s));
}
if (shouldRestore) {
for (final s in delSpis) {
Stores.server.delete(s.id);
}
for (final s in updateSpis) {
Stores.server.put(s);
}
for (final s in delSpis) {
Stores.server.box.delete(s);
}
for (final s in updateSpis) {
Stores.server.box.put(s, spis.firstWhere((e) => e.id == s));
}
// PrivateKeyInfo
final nowKeys = Stores.key.fetch().toSet();
final bakKeys = keys.toSet();
final nowKeys = Stores.key.box.keys.toSet();
final bakKeys = keys.map((e) => e.id).toSet();
final newKeys = bakKeys.difference(nowKeys);
final delKeys = nowKeys.difference(bakKeys);
final updateKeys = nowKeys.intersection(bakKeys);
for (final s in newKeys) {
Stores.key.put(s);
Stores.key.box.put(s, keys.firstWhere((e) => e.id == s));
}
if (shouldRestore) {
for (final s in delKeys) {
Stores.key.delete(s);
}
for (final s in updateKeys) {
Stores.key.put(s);
}
for (final s in delKeys) {
Stores.key.box.delete(s);
}
for (final s in updateKeys) {
Stores.key.box.put(s, keys.firstWhere((e) => e.id == s));
}
// History
@@ -172,13 +168,11 @@ class Backup {
for (final s in newHistory) {
Stores.history.box.put(s, history[s]);
}
if (shouldRestore) {
for (final s in delHistory) {
Stores.history.box.delete(s);
}
for (final s in updateHistory) {
Stores.history.box.put(s, history[s]);
}
for (final s in delHistory) {
Stores.history.box.delete(s);
}
for (final s in updateHistory) {
Stores.history.box.put(s, history[s]);
}
// Container
@@ -188,22 +182,19 @@ class Backup {
final delContainer = nowContainer.difference(bakContainer);
final updateContainer = nowContainer.intersection(bakContainer);
for (final s in newContainer) {
Stores.docker.put(s, container[s]);
Stores.docker.box.put(s, container[s]);
}
if (shouldRestore) {
for (final s in delContainer) {
Stores.docker.box.delete(s);
}
for (final s in updateContainer) {
Stores.docker.put(s, container[s]);
}
for (final s in delContainer) {
Stores.docker.box.delete(s);
}
for (final s in updateContainer) {
Stores.docker.box.put(s, container[s]);
}
// update last modified time, avoid restore again
Stores.setting.box.updateLastModified(lastModTime);
Pros.reload();
RebuildNodes.app.rebuild();
_logger.info('Restore success');
}
Backup.fromJsonString(String raw)

View File

@@ -1,7 +0,0 @@
abstract class JsonSerializable<T> {
/// Convert [this] to json
Map<String, dynamic> toJson();
/// Create [this] from json
T fromJson(Map<String, dynamic> json);
}

View File

@@ -41,4 +41,8 @@ enum ServerFuncBtn {
terminal => l10n.terminal,
iperf => 'iperf',
};
int toJson() => index;
static ServerFuncBtn fromJson(int i) => values[i];
}

View File

@@ -2,9 +2,9 @@
class BuildData {
static const String name = "ServerBox";
static const int build = 723;
static const int build = 724;
static const String engine = "3.16.8";
static const String buildAt = "2024-01-26 17:05:35";
static const int modifications = 3;
static const String buildAt = "2024-01-26 21:05:29";
static const int modifications = 2;
static const int script = 36;
}

View File

@@ -13,6 +13,7 @@ class DockerStore extends PersistentStore {
void put(String id, String host) {
box.put(id, host);
box.updateLastModified();
}
ContainerType getType([String? id]) {
@@ -26,5 +27,6 @@ class DockerStore extends PersistentStore {
void setType(String? id, ContainerType type) {
box.put(_keyConfig + (id ?? ''), type.toString());
box.updateLastModified();
}
}

View File

@@ -18,6 +18,7 @@ class _ListHistory {
_history.remove(path);
_history.insert(0, path);
_box.put(_name, _history);
_box.updateLastModified();
}
List get all => _history;
@@ -38,6 +39,7 @@ class _MapHistory {
void put(String id, String val) {
_history[id] = val;
_box.put(_name, _history);
_box.updateLastModified();
}
String? fetch(String id) => _history[id];

View File

@@ -6,6 +6,7 @@ class PrivateKeyStore extends PersistentStore {
void put(PrivateKeyInfo info) {
box.put(info.id, info);
box.updateLastModified();
}
List<PrivateKeyInfo> fetch() {
@@ -27,5 +28,6 @@ class PrivateKeyStore extends PersistentStore {
void delete(PrivateKeyInfo s) {
box.delete(s.id);
box.updateLastModified();
}
}

View File

@@ -6,6 +6,7 @@ class ServerStore extends PersistentStore {
void put(ServerPrivateInfo info) {
box.put(info.id, info);
box.updateLastModified();
}
List<ServerPrivateInfo> fetch() {
@@ -22,10 +23,12 @@ class ServerStore extends PersistentStore {
void delete(String id) {
box.delete(id);
box.updateLastModified();
}
void deleteAll() {
box.clear();
box.updateLastModified();
}
void update(ServerPrivateInfo old, ServerPrivateInfo newInfo) {

View File

@@ -6,6 +6,7 @@ class SnippetStore extends PersistentStore {
void put(Snippet snippet) {
box.put(snippet.name, snippet);
box.updateLastModified();
}
List<Snippet> fetch() {
@@ -22,5 +23,6 @@ class SnippetStore extends PersistentStore {
void delete(Snippet s) {
box.delete(s.name);
box.updateLastModified();
}
}