Skip to content

Commit 069eeec

Browse files
committed
Refactor MSStoreService
- improved filtering of outdated packages - delete a package diretory if exists before downloading a new one
1 parent 5d4fdd4 commit 069eeec

File tree

3 files changed

+102
-57
lines changed

3 files changed

+102
-57
lines changed

lib/models/ms_store/packages_info.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ part 'packages_info.freezed.dart';
33
part 'packages_info.g.dart';
44

55
@freezed
6-
class PackagesInfo with _$PackagesInfo implements Comparable<PackagesInfo>{
6+
class PackagesInfo with _$PackagesInfo implements Comparable<PackagesInfo> {
77
PackagesInfo._();
88

99
factory PackagesInfo(
@@ -15,6 +15,7 @@ class PackagesInfo with _$PackagesInfo implements Comparable<PackagesInfo>{
1515
String? id,
1616
double? size,
1717
String? digest,
18+
DateTime? lastModified,
1819
int? originalIndex,
1920
String? commandLines) = _PackagesInfo;
2021

lib/services/msstore_service.dart

Lines changed: 91 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:io';
22
import 'package:collection/collection.dart';
33
import 'package:dio/dio.dart';
44
import 'package:fluent_ui/fluent_ui.dart';
5+
import 'package:mixin_logger/mixin_logger.dart';
56
import 'package:process_run/cmd_run.dart';
67
import 'package:process_run/shell_run.dart';
78
import '../models/ms_store/non_uwp_response.dart';
@@ -41,21 +42,22 @@ class MSStoreService {
4142
);
4243

4344
static final _regex = RegExp(r'"WuCategoryId":"([^"]+)"');
44-
static final _namePattern = RegExp(r'^[^_]+');
45+
static final _namePattern = RegExp(r'^[^_]+', multiLine: true);
4546

4647
/// major.minor.build.revision
47-
static final _versionPattern = RegExp(r'_(\d+\.\d+\.\d+\.\d+)_');
48-
49-
static const _validUWPExtensions = {
50-
"appx",
51-
"appxbundle",
52-
"msix",
53-
"msixbundle",
54-
// "eappx",
55-
// "eappxbundle",
56-
// "emsix",
57-
// "emsixbundle"
58-
};
48+
// static final _versionPattern = RegExp(r'_(\d+\.\d+\.\d+\.\d+)_');
49+
50+
// static const _validUWPExtensions = {
51+
// "appx",
52+
// "appxbundle",
53+
// "msix",
54+
// "msixbundle",
55+
// // "eappx",
56+
// // "eappxbundle",
57+
// // "emsix",
58+
// // "emsixbundle"
59+
// };
60+
5961
static var _cookie = "";
6062

6163
final _dio = Dio();
@@ -158,10 +160,11 @@ class MSStoreService {
158160
data: cookie2, options: _optionsSoapXML, cancelToken: _cancelToken);
159161

160162
if (response.statusCode == 200) {
161-
return xml.XmlDocument.parse(response.data)
163+
final xmlDoc = xml.XmlDocument.parse(response.data)
162164
.toString()
163165
.replaceAll("&lt;", "<")
164166
.replaceAll("&gt;", ">");
167+
return xmlDoc;
165168
}
166169
throw Exception('Failed to get file list xml');
167170
}
@@ -199,6 +202,7 @@ class MSStoreService {
199202
-1,
200203
"",
201204
null,
205+
null,
202206
installer.installerSwitches!.silent,
203207
),
204208
);
@@ -217,13 +221,14 @@ class MSStoreService {
217221

218222
for (final node in xmlDoc.findAllElements("File")) {
219223
if (node.getAttribute("InstallerSpecificIdentifier") != null) {
220-
String name = node.getAttribute("InstallerSpecificIdentifier")!;
221-
String digest = node.getAttribute("Digest")!;
224+
final name = node.getAttribute("InstallerSpecificIdentifier")!;
225+
final digest = node.getAttribute("Digest")!;
226+
final modified = node.getAttribute("Modified")!;
222227

223228
packageMap.putIfAbsent(
224229
name,
225230
() =>
226-
'${node.getAttribute("FileName")!.substring(node.getAttribute("FileName")!.lastIndexOf('.') + 1)}|${node.getAttribute("Size")!}|$digest');
231+
'${node.getAttribute("FileName")!.substring(node.getAttribute("FileName")!.lastIndexOf('.') + 1)}|${node.getAttribute("Size")!}|$digest|$modified');
227232
}
228233
}
229234

@@ -236,25 +241,27 @@ class MSStoreService {
236241
.getAttribute("PackageMoniker");
237242
if (name != null) {
238243
final package = packageMap[name]!;
239-
final extension = package.split('|')[0];
244+
final ext = package.split('|')[0];
245+
final size = double.parse(package.split('|')[1]);
240246
final digest = package.split('|')[2];
247+
final lastModified = DateTime.parse(package.split('|')[3]);
248+
241249
final updateIdentity =
242250
node.parent!.parent!.getElement('UpdateIdentity')!;
243251

244-
if (_validUWPExtensions.contains(extension) &&
245-
!name.contains("Microsoft.Advertising") &&
246-
name.contains("x64") ||
247-
name.contains("neutral")) {
252+
if (!name.contains("Microsoft.Advertising") && name.contains("x64") ||
253+
name.contains("neutral") && !ext.startsWith("e")) {
248254
packages.add(PackagesInfo(
249255
name,
250-
extension,
256+
ext,
251257
await _getUri(updateIdentity.getAttribute('UpdateID')!,
252258
updateIdentity.getAttribute('RevisionNumber')!, ring, digest),
253259
updateIdentity.getAttribute('RevisionNumber')!,
254260
updateIdentity.getAttribute('UpdateID')!,
255261
node.parent!.parent!.parent!.getElement('ID')!.value,
256-
double.parse(package.split('|')[1]),
262+
size,
257263
digest,
264+
lastModified,
258265
null,
259266
null,
260267
));
@@ -311,6 +318,7 @@ class MSStoreService {
311318
entry.value.id,
312319
entry.value.size,
313320
entry.value.digest,
321+
entry.value.lastModified,
314322
entry.key,
315323
null))
316324
.toList()
@@ -319,51 +327,79 @@ class MSStoreService {
319327
return groupedItems;
320328
}
321329

322-
/// Returns a list of latest UWP packages
323330
List<PackagesInfo> _getLatestPackages(
324331
Map<String?, List<PackagesInfo>> groupedPackages) {
325332
if (groupedPackages.isEmpty) return [];
326333

327334
final latestGenPackages = groupedPackages.values.map((group) {
328-
Map<String, PackagesInfo> versionMap = {};
329-
335+
Map<PackagesInfo, DateTime> versionMap = {};
330336
for (final package in group) {
331-
final match = _versionPattern.firstMatch(package.name!);
332-
333-
if (match != null) {
334-
final ver = match.group(1)!;
335-
336-
if (!versionMap.containsKey(ver)) {
337-
versionMap[ver] = package;
338-
} else {
339-
final lastSavedVer =
340-
versionMap[ver]!.name!.split('.').map(int.parse).toList();
341-
final currentVer = package.name!.split('.').map(int.parse).toList();
342-
343-
final lastSavedVerLength = lastSavedVer.length;
344-
final currentverLength = currentVer.length;
345-
346-
for (int i = 0; i < currentverLength; i++) {
347-
if (i >= lastSavedVerLength || currentVer[i] > lastSavedVer[i]) {
348-
versionMap[ver] = package;
349-
break;
350-
} else if (currentVer[i] < lastSavedVer[i]) {
351-
break;
352-
}
353-
}
337+
if (versionMap.isEmpty) {
338+
versionMap[package] = package.lastModified!;
339+
} else {
340+
final lastSavedVer = versionMap.values.first;
341+
final currentVer = package.lastModified!;
342+
343+
if (currentVer.isAfter(lastSavedVer)) {
344+
versionMap.clear();
345+
versionMap[package] = currentVer;
354346
}
355347
}
356348
}
357-
358-
final latestVersion = versionMap.keys
359-
.reduce((curr, next) => curr.compareTo(next) > 0 ? curr : next);
360-
361-
return versionMap[latestVersion]!;
349+
return versionMap.keys.first;
362350
}).toList();
363351

364352
return latestGenPackages;
365353
}
366354

355+
/// Returns a list of latest UWP packages
356+
// List<PackagesInfo> _getLatestPackages(
357+
// Map<String?, List<PackagesInfo>> groupedPackages) {
358+
// if (groupedPackages.isEmpty) return [];
359+
360+
// final latestGenPackages = groupedPackages.values.map((group) {
361+
// Map<String, PackagesInfo> versionMap = {};
362+
363+
// for (final package in group) {
364+
// final match = _versionPattern.firstMatch(package.name!);
365+
366+
// if (match != null) {
367+
// final ver = match.group(1)!;
368+
369+
// if (versionMap.isEmpty) {
370+
// versionMap[ver] = package;
371+
// } else {
372+
// debugPrint("Version: $ver");
373+
// final lastSavedVer =
374+
// versionMap.keys.first.split('.').map(int.parse).toList();
375+
376+
// final currentVer = ver.split('.').map(int.parse).toList();
377+
378+
// final lastSavedVerLength = lastSavedVer.length;
379+
// final currentverLength = currentVer.length;
380+
381+
// for (int i = 0; i < currentverLength; i++) {
382+
// if (i >= lastSavedVerLength || currentVer[i] > lastSavedVer[i]) {
383+
// versionMap.clear();
384+
// versionMap[ver] = package;
385+
// break;
386+
// } else if (currentVer[i] < lastSavedVer[i]) {
387+
// break;
388+
// }
389+
// }
390+
// }
391+
// }
392+
// }
393+
394+
// final latestVersion = versionMap.keys
395+
// .reduce((curr, next) => curr.compareTo(next) > 0 ? curr : next);
396+
397+
// return versionMap[latestVersion]!;
398+
// }).toList();
399+
400+
// return latestGenPackages;
401+
// }
402+
367403
Future<List<ProcessResult>> installUWPPackages(String path) async {
368404
return await run(
369405
'powershell -NoP -ExecutionPolicy Bypass -NonInteractive -C "& {\$appxFiles = Get-ChildItem -Path "$path"; foreach (\$file in \$appxFiles) { Add-AppxPackage -ForceApplicationShutdown -Path \$file.FullName; echo "\$(\$file.Name)";}}"',

lib/widgets/download_widget.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,18 @@ class _DownloadWidgetState extends State<DownloadWidget> {
3535
@override
3636
void initState() {
3737
super.initState();
38+
39+
final String path =
40+
'${Directory.systemTemp.path}\\Revision-Tool\\MSStore\\${widget.productId}';
41+
final Directory directory = Directory(path);
42+
if (directory.existsSync()) {
43+
directory.deleteSync(recursive: true);
44+
}
45+
3846
_streams = widget.items
3947
.map((item) => _dio.download(
4048
item.uri!,
41-
'${Directory.systemTemp.path}\\Revision-Tool\\MSStore\\${widget.productId}\\${item.name}.${item.extension}',
49+
'$path\\${item.name}.${item.extension}',
4250
cancelToken: CancelToken(),
4351
onReceiveProgress: (received, total) {
4452
if (total != -1) {

0 commit comments

Comments
 (0)