Skip to content

Commit 37d4315

Browse files
committed
Merge pull request #201 from kostiakoval/git-v2-error
throw error if git version is less than 2
2 parents 6840096 + 32318ab commit 37d4315

File tree

6 files changed

+122
-8
lines changed

6 files changed

+122
-8
lines changed

Sources/Get/Git.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,12 @@ extension Git {
3636
"--depth", "10",
3737
url, dstdir, environment: environment, message: "Cloning \(url)")
3838
} catch POSIX.Error.ExitStatus {
39-
throw Error.GitCloneFailure(url, dstdir)
39+
// Git 2.0 or higher is required
40+
if Git.majorVersionNumber < 2 {
41+
throw Utility.Error.ObsoleteGitVersion
42+
} else {
43+
throw Error.GitCloneFailure(url, dstdir)
44+
}
4045
}
4146

4247
return Repo(path: dstdir)! //TODO no bangs
@@ -45,7 +50,7 @@ extension Git {
4550

4651
extension Git.Repo {
4752
var versions: [Version] {
48-
let out = (try? popen([Git.tool, "-C", path, "tag", "-l"])) ?? ""
53+
let out = (try? Git.runPopen([Git.tool, "-C", path, "tag", "-l"])) ?? ""
4954
let tags = out.characters.split(separator: Character.newline)
5055
let versions = tags.flatMap(Version.init).sorted()
5156
if !versions.isEmpty {
@@ -66,6 +71,6 @@ extension Git.Repo {
6671
no versions, returns false.
6772
*/
6873
var versionsArePrefixed: Bool {
69-
return (try? popen([Git.tool, "-C", path, "tag", "-l"]))?.hasPrefix("v") ?? false
74+
return (try? Git.runPopen([Git.tool, "-C", path, "tag", "-l"]))?.hasPrefix("v") ?? false
7075
}
7176
}

Sources/Get/RawClone.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ class RawClone: Fetchable {
6363
func setVersion(ver: Version) throws {
6464
let packageVersionsArePrefixed = repo.versionsArePrefixed
6565
let v = (packageVersionsArePrefixed ? "v" : "") + ver.description
66-
try popen([Git.tool, "-C", path, "reset", "--hard", v])
67-
try popen([Git.tool, "-C", path, "branch", "-m", v])
66+
try Git.runPopen([Git.tool, "-C", path, "reset", "--hard", v])
67+
try Git.runPopen([Git.tool, "-C", path, "branch", "-m", v])
6868

6969
print("Resolved version:", ver)
7070

Sources/Utility/Error.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright 2015 - 2016 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+
public enum Error: ErrorProtocol {
12+
case ObsoleteGitVersion
13+
case UnknownGitError
14+
}
15+
16+
extension Error: CustomStringConvertible {
17+
public var description: String {
18+
switch self {
19+
case ObsoleteGitVersion:
20+
return "Git 2.0 or higher is required. Please update git and retry."
21+
case UnknownGitError:
22+
return "Failed to invoke git command. Please try updating git"
23+
}
24+
}
25+
}

Sources/Utility/Git.swift

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import func POSIX.realpath
1212
import func POSIX.getenv
13+
import libc
1314

1415
public class Git {
1516
public class Repo {
@@ -23,7 +24,7 @@ public class Git {
2324

2425
public lazy var origin: String? = { repo in
2526
do {
26-
guard let url = try popen([Git.tool, "-C", repo.path, "config", "--get", "remote.origin.url"]).chuzzle() else {
27+
guard let url = try Git.runPopen([Git.tool, "-C", repo.path, "config", "--get", "remote.origin.url"]).chuzzle() else {
2728
return nil
2829
}
2930
if URL.scheme(url) == nil {
@@ -40,15 +41,54 @@ public class Git {
4041
}(self)
4142

4243
public var branch: String! {
43-
return try? popen([Git.tool, "-C", path, "rev-parse", "--abbrev-ref", "HEAD"]).chomp()
44+
return try? Git.runPopen([Git.tool, "-C", path, "rev-parse", "--abbrev-ref", "HEAD"]).chomp()
4445
}
4546

4647
public func fetch() throws {
47-
try system(Git.tool, "-C", path, "fetch", "--tags", "origin", message: nil)
48+
do {
49+
try system(Git.tool, "-C", path, "fetch", "--tags", "origin", message: nil)
50+
} catch let errror {
51+
Git.handle(errror)
52+
}
4853
}
4954
}
5055

5156
public class var tool: String {
5257
return getenv("SWIFT_GIT") ?? "git"
5358
}
59+
60+
public class var version: String! {
61+
return try? Git.runPopen([Git.tool, "version"])
62+
}
63+
64+
public class var majorVersionNumber: Int? {
65+
let prefix = "git version"
66+
var version = self.version
67+
if version.hasPrefix(prefix) {
68+
let prefixRange = version.startIndex...version.startIndex.advanced(by: prefix.characters.count)
69+
version.removeSubrange(prefixRange)
70+
}
71+
guard let first = version.characters.first else {
72+
return nil
73+
}
74+
return Int(String(first))
75+
}
76+
77+
@noreturn public class func handle(error: ErrorProtocol) {
78+
// Git 2.0 or higher is required
79+
if Git.majorVersionNumber < 2 {
80+
print("error: ", Error.ObsoleteGitVersion)
81+
} else {
82+
print("error: ", Error.UnknownGitError)
83+
}
84+
exit(1)
85+
}
86+
87+
public class func runPopen(arguments: [String]) throws -> String {
88+
do {
89+
return try popen(arguments)
90+
} catch let error {
91+
handle(error)
92+
}
93+
}
5494
}

Tests/LinuxMain.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,5 @@ XCTMain([
4040
testCase(WalkTests.allTests),
4141
testCase(ModuleMapsTestCase.allTests),
4242
testCase(DescribeTests.allTests),
43+
testCase(GitUtilityTests.allTests),
4344
])

Tests/Utility/GitTests.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright 2015 - 2016 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+
@testable import Utility
12+
import XCTest
13+
14+
class GitMoc: Git {
15+
static var mocVersion: String = "git version 2.5.4 (Apple Git-61)"
16+
override class var version: String! {
17+
return mocVersion
18+
}
19+
}
20+
21+
class GitUtilityTests: XCTestCase {
22+
23+
func testGitVersion() {
24+
XCTAssertEqual(GitMoc.majorVersionNumber, 2)
25+
26+
GitMoc.mocVersion = "2.5.4"
27+
XCTAssertEqual(GitMoc.majorVersionNumber, 2)
28+
29+
GitMoc.mocVersion = "git version 1.5.4"
30+
XCTAssertEqual(GitMoc.majorVersionNumber, 1)
31+
32+
GitMoc.mocVersion = "1.25.4"
33+
XCTAssertEqual(GitMoc.majorVersionNumber, 1)
34+
}
35+
}
36+
37+
extension GitUtilityTests {
38+
static var allTests : [(String, GitUtilityTests -> () throws -> Void)] {
39+
return [
40+
("testGitVersion", testGitVersion),
41+
]
42+
}
43+
}

0 commit comments

Comments
 (0)