@@ -44,40 +44,37 @@ final class DownloadQueueObserver: CKDownloadQueueObserver {
4444 return
4545 }
4646
47- let appNameAndVersion = metadata. appNameAndVersion
48- let currPhaseType = status. activePhase? . phaseType
47+ let currPhaseType = status. activePhaseType
4948 if prevPhaseType != currPhaseType {
5049 switch currPhaseType {
51- case downloadingPhaseType :
52- if prevPhaseType == initialPhaseType {
53- MAS . printer. progress ( status : status , for: appNameAndVersion)
50+ case . downloading :
51+ if prevPhaseType == . initial {
52+ MAS . printer. progress ( phase : currPhaseType , for: metadata . appNameAndVersion)
5453 }
55- case downloadedPhaseType :
56- if prevPhaseType == downloadingPhaseType {
57- MAS . printer. progress ( status : status , for: appNameAndVersion)
54+ case . downloaded :
55+ if prevPhaseType == . downloading {
56+ MAS . printer. progress ( phase : currPhaseType , for: metadata . appNameAndVersion)
5857 }
59- case installingPhaseType :
60- MAS . printer. progress ( status : status , for: appNameAndVersion)
58+ case . installing :
59+ MAS . printer. progress ( phase : currPhaseType , for: metadata . appNameAndVersion)
6160 default :
6261 break
6362 }
6463 }
6564
66- if isatty ( FileHandle . standardOutput. fileDescriptor) != 0 {
67- // Only output the progress bar if connected to a terminal
68- let percentComplete = min (
69- status. percentComplete / ( currPhaseType == downloadingPhaseType ? 0.8 : 0.2 ) ,
70- 1.0
71- )
65+ let percentComplete = status. phasePercentComplete
66+ if isatty ( FileHandle . standardOutput. fileDescriptor) != 0 , percentComplete != 0 || currPhaseType != . initial {
67+ // Output the progress bar iff connected to a terminal
7268 let totalLength = 60
7369 let completedLength = Int ( percentComplete * Float( totalLength) )
74- MAS . printer. ephemeral (
70+ MAS . printer. clearCurrentLine ( of: . standardOutput)
71+ MAS . printer. info (
7572 String ( repeating: " # " , count: completedLength) ,
7673 String ( repeating: " - " , count: totalLength - completedLength) ,
7774 " " ,
7875 String ( format: " %.0f%% " , floor ( percentComplete * 100 ) . rounded ( ) ) ,
7976 " " ,
80- status. activePhaseDescription ,
77+ status. activePhaseType . description ,
8178 separator: " " ,
8279 terminator: " "
8380 )
@@ -99,19 +96,29 @@ final class DownloadQueueObserver: CKDownloadQueueObserver {
9996 return
10097 }
10198
102- MAS . printer. terminateEphemeral ( )
99+ MAS . printer. clearCurrentLine ( of : . standardOutput )
103100
104- guard !status. isFailed else {
105- errorHandler ? ( status. error ?? MASError . runtimeError ( " Failed to download \( metadata. appNameAndVersion) " ) )
106- return
107- }
108- guard !status. isCancelled else {
109- shouldCancel ( download, false ) ? completionHandler ? ( ) : errorHandler ? ( MASError . runtimeError ( " Download cancelled " ) )
110- return
111- }
101+ do {
102+ if let error = status. error {
103+ throw error
104+ }
105+ guard !status. isFailed else {
106+ throw MASError . runtimeError ( " Failed to download \( metadata. appNameAndVersion) " )
107+ }
108+ guard !status. isCancelled else {
109+ guard shouldCancel ( download, false ) else {
110+ throw MASError . runtimeError ( " Download cancelled " )
111+ }
112112
113- MAS . printer. notice ( " Installed " , metadata. appNameAndVersion)
114- completionHandler ? ( )
113+ completionHandler ? ( )
114+ return
115+ }
116+
117+ MAS . printer. notice ( " Installed " , metadata. appNameAndVersion)
118+ completionHandler ? ( )
119+ } catch {
120+ errorHandler ? ( error)
121+ }
115122 }
116123
117124 func observeDownloadQueue( _ queue: CKDownloadQueue = . shared( ) ) async throws {
@@ -135,12 +142,38 @@ final class DownloadQueueObserver: CKDownloadQueueObserver {
135142 }
136143}
137144
138- private typealias PhaseType = Int64
145+ private enum PhaseType : Int64 { // swiftlint:disable sorted_enum_cases
146+ case initial = 4 // swiftlint:disable:previous one_declaration_per_file
147+ case downloading = 0
148+ case downloaded = 5
149+ case installing = 1 // swiftlint:enable sorted_enum_cases
150+ }
151+
152+ extension PhaseType : CustomStringConvertible {
153+ var description : String {
154+ switch self {
155+ case . downloading:
156+ " Downloading "
157+ case . downloaded:
158+ " Downloaded "
159+ case . installing:
160+ " Installing "
161+ default :
162+ " Waiting "
163+ }
164+ }
165+ }
166+
167+ private extension PhaseType ? {
168+ var description : String {
169+ map ( \. description) ?? " Processing "
170+ }
171+ }
139172
140173private extension Printer {
141- func progress( status : SSDownloadStatus , for appNameAndVersion: String ) {
142- terminateEphemeral ( )
143- notice ( status . activePhaseDescription , appNameAndVersion)
174+ func progress( phase : PhaseType ? , for appNameAndVersion: String ) {
175+ clearCurrentLine ( of : . standardOutput )
176+ notice ( phase . description , appNameAndVersion)
144177 }
145178}
146179
@@ -151,23 +184,7 @@ private extension SSDownloadMetadata {
151184}
152185
153186private extension SSDownloadStatus {
154- var activePhaseDescription : String {
155- switch activePhase? . phaseType {
156- case downloadedPhaseType:
157- " Downloaded "
158- case downloadingPhaseType:
159- " Downloading "
160- case installingPhaseType:
161- " Installing "
162- case nil :
163- " Processing "
164- default :
165- " Waiting "
166- }
187+ var activePhaseType : PhaseType ? {
188+ activePhase. flatMap { PhaseType ( rawValue: $0. phaseType) }
167189 }
168190}
169-
170- private let downloadingPhaseType = 0 as PhaseType
171- private let installingPhaseType = 1 as PhaseType
172- private let initialPhaseType = 4 as PhaseType
173- private let downloadedPhaseType = 5 as PhaseType
0 commit comments