1
1
using System ;
2
2
using System . Collections . Generic ;
3
- using System . Collections . ObjectModel ;
4
3
using System . Linq ;
5
4
using Coder . Desktop . App . Converters ;
6
5
using Coder . Desktop . MutagenSdk . Proto . Synchronization ;
@@ -49,163 +48,9 @@ public string Description(string linePrefix = "")
49
48
}
50
49
}
51
50
52
- public enum SyncSessionModelEntryKind
53
- {
54
- Unknown ,
55
- Directory ,
56
- File ,
57
- SymbolicLink ,
58
- Untracked ,
59
- Problematic ,
60
- PhantomDirectory ,
61
- }
62
-
63
- public sealed class SyncSessionModelEntry
64
- {
65
- public readonly SyncSessionModelEntryKind Kind ;
66
-
67
- // For Kind == Directory only.
68
- public readonly ReadOnlyDictionary < string , SyncSessionModelEntry > Contents ;
69
-
70
- // For Kind == File only.
71
- public readonly string Digest = "" ;
72
- public readonly bool Executable ;
73
-
74
- // For Kind = SymbolicLink only.
75
- public readonly string Target = "" ;
76
-
77
- // For Kind = Problematic only.
78
- public readonly string Problem = "" ;
79
-
80
- public SyncSessionModelEntry ( Entry protoEntry )
81
- {
82
- Kind = protoEntry . Kind switch
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
- case SyncSessionModelEntryKind . Directory :
96
- {
97
- var contents = new Dictionary < string , SyncSessionModelEntry > ( ) ;
98
- foreach ( var ( key , value ) in protoEntry . Contents )
99
- contents [ key ] = new SyncSessionModelEntry ( value ) ;
100
- Contents = new ReadOnlyDictionary < string , SyncSessionModelEntry > ( contents ) ;
101
- break ;
102
- }
103
- case SyncSessionModelEntryKind . File :
104
- Digest = BitConverter . ToString ( protoEntry . Digest . ToByteArray ( ) ) . Replace ( "-" , "" ) . ToLower ( ) ;
105
- Executable = protoEntry . Executable ;
106
- break ;
107
- case SyncSessionModelEntryKind . SymbolicLink :
108
- Target = protoEntry . Target ;
109
- break ;
110
- case SyncSessionModelEntryKind . Problematic :
111
- Problem = protoEntry . Problem ;
112
- break ;
113
- }
114
- }
115
-
116
- public new string ToString ( )
117
- {
118
- var str = Kind . ToString ( ) ;
119
- switch ( Kind )
120
- {
121
- case SyncSessionModelEntryKind . Directory :
122
- str += $ " ({ Contents . Count } entries)";
123
- break ;
124
- case SyncSessionModelEntryKind . File :
125
- str += $ " ({ Digest } , executable: { Executable } )";
126
- break ;
127
- case SyncSessionModelEntryKind . SymbolicLink :
128
- str += $ " (target: { Target } )";
129
- break ;
130
- case SyncSessionModelEntryKind . Problematic :
131
- str += $ " ({ Problem } )";
132
- break ;
133
- }
134
-
135
- return str ;
136
- }
137
- }
138
-
139
- public sealed class SyncSessionModelConflictChange
140
- {
141
- public readonly string Path ; // relative to sync root
142
-
143
- // null means non-existent:
144
- public readonly SyncSessionModelEntry ? Old ;
145
- public readonly SyncSessionModelEntry ? New ;
146
-
147
- public SyncSessionModelConflictChange ( Change protoChange )
148
- {
149
- Path = protoChange . Path ;
150
- Old = protoChange . Old != null ? new SyncSessionModelEntry ( protoChange . Old ) : null ;
151
- New = protoChange . New != null ? new SyncSessionModelEntry ( protoChange . New ) : null ;
152
- }
153
-
154
- public new string ToString ( )
155
- {
156
- const string nonExistent = "<non-existent>" ;
157
- var oldStr = Old != null ? Old . ToString ( ) : nonExistent ;
158
- var newStr = New != null ? New . ToString ( ) : nonExistent ;
159
- return $ "{ Path } ({ oldStr } -> { newStr } )";
160
- }
161
- }
162
-
163
- public sealed class SyncSessionModelConflict
164
- {
165
- public readonly string Root ; // relative to sync root
166
- public readonly List < SyncSessionModelConflictChange > AlphaChanges ;
167
- public readonly List < SyncSessionModelConflictChange > BetaChanges ;
168
-
169
- public SyncSessionModelConflict ( Conflict protoConflict )
170
- {
171
- Root = protoConflict . Root ;
172
- AlphaChanges = protoConflict . AlphaChanges . Select ( change => new SyncSessionModelConflictChange ( change ) ) . ToList ( ) ;
173
- BetaChanges = protoConflict . BetaChanges . Select ( change => new SyncSessionModelConflictChange ( change ) ) . ToList ( ) ;
174
- }
175
-
176
- private string ? 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
- return null ;
188
- }
189
-
190
- public string Description ( )
191
- {
192
- // This formatting is very similar to Mutagen.
193
- var str = $ "Conflict at path '{ Root } ':";
194
- foreach ( var change in AlphaChanges )
195
- str += $ "\n (alpha) { change . ToString ( ) } ";
196
- foreach ( var change in AlphaChanges )
197
- str += $ "\n (beta) { change . ToString ( ) } ";
198
- if ( FriendlyProblem ( ) is { } friendlyProblem )
199
- str += $ "\n \n { friendlyProblem } ";
200
-
201
- return str ;
202
- }
203
- }
204
-
205
51
public class SyncSessionModel
206
52
{
207
53
public readonly string Identifier ;
208
- public readonly string Name ;
209
54
210
55
public readonly string AlphaName ;
211
56
public readonly string AlphaPath ;
@@ -219,8 +64,8 @@ public class SyncSessionModel
219
64
public readonly SyncSessionModelEndpointSize AlphaSize ;
220
65
public readonly SyncSessionModelEndpointSize BetaSize ;
221
66
222
- public readonly IReadOnlyList < SyncSessionModelConflict > Conflicts ;
223
- public ulong OmittedConflicts ;
67
+ public readonly IReadOnlyList < string > Conflicts ; // Conflict descriptions
68
+ public readonly ulong OmittedConflicts ;
224
69
public readonly IReadOnlyList < string > Errors ;
225
70
226
71
// If Paused is true, the session can be resumed. If false, the session can
@@ -231,10 +76,12 @@ public string StatusDetails
231
76
{
232
77
get
233
78
{
234
- var str = $ "{ StatusString } ({ StatusCategory } )\n \n { StatusDescription } ";
235
- foreach ( var err in Errors ) str += $ "\n \n Error: { err } ";
236
- foreach ( var conflict in Conflicts ) str += $ "\n \n { conflict . Description ( ) } ";
237
- if ( OmittedConflicts > 0 ) str += $ "\n \n { OmittedConflicts : N0} conflicts omitted";
79
+ var str = StatusString ;
80
+ if ( StatusCategory . ToString ( ) != StatusString ) str += $ " ({ StatusCategory } )";
81
+ str += $ "\n \n { StatusDescription } ";
82
+ foreach ( var err in Errors ) str += $ "\n \n -----\n \n { err } ";
83
+ foreach ( var conflict in Conflicts ) str += $ "\n \n -----\n \n { conflict } ";
84
+ if ( OmittedConflicts > 0 ) str += $ "\n \n -----\n \n { OmittedConflicts : N0} conflicts omitted";
238
85
return str ;
239
86
}
240
87
}
@@ -252,7 +99,6 @@ public string SizeDetails
252
99
public SyncSessionModel ( State state )
253
100
{
254
101
Identifier = state . Session . Identifier ;
255
- Name = state . Session . Name ;
256
102
257
103
( AlphaName , AlphaPath ) = NameAndPathFromUrl ( state . Session . Alpha ) ;
258
104
( BetaName , BetaPath ) = NameAndPathFromUrl ( state . Session . Beta ) ;
@@ -354,7 +200,7 @@ public SyncSessionModel(State state)
354
200
StatusDescription = "The session has conflicts that need to be resolved." ;
355
201
}
356
202
357
- Conflicts = state . Conflicts . Select ( c => new SyncSessionModelConflict ( c ) ) . ToList ( ) ;
203
+ Conflicts = state . Conflicts . Select ( ConflictToString ) . ToList ( ) ;
358
204
OmittedConflicts = state . ExcludedConflicts ;
359
205
360
206
AlphaSize = new SyncSessionModelEndpointSize
@@ -403,4 +249,55 @@ private static (string, string) NameAndPathFromUrl(URL url)
403
249
404
250
return ( name , path ) ;
405
251
}
252
+
253
+ private static string ConflictToString ( Conflict conflict )
254
+ {
255
+ string ? friendlyProblem = null ;
256
+ if ( conflict . AlphaChanges . Count == 1 && conflict . BetaChanges . Count == 1 &&
257
+ conflict . AlphaChanges [ 0 ] . Old == null &&
258
+ conflict . BetaChanges [ 0 ] . Old == null &&
259
+ conflict . AlphaChanges [ 0 ] . New != null &&
260
+ conflict . BetaChanges [ 0 ] . New != null )
261
+ friendlyProblem =
262
+ "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." ;
263
+
264
+ var str = $ "Conflict at path '{ conflict . Root } ':";
265
+ foreach ( var change in conflict . AlphaChanges )
266
+ str += $ "\n (alpha) { ChangeToString ( change ) } ";
267
+ foreach ( var change in conflict . BetaChanges )
268
+ str += $ "\n (beta) { ChangeToString ( change ) } ";
269
+ if ( friendlyProblem != null )
270
+ str += $ "\n \n { friendlyProblem } ";
271
+
272
+ return str ;
273
+ }
274
+
275
+ private static string ChangeToString ( Change change )
276
+ {
277
+ return $ "{ change . Path } ({ EntryToString ( change . Old ) } -> { EntryToString ( change . New ) } )";
278
+ }
279
+
280
+ private static string EntryToString ( Entry ? entry )
281
+ {
282
+ if ( entry == null ) return "<non-existent>" ;
283
+ var str = entry . Kind . ToString ( ) ;
284
+ switch ( entry . Kind )
285
+ {
286
+ case EntryKind . Directory :
287
+ str += $ " ({ entry . Contents . Count } entries)";
288
+ break ;
289
+ case EntryKind . File :
290
+ var digest = BitConverter . ToString ( entry . Digest . ToByteArray ( ) ) . Replace ( "-" , "" ) . ToLower ( ) ;
291
+ str += $ " ({ digest } , executable: { entry . Executable } )";
292
+ break ;
293
+ case EntryKind . SymbolicLink :
294
+ str += $ " (target: { entry . Target } )";
295
+ break ;
296
+ case EntryKind . Problematic :
297
+ str += $ " ({ entry . Problem } )";
298
+ break ;
299
+ }
300
+
301
+ return str ;
302
+ }
406
303
}
0 commit comments