Repository: Return libgit2 errors for failures

- Update Guanaco for improved matching on failures,
  i.e.: `haveFailed(beAnError(domain: match("abc")))`.
- All functions that return Result objects now return sane errors for
  failure cases.
- Unit tests verify libgit2 error is domain is used for most failures.
This commit is contained in:
Brian Gesiak 2015-02-20 01:52:39 -05:00
parent 7d6409a406
commit f23f98f033
3 changed files with 61 additions and 65 deletions

2
External/Guanaco vendored

@ -1 +1 @@
Subproject commit 33563ba4911f11b7cd6edb357974565c375359ad Subproject commit 7961d9851d72e2c8c8e2c620054041c6217806e7

View File

@ -90,7 +90,7 @@ final public class Repository {
if result != GIT_OK.value { if result != GIT_OK.value {
pointer.dealloc(1) pointer.dealloc(1)
return failure() return failure(libGit2Error(result, libGit2PointOfFailure: "git_object_lookup"))
} }
let value = transform(pointer.memory) let value = transform(pointer.memory)
@ -120,7 +120,15 @@ final public class Repository {
} else if type == Tree.type { } else if type == Tree.type {
return success(Tree(object)) return success(Tree(object))
} }
return failure()
let error = NSError(
domain: "org.libgit2.SwiftGit2",
code: 1,
userInfo: [
NSLocalizedDescriptionKey: "Unrecognized git_otype '\(type)' for oid '\(oid)'."
]
)
return failure(error)
} }
} }
@ -199,7 +207,7 @@ final public class Repository {
if result != GIT_OK.value { if result != GIT_OK.value {
pointer.dealloc(1) pointer.dealloc(1)
return failure() return failure(libGit2Error(result, libGit2PointOfFailure: "git_remote_list"))
} }
let strarray = pointer.memory let strarray = pointer.memory
@ -228,7 +236,7 @@ final public class Repository {
if result != GIT_OK.value { if result != GIT_OK.value {
pointer.dealloc(1) pointer.dealloc(1)
return failure() return failure(libGit2Error(result, libGit2PointOfFailure: "git_remote_lookup"))
} }
let value = Remote(pointer.memory) let value = Remote(pointer.memory)
@ -247,7 +255,7 @@ final public class Repository {
if result != GIT_OK.value { if result != GIT_OK.value {
pointer.dealloc(1) pointer.dealloc(1)
return failure() return failure(libGit2Error(result, libGit2PointOfFailure: "git_reference_list"))
} }
let strarray = pointer.memory let strarray = pointer.memory
@ -280,7 +288,7 @@ final public class Repository {
if result != GIT_OK.value { if result != GIT_OK.value {
pointer.dealloc(1) pointer.dealloc(1)
return failure() return failure(libGit2Error(result, libGit2PointOfFailure: "git_reference_lookup"))
} }
var value: ReferenceType var value: ReferenceType

View File

@ -23,10 +23,10 @@ class RepositorySpec: QuickSpec {
it("should fail if the repo doesn't exist") { it("should fail if the repo doesn't exist") {
let url = NSURL(fileURLWithPath: "blah")! let url = NSURL(fileURLWithPath: "blah")!
let result = Repository.atURL(url) let result = Repository.atURL(url)
expect(result).to(haveFailed( expect(result).to(haveFailed(beAnError(
domain: libGit2ErrorDomain, domain: equal(libGit2ErrorDomain),
localizedDescription: "Failed to resolve path '\(url.path!)': No such file or directory" localizedDescription: match("Failed to resolve path")
)) )))
} }
} }
@ -36,9 +36,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "41078396f5187daed5f673e4a13b185bbad71fba")! let oid = OID(string: "41078396f5187daed5f673e4a13b185bbad71fba")!
let result = repo.blobWithOID(oid) let result = repo.blobWithOID(oid)
let blob = result.value expect(result.map { $0.oid }).to(haveSucceeded(equal(oid)))
expect(blob).notTo(beNil())
expect(blob?.oid).to(equal(oid))
} }
it("should error if the blob doesn't exist") { it("should error if the blob doesn't exist") {
@ -46,7 +44,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")! let oid = OID(string: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")!
let result = repo.blobWithOID(oid) let result = repo.blobWithOID(oid)
expect(result.error).notTo(beNil()) expect(result).to(haveFailed(beAnError(domain: equal(libGit2ErrorDomain))))
} }
it("should error if the oid doesn't point to a blob") { it("should error if the oid doesn't point to a blob") {
@ -55,7 +53,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "f93e3a1a1525fb5b91020da86e44810c87a2d7bc")! let oid = OID(string: "f93e3a1a1525fb5b91020da86e44810c87a2d7bc")!
let result = repo.blobWithOID(oid) let result = repo.blobWithOID(oid)
expect(result.error).notTo(beNil()) expect(result).to(haveFailed())
} }
} }
@ -65,9 +63,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "dc220a3f0c22920dab86d4a8d3a3cb7e69d6205a")! let oid = OID(string: "dc220a3f0c22920dab86d4a8d3a3cb7e69d6205a")!
let result = repo.commitWithOID(oid) let result = repo.commitWithOID(oid)
let commit = result.value expect(result.map { $0.oid }).to(haveSucceeded(equal(oid)))
expect(commit).notTo(beNil())
expect(commit?.oid).to(equal(oid))
} }
it("should error if the commit doesn't exist") { it("should error if the commit doesn't exist") {
@ -75,7 +71,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")! let oid = OID(string: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")!
let result = repo.commitWithOID(oid) let result = repo.commitWithOID(oid)
expect(result.error).notTo(beNil()) expect(result).to(haveFailed(beAnError(domain: equal(libGit2ErrorDomain))))
} }
it("should error if the oid doesn't point to a commit") { it("should error if the oid doesn't point to a commit") {
@ -84,7 +80,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "f93e3a1a1525fb5b91020da86e44810c87a2d7bc")! let oid = OID(string: "f93e3a1a1525fb5b91020da86e44810c87a2d7bc")!
let result = repo.commitWithOID(oid) let result = repo.commitWithOID(oid)
expect(result.error).notTo(beNil()) expect(result).to(haveFailed(beAnError(domain: equal(libGit2ErrorDomain))))
} }
} }
@ -94,9 +90,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "57943b8ee00348180ceeedc960451562750f6d33")! let oid = OID(string: "57943b8ee00348180ceeedc960451562750f6d33")!
let result = repo.tagWithOID(oid) let result = repo.tagWithOID(oid)
let tag = result.value expect(result.map { $0.oid }).to(haveSucceeded(equal(oid)))
expect(tag).notTo(beNil())
expect(tag?.oid).to(equal(oid))
} }
it("should error if the tag doesn't exist") { it("should error if the tag doesn't exist") {
@ -104,7 +98,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")! let oid = OID(string: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")!
let result = repo.tagWithOID(oid) let result = repo.tagWithOID(oid)
expect(result.error).notTo(beNil()) expect(result).to(haveFailed(beAnError(domain: equal(libGit2ErrorDomain))))
} }
it("should error if the oid doesn't point to a tag") { it("should error if the oid doesn't point to a tag") {
@ -113,7 +107,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "dc220a3f0c22920dab86d4a8d3a3cb7e69d6205a")! let oid = OID(string: "dc220a3f0c22920dab86d4a8d3a3cb7e69d6205a")!
let result = repo.tagWithOID(oid) let result = repo.tagWithOID(oid)
expect(result.error).notTo(beNil()) expect(result).to(haveFailed(beAnError(domain: equal(libGit2ErrorDomain))))
} }
} }
@ -123,9 +117,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "f93e3a1a1525fb5b91020da86e44810c87a2d7bc")! let oid = OID(string: "f93e3a1a1525fb5b91020da86e44810c87a2d7bc")!
let result = repo.treeWithOID(oid) let result = repo.treeWithOID(oid)
let tree = result.value expect(result.map { $0.oid }).to(haveSucceeded(equal(oid)))
expect(tree).notTo(beNil())
expect(tree?.oid).to(equal(oid))
} }
it("should error if the tree doesn't exist") { it("should error if the tree doesn't exist") {
@ -133,7 +125,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")! let oid = OID(string: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")!
let result = repo.treeWithOID(oid) let result = repo.treeWithOID(oid)
expect(result.error).notTo(beNil()) expect(result).to(haveFailed(beAnError(domain: equal(libGit2ErrorDomain))))
} }
it("should error if the oid doesn't point to a tree") { it("should error if the oid doesn't point to a tree") {
@ -142,7 +134,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "dc220a3f0c22920dab86d4a8d3a3cb7e69d6205a")! let oid = OID(string: "dc220a3f0c22920dab86d4a8d3a3cb7e69d6205a")!
let result = repo.treeWithOID(oid) let result = repo.treeWithOID(oid)
expect(result.error).notTo(beNil()) expect(result).to(haveFailed(beAnError(domain: equal(libGit2ErrorDomain))))
} }
} }
@ -152,8 +144,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "41078396f5187daed5f673e4a13b185bbad71fba")! let oid = OID(string: "41078396f5187daed5f673e4a13b185bbad71fba")!
let blob = repo.blobWithOID(oid).value let blob = repo.blobWithOID(oid).value
let result = repo.objectWithOID(oid) let result = repo.objectWithOID(oid)
expect(result.value).notTo(beNil()) expect(result.map { $0 as Blob }).to(haveSucceeded(equal(blob)))
expect(result.value as Blob?).to(equal(blob))
} }
it("should work with a commit") { it("should work with a commit") {
@ -161,8 +152,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "dc220a3f0c22920dab86d4a8d3a3cb7e69d6205a")! let oid = OID(string: "dc220a3f0c22920dab86d4a8d3a3cb7e69d6205a")!
let commit = repo.commitWithOID(oid).value let commit = repo.commitWithOID(oid).value
let result = repo.objectWithOID(oid) let result = repo.objectWithOID(oid)
expect(result.value).notTo(beNil()) expect(result.map { $0 as Commit }).to(haveSucceeded(equal(commit)))
expect(result.value as Commit?).to(equal(commit))
} }
it("should work with a tag") { it("should work with a tag") {
@ -170,8 +160,7 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "57943b8ee00348180ceeedc960451562750f6d33")! let oid = OID(string: "57943b8ee00348180ceeedc960451562750f6d33")!
let tag = repo.tagWithOID(oid).value let tag = repo.tagWithOID(oid).value
let result = repo.objectWithOID(oid) let result = repo.objectWithOID(oid)
expect(result.value).notTo(beNil()) expect(result.map { $0 as Tag }).to(haveSucceeded(equal(tag)))
expect(result.value as Tag?).to(equal(tag))
} }
it("should work with a tree") { it("should work with a tree") {
@ -179,15 +168,14 @@ class RepositorySpec: QuickSpec {
let oid = OID(string: "f93e3a1a1525fb5b91020da86e44810c87a2d7bc")! let oid = OID(string: "f93e3a1a1525fb5b91020da86e44810c87a2d7bc")!
let tree = repo.treeWithOID(oid).value let tree = repo.treeWithOID(oid).value
let result = repo.objectWithOID(oid) let result = repo.objectWithOID(oid)
expect(result.value).notTo(beNil()) expect(result.map { $0 as Tree }).to(haveSucceeded(equal(tree)))
expect(result.value as Tree?).to(equal(tree))
} }
it("should error if there's no object with that oid") { it("should error if there's no object with that oid") {
let repo = Fixtures.simpleRepository let repo = Fixtures.simpleRepository
let oid = OID(string: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")! let oid = OID(string: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")!
let result = repo.objectWithOID(oid) let result = repo.objectWithOID(oid)
expect(result.error).notTo(beNil()) expect(result).to(haveFailed(beAnError(domain: equal(libGit2ErrorDomain))))
} }
} }
@ -198,7 +186,7 @@ class RepositorySpec: QuickSpec {
let pointer = PointerTo<Commit>(oid) let pointer = PointerTo<Commit>(oid)
let commit = repo.commitWithOID(oid).value! let commit = repo.commitWithOID(oid).value!
expect(repo.objectFromPointer(pointer).value).to(equal(commit)) expect(repo.objectFromPointer(pointer)).to(haveSucceeded(equal(commit)))
} }
it("should work with trees") { it("should work with trees") {
@ -207,7 +195,7 @@ class RepositorySpec: QuickSpec {
let pointer = PointerTo<Tree>(oid) let pointer = PointerTo<Tree>(oid)
let tree = repo.treeWithOID(oid).value! let tree = repo.treeWithOID(oid).value!
expect(repo.objectFromPointer(pointer).value).to(equal(tree)) expect(repo.objectFromPointer(pointer)).to(haveSucceeded(equal(tree)))
} }
it("should work with blobs") { it("should work with blobs") {
@ -216,7 +204,7 @@ class RepositorySpec: QuickSpec {
let pointer = PointerTo<Blob>(oid) let pointer = PointerTo<Blob>(oid)
let blob = repo.blobWithOID(oid).value! let blob = repo.blobWithOID(oid).value!
expect(repo.objectFromPointer(pointer).value).to(equal(blob)) expect(repo.objectFromPointer(pointer)).to(haveSucceeded(equal(blob)))
} }
it("should work with tags") { it("should work with tags") {
@ -225,7 +213,7 @@ class RepositorySpec: QuickSpec {
let pointer = PointerTo<Tag>(oid) let pointer = PointerTo<Tag>(oid)
let tag = repo.tagWithOID(oid).value! let tag = repo.tagWithOID(oid).value!
expect(repo.objectFromPointer(pointer).value).to(equal(tag)) expect(repo.objectFromPointer(pointer)).to(haveSucceeded(equal(tag)))
} }
} }
@ -236,8 +224,8 @@ class RepositorySpec: QuickSpec {
let pointer = Pointer.Commit(oid) let pointer = Pointer.Commit(oid)
let commit = repo.commitWithOID(oid).value! let commit = repo.commitWithOID(oid).value!
let result = repo.objectFromPointer(pointer).map { $0 as Commit }.value let result = repo.objectFromPointer(pointer).map { $0 as Commit }
expect(result).to(equal(commit)) expect(result).to(haveSucceeded(equal(commit)))
} }
it("should work with trees") { it("should work with trees") {
@ -246,8 +234,8 @@ class RepositorySpec: QuickSpec {
let pointer = Pointer.Tree(oid) let pointer = Pointer.Tree(oid)
let tree = repo.treeWithOID(oid).value! let tree = repo.treeWithOID(oid).value!
let result = repo.objectFromPointer(pointer).map { $0 as Tree }.value let result = repo.objectFromPointer(pointer).map { $0 as Tree }
expect(result).to(equal(tree)) expect(result).to(haveSucceeded(equal(tree)))
} }
it("should work with blobs") { it("should work with blobs") {
@ -256,8 +244,8 @@ class RepositorySpec: QuickSpec {
let pointer = Pointer.Blob(oid) let pointer = Pointer.Blob(oid)
let blob = repo.blobWithOID(oid).value! let blob = repo.blobWithOID(oid).value!
let result = repo.objectFromPointer(pointer).map { $0 as Blob }.value let result = repo.objectFromPointer(pointer).map { $0 as Blob }
expect(result).to(equal(blob)) expect(result).to(haveSucceeded(equal(blob)))
} }
it("should work with tags") { it("should work with tags") {
@ -266,8 +254,8 @@ class RepositorySpec: QuickSpec {
let pointer = Pointer.Tag(oid) let pointer = Pointer.Tag(oid)
let tag = repo.tagWithOID(oid).value! let tag = repo.tagWithOID(oid).value!
let result = repo.objectFromPointer(pointer).map { $0 as Tag }.value let result = repo.objectFromPointer(pointer).map { $0 as Tag }
expect(result).to(equal(tag)) expect(result).to(haveSucceeded(equal(tag)))
} }
} }
@ -275,15 +263,15 @@ class RepositorySpec: QuickSpec {
it("should return an empty list if there are no remotes") { it("should return an empty list if there are no remotes") {
let repo = Fixtures.simpleRepository let repo = Fixtures.simpleRepository
let result = repo.allRemotes() let result = repo.allRemotes()
expect(result.value).to(equal([])) expect(result).to(haveSucceeded(beEmpty()))
} }
it("should return all the remotes") { it("should return all the remotes") {
let repo = Fixtures.mantleRepository let repo = Fixtures.mantleRepository
let remotes = repo.allRemotes().value let remotes = repo.allRemotes()
let names = remotes?.map { $0.name } let names = remotes.map { $0.map { $0.name } }
expect(remotes?.count).to(equal(2)) expect(remotes.map { $0.count }).to(haveSucceeded(equal(2)))
expect(names).to(contain("origin", "upstream")) expect(names).to(haveSucceeded(contain("origin", "upstream")))
} }
} }
@ -291,13 +279,13 @@ class RepositorySpec: QuickSpec {
it("should return the remote if it exists") { it("should return the remote if it exists") {
let repo = Fixtures.mantleRepository let repo = Fixtures.mantleRepository
let result = repo.remoteWithName("upstream") let result = repo.remoteWithName("upstream")
expect(result.value?.name).to(equal("upstream")) expect(result.map { $0.name }).to(haveSucceeded(equal("upstream")))
} }
it("should error if the remote doesn't exist") { it("should error if the remote doesn't exist") {
let repo = Fixtures.simpleRepository let repo = Fixtures.simpleRepository
let result = repo.remoteWithName("nonexistent") let result = repo.remoteWithName("nonexistent")
expect(result.error).notTo(beNil()) expect(result).to(haveFailed(beAnError(domain: equal(libGit2ErrorDomain))))
} }
} }
@ -305,14 +293,14 @@ class RepositorySpec: QuickSpec {
it("should return a local branch if it exists") { it("should return a local branch if it exists") {
let name = "refs/heads/master" let name = "refs/heads/master"
let result = Fixtures.simpleRepository.referenceWithName(name) let result = Fixtures.simpleRepository.referenceWithName(name)
expect(result.value?.longName).to(equal(name)) expect(result.map { $0.longName }).to(haveSucceeded(equal(name)))
expect(result.value? as? Branch).notTo(beNil()) expect(result.value? as? Branch).notTo(beNil())
} }
it("should return a remote branch if it exists") { it("should return a remote branch if it exists") {
let name = "refs/remotes/upstream/master" let name = "refs/remotes/upstream/master"
let result = Fixtures.mantleRepository.referenceWithName(name) let result = Fixtures.mantleRepository.referenceWithName(name)
expect(result.value?.longName).to(equal(name)) expect(result.map { $0.longName }).to(haveSucceeded(equal(name)))
expect(result.value? as? Branch).notTo(beNil()) expect(result.value? as? Branch).notTo(beNil())
} }
@ -331,7 +319,7 @@ class RepositorySpec: QuickSpec {
it("should error if the reference doesn't exist") { it("should error if the reference doesn't exist") {
let result = Fixtures.simpleRepository.referenceWithName("refs/heads/nonexistent") let result = Fixtures.simpleRepository.referenceWithName("refs/heads/nonexistent")
expect(result.error).notTo(beNil()) expect(result).to(haveFailed(beAnError(domain: equal(libGit2ErrorDomain))))
} }
} }
@ -386,7 +374,7 @@ class RepositorySpec: QuickSpec {
it("should error if the branch doesn't exists") { it("should error if the branch doesn't exists") {
let result = Fixtures.simpleRepository.localBranchWithName("nonexistent") let result = Fixtures.simpleRepository.localBranchWithName("nonexistent")
expect(result.error).notTo(beNil()) expect(result).to(haveFailed(beAnError(domain: equal(libGit2ErrorDomain))))
} }
} }
@ -398,7 +386,7 @@ class RepositorySpec: QuickSpec {
it("should error if the branch doesn't exists") { it("should error if the branch doesn't exists") {
let result = Fixtures.simpleRepository.remoteBranchWithName("origin/nonexistent") let result = Fixtures.simpleRepository.remoteBranchWithName("origin/nonexistent")
expect(result.error).notTo(beNil()) expect(result).to(haveFailed(beAnError(domain: equal(libGit2ErrorDomain))))
} }
} }
@ -421,7 +409,7 @@ class RepositorySpec: QuickSpec {
it("should error if the branch doesn't exists") { it("should error if the branch doesn't exists") {
let result = Fixtures.simpleRepository.tagWithName("nonexistent") let result = Fixtures.simpleRepository.tagWithName("nonexistent")
expect(result.error).notTo(beNil()) expect(result).to(haveFailed(beAnError(domain: equal(libGit2ErrorDomain))))
} }
} }
} }