database, string id) where T : Commit
9 | {
10 | if (string.IsNullOrWhiteSpace(id))
11 | {
12 | return database.GetAll();
13 | }
14 | return database.GetAllAfter(t => t.Id == id);
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurEventSyncer/Tools/SafeQueue.cs:
--------------------------------------------------------------------------------
1 | namespace Aiursoft.AiurEventSyncer.Tools
2 | {
3 | public class SafeQueue
4 | {
5 | private readonly Queue _queue = new();
6 |
7 | public void Enqueue(T item)
8 | {
9 | lock (this)
10 | {
11 | _queue.Enqueue(item);
12 | }
13 | }
14 |
15 | public T Dequeue()
16 | {
17 | T item;
18 | lock (this)
19 | {
20 | item = _queue.Dequeue();
21 | }
22 | return item;
23 | }
24 |
25 | public bool Any()
26 | {
27 | bool any;
28 | lock (this)
29 | {
30 | any = _queue.Any();
31 | }
32 | return any;
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/Aiursoft.AiurEventSyncer/Tools/TaskQueue.cs:
--------------------------------------------------------------------------------
1 | namespace Aiursoft.AiurEventSyncer.Tools
2 | {
3 | public class TaskQueue
4 | {
5 | public Action OnError;
6 |
7 | private readonly SafeQueue> _pendingTaskFactories = new();
8 | private Task _engine = Task.CompletedTask;
9 |
10 | public void QueueNew(Func taskFactory)
11 | {
12 | _pendingTaskFactories.Enqueue(taskFactory);
13 | Task.Factory.StartNew(() =>
14 | {
15 | lock (this)
16 | {
17 | if (_engine.IsCompleted)
18 | {
19 | _engine = RunTasksInQueue();
20 | }
21 | }
22 | });
23 | }
24 |
25 | private async Task RunTasksInQueue()
26 | {
27 | var tasksInFlight = Task.CompletedTask;
28 | while (_pendingTaskFactories.Any())
29 | {
30 | while (tasksInFlight.IsCompleted && _pendingTaskFactories.Any())
31 | {
32 | var taskFactory = _pendingTaskFactories.Dequeue();
33 | tasksInFlight = taskFactory();
34 | }
35 | try
36 | {
37 | await tasksInFlight;
38 | }
39 | catch (Exception e)
40 | {
41 | OnError?.Invoke(e);
42 | }
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurEventSyncer/Tools/WebSocketExtends.cs:
--------------------------------------------------------------------------------
1 | using Aiursoft.AiurStore.Tools;
2 | using System.Net.WebSockets;
3 | using System.Text;
4 |
5 | namespace Aiursoft.AiurEventSyncer.Tools
6 | {
7 | public static class WebSocketExtends
8 | {
9 | public static async Task SendMessage(this WebSocket ws, string message)
10 | {
11 | var buffer = new ArraySegment(Encoding.UTF8.GetBytes(message));
12 | await ws.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
13 | }
14 |
15 | public static async Task Subscribe(this WebSocket ws, Func onNewMessage)
16 | {
17 | var ms = new MemoryStream();
18 | while (ws.State == WebSocketState.Open)
19 | {
20 | WebSocketReceiveResult result;
21 | do
22 | {
23 | var messageBuffer = WebSocket.CreateClientBuffer(1024, 16);
24 | result = await ws.ReceiveAsync(messageBuffer, CancellationToken.None);
25 | ms.Write(messageBuffer.Array ?? [], messageBuffer.Offset, result.Count);
26 | }
27 | while (!result.EndOfMessage);
28 |
29 | if (result.MessageType == WebSocketMessageType.Text)
30 | {
31 | var msgString = Encoding.UTF8.GetString(ms.ToArray());
32 | ms.Seek(0, SeekOrigin.Begin);
33 | ms.SetLength(0);
34 | await onNewMessage(msgString);
35 | }
36 | else
37 | {
38 | throw new InvalidOperationException();
39 | }
40 | }
41 | }
42 |
43 | public static async Task SendObject(this WebSocket ws, T model)
44 | {
45 | var rawJson = JsonTools.Serialize(model);
46 | await ws.SendMessage(rawJson);
47 | }
48 |
49 | public static Task Monitor(this WebSocket ws, Func onNewObject)
50 | {
51 | return ws.Subscribe(rawJson => onNewObject(JsonTools.Deserialize(rawJson)));
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurStore/Aiursoft.AiurStore.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Library
4 | 9.0.0
5 | net9.0
6 | Aiursoft.AiurStore
7 | Aiursoft.AiurStore
8 | false
9 | true
10 | true
11 | enable
12 | Aiursoft
13 | AiurStore
14 | Nuget package of 'AiurStore' provided by Aiursoft
15 | Aiursoft.AiurStore
16 | nuget package dotnet csproj dependencies
17 | MIT
18 | https://gitlab.aiursoft.cn/aiursoft/aiurversioncontrol
19 | git
20 | https://gitlab.aiursoft.cn/aiursoft/aiurversioncontrol.git
21 | README.md
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurStore/Models/IOutOnlyDatabase.cs:
--------------------------------------------------------------------------------
1 | namespace Aiursoft.AiurStore.Models
2 | {
3 | ///
4 | /// Describe a collection which can be queried after a statement.
5 | ///
6 | ///
7 | public interface IOutOnlyDatabase : IReadOnlyCollection
8 | {
9 | public IEnumerable GetAll();
10 | public IEnumerable GetAllAfter(T afterWhich);
11 | public IEnumerable GetAllAfter(Predicate prefix);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurStore/Models/InOutDatabase.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Specialized;
3 |
4 | namespace Aiursoft.AiurStore.Models
5 | {
6 | ///
7 | /// Describe a collection which can be queried after a statement and inserted after an item.
8 | ///
9 | ///
10 | public abstract class InOutDatabase : IOutOnlyDatabase, INotifyCollectionChanged
11 | {
12 | public abstract event NotifyCollectionChangedEventHandler CollectionChanged;
13 | public abstract IEnumerable GetAll();
14 | public abstract IEnumerable GetAllAfter(T afterWhich);
15 | public abstract IEnumerable GetAllAfter(Predicate prefix);
16 | public abstract void Add(T newItem);
17 | public abstract void InsertAfter(T afterWhich, T newItem);
18 | public abstract int Count { get; }
19 |
20 | public IEnumerator GetEnumerator()
21 | {
22 | using var enumerator = GetAll().GetEnumerator();
23 | while (enumerator.MoveNext())
24 | {
25 | yield return enumerator.Current;
26 | }
27 | }
28 |
29 | IEnumerator IEnumerable.GetEnumerator()
30 | {
31 | return GetEnumerator();
32 | }
33 |
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurStore/Providers/MemoryAiurStoreDb.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Specialized;
2 | using Aiursoft.AiurStore.Models;
3 | using Aiursoft.AiurStore.Tools;
4 |
5 | namespace Aiursoft.AiurStore.Providers
6 | {
7 | public class MemoryAiurStoreDb : InOutDatabase
8 | {
9 | private readonly LinkedList _store = new();
10 | public override event NotifyCollectionChangedEventHandler CollectionChanged;
11 |
12 | private LinkedListNode SearchFromLast(Predicate prefix)
13 | {
14 | var last = _store.Last;
15 | while (last != null)
16 | {
17 | if (prefix(last.Value))
18 | {
19 | return last;
20 | }
21 | last = last.Previous;
22 | }
23 | throw new InvalidOperationException("Result not found.");
24 | }
25 |
26 | public override IEnumerable GetAll()
27 | {
28 | return _store;
29 | }
30 |
31 | public override IEnumerable GetAllAfter(Predicate prefix)
32 | {
33 | var node = SearchFromLast(prefix);
34 | return ListExtends.YieldAfter(node);
35 | }
36 |
37 | public override IEnumerable GetAllAfter(T afterWhich)
38 | {
39 | if (afterWhich == null)
40 | {
41 | return _store;
42 | }
43 |
44 | var start = _store.FindLast(afterWhich);
45 | return ListExtends.YieldAfter(start);
46 | }
47 |
48 | public override void Add(T newItem)
49 | {
50 | _store.AddLast(newItem);
51 | CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newItem));
52 | }
53 |
54 | public override void InsertAfter(T afterWhich, T newItem)
55 | {
56 | if (afterWhich == null)
57 | {
58 | _store.AddFirst(newItem);
59 | CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newItem, 0));
60 | }
61 | else
62 | {
63 | var which = _store.FindLast(afterWhich);
64 | if (which == null) throw new KeyNotFoundException($"Insertion point {nameof(afterWhich)} not found.");
65 | _store.AddAfter(which, newItem);
66 | CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
67 | }
68 | }
69 |
70 | public override int Count => _store.Count;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurStore/Tools/JsonTools.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using Newtonsoft.Json.Serialization;
3 |
4 | namespace Aiursoft.AiurStore.Tools
5 | {
6 | public static class JsonTools
7 | {
8 | private static readonly JsonSerializerSettings Settings = new()
9 | {
10 | TypeNameHandling = TypeNameHandling.Auto,
11 | DateTimeZoneHandling = DateTimeZoneHandling.Utc,
12 | ContractResolver = new CamelCasePropertyNamesContractResolver()
13 | };
14 |
15 | public static string Serialize(T model)
16 | {
17 | return JsonConvert.SerializeObject(model, Settings);
18 | }
19 |
20 | public static T Deserialize(string json)
21 | {
22 | return JsonConvert.DeserializeObject(json, Settings);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurStore/Tools/ListExtends.cs:
--------------------------------------------------------------------------------
1 | namespace Aiursoft.AiurStore.Tools
2 | {
3 | public static class ListExtends
4 | {
5 | public static IEnumerable YieldAfter(LinkedListNode node)
6 | {
7 | return YieldFrom(node.Next);
8 | }
9 |
10 | private static IEnumerable YieldFrom(LinkedListNode node)
11 | {
12 | while (node != null)
13 | {
14 | yield return node.Value;
15 | node = node.Next;
16 | }
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurVersionControl.Crud/Aiursoft.AiurVersionControl.Crud.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Library
4 | 9.0.1
5 | net9.0
6 | Aiursoft.AiurVersionControl.Crud
7 | Aiursoft.AiurVersionControl.Crud
8 | false
9 | true
10 | true
11 | enable
12 | Aiursoft
13 | Crud
14 | Nuget package of 'Crud' provided by Aiursoft
15 | Aiursoft.AiurVersionControl.Crud
16 | nuget package dotnet csproj dependencies
17 | MIT
18 | https://gitlab.aiursoft.cn/aiursoft/aiurversioncontrol
19 | git
20 | https://gitlab.aiursoft.cn/aiursoft/aiurversioncontrol.git
21 | README.md
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurVersionControl.Crud/CollectionRepository.cs:
--------------------------------------------------------------------------------
1 | using Aiursoft.AiurVersionControl.Models;
2 | using System.Collections;
3 | using System.Collections.Specialized;
4 | using Aiursoft.AiurVersionControl.Crud.Modifications;
5 |
6 | namespace Aiursoft.AiurVersionControl.Crud
7 | {
8 | ///
9 | /// A special controlled repository that contains a collection workspace which you can do CRUD to.
10 | ///
11 | /// The item type of the collection.
12 | public class CollectionRepository : ControlledRepository>, IEnumerable, INotifyCollectionChanged
13 | {
14 | public event NotifyCollectionChangedEventHandler CollectionChanged;
15 |
16 | public override void BroadcastWorkSpaceChanged()
17 | {
18 | base.BroadcastWorkSpaceChanged();
19 | CollectionChanged?.Invoke(null, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
20 | }
21 |
22 | public void Add(T newItem)
23 | {
24 | ApplyChange(new Add(newItem));
25 | }
26 |
27 | public void Drop(string searchProperty, TProperty value)
28 | {
29 | ApplyChange(new Drop(searchProperty, value));
30 | }
31 |
32 | public void Patch(string searchPropertyName,
33 | TPropertySearch expectValue,
34 | string patchPropertyName,
35 | TPropertyPatch newValue)
36 | {
37 | ApplyChange(new Patch(searchPropertyName, expectValue, patchPropertyName, newValue));
38 | }
39 |
40 | public IEnumerator GetEnumerator()
41 | {
42 | using var enumerator = WorkSpace.GetEnumerator();
43 | while (enumerator.MoveNext())
44 | {
45 | yield return enumerator.Current;
46 | }
47 | }
48 |
49 | IEnumerator IEnumerable.GetEnumerator()
50 | {
51 | return GetEnumerator();
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurVersionControl.Crud/CollectionWorkSpace.cs:
--------------------------------------------------------------------------------
1 | using Aiursoft.AiurVersionControl.Models;
2 | using System.Collections;
3 |
4 | namespace Aiursoft.AiurVersionControl.Crud
5 | {
6 | ///
7 | /// A special workspace which contains a collection with item type is T.
8 | ///
9 | /// The type of the item in the collection.
10 | public class CollectionWorkSpace : WorkSpace, IEnumerable
11 | {
12 | public List List { get; init; } = new ();
13 | public T this[int index] => List[index];
14 |
15 | public CollectionWorkSpace()
16 | {
17 |
18 | }
19 |
20 | public CollectionWorkSpace(List list)
21 | {
22 | List = list;
23 | }
24 |
25 | public override object Clone()
26 | {
27 | return new CollectionWorkSpace(List.ToList());
28 | }
29 |
30 | public IEnumerator GetEnumerator()
31 | {
32 | return List.GetEnumerator();
33 | }
34 |
35 | IEnumerator IEnumerable.GetEnumerator()
36 | {
37 | return GetEnumerator();
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurVersionControl.Crud/Modifications/Add.cs:
--------------------------------------------------------------------------------
1 | using Aiursoft.AiurVersionControl.Models;
2 |
3 | namespace Aiursoft.AiurVersionControl.Crud.Modifications
4 | {
5 | public class Add : IModification>
6 | {
7 | public T Item { get; set; }
8 |
9 | [Obsolete(error: true, message: "This message is only for Newtonsoft.Json")]
10 | public Add() { }
11 |
12 | public Add(T item)
13 | {
14 | Item = item;
15 | }
16 |
17 | public void Apply(CollectionWorkSpace workspace)
18 | {
19 | workspace.List.Add(Item);
20 | }
21 |
22 | public override string ToString()
23 | {
24 | return $"Add a new {typeof(T).Name}";
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurVersionControl.Crud/Modifications/Drop.cs:
--------------------------------------------------------------------------------
1 | using Aiursoft.AiurVersionControl.Models;
2 |
3 | namespace Aiursoft.AiurVersionControl.Crud.Modifications
4 | {
5 | public class Drop : IModification>
6 | {
7 | public string PropertyName { get; set; }
8 | public TSearch ExpectValue { get; set; }
9 |
10 | [Obsolete(error: true, message: "This message is only for Newtonsoft.Json")]
11 | public Drop() { }
12 |
13 | public Drop(string propertyName, TSearch expectValue)
14 | {
15 | PropertyName = propertyName;
16 | ExpectValue = expectValue;
17 | }
18 |
19 | public void Apply(CollectionWorkSpace workspace)
20 | {
21 | var property = typeof(T).GetProperty(PropertyName);
22 | var toRemove = workspace.List.FirstOrDefault(t => property?.GetValue(t, null)?.Equals(ExpectValue) ?? false);
23 | if (toRemove is not null)
24 | {
25 | workspace.List.Remove(toRemove);
26 | }
27 | }
28 |
29 | public override string ToString()
30 | {
31 | return $"Drop a {typeof(T).Name}";
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurVersionControl.Crud/Modifications/Patch.cs:
--------------------------------------------------------------------------------
1 | using Aiursoft.AiurVersionControl.Models;
2 |
3 | namespace Aiursoft.AiurVersionControl.Crud.Modifications
4 | {
5 | public class Patch : IModification>
6 | {
7 | public string SearchPropertyName { get; set; }
8 | public TSearch ExpectValue { get; set; }
9 | public string PatchPropertyName { get; set; }
10 | public TPatch NewValue { get; set; }
11 |
12 | [Obsolete(error: true, message: "This message is only for Newtonsoft.Json")]
13 | public Patch() { }
14 |
15 | public Patch(
16 | string searchPropertyName,
17 | TSearch expectValue,
18 | string patchPropertyName,
19 | TPatch newValue)
20 | {
21 | SearchPropertyName = searchPropertyName;
22 | ExpectValue = expectValue;
23 | PatchPropertyName = patchPropertyName;
24 | NewValue = newValue;
25 | }
26 |
27 | public void Apply(CollectionWorkSpace workspace)
28 | {
29 | var property = typeof(T).GetProperty(SearchPropertyName);
30 | var patchProperty = typeof(T).GetProperty(PatchPropertyName);
31 | var toPatch = workspace.List.FirstOrDefault(t => property?.GetValue(t, null)?.Equals(ExpectValue) ?? false);
32 | if (toPatch is not null)
33 | {
34 | patchProperty?.SetValue(toPatch, NewValue);
35 | }
36 | }
37 |
38 | public override string ToString()
39 | {
40 | return $"Patch a {typeof(T).Name}";
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurVersionControl/Aiursoft.AiurVersionControl.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Library
4 | 9.0.1
5 | net9.0
6 | Aiursoft.AiurVersionControl
7 | Aiursoft.AiurVersionControl
8 | false
9 | true
10 | true
11 | enable
12 | Aiursoft
13 | AiurVersionControl
14 | Nuget package of 'AiurVersionControl' provided by Aiursoft
15 | Aiursoft.AiurVersionControl
16 | nuget package dotnet csproj dependencies
17 | MIT
18 | https://gitlab.aiursoft.cn/aiursoft/aiurversioncontrol
19 | git
20 | https://gitlab.aiursoft.cn/aiursoft/aiurversioncontrol.git
21 | README.md
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurVersionControl/Models/ControlledRepository.cs:
--------------------------------------------------------------------------------
1 | using Aiursoft.AiurEventSyncer.Abstract;
2 | using Aiursoft.AiurEventSyncer.Models;
3 | using System.ComponentModel;
4 |
5 | namespace Aiursoft.AiurVersionControl.Models
6 | {
7 | ///
8 | /// A special repository which contains a workspace and applies modifications to it automatically.
9 | ///
10 | ///
11 | public class ControlledRepository : Repository>, INotifyPropertyChanged where T : WorkSpace, new()
12 | {
13 | public event PropertyChangedEventHandler PropertyChanged;
14 |
15 | public T WorkSpace { get; internal set; }
16 |
17 | ///
18 | /// Call this method to manually broadcast a new event to all workspace changed subscribers.
19 | ///
20 | public virtual void BroadcastWorkSpaceChanged() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(WorkSpace)));
21 |
22 | public ControlledRepository()
23 | {
24 | WorkSpace = new T();
25 | }
26 |
27 | protected override void OnAppendCommits(List>> newCommits)
28 | {
29 | foreach (var newCommit in newCommits)
30 | {
31 | newCommit.Item.Apply(WorkSpace);
32 | BroadcastWorkSpaceChanged();
33 | }
34 | base.OnAppendCommits(newCommits);
35 | }
36 |
37 | public void ApplyChange(IModification newModification)
38 | {
39 | Commit(newModification);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurVersionControl/Models/IModification.cs:
--------------------------------------------------------------------------------
1 | namespace Aiursoft.AiurVersionControl.Models
2 | {
3 | ///
4 | /// An operation which can be applied to workspace.
5 | ///
6 | /// Target workspace type.
7 | public interface IModification where T: WorkSpace
8 | {
9 | void Apply(T workspace);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurVersionControl/Models/RemoteWithWorkSpace.cs:
--------------------------------------------------------------------------------
1 | using Aiursoft.AiurEventSyncer.Abstract;
2 | using Aiursoft.AiurEventSyncer.Models;
3 |
4 | namespace Aiursoft.AiurVersionControl.Models
5 | {
6 | public class RemoteWithWorkSpace : Remote> where T : WorkSpace, new()
7 | {
8 | public T RemoteWorkSpace { get; } = new();
9 |
10 | public RemoteWithWorkSpace(
11 | IConnectionProvider> provider,
12 | bool autoPush = false,
13 | bool autoPull = false) : base(provider, autoPush, autoPull)
14 | {
15 | }
16 |
17 | public override void OnPullPointerMovedForwardOnce(Commit> pointer)
18 | {
19 | pointer.Item.Apply(RemoteWorkSpace);
20 | }
21 |
22 | public override void OnPullInsert()
23 | {
24 | if (ContextRepository is ControlledRepository controlled)
25 | {
26 | var fork = (T)RemoteWorkSpace.Clone();
27 | var localNewCommits = controlled.Commits.GetAllAfter(PullPointer);
28 | foreach (var localNewCommit in localNewCommits)
29 | {
30 | localNewCommit.Item.Apply(fork);
31 | }
32 | controlled.WorkSpace = fork;
33 | controlled.BroadcastWorkSpaceChanged();
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurVersionControl/Models/WorkSpace.cs:
--------------------------------------------------------------------------------
1 | namespace Aiursoft.AiurVersionControl.Models
2 | {
3 | ///
4 | /// A class which must inert to be version controlled in a controlled repository.
5 | ///
6 | public abstract class WorkSpace : ICloneable
7 | {
8 | public abstract object Clone();
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurVersionControl/Remotes/ObjectRemoteWithWorkSpace.cs:
--------------------------------------------------------------------------------
1 | using Aiursoft.AiurEventSyncer.ConnectionProviders;
2 | using Aiursoft.AiurVersionControl.Models;
3 |
4 | namespace Aiursoft.AiurVersionControl.Remotes
5 | {
6 | public class ObjectRemoteWithWorkSpace : RemoteWithWorkSpace where T : WorkSpace, new()
7 | {
8 | public ObjectRemoteWithWorkSpace(ControlledRepository localRepository, bool autoPush = false, bool autoPull = false)
9 | : base(new FakeConnection>(localRepository), autoPush, autoPull)
10 | {
11 |
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/Aiursoft.AiurVersionControl/Remotes/WebSocketRemoteWithWorkSpace.cs:
--------------------------------------------------------------------------------
1 | using Aiursoft.AiurEventSyncer.ConnectionProviders;
2 | using Aiursoft.AiurVersionControl.Models;
3 |
4 | namespace Aiursoft.AiurVersionControl.Remotes
5 | {
6 | public class WebSocketRemoteWithWorkSpace : RemoteWithWorkSpace where T : WorkSpace, new()
7 | {
8 | public string EndPoint { get; private set; }
9 |
10 | public WebSocketRemoteWithWorkSpace(string endPoint, bool autoRetry = false) :
11 | base(autoRetry
12 | ? new RetryableWebSocketConnection>(endPoint)
13 | : new WebSocketConnection>(endPoint), true, true)
14 | {
15 | EndPoint = endPoint;
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/tests/Aiursoft.AiurEventSyncer.Tests/Aiursoft.AiurEventSyncer.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Library
4 | net9.0
5 | Aiursoft.AiurEventSyncer.Tests
6 | true
7 | false
8 | enable
9 |
10 |
11 |
12 | runtime; build; native; contentfiles; analyzers; buildtransitive
13 | all
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/tests/Aiursoft.AiurEventSyncer.Tests/AutoTest.cs:
--------------------------------------------------------------------------------
1 | using Aiursoft.AiurEventSyncer.Models;
2 | using Aiursoft.AiurEventSyncer.Remotes;
3 | using Aiursoft.AiurEventSyncer.Tests.Tools;
4 | using Microsoft.VisualStudio.TestTools.UnitTesting;
5 |
6 | namespace Aiursoft.AiurEventSyncer.Tests
7 | {
8 | [TestClass]
9 | public class AutoTest
10 | {
11 | private Repository _localRepo;
12 |
13 | [TestInitialize]
14 | public void GetBasicRepo()
15 | {
16 | _localRepo = new Repository();
17 | _localRepo.Commit(1);
18 | _localRepo.Commit(2);
19 | _localRepo.Commit(3);
20 | _localRepo.Assert(1, 2, 3);
21 | }
22 |
23 | [TestMethod]
24 | public async Task TestAutoPush()
25 | {
26 | var remoteRepo = new Repository();
27 | await new ObjectRemote(remoteRepo, autoPush: true).AttachAsync(_localRepo);
28 |
29 | _localRepo.Commit(50);
30 | remoteRepo.Assert(1, 2, 3, 50);
31 |
32 | _localRepo.Commit(200);
33 | _localRepo.Commit(300);
34 |
35 | _localRepo.Assert(1, 2, 3, 50, 200, 300);
36 | remoteRepo.Assert(1, 2, 3, 50, 200, 300);
37 | }
38 |
39 | [TestMethod]
40 | public async Task TestAutoPull()
41 | {
42 | var remoteRepo = _localRepo;
43 | var localRepo = new Repository();
44 | await new ObjectRemote(remoteRepo, autoPush: false, autoPull: true).AttachAsync(localRepo);
45 | localRepo.Assert(1, 2, 3);
46 |
47 | remoteRepo.Commit(50);
48 | localRepo.Assert(1, 2, 3, 50);
49 |
50 | remoteRepo.Commit(200);
51 | remoteRepo.Commit(300);
52 |
53 | localRepo.Assert(1, 2, 3, 50, 200, 300);
54 | remoteRepo.Assert(1, 2, 3, 50, 200, 300);
55 | }
56 |
57 | [TestMethod]
58 | public async Task DoubleWaySync()
59 | {
60 | var a = new Repository();
61 | var b = new Repository |