Skip to content

Commit

Permalink
Merge pull request #140 from haikusw/fix132v2
Browse files Browse the repository at this point in the history
An alternate version of PR #139 that fixes #132
  • Loading branch information
mxcl committed May 25, 2021
2 parents 41b120e + a037273 commit 4146224
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 3 deletions.
10 changes: 9 additions & 1 deletion Sources/Script/DependencyName.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,17 @@ extension ImportSpecification.DependencyName: Codable {
self = .github(user: mangleGitHubUsername(username), repo: importName)
return
}
guard let cc = URLComponents(string: string) else {

let string = string.trimmingCharacters(in: .whitespaces)
var ccmaybe = URLComponents(string: string)
if ccmaybe == nil,
let encodedString = string.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) {
ccmaybe = URLComponents(string: encodedString)
}
guard let cc = ccmaybe else {
throw E.invalidDependencySpecification(string)
}

if cc.scheme == nil {
if let p = Path(cc.path), p.exists {
self = .local(p)
Expand Down
18 changes: 17 additions & 1 deletion Sources/Script/parse().swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,25 @@ enum E: Error {

/// - Parameter line: Contract: Single line string trimmed of whitespace.
func parse(_ line: String, from input: Script.Input) throws -> ImportSpecification? {
let pattern = "import\\s+(.*?)\\s*\\/\\/\\s*([~@]?[\\w\\/(@|:)\\.\\-]+)\\s*(?:(==|~>)\\s*([^\\s]+))?"
let importModNamePattern = "import\\s+(.*?)"
let commentPattern = "\\/\\/"
let localFilePattern = "(?:(?:~|[\\./]+)+?[\\w \\/\\.\\-]*)"
let repoRefPattern = "(?:(?:[(@|\\w)]?[\\w\\/(@|:)\\.\\-]+))"
let repoConstraintPattern = "(?:(==|~>)\\s*([^\\s]+))?"
let pattern = "\(importModNamePattern)\\s*\(commentPattern)\\s*(\(localFilePattern)|\(repoRefPattern))\\s*\(repoConstraintPattern)"
// or if you prefer, one big pattern:
// let pattern = "import\\s+(.*?)\\s*\\/\\/\\s*((?:(?:~|[\\./]+)+?[\\w \\/\\.\\-]*)|(?:(?:[(@|\\w)]?[\\w\\/(@|:)\\.\\-]+)))\\s*(?:(==|~>)\\s*([^\\s]+))?"
let rx = try! NSRegularExpression(pattern: pattern)

// match 0: whole string
// match 1: module name
// match 2: one of:
// user ref (e.g., @mxcl)
// local file ref (e.g., ./my/project or ../my/project or ~/foo, or /foo/bar)
// url ref (e.g., https://foo/bar.git or git@github.com:user/repo.git or ssh://git@github.com:user/repo.git)
// match 3: range spec (e.g., ~> or ==) -- IFF NOT local file ref (and match 8 valid))
// match 4: range value (e.g., 1.0.0-alpha.1 or b27a89 or 1) -- IFF NOT local file ref (and match 7 valid)

// doesn’t look like an import line, we have to silently ignore it, even though it could
// be a typo or whatever which is not useful to our user, but at the end of the day
// we’re a hack waiting for a real API in Swift itself that can then error properly
Expand Down
65 changes: 64 additions & 1 deletion Tests/All/ImportSpecificationUnitTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,60 @@ class ImportSpecificationUnitTests: XCTestCase {
XCTAssertEqual(b?.packageLine, ".package(path: \"\(cwdParent.string)\")")
}

func testCanProvideLocalPathWithHypen() throws {
let tmpPath = Path.root.tmp.fake/"with-hyphen-two"/"lastone"
try tmpPath.mkdir(.p)
let b = try parse("import Foo // /tmp/fake/with-hyphen-two/lastone", from: .path(tmpPath.join("script.swift")))
XCTAssertEqual(b?.dependencyName, .local(tmpPath))
XCTAssertEqual(b?.importName, "Foo")
XCTAssertEqual(b?.packageLine, ".package(path: \"\(tmpPath.string)\")")
}

func testCanProvideLocalPathWithHyphenAndDotsAndSpacesOhMy() throws {
let tmpPath = Path.root.tmp.fake/"with-hyphen.two.one-zero"/"last one"
try tmpPath.mkdir(.p)
let b = try parse("import Foo // /tmp/fake/with-hyphen.two.one-zero/last one", from: .path(tmpPath.join("script.swift")))
XCTAssertEqual(b?.dependencyName, .local(tmpPath))
XCTAssertEqual(b?.importName, "Foo")
XCTAssertEqual(b?.packageLine, ".package(path: \"\(tmpPath.string)\")")
}

func testCanProvideLocalPathWithSpaces() throws {
let tmpPath = Path.root.tmp.fake/"with space"/"last"
try tmpPath.mkdir(.p)
let b = try parse("import Bar // /tmp/fake/with space/last", from: .path(tmpPath.join("script.swift")))
XCTAssertEqual(b?.dependencyName, .local(tmpPath))
XCTAssertEqual(b?.importName, "Bar")
XCTAssertEqual(b?.packageLine, ".package(path: \"\(tmpPath.string)\")")
}

func testCanProvideLocalPathWithSpacesInLast() throws {
let tmpPath = Path.root.tmp.fake/"with space"/"last one"
try tmpPath.mkdir(.p)
let b = try parse("import Foo // /tmp/fake/with space/last one", from: .path(tmpPath.join("script.swift")))
XCTAssertEqual(b?.dependencyName, .local(tmpPath))
XCTAssertEqual(b?.importName, "Foo")
XCTAssertEqual(b?.packageLine, ".package(path: \"\(tmpPath.string)\")")
}

func testCanProvideLocalPathWithSpacesAndRelativeParentsUp() throws {
let tmpPath = Path.root.tmp.fake.fakechild/".."/"with space"/"last"
try tmpPath.mkdir(.p)
let b = try parse("import Bar // /tmp/fake/with space/last", from: .path(tmpPath.join("script.swift")))
XCTAssertEqual(b?.dependencyName, .local(tmpPath))
XCTAssertEqual(b?.importName, "Bar")
XCTAssertEqual(b?.packageLine, ".package(path: \"\(tmpPath.string)\")")
}

func testCanProvideLocalPathWithSpacesAndRelativeParentsUpTwo() throws {
let tmpPath = Path.root.tmp.fake.fakechild1.fakechild2/"../.."/"with space"/"last"
try tmpPath.mkdir(.p)
let b = try parse("import Bar // /tmp/fake/with space/last", from: .path(tmpPath.join("script.swift")))
XCTAssertEqual(b?.dependencyName, .local(tmpPath))
XCTAssertEqual(b?.importName, "Bar")
XCTAssertEqual(b?.packageLine, ".package(path: \"\(tmpPath.string)\")")
}

func testCanProvideFullURL() throws {
let b = try parse("import Foo // https://example.com/mxcl/Bar.git ~> 1.0", from: .path(Path.cwd.join("script.swift")))
XCTAssertEqual(b?.dependencyName, .url(URL(string: "https://example.com/mxcl/Bar.git")!))
Expand All @@ -124,7 +178,16 @@ class ImportSpecificationUnitTests: XCTestCase {
XCTAssertEqual(b?.importName, "Bar")
XCTAssertEqual(b?.dependencyName.urlString, url)
}


func testCanProvideCommonSSHURLStyle() throws {
let uri = "git@github.com:MariusCiocanel/Path.swift.git"
let b = try parse("import Path // \(uri) ~> 1.0", from: .path(Path.cwd.join("script.swift")))
XCTAssertEqual(b?.dependencyName, .scp(uri))
XCTAssertEqual(b?.constraint, .upToNextMajor(from: .one))
XCTAssertEqual(b?.importName, "Path")
XCTAssertEqual(b?.dependencyName.urlString, "git@github.com:MariusCiocanel/Path.swift.git")
}

func testCanProvideCommonSSHURLStyleWithHyphen() throws {
let uri = "git@github.com:MariusCiocanel/swift-sh.git"
let b = try parse("import Bar // \(uri) ~> 1.0", from: .path(Path.cwd.join("script.swift")))
Expand Down

0 comments on commit 4146224

Please sign in to comment.