Skip to content

Commit bcd90cd

Browse files
authored
Merge pull request #2808 from spevans/pr_sr_12366
2 parents 5db60c0 + 64ad03e commit bcd90cd

File tree

7 files changed

+118
-12
lines changed

7 files changed

+118
-12
lines changed

DarwinCompatibilityTests.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
B94B0837240185FF00B244E8 /* DarwinShims.swift in Sources */ = {isa = PBXBuildFile; fileRef = B94B0836240185FF00B244E8 /* DarwinShims.swift */; };
139139
B9ED84FD23641F7000A58AF2 /* DarwinShims.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F3269E1FC714DD003C3599 /* DarwinShims.swift */; };
140140
B9F137A120B998D0000B7577 /* xdgTestHelper in CopyFiles */ = {isa = PBXBuildFile; fileRef = B917D31C20B0DB8B00728EE0 /* xdgTestHelper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
141+
B9F4492A2483FA1E00B30F02 /* TestNSURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F449292483FA1E00B30F02 /* TestNSURL.swift */; };
141142
/* End PBXBuildFile section */
142143

143144
/* Begin PBXContainerItemProxy section */
@@ -310,6 +311,7 @@
310311
B9C89EDB1F6BF77E00087AF4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
311312
B9C89EDF1F6BF79000087AF4 /* TestFoundation */ = {isa = PBXFileReference; lastKnownFileType = folder; name = TestFoundation; path = ../TestFoundation; sourceTree = "<group>"; };
312313
B9F3269E1FC714DD003C3599 /* DarwinShims.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DarwinShims.swift; sourceTree = "<group>"; };
314+
B9F449292483FA1E00B30F02 /* TestNSURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestNSURL.swift; path = Tests/Foundation/Tests/TestNSURL.swift; sourceTree = "<group>"; };
313315
/* End PBXFileReference section */
314316

315317
/* Begin PBXFrameworksBuildPhase section */
@@ -341,6 +343,7 @@
341343
B9C89EB81F6BF47D00087AF4 = {
342344
isa = PBXGroup;
343345
children = (
346+
B9F449292483FA1E00B30F02 /* TestNSURL.swift */,
344347
B91161AE242A385A00BD2907 /* TestDataURLProtocol.swift */,
345348
B94B08342401854E00B244E8 /* main.swift */,
346349
B94B07822401849700B244E8 /* TestAffineTransform.swift */,
@@ -681,6 +684,7 @@
681684
B94B07D62401849B00B244E8 /* TestUserDefaults.swift in Sources */,
682685
B94B07D72401849B00B244E8 /* TestNSTextCheckingResult.swift in Sources */,
683686
B94B07D82401849B00B244E8 /* TestNSNumberBridging.swift in Sources */,
687+
B9F4492A2483FA1E00B30F02 /* TestNSURL.swift in Sources */,
684688
B94B07D92401849B00B244E8 /* TestOperationQueue.swift in Sources */,
685689
B94B07DA2401849B00B244E8 /* TestJSONEncoder.swift in Sources */,
686690
B94B07DB2401849B00B244E8 /* TestNSKeyedArchiver.swift in Sources */,

Foundation.xcodeproj/project.pbxproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@
409409
B9D9734123D19E2E00AB249C /* TestNSDateComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9D9734023D19E2E00AB249C /* TestNSDateComponents.swift */; };
410410
B9D9734323D19FD100AB249C /* TestURLComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9D9734223D19FD100AB249C /* TestURLComponents.swift */; };
411411
B9D9734523D1A36E00AB249C /* TestHTTPURLResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9D9734423D1A36E00AB249C /* TestHTTPURLResponse.swift */; };
412+
B9F4492D2483FFD700B30F02 /* TestNSURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F4492B2483FFBF00B30F02 /* TestNSURL.swift */; };
412413
BB3D7558208A1E500085CFDC /* Imports.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3D7557208A1E500085CFDC /* Imports.swift */; };
413414
BD8042161E09857800487EB8 /* TestLengthFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD8042151E09857800487EB8 /* TestLengthFormatter.swift */; };
414415
BDBB65901E256BFA001A7286 /* TestEnergyFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDBB658F1E256BFA001A7286 /* TestEnergyFormatter.swift */; };
@@ -1108,6 +1109,7 @@
11081109
B9D9734023D19E2E00AB249C /* TestNSDateComponents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSDateComponents.swift; sourceTree = "<group>"; };
11091110
B9D9734223D19FD100AB249C /* TestURLComponents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestURLComponents.swift; sourceTree = "<group>"; };
11101111
B9D9734423D1A36E00AB249C /* TestHTTPURLResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestHTTPURLResponse.swift; sourceTree = "<group>"; };
1112+
B9F4492B2483FFBF00B30F02 /* TestNSURL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSURL.swift; sourceTree = "<group>"; };
11111113
BB3D7557208A1E500085CFDC /* Imports.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Imports.swift; sourceTree = "<group>"; };
11121114
BD8042151E09857800487EB8 /* TestLengthFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestLengthFormatter.swift; sourceTree = "<group>"; };
11131115
BDBB658F1E256BFA001A7286 /* TestEnergyFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestEnergyFormatter.swift; sourceTree = "<group>"; };
@@ -1832,6 +1834,7 @@
18321834
152EF3932283457B001E1269 /* TestNSSortDescriptor.swift */,
18331835
EA66F6421BF1619600136161 /* TestNSString.swift */,
18341836
5FE52C941D147D1C00F7D270 /* TestNSTextCheckingResult.swift */,
1837+
B9F4492B2483FFBF00B30F02 /* TestNSURL.swift */,
18351838
83712C8D1C1684900049AD49 /* TestNSURLRequest.swift */,
18361839
C2A9D75B1C15C08B00993803 /* TestNSUUID.swift */,
18371840
D3047AEB1C38BC3300295652 /* TestNSValue.swift */,
@@ -2613,7 +2616,7 @@
26132616
};
26142617
5B7C8A6D1BEA7F8F00C5B690 = {
26152618
CreatedOnToolsVersion = 7.2;
2616-
LastSwiftMigration = 1140;
2619+
LastSwiftMigration = 1150;
26172620
ProvisioningStyle = Manual;
26182621
};
26192622
5BDC405B1BD6D83B00ED97BB = {
@@ -3046,6 +3049,7 @@
30463049
isa = PBXSourcesBuildPhase;
30473050
buildActionMask = 2147483647;
30483051
files = (
3052+
B9F4492D2483FFD700B30F02 /* TestNSURL.swift in Sources */,
30493053
B91161AD242A363900BD2907 /* TestDataURLProtocol.swift in Sources */,
30503054
B95FC97622B84B0A005DEA0A /* TestNSSortDescriptor.swift in Sources */,
30513055
B940492D223B146800FB4384 /* TestProgressFraction.swift in Sources */,

Sources/Foundation/NSURL.swift

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -640,20 +640,23 @@ open class NSURL : NSObject, NSSecureCoding, NSCopying {
640640

641641
/* A string constant for the "file" URL scheme. If you are using this to compare to a URL's scheme to see if it is a file URL, you should instead use the NSURL fileURL property -- the fileURL property is much faster. */
642642
open var standardized: URL? {
643-
guard (path != nil) else {
643+
guard path != nil else {
644644
return nil
645645
}
646646

647-
let URLComponents = NSURLComponents(string: relativeString)
648-
guard ((URLComponents != nil) && (URLComponents!.path != nil)) else {
647+
guard let components = NSURLComponents(string: relativeString), let componentPath = components.path else {
649648
return nil
650649
}
651-
guard (URLComponents!.path!.contains("..") || URLComponents!.path!.contains(".")) else{
652-
return URLComponents!.url(relativeTo: baseURL)
650+
651+
if componentPath.contains("..") || componentPath.contains(".") {
652+
components.path = _pathByRemovingDots(pathComponents!)
653+
}
654+
655+
if let filePath = components.path, isFileURL {
656+
return URL(fileURLWithPath: filePath, isDirectory: hasDirectoryPath, relativeTo: baseURL)
653657
}
654658

655-
URLComponents!.path! = _pathByRemovingDots(pathComponents!)
656-
return URLComponents!.url(relativeTo: baseURL)
659+
return components.url(relativeTo: baseURL)
657660
}
658661

659662
/* Returns whether the URL's resource exists and is reachable. This method synchronously checks if the resource's backing store is reachable. Checking reachability is appropriate when making decisions that do not require other immediate operations on the resource, e.g. periodic maintenance of UI state that depends on the existence of a specific document. When performing operations such as opening a file or copying resource properties, it is more efficient to simply try the operation and handle failures. If this method returns NO, the optional error is populated. This method is currently applicable only to URLs for file system resources. For other URL types, NO is returned. Symbol is present in iOS 4, but performs no operation.
@@ -997,14 +1000,14 @@ extension NSURL {
9971000
open var standardizingPath: URL? {
9981001
// Documentation says it should expand initial tilde, but it does't do this on OS X.
9991002
// In remaining cases it works just like URLByResolvingSymlinksInPath.
1000-
return resolvingSymlinksInPath
1003+
return _resolveSymlinksInPath(excludeSystemDirs: true, preserveDirectoryFlag: true)
10011004
}
10021005

10031006
open var resolvingSymlinksInPath: URL? {
10041007
return _resolveSymlinksInPath(excludeSystemDirs: true)
10051008
}
10061009

1007-
internal func _resolveSymlinksInPath(excludeSystemDirs: Bool) -> URL? {
1010+
internal func _resolveSymlinksInPath(excludeSystemDirs: Bool, preserveDirectoryFlag: Bool = false) -> URL? {
10081011
guard isFileURL else {
10091012
return URL(string: absoluteString)
10101013
}
@@ -1056,8 +1059,12 @@ extension NSURL {
10561059
if isExistingDirectory.boolValue && !resolvedPath.hasSuffix("/") {
10571060
resolvedPath += "/"
10581061
}
1059-
1060-
return URL(fileURLWithPath: resolvedPath)
1062+
1063+
if preserveDirectoryFlag {
1064+
return URL(fileURLWithPath: resolvedPath, isDirectory: self.hasDirectoryPath)
1065+
} else {
1066+
return URL(fileURLWithPath: resolvedPath)
1067+
}
10611068
}
10621069

10631070
fileprivate func _pathByRemovingDots(_ comps: [String]) -> String {

Tests/Foundation/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ target_sources(TestFoundation PRIVATE
6868
Tests/TestNSSortDescriptor.swift
6969
Tests/TestNSString.swift
7070
Tests/TestNSTextCheckingResult.swift
71+
Tests/TestNSURL.swift
7172
Tests/TestNSURLRequest.swift
7273
Tests/TestNSUUID.swift
7374
Tests/TestNSValue.swift
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// This source file is part of the Swift.org open source project
2+
//
3+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
4+
// Licensed under Apache License v2.0 with Runtime Library Exception
5+
//
6+
// See https://swift.org/LICENSE.txt for license information
7+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
8+
//
9+
10+
class TestNSURL: XCTestCase {
11+
12+
func test_absoluteString() {
13+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/folder", isDirectory: true).absoluteString, "file:///path/to/folder/")
14+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/folder/", isDirectory: true).absoluteString, "file:///path/to/folder/")
15+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/../folder", isDirectory: true).absoluteString, "file:///path/../folder/")
16+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/./folder/..", isDirectory: true).absoluteString, "file:///path/to/./folder/../")
17+
18+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/.file", isDirectory: false).absoluteString, "file:///path/to/.file")
19+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/file/", isDirectory: false).absoluteString, "file:///path/to/file")
20+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/../file", isDirectory: false).absoluteString, "file:///path/../file")
21+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/./file/..", isDirectory: false).absoluteString, "file:///path/to/./file/..")
22+
}
23+
24+
func test_pathComponents() {
25+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/folder", isDirectory: true).pathComponents, ["/", "path", "to", "folder"])
26+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/folder/", isDirectory: true).pathComponents, ["/", "path", "to", "folder"])
27+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/../folder", isDirectory: true).pathComponents, ["/", "path", "..", "folder"])
28+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/../folder", isDirectory: true).standardized?.pathComponents, ["/", "folder"])
29+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/./folder/..", isDirectory: true).pathComponents, ["/", "path", "to", ".", "folder", ".."])
30+
31+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/.file", isDirectory: false).pathComponents, ["/", "path", "to", ".file"])
32+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/file/", isDirectory: false).pathComponents, ["/", "path", "to", "file"])
33+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/../file", isDirectory: false).pathComponents, ["/", "path", "..", "file"])
34+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/./file/..", isDirectory: false).pathComponents, ["/", "path", "to", ".", "file", ".."])
35+
}
36+
37+
func test_standardized() {
38+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/folder", isDirectory: true).standardized?.absoluteString, "file:///path/to/folder/")
39+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/folder/", isDirectory: true).standardized?.absoluteString, "file:///path/to/folder/")
40+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/../folder", isDirectory: true).standardized?.absoluteString, "file:///folder/")
41+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/./folder/..", isDirectory: true).standardized?.absoluteString, "file:///path/to/")
42+
43+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/.file", isDirectory: false).standardized?.absoluteString, "file:///path/to/.file")
44+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/file/", isDirectory: false).standardized?.absoluteString, "file:///path/to/file")
45+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/../file", isDirectory: false).standardized?.absoluteString, "file:///file")
46+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/./file/..", isDirectory: false).standardized?.absoluteString, "file:///path/to")
47+
}
48+
49+
func test_standardizingPath() {
50+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/folder", isDirectory: true).standardizingPath?.absoluteString, "file:///path/to/folder/")
51+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/folder/", isDirectory: true).standardizingPath?.absoluteString, "file:///path/to/folder/")
52+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/../folder", isDirectory: true).standardizingPath?.absoluteString, "file:///folder/")
53+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/./folder/..", isDirectory: true).standardizingPath?.absoluteString, "file:///path/to/")
54+
55+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/.file", isDirectory: false).standardizingPath?.absoluteString, "file:///path/to/.file")
56+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/file/", isDirectory: false).standardizingPath?.absoluteString, "file:///path/to/file")
57+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/../file", isDirectory: false).standardizingPath?.absoluteString, "file:///file")
58+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/./file/..", isDirectory: false).standardizingPath?.absoluteString, "file:///path/to")
59+
}
60+
61+
func test_resolvingSymlinksInPath() {
62+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/folder", isDirectory: true).resolvingSymlinksInPath?.absoluteString, "file:///path/to/folder")
63+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/folder/", isDirectory: true).resolvingSymlinksInPath?.absoluteString, "file:///path/to/folder")
64+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/../folder", isDirectory: true).resolvingSymlinksInPath?.absoluteString, "file:///folder")
65+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/./folder/..", isDirectory: true).resolvingSymlinksInPath?.absoluteString, "file:///path/to")
66+
67+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/.file", isDirectory: false).resolvingSymlinksInPath?.absoluteString, "file:///path/to/.file")
68+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/file/", isDirectory: false).resolvingSymlinksInPath?.absoluteString, "file:///path/to/file")
69+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/../file", isDirectory: false).resolvingSymlinksInPath?.absoluteString, "file:///file")
70+
XCTAssertEqual(NSURL(fileURLWithPath: "/path/to/./file/..", isDirectory: false).resolvingSymlinksInPath?.absoluteString, "file:///path/to")
71+
}
72+
73+
static var allTests: [(String, (TestNSURL) -> () throws -> Void)] {
74+
let tests: [(String, (TestNSURL) -> () throws -> Void)] = [
75+
("test_absoluteString", test_absoluteString),
76+
("test_pathComponents", test_pathComponents),
77+
("test_standardized", test_standardized),
78+
("test_standardizingPath", test_standardizingPath),
79+
("test_resolvingSymlinksInPath", test_resolvingSymlinksInPath),
80+
]
81+
82+
return tests
83+
}
84+
}

Tests/Foundation/Tests/TestURL.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,11 @@ class TestURL : XCTestCase {
434434
let lengthOfRelativePath = Int(strlen(TestURL.gFileDoesNotExistName))
435435
let relativePath = fileSystemRep.advanced(by: Int(TestURL.gRelativeOffsetFromBaseCurrentWorkingDirectory))
436436
XCTAssertTrue(strncmp(TestURL.gFileDoesNotExistName, relativePath, lengthOfRelativePath) == 0, "fileSystemRepresentation of file path is wrong")
437+
438+
// SR-12366
439+
let url1 = URL(fileURLWithPath: "/path/to/b/folder", isDirectory: true).standardizedFileURL.absoluteString
440+
let url2 = URL(fileURLWithPath: "/path/to/b/folder", isDirectory: true).absoluteString
441+
XCTAssertEqual(url1, url2)
437442
}
438443

439444
func test_fileURLWithPath_isDirectory() {

Tests/Foundation/main.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ var allTestCases = [
9292
testCase(TestURLProtectionSpace.allTests),
9393
testCase(TestURLProtocol.allTests),
9494
testCase(TestNSURLRequest.allTests),
95+
testCase(TestNSURL.allTests),
9596
testCase(TestURLRequest.allTests),
9697
testCase(TestURLResponse.allTests),
9798
testCase(TestHTTPURLResponse.allTests),

0 commit comments

Comments
 (0)