CommandLineToolkit
88 строк · 3.3 Кб
1import CLTExtensions
2#if canImport(Darwin)
3import Darwin
4#endif
5#if canImport(Glibc)
6import Glibc
7#endif
8import Foundation
9import PathLib
10
11public final class TemporaryFolder {
12public let absolutePath: AbsolutePath
13private let deleteOnDealloc: Bool
14
15public init(
16containerPath: AbsolutePath? = nil,
17prefix: String = "TemporaryFolder",
18deleteOnDealloc: Bool = true
19) throws {
20if let containerPath = containerPath {
21try FileManager.default.createDirectory(atPath: containerPath)
22}
23let containerPath = containerPath ?? AbsolutePath(NSTemporaryDirectory())
24let pathTemplate = containerPath.appending("\(prefix).XXXXXX")
25var templateBytes = [UInt8](pathTemplate.pathString.utf8).map { Int8($0) } + [Int8(0)]
26if mkdtemp(&templateBytes) == nil {
27throw ErrnoError.failedToCreateTemporaryFolder(pathTemplate, code: errno)
28}
29
30let resultingPath = String(cString: templateBytes)
31let urlValues = try URL(fileURLWithPath: resultingPath).resourceValues(forKeys: [.canonicalPathKey])
32guard let canonicalPath = urlValues.canonicalPath else {
33throw UnknownCanonicalPath(path: resultingPath)
34}
35
36self.absolutePath = AbsolutePath(canonicalPath)
37self.deleteOnDealloc = deleteOnDealloc
38}
39
40deinit {
41if deleteOnDealloc {
42try? FileManager.default.removeItem(atPath: absolutePath.pathString)
43} else {
44rmdir(absolutePath.pathString)
45}
46}
47
48public func pathWith(components: [String]) -> AbsolutePath {
49return absolutePath.appending(components: components)
50}
51
52@discardableResult
53public func createDirectory(components: [String], attributes: [FileAttributeKey: Any]? = nil) throws -> AbsolutePath {
54let path = pathWith(components: components)
55try FileManager.default.createDirectory(atPath: path, attributes: attributes)
56return path
57}
58
59@discardableResult
60public func createFile(components: [String] = [], filename: String, contents: Data? = nil, attributes: [FileAttributeKey: Any]? = nil) throws -> AbsolutePath {
61let container = try createDirectory(components: components)
62let path = container.appending(filename)
63FileManager.default.createFile(atPath: path.pathString, contents: contents, attributes: attributes)
64return path
65}
66
67@discardableResult
68public func createFile(components: [String] = [], filename: String, contents: String, attributes: [FileAttributeKey: Any]? = nil) throws -> AbsolutePath {
69return try createFile(components: components, filename: filename, contents: contents.dataUsingUtf8(), attributes: attributes)
70}
71
72public func createSymbolicLink(at path: RelativePath, destination: Path) throws -> AbsolutePath {
73let symbolicLinkPath = pathWith(components: path.components)
74try FileManager.default.createSymbolicLink(
75atPath: symbolicLinkPath.pathString,
76withDestinationPath: destination.pathString
77)
78return symbolicLinkPath
79}
80
81public static func == (left: TemporaryFolder, right: TemporaryFolder) -> Bool {
82return left.absolutePath == right.absolutePath
83}
84
85public func hash(into hasher: inout Hasher) {
86hasher.combine(absolutePath)
87}
88}
89