Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit81f8c02

Browse files
committed
Conflict messages
1 parentf7817a9 commit81f8c02

File tree

1 file changed

+185
-5
lines changed

1 file changed

+185
-5
lines changed

‎App/Models/SyncSessionModel.cs

Lines changed: 185 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
usingSystem;
2+
usingSystem.Collections.Generic;
3+
usingSystem.Collections.ObjectModel;
4+
usingSystem.Linq;
15
usingCoder.Desktop.App.Converters;
26
usingCoder.Desktop.MutagenSdk.Proto.Synchronization;
7+
usingCoder.Desktop.MutagenSdk.Proto.Synchronization.Core;
38
usingCoder.Desktop.MutagenSdk.Proto.Url;
49

510
namespaceCoder.Desktop.App.Models;
@@ -44,6 +49,159 @@ public string Description(string linePrefix = "")
4449
}
4550
}
4651

52+
publicenumSyncSessionModelEntryKind
53+
{
54+
Unknown,
55+
Directory,
56+
File,
57+
SymbolicLink,
58+
Untracked,
59+
Problematic,
60+
PhantomDirectory,
61+
}
62+
63+
publicsealedclassSyncSessionModelEntry
64+
{
65+
publicreadonlySyncSessionModelEntryKindKind;
66+
67+
// For Kind == Directory only.
68+
publicreadonlyReadOnlyDictionary<string,SyncSessionModelEntry>Contents;
69+
70+
// For Kind == File only.
71+
publicreadonlystringDigest="";
72+
publicreadonlyboolExecutable;
73+
74+
// For Kind = SymbolicLink only.
75+
publicreadonlystringTarget="";
76+
77+
// For Kind = Problematic only.
78+
publicreadonlystringProblem="";
79+
80+
publicSyncSessionModelEntry(EntryprotoEntry)
81+
{
82+
Kind=protoEntry.Kindswitch
83+
{
84+
EntryKind.Directory=>SyncSessionModelEntryKind.Directory,
85+
EntryKind.File=>SyncSessionModelEntryKind.File,
86+
EntryKind.SymbolicLink=>SyncSessionModelEntryKind.SymbolicLink,
87+
EntryKind.Untracked=>SyncSessionModelEntryKind.Untracked,
88+
EntryKind.Problematic=>SyncSessionModelEntryKind.Problematic,
89+
EntryKind.PhantomDirectory=>SyncSessionModelEntryKind.PhantomDirectory,
90+
_=>SyncSessionModelEntryKind.Unknown,
91+
};
92+
93+
switch(Kind)
94+
{
95+
caseSyncSessionModelEntryKind.Directory:
96+
{
97+
varcontents=newDictionary<string,SyncSessionModelEntry>();
98+
foreach(var(key,value)inprotoEntry.Contents)
99+
contents[key]=newSyncSessionModelEntry(value);
100+
Contents=newReadOnlyDictionary<string,SyncSessionModelEntry>(contents);
101+
break;
102+
}
103+
caseSyncSessionModelEntryKind.File:
104+
Digest=BitConverter.ToString(protoEntry.Digest.ToByteArray()).Replace("-","").ToLower();
105+
Executable=protoEntry.Executable;
106+
break;
107+
caseSyncSessionModelEntryKind.SymbolicLink:
108+
Target=protoEntry.Target;
109+
break;
110+
caseSyncSessionModelEntryKind.Problematic:
111+
Problem=protoEntry.Problem;
112+
break;
113+
}
114+
}
115+
116+
publicnewstringToString()
117+
{
118+
varstr=Kind.ToString();
119+
switch(Kind)
120+
{
121+
caseSyncSessionModelEntryKind.Directory:
122+
str+=$" ({Contents.Count} entries)";
123+
break;
124+
caseSyncSessionModelEntryKind.File:
125+
str+=$" ({Digest}, executable:{Executable})";
126+
break;
127+
caseSyncSessionModelEntryKind.SymbolicLink:
128+
str+=$" (target:{Target})";
129+
break;
130+
caseSyncSessionModelEntryKind.Problematic:
131+
str+=$" ({Problem})";
132+
break;
133+
}
134+
135+
returnstr;
136+
}
137+
}
138+
139+
publicsealedclassSyncSessionModelConflictChange
140+
{
141+
publicreadonlystringPath;// relative to sync root
142+
143+
// null means non-existent:
144+
publicreadonlySyncSessionModelEntry?Old;
145+
publicreadonlySyncSessionModelEntry?New;
146+
147+
publicSyncSessionModelConflictChange(ChangeprotoChange)
148+
{
149+
Path=protoChange.Path;
150+
Old=protoChange.Old!=null?newSyncSessionModelEntry(protoChange.Old):null;
151+
New=protoChange.New!=null?newSyncSessionModelEntry(protoChange.New):null;
152+
}
153+
154+
publicnewstringToString()
155+
{
156+
conststringnonExistent="<non-existent>";
157+
varoldStr=Old!=null?Old.ToString():nonExistent;
158+
varnewStr=New!=null?New.ToString():nonExistent;
159+
return$"{Path} ({oldStr} ->{newStr})";
160+
}
161+
}
162+
163+
publicsealedclassSyncSessionModelConflict
164+
{
165+
publicreadonlystringRoot;// relative to sync root
166+
publicreadonlyList<SyncSessionModelConflictChange>AlphaChanges;
167+
publicreadonlyList<SyncSessionModelConflictChange>BetaChanges;
168+
169+
publicSyncSessionModelConflict(ConflictprotoConflict)
170+
{
171+
Root=protoConflict.Root;
172+
AlphaChanges=protoConflict.AlphaChanges.Select(change=>newSyncSessionModelConflictChange(change)).ToList();
173+
BetaChanges=protoConflict.BetaChanges.Select(change=>newSyncSessionModelConflictChange(change)).ToList();
174+
}
175+
176+
privatestring?FriendlyProblem()
177+
{
178+
// If the change is <non-existent> -> !<non-existent>.
179+
if(AlphaChanges.Count==1&&BetaChanges.Count==1&&
180+
AlphaChanges[0].Old==null&&
181+
BetaChanges[0].Old==null&&
182+
AlphaChanges[0].New!=null&&
183+
BetaChanges[0].New!=null)
184+
return
185+
"An entry was created on both endpoints and they do not match. You can resolve this conflict by deleting one of the entries on either side.";
186+
187+
returnnull;
188+
}
189+
190+
publicstringDescription()
191+
{
192+
// This formatting is very similar to Mutagen.
193+
varstr=$"Conflict at path '{Root}':";
194+
foreach(varchangeinAlphaChanges)
195+
str+=$"\n (alpha){change.ToString()}";
196+
foreach(varchangeinAlphaChanges)
197+
str+=$"\n (beta){change.ToString()}";
198+
if(FriendlyProblem()is{}friendlyProblem)
199+
str+=$"\n\n{friendlyProblem}";
200+
201+
returnstr;
202+
}
203+
}
204+
47205
publicclassSyncSessionModel
48206
{
49207
publicreadonlystringIdentifier;
@@ -61,7 +219,9 @@ public class SyncSessionModel
61219
publicreadonlySyncSessionModelEndpointSizeAlphaSize;
62220
publicreadonlySyncSessionModelEndpointSizeBetaSize;
63221

64-
publicreadonlystring[]Errors=[];
222+
publicreadonlyIReadOnlyList<SyncSessionModelConflict>Conflicts;
223+
publiculongOmittedConflicts;
224+
publicreadonlyIReadOnlyList<string>Errors;
65225

66226
// If Paused is true, the session can be resumed. If false, the session can
67227
// be paused.
@@ -72,7 +232,9 @@ public string StatusDetails
72232
get
73233
{
74234
varstr=$"{StatusString} ({StatusCategory})\n\n{StatusDescription}";
75-
foreach(varerrinErrors)str+=$"\n\n{err}";
235+
foreach(varerrinErrors)str+=$"\n\nError:{err}";
236+
foreach(varconflictinConflicts)str+=$"\n\n{conflict.Description()}";
237+
if(OmittedConflicts>0)str+=$"\n\n{OmittedConflicts:N0} conflicts omitted";
76238
returnstr;
77239
}
78240
}
@@ -192,6 +354,9 @@ public SyncSessionModel(State state)
192354
StatusDescription="The session has conflicts that need to be resolved.";
193355
}
194356

357+
Conflicts=state.Conflicts.Select(c=>newSyncSessionModelConflict(c)).ToList();
358+
OmittedConflicts=state.ExcludedConflicts;
359+
195360
AlphaSize=newSyncSessionModelEndpointSize
196361
{
197362
SizeBytes=state.AlphaState.TotalFileSize,
@@ -207,9 +372,24 @@ public SyncSessionModel(State state)
207372
SymlinkCount=state.BetaState.SymbolicLinks,
208373
};
209374

210-
// TODO: accumulate errors, there seems to be multiple fields they can
211-
// come from
212-
if(!string.IsNullOrWhiteSpace(state.LastError))Errors=[state.LastError];
375+
List<string>errors=[];
376+
if(!string.IsNullOrWhiteSpace(state.LastError))errors.Add($"Last error:\n{state.LastError}");
377+
// TODO: scan problems + transition problems + omissions should probably be fields
378+
foreach(varscanProbleminstate.AlphaState.ScanProblems)errors.Add($"Alpha scan problem:{scanProblem}");
379+
if(state.AlphaState.ExcludedScanProblems>0)
380+
errors.Add($"Alpha scan problems omitted:{state.AlphaState.ExcludedScanProblems}");
381+
foreach(varscanProbleminstate.AlphaState.ScanProblems)errors.Add($"Beta scan problem:{scanProblem}");
382+
if(state.BetaState.ExcludedScanProblems>0)
383+
errors.Add($"Beta scan problems omitted:{state.BetaState.ExcludedScanProblems}");
384+
foreach(vartransitionProbleminstate.AlphaState.TransitionProblems)
385+
errors.Add($"Alpha transition problem:{transitionProblem}");
386+
if(state.AlphaState.ExcludedTransitionProblems>0)
387+
errors.Add($"Alpha transition problems omitted:{state.AlphaState.ExcludedTransitionProblems}");
388+
foreach(vartransitionProbleminstate.AlphaState.TransitionProblems)
389+
errors.Add($"Beta transition problem:{transitionProblem}");
390+
if(state.BetaState.ExcludedTransitionProblems>0)
391+
errors.Add($"Beta transition problems omitted:{state.BetaState.ExcludedTransitionProblems}");
392+
Errors=errors;
213393
}
214394

215395
privatestatic(string,string)NameAndPathFromUrl(URLurl)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp