Skip to content

Commit

Permalink
improve current state parsing, don't crash when state is unknown
Browse files Browse the repository at this point in the history
  • Loading branch information
lukepistrol committed Oct 15, 2024
1 parent 57c03e4 commit 1e436bc
Show file tree
Hide file tree
Showing 19 changed files with 440 additions and 13 deletions.
8 changes: 8 additions & 0 deletions TimeMachineStatus.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
2818227A2AFE292A0067E564 /* UserfacingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 281822792AFE292A0067E564 /* UserfacingError.swift */; };
2818227C2AFE33CA0067E564 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2818227B2AFE33CA0067E564 /* Constants.swift */; };
2818227E2AFE36780067E564 /* Bundle+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2818227D2AFE36780067E564 /* Bundle+.swift */; };
281C819E2CBC887D00CDFED6 /* HiddenViewModifier+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 281C819D2CBC887D00CDFED6 /* HiddenViewModifier+.swift */; };
28263F912B023D4E00F74655 /* HelperAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28263F902B023D4E00F74655 /* HelperAppDelegate.swift */; };
28263FA32B023FFE00F74655 /* ServiceManagement.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28263FA22B023FFE00F74655 /* ServiceManagement.framework */; };
28710D2F2CAF16AF00033855 /* Timer+Sendable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28710D2E2CAF16AF00033855 /* Timer+Sendable.swift */; };
Expand Down Expand Up @@ -58,6 +59,7 @@
28F2D4412B0257E700B75998 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2818227B2AFE33CA0067E564 /* Constants.swift */; };
28F2D4452B02F2F300B75998 /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 28F2D4442B02F2F300B75998 /* Sparkle */; };
28F2D4472B02F62400B75998 /* UpdaterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28F2D4462B02F62400B75998 /* UpdaterViewModel.swift */; };
28F7A65E2CBE5323000158D5 /* Unknown.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28F7A65D2CBE5323000158D5 /* Unknown.swift */; };
28FAD5A72AFE3DBF00F642E7 /* CardViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28FAD5A62AFE3DBF00F642E7 /* CardViewModifier.swift */; };
28FAD5A92AFE9BCB00F642E7 /* DestinationInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28FAD5A82AFE9BCB00F642E7 /* DestinationInfoView.swift */; };
28FAD5AB2AFE9BF300F642E7 /* CustomLabeledContentStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28FAD5AA2AFE9BF300F642E7 /* CustomLabeledContentStyle.swift */; };
Expand Down Expand Up @@ -101,6 +103,7 @@
281822792AFE292A0067E564 /* UserfacingError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserfacingError.swift; sourceTree = "<group>"; };
2818227B2AFE33CA0067E564 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
2818227D2AFE36780067E564 /* Bundle+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+.swift"; sourceTree = "<group>"; };
281C819D2CBC887D00CDFED6 /* HiddenViewModifier+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HiddenViewModifier+.swift"; sourceTree = "<group>"; };
28263F902B023D4E00F74655 /* HelperAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelperAppDelegate.swift; sourceTree = "<group>"; };
28263FA22B023FFE00F74655 /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; };
28263FA42B0241E200F74655 /* TimeMachineStatusHelper.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = TimeMachineStatusHelper.entitlements; sourceTree = "<group>"; };
Expand Down Expand Up @@ -131,6 +134,7 @@
28F2D43F2B02560400B75998 /* LaunchItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchItemProvider.swift; sourceTree = "<group>"; };
28F2D4462B02F62400B75998 /* UpdaterViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdaterViewModel.swift; sourceTree = "<group>"; };
28F2D4482B03000900B75998 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
28F7A65D2CBE5323000158D5 /* Unknown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Unknown.swift; sourceTree = "<group>"; };
28FAD5A62AFE3DBF00F642E7 /* CardViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardViewModifier.swift; sourceTree = "<group>"; };
28FAD5A82AFE9BCB00F642E7 /* DestinationInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DestinationInfoView.swift; sourceTree = "<group>"; };
28FAD5AA2AFE9BF300F642E7 /* CustomLabeledContentStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomLabeledContentStyle.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -277,6 +281,7 @@
281822662AFD86AC0067E564 /* Color+RawRepresentable.swift */,
2888D17B2C99B3E80081FBBB /* KeyedDecodingContainer+.swift */,
28710D2E2CAF16AF00033855 /* Timer+Sendable.swift */,
281C819D2CBC887D00CDFED6 /* HiddenViewModifier+.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -315,6 +320,7 @@
281822682AFD8E5A0067E564 /* Internal */,
28A002542AFC03E300E2A01E /* BackupState.swift */,
28A0025B2AFC04B300E2A01E /* Idle.swift */,
28F7A65D2CBE5323000158D5 /* Unknown.swift */,
2818225C2AFD3FB80067E564 /* FindingBackupVolume.swift */,
28A0026F2AFC342100E2A01E /* Starting.swift */,
28A0025D2AFC04D300E2A01E /* Mounting.swift */,
Expand Down Expand Up @@ -534,7 +540,9 @@
28F2D4472B02F62400B75998 /* UpdaterViewModel.swift in Sources */,
28A0026E2AFC312000E2A01E /* Finishing.swift in Sources */,
28A0026C2AFC0CC700E2A01E /* Preferences.swift in Sources */,
28F7A65E2CBE5323000158D5 /* Unknown.swift in Sources */,
281822512AFCF8750067E564 /* DestinationCell.swift in Sources */,
281C819E2CBC887D00CDFED6 /* HiddenViewModifier+.swift in Sources */,
28A002552AFC03E300E2A01E /* BackupState.swift in Sources */,
281822592AFCFAE50067E564 /* AppDelegate.swift in Sources */,
);
Expand Down
16 changes: 16 additions & 0 deletions TimeMachineStatus/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,22 @@
}
}
},
"D" : {
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "D"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "D"
}
}
}
},
"dest_info_encrypted" : {
"extractionState" : "manual",
"localizations" : {
Expand Down
21 changes: 17 additions & 4 deletions TimeMachineStatus/Model/BackupState/BackupState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,15 @@ enum BackupState {
throw BackupStateError.couldNotConvertStringToData(string: result)
}

if let state = try _decodePlist(data) {
if let state = try? _decodePlist(data, raw: result) {
return state
}
#if DEBUG
log.error("Unknown state: \(result)")
fatalError("Unknown state: \(result)")
#else
throw BackupStateError.invalidState(raw: result)
#endif
}
}

Expand All @@ -42,7 +47,7 @@ extension BackupState {
}()

// swiftlint:disable:next cyclomatic_complexity
private static func _decodePlist(_ data: Data) throws -> _State? {
private static func _decodePlist(_ data: Data, raw: String) throws -> _State {
let decoder = PropertyListDecoder()
let state = try decoder.decode(BackupState._State.self, from: data)
switch state.state {
Expand All @@ -66,8 +71,16 @@ extension BackupState {
return try decoder.decode(BackupState.Stopping.self, from: data)
case ._thinning:
return try decoder.decode(BackupState.Thinning.self, from: data)
case ._unknown:
return nil
case ._unknown(let state):
#if DEBUG
throw BackupStateError.invalidState(raw: raw)
#else
return BackupState.Unknown(title: state, raw: raw)
#endif
}
}
}

extension BackupState._State {
enum Mock {}
}
57 changes: 57 additions & 0 deletions TimeMachineStatus/Model/BackupState/Copying.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,26 @@ extension BackupState {
try super.init(from: decoder)
}

fileprivate init(
clientID: String,
destinationID: UUID,
attemptOptions: Int,
stateChange: Date?,
destinationMountPoint: String,
fractionOfProgressBar: Double,
progress: Progress
) {
self.fractionOfProgressBar = fractionOfProgressBar
self.progress = progress
super.init(
clientID: clientID,
destinationID: destinationID,
attemptOptions: attemptOptions,
stateChange: stateChange,
destinationMountPoint: destinationMountPoint
)
}

let fractionOfProgressBar: Double
let progress: Progress

Expand Down Expand Up @@ -72,6 +92,22 @@ extension BackupState.Copying {
self.totalFiles = Int(totalFilesString ?? "")
}

init(
percent: Double?,
timeRemaining: String?,
bytes: Int?,
files: Int?,
totalBytes: Int?,
totalFiles: Int?
) {
self.percent = percent
self.timeRemaining = timeRemaining
self.bytes = bytes
self.files = files
self.totalBytes = totalBytes
self.totalFiles = totalFiles
}

let percent: Double?
let timeRemaining: String?
let bytes: Int?
Expand All @@ -80,3 +116,24 @@ extension BackupState.Copying {
let totalFiles: Int?
}
}

extension BackupState._State.Mock {
static func copying(_ id: UUID = UUID()) -> BackupState.Copying {
.init(
clientID: "1234",
destinationID: id,
attemptOptions: 0,
stateChange: Date(),
destinationMountPoint: "/Volumes/BackupDrive",
fractionOfProgressBar: 0.5,
progress: BackupState.Copying.Progress(
percent: 50,
timeRemaining: "2 hours",
bytes: 1_024,
files: 10,
totalBytes: 2_048,
totalFiles: 20
)
)
}
}
20 changes: 20 additions & 0 deletions TimeMachineStatus/Model/BackupState/FindingBackupVolume.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ extension BackupState {
try super.init(from: decoder)
}

override fileprivate init(
clientID: String,
destinationID: UUID,
attemptOptions: Int
) {
super.init(
clientID: clientID,
destinationID: destinationID,
attemptOptions: attemptOptions
)
}

override var statusString: String {
"Finding Backup Volume"
}
Expand All @@ -27,3 +39,11 @@ extension BackupState {
}
}
}

extension BackupState._State.Mock {
static let findingBackupVolume = BackupState.FindingBackupVolume(
clientID: "1234",
destinationID: UUID(uuidString: "1234")!, // swiftlint:disable:this force_unwrapping
attemptOptions: 0
)
}
37 changes: 37 additions & 0 deletions TimeMachineStatus/Model/BackupState/FindingChanges.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,28 @@ extension BackupState {
try super.init(from: decoder)
}

fileprivate init(
clientID: String,
destinationID: UUID,
attemptOptions: Int,
stateChange: Date?,
destinationMountPoint: String,
itemsFound: Int,
fractionDone: Double,
fractionOfProgressBar: Double
) {
self.itemsFound = itemsFound
self.fractionDone = fractionDone
self.fractionOfProgressBar = fractionOfProgressBar
super.init(
clientID: clientID,
destinationID: destinationID,
attemptOptions: attemptOptions,
stateChange: stateChange,
destinationMountPoint: destinationMountPoint
)
}

let itemsFound: Int
let fractionDone: Double
let fractionOfProgressBar: Double
Expand All @@ -44,3 +66,18 @@ extension BackupState {
}
}
}

extension BackupState._State.Mock {
static func findingChanges(_ id: UUID = UUID()) -> BackupState.FindingChanges {
.init(
clientID: "1234",
destinationID: id,
attemptOptions: 0,
stateChange: Date(),
destinationMountPoint: "/Volumes/Backup",
itemsFound: .random(in: 0...100),
fractionDone: .random(in: 0...1),
fractionOfProgressBar: 0.1
)
}
}
26 changes: 26 additions & 0 deletions TimeMachineStatus/Model/BackupState/Finishing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,34 @@ extension BackupState {
"Finishing"
}

override fileprivate init(
clientID: String,
destinationID: UUID,
attemptOptions: Int,
stateChange: Date?,
destinationMountPoint: String
) {
super.init(
clientID: clientID,
destinationID: destinationID,
attemptOptions: attemptOptions,
stateChange: stateChange,
destinationMountPoint: destinationMountPoint
)
}

override var shortStatusString: String {
statusString
}
}
}

extension BackupState._State.Mock {
static let finishing = BackupState.Finishing(
clientID: "1234",
destinationID: UUID(uuidString: "1234")!, // swiftlint:disable:this force_unwrapping
attemptOptions: 0,
stateChange: Date(),
destinationMountPoint: "/Volumes/Backup"
)
}
9 changes: 9 additions & 0 deletions TimeMachineStatus/Model/BackupState/Idle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ extension BackupState {
try super.init(from: decoder)
}

fileprivate init(clientID: String) {
self.clientID = clientID
super.init()
}

let clientID: String

override var statusString: String {
Expand All @@ -33,3 +38,7 @@ extension BackupState {
}
}
}

extension BackupState._State.Mock {
static let idle = BackupState.Idle(clientID: "1234")
}
11 changes: 11 additions & 0 deletions TimeMachineStatus/Model/BackupState/Internal/_BaseState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ extension BackupState {
try super.init(from: decoder)
}

init(
clientID: String,
destinationID: UUID,
attemptOptions: Int
) {
self.clientID = clientID
self.destinationID = destinationID
self.attemptOptions = attemptOptions
super.init()
}

let clientID: String
let destinationID: UUID
let attemptOptions: Int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ extension BackupState {
try super.init(from: decoder)
}

init(
clientID: String,
destinationID: UUID,
attemptOptions: Int,
stateChange: Date?,
destinationMountPoint: String
) {
self.stateChange = stateChange
self.destinationMountPoint = destinationMountPoint
super.init(clientID: clientID, destinationID: destinationID, attemptOptions: attemptOptions)
}

let stateChange: Date?
let destinationMountPoint: String
}
Expand Down
Loading

0 comments on commit 1e436bc

Please sign in to comment.