-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: jld3103 <[email protected]>
- Loading branch information
1 parent
b552f07
commit 218082a
Showing
20 changed files
with
1,108 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,3 +23,4 @@ rules: | |
- neon_lints | ||
- nextcloud | ||
- sort_box | ||
- synchronize |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Miscellaneous | ||
*.class | ||
*.log | ||
*.pyc | ||
*.swp | ||
.DS_Store | ||
.atom/ | ||
.buildlog/ | ||
.history | ||
.svn/ | ||
migrate_working_dir/ | ||
|
||
# IntelliJ related | ||
*.iml | ||
*.ipr | ||
*.iws | ||
.idea/ | ||
|
||
# The .vscode folder contains launch configuration and tasks you configure in | ||
# VS Code which you may wish to be included in version control, so this line | ||
# is commented out by default. | ||
#.vscode/ | ||
|
||
# Flutter/Dart/Pub related | ||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. | ||
/pubspec.lock | ||
**/doc/api/ | ||
.dart_tool/ | ||
.packages | ||
build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# This file tracks properties of this Flutter project. | ||
# Used by Flutter tool to assess capabilities and perform upgrades etc. | ||
# | ||
# This file should be version controlled and should not be manually edited. | ||
|
||
version: | ||
revision: 2aa348b9407e96ffe4eca8e8f213c7984afad3f7 | ||
channel: master | ||
|
||
project_type: package |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../LICENSE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# synchronize | ||
|
||
A simple generic implementation of https://unterwaditzer.net/2016/sync-algorithm.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
include: package:neon_lints/dart.yaml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import 'package:meta/meta.dart'; | ||
import 'package:synchronize/src/object.dart'; | ||
|
||
/// Action to be executed in the sync process | ||
@internal | ||
sealed class SyncAction<T> { | ||
// ignore: public_member_api_docs | ||
SyncAction(this.object); | ||
|
||
// ignore: public_member_api_docs | ||
final SyncObject<T> object; | ||
} | ||
|
||
/// Action to delete object from A | ||
@internal | ||
interface class SyncActionDeleteFromA<T1, T2> extends SyncAction<T1> { | ||
// ignore: public_member_api_docs | ||
SyncActionDeleteFromA(super.object); | ||
} | ||
|
||
/// Action to delete object from B | ||
@internal | ||
interface class SyncActionDeleteFromB<T1, T2> extends SyncAction<T2> { | ||
// ignore: public_member_api_docs | ||
SyncActionDeleteFromB(super.object); | ||
} | ||
|
||
/// Action to write object to A | ||
@internal | ||
interface class SyncActionWriteToA<T1, T2> extends SyncAction<T2> { | ||
// ignore: public_member_api_docs | ||
SyncActionWriteToA(super.object); | ||
} | ||
|
||
/// Action to write object to B | ||
@internal | ||
interface class SyncActionWriteToB<T1, T2> extends SyncAction<T1> { | ||
// ignore: public_member_api_docs | ||
SyncActionWriteToB(super.object); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import 'package:meta/meta.dart'; | ||
import 'package:synchronize/src/object.dart'; | ||
|
||
/// Contains information about a conflict that appeared during sync. | ||
@immutable | ||
class SyncConflict<T1, T2> { | ||
// ignore: public_member_api_docs | ||
const SyncConflict({ | ||
required this.id, | ||
required this.type, | ||
required this.objectA, | ||
required this.objectB, | ||
this.skipped = false, | ||
}); | ||
|
||
/// Id of the objects involved in the conflict. | ||
final String id; | ||
|
||
/// Type of the conflict that appeared. See [SyncConflictType] for more info. | ||
final SyncConflictType type; | ||
|
||
/// Object A involved in the conflict. | ||
final SyncObject<T1> objectA; | ||
|
||
/// Object B involved in the conflict. | ||
final SyncObject<T2> objectB; | ||
|
||
/// Whether the conflict was skipped by the user, useful for ignoring it later on | ||
final bool skipped; | ||
|
||
@override | ||
bool operator ==(final dynamic other) => other is SyncConflict && other.id == id; | ||
|
||
@override | ||
int get hashCode => id.hashCode; | ||
} | ||
|
||
/// Types of conflicts that can appear during sync. | ||
enum SyncConflictType { | ||
/// New objects with the same id exist on both sides. | ||
bothNew, | ||
|
||
/// Both objects with the same id have changed. | ||
bothChanged, | ||
} | ||
|
||
/// Ways to resolve [SyncConflict]s. | ||
enum SyncConflictSolution { | ||
/// Overwrite the content of object A with the content of object B. | ||
overwriteA, | ||
|
||
/// Overwrite the content of object B with the content of object A. | ||
overwriteB, | ||
|
||
/// Skip the conflict and just do nothing. | ||
skip, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import 'package:json_annotation/json_annotation.dart'; | ||
import 'package:synchronize/src/journal_entry.dart'; | ||
|
||
part 'journal.g.dart'; | ||
|
||
/// Contains the journal. | ||
/// | ||
/// Used for detecting changes and new or deleted files. | ||
@JsonSerializable() | ||
class SyncJournal { | ||
// Note: This must not be const as otherwise the entries are not modifiable when a const set is used! | ||
// ignore: public_member_api_docs | ||
SyncJournal( | ||
this.entries, | ||
); | ||
|
||
// ignore: public_member_api_docs | ||
factory SyncJournal.fromJson(final Map<String, dynamic> json) => _$SyncJournalFromJson(json); | ||
// ignore: public_member_api_docs | ||
Map<String, dynamic> toJson() => _$SyncJournalToJson(this); | ||
|
||
/// All entries contained in the journal. | ||
final Set<SyncJournalEntry> entries; | ||
|
||
/// Update an [entry]. | ||
void updateEntry(final SyncJournalEntry entry) { | ||
entries | ||
..remove(entry) | ||
..add(entry); | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import 'package:collection/collection.dart'; | ||
import 'package:json_annotation/json_annotation.dart'; | ||
import 'package:meta/meta.dart'; | ||
import 'package:synchronize/src/journal.dart'; | ||
|
||
part 'journal_entry.g.dart'; | ||
|
||
/// Stores a single entry in the [SyncJournal]. | ||
/// | ||
/// It contains an [id] and ETags for each object, [etagA] and [etagB] respectively. | ||
@immutable | ||
@JsonSerializable() | ||
class SyncJournalEntry { | ||
// ignore: public_member_api_docs | ||
const SyncJournalEntry( | ||
this.id, | ||
this.etagA, | ||
this.etagB, | ||
); | ||
|
||
// ignore: public_member_api_docs | ||
factory SyncJournalEntry.fromJson(final Map<String, dynamic> json) => _$SyncJournalEntryFromJson(json); | ||
// ignore: public_member_api_docs | ||
Map<String, dynamic> toJson() => _$SyncJournalEntryToJson(this); | ||
|
||
// ignore: public_member_api_docs | ||
final String id; | ||
|
||
/// ETag of the object A. | ||
final String etagA; | ||
|
||
/// ETag of the object B. | ||
final String etagB; | ||
|
||
@override | ||
String toString() => 'SyncJournalEntry(id: $id, etagA: $etagA, etagB: $etagB)'; | ||
|
||
@override | ||
bool operator ==(final Object other) => other is SyncJournalEntry && other.id == id; | ||
|
||
@override | ||
int get hashCode => id.hashCode; | ||
} | ||
|
||
// ignore: public_member_api_docs | ||
extension SyncJournalEntriesFind on Iterable<SyncJournalEntry> { | ||
// ignore: public_member_api_docs | ||
SyncJournalEntry? tryFind(final String id) => firstWhereOrNull((final entry) => entry.id == id); | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import 'package:collection/collection.dart'; | ||
|
||
/// Wraps the actual data contained on each side. | ||
typedef SyncObject<T> = (String, T); | ||
|
||
// ignore: public_member_api_docs | ||
extension SyncObjectFields<T> on SyncObject<T> { | ||
/// Id of the object. | ||
String get id => $1; | ||
|
||
/// Actual data of the object, can be anything. | ||
T get data => $2; | ||
} | ||
|
||
// ignore: public_member_api_docs | ||
extension SyncObjectsFind<T> on List<SyncObject<T>> { | ||
// ignore: public_member_api_docs | ||
SyncObject<T>? tryFind(final String id) => firstWhereOrNull((final object) => object.id == id); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import 'dart:async'; | ||
|
||
import 'package:synchronize/src/conflict.dart'; | ||
import 'package:synchronize/src/object.dart'; | ||
|
||
/// The source the sync uses to sync from and to. | ||
abstract interface class SyncSource<T1, T2> { | ||
/// List all the objects. | ||
FutureOr<List<SyncObject<T1>>> listObjects(); | ||
|
||
/// Calculates the ETag of a given [object]. | ||
/// | ||
/// Should be something easy to compute like the mtime of a file and preferably not the hash of the whole content in order to be fast | ||
FutureOr<String> getObjectETag(final SyncObject<T1> object); | ||
|
||
/// Writes the given [object]. | ||
FutureOr<SyncObject<T1>> writeObject(final SyncObject<T2> object); | ||
|
||
/// Deletes the given [object]. | ||
FutureOr deleteObject(final SyncObject<T1> object); | ||
} | ||
|
||
/// The sources the sync uses to sync from and to. | ||
abstract interface class SyncSources<T1, T2> { | ||
// ignore: public_member_api_docs | ||
SyncSources( | ||
this.sourceA, | ||
this.sourceB, | ||
); | ||
|
||
// ignore: public_member_api_docs | ||
final SyncSource<T1, T2> sourceA; | ||
|
||
// ignore: public_member_api_docs | ||
final SyncSource<T2, T1> sourceB; | ||
|
||
/// Automatically find a solution for conflicts that don't matter. Useful e.g. for ignoring new directories. | ||
SyncConflictSolution? findSolution(final SyncObject<T1> objectA, final SyncObject<T2> objectB); | ||
} |
Oops, something went wrong.