@testable import Path import Foundation class TemporaryDirectory { let url: URL var path: Path { return Path(string: url.path) } /** Creates a new temporary directory. The directory is recursively deleted when this object deallocates. If you need a temporary directory on a specific volume use the `appropriateFor` parameter. - Important: If you are moving a file, ensure to use the `appropriateFor` parameter, since it is volume aware and moving the file across volumes will take exponentially longer! - Important: The `appropriateFor` parameter does not work on Linux. - Parameter appropriateFor: The temporary directory will be located on this volume. */ init(appropriateFor: URL? = nil) throws { #if !os(Linux) let appropriate: URL if let appropriateFor = appropriateFor { appropriate = appropriateFor } else if #available(OSX 10.12, iOS 10, tvOS 10, watchOS 3, *) { appropriate = FileManager.default.temporaryDirectory } else { appropriate = URL(fileURLWithPath: NSTemporaryDirectory()) } url = try FileManager.default.url(for: .itemReplacementDirectory, in: .userDomainMask, appropriateFor: appropriate, create: true) #else let envs = ProcessInfo.processInfo.environment let env = envs["TMPDIR"] ?? envs["TEMP"] ?? envs["TMP"] ?? "/tmp" let dir = Path.root/env/"swift-sh.XXXXXX" var template = [UInt8](dir.string.utf8).map({ Int8($0) }) + [Int8(0)] guard mkdtemp(&template) != nil else { throw CocoaError.error(.featureUnsupported) } url = URL(fileURLWithPath: String(cString: template)) #endif } deinit { _ = try? FileManager.default.removeItem(at: url) } } extension Path { static func mktemp(body: (Path) throws -> T) throws -> T { let tmp = try TemporaryDirectory() return try body(tmp.path) } }