@@ -6,6 +6,43 @@ namespace UniGetUI.PackageEngine.Serializable
66{
77 public class InstallOptions : SerializableComponent < InstallOptions >
88 {
9+ private readonly IReadOnlyDictionary < string , bool > DefaultBoolValues = new Dictionary < string , bool > ( )
10+ { // OverridesNextLevelOpts is deliberately skipped here
11+ { "SkipHashCheck" , false } ,
12+ { "InteractiveInstallation" , false } ,
13+ { "RunAsAdministrator" , false } ,
14+ { "PreRelease" , false } ,
15+ { "SkipMinorUpdates" , false } ,
16+ { "RemoveDataOnUninstall" , false } ,
17+ { "UninstallPreviousVersionsOnUpdate" , false } ,
18+ { "AbortOnPreInstallFail" , true } ,
19+ { "AbortOnPreUpdateFail" , true } ,
20+ { "AbortOnPreUninstallFail" , true } ,
21+ } ;
22+
23+ private readonly IReadOnlyDictionary < string , string > DefaultStringValues = new Dictionary < string , string > ( )
24+ {
25+ { "Architecture" , "" } ,
26+ { "InstallationScope" , "" } ,
27+ { "CustomInstallLocation" , "" } ,
28+ { "Version" , "" } ,
29+ { "PreInstallCommand" , "" } ,
30+ { "PostInstallCommand" , "" } ,
31+ { "PreUpdateCommand" , "" } ,
32+ { "PostUpdateCommand" , "" } ,
33+ { "PreUninstallCommand" , "" } ,
34+ { "PostUninstallCommand" , "" } ,
35+ } ;
36+
37+ private readonly IReadOnlyList < string > DefaultListValues = new List < string > ( )
38+ {
39+ "CustomParameters_Install" ,
40+ "CustomParameters_Update" ,
41+ "CustomParameters_Uninstall" ,
42+ "KillBeforeOperation" ,
43+ } ;
44+
45+
946 public bool SkipHashCheck { get ; set ; }
1047 public bool InteractiveInstallation { get ; set ; }
1148 public bool RunAsAdministrator { get ; set ; }
@@ -18,7 +55,6 @@ public class InstallOptions: SerializableComponent<InstallOptions>
1855 public string CustomInstallLocation { get ; set ; } = "" ;
1956 public string Version { get ; set ; } = "" ;
2057 public bool SkipMinorUpdates { get ; set ; }
21- public bool OverridesNextLevelOpts { get ; set ; }
2258 public bool RemoveDataOnUninstall { get ; set ; }
2359 public bool UninstallPreviousVersionsOnUpdate { get ; set ; }
2460 public List < string > KillBeforeOperation { get ; set ; } = [ ] ;
@@ -33,53 +69,54 @@ public class InstallOptions: SerializableComponent<InstallOptions>
3369 public string PostUninstallCommand { get ; set ; } = "" ;
3470 public bool AbortOnPreUninstallFail { get ; set ; } = true ;
3571
72+ public bool OverridesNextLevelOpts { get ; set ; }
3673
3774 public override InstallOptions Copy ( )
3875 {
39- return new ( )
40- {
41- SkipHashCheck = SkipHashCheck ,
42- Architecture = Architecture ,
43- CustomInstallLocation = CustomInstallLocation ,
44- CustomParameters_Install = CustomParameters_Install . ToList ( ) ,
45- CustomParameters_Update = CustomParameters_Update . ToList ( ) ,
46- CustomParameters_Uninstall = CustomParameters_Uninstall . ToList ( ) ,
47- InstallationScope = InstallationScope ,
48- InteractiveInstallation = InteractiveInstallation ,
49- PreRelease = PreRelease ,
50- RunAsAdministrator = RunAsAdministrator ,
51- Version = Version ,
52- SkipMinorUpdates = SkipMinorUpdates ,
53- OverridesNextLevelOpts = OverridesNextLevelOpts ,
54- RemoveDataOnUninstall = RemoveDataOnUninstall ,
55- KillBeforeOperation = KillBeforeOperation . ToList ( ) ,
56- PreInstallCommand = PreInstallCommand ,
57- PreUpdateCommand = PreUpdateCommand ,
58- PreUninstallCommand = PreUninstallCommand ,
59- PostInstallCommand = PostInstallCommand ,
60- PostUpdateCommand = PostUpdateCommand ,
61- PostUninstallCommand = PostUninstallCommand ,
62- AbortOnPreInstallFail = AbortOnPreInstallFail ,
63- AbortOnPreUpdateFail = AbortOnPreUpdateFail ,
64- AbortOnPreUninstallFail = AbortOnPreUninstallFail ,
65- UninstallPreviousVersionsOnUpdate = UninstallPreviousVersionsOnUpdate ,
66- } ;
76+ var copy = new InstallOptions ( ) ;
77+
78+ foreach ( var ( boolKey , _) in DefaultBoolValues )
79+ copy . SetValueToProperty ( boolKey , GetValueFromProperty < bool > ( boolKey ) ) ;
80+
81+ foreach ( var ( stringKey , _) in DefaultStringValues )
82+ copy . SetValueToProperty ( stringKey , GetValueFromProperty < string > ( stringKey ) ) ;
83+
84+ foreach ( var listKey in DefaultListValues )
85+ copy . SetValueToProperty ( listKey , GetValueFromProperty < IReadOnlyList < string > > ( listKey ) . ToList ( ) ) ;
86+
87+ // Handle non-automated OverridesNextLevelOpts
88+ copy . OverridesNextLevelOpts = OverridesNextLevelOpts ;
89+ return copy ;
90+ }
91+
92+ public void SetValueToProperty < T > ( string name , T value )
93+ {
94+ var property = this . GetType ( ) . GetProperty ( name ) ;
95+ property ? . SetValue ( this , value ) ;
96+ }
97+
98+ public T GetValueFromProperty < T > ( string name )
99+ {
100+ var property = this . GetType ( ) . GetProperty ( name ) ;
101+ return ( T ) ( property ? . GetValue ( this ) ?? throw new InvalidDataException ( $ "Invalid datatype for property { name } (expected { nameof ( T ) } )") ) ;
67102 }
68103
69104 public override void LoadFromJson ( JsonNode data )
70105 {
71- // RemoveDataOnUninstall should not be loaded from disk
106+ foreach ( var ( boolKey , defValue ) in DefaultBoolValues )
107+ {
108+ // RemoveDataOnUninstall should not be loaded from disk
109+ if ( boolKey == "RemoveDataOnUninstall" ) continue ;
110+ SetValueToProperty ( boolKey , data [ boolKey ] ? . GetVal < bool > ( ) ?? defValue ) ;
111+ }
72112
73- this . SkipHashCheck = data [ nameof ( SkipHashCheck ) ] ? . GetVal < bool > ( ) ?? false ;
74- this . InteractiveInstallation = data [ nameof ( InteractiveInstallation ) ] ? . GetVal < bool > ( ) ?? false ;
75- this . RunAsAdministrator = data [ nameof ( RunAsAdministrator ) ] ? . GetVal < bool > ( ) ?? false ;
76- this . Architecture = data [ nameof ( Architecture ) ] ? . GetVal < string > ( ) ?? "" ;
77- this . InstallationScope = data [ nameof ( InstallationScope ) ] ? . GetVal < string > ( ) ?? "" ;
113+ foreach ( var ( stringKey , defValue ) in DefaultStringValues )
114+ SetValueToProperty ( stringKey , data [ stringKey ] ? . GetVal < string > ( ) ?? defValue ) ;
78115
79- this . CustomParameters_Install = ReadArrayFromJson ( data , nameof ( CustomParameters_Install ) ) ;
80- this . CustomParameters_Update = ReadArrayFromJson ( data , nameof ( CustomParameters_Update ) ) ;
81- this . CustomParameters_Uninstall = ReadArrayFromJson ( data , nameof ( CustomParameters_Uninstall ) ) ;
116+ foreach ( var listKey in DefaultListValues )
117+ SetValueToProperty ( listKey , ReadArrayFromJson ( data , listKey ) ) ;
82118
119+ // Handle case where setting has not been migrated yet
83120 if ( this . CustomParameters_Install . Count is 0 &&
84121 this . CustomParameters_Update . Count is 0 &&
85122 this . CustomParameters_Uninstall . Count is 0 &&
@@ -90,28 +127,10 @@ this.CustomParameters_Uninstall.Count is 0 &&
90127 this . CustomParameters_Uninstall = ReadArrayFromJson ( data , "CustomParameters" ) ;
91128 }
92129
93- this . KillBeforeOperation = ReadArrayFromJson ( data , nameof ( KillBeforeOperation ) ) ;
94- this . PreRelease = data [ nameof ( PreRelease ) ] ? . GetVal < bool > ( ) ?? false ;
95- this . CustomInstallLocation = data [ nameof ( CustomInstallLocation ) ] ? . GetVal < string > ( ) ?? "" ;
96- this . Version = data [ nameof ( Version ) ] ? . GetVal < string > ( ) ?? "" ;
97- this . SkipMinorUpdates = data [ nameof ( SkipMinorUpdates ) ] ? . GetVal < bool > ( ) ?? false ;
98- this . UninstallPreviousVersionsOnUpdate = data [ nameof ( UninstallPreviousVersionsOnUpdate ) ] ? . GetVal < bool > ( ) ?? false ;
99-
100- this . PreInstallCommand = data [ nameof ( PreInstallCommand ) ] ? . GetVal < string > ( ) ?? "" ;
101- this . PreUpdateCommand = data [ nameof ( PreUpdateCommand ) ] ? . GetVal < string > ( ) ?? "" ;
102- this . PreUninstallCommand = data [ nameof ( PreUninstallCommand ) ] ? . GetVal < string > ( ) ?? "" ;
103- this . PostInstallCommand = data [ nameof ( PostInstallCommand ) ] ? . GetVal < string > ( ) ?? "" ;
104- this . PostUpdateCommand = data [ nameof ( PostUpdateCommand ) ] ? . GetVal < string > ( ) ?? "" ;
105- this . PostUninstallCommand = data [ nameof ( PostUninstallCommand ) ] ? . GetVal < string > ( ) ?? "" ;
106- this . AbortOnPreInstallFail = data [ nameof ( AbortOnPreInstallFail ) ] ? . GetVal < bool > ( ) ?? true ;
107- this . AbortOnPreUpdateFail = data [ nameof ( AbortOnPreUpdateFail ) ] ? . GetVal < bool > ( ) ?? true ;
108- this . AbortOnPreUninstallFail = data [ nameof ( AbortOnPreUninstallFail ) ] ? . GetVal < bool > ( ) ?? true ;
109-
110130 // if OverridesNextLevelOpts is not found on the JSON, set it to true or false depending
111131 // on whether the current settings instances are different from the default values.
112132 // This entry shall be checked the last one, to ensure all other properties are set
113- this . OverridesNextLevelOpts =
114- data [ nameof ( OverridesNextLevelOpts ) ] ? . GetValue < bool > ( ) ?? DiffersFromDefault ( ) ;
133+ this . OverridesNextLevelOpts = data [ nameof ( OverridesNextLevelOpts ) ] ? . GetValue < bool > ( ) ?? DiffersFromDefault ( ) ;
115134 }
116135
117136 public override JsonNode AsJsonNode ( )
@@ -121,81 +140,27 @@ public override JsonNode AsJsonNode()
121140 if ( OverridesNextLevelOpts is not false )
122141 obj . Add ( nameof ( OverridesNextLevelOpts ) , OverridesNextLevelOpts ) ;
123142
124- if ( SkipHashCheck is not false )
125- obj . Add ( nameof ( SkipHashCheck ) , SkipHashCheck ) ;
126-
127- if ( InteractiveInstallation is not false )
128- obj . Add ( nameof ( InteractiveInstallation ) , InteractiveInstallation ) ;
129-
130- if ( RunAsAdministrator is not false )
131- obj . Add ( nameof ( RunAsAdministrator ) , RunAsAdministrator ) ;
132-
133- if ( PreRelease is not false )
134- obj . Add ( nameof ( PreRelease ) , PreRelease ) ;
135-
136- if ( SkipMinorUpdates is not false )
137- obj . Add ( nameof ( SkipMinorUpdates ) , SkipMinorUpdates ) ;
138-
139- if ( Architecture . Any ( ) )
140- obj . Add ( nameof ( Architecture ) , Architecture ) ;
141-
142- if ( InstallationScope . Any ( ) )
143- obj . Add ( nameof ( InstallationScope ) , InstallationScope ) ;
144-
145- if ( CustomParameters_Install . Where ( x => x . Any ( ) ) . Any ( ) )
146- obj . Add ( nameof ( CustomParameters_Install ) ,
147- new JsonArray ( CustomParameters_Install . Select ( x => JsonValue . Create ( x ) as JsonNode ) . ToArray ( ) ) ) ;
148-
149- if ( CustomParameters_Update . Where ( x => x . Any ( ) ) . Any ( ) )
150- obj . Add ( nameof ( CustomParameters_Update ) ,
151- new JsonArray ( CustomParameters_Update . Select ( x => JsonValue . Create ( x ) as JsonNode ) . ToArray ( ) ) ) ;
152-
153- if ( CustomParameters_Uninstall . Where ( x => x . Any ( ) ) . Any ( ) )
154- obj . Add ( nameof ( CustomParameters_Uninstall ) ,
155- new JsonArray ( CustomParameters_Uninstall . Select ( x => JsonValue . Create ( x ) as JsonNode ) . ToArray ( ) ) ) ;
156-
157- if ( KillBeforeOperation . Where ( x => x . Any ( ) ) . Any ( ) )
158- obj . Add ( nameof ( KillBeforeOperation ) ,
159- new JsonArray ( KillBeforeOperation . Select ( x => JsonValue . Create ( x ) as JsonNode ) . ToArray ( ) ) ) ;
160-
161- if ( CustomInstallLocation . Any ( ) )
162- obj . Add ( nameof ( CustomInstallLocation ) , CustomInstallLocation ) ;
163-
164- if ( RemoveDataOnUninstall is not false )
165- obj . Add ( nameof ( RemoveDataOnUninstall ) , RemoveDataOnUninstall ) ;
166-
167- if ( Version . Any ( ) )
168- obj . Add ( nameof ( Version ) , Version ) ;
169-
170- if ( PreInstallCommand . Any ( ) )
171- obj . Add ( nameof ( PreInstallCommand ) , PreInstallCommand ) ;
172-
173- if ( PostInstallCommand . Any ( ) )
174- obj . Add ( nameof ( PostInstallCommand ) , PostInstallCommand ) ;
175-
176- if ( AbortOnPreInstallFail is not true )
177- obj . Add ( nameof ( AbortOnPreInstallFail ) , AbortOnPreInstallFail ) ;
178-
179- if ( PreUpdateCommand . Any ( ) )
180- obj . Add ( nameof ( PreUpdateCommand ) , PreUpdateCommand ) ;
181-
182- if ( PostUpdateCommand . Any ( ) )
183- obj . Add ( nameof ( PostUpdateCommand ) , PostUpdateCommand ) ;
184-
185- if ( AbortOnPreUpdateFail is not true )
186- obj . Add ( nameof ( AbortOnPreUpdateFail ) , AbortOnPreUpdateFail ) ;
187-
188- if ( PreUninstallCommand . Any ( ) )
189- obj . Add ( nameof ( PreUninstallCommand ) , PreUninstallCommand ) ;
143+ foreach ( var ( boolKey , defValue ) in DefaultBoolValues )
144+ {
145+ bool currentValue = GetValueFromProperty < bool > ( boolKey ) ;
146+ if ( currentValue != defValue ) obj . Add ( boolKey , currentValue ) ;
147+ }
190148
191- if ( PostUninstallCommand . Any ( ) )
192- obj . Add ( nameof ( PostUninstallCommand ) , PostUninstallCommand ) ;
149+ foreach ( var ( stringKey , defValue ) in DefaultStringValues )
150+ {
151+ string currentValue = GetValueFromProperty < string > ( stringKey ) ;
152+ if ( currentValue != defValue ) obj . Add ( stringKey , currentValue ) ;
153+ }
193154
194- if ( UninstallPreviousVersionsOnUpdate is not false )
195- obj . Add ( nameof ( UninstallPreviousVersionsOnUpdate ) , UninstallPreviousVersionsOnUpdate ) ;
155+ foreach ( var listKey in DefaultListValues )
156+ {
157+ IReadOnlyList < string > currentValue = GetValueFromProperty < IReadOnlyList < string > > ( listKey ) ;
196158
197- if ( AbortOnPreUninstallFail is not true )
198- obj . Add ( nameof ( AbortOnPreUninstallFail ) , AbortOnPreUninstallFail ) ;
159+ if ( currentValue . Where ( x => x . Any ( ) ) . Any ( ) )
160+ {
161+ obj . Add ( listKey , new JsonArray ( currentValue . Select ( x => JsonValue . Create ( x ) as JsonNode ) . ToArray ( ) ) ) ;
162+ }
163+ }
199164
200165 return obj ;
201166 }
@@ -211,30 +176,19 @@ private static List<string> ReadArrayFromJson(JsonNode data, string name)
211176
212177 public bool DiffersFromDefault ( )
213178 {
214- return SkipHashCheck is not false ||
215- InteractiveInstallation is not false ||
216- RunAsAdministrator is not false ||
217- PreRelease is not false ||
218- SkipMinorUpdates is not false ||
219- Architecture . Any ( ) ||
220- InstallationScope . Any ( ) ||
221- CustomParameters_Install . Where ( x => x . Any ( ) ) . Any ( ) ||
222- CustomParameters_Update . Where ( x => x . Any ( ) ) . Any ( ) ||
223- CustomParameters_Uninstall . Where ( x => x . Any ( ) ) . Any ( ) ||
224- KillBeforeOperation . Where ( x => x . Any ( ) ) . Any ( ) ||
225- CustomInstallLocation . Any ( ) ||
226- RemoveDataOnUninstall is not false ||
227- Version . Any ( ) ||
228- PreInstallCommand . Any ( ) ||
229- PostInstallCommand . Any ( ) ||
230- AbortOnPreInstallFail is not true ||
231- PreUpdateCommand . Any ( ) ||
232- PostUpdateCommand . Any ( ) ||
233- AbortOnPreUpdateFail is not true ||
234- PreUninstallCommand . Any ( ) ||
235- PostUninstallCommand . Any ( ) ||
236- UninstallPreviousVersionsOnUpdate is not false ||
237- AbortOnPreUninstallFail is not true ;
179+ foreach ( var ( boolKey , defValue ) in DefaultBoolValues )
180+ if ( GetValueFromProperty < bool > ( boolKey ) != defValue ) return true ;
181+
182+ foreach ( var ( stringKey , defValue ) in DefaultStringValues )
183+ if ( GetValueFromProperty < string > ( stringKey ) != defValue ) return true ;
184+
185+ foreach ( var listKey in DefaultListValues )
186+ {
187+ IReadOnlyList < string > currentValue = GetValueFromProperty < IReadOnlyList < string > > ( listKey ) ;
188+ if ( currentValue . Where ( x => x . Any ( ) ) . Any ( ) ) return true ;
189+ }
190+
191+ return false ;
238192 // OverridesNextLevelOpts does not need to be checked here, since
239193 // this method is invoked before this property has been set
240194 }
0 commit comments