diff --git a/Sources/TSCBasic/Path.swift b/Sources/TSCBasic/Path.swift index 038641de..789d7d13 100644 --- a/Sources/TSCBasic/Path.swift +++ b/Sources/TSCBasic/Path.swift @@ -90,7 +90,7 @@ public struct AbsolutePath: Hashable, Sendable { self.init(String(decodingCString: pwszResult, as: UTF16.self)) #else - self.init(basePath, RelativePath(str)) + try self.init(basePath, RelativePath(validating: str)) #endif } } @@ -102,8 +102,8 @@ public struct AbsolutePath: Hashable, Sendable { } /// Convenience initializer that appends a string to a relative path. - public init(_ absPath: AbsolutePath, _ relStr: String) { - self.init(absPath, RelativePath(relStr)) + public init(_ absPath: AbsolutePath, validating relStr: String) throws { + try self.init(absPath, RelativePath(validating: relStr)) } /// Initializes the AbsolutePath from `absStr`, which must be an absolute @@ -240,23 +240,6 @@ public struct RelativePath: Hashable, Sendable { _impl = impl } - /// Private initializer for constructing a relative path without performing - /// normalization or canonicalization. This will construct a path without - /// an anchor and thus may be invalid. - fileprivate init(unsafeUncheckedPath string: String) { - self.init(PathImpl(string: string)) - } - - /// Initializes the RelativePath from `str`, which must be a relative path - /// (which means that it must not begin with a path separator or a tilde). - /// An empty input path is allowed, but will be normalized to a single `.` - /// character. The input string will be normalized if needed, as described - /// in the documentation for RelativePath. - public init(_ string: String) { - // Normalize the relative string and store it as our Path. - self.init(PathImpl(normalizingRelativePath: string)) - } - /// Convenience initializer that verifies that the path is relative. public init(validating path: String) throws { try self.init(PathImpl(validatingRelativePath: path)) @@ -429,12 +412,6 @@ protocol Path: Hashable { /// Creates a path from its normalized string representation. init(string: String) - /// Creates a path from an absolute string representation and normalizes it. - init(normalizingAbsolutePath: String) - - /// Creates a path from an relative string representation and normalizes it. - init(normalizingRelativePath: String) - /// Creates a path from a string representation, validates that it is a valid absolute path and normalizes it. init(validatingAbsolutePath: String) throws @@ -534,34 +511,12 @@ private struct WindowsPath: Path, Sendable { return String(cString: representation) } - init(normalizingAbsolutePath path: String) { - self.init(string: Self.repr(path).withCString(encodedAs: UTF16.self) { pwszPath in - var canonical: PWSTR! - _ = PathAllocCanonicalize(pwszPath, - ULONG(PATHCCH_ALLOW_LONG_PATHS.rawValue), - &canonical) - return String(decodingCString: canonical, as: UTF16.self) - }) - } - init(validatingAbsolutePath path: String) throws { let realpath = Self.repr(path) if !Self.isAbsolutePath(realpath) { throw PathValidationError.invalidAbsolutePath(path) } - self.init(normalizingAbsolutePath: path) - } - - init(normalizingRelativePath path: String) { - if path.isEmpty || path == "." { - self.init(string: ".") - } else { - var buffer: [WCHAR] = Array(repeating: 0, count: Int(MAX_PATH + 1)) - _ = path.replacingOccurrences(of: "/", with: "\\").withCString(encodedAs: UTF16.self) { - PathCanonicalizeW(&buffer, $0) - } - self.init(string: String(decodingCString: buffer, as: UTF16.self)) - } + self.init(string: realpath) } init(validatingRelativePath path: String) throws { @@ -570,11 +525,10 @@ private struct WindowsPath: Path, Sendable { } else { let realpath: String = Self.repr(path) // Treat a relative path as an invalid relative path... - if Self.isAbsolutePath(realpath) || - realpath.first == "~" || realpath.first == "\\" { + if Self.isAbsolutePath(realpath) || realpath.first == "\\" { throw PathValidationError.invalidRelativePath(path) } - self.init(normalizingRelativePath: path) + self.init(string: realpath) } } @@ -597,7 +551,7 @@ private struct WindowsPath: Path, Sendable { } } defer { LocalFree(result) } - return PathImpl(string: String(decodingCString: result!, as: UTF16.self)) + return Self(string: String(decodingCString: result!, as: UTF16.self)) } func appending(relativePath: Self) -> Self { @@ -608,7 +562,7 @@ private struct WindowsPath: Path, Sendable { } } defer { LocalFree(result) } - return PathImpl(string: String(decodingCString: result!, as: UTF16.self)) + return Self(string: String(decodingCString: result!, as: UTF16.self)) } } #else @@ -830,7 +784,7 @@ private struct UNIXPath: Path, Sendable { init(validatingRelativePath path: String) throws { switch path.first { - case "/", "~": + case "/": throw PathValidationError.invalidRelativePath(path) default: self.init(normalizingRelativePath: path) @@ -875,9 +829,9 @@ private struct UNIXPath: Path, Sendable { } if self == Self.root { - return PathImpl(string: "/" + name) + return Self(string: "/" + name) } else { - return PathImpl(string: string + "/" + name) + return Self(string: string + "/" + name) } } @@ -900,12 +854,12 @@ private struct UNIXPath: Path, Sendable { // the beginning of the path only. if relativePathString.hasPrefix(".") { if newPathString.hasPrefix("/") { - return PathImpl(normalizingAbsolutePath: newPathString) + return Self(normalizingAbsolutePath: newPathString) } else { - return PathImpl(normalizingRelativePath: newPathString) + return Self(normalizingRelativePath: newPathString) } } else { - return PathImpl(string: newPathString) + return Self(string: newPathString) } } } @@ -926,7 +880,7 @@ extension PathValidationError: CustomStringConvertible { case .invalidAbsolutePath(let path): return "invalid absolute path '\(path)'" case .invalidRelativePath(let path): - return "invalid relative path '\(path)'; relative path should not begin with '\(AbsolutePath.root.pathString)' or '~'" + return "invalid relative path '\(path)'; relative path should not begin with '\(AbsolutePath.root.pathString)'" } } } @@ -956,10 +910,16 @@ extension AbsolutePath { // might be an empty path (when self and the base are equal). let relComps = pathComps.dropFirst(baseComps.count) #if os(Windows) - result = RelativePath(unsafeUncheckedPath: relComps.joined(separator: "\\")) + let pathString = relComps.joined(separator: "\\") #else - result = RelativePath(relComps.joined(separator: "/")) + let pathString = relComps.joined(separator: "/") #endif + do { + result = try RelativePath(validating: pathString) + } catch { + preconditionFailure("invalid relative path computed from \(pathString)") + } + } else { // General case, in which we might well need `..` components to go // "up" before we can go "down" the directory tree. @@ -975,10 +935,15 @@ extension AbsolutePath { var relComps = Array(repeating: "..", count: newBaseComps.count) relComps.append(contentsOf: newPathComps) #if os(Windows) - result = RelativePath(unsafeUncheckedPath: relComps.joined(separator: "\\")) + let pathString = relComps.joined(separator: "\\") #else - result = RelativePath(relComps.joined(separator: "/")) + let pathString = relComps.joined(separator: "/") #endif + do { + result = try RelativePath(validating: pathString) + } catch { + preconditionFailure("invalid relative path computed from \(pathString)") + } } assert(AbsolutePath(base, result) == self) @@ -1065,13 +1030,31 @@ private func mayNeedNormalization(absolute string: String) -> Bool { // MARK: - `AbsolutePath` backwards compatibility, delete after deprecation period. extension AbsolutePath { + @_disfavoredOverload @available(*, deprecated, message: "use throwing `init(validating:)` variant instead") public init(_ absStr: String) { try! self.init(validating: absStr) } + @_disfavoredOverload @available(*, deprecated, message: "use throwing `init(validating:relativeTo:)` variant instead") public init(_ str: String, relativeTo basePath: AbsolutePath) { try! self.init(validating: str, relativeTo: basePath) } + + @_disfavoredOverload + @available(*, deprecated, message: "use throwing variant instead") + public init(_ absPath: AbsolutePath, _ relStr: String) { + try! self.init(absPath, validating: relStr) + } +} + +// MARK: - `AbsolutePath` backwards compatibility, delete after deprecation period. + +extension RelativePath { + @_disfavoredOverload + @available(*, deprecated, message: "use throwing variant instead") + public init(_ string: String) { + try! self.init(validating: string) + } } diff --git a/Sources/TSCTestSupport/FileSystemExtensions.swift b/Sources/TSCTestSupport/FileSystemExtensions.swift index 397c9b55..3b190196 100644 --- a/Sources/TSCTestSupport/FileSystemExtensions.swift +++ b/Sources/TSCTestSupport/FileSystemExtensions.swift @@ -73,18 +73,69 @@ extension FileSystem { } } -public extension AbsolutePath { - init(path: StaticString) { +extension AbsolutePath { + @available(*, deprecated, message: "use direct string instead") + public init(path: StaticString) { let pathString = path.withUTF8Buffer { String(decoding: $0, as: UTF8.self) } try! self.init(validating: pathString) } - init(path: StaticString, relativeTo basePath: AbsolutePath) { + @available(*, deprecated, message: "use init(: relativeTo:) instead") + public init(path: StaticString, relativeTo basePath: AbsolutePath) { let pathString = path.withUTF8Buffer { String(decoding: $0, as: UTF8.self) } try! self.init(validating: pathString, relativeTo: basePath) } + + + @available(*, deprecated, message: "use direct string instead") + public init(base: AbsolutePath, _ relStr: StaticString) { + let pathString = relStr.withUTF8Buffer { + String(decoding: $0, as: UTF8.self) + } + self.init(base, RelativePath(stringLiteral: pathString)) + } +} + +extension AbsolutePath: ExpressibleByStringLiteral { + public init(_ value: StringLiteralType) { + try! self.init(validating: value) + } +} + +extension AbsolutePath: ExpressibleByStringInterpolation { + public init(stringLiteral value: String) { + try! self.init(validating: value) + } +} + +extension AbsolutePath { + public init(_ path: StringLiteralType, relativeTo basePath: AbsolutePath) { + try! self.init(validating: path, relativeTo: basePath) + } +} + +extension RelativePath { + @available(*, deprecated, message: "use direct string instead") + public init(static path: StaticString) { + let pathString = path.withUTF8Buffer { + String(decoding: $0, as: UTF8.self) + } + try! self.init(validating: pathString) + } +} + +extension RelativePath: ExpressibleByStringLiteral { + public init(_ value: StringLiteralType) { + try! self.init(validating: value) + } +} + +extension RelativePath: ExpressibleByStringInterpolation { + public init(stringLiteral value: String) { + try! self.init(validating: value) + } } diff --git a/Tests/TSCBasicPerformanceTests/PathPerfTests.swift b/Tests/TSCBasicPerformanceTests/PathPerfTests.swift index 86fc3a27..66fd0fbe 100644 --- a/Tests/TSCBasicPerformanceTests/PathPerfTests.swift +++ b/Tests/TSCBasicPerformanceTests/PathPerfTests.swift @@ -19,7 +19,7 @@ class PathPerfTests: XCTestCasePerf { @available(*, deprecated) func testJoinPerf_X100000() { #if canImport(Darwin) - let absPath = AbsolutePath(path: "/hello/little") + let absPath = AbsolutePath("/hello/little") let relPath = RelativePath("world") let N = 100000 self.measure { diff --git a/Tests/TSCBasicTests/FileSystemTests.swift b/Tests/TSCBasicTests/FileSystemTests.swift index 8fc62006..e3920db4 100644 --- a/Tests/TSCBasicTests/FileSystemTests.swift +++ b/Tests/TSCBasicTests/FileSystemTests.swift @@ -23,17 +23,17 @@ class FileSystemTests: XCTestCase { try! withTemporaryFile { file in try! withTemporaryDirectory(removeTreeOnDeinit: true) { tempDirPath in // exists() - XCTAssert(fs.exists(AbsolutePath(path: "/"))) - XCTAssert(!fs.exists(AbsolutePath(path: "/does-not-exist"))) + XCTAssert(fs.exists("/")) + XCTAssert(!fs.exists("/does-not-exist")) // isFile() XCTAssertTrue(fs.exists(file.path)) XCTAssertTrue(fs.isFile(file.path)) XCTAssertEqual(try fs.getFileInfo(file.path).fileType, .typeRegular) XCTAssertFalse(fs.isDirectory(file.path)) - XCTAssertFalse(fs.isFile(AbsolutePath(path: "/does-not-exist"))) - XCTAssertFalse(fs.isSymlink(AbsolutePath(path: "/does-not-exist"))) - XCTAssertThrowsError(try fs.getFileInfo(AbsolutePath(path: "/does-not-exist"))) + XCTAssertFalse(fs.isFile("/does-not-exist")) + XCTAssertFalse(fs.isSymlink("/does-not-exist")) + XCTAssertThrowsError(try fs.getFileInfo("/does-not-exist")) // isSymlink() let sym = tempDirPath.appending(component: "hello") @@ -61,25 +61,25 @@ class FileSystemTests: XCTestCase { XCTAssertTrue(fs.isSymlink(executableSym)) XCTAssertFalse(fs.isExecutableFile(sym)) XCTAssertFalse(fs.isExecutableFile(file.path)) - XCTAssertFalse(fs.isExecutableFile(AbsolutePath(path: "/does-not-exist"))) - XCTAssertFalse(fs.isExecutableFile(AbsolutePath(path: "/"))) + XCTAssertFalse(fs.isExecutableFile("/does-not-exist")) + XCTAssertFalse(fs.isExecutableFile("/")) // isDirectory() - XCTAssert(fs.isDirectory(AbsolutePath(path: "/"))) - XCTAssert(!fs.isDirectory(AbsolutePath(path: "/does-not-exist"))) + XCTAssert(fs.isDirectory("/")) + XCTAssert(!fs.isDirectory("/does-not-exist")) // getDirectoryContents() do { - _ = try fs.getDirectoryContents(AbsolutePath(path: "/does-not-exist")) + _ = try fs.getDirectoryContents("/does-not-exist") XCTFail("Unexpected success") } catch { XCTAssertEqual(error.localizedDescription, "The folder “does-not-exist” doesn’t exist.") } - let thisDirectoryContents = try! fs.getDirectoryContents(AbsolutePath(path: #file).parentDirectory) + let thisDirectoryContents = try! fs.getDirectoryContents(AbsolutePath(#file).parentDirectory) XCTAssertTrue(!thisDirectoryContents.contains(where: { $0 == "." })) XCTAssertTrue(!thisDirectoryContents.contains(where: { $0 == ".." })) - XCTAssertTrue(thisDirectoryContents.contains(where: { $0 == AbsolutePath(path: #file).basename })) + XCTAssertTrue(thisDirectoryContents.contains(where: { $0 == AbsolutePath(#file).basename })) } } } @@ -287,7 +287,7 @@ class FileSystemTests: XCTestCase { XCTAssertEqual(data, ByteString(testData)) // Atomic writes - let inMemoryFilePath = AbsolutePath(path: "/file.text") + let inMemoryFilePath = AbsolutePath("/file.text") XCTAssertNoThrow(try TSCBasic.InMemoryFileSystem(files: [:]).writeFileContents(inMemoryFilePath, bytes: ByteString(testData), atomically: true)) XCTAssertNoThrow(try TSCBasic.InMemoryFileSystem(files: [:]).writeFileContents(inMemoryFilePath, bytes: ByteString(testData), atomically: false)) // Local file system does support atomic writes, so it doesn't throw. @@ -323,9 +323,9 @@ class FileSystemTests: XCTestCase { // Check read/write against root. #if os(Android) - let root = AbsolutePath(path: "/system/") + let root = AbsolutePath("/system/") #else - let root = AbsolutePath(path: "/") + let root = AbsolutePath("/") #endif XCTAssertThrows(FileSystemError(.ioError(code: TSCLibc.EPERM), root)) { _ = try fs.readFileContents(root) @@ -444,7 +444,7 @@ class FileSystemTests: XCTestCase { func testInMemoryBasics() throws { let fs = InMemoryFileSystem() - let doesNotExist = AbsolutePath(path: "/does-not-exist") + let doesNotExist = AbsolutePath("/does-not-exist") // exists() XCTAssert(!fs.exists(doesNotExist)) @@ -464,22 +464,22 @@ class FileSystemTests: XCTestCase { } // createDirectory() - XCTAssert(!fs.isDirectory(AbsolutePath(path: "/new-dir"))) - try fs.createDirectory(AbsolutePath(path: "/new-dir/subdir"), recursive: true) - XCTAssert(fs.isDirectory(AbsolutePath(path: "/new-dir"))) - XCTAssert(fs.isDirectory(AbsolutePath(path: "/new-dir/subdir"))) - XCTAssertEqual(try fs.getDirectoryContents(AbsolutePath(path: "/")), ["new-dir"]) - XCTAssertEqual(try fs.getDirectoryContents(AbsolutePath(path: "/new-dir")), ["subdir"]) + XCTAssert(!fs.isDirectory("/new-dir")) + try fs.createDirectory("/new-dir/subdir", recursive: true) + XCTAssert(fs.isDirectory("/new-dir")) + XCTAssert(fs.isDirectory("/new-dir/subdir")) + XCTAssertEqual(try fs.getDirectoryContents("/"), ["new-dir"]) + XCTAssertEqual(try fs.getDirectoryContents("/new-dir"), ["subdir"]) } func testInMemoryCreateDirectory() { let fs = InMemoryFileSystem() // Make sure root entry isn't created. - try! fs.createDirectory(AbsolutePath(path: "/"), recursive: true) + try! fs.createDirectory("/", recursive: true) let rootContents = try! fs.getDirectoryContents(.root) XCTAssertEqual(rootContents, []) - let subdir = AbsolutePath(path: "/new-dir/subdir") + let subdir = AbsolutePath("/new-dir/subdir") try! fs.createDirectory(subdir, recursive: true) XCTAssert(fs.isDirectory(subdir)) @@ -494,7 +494,7 @@ class FileSystemTests: XCTestCase { XCTAssert(fs.isDirectory(subsubdir)) // Check non-recursive failing subdir case. - let veryNewDir = AbsolutePath(path: "/very-new-dir") + let veryNewDir = AbsolutePath("/very-new-dir") let newsubdir = veryNewDir.appending(component: "subdir") XCTAssert(!fs.isDirectory(newsubdir)) XCTAssertThrows(FileSystemError(.noEntry, veryNewDir)) { @@ -503,7 +503,7 @@ class FileSystemTests: XCTestCase { XCTAssert(!fs.isDirectory(newsubdir)) // Check directory creation over a file. - let filePath = AbsolutePath(path: "/mach_kernel") + let filePath = AbsolutePath("/mach_kernel") try! fs.writeFileContents(filePath, bytes: [0xCD, 0x0D]) XCTAssert(fs.exists(filePath) && !fs.isDirectory(filePath)) XCTAssertThrows(FileSystemError(.notDirectory, filePath)) { @@ -548,10 +548,10 @@ class FileSystemTests: XCTestCase { func testInMemoryReadWriteFile() { let fs = InMemoryFileSystem() - try! fs.createDirectory(AbsolutePath(path: "/new-dir/subdir"), recursive: true) + try! fs.createDirectory("/new-dir/subdir", recursive: true) // Check read/write of a simple file. - let filePath = AbsolutePath(path: "/new-dir/subdir").appending(component: "new-file.txt") + let filePath = AbsolutePath("/new-dir/subdir").appending(component: "new-file.txt") XCTAssert(!fs.exists(filePath)) XCTAssertFalse(fs.isFile(filePath)) try! fs.writeFileContents(filePath, bytes: "Hello, world!") @@ -575,7 +575,7 @@ class FileSystemTests: XCTestCase { XCTAssertEqual(try! fs.readFileContents(filePath), "Hello, new world!") // Check read/write against root. - let root = AbsolutePath(path: "/") + let root = AbsolutePath("/") XCTAssertThrows(FileSystemError(.isDirectory, root)) { _ = try fs.readFileContents(root) } @@ -596,7 +596,7 @@ class FileSystemTests: XCTestCase { XCTAssert(fs.exists(filePath)) // Check read/write into a missing directory. - let missingParent = AbsolutePath(path: "/does/not") + let missingParent = AbsolutePath("/does/not") let missingFile = missingParent.appending(component: "exist") XCTAssertThrows(FileSystemError(.noEntry, missingFile)) { _ = try fs.readFileContents(missingFile) @@ -609,8 +609,8 @@ class FileSystemTests: XCTestCase { func testInMemoryFsCopy() throws { let fs = InMemoryFileSystem() - try! fs.createDirectory(AbsolutePath(path: "/new-dir/subdir"), recursive: true) - let filePath = AbsolutePath(path: "/new-dir/subdir").appending(component: "new-file.txt") + try! fs.createDirectory("/new-dir/subdir", recursive: true) + let filePath = AbsolutePath("/new-dir/subdir").appending(component: "new-file.txt") try! fs.writeFileContents(filePath, bytes: "Hello, world!") XCTAssertEqual(try! fs.readFileContents(filePath), "Hello, world!") @@ -629,7 +629,7 @@ class FileSystemTests: XCTestCase { func testInMemCopyAndMoveItem() throws { let fs = InMemoryFileSystem() - let path = AbsolutePath(path: "/tmp") + let path = AbsolutePath("/tmp") try fs.createDirectory(path) let source = path.appending(component: "source") let destination = path.appending(component: "destination") @@ -707,33 +707,33 @@ class FileSystemTests: XCTestCase { func testRootedFileSystem() throws { // Create the test file system. let baseFileSystem = InMemoryFileSystem() as FileSystem - try baseFileSystem.createDirectory(AbsolutePath(path: "/base/rootIsHere/subdir"), recursive: true) - try baseFileSystem.writeFileContents(AbsolutePath(path: "/base/rootIsHere/subdir/file"), bytes: "Hello, world!") + try baseFileSystem.createDirectory("/base/rootIsHere/subdir", recursive: true) + try baseFileSystem.writeFileContents("/base/rootIsHere/subdir/file", bytes: "Hello, world!") // Create the rooted file system. - let rerootedFileSystem = RerootedFileSystemView(baseFileSystem, rootedAt: AbsolutePath(path: "/base/rootIsHere")) + let rerootedFileSystem = RerootedFileSystemView(baseFileSystem, rootedAt: "/base/rootIsHere") // Check that it has the appropriate view. - XCTAssert(rerootedFileSystem.exists(AbsolutePath(path: "/subdir"))) - XCTAssert(rerootedFileSystem.isDirectory(AbsolutePath(path: "/subdir"))) - XCTAssert(rerootedFileSystem.exists(AbsolutePath(path: "/subdir/file"))) - XCTAssertEqual(try rerootedFileSystem.readFileContents(AbsolutePath(path: "/subdir/file")), "Hello, world!") + XCTAssert(rerootedFileSystem.exists("/subdir")) + XCTAssert(rerootedFileSystem.isDirectory("/subdir")) + XCTAssert(rerootedFileSystem.exists("/subdir/file")) + XCTAssertEqual(try rerootedFileSystem.readFileContents("/subdir/file"), "Hello, world!") // Check that mutations work appropriately. - XCTAssert(!baseFileSystem.exists(AbsolutePath(path: "/base/rootIsHere/subdir2"))) - try rerootedFileSystem.createDirectory(AbsolutePath(path: "/subdir2")) - XCTAssert(baseFileSystem.isDirectory(AbsolutePath(path: "/base/rootIsHere/subdir2"))) + XCTAssert(!baseFileSystem.exists("/base/rootIsHere/subdir2")) + try rerootedFileSystem.createDirectory("/subdir2") + XCTAssert(baseFileSystem.isDirectory("/base/rootIsHere/subdir2")) } func testRootedCreateSymlink() throws { // Create the test file system. let baseFileSystem = InMemoryFileSystem() as FileSystem - try baseFileSystem.createDirectory(AbsolutePath(path: "/base/rootIsHere/subdir"), recursive: true) + try baseFileSystem.createDirectory("/base/rootIsHere/subdir", recursive: true) // Create the rooted file system. - let fs = RerootedFileSystemView(baseFileSystem, rootedAt: AbsolutePath(path: "/base/rootIsHere")) + let fs = RerootedFileSystemView(baseFileSystem, rootedAt: "/base/rootIsHere") - let path = AbsolutePath(path: "/test") + let path = AbsolutePath("/test") try fs.createDirectory(path, recursive: true) let source = path.appending(component: "source") @@ -818,7 +818,7 @@ class FileSystemTests: XCTestCase { func testInMemoryFileSystemFileLock() throws { let fs = InMemoryFileSystem() - let path = AbsolutePath(path: "/") + let path = AbsolutePath("/") try fs.createDirectory(path) let fileA = path.appending(component: "fileA") @@ -846,11 +846,11 @@ class FileSystemTests: XCTestCase { func testRerootedFileSystemViewFileLock() throws { let inMemoryFS = InMemoryFileSystem() - let rootPath = AbsolutePath(path: "/tmp") + let rootPath = AbsolutePath("/tmp") try inMemoryFS.createDirectory(rootPath) let fs = RerootedFileSystemView(inMemoryFS, rootedAt: rootPath) - let path = AbsolutePath(path: "/") + let path = AbsolutePath("/") try fs.createDirectory(path) let fileA = path.appending(component: "fileA") diff --git a/Tests/TSCBasicTests/PathShimTests.swift b/Tests/TSCBasicTests/PathShimTests.swift index 072e18ff..1af04a37 100644 --- a/Tests/TSCBasicTests/PathShimTests.swift +++ b/Tests/TSCBasicTests/PathShimTests.swift @@ -36,17 +36,17 @@ class WalkTests : XCTestCase { func testNonRecursive() throws { #if os(Android) let root = "/system" - var expected = [ - AbsolutePath(path: "\(root)/usr"), - AbsolutePath(path: "\(root)/bin"), - AbsolutePath(path: "\(root)/xbin") + var expected: [AbsolutePath] = [ + "\(root)/usr", + "\(root)/bin", + "\(root)/xbin" ] #else let root = "" - var expected = [ - AbsolutePath(path: "/usr"), - AbsolutePath(path: "/bin"), - AbsolutePath(path: "/sbin") + var expected: [AbsolutePath] = [ + "/usr", + "/bin", + "/sbin" ] #endif for x in try walk(AbsolutePath(validating: "\(root)/"), recursively: false) { @@ -63,7 +63,7 @@ class WalkTests : XCTestCase { } func testRecursive() { - let root = AbsolutePath(path: #file).parentDirectory.parentDirectory.parentDirectory.appending(component: "Sources") + let root = AbsolutePath(#file).parentDirectory.parentDirectory.parentDirectory.appending(component: "Sources") var expected = [ root.appending(component: "TSCBasic"), root.appending(component: "TSCUtility") diff --git a/Tests/TSCBasicTests/PathTests.swift b/Tests/TSCBasicTests/PathTests.swift index cdb27a4d..90822d63 100644 --- a/Tests/TSCBasicTests/PathTests.swift +++ b/Tests/TSCBasicTests/PathTests.swift @@ -8,41 +8,41 @@ See http://swift.org/CONTRIBUTORS.txt for Swift project authors */ -import XCTest import Foundation - import TSCBasic +import TSCTestSupport +import XCTest class PathTests: XCTestCase { func testBasics() { - XCTAssertEqual(AbsolutePath(path: "/").pathString, "/") - XCTAssertEqual(AbsolutePath(path: "/a").pathString, "/a") - XCTAssertEqual(AbsolutePath(path: "/a/b/c").pathString, "/a/b/c") + XCTAssertEqual(AbsolutePath("/").pathString, "/") + XCTAssertEqual(AbsolutePath("/a").pathString, "/a") + XCTAssertEqual(AbsolutePath("/a/b/c").pathString, "/a/b/c") XCTAssertEqual(RelativePath(".").pathString, ".") XCTAssertEqual(RelativePath("a").pathString, "a") XCTAssertEqual(RelativePath("a/b/c").pathString, "a/b/c") XCTAssertEqual(RelativePath("~").pathString, "~") // `~` is not special } - func testStringInitialization() { - let abs1 = AbsolutePath(path: "/") + func testStringInitialization() throws { + let abs1 = AbsolutePath("/") let abs2 = AbsolutePath(abs1, ".") XCTAssertEqual(abs1, abs2) let rel3 = "." - let abs3 = AbsolutePath(abs2, rel3) + let abs3 = try AbsolutePath(abs2, validating: rel3) XCTAssertEqual(abs2, abs3) - let base = AbsolutePath(path: "/base/path") - let abs4 = AbsolutePath(path: "/a/b/c", relativeTo: base) - XCTAssertEqual(abs4, AbsolutePath(path: "/a/b/c")) - let abs5 = AbsolutePath(path: "./a/b/c", relativeTo: base) - XCTAssertEqual(abs5, AbsolutePath(path: "/base/path/a/b/c")) - let abs6 = AbsolutePath(path: "~/bla", relativeTo: base) // `~` isn't special - XCTAssertEqual(abs6, AbsolutePath(path: "/base/path/~/bla")) + let base = AbsolutePath("/base/path") + let abs4 = AbsolutePath("/a/b/c", relativeTo: base) + XCTAssertEqual(abs4, AbsolutePath("/a/b/c")) + let abs5 = AbsolutePath("./a/b/c", relativeTo: base) + XCTAssertEqual(abs5, AbsolutePath("/base/path/a/b/c")) + let abs6 = AbsolutePath("~/bla", relativeTo: base) // `~` isn't special + XCTAssertEqual(abs6, AbsolutePath("/base/path/~/bla")) } func testStringLiteralInitialization() { - let abs = AbsolutePath(path: "/") + let abs = AbsolutePath("/") XCTAssertEqual(abs.pathString, "/") let rel1 = RelativePath(".") XCTAssertEqual(rel1.pathString, ".") @@ -51,34 +51,34 @@ class PathTests: XCTestCase { } func testRepeatedPathSeparators() { - XCTAssertEqual(AbsolutePath(path: "/ab//cd//ef").pathString, "/ab/cd/ef") - XCTAssertEqual(AbsolutePath(path: "/ab///cd//ef").pathString, "/ab/cd/ef") + XCTAssertEqual(AbsolutePath("/ab//cd//ef").pathString, "/ab/cd/ef") + XCTAssertEqual(AbsolutePath("/ab///cd//ef").pathString, "/ab/cd/ef") XCTAssertEqual(RelativePath("ab//cd//ef").pathString, "ab/cd/ef") XCTAssertEqual(RelativePath("ab//cd///ef").pathString, "ab/cd/ef") } func testTrailingPathSeparators() { - XCTAssertEqual(AbsolutePath(path: "/ab/cd/ef/").pathString, "/ab/cd/ef") - XCTAssertEqual(AbsolutePath(path: "/ab/cd/ef//").pathString, "/ab/cd/ef") + XCTAssertEqual(AbsolutePath("/ab/cd/ef/").pathString, "/ab/cd/ef") + XCTAssertEqual(AbsolutePath("/ab/cd/ef//").pathString, "/ab/cd/ef") XCTAssertEqual(RelativePath("ab/cd/ef/").pathString, "ab/cd/ef") XCTAssertEqual(RelativePath("ab/cd/ef//").pathString, "ab/cd/ef") } func testDotPathComponents() { - XCTAssertEqual(AbsolutePath(path: "/ab/././cd//ef").pathString, "/ab/cd/ef") - XCTAssertEqual(AbsolutePath(path: "/ab/./cd//ef/.").pathString, "/ab/cd/ef") + XCTAssertEqual(AbsolutePath("/ab/././cd//ef").pathString, "/ab/cd/ef") + XCTAssertEqual(AbsolutePath("/ab/./cd//ef/.").pathString, "/ab/cd/ef") XCTAssertEqual(RelativePath("ab/./cd/././ef").pathString, "ab/cd/ef") XCTAssertEqual(RelativePath("ab/./cd/ef/.").pathString, "ab/cd/ef") } func testDotDotPathComponents() { - XCTAssertEqual(AbsolutePath(path: "/..").pathString, "/") - XCTAssertEqual(AbsolutePath(path: "/../../../../..").pathString, "/") - XCTAssertEqual(AbsolutePath(path: "/abc/..").pathString, "/") - XCTAssertEqual(AbsolutePath(path: "/abc/../..").pathString, "/") - XCTAssertEqual(AbsolutePath(path: "/../abc").pathString, "/abc") - XCTAssertEqual(AbsolutePath(path: "/../abc/..").pathString, "/") - XCTAssertEqual(AbsolutePath(path: "/../abc/../def").pathString, "/def") + XCTAssertEqual(AbsolutePath("/..").pathString, "/") + XCTAssertEqual(AbsolutePath("/../../../../..").pathString, "/") + XCTAssertEqual(AbsolutePath("/abc/..").pathString, "/") + XCTAssertEqual(AbsolutePath("/abc/../..").pathString, "/") + XCTAssertEqual(AbsolutePath("/../abc").pathString, "/abc") + XCTAssertEqual(AbsolutePath("/../abc/..").pathString, "/") + XCTAssertEqual(AbsolutePath("/../abc/../def").pathString, "/def") XCTAssertEqual(RelativePath("..").pathString, "..") XCTAssertEqual(RelativePath("../..").pathString, "../..") XCTAssertEqual(RelativePath(".././..").pathString, "../..") @@ -88,8 +88,8 @@ class PathTests: XCTestCase { } func testCombinationsAndEdgeCases() { - XCTAssertEqual(AbsolutePath(path: "///").pathString, "/") - XCTAssertEqual(AbsolutePath(path: "/./").pathString, "/") + XCTAssertEqual(AbsolutePath("///").pathString, "/") + XCTAssertEqual(AbsolutePath("/./").pathString, "/") XCTAssertEqual(RelativePath("").pathString, ".") XCTAssertEqual(RelativePath(".").pathString, ".") XCTAssertEqual(RelativePath("./abc").pathString, "abc") @@ -117,11 +117,11 @@ class PathTests: XCTestCase { } func testDirectoryNameExtraction() { - XCTAssertEqual(AbsolutePath(path: "/").dirname, "/") - XCTAssertEqual(AbsolutePath(path: "/a").dirname, "/") - XCTAssertEqual(AbsolutePath(path: "/./a").dirname, "/") - XCTAssertEqual(AbsolutePath(path: "/../..").dirname, "/") - XCTAssertEqual(AbsolutePath(path: "/ab/c//d/").dirname, "/ab/c") + XCTAssertEqual(AbsolutePath("/").dirname, "/") + XCTAssertEqual(AbsolutePath("/a").dirname, "/") + XCTAssertEqual(AbsolutePath("/./a").dirname, "/") + XCTAssertEqual(AbsolutePath("/../..").dirname, "/") + XCTAssertEqual(AbsolutePath("/ab/c//d/").dirname, "/ab/c") XCTAssertEqual(RelativePath("ab/c//d/").dirname, "ab/c") XCTAssertEqual(RelativePath("../a").dirname, "..") XCTAssertEqual(RelativePath("../a/..").dirname, ".") @@ -134,10 +134,10 @@ class PathTests: XCTestCase { } func testBaseNameExtraction() { - XCTAssertEqual(AbsolutePath(path: "/").basename, "/") - XCTAssertEqual(AbsolutePath(path: "/a").basename, "a") - XCTAssertEqual(AbsolutePath(path: "/./a").basename, "a") - XCTAssertEqual(AbsolutePath(path: "/../..").basename, "/") + XCTAssertEqual(AbsolutePath("/").basename, "/") + XCTAssertEqual(AbsolutePath("/a").basename, "a") + XCTAssertEqual(AbsolutePath("/./a").basename, "a") + XCTAssertEqual(AbsolutePath("/../..").basename, "/") XCTAssertEqual(RelativePath("../..").basename, "..") XCTAssertEqual(RelativePath("../a").basename, "a") XCTAssertEqual(RelativePath("../a/..").basename, "..") @@ -150,10 +150,10 @@ class PathTests: XCTestCase { } func testBaseNameWithoutExt() { - XCTAssertEqual(AbsolutePath(path: "/").basenameWithoutExt, "/") - XCTAssertEqual(AbsolutePath(path: "/a").basenameWithoutExt, "a") - XCTAssertEqual(AbsolutePath(path: "/./a").basenameWithoutExt, "a") - XCTAssertEqual(AbsolutePath(path: "/../..").basenameWithoutExt, "/") + XCTAssertEqual(AbsolutePath("/").basenameWithoutExt, "/") + XCTAssertEqual(AbsolutePath("/a").basenameWithoutExt, "a") + XCTAssertEqual(AbsolutePath("/./a").basenameWithoutExt, "a") + XCTAssertEqual(AbsolutePath("/../..").basenameWithoutExt, "/") XCTAssertEqual(RelativePath("../..").basenameWithoutExt, "..") XCTAssertEqual(RelativePath("../a").basenameWithoutExt, "a") XCTAssertEqual(RelativePath("../a/..").basenameWithoutExt, "..") @@ -164,8 +164,8 @@ class PathTests: XCTestCase { XCTAssertEqual(RelativePath("").basenameWithoutExt, ".") XCTAssertEqual(RelativePath(".").basenameWithoutExt, ".") - XCTAssertEqual(AbsolutePath(path: "/a.txt").basenameWithoutExt, "a") - XCTAssertEqual(AbsolutePath(path: "/./a.txt").basenameWithoutExt, "a") + XCTAssertEqual(AbsolutePath("/a.txt").basenameWithoutExt, "a") + XCTAssertEqual(AbsolutePath("/./a.txt").basenameWithoutExt, "a") XCTAssertEqual(RelativePath("../a.bc").basenameWithoutExt, "a") XCTAssertEqual(RelativePath("abc.swift").basenameWithoutExt, "abc") XCTAssertEqual(RelativePath("../a.b.c").basenameWithoutExt, "a.b") @@ -198,60 +198,60 @@ class PathTests: XCTestCase { } func testParentDirectory() { - XCTAssertEqual(AbsolutePath(path: "/").parentDirectory, AbsolutePath(path: "/")) - XCTAssertEqual(AbsolutePath(path: "/").parentDirectory.parentDirectory, AbsolutePath(path: "/")) - XCTAssertEqual(AbsolutePath(path: "/bar").parentDirectory, AbsolutePath(path: "/")) - XCTAssertEqual(AbsolutePath(path: "/bar/../foo/..//").parentDirectory.parentDirectory, AbsolutePath(path: "/")) - XCTAssertEqual(AbsolutePath(path: "/bar/../foo/..//yabba/a/b").parentDirectory.parentDirectory, AbsolutePath(path: "/yabba")) + XCTAssertEqual(AbsolutePath("/").parentDirectory, AbsolutePath("/")) + XCTAssertEqual(AbsolutePath("/").parentDirectory.parentDirectory, AbsolutePath("/")) + XCTAssertEqual(AbsolutePath("/bar").parentDirectory, AbsolutePath("/")) + XCTAssertEqual(AbsolutePath("/bar/../foo/..//").parentDirectory.parentDirectory, AbsolutePath("/")) + XCTAssertEqual(AbsolutePath("/bar/../foo/..//yabba/a/b").parentDirectory.parentDirectory, AbsolutePath("/yabba")) } @available(*, deprecated) func testConcatenation() { - XCTAssertEqual(AbsolutePath(AbsolutePath(path: "/"), RelativePath("")).pathString, "/") - XCTAssertEqual(AbsolutePath(AbsolutePath(path: "/"), RelativePath(".")).pathString, "/") - XCTAssertEqual(AbsolutePath(AbsolutePath(path: "/"), RelativePath("..")).pathString, "/") - XCTAssertEqual(AbsolutePath(AbsolutePath(path: "/"), RelativePath("bar")).pathString, "/bar") - XCTAssertEqual(AbsolutePath(AbsolutePath(path: "/foo/bar"), RelativePath("..")).pathString, "/foo") - XCTAssertEqual(AbsolutePath(AbsolutePath(path: "/bar"), RelativePath("../foo")).pathString, "/foo") - XCTAssertEqual(AbsolutePath(AbsolutePath(path: "/bar"), RelativePath("../foo/..//")).pathString, "/") - XCTAssertEqual(AbsolutePath(AbsolutePath(path: "/bar/../foo/..//yabba/"), RelativePath("a/b")).pathString, "/yabba/a/b") - - XCTAssertEqual(AbsolutePath(path: "/").appending(RelativePath("")).pathString, "/") - XCTAssertEqual(AbsolutePath(path: "/").appending(RelativePath(".")).pathString, "/") - XCTAssertEqual(AbsolutePath(path: "/").appending(RelativePath("..")).pathString, "/") - XCTAssertEqual(AbsolutePath(path: "/").appending(RelativePath("bar")).pathString, "/bar") - XCTAssertEqual(AbsolutePath(path: "/foo/bar").appending(RelativePath("..")).pathString, "/foo") - XCTAssertEqual(AbsolutePath(path: "/bar").appending(RelativePath("../foo")).pathString, "/foo") - XCTAssertEqual(AbsolutePath(path: "/bar").appending(RelativePath("../foo/..//")).pathString, "/") - XCTAssertEqual(AbsolutePath(path: "/bar/../foo/..//yabba/").appending(RelativePath("a/b")).pathString, "/yabba/a/b") - - XCTAssertEqual(AbsolutePath(path: "/").appending(component: "a").pathString, "/a") - XCTAssertEqual(AbsolutePath(path: "/a").appending(component: "b").pathString, "/a/b") - XCTAssertEqual(AbsolutePath(path: "/").appending(components: "a", "b").pathString, "/a/b") - XCTAssertEqual(AbsolutePath(path: "/a").appending(components: "b", "c").pathString, "/a/b/c") - - XCTAssertEqual(AbsolutePath(path: "/a/b/c").appending(components: "", "c").pathString, "/a/b/c/c") - XCTAssertEqual(AbsolutePath(path: "/a/b/c").appending(components: "").pathString, "/a/b/c") - XCTAssertEqual(AbsolutePath(path: "/a/b/c").appending(components: ".").pathString, "/a/b/c") - XCTAssertEqual(AbsolutePath(path: "/a/b/c").appending(components: "..").pathString, "/a/b") - XCTAssertEqual(AbsolutePath(path: "/a/b/c").appending(components: "..", "d").pathString, "/a/b/d") - XCTAssertEqual(AbsolutePath(path: "/").appending(components: "..").pathString, "/") - XCTAssertEqual(AbsolutePath(path: "/").appending(components: ".").pathString, "/") - XCTAssertEqual(AbsolutePath(path: "/").appending(components: "..", "a").pathString, "/a") + XCTAssertEqual(AbsolutePath(AbsolutePath("/"), RelativePath("")).pathString, "/") + XCTAssertEqual(AbsolutePath(AbsolutePath("/"), RelativePath(".")).pathString, "/") + XCTAssertEqual(AbsolutePath(AbsolutePath("/"), RelativePath("..")).pathString, "/") + XCTAssertEqual(AbsolutePath(AbsolutePath("/"), RelativePath("bar")).pathString, "/bar") + XCTAssertEqual(AbsolutePath(AbsolutePath("/foo/bar"), RelativePath("..")).pathString, "/foo") + XCTAssertEqual(AbsolutePath(AbsolutePath("/bar"), RelativePath("../foo")).pathString, "/foo") + XCTAssertEqual(AbsolutePath(AbsolutePath("/bar"), RelativePath("../foo/..//")).pathString, "/") + XCTAssertEqual(AbsolutePath(AbsolutePath("/bar/../foo/..//yabba/"), RelativePath("a/b")).pathString, "/yabba/a/b") + + XCTAssertEqual(AbsolutePath("/").appending(RelativePath("")).pathString, "/") + XCTAssertEqual(AbsolutePath("/").appending(RelativePath(".")).pathString, "/") + XCTAssertEqual(AbsolutePath("/").appending(RelativePath("..")).pathString, "/") + XCTAssertEqual(AbsolutePath("/").appending(RelativePath("bar")).pathString, "/bar") + XCTAssertEqual(AbsolutePath("/foo/bar").appending(RelativePath("..")).pathString, "/foo") + XCTAssertEqual(AbsolutePath("/bar").appending(RelativePath("../foo")).pathString, "/foo") + XCTAssertEqual(AbsolutePath("/bar").appending(RelativePath("../foo/..//")).pathString, "/") + XCTAssertEqual(AbsolutePath("/bar/../foo/..//yabba/").appending(RelativePath("a/b")).pathString, "/yabba/a/b") + + XCTAssertEqual(AbsolutePath("/").appending(component: "a").pathString, "/a") + XCTAssertEqual(AbsolutePath("/a").appending(component: "b").pathString, "/a/b") + XCTAssertEqual(AbsolutePath("/").appending(components: "a", "b").pathString, "/a/b") + XCTAssertEqual(AbsolutePath("/a").appending(components: "b", "c").pathString, "/a/b/c") + + XCTAssertEqual(AbsolutePath("/a/b/c").appending(components: "", "c").pathString, "/a/b/c/c") + XCTAssertEqual(AbsolutePath("/a/b/c").appending(components: "").pathString, "/a/b/c") + XCTAssertEqual(AbsolutePath("/a/b/c").appending(components: ".").pathString, "/a/b/c") + XCTAssertEqual(AbsolutePath("/a/b/c").appending(components: "..").pathString, "/a/b") + XCTAssertEqual(AbsolutePath("/a/b/c").appending(components: "..", "d").pathString, "/a/b/d") + XCTAssertEqual(AbsolutePath("/").appending(components: "..").pathString, "/") + XCTAssertEqual(AbsolutePath("/").appending(components: ".").pathString, "/") + XCTAssertEqual(AbsolutePath("/").appending(components: "..", "a").pathString, "/a") XCTAssertEqual(RelativePath("hello").appending(components: "a", "b", "c", "..").pathString, "hello/a/b") XCTAssertEqual(RelativePath("hello").appending(RelativePath("a/b/../c/d")).pathString, "hello/a/c/d") } func testPathComponents() { - XCTAssertEqual(AbsolutePath(path: "/").components, ["/"]) - XCTAssertEqual(AbsolutePath(path: "/.").components, ["/"]) - XCTAssertEqual(AbsolutePath(path: "/..").components, ["/"]) - XCTAssertEqual(AbsolutePath(path: "/bar").components, ["/", "bar"]) - XCTAssertEqual(AbsolutePath(path: "/foo/bar/..").components, ["/", "foo"]) - XCTAssertEqual(AbsolutePath(path: "/bar/../foo").components, ["/", "foo"]) - XCTAssertEqual(AbsolutePath(path: "/bar/../foo/..//").components, ["/"]) - XCTAssertEqual(AbsolutePath(path: "/bar/../foo/..//yabba/a/b/").components, ["/", "yabba", "a", "b"]) + XCTAssertEqual(AbsolutePath("/").components, ["/"]) + XCTAssertEqual(AbsolutePath("/.").components, ["/"]) + XCTAssertEqual(AbsolutePath("/..").components, ["/"]) + XCTAssertEqual(AbsolutePath("/bar").components, ["/", "bar"]) + XCTAssertEqual(AbsolutePath("/foo/bar/..").components, ["/", "foo"]) + XCTAssertEqual(AbsolutePath("/bar/../foo").components, ["/", "foo"]) + XCTAssertEqual(AbsolutePath("/bar/../foo/..//").components, ["/"]) + XCTAssertEqual(AbsolutePath("/bar/../foo/..//yabba/a/b/").components, ["/", "yabba", "a", "b"]) XCTAssertEqual(RelativePath("").components, ["."]) XCTAssertEqual(RelativePath(".").components, ["."]) @@ -272,44 +272,44 @@ class PathTests: XCTestCase { } func testRelativePathFromAbsolutePaths() { - XCTAssertEqual(AbsolutePath(path: "/").relative(to: AbsolutePath(path: "/")), RelativePath(".")); - XCTAssertEqual(AbsolutePath(path: "/a/b/c/d").relative(to: AbsolutePath(path: "/")), RelativePath("a/b/c/d")); - XCTAssertEqual(AbsolutePath(path: "/").relative(to: AbsolutePath(path: "/a/b/c")), RelativePath("../../..")); - XCTAssertEqual(AbsolutePath(path: "/a/b/c/d").relative(to: AbsolutePath(path: "/a/b")), RelativePath("c/d")); - XCTAssertEqual(AbsolutePath(path: "/a/b/c/d").relative(to: AbsolutePath(path: "/a/b/c")), RelativePath("d")); - XCTAssertEqual(AbsolutePath(path: "/a/b/c/d").relative(to: AbsolutePath(path: "/a/c/d")), RelativePath("../../b/c/d")); - XCTAssertEqual(AbsolutePath(path: "/a/b/c/d").relative(to: AbsolutePath(path: "/b/c/d")), RelativePath("../../../a/b/c/d")); + XCTAssertEqual(AbsolutePath("/").relative(to: AbsolutePath("/")), RelativePath(".")); + XCTAssertEqual(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/")), RelativePath("a/b/c/d")); + XCTAssertEqual(AbsolutePath("/").relative(to: AbsolutePath("/a/b/c")), RelativePath("../../..")); + XCTAssertEqual(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/a/b")), RelativePath("c/d")); + XCTAssertEqual(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/a/b/c")), RelativePath("d")); + XCTAssertEqual(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/a/c/d")), RelativePath("../../b/c/d")); + XCTAssertEqual(AbsolutePath("/a/b/c/d").relative(to: AbsolutePath("/b/c/d")), RelativePath("../../../a/b/c/d")); } func testComparison() { - XCTAssertTrue(AbsolutePath(path: "/") <= AbsolutePath(path: "/")); - XCTAssertTrue(AbsolutePath(path: "/abc") < AbsolutePath(path: "/def")); - XCTAssertTrue(AbsolutePath(path: "/2") <= AbsolutePath(path: "/2.1")); - XCTAssertTrue(AbsolutePath(path: "/3.1") > AbsolutePath(path: "/2")); - XCTAssertTrue(AbsolutePath(path: "/2") >= AbsolutePath(path: "/2")); - XCTAssertTrue(AbsolutePath(path: "/2.1") >= AbsolutePath(path: "/2")); + XCTAssertTrue(AbsolutePath("/") <= AbsolutePath("/")); + XCTAssertTrue(AbsolutePath("/abc") < AbsolutePath("/def")); + XCTAssertTrue(AbsolutePath("/2") <= AbsolutePath("/2.1")); + XCTAssertTrue(AbsolutePath("/3.1") > AbsolutePath("/2")); + XCTAssertTrue(AbsolutePath("/2") >= AbsolutePath("/2")); + XCTAssertTrue(AbsolutePath("/2.1") >= AbsolutePath("/2")); } func testAncestry() { - XCTAssertTrue(AbsolutePath(path: "/a/b/c/d/e/f").isDescendantOfOrEqual(to: AbsolutePath(path: "/a/b/c/d"))) - XCTAssertTrue(AbsolutePath(path: "/a/b/c/d/e/f.swift").isDescendantOfOrEqual(to: AbsolutePath(path: "/a/b/c"))) - XCTAssertTrue(AbsolutePath(path: "/").isDescendantOfOrEqual(to: AbsolutePath(path: "/"))) - XCTAssertTrue(AbsolutePath(path: "/foo/bar").isDescendantOfOrEqual(to: AbsolutePath(path: "/"))) - XCTAssertFalse(AbsolutePath(path: "/foo/bar").isDescendantOfOrEqual(to: AbsolutePath(path: "/foo/bar/baz"))) - XCTAssertFalse(AbsolutePath(path: "/foo/bar").isDescendantOfOrEqual(to: AbsolutePath(path: "/bar"))) - - XCTAssertFalse(AbsolutePath(path: "/foo/bar").isDescendant(of: AbsolutePath(path: "/foo/bar"))) - XCTAssertTrue(AbsolutePath(path: "/foo/bar").isDescendant(of: AbsolutePath(path: "/foo"))) - - XCTAssertTrue(AbsolutePath(path: "/a/b/c/d").isAncestorOfOrEqual(to: AbsolutePath(path: "/a/b/c/d/e/f"))) - XCTAssertTrue(AbsolutePath(path: "/a/b/c").isAncestorOfOrEqual(to: AbsolutePath(path: "/a/b/c/d/e/f.swift"))) - XCTAssertTrue(AbsolutePath(path: "/").isAncestorOfOrEqual(to: AbsolutePath(path: "/"))) - XCTAssertTrue(AbsolutePath(path: "/").isAncestorOfOrEqual(to: AbsolutePath(path: "/foo/bar"))) - XCTAssertFalse(AbsolutePath(path: "/foo/bar/baz").isAncestorOfOrEqual(to: AbsolutePath(path: "/foo/bar"))) - XCTAssertFalse(AbsolutePath(path: "/bar").isAncestorOfOrEqual(to: AbsolutePath(path: "/foo/bar"))) - - XCTAssertFalse(AbsolutePath(path: "/foo/bar").isAncestor(of: AbsolutePath(path: "/foo/bar"))) - XCTAssertTrue(AbsolutePath(path: "/foo").isAncestor(of: AbsolutePath(path: "/foo/bar"))) + XCTAssertTrue(AbsolutePath("/a/b/c/d/e/f").isDescendantOfOrEqual(to: AbsolutePath("/a/b/c/d"))) + XCTAssertTrue(AbsolutePath("/a/b/c/d/e/f.swift").isDescendantOfOrEqual(to: AbsolutePath("/a/b/c"))) + XCTAssertTrue(AbsolutePath("/").isDescendantOfOrEqual(to: AbsolutePath("/"))) + XCTAssertTrue(AbsolutePath("/foo/bar").isDescendantOfOrEqual(to: AbsolutePath("/"))) + XCTAssertFalse(AbsolutePath("/foo/bar").isDescendantOfOrEqual(to: AbsolutePath("/foo/bar/baz"))) + XCTAssertFalse(AbsolutePath("/foo/bar").isDescendantOfOrEqual(to: AbsolutePath("/bar"))) + + XCTAssertFalse(AbsolutePath("/foo/bar").isDescendant(of: AbsolutePath("/foo/bar"))) + XCTAssertTrue(AbsolutePath("/foo/bar").isDescendant(of: AbsolutePath("/foo"))) + + XCTAssertTrue(AbsolutePath("/a/b/c/d").isAncestorOfOrEqual(to: AbsolutePath("/a/b/c/d/e/f"))) + XCTAssertTrue(AbsolutePath("/a/b/c").isAncestorOfOrEqual(to: AbsolutePath("/a/b/c/d/e/f.swift"))) + XCTAssertTrue(AbsolutePath("/").isAncestorOfOrEqual(to: AbsolutePath("/"))) + XCTAssertTrue(AbsolutePath("/").isAncestorOfOrEqual(to: AbsolutePath("/foo/bar"))) + XCTAssertFalse(AbsolutePath("/foo/bar/baz").isAncestorOfOrEqual(to: AbsolutePath("/foo/bar"))) + XCTAssertFalse(AbsolutePath("/bar").isAncestorOfOrEqual(to: AbsolutePath("/foo/bar"))) + + XCTAssertFalse(AbsolutePath("/foo/bar").isAncestor(of: AbsolutePath("/foo/bar"))) + XCTAssertTrue(AbsolutePath("/foo").isAncestor(of: AbsolutePath("/foo/bar"))) } func testAbsolutePathValidation() { @@ -328,12 +328,13 @@ class PathTests: XCTestCase { XCTAssertNoThrow(try RelativePath(validating: "a/b/c/d")) XCTAssertThrowsError(try RelativePath(validating: "/a/b/d")) { error in - XCTAssertEqual("\(error)", "invalid relative path '/a/b/d'; relative path should not begin with '/' or '~'") + XCTAssertEqual("\(error)", "invalid relative path '/a/b/d'; relative path should not begin with '/'") + //XCTAssertEqual("\(error)", "invalid relative path '/a/b/d'; relative path should not begin with '/' or '~'") } - XCTAssertThrowsError(try RelativePath(validating: "~/a/b/d")) { error in + /*XCTAssertThrowsError(try RelativePath(validating: "~/a/b/d")) { error in XCTAssertEqual("\(error)", "invalid relative path '~/a/b/d'; relative path should not begin with '/' or '~'") - } + }*/ } func testCodable() throws { @@ -350,14 +351,14 @@ class PathTests: XCTestCase { } do { - let foo = Foo(path: AbsolutePath(path: "/path/to/foo")) + let foo = Foo(path: "/path/to/foo") let data = try JSONEncoder().encode(foo) let decodedFoo = try JSONDecoder().decode(Foo.self, from: data) XCTAssertEqual(foo, decodedFoo) } do { - let foo = Foo(path: AbsolutePath(path: "/path/to/../to/foo")) + let foo = Foo(path: "/path/to/../to/foo") let data = try JSONEncoder().encode(foo) let decodedFoo = try JSONDecoder().decode(Foo.self, from: data) XCTAssertEqual(foo, decodedFoo) @@ -366,14 +367,14 @@ class PathTests: XCTestCase { } do { - let bar = Bar(path: RelativePath("path/to/bar")) + let bar = Bar(path: "path/to/bar") let data = try JSONEncoder().encode(bar) let decodedBar = try JSONDecoder().decode(Bar.self, from: data) XCTAssertEqual(bar, decodedBar) } do { - let bar = Bar(path: RelativePath("path/to/../to/bar")) + let bar = Bar(path: "path/to/../to/bar") let data = try JSONEncoder().encode(bar) let decodedBar = try JSONDecoder().decode(Bar.self, from: data) XCTAssertEqual(bar, decodedBar) diff --git a/Tests/TSCBasicTests/ProcessSetTests.swift b/Tests/TSCBasicTests/ProcessSetTests.swift index 700605d6..e6f98c11 100644 --- a/Tests/TSCBasicTests/ProcessSetTests.swift +++ b/Tests/TSCBasicTests/ProcessSetTests.swift @@ -17,7 +17,7 @@ import TSCTestSupport class ProcessSetTests: XCTestCase { #if !os(Windows) // Signals are not supported in Windows func script(_ name: String) -> String { - return AbsolutePath(path: #file).parentDirectory.appending(components: "processInputs", name).pathString + return AbsolutePath(#file).parentDirectory.appending(components: "processInputs", name).pathString } func testSigInt() throws { diff --git a/Tests/TSCBasicTests/ProcessTests.swift b/Tests/TSCBasicTests/ProcessTests.swift index 5c63ecf1..1e616a04 100644 --- a/Tests/TSCBasicTests/ProcessTests.swift +++ b/Tests/TSCBasicTests/ProcessTests.swift @@ -470,7 +470,7 @@ fileprivate extension Process { } private static func script(_ name: String) -> String { - return AbsolutePath(path: #file).parentDirectory.appending(components: "processInputs", name).pathString + return AbsolutePath(#file).parentDirectory.appending(components: "processInputs", name).pathString } convenience init(scriptName: String, arguments: [String] = [], outputRedirection: OutputRedirection = .collect) { diff --git a/Tests/TSCBasicTests/miscTests.swift b/Tests/TSCBasicTests/miscTests.swift index c4e8ebc9..0f9443f1 100644 --- a/Tests/TSCBasicTests/miscTests.swift +++ b/Tests/TSCBasicTests/miscTests.swift @@ -48,13 +48,13 @@ class miscTests: XCTestCase { } func testEnvSearchPaths() throws { - let cwd = AbsolutePath(path: "/dummy") + let cwd = AbsolutePath("/dummy") let paths = getEnvSearchPaths(pathString: "something:.:abc/../.build/debug:/usr/bin:/bin/", currentWorkingDirectory: cwd) XCTAssertEqual(paths, try ["/dummy/something", "/dummy", "/dummy/.build/debug", "/usr/bin", "/bin"].map({ try AbsolutePath(validating: $0)})) } func testEmptyEnvSearchPaths() throws { - let cwd = AbsolutePath(path: "/dummy") + let cwd = AbsolutePath("/dummy") let paths = getEnvSearchPaths(pathString: "", currentWorkingDirectory: cwd) XCTAssertEqual(paths, []) diff --git a/Tests/TSCUtilityTests/BitstreamTests.swift b/Tests/TSCUtilityTests/BitstreamTests.swift index bc099a95..700f13b3 100644 --- a/Tests/TSCUtilityTests/BitstreamTests.swift +++ b/Tests/TSCUtilityTests/BitstreamTests.swift @@ -33,7 +33,7 @@ final class BitstreamTests: XCTestCase { } } - let bitstreamPath = AbsolutePath(path: #file).parentDirectory + let bitstreamPath = AbsolutePath(#file).parentDirectory .appending(components: "Inputs", "serialized.dia") let contents = try localFileSystem.readFileContents(bitstreamPath) var visitor = LoggingVisitor() @@ -126,7 +126,7 @@ final class BitstreamTests: XCTestCase { } } - let bitstreamPath = AbsolutePath(path: #file).parentDirectory + let bitstreamPath = AbsolutePath(#file).parentDirectory .appending(components: "Inputs", "serialized.dia") let contents = try localFileSystem.readFileContents(bitstreamPath) var visitor = LoggingVisitor() diff --git a/Tests/TSCUtilityTests/SerializedDiagnosticsTests.swift b/Tests/TSCUtilityTests/SerializedDiagnosticsTests.swift index 469d0bb7..2a024e85 100644 --- a/Tests/TSCUtilityTests/SerializedDiagnosticsTests.swift +++ b/Tests/TSCUtilityTests/SerializedDiagnosticsTests.swift @@ -15,7 +15,7 @@ import TSCUtility final class SerializedDiagnosticsTests: XCTestCase { func testReadSwiftDiagnosticWithNote() throws { - let serializedDiagnosticsPath = AbsolutePath(path: #file).parentDirectory + let serializedDiagnosticsPath = AbsolutePath(#file).parentDirectory .appending(components: "Inputs", "multiblock.dia") let contents = try localFileSystem.readFileContents(serializedDiagnosticsPath) let serializedDiags = try SerializedDiagnostics(bytes: contents) @@ -97,7 +97,7 @@ final class SerializedDiagnosticsTests: XCTestCase { } func testReadSwiftSerializedDiags() throws { - let serializedDiagnosticsPath = AbsolutePath(path: #file).parentDirectory + let serializedDiagnosticsPath = AbsolutePath(#file).parentDirectory .appending(components: "Inputs", "serialized.dia") let contents = try localFileSystem.readFileContents(serializedDiagnosticsPath) let serializedDiags = try SerializedDiagnostics(bytes: contents) @@ -145,7 +145,7 @@ final class SerializedDiagnosticsTests: XCTestCase { } func testReadDiagsWithNoLocation() throws { - let serializedDiagnosticsPath = AbsolutePath(path: #file).parentDirectory + let serializedDiagnosticsPath = AbsolutePath(#file).parentDirectory .appending(components: "Inputs", "no-location.dia") let contents = try localFileSystem.readFileContents(serializedDiagnosticsPath) let serializedDiags = try SerializedDiagnostics(bytes: contents) @@ -164,7 +164,7 @@ final class SerializedDiagnosticsTests: XCTestCase { } func testReadDiagsWithUnknownRecord() throws { - let serializedDiagnosticsPath = AbsolutePath(path: #file).parentDirectory + let serializedDiagnosticsPath = AbsolutePath(#file).parentDirectory .appending(components: "Inputs", "string_init_ambig.dia") let contents = try localFileSystem.readFileContents(serializedDiagnosticsPath) let serializedDiags = try SerializedDiagnostics(bytes: contents) @@ -174,7 +174,7 @@ final class SerializedDiagnosticsTests: XCTestCase { } func testReadClangSerializedDiags() throws { - let serializedDiagnosticsPath = AbsolutePath(path: #file).parentDirectory + let serializedDiagnosticsPath = AbsolutePath(#file).parentDirectory .appending(components: "Inputs", "clang.dia") let contents = try localFileSystem.readFileContents(serializedDiagnosticsPath) let serializedDiags = try SerializedDiagnostics(bytes: contents) diff --git a/Tests/TSCUtilityTests/SimplePersistenceTests.swift b/Tests/TSCUtilityTests/SimplePersistenceTests.swift index a4ed5ed5..f231fead 100644 --- a/Tests/TSCUtilityTests/SimplePersistenceTests.swift +++ b/Tests/TSCUtilityTests/SimplePersistenceTests.swift @@ -119,7 +119,7 @@ class SimplePersistenceTests: XCTestCase { func testBasics() throws { let fs = InMemoryFileSystem() let stateFile = AbsolutePath.root.appending(components: "subdir", "state.json") - let foo = Foo(int: 1, path: AbsolutePath(path: "/hello"), fileSystem: fs) + let foo = Foo(int: 1, path: "/hello", fileSystem: fs) // Restoring right now should return false because state is not present. XCTAssertFalse(try foo.restore()) @@ -133,7 +133,7 @@ class SimplePersistenceTests: XCTestCase { foo.int = 5 XCTAssertTrue(try foo.restore()) XCTAssertEqual(foo.int, 1) - XCTAssertEqual(foo.path, AbsolutePath(path: "/hello")) + XCTAssertEqual(foo.path, "/hello") // Modify state's schema version. let newJSON = JSON(["version": 2]) @@ -194,14 +194,14 @@ class SimplePersistenceTests: XCTestCase { """ } - let foo = Foo(int: 1, path: AbsolutePath(path: "/hello"), fileSystem: fs) - XCTAssertEqual(foo.path, AbsolutePath(path: "/hello")) + let foo = Foo(int: 1, path: "/hello", fileSystem: fs) + XCTAssertEqual(foo.path, "/hello") XCTAssertEqual(foo.int, 1) // Load from an older but supported schema state file. XCTAssertTrue(try foo.restore()) - XCTAssertEqual(foo.path, AbsolutePath(path: "/oldpath")) + XCTAssertEqual(foo.path, "/oldpath") XCTAssertEqual(foo.int, 4) } }