1+ using System . Text . Json ;
12using System . Text . Json . Nodes ;
23using UniGetUI . Core . Data ;
34
45namespace UniGetUI . PackageEngine . Serializable
56{
67 public class InstallOptions : SerializableComponent < InstallOptions >
78 {
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+
846 public bool SkipHashCheck { get ; set ; }
947 public bool InteractiveInstallation { get ; set ; }
1048 public bool RunAsAdministrator { get ; set ; }
@@ -17,7 +55,6 @@ public class InstallOptions: SerializableComponent<InstallOptions>
1755 public string CustomInstallLocation { get ; set ; } = "" ;
1856 public string Version { get ; set ; } = "" ;
1957 public bool SkipMinorUpdates { get ; set ; }
20- public bool OverridesNextLevelOpts { get ; set ; }
2158 public bool RemoveDataOnUninstall { get ; set ; }
2259 public bool UninstallPreviousVersionsOnUpdate { get ; set ; }
2360 public List < string > KillBeforeOperation { get ; set ; } = [ ] ;
@@ -32,53 +69,54 @@ public class InstallOptions: SerializableComponent<InstallOptions>
3269 public string PostUninstallCommand { get ; set ; } = "" ;
3370 public bool AbortOnPreUninstallFail { get ; set ; } = true ;
3471
72+ public bool OverridesNextLevelOpts { get ; set ; }
3573
3674 public override InstallOptions Copy ( )
3775 {
38- return new ( )
39- {
40- SkipHashCheck = SkipHashCheck ,
41- Architecture = Architecture ,
42- CustomInstallLocation = CustomInstallLocation ,
43- CustomParameters_Install = CustomParameters_Install . ToList ( ) ,
44- CustomParameters_Update = CustomParameters_Update . ToList ( ) ,
45- CustomParameters_Uninstall = CustomParameters_Uninstall . ToList ( ) ,
46- InstallationScope = InstallationScope ,
47- InteractiveInstallation = InteractiveInstallation ,
48- PreRelease = PreRelease ,
49- RunAsAdministrator = RunAsAdministrator ,
50- Version = Version ,
51- SkipMinorUpdates = SkipMinorUpdates ,
52- OverridesNextLevelOpts = OverridesNextLevelOpts ,
53- RemoveDataOnUninstall = RemoveDataOnUninstall ,
54- KillBeforeOperation = KillBeforeOperation . ToList ( ) ,
55- PreInstallCommand = PreInstallCommand ,
56- PreUpdateCommand = PreUpdateCommand ,
57- PreUninstallCommand = PreUninstallCommand ,
58- PostInstallCommand = PostInstallCommand ,
59- PostUpdateCommand = PostUpdateCommand ,
60- PostUninstallCommand = PostUninstallCommand ,
61- AbortOnPreInstallFail = AbortOnPreInstallFail ,
62- AbortOnPreUpdateFail = AbortOnPreUpdateFail ,
63- AbortOnPreUninstallFail = AbortOnPreUninstallFail ,
64- UninstallPreviousVersionsOnUpdate = UninstallPreviousVersionsOnUpdate ,
65- } ;
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 ) } )") ) ;
66102 }
67103
68104 public override void LoadFromJson ( JsonNode data )
69105 {
70- // 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+ }
71112
72- this . SkipHashCheck = data [ nameof ( SkipHashCheck ) ] ? . GetVal < bool > ( ) ?? false ;
73- this . InteractiveInstallation = data [ nameof ( InteractiveInstallation ) ] ? . GetVal < bool > ( ) ?? false ;
74- this . RunAsAdministrator = data [ nameof ( RunAsAdministrator ) ] ? . GetVal < bool > ( ) ?? false ;
75- this . Architecture = data [ nameof ( Architecture ) ] ? . GetVal < string > ( ) ?? "" ;
76- this . InstallationScope = data [ nameof ( InstallationScope ) ] ? . GetVal < string > ( ) ?? "" ;
113+ foreach ( var ( stringKey , defValue ) in DefaultStringValues )
114+ SetValueToProperty ( stringKey , data [ stringKey ] ? . GetVal < string > ( ) ?? defValue ) ;
77115
78- this . CustomParameters_Install = ReadArrayFromJson ( data , nameof ( CustomParameters_Install ) ) ;
79- this . CustomParameters_Update = ReadArrayFromJson ( data , nameof ( CustomParameters_Update ) ) ;
80- this . CustomParameters_Uninstall = ReadArrayFromJson ( data , nameof ( CustomParameters_Uninstall ) ) ;
116+ foreach ( var listKey in DefaultListValues )
117+ SetValueToProperty ( listKey , ReadArrayFromJson ( data , listKey ) ) ;
81118
119+ // Handle case where setting has not been migrated yet
82120 if ( this . CustomParameters_Install . Count is 0 &&
83121 this . CustomParameters_Update . Count is 0 &&
84122 this . CustomParameters_Uninstall . Count is 0 &&
@@ -89,28 +127,42 @@ this.CustomParameters_Uninstall.Count is 0 &&
89127 this . CustomParameters_Uninstall = ReadArrayFromJson ( data , "CustomParameters" ) ;
90128 }
91129
92- this . KillBeforeOperation = ReadArrayFromJson ( data , nameof ( KillBeforeOperation ) ) ;
93- this . PreRelease = data [ nameof ( PreRelease ) ] ? . GetVal < bool > ( ) ?? false ;
94- this . CustomInstallLocation = data [ nameof ( CustomInstallLocation ) ] ? . GetVal < string > ( ) ?? "" ;
95- this . Version = data [ nameof ( Version ) ] ? . GetVal < string > ( ) ?? "" ;
96- this . SkipMinorUpdates = data [ nameof ( SkipMinorUpdates ) ] ? . GetVal < bool > ( ) ?? false ;
97- this . UninstallPreviousVersionsOnUpdate = data [ nameof ( UninstallPreviousVersionsOnUpdate ) ] ? . GetVal < bool > ( ) ?? false ;
98-
99- this . PreInstallCommand = data [ nameof ( PreInstallCommand ) ] ? . GetVal < string > ( ) ?? "" ;
100- this . PreUpdateCommand = data [ nameof ( PreUpdateCommand ) ] ? . GetVal < string > ( ) ?? "" ;
101- this . PreUninstallCommand = data [ nameof ( PreUninstallCommand ) ] ? . GetVal < string > ( ) ?? "" ;
102- this . PostInstallCommand = data [ nameof ( PostInstallCommand ) ] ? . GetVal < string > ( ) ?? "" ;
103- this . PostUpdateCommand = data [ nameof ( PostUpdateCommand ) ] ? . GetVal < string > ( ) ?? "" ;
104- this . PostUninstallCommand = data [ nameof ( PostUninstallCommand ) ] ? . GetVal < string > ( ) ?? "" ;
105- this . AbortOnPreInstallFail = data [ nameof ( AbortOnPreInstallFail ) ] ? . GetVal < bool > ( ) ?? true ;
106- this . AbortOnPreUpdateFail = data [ nameof ( AbortOnPreUpdateFail ) ] ? . GetVal < bool > ( ) ?? true ;
107- this . AbortOnPreUninstallFail = data [ nameof ( AbortOnPreUninstallFail ) ] ? . GetVal < bool > ( ) ?? true ;
108-
109130 // if OverridesNextLevelOpts is not found on the JSON, set it to true or false depending
110131 // on whether the current settings instances are different from the default values.
111132 // This entry shall be checked the last one, to ensure all other properties are set
112- this . OverridesNextLevelOpts =
113- data [ nameof ( OverridesNextLevelOpts ) ] ? . GetValue < bool > ( ) ?? DiffersFromDefault ( ) ;
133+ this . OverridesNextLevelOpts = data [ nameof ( OverridesNextLevelOpts ) ] ? . GetValue < bool > ( ) ?? DiffersFromDefault ( ) ;
134+ }
135+
136+ public override JsonNode AsJsonNode ( )
137+ {
138+ JsonObject obj = new ( ) ;
139+
140+ if ( OverridesNextLevelOpts is not false )
141+ obj . Add ( nameof ( OverridesNextLevelOpts ) , OverridesNextLevelOpts ) ;
142+
143+ foreach ( var ( boolKey , defValue ) in DefaultBoolValues )
144+ {
145+ bool currentValue = GetValueFromProperty < bool > ( boolKey ) ;
146+ if ( currentValue != defValue ) obj . Add ( boolKey , currentValue ) ;
147+ }
148+
149+ foreach ( var ( stringKey , defValue ) in DefaultStringValues )
150+ {
151+ string currentValue = GetValueFromProperty < string > ( stringKey ) ;
152+ if ( currentValue != defValue ) obj . Add ( stringKey , currentValue ) ;
153+ }
154+
155+ foreach ( var listKey in DefaultListValues )
156+ {
157+ IReadOnlyList < string > currentValue = GetValueFromProperty < IReadOnlyList < string > > ( listKey ) ;
158+
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+ }
164+
165+ return obj ;
114166 }
115167
116168 private static List < string > ReadArrayFromJson ( JsonNode data , string name )
@@ -124,30 +176,19 @@ private static List<string> ReadArrayFromJson(JsonNode data, string name)
124176
125177 public bool DiffersFromDefault ( )
126178 {
127- return SkipHashCheck is not false ||
128- InteractiveInstallation is not false ||
129- RunAsAdministrator is not false ||
130- PreRelease is not false ||
131- SkipMinorUpdates is not false ||
132- Architecture . Any ( ) ||
133- InstallationScope . Any ( ) ||
134- CustomParameters_Install . Where ( x => x . Any ( ) ) . Any ( ) ||
135- CustomParameters_Update . Where ( x => x . Any ( ) ) . Any ( ) ||
136- CustomParameters_Uninstall . Where ( x => x . Any ( ) ) . Any ( ) ||
137- KillBeforeOperation . Where ( x => x . Any ( ) ) . Any ( ) ||
138- CustomInstallLocation . Any ( ) ||
139- RemoveDataOnUninstall is not false ||
140- Version . Any ( ) ||
141- PreInstallCommand . Any ( ) ||
142- PostInstallCommand . Any ( ) ||
143- AbortOnPreInstallFail is not true ||
144- PreUpdateCommand . Any ( ) ||
145- PostUpdateCommand . Any ( ) ||
146- AbortOnPreUpdateFail is not true ||
147- PreUninstallCommand . Any ( ) ||
148- PostUninstallCommand . Any ( ) ||
149- UninstallPreviousVersionsOnUpdate is not false ||
150- 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 ;
151192 // OverridesNextLevelOpts does not need to be checked here, since
152193 // this method is invoked before this property has been set
153194 }
0 commit comments