Skip to content

Commit f870946

Browse files
authored
Merge pull request #5 from apple/update
Sync with SwiftPM trunk
2 parents 8aad804 + 7c17aae commit f870946

15 files changed

+166
-30
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
/Packages
44
/*.xcodeproj
55
xcuserdata/
6+
.swiftpm

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version:4.2
1+
// swift-tools-version:5.1
22

33
/*
44
This source file is part of the Swift.org open source project

Sources/TSCBasic/DictionaryLiteralExtensions.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// Can't conform a protocol explicitly with certain where clause for now but it'd be resolved by SE-0143.
1212
// ref: https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md
1313
// MARK: CustomStringConvertible
14-
extension DictionaryLiteral where Key: CustomStringConvertible, Value: CustomStringConvertible {
14+
extension KeyValuePairs where Key: CustomStringConvertible, Value: CustomStringConvertible {
1515
/// A string that represents the contents of the dictionary literal.
1616
public var description: String {
1717
let lastCount = self.count - 1
@@ -25,8 +25,8 @@ extension DictionaryLiteral where Key: CustomStringConvertible, Value: CustomStr
2525
}
2626

2727
// MARK: Equatable
28-
extension DictionaryLiteral where Key: Equatable, Value: Equatable {
29-
public static func ==(lhs: DictionaryLiteral<Key,Value>, rhs: DictionaryLiteral<Key,Value>) -> Bool {
28+
extension KeyValuePairs where Key: Equatable, Value: Equatable {
29+
public static func ==(lhs: KeyValuePairs<Key,Value>, rhs: KeyValuePairs<Key,Value>) -> Bool {
3030
if lhs.count != rhs.count {
3131
return false
3232
}

Sources/TSCBasic/FileSystem.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ public class InMemoryFileSystem: FileSystem {
665665
// Ignore root and get the parent node's content if its a directory.
666666
guard !path.isRoot,
667667
let parent = try? getNode(path.parentDirectory),
668-
case .directory(let contents)? = parent?.contents else {
668+
case .directory(let contents) = parent.contents else {
669669
return
670670
}
671671
// Set it to nil to release the contents.

Sources/TSCBasic/GraphAlgorithms.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public func findCycle<T: Hashable>(
121121
func visit(_ node: T, _ successors: (T) throws -> [T]) rethrows -> (path: [T], cycle: [T])? {
122122
// If this node is already in the current path then we have found a cycle.
123123
if !path.append(node) {
124-
let index = path.index(of: node)!
124+
let index = path.firstIndex(of: node)!
125125
return (Array(path[path.startIndex..<index]), Array(path[index..<path.endIndex]))
126126
}
127127

Sources/TSCBasic/JSON.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public enum JSON {
4545
case dictionary([String: JSON])
4646

4747
/// An ordered dictionary.
48-
case orderedDictionary(DictionaryLiteral<String, JSON>)
48+
case orderedDictionary(KeyValuePairs<String, JSON>)
4949
}
5050

5151
/// A JSON representation of an element.
@@ -262,7 +262,7 @@ extension JSON {
262262

263263
/// Load a JSON item from a byte string.
264264
public init(bytes: ByteString) throws {
265-
try self.init(data: Data(bytes: bytes.contents))
265+
try self.init(data: Data(bytes.contents))
266266
}
267267

268268
/// Convenience initalizer for UTF8 encoded strings.

Sources/TSCBasic/JSONMapper.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ extension JSON {
4141

4242
/// Returns an optional JSON mappable object from a given key.
4343
public func get<T: JSONMappable>(_ key: String) -> T? {
44-
return try? get(key)
44+
if let object: JSON = try? get(key) {
45+
return try? T.init(json: object)
46+
}
47+
return nil
4548
}
4649

4750
/// Returns a JSON mappable array from a given key.

Sources/TSCBasic/OrderedDictionary.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public struct OrderedDictionary<Key: Hashable, Value> {
7575
return nil
7676
}
7777
dict[key] = nil
78-
array.remove(at: array.index(of: key)!)
78+
array.remove(at: array.firstIndex(of: key)!)
7979
return value
8080
}
8181

Sources/TSCBasic/OrderedSet.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public struct OrderedSet<E: Hashable>: Equatable, Collection {
9898
let _removedElement = set.remove(element)
9999
guard let removedElement = _removedElement else { return nil }
100100

101-
let idx = array.index(of: element)!
101+
let idx = array.firstIndex(of: element)!
102102
array.remove(at: idx)
103103

104104
return removedElement

Sources/TSCBasic/StringConversions.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ extension String {
4545
public func spm_shellEscaped() -> String {
4646

4747
// If all the characters in the string are in whitelist then no need to escape.
48-
guard let pos = utf8.index(where: { !inShellWhitelist($0) }) else {
48+
guard let pos = utf8.firstIndex(where: { !inShellWhitelist($0) }) else {
4949
return self
5050
}
5151

5252
// If there are no single quotes then we can just wrap the string around single quotes.
53-
guard let singleQuotePos = utf8[pos...].index(of: UInt8(ascii: "'")) else {
53+
guard let singleQuotePos = utf8[pos...].firstIndex(of: UInt8(ascii: "'")) else {
5454
return "'" + self + "'"
5555
}
5656

Sources/TSCUtility/PkgConfig.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ struct PkgConfigParser {
200200

201201
mutating func parse() throws {
202202
func removeComment(line: String) -> String {
203-
if let commentIndex = line.index(of: "#") {
203+
if let commentIndex = line.firstIndex(of: "#") {
204204
return String(line[line.startIndex..<commentIndex])
205205
}
206206
return line
@@ -321,9 +321,9 @@ struct PkgConfigParser {
321321
// We make sure it of form ${name} otherwise it is not a variable.
322322
func findVariable(_ fragment: String)
323323
-> (name: String, startIndex: String.Index, endIndex: String.Index)? {
324-
guard let dollar = fragment.index(of: "$"),
324+
guard let dollar = fragment.firstIndex(of: "$"),
325325
dollar != fragment.endIndex && fragment[fragment.index(after: dollar)] == "{",
326-
let variableEndIndex = fragment.index(of: "}")
326+
let variableEndIndex = fragment.firstIndex(of: "}")
327327
else { return nil }
328328
return (String(fragment[fragment.index(dollar, offsetBy: 2)..<variableEndIndex]), dollar, variableEndIndex)
329329
}

Sources/TSCUtility/Version.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ public extension Version {
110110
/// - Parameters:
111111
/// - string: The string to parse.
112112
init?(string: String) {
113-
let prereleaseStartIndex = string.index(of: "-")
114-
let metadataStartIndex = string.index(of: "+")
113+
let prereleaseStartIndex = string.firstIndex(of: "-")
114+
let metadataStartIndex = string.firstIndex(of: "+")
115115

116116
let requiredEndIndex = prereleaseStartIndex ?? metadataStartIndex ?? string.endIndex
117117
let requiredCharacters = string.prefix(upTo: requiredEndIndex)

Tests/TSCBasicTests/DictionaryLiteralExtensionsTests.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ import TSCBasic
1414
class DictionaryLiteralExtensionsTests: XCTestCase {
1515

1616
func testDescription() {
17-
XCTAssertEqual(DictionaryLiteral(dictionaryLiteral: ("foo", 1)).description, "[foo: 1]")
18-
XCTAssertEqual(DictionaryLiteral(dictionaryLiteral: ("foo", 1), ("bar", 2)).description, "[foo: 1, bar: 2]")
17+
XCTAssertEqual(KeyValuePairs(dictionaryLiteral: ("foo", 1)).description, "[foo: 1]")
18+
XCTAssertEqual(KeyValuePairs(dictionaryLiteral: ("foo", 1), ("bar", 2)).description, "[foo: 1, bar: 2]")
1919
}
2020

2121
func testEquality() {
22-
XCTAssertTrue(DictionaryLiteral(dictionaryLiteral: ("foo", 1)) == DictionaryLiteral(dictionaryLiteral: ("foo", 1)))
23-
XCTAssertTrue(DictionaryLiteral(dictionaryLiteral: ("foo", 1), ("bar", 2)) == DictionaryLiteral(dictionaryLiteral: ("foo", 1), ("bar", 2)))
22+
XCTAssertTrue(KeyValuePairs(dictionaryLiteral: ("foo", 1)) == KeyValuePairs(dictionaryLiteral: ("foo", 1)))
23+
XCTAssertTrue(KeyValuePairs(dictionaryLiteral: ("foo", 1), ("bar", 2)) == KeyValuePairs(dictionaryLiteral: ("foo", 1), ("bar", 2)))
2424

25-
XCTAssertFalse(DictionaryLiteral(dictionaryLiteral: ("no-foo", 1), ("bar", 2)) == DictionaryLiteral(dictionaryLiteral: ("foo", 1), ("bar", 2)))
26-
XCTAssertFalse(DictionaryLiteral(dictionaryLiteral: ("foo", 0), ("bar", 2)) == DictionaryLiteral(dictionaryLiteral: ("foo", 1), ("bar", 2)))
27-
XCTAssertFalse(DictionaryLiteral(dictionaryLiteral: ("foo", 1), ("bar", 2), ("hoge", 3)) == DictionaryLiteral(dictionaryLiteral: ("foo", 1), ("bar", 2)))
28-
XCTAssertFalse(DictionaryLiteral(dictionaryLiteral: ("foo", 1), ("bar", 2)) == DictionaryLiteral(dictionaryLiteral: ("bar", 2), ("foo", 1)))
25+
XCTAssertFalse(KeyValuePairs(dictionaryLiteral: ("no-foo", 1), ("bar", 2)) == KeyValuePairs(dictionaryLiteral: ("foo", 1), ("bar", 2)))
26+
XCTAssertFalse(KeyValuePairs(dictionaryLiteral: ("foo", 0), ("bar", 2)) == KeyValuePairs(dictionaryLiteral: ("foo", 1), ("bar", 2)))
27+
XCTAssertFalse(KeyValuePairs(dictionaryLiteral: ("foo", 1), ("bar", 2), ("hoge", 3)) == KeyValuePairs(dictionaryLiteral: ("foo", 1), ("bar", 2)))
28+
XCTAssertFalse(KeyValuePairs(dictionaryLiteral: ("foo", 1), ("bar", 2)) == KeyValuePairs(dictionaryLiteral: ("bar", 2), ("foo", 1)))
2929
}
3030
}

Tests/TSCBasicTests/PathShimTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class WalkTests : XCTestCase {
7070
AbsolutePath("/sbin")
7171
]
7272
for x in try! walk(AbsolutePath("/"), recursively: false) {
73-
if let i = expected.index(of: x) {
73+
if let i = expected.firstIndex(of: x) {
7474
expected.remove(at: i)
7575
}
7676
XCTAssertEqual(2, x.components.count)
@@ -81,11 +81,11 @@ class WalkTests : XCTestCase {
8181
func testRecursive() {
8282
let root = AbsolutePath(#file).parentDirectory.parentDirectory.parentDirectory.appending(component: "Sources")
8383
var expected = [
84-
root.appending(component: "Build"),
85-
root.appending(component: "Commands")
84+
root.appending(component: "TSCBasic"),
85+
root.appending(component: "TSCUtility")
8686
]
8787
for x in try! walk(root) {
88-
if let i = expected.index(of: x) {
88+
if let i = expected.firstIndex(of: x) {
8989
expected.remove(at: i)
9090
}
9191
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See http://swift.org/LICENSE.txt for license information
8+
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
*/
10+
11+
import Foundation
12+
import XCTest
13+
14+
import TSCBasic
15+
16+
class PathShimTests : XCTestCase {
17+
18+
func testResolvingSymlinks() {
19+
// Make sure the root path resolves to itself.
20+
XCTAssertEqual(resolveSymlinks(AbsolutePath.root), AbsolutePath.root)
21+
22+
// For the rest of the tests we'll need a temporary directory.
23+
try! withTemporaryDirectory(removeTreeOnDeinit: true) { path in
24+
// FIXME: it would be better to not need to resolve symbolic links, but we end up relying on /tmp -> /private/tmp.
25+
let tmpDirPath = resolveSymlinks(path)
26+
27+
// Create a symbolic link and directory.
28+
let slnkPath = tmpDirPath.appending(component: "slnk")
29+
let fldrPath = tmpDirPath.appending(component: "fldr")
30+
31+
// Create a symbolic link pointing at the (so far non-existent) directory.
32+
try! createSymlink(slnkPath, pointingAt: fldrPath, relative: true)
33+
34+
// Resolving the symlink should not yet change anything.
35+
XCTAssertEqual(resolveSymlinks(slnkPath), slnkPath)
36+
37+
// Create a directory to be the referent of the symbolic link.
38+
try! makeDirectories(fldrPath)
39+
40+
// Resolving the symlink should now point at the directory.
41+
XCTAssertEqual(resolveSymlinks(slnkPath), fldrPath)
42+
43+
// Resolving the directory should still not change anything.
44+
XCTAssertEqual(resolveSymlinks(fldrPath), fldrPath)
45+
}
46+
}
47+
48+
func testRescursiveDirectoryCreation() {
49+
// For the tests we'll need a temporary directory.
50+
try! withTemporaryDirectory(removeTreeOnDeinit: true) { path in
51+
// Create a directory under several ancestor directories.
52+
let dirPath = path.appending(components: "abc", "def", "ghi", "mno", "pqr")
53+
try! makeDirectories(dirPath)
54+
55+
// Check that we were able to actually create the directory.
56+
XCTAssertTrue(localFileSystem.isDirectory(dirPath))
57+
58+
// Check that there's no error if we try to create the directory again.
59+
try! makeDirectories(dirPath)
60+
}
61+
}
62+
}
63+
64+
class WalkTests : XCTestCase {
65+
66+
func testNonRecursive() {
67+
var expected = [
68+
AbsolutePath("/usr"),
69+
AbsolutePath("/bin"),
70+
AbsolutePath("/sbin")
71+
]
72+
for x in try! walk(AbsolutePath("/"), recursively: false) {
73+
if let i = expected.firstIndex(of: x) {
74+
expected.remove(at: i)
75+
}
76+
XCTAssertEqual(2, x.components.count)
77+
}
78+
XCTAssertEqual(expected.count, 0)
79+
}
80+
81+
func testRecursive() {
82+
let root = AbsolutePath(#file).parentDirectory.parentDirectory.parentDirectory.appending(component: "Sources")
83+
var expected = [
84+
root.appending(component: "Build"),
85+
root.appending(component: "Commands")
86+
]
87+
for x in try! walk(root) {
88+
if let i = expected.firstIndex(of: x) {
89+
expected.remove(at: i)
90+
}
91+
}
92+
XCTAssertEqual(expected, [])
93+
}
94+
95+
func testSymlinksNotWalked() {
96+
try! withTemporaryDirectory(removeTreeOnDeinit: true) { path in
97+
// FIXME: it would be better to not need to resolve symbolic links, but we end up relying on /tmp -> /private/tmp.
98+
let tmpDirPath = resolveSymlinks(path)
99+
100+
try! makeDirectories(tmpDirPath.appending(component: "foo"))
101+
try! makeDirectories(tmpDirPath.appending(components: "bar", "baz", "goo"))
102+
try! createSymlink(tmpDirPath.appending(components: "foo", "symlink"), pointingAt: tmpDirPath.appending(component: "bar"), relative: true)
103+
104+
XCTAssertTrue(localFileSystem.isSymlink(tmpDirPath.appending(components: "foo", "symlink")))
105+
XCTAssertEqual(resolveSymlinks(tmpDirPath.appending(components: "foo", "symlink")), tmpDirPath.appending(component: "bar"))
106+
XCTAssertTrue(localFileSystem.isDirectory(resolveSymlinks(tmpDirPath.appending(components: "foo", "symlink", "baz"))))
107+
108+
let results = try! walk(tmpDirPath.appending(component: "foo")).map{ $0 }
109+
110+
XCTAssertEqual(results, [tmpDirPath.appending(components: "foo", "symlink")])
111+
}
112+
}
113+
114+
func testWalkingADirectorySymlinkResolvesOnce() {
115+
try! withTemporaryDirectory(removeTreeOnDeinit: true) { tmpDirPath in
116+
try! makeDirectories(tmpDirPath.appending(components: "foo", "bar"))
117+
try! makeDirectories(tmpDirPath.appending(components: "abc", "bar"))
118+
try! createSymlink(tmpDirPath.appending(component: "symlink"), pointingAt: tmpDirPath.appending(component: "foo"), relative: true)
119+
try! createSymlink(tmpDirPath.appending(components: "foo", "baz"), pointingAt: tmpDirPath.appending(component: "abc"), relative: true)
120+
121+
XCTAssertTrue(localFileSystem.isSymlink(tmpDirPath.appending(component: "symlink")))
122+
123+
let results = try! walk(tmpDirPath.appending(component: "symlink")).map{ $0 }.sorted()
124+
125+
// we recurse a symlink to a directory, so this should work,
126+
// but `abc` should not show because `baz` is a symlink too
127+
// and that should *not* be followed
128+
129+
XCTAssertEqual(results, [tmpDirPath.appending(components: "symlink", "bar"), tmpDirPath.appending(components: "symlink", "baz")])
130+
}
131+
}
132+
}

0 commit comments

Comments
 (0)