Skip to content

Commit 3e9e091

Browse files
committed
Improve JSON progress file handling and error reporting
1 parent 79f5c8b commit 3e9e091

File tree

3 files changed

+28
-32
lines changed

3 files changed

+28
-32
lines changed

Sources/Swiftly/JsonFileProgressReporter.swift

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,30 @@ enum ProgressInfo: Codable {
1111
struct JsonFileProgressReporter: ProgressAnimationProtocol {
1212
let filePath: FilePath
1313
private let encoder: JSONEncoder
14+
private let ctx: SwiftlyCoreContext
15+
private let fileHandle: FileHandle
1416

15-
init(filePath: FilePath, encoder: JSONEncoder = JSONEncoder()) {
17+
init(_ ctx: SwiftlyCoreContext, filePath: FilePath, encoder: JSONEncoder = JSONEncoder()) throws
18+
{
19+
self.ctx = ctx
1620
self.filePath = filePath
1721
self.encoder = encoder
22+
self.fileHandle = try FileHandle(forWritingTo: URL(fileURLWithPath: filePath.string))
1823
}
1924

2025
private func writeProgress(_ progress: ProgressInfo) {
2126
let jsonData = try? self.encoder.encode(progress)
22-
guard let jsonData = jsonData, let jsonString = String(data: jsonData, encoding: .utf8)
23-
else {
24-
print("Failed to encode progress entry to JSON")
27+
guard let jsonData = jsonData else {
28+
Task { [ctx = self.ctx] in
29+
await ctx.message("Failed to encode progress entry to JSON")
30+
}
2531
return
2632
}
2733

28-
let jsonLine = jsonString + "\n"
29-
30-
do {
31-
try jsonLine.append(to: self.filePath)
32-
} catch {
33-
print("Failed to write progress entry to \(self.filePath): \(error)")
34-
}
34+
self.fileHandle.seekToEndOfFile()
35+
self.fileHandle.write(jsonData)
36+
self.fileHandle.write("\n".data(using: .utf8) ?? Data())
37+
self.fileHandle.synchronizeFile()
3538
}
3639

3740
func update(step: Int, total: Int, text: String) {
@@ -49,10 +52,11 @@ struct JsonFileProgressReporter: ProgressAnimationProtocol {
4952
}
5053

5154
func clear() {
52-
do {
53-
try FileManager.default.removeItem(atPath: self.filePath.string)
54-
} catch {
55-
print("Failed to clear progress file at \(self.filePath): \(error)")
56-
}
55+
self.fileHandle.truncateFile(atOffset: 0)
56+
self.fileHandle.synchronizeFile()
57+
}
58+
59+
func close() throws {
60+
try self.fileHandle.close()
5761
}
5862
}

Sources/SwiftlyCore/FileManager+FilePath.swift

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -195,15 +195,6 @@ extension String {
195195
try self.write(to: path, atomically: true, encoding: enc)
196196
return
197197
}
198-
199-
let fileHandle = try FileHandle(forWritingTo: URL(fileURLWithPath: path.string))
200-
defer { fileHandle.closeFile() }
201-
fileHandle.seekToEndOfFile()
202-
if let data = self.data(using: enc) {
203-
fileHandle.write(data)
204-
} else {
205-
throw SwiftlyError(message: "Failed to convert string to data with encoding \(enc)")
206-
}
207198
}
208199

209200
public init(contentsOf path: FilePath, encoding enc: String.Encoding = .utf8) throws {

Tests/SwiftlyTests/JsonFileProgressReporterTests.swift

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import Foundation
2-
@testable import Swiftly
3-
@testable import SwiftlyCore
42
import SystemPackage
53
import Testing
64

@@ -102,18 +100,21 @@ import Testing
102100
try FileManager.default.removeItem(atPath: tempFile.string)
103101
}
104102

105-
@Test("Test clear method removes file")
106-
func testClearRemovesFile() throws {
103+
@Test("Test clear method truncates the file")
104+
func testClearTruncatesFile() async throws {
107105
let tempFile = fs.mktemp(ext: ".json")
108-
let reporter = JsonFileProgressReporter(filePath: tempFile)
106+
try await fs.create(.mode(Int(0o644)), file: tempFile)
107+
defer { try? FileManager.default.removeItem(atPath: tempFile.string) }
108+
let reporter = try JsonFileProgressReporter(SwiftlyTests.ctx, filePath: tempFile)
109+
defer { try? reporter.close() }
109110

110111
reporter.update(step: 1, total: 2, text: "Test")
111112

112-
#expect(FileManager.default.fileExists(atPath: tempFile.string))
113+
#expect(try String(contentsOf: tempFile).lengthOfBytes(using: String.Encoding.utf8) > 0)
113114

114115
reporter.clear()
115116

116-
#expect(!FileManager.default.fileExists(atPath: tempFile.string))
117+
#expect(try String(contentsOf: tempFile).lengthOfBytes(using: String.Encoding.utf8) == 0)
117118
}
118119

119120
@Test("Test multiple progress updates create multiple lines")

0 commit comments

Comments
 (0)