Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support ssh protocol (for private repos) #40

Merged
merged 2 commits into from
Mar 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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