-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathUpdateFile.swift
65 lines (54 loc) · 2.19 KB
/
UpdateFile.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import Foundation
import SwiftCICDCore
public struct UpdateFile: Action {
@Value var previousFileContents: Data?
let filePath: String
let createFile: Bool
let update: (inout Data) -> Void
public init(_ filePath: String, createFile: Bool = true, update: @escaping (inout Data) -> Void) {
self.filePath = filePath
self.createFile = createFile
self.update = update
}
public init(_ filePath: String, createFile: Bool = true, update: @escaping (inout String) -> Void) {
self.filePath = filePath
self.createFile = createFile
self.update = { data in
var string = data.string
update(&string)
data = string.data
}
}
public func run() async throws {
var contents = Data()
if let fileContents = context.fileManager.contents(atPath: filePath) {
contents = fileContents
} else if createFile {
context.fileManager.createFile(atPath: filePath, contents: nil)
} else {
throw ActionError("Failed to read contents of \(filePath)")
}
previousFileContents = contents
update(&contents)
guard context.fileManager.createFile(atPath: filePath, contents: contents) else {
throw ActionError("Failed to update file \(filePath)")
}
}
public func cleanUp(error: Error?) async throws {
if createFile {
try context.fileManager.removeItemIfItExists(atPath: filePath)
logger.debug("Deleted \(filePath)")
} else if let previousFileContents {
context.fileManager.createFile(atPath: filePath, contents: previousFileContents)
logger.debug("Restored \(filePath) to its previous state")
}
}
}
public extension Action {
func updateFile(_ filePath: String, createFile: Bool = true, update: @escaping (inout Data) -> Void) async throws {
try await run(UpdateFile(filePath, createFile: createFile, update: update))
}
func updateFile(_ filePath: String, createFile: Bool = true, update: @escaping (inout String) -> Void) async throws {
try await run(UpdateFile(filePath, createFile: createFile, update: update))
}
}