Skip to content

Commit

Permalink
Merge pull request #40 from finestructure/support-private-repos
Browse files Browse the repository at this point in the history
Support ssh protocol (for private repos)
  • Loading branch information
finestructure authored Mar 27, 2020
2 parents b4e1272 + a1c7ec0 commit 66df4b0
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 129 deletions.
4 changes: 2 additions & 2 deletions Sources/ArenaCore/Parser+ext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ extension Parser where A == RefSpec {


extension Parser where A == Scheme {
static var aScheme: Parser<Scheme> {
static var scheme: Parser<Scheme> {
oneOf(Scheme.allCases.map { string($0.rawValue).map { Scheme(rawValue: $0)! } } )
}
}
Expand All @@ -80,7 +80,7 @@ extension Parser where A == Scheme {
extension Parser where A == Foundation.URL {
static var url: Parser<Foundation.URL> {
zip(
Parser<Scheme>.aScheme,
Parser<Scheme>.scheme,
prefix(upTo: "@").map(String.init)
).flatMap { (scheme, rest) in
if let url = scheme.url(path: rest) {
Expand Down
8 changes: 8 additions & 0 deletions Sources/ArenaCore/Scheme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Path
enum Scheme: String, CaseIterable {
case https = "https://"
case http = "http://"
case git = "git@"
case file = "file://"
case nonstandardizedFile = "file:"
case empty = ""
Expand All @@ -20,6 +21,13 @@ enum Scheme: String, CaseIterable {
switch self {
case .https, .http, .file:
return URL(string: rawValue + path)
case .git:
return URL(string:
"ssh://"
+ rawValue
+ path
.split(separator: ":", maxSplits: 1)
.joined(separator: "/"))
case .nonstandardizedFile:
return URL(string: Scheme.file.rawValue + path)
case .empty:
Expand Down
126 changes: 0 additions & 126 deletions Tests/ArenaTests/ArenaTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,132 +139,6 @@ final class ArenaTests: XCTestCase {
XCTAssertEqual(res.libNames, ["foo", "bar"])
}

func test_parse_version() throws {
XCTAssertEqual(Parser.version.run("1.2.3"), Match(result: Version(1, 2, 3), rest: ""))
XCTAssertEqual(Parser.version.run("1.2.3="), Match(result: Version(1, 2, 3), rest: "="))
}

func test_parse_requirement() throws {
XCTAssertEqual(Parser.exact.run("@1.2.3"), Match(result: .exact("1.2.3"), rest: ""))

XCTAssertEqual(Parser.from.run("@from:1.2.3"), Match(result: .from("1.2.3"), rest: ""))

XCTAssertEqual(Parser.range.run("@1.2.3..<3.2.1"), Match(result: .range("1.2.3"..<"3.2.1"), rest: ""))
XCTAssertEqual(Parser.range.run("@1.2.3...3.2.1"), Match(result: .range("1.2.3"..<"3.2.2"), rest: ""))

do { // combined
XCTAssertEqual(Parser.refSpec.run(""), Match(result: .noVersion, rest: ""))
XCTAssertEqual(Parser.refSpec.run("@1.2.3"), Match(result: .exact("1.2.3"), rest: ""))
XCTAssertEqual(Parser.refSpec.run("@from:1.2.3"), Match(result: .from("1.2.3"), rest: ""))
XCTAssertEqual(Parser.refSpec.run("@1.2.3..<3.0.0"), Match(result: .range("1.2.3"..<"3.0.0"), rest: ""))
}
}

func test_parse_url() throws {
XCTAssertEqual(Parser.url.run("https://github.com/foo/bar"),
Match(result: URL(string: "https://github.com/foo/bar"), rest: ""))
XCTAssertEqual(Parser.url.run("https://github.com/foo/bar@rest"),
Match(result: URL(string: "https://github.com/foo/bar"), rest: "@rest"))
XCTAssertEqual(Parser.url.run("http://github.com/foo/bar@rest"),
Match(result: URL(string: "http://github.com/foo/bar"), rest: "@rest"))
XCTAssertEqual(Parser.url.run("/foo/bar@rest"),
Match(result: URL(string: "file:///foo/bar"), rest: "@rest"))
XCTAssertEqual(Parser.url.run("file:///foo/bar@rest"),
Match(result: URL(string: "file:///foo/bar"), rest: "@rest"))
XCTAssertEqual(Parser.url.run("file:/foo/bar@rest"),
Match(result: URL(string: "file:///foo/bar"), rest: "@rest"))
}

func test_parse_branchName() {
XCTAssertEqual(branchName.run("develop"), Match(result: "develop", rest: ""))
XCTAssertEqual(branchName.run("foo-bar"), Match(result: "foo-bar", rest: ""))
// disallowed
XCTAssertEqual(branchName.run("/foo"), Match(result: nil, rest: "/foo"))
XCTAssertEqual(branchName.run("foo."), Match(result: nil, rest: "foo."))
XCTAssertEqual(branchName.run("foo/"), Match(result: nil, rest: "foo/"))
}

func test_parse_branch() {
XCTAssertEqual(Parser.branch.run("@branch:develop"), Match(result: .branch("develop"), rest: ""))
}

func test_parse_revision() {
XCTAssertEqual(Parser.revision.run("@revision:foo"), Match(result: .revision("foo"), rest: ""))
XCTAssertEqual(Parser.revision.run("@revision:7ba3c50793d971b50bc748ad4c9a061ba8e6a0c5"), Match(result: .revision("7ba3c50793d971b50bc748ad4c9a061ba8e6a0c5"), rest: ""))
XCTAssertEqual(Parser.revision.run("@revision:1.2.3-rc4"), Match(result: .revision("1.2.3-rc4"), rest: ""))
}

func test_parse_dependency() throws {
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .noVersion),
rest: ""))
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/[email protected]"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .exact("1.2.3")),
rest: ""))
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@from:1.2.3"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .from("1.2.3")),
rest: ""))
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/[email protected]..<4.0.0"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .range("1.2.3"..<"4.0.0")),
rest: ""))
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/[email protected]"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .range("1.2.3"..<"4.0.1")),
rest: ""))
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@branch:develop"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .branch("develop")),
rest: ""))
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@branch:feature/a"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .branch("feature/a")),
rest: ""))
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@revision:somerevision"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .revision("somerevision")),
rest: ""))

// local path dependency
XCTAssertEqual(
Parser.dependency.run("/foo/bar"),
Match(result: Dependency(url: URL(string: "file:///foo/bar")!, requirement: .path), rest: ""))
XCTAssertEqual(
Parser.dependency.run("./foo/bar"),
Match(result: Dependency(url: URL(string: "file://\(Path.cwd)/foo/bar")!, requirement: .path), rest: ""))
XCTAssertEqual(
Parser.dependency.run("~/foo/bar"),
Match(result: Dependency(url: URL(string: "file://\(Path.home)/foo/bar")!, requirement: .path), rest: ""))
XCTAssertEqual(
Parser.dependency.run("foo/bar"),
Match(result: Dependency(url: URL(string: "file://\(Path.cwd)/foo/bar")!, requirement: .path), rest: ""))
XCTAssertEqual(
Parser.dependency.run("../foo/bar"),
Match(result: Dependency(url: URL(string: "file://\(Path.cwd/"../foo/bar")")!, requirement: .path), rest: ""))
}

func test_parse_dependency_errors() throws {
// unparsable trailing characters
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@from:1.2.3trailingjunk"),
Match(result: nil,
rest: "https://github.com/foo/bar@from:1.2.3trailingjunk"))
// invalid version
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@from:1.2.3..<2.0.0"),
Match(result: nil,
rest: "https://github.com/foo/bar@from:1.2.3..<2.0.0"))
// invalid branch
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@branch:foo bar"),
Match(result: nil,
rest: "https://github.com/foo/bar@branch:foo bar"))
// invalid revision
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@revision:1.2.3 rc4"),
Match(result: nil,
rest: "https://github.com/foo/bar@revision:1.2.3 rc4"))
}

func test_dependency_package_clause() throws {
do {
let dep = Dependency(url: URL(string: "https://github.com/foo/bar")!, requirement: .branch("develop"))
Expand Down
25 changes: 25 additions & 0 deletions Tests/ArenaTests/IntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,30 @@ class IntegrationTests: XCTestCase {
}
#endif

#if swift(>=5.2)
func test_git_protocol() throws {
try XCTSkipUnless(ProcessInfo().hostName == "luna.local", "fails on CI, only run locally")

let arena = try Arena.parse([
"[email protected]:finestructure/[email protected]",
"--name=ArenaIntegrationTest",
"--force",
"--skip-open"])

let exp = self.expectation(description: "exp")

let progress: ProgressUpdate = { stage, _ in
print("progress: \(stage)")
if stage == .completed {
exp.fulfill()
}
}

try arena.run(progress: progress)

wait(for: [exp], timeout: 10)
}
#endif

}

155 changes: 155 additions & 0 deletions Tests/ArenaTests/ParserTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
//
// ParserTests.swift
// ArenaTests
//
// Created by Sven A. Schmidt on 27/03/2020.
//

@testable import ArenaCore
import Path
import Parser
import Workspace
import XCTest


class ParserTests: XCTestCase {

func test_parse_version() throws {
XCTAssertEqual(Parser.version.run("1.2.3"), Match(result: Version(1, 2, 3), rest: ""))
XCTAssertEqual(Parser.version.run("1.2.3="), Match(result: Version(1, 2, 3), rest: "="))
}

func test_parse_requirement() throws {
XCTAssertEqual(Parser.exact.run("@1.2.3"), Match(result: .exact("1.2.3"), rest: ""))

XCTAssertEqual(Parser.from.run("@from:1.2.3"), Match(result: .from("1.2.3"), rest: ""))

XCTAssertEqual(Parser.range.run("@1.2.3..<3.2.1"), Match(result: .range("1.2.3"..<"3.2.1"), rest: ""))
XCTAssertEqual(Parser.range.run("@1.2.3...3.2.1"), Match(result: .range("1.2.3"..<"3.2.2"), rest: ""))

do { // combined
XCTAssertEqual(Parser.refSpec.run(""), Match(result: .noVersion, rest: ""))
XCTAssertEqual(Parser.refSpec.run("@1.2.3"), Match(result: .exact("1.2.3"), rest: ""))
XCTAssertEqual(Parser.refSpec.run("@from:1.2.3"), Match(result: .from("1.2.3"), rest: ""))
XCTAssertEqual(Parser.refSpec.run("@1.2.3..<3.0.0"), Match(result: .range("1.2.3"..<"3.0.0"), rest: ""))
}
}

func test_parse_url() throws {
XCTAssertEqual(Parser.url.run("https://github.com/foo/bar"),
Match(result: URL(string: "https://github.com/foo/bar"), rest: ""))
XCTAssertEqual(Parser.url.run("https://github.com/foo/bar@rest"),
Match(result: URL(string: "https://github.com/foo/bar"), rest: "@rest"))
XCTAssertEqual(Parser.url.run("http://github.com/foo/bar@rest"),
Match(result: URL(string: "http://github.com/foo/bar"), rest: "@rest"))
XCTAssertEqual(Parser.url.run("/foo/bar@rest"),
Match(result: URL(string: "file:///foo/bar"), rest: "@rest"))
XCTAssertEqual(Parser.url.run("file:///foo/bar@rest"),
Match(result: URL(string: "file:///foo/bar"), rest: "@rest"))
XCTAssertEqual(Parser.url.run("file:/foo/bar@rest"),
Match(result: URL(string: "file:///foo/bar"), rest: "@rest"))
}

func test_parse_branchName() {
XCTAssertEqual(branchName.run("develop"), Match(result: "develop", rest: ""))
XCTAssertEqual(branchName.run("foo-bar"), Match(result: "foo-bar", rest: ""))
// disallowed
XCTAssertEqual(branchName.run("/foo"), Match(result: nil, rest: "/foo"))
XCTAssertEqual(branchName.run("foo."), Match(result: nil, rest: "foo."))
XCTAssertEqual(branchName.run("foo/"), Match(result: nil, rest: "foo/"))
}

func test_parse_branch() {
XCTAssertEqual(Parser.branch.run("@branch:develop"), Match(result: .branch("develop"), rest: ""))
}

func test_parse_revision() {
XCTAssertEqual(Parser.revision.run("@revision:foo"), Match(result: .revision("foo"), rest: ""))
XCTAssertEqual(Parser.revision.run("@revision:7ba3c50793d971b50bc748ad4c9a061ba8e6a0c5"), Match(result: .revision("7ba3c50793d971b50bc748ad4c9a061ba8e6a0c5"), rest: ""))
XCTAssertEqual(Parser.revision.run("@revision:1.2.3-rc4"), Match(result: .revision("1.2.3-rc4"), rest: ""))
}

func test_parse_dependency() throws {
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .noVersion),
rest: ""))
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/[email protected]"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .exact("1.2.3")),
rest: ""))
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@from:1.2.3"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .from("1.2.3")),
rest: ""))
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/[email protected]..<4.0.0"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .range("1.2.3"..<"4.0.0")),
rest: ""))
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/[email protected]"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .range("1.2.3"..<"4.0.1")),
rest: ""))
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@branch:develop"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .branch("develop")),
rest: ""))
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@branch:feature/a"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .branch("feature/a")),
rest: ""))
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@revision:somerevision"),
Match(result: Dependency(url: URL(string: "https://github.com/foo/bar")!,
requirement: .revision("somerevision")),
rest: ""))

// local path dependency
XCTAssertEqual(
Parser.dependency.run("/foo/bar"),
Match(result: Dependency(url: URL(string: "file:///foo/bar")!, requirement: .path), rest: ""))
XCTAssertEqual(
Parser.dependency.run("./foo/bar"),
Match(result: Dependency(url: URL(string: "file://\(Path.cwd)/foo/bar")!, requirement: .path), rest: ""))
XCTAssertEqual(
Parser.dependency.run("~/foo/bar"),
Match(result: Dependency(url: URL(string: "file://\(Path.home)/foo/bar")!, requirement: .path), rest: ""))
XCTAssertEqual(
Parser.dependency.run("foo/bar"),
Match(result: Dependency(url: URL(string: "file://\(Path.cwd)/foo/bar")!, requirement: .path), rest: ""))
XCTAssertEqual(
Parser.dependency.run("../foo/bar"),
Match(result: Dependency(url: URL(string: "file://\(Path.cwd/"../foo/bar")")!, requirement: .path), rest: ""))
}

func test_parse_dependency_git_protocol() throws {
// git protocol
XCTAssertEqual(Parser.dependency.run("[email protected]:foo/bar.git"),
Match(result: Dependency(url: URL(string: "ssh://[email protected]/foo/bar.git")!,
requirement: .noVersion),
rest: ""))
XCTAssertEqual(Parser.dependency.run("[email protected]:foo/bar"),
Match(result: Dependency(url: URL(string: "ssh://[email protected]/foo/bar")!,
requirement: .noVersion),
rest: ""))
}

func test_parse_dependency_errors() throws {
// unparsable trailing characters
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@from:1.2.3trailingjunk"),
Match(result: nil,
rest: "https://github.com/foo/bar@from:1.2.3trailingjunk"))
// invalid version
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@from:1.2.3..<2.0.0"),
Match(result: nil,
rest: "https://github.com/foo/bar@from:1.2.3..<2.0.0"))
// invalid branch
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@branch:foo bar"),
Match(result: nil,
rest: "https://github.com/foo/bar@branch:foo bar"))
// invalid revision
XCTAssertEqual(Parser.dependency.run("https://github.com/foo/bar@revision:1.2.3 rc4"),
Match(result: nil,
rest: "https://github.com/foo/bar@revision:1.2.3 rc4"))
}

}
4 changes: 3 additions & 1 deletion misc/run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ swift build
for dep in "finestructure/Gala" \
"finestructure/Parser" \
"alamofire/alamofire" \
"pointfreeco/swift-gen"
"pointfreeco/swift-gen" \
"~/Projects/Parser" \
"[email protected]:finestructure/parser"
do
echo "-------------------------"
echo Test: $dep
Expand Down

0 comments on commit 66df4b0

Please sign in to comment.