mirror of
https://github.com/X1a0He/Adobe-Downloader.git
synced 2025-11-25 11:18:53 +08:00
fix: Fix the issue of installation failure caused by abnormal number of dependencies and packages.
This commit is contained in:
@@ -31,7 +31,7 @@
|
|||||||
shouldAutocreateTestPlan = "YES">
|
shouldAutocreateTestPlan = "YES">
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Release"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
|
|||||||
@@ -20,22 +20,6 @@
|
|||||||
landmarkType = "7">
|
landmarkType = "7">
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
</BreakpointProxy>
|
</BreakpointProxy>
|
||||||
<BreakpointProxy
|
|
||||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
|
||||||
<BreakpointContent
|
|
||||||
uuid = "A757ED7D-136A-4033-8710-3B3C60074969"
|
|
||||||
shouldBeEnabled = "No"
|
|
||||||
ignoreCount = "0"
|
|
||||||
continueAfterRunningActions = "No"
|
|
||||||
filePath = "Adobe Downloader/Utils/DownloadUtils.swift"
|
|
||||||
startingColumnNumber = "9223372036854775807"
|
|
||||||
endingColumnNumber = "9223372036854775807"
|
|
||||||
startingLineNumber = "668"
|
|
||||||
endingLineNumber = "668"
|
|
||||||
landmarkName = "handleDownload(task:productInfo:allowedPlatform:saps:)"
|
|
||||||
landmarkType = "7">
|
|
||||||
</BreakpointContent>
|
|
||||||
</BreakpointProxy>
|
|
||||||
<BreakpointProxy
|
<BreakpointProxy
|
||||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||||
<BreakpointContent
|
<BreakpointContent
|
||||||
|
|||||||
@@ -28,7 +28,12 @@ struct Adobe_DownloaderApp: App {
|
|||||||
updaterController = SPUStandardUpdaterController(startingUpdater: true, updaterDelegate: nil, userDriverDelegate: nil)
|
updaterController = SPUStandardUpdaterController(startingUpdater: true, updaterDelegate: nil, userDriverDelegate: nil)
|
||||||
|
|
||||||
if StorageData.shared.isFirstLaunch {
|
if StorageData.shared.isFirstLaunch {
|
||||||
StorageData.shared.downloadAppleSilicon = AppStatics.isAppleSilicon
|
let shouldDownloadAppleSilicon = AppStatics.isAppleSilicon
|
||||||
|
StorageData.shared.downloadAppleSilicon = shouldDownloadAppleSilicon
|
||||||
|
_downloadAppleSilicon.wrappedValue = shouldDownloadAppleSilicon
|
||||||
|
|
||||||
|
StorageData.shared.confirmRedownload = true
|
||||||
|
_confirmRedownload.wrappedValue = true
|
||||||
|
|
||||||
let systemLanguage = Locale.current.identifier
|
let systemLanguage = Locale.current.identifier
|
||||||
let matchedLanguage = AppStatics.supportedLanguages.first {
|
let matchedLanguage = AppStatics.supportedLanguages.first {
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ class NetworkManager: ObservableObject {
|
|||||||
loadingState = .loading
|
loadingState = .loading
|
||||||
do {
|
do {
|
||||||
let (saps, cdn, sapCodes) = try await networkService.fetchProductsData(
|
let (saps, cdn, sapCodes) = try await networkService.fetchProductsData(
|
||||||
version: apiVersion,
|
|
||||||
platform: allowedPlatform.joined(separator: ",")
|
platform: allowedPlatform.joined(separator: ",")
|
||||||
)
|
)
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
@@ -173,7 +172,7 @@ class NetworkManager: ObservableObject {
|
|||||||
|
|
||||||
while retryCount < maxRetries {
|
while retryCount < maxRetries {
|
||||||
do {
|
do {
|
||||||
let (saps, cdn, sapCodes) = try await networkService.fetchProductsData(version: apiVersion, platform: allowedPlatform.joined(separator: ","))
|
let (saps, cdn, sapCodes) = try await networkService.fetchProductsData(platform: allowedPlatform.joined(separator: ","))
|
||||||
|
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
self.saps = saps
|
self.saps = saps
|
||||||
|
|||||||
13
Adobe Downloader/Scripts/clean-config.sh
Normal file
13
Adobe Downloader/Scripts/clean-config.sh
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# clean-config.sh
|
||||||
|
# AdobeDownloader
|
||||||
|
#
|
||||||
|
# Created by X1a0He on 2024/11/15.
|
||||||
|
# Copyright © 2024 X1a0He. All rights reserved.
|
||||||
|
sudo /usr/bin/killall -u root -9 Adobe\ Downloader
|
||||||
|
sudo /bin/launchctl unload /Library/LaunchDaemons/com.x1a0he.macOS.Adobe-Downloader.helper.plist
|
||||||
|
sudo /bin/rm /Library/LaunchDaemons/com.x1a0he.macOS.Adobe-Downloader.helper.plist
|
||||||
|
sudo /bin/rm /Library/PrivilegedHelperTools/com.x1a0he.macOS.Adobe-Downloader.helper
|
||||||
|
sudo /bin/rm ~/Library/Preferences/com.x1a0he.macOS.Adobe-Downloader.plist
|
||||||
|
sudo /usr/bin/killall -u root -9 com.x1a0he.macOS.Adobe-Downloader.helper
|
||||||
@@ -3,15 +3,14 @@ import Foundation
|
|||||||
class NetworkService {
|
class NetworkService {
|
||||||
typealias ProductsData = (products: [String: Sap], cdn: String, sapCodes: [SapCodes])
|
typealias ProductsData = (products: [String: Sap], cdn: String, sapCodes: [SapCodes])
|
||||||
|
|
||||||
private func makeProductsURL(version: String) throws -> URL {
|
private func makeProductsURL() throws -> URL {
|
||||||
var components = URLComponents(string: NetworkConstants.productsXmlURL)
|
var components = URLComponents(string: NetworkConstants.productsXmlURL)
|
||||||
components?.queryItems = [
|
components?.queryItems = [
|
||||||
URLQueryItem(name: "_type", value: "xml"),
|
URLQueryItem(name: "_type", value: "xml"),
|
||||||
URLQueryItem(name: "channel", value: "ccm"),
|
URLQueryItem(name: "channel", value: "ccm"),
|
||||||
URLQueryItem(name: "channel", value: "sti"),
|
URLQueryItem(name: "channel", value: "sti"),
|
||||||
URLQueryItem(name: "platform", value: "osx10-64,osx10,macarm64,macuniversal"),
|
URLQueryItem(name: "platform", value: "osx10-64,osx10,macarm64,macuniversal"),
|
||||||
URLQueryItem(name: "productType", value: "Desktop"),
|
URLQueryItem(name: "productType", value: "Desktop")
|
||||||
URLQueryItem(name: "version", value: version)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
guard let url = components?.url else {
|
guard let url = components?.url else {
|
||||||
@@ -25,8 +24,8 @@ class NetworkService {
|
|||||||
headers.forEach { request.setValue($0.value, forHTTPHeaderField: $0.key) }
|
headers.forEach { request.setValue($0.value, forHTTPHeaderField: $0.key) }
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchProductsData(version: String, platform: String) async throws -> ProductsData {
|
func fetchProductsData(platform: String) async throws -> ProductsData {
|
||||||
let url = try makeProductsURL(version: version)
|
let url = try makeProductsURL()
|
||||||
var request = URLRequest(url: url)
|
var request = URLRequest(url: url)
|
||||||
request.httpMethod = "GET"
|
request.httpMethod = "GET"
|
||||||
configureRequest(&request, headers: NetworkConstants.adobeRequestHeaders)
|
configureRequest(&request, headers: NetworkConstants.adobeRequestHeaders)
|
||||||
|
|||||||
@@ -83,6 +83,14 @@ final class StorageData: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private init() {
|
private init() {
|
||||||
|
let isFirstLaunchKey = "isFirstLaunch"
|
||||||
|
if !UserDefaults.standard.contains(key: isFirstLaunchKey) {
|
||||||
|
self.isFirstLaunch = true
|
||||||
|
UserDefaults.standard.set(true, forKey: isFirstLaunchKey)
|
||||||
|
} else {
|
||||||
|
self.isFirstLaunch = UserDefaults.standard.bool(forKey: isFirstLaunchKey)
|
||||||
|
}
|
||||||
|
|
||||||
self.installedHelperBuild = UserDefaults.standard.string(forKey: "InstalledHelperBuild") ?? "0"
|
self.installedHelperBuild = UserDefaults.standard.string(forKey: "InstalledHelperBuild") ?? "0"
|
||||||
self.downloadAppleSilicon = UserDefaults.standard.bool(forKey: "downloadAppleSilicon")
|
self.downloadAppleSilicon = UserDefaults.standard.bool(forKey: "downloadAppleSilicon")
|
||||||
self.useDefaultLanguage = UserDefaults.standard.bool(forKey: "useDefaultLanguage")
|
self.useDefaultLanguage = UserDefaults.standard.bool(forKey: "useDefaultLanguage")
|
||||||
@@ -91,7 +99,6 @@ final class StorageData: ObservableObject {
|
|||||||
self.defaultDirectory = UserDefaults.standard.string(forKey: "defaultDirectory") ?? ""
|
self.defaultDirectory = UserDefaults.standard.string(forKey: "defaultDirectory") ?? ""
|
||||||
self.confirmRedownload = UserDefaults.standard.bool(forKey: "confirmRedownload")
|
self.confirmRedownload = UserDefaults.standard.bool(forKey: "confirmRedownload")
|
||||||
self.apiVersion = UserDefaults.standard.string(forKey: "apiVersion") ?? "6"
|
self.apiVersion = UserDefaults.standard.string(forKey: "apiVersion") ?? "6"
|
||||||
self.isFirstLaunch = UserDefaults.standard.bool(forKey: "isFirstLaunch")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,3 +130,9 @@ extension Notification.Name {
|
|||||||
static let storageDidChange = Notification.Name("storageDidChange")
|
static let storageDidChange = Notification.Name("storageDidChange")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension UserDefaults {
|
||||||
|
func contains(key: String) -> Bool {
|
||||||
|
return object(forKey: key) != nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -658,28 +658,49 @@ class DownloadUtils {
|
|||||||
|
|
||||||
for dependency in productInfo.dependencies {
|
for dependency in productInfo.dependencies {
|
||||||
if let dependencyVersions = saps[dependency.sapCode]?.versions {
|
if let dependencyVersions = saps[dependency.sapCode]?.versions {
|
||||||
|
var firstGuid: String?
|
||||||
|
var buildGuid: String?
|
||||||
|
|
||||||
let matchingVersions = dependencyVersions.filter {
|
let sortedVersions = dependencyVersions.sorted { version1, version2 in
|
||||||
$0.value.baseVersion == dependency.version
|
let v1Components = version1.key.split(separator: ".").compactMap { Int($0) }
|
||||||
|
let v2Components = version2.key.split(separator: ".").compactMap { Int($0) }
|
||||||
|
|
||||||
|
for i in 0..<min(v1Components.count, v2Components.count) {
|
||||||
|
if v1Components[i] != v2Components[i] {
|
||||||
|
return v1Components[i] > v2Components[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v1Components.count > v2Components.count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for version in sortedVersions {
|
||||||
|
if version.value.baseVersion == dependency.version {
|
||||||
|
if firstGuid == nil { firstGuid = version.value.buildGuid }
|
||||||
|
|
||||||
var selectedVersion: (key: String, value: Sap.Versions)? = matchingVersions.first {
|
// print("\(version.value.sapCode), \(version.key), \(allowedPlatform), \(version.value.apPlatform), \(allowedPlatform.contains(version.value.apPlatform))")
|
||||||
allowedPlatform.contains($0.value.apPlatform)
|
|
||||||
|
if allowedPlatform.contains(version.value.apPlatform) {
|
||||||
|
buildGuid = version.value.buildGuid
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedVersion = selectedVersion ?? matchingVersions.first
|
|
||||||
|
|
||||||
if let version = selectedVersion {
|
if buildGuid == nil { buildGuid = firstGuid }
|
||||||
|
if let finalBuildGuid = buildGuid {
|
||||||
productsToDownload.append(ProductsToDownload(
|
productsToDownload.append(ProductsToDownload(
|
||||||
sapCode: dependency.sapCode,
|
sapCode: dependency.sapCode,
|
||||||
version: dependency.version,
|
version: dependency.version,
|
||||||
buildGuid: version.value.buildGuid
|
buildGuid: finalBuildGuid
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for product in productsToDownload {
|
||||||
|
// print("\(product.sapCode), \(product.version), \(product.buildGuid)")
|
||||||
|
// }
|
||||||
|
|
||||||
for product in productsToDownload {
|
for product in productsToDownload {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
task.setStatus(.preparing(DownloadStatus.PrepareInfo(
|
task.setStatus(.preparing(DownloadStatus.PrepareInfo(
|
||||||
@@ -689,11 +710,11 @@ class DownloadUtils {
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let jsonString = try await getApplicationInfo(buildGuid: product.buildGuid)
|
||||||
let productDir = task.directory.appendingPathComponent("\(product.sapCode)")
|
let productDir = task.directory.appendingPathComponent("\(product.sapCode)")
|
||||||
if !FileManager.default.fileExists(atPath: productDir.path) {
|
if !FileManager.default.fileExists(atPath: productDir.path) {
|
||||||
try FileManager.default.createDirectory(at: productDir, withIntermediateDirectories: true)
|
try FileManager.default.createDirectory(at: productDir, withIntermediateDirectories: true)
|
||||||
}
|
}
|
||||||
let jsonString = try await getApplicationInfo(buildGuid: product.buildGuid)
|
|
||||||
let jsonURL = productDir.appendingPathComponent("application.json")
|
let jsonURL = productDir.appendingPathComponent("application.json")
|
||||||
try jsonString.write(to: jsonURL, atomically: true, encoding: .utf8)
|
try jsonString.write(to: jsonURL, atomically: true, encoding: .utf8)
|
||||||
|
|
||||||
@@ -704,7 +725,15 @@ class DownloadUtils {
|
|||||||
throw NetworkError.invalidData("无法解析产品信息")
|
throw NetworkError.invalidData("无法解析产品信息")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var corePackageCount = 0
|
||||||
|
var nonCorePackageCount = 0
|
||||||
|
|
||||||
for package in packageArray {
|
for package in packageArray {
|
||||||
|
let packageType = package["Type"] as? String ?? "non-core"
|
||||||
|
let isCore = packageType == "core"
|
||||||
|
|
||||||
|
guard let downloadURL = package["Path"] as? String, !downloadURL.isEmpty else { continue }
|
||||||
|
|
||||||
let fullPackageName: String
|
let fullPackageName: String
|
||||||
if let name = package["fullPackageName"] as? String, !name.isEmpty {
|
if let name = package["fullPackageName"] as? String, !name.isEmpty {
|
||||||
fullPackageName = name
|
fullPackageName = name
|
||||||
@@ -712,33 +741,18 @@ class DownloadUtils {
|
|||||||
fullPackageName = "\(name).zip"
|
fullPackageName = "\(name).zip"
|
||||||
} else { continue }
|
} else { continue }
|
||||||
|
|
||||||
let packageType = package["Type"] as? String ?? "non-core"
|
let downloadSize: Int64
|
||||||
let isLanguageSuitable: Bool
|
if let sizeNumber = package["DownloadSize"] as? NSNumber {
|
||||||
if packageType == "core" {
|
downloadSize = sizeNumber.int64Value
|
||||||
isLanguageSuitable = true
|
} else if let sizeString = package["DownloadSize"] as? String,
|
||||||
} else {
|
let parsedSize = Int64(sizeString) {
|
||||||
let condition = package["Condition"] as? String ?? ""
|
downloadSize = parsedSize
|
||||||
let osLang = Locale.current.identifier
|
} else if let sizeInt = package["DownloadSize"] as? Int {
|
||||||
isLanguageSuitable = (
|
downloadSize = Int64(sizeInt)
|
||||||
task.language == "ALL" || condition.isEmpty ||
|
} else { continue }
|
||||||
!condition.contains("[installLanguage]") || condition.contains("[installLanguage]==\(task.language)") ||
|
|
||||||
condition.contains("[installLanguage]==\(osLang)")
|
if isCore {
|
||||||
)
|
corePackageCount += 1
|
||||||
}
|
|
||||||
|
|
||||||
if isLanguageSuitable {
|
|
||||||
let downloadSize: Int64
|
|
||||||
if let sizeNumber = package["DownloadSize"] as? NSNumber {
|
|
||||||
downloadSize = sizeNumber.int64Value
|
|
||||||
} else if let sizeString = package["DownloadSize"] as? String,
|
|
||||||
let parsedSize = Int64(sizeString) {
|
|
||||||
downloadSize = parsedSize
|
|
||||||
} else if let sizeInt = package["DownloadSize"] as? Int {
|
|
||||||
downloadSize = Int64(sizeInt)
|
|
||||||
} else { continue }
|
|
||||||
|
|
||||||
guard let downloadURL = package["Path"] as? String, !downloadURL.isEmpty else { continue }
|
|
||||||
|
|
||||||
let newPackage = Package(
|
let newPackage = Package(
|
||||||
type: packageType,
|
type: packageType,
|
||||||
fullPackageName: fullPackageName,
|
fullPackageName: fullPackageName,
|
||||||
@@ -746,6 +760,31 @@ class DownloadUtils {
|
|||||||
downloadURL: downloadURL
|
downloadURL: downloadURL
|
||||||
)
|
)
|
||||||
product.packages.append(newPackage)
|
product.packages.append(newPackage)
|
||||||
|
} else {
|
||||||
|
let languageIsSuitable: Bool
|
||||||
|
if task.language == "ALL" {
|
||||||
|
languageIsSuitable = true
|
||||||
|
} else if !package.keys.contains("Condition") {
|
||||||
|
languageIsSuitable = true
|
||||||
|
} else if let condition = package["Condition"] as? String {
|
||||||
|
let matchesTaskLang = condition.contains("[installLanguage]==\(task.language)")
|
||||||
|
let matchesOSLang = condition.contains("[installLanguage]==en_US")
|
||||||
|
languageIsSuitable = matchesTaskLang || matchesOSLang
|
||||||
|
} else {
|
||||||
|
languageIsSuitable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if languageIsSuitable {
|
||||||
|
nonCorePackageCount += 1
|
||||||
|
let newPackage = Package(
|
||||||
|
type: packageType,
|
||||||
|
fullPackageName: fullPackageName,
|
||||||
|
downloadSize: downloadSize,
|
||||||
|
downloadURL: downloadURL
|
||||||
|
)
|
||||||
|
product.packages.append(newPackage)
|
||||||
|
} else {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user