@@ -46,28 +46,38 @@ extension AppState {
4646 }
4747
4848 func downloadRuntime( runtime: DownloadableRuntime ) {
49- self . runtimePublishers [ runtime. identifier] = downloadRunTimeFull ( runtime: runtime)
50- . receive ( on: DispatchQueue . main)
51- . sink (
52- receiveCompletion: { [ unowned self] completion in
53- self . runtimePublishers [ runtime. identifier] = nil
54- if case let . failure( error) = completion {
55- // // Prevent setting the app state error if it is an invalid session, we will present the sign in view instead
56- // if error as? AuthenticationError != .invalidSession {
57- // self.error = error
58- // self.presentedAlert = .generic(title: localizeString("Alert.Install.Error.Title"), message: error.legibleLocalizedDescription)
59- // }
60- // if let index = self.allXcodes.firstIndex(where: { $0.id == id }) {
61- // self.allXcodes[index].installState = .notInstalled
62- // }
63- }
64- } ,
65- receiveValue: { _ in }
66- )
49+ Task {
50+ try ? await downloadRunTimeFull ( runtime: runtime)
51+ }
52+
53+ // self.runtimePublishers[runtime.identifier] = downloadRunTimeFull(runtime: runtime)
54+ // .receive(on: DispatchQueue.main)
55+ // .sink(
56+ // receiveCompletion: { [unowned self] completion in
57+ // self.runtimePublishers[runtime.identifier] = nil
58+ // if case let .failure(error) = completion {
59+ // Logger.appState.error("Error downloading runtime: \(error.localizedDescription)")
60+ //// // Prevent setting the app state error if it is an invalid session, we will present the sign in view instead
61+ //// if error as? AuthenticationError != .invalidSession {
62+ //// self.error = error
63+ //// self.presentedAlert = .generic(title: localizeString("Alert.Install.Error.Title"), message: error.legibleLocalizedDescription)
64+ //// }
65+ //// if let index = self.allXcodes.firstIndex(where: { $0.id == id }) {
66+ //// self.allXcodes[index].installState = .notInstalled
67+ //// }
68+ // }
69+ // },
70+ // receiveValue: { _ in }
71+ // )
6772 }
6873
69- func downloadRunTimeFull( runtime: DownloadableRuntime ) -> AnyPublisher < ( DownloadableRuntime , URL ) , Error > {
70- // gets a proper cookie for runtimes
74+ func downloadRunTimeFull( runtime: DownloadableRuntime ) async throws {
75+ // sets a proper cookie for runtimes
76+ try await validateADCSession ( path: runtime. downloadPath)
77+
78+ let downloader = Downloader ( rawValue: UserDefaults . standard. string ( forKey: " downloader " ) ?? " aria2 " ) ?? . aria2
79+ Logger . appState. info ( " Downloading \( runtime. visibleIdentifier) with \( downloader) " )
80+
7181
7282 return validateADCSession ( path: runtime. downloadPath)
7383 . flatMap { _ in
@@ -82,6 +92,18 @@ extension AppState {
8292 } )
8393 . map { return ( runtime, $0) }
8494 }
95+ . flatMap { runtime, url -> AnyPublisher < URL , Error > in
96+ switch runtime. contentType {
97+ case . package :
98+ return self . installFromPackage ( dmgURL: url, runtime: runtime)
99+ case . diskImage:
100+ return self . installFromImage ( dmgURL: url)
101+ }
102+ }
103+ . map { url in
104+ // Done deleting
105+ Logger . appState. debug ( " URL: \( url) " )
106+ }
85107 . eraseToAnyPublisher ( )
86108 }
87109
@@ -92,7 +114,9 @@ extension AppState {
92114 // use runtime.url for final with cookies
93115
94116 // Check to see if the archive is in the expected path in case it was downloaded but failed to install
95- let expectedRuntimePath = Path . xcodesApplicationSupport/ " \( runtime. name) . \( runtime. name. suffix ( fromLast: " . " ) ) "
117+ // let expectedRuntimePath = Path.xcodesApplicationSupport/"\(runtime.name).\(runtime.name.suffix(fromLast: "."))"
118+ let url = URL ( string: runtime. source) !
119+ let expectedRuntimePath = Path . xcodesApplicationSupport/ " \( url. lastPathComponent) "
96120 // aria2 downloads directly to the destination (instead of into /tmp first) so we need to make sure that the download isn't incomplete
97121 let aria2DownloadMetadataPath = expectedRuntimePath. parent/ ( expectedRuntimePath. basename ( ) + " .aria2 " )
98122 var aria2DownloadIsIncomplete = false
@@ -106,7 +130,8 @@ extension AppState {
106130 . eraseToAnyPublisher ( )
107131 }
108132 else {
109- // let destination = Path.xcodesApplicationSupport/"Xcode-\(availableXcode.version).\(availableXcode.filename.suffix(fromLast: "."))"
133+
134+ Logger . appState. info ( " Downloading runtime: \( url. lastPathComponent) " )
110135 switch downloader {
111136 case . aria2:
112137 let aria2Path = Path ( url: Bundle . main. url ( forAuxiliaryExecutable: " aria2c " ) !) !
@@ -115,12 +140,7 @@ extension AppState {
115140 to: expectedRuntimePath,
116141 aria2Path: aria2Path,
117142 progressChanged: progressChanged)
118- // return downloadXcodeWithAria2(
119- // availableXcode,
120- // to: destination,
121- // aria2Path: aria2Path,
122- // progressChanged: progressChanged
123- // )
143+
124144 case . urlSession:
125145
126146 return Just ( runtime. url)
@@ -134,7 +154,6 @@ extension AppState {
134154// )
135155 }
136156 }
137-
138157 }
139158
140159 public func downloadRuntimeWithAria2( _ runtime: DownloadableRuntime , to destination: Path , aria2Path: Path , progressChanged: @escaping ( Progress ) -> Void ) -> AnyPublisher < URL , Error > {
@@ -151,4 +170,54 @@ extension AppState {
151170 . map { _ in destination. url }
152171 . eraseToAnyPublisher ( )
153172 }
173+
174+ public func downloadRuntimeWithAria2( _ runtime: DownloadableRuntime , to destination: Path , aria2Path: Path , progressChanged: @escaping ( Progress ) -> Void ) async -> URL {
175+
176+ }
177+
178+ public func installFromImage( dmgURL: URL ) -> AnyPublisher < URL , Error > {
179+
180+
181+ try ? self . runtimeService. installRuntimeImage ( dmgURL: dmgURL)
182+
183+
184+ return Just ( dmgURL)
185+ . setFailureType ( to: Error . self)
186+ . eraseToAnyPublisher ( )
187+
188+ }
189+
190+ public func installFromPackage( dmgURL: URL , runtime: DownloadableRuntime ) -> AnyPublisher < URL , Error > {
191+ Logger . appState. info ( " Mounting DMG " )
192+ Task {
193+ do {
194+ let mountedUrl = try await self . runtimeService. mountDMG ( dmgUrl: dmgURL)
195+
196+ // 2-Get the first path under the mounted path, should be a .pkg
197+ let pkgPath = Path ( url: mountedUrl) !. ls ( ) . first!
198+ try Path . xcodesCaches. mkdir ( ) . setCurrentUserAsOwner ( )
199+
200+ let expandedPkgPath = Path . xcodesCaches/ runtime. identifier
201+ //try expandedPkgPath.mkdir()
202+ Logger . appState. info ( " PKG Path: \( pkgPath) " )
203+ Logger . appState. info ( " Expanded PKG Path: \( expandedPkgPath) " )
204+ //try? Current.files.removeItem(at: expandedPkgPath.url)
205+
206+ // 5-Expand (not install) the pkg to temporary path
207+ try await self . runtimeService. expand ( pkgPath: pkgPath, expandedPkgPath: expandedPkgPath)
208+ //try await self.runtimeService.unmountDMG(mountedURL: mountedUrl)
209+
210+ } catch {
211+ Logger . appState. error ( " Error installing runtime: \( error. localizedDescription) " )
212+ }
213+
214+ }
215+
216+
217+
218+ return Just ( dmgURL)
219+ . setFailureType ( to: Error . self)
220+ . eraseToAnyPublisher ( )
221+ }
222+
154223}
0 commit comments