Merge develop to master

This commit is contained in:
Arnon Keereena 2017-04-28 22:20:01 +02:00
commit 96e9cf61a7
4 changed files with 91 additions and 26 deletions

View File

@ -21,6 +21,8 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
2549921B34FFC36AF8C9CD6D /* CommitIterator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25499A996CA7BD416620A397 /* CommitIterator.swift */; };
25499D325997CAB9BEFFCA4D /* CommitIterator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25499A996CA7BD416620A397 /* CommitIterator.swift */; };
621E66A01C72958800A0F352 /* OID.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE70B3E41A1ACB1A002C3F4E /* OID.swift */; };
621E66A11C72958800A0F352 /* Remotes.swift in Sources */ = {isa = PBXBuildFile; fileRef = BECB5F6D1A57284700999413 /* Remotes.swift */; };
621E66A21C72958800A0F352 /* CheckoutStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE276B281ACCD3CF00D6DAD7 /* CheckoutStrategy.swift */; };
@ -129,6 +131,7 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
25499A996CA7BD416620A397 /* CommitIterator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommitIterator.swift; sourceTree = "<group>"; };
621E66B41C72958800A0F352 /* SwiftGit2.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftGit2.framework; sourceTree = BUILT_PRODUCTS_DIR; };
621E66CE1C72958D00A0F352 /* SwiftGit2-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SwiftGit2-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
621E66D81C72989900A0F352 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Result.framework; path = "Carthage/Checkouts/Result/build/Debug-iphoneos/Result.framework"; sourceTree = "<group>"; };
@ -313,6 +316,7 @@
BECB5F691A56F19900999413 /* References.swift */,
BECB5F6D1A57284700999413 /* Remotes.swift */,
BEB31F261A0D6F7A00F525B9 /* Supporting Files */,
25499A996CA7BD416620A397 /* CommitIterator.swift */,
);
path = SwiftGit2;
sourceTree = "<group>";
@ -749,6 +753,7 @@
621E66A71C72958800A0F352 /* Pointers.swift in Sources */,
621E66A81C72958800A0F352 /* Errors.swift in Sources */,
621E66A91C72958800A0F352 /* SwiftGit2.m in Sources */,
2549921B34FFC36AF8C9CD6D /* CommitIterator.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -781,6 +786,7 @@
BE7A753F1A4A2BCC002DA7E3 /* Pointers.swift in Sources */,
DA5914761A94579000AED74C /* Errors.swift in Sources */,
BE14AA501A1974010015B439 /* SwiftGit2.m in Sources */,
25499D325997CAB9BEFFCA4D /* CommitIterator.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -0,0 +1,67 @@
//
// Created by Arnon Keereena on 4/28/17.
// Copyright (c) 2017 GitHub, Inc. All rights reserved.
//
import Result
import libgit2
public class CommitIterator: IteratorProtocol {
public typealias Element = Result<Commit, NSError>
var repo: Repository
var branch: Branch
var revisionWalker: OpaquePointer? = nil
var oid: git_oid
private var unsafeCommit: OpaquePointer? = nil
public init(repo: Repository, branch: Branch) {
self.repo = repo
self.branch = branch
self.oid = branch.oid.oid
setupRevisionWalker()
}
deinit {
git_revwalk_free(self.revisionWalker)
}
private func setupRevisionWalker() {
git_revwalk_new(&revisionWalker, repo.pointer)
git_revwalk_sorting(revisionWalker, GIT_SORT_TOPOLOGICAL.rawValue)
git_revwalk_sorting(revisionWalker, GIT_SORT_TIME.rawValue)
git_revwalk_push(revisionWalker, &oid)
}
private func result(withName name: String, from result: Int32) -> (stop: Bool, error: NSError?) {
guard result == GIT_OK.rawValue else {
if result == GIT_ITEROVER.rawValue {
return (stop: true, error: nil)
} else {
return (stop: false, error: NSError(gitError: result, pointOfFailure: name))
}
}
return (stop: false, error: nil)
}
public func next() -> Element? {
let revwalkGitResult = git_revwalk_next(&self.oid, self.revisionWalker)
let revwalkResult = result(withName: "git_revwalk_next", from: revwalkGitResult)
if revwalkResult.stop {
return nil
} else if let error = revwalkResult.error {
return Result.failure(error)
}
let lookupGitResult = git_commit_lookup(&self.unsafeCommit, self.repo.pointer, &self.oid)
let lookupResult = result(withName: "git_commit_lookup", from: lookupGitResult)
if lookupResult.stop {
return nil
} else if let error = lookupResult.error {
return Result.failure(error)
}
guard let commit = unsafeCommit else {
return nil
}
git_commit_free(unsafeCommit)
return Result.success(Commit(commit))
}
}

View File

@ -510,34 +510,22 @@ final public class Repository {
return setHEAD(reference).flatMap { self.checkout(strategy: strategy, progress: progress) }
}
/// Cache for commits(in: branch)
///
/// Specifically for allowing syntax "while let commit = repo.commits(in: branch).next() {}"
public var branchCommitIteratorMap: [Branch: CommitIterator] = [:]
/// Load all commits in the specified branch in topological & time order descending
///
/// :param: branch The branch to get all commits from
/// :returns: Returns a result with array of branches or the error that occurred
public func allCommits(in branch: Branch) -> Result<[Commit], NSError> {
var commits: [Commit] = []
var walker: OpaquePointer? = nil
var unsafeCommit: OpaquePointer? = nil
var oid = branch.oid.oid
git_revwalk_new(&walker, self.pointer)
defer {
git_revwalk_free(walker)
public func commits(in branch: Branch) -> CommitIterator {
if let iterator = branchCommitIteratorMap[branch] {
return iterator
} else {
let iterator = CommitIterator(repo: self, branch: branch)
branchCommitIteratorMap[branch] = iterator
return iterator
}
git_revwalk_sorting(walker, GIT_SORT_TOPOLOGICAL.rawValue)
git_revwalk_sorting(walker, GIT_SORT_TIME.rawValue)
git_revwalk_push(walker, &oid)
while git_revwalk_next(&oid, walker) == GIT_OK.rawValue {
let result = git_commit_lookup(&unsafeCommit, self.pointer, &oid)
guard result == GIT_OK.rawValue else {
return Result.failure(NSError(gitError: result, pointOfFailure: "git_commit_lookup"))
}
guard let commit = unsafeCommit else {
continue
}
commits += [Commit(commit)]
git_commit_free(unsafeCommit)
}
return Result.success(commits)
}
}

View File

@ -605,9 +605,13 @@ class RepositorySpec: QuickSpec {
it("should return all (9) commits") {
let repo = Fixtures.simpleRepository
let branches = repo.localBranches().value!
let commits = branches.map { repo.allCommits(in: $0).value!.map { $0 } }
let count = commits.reduce(0) { $0 + $1.count }
let expected = 9
var count = 0
let expected = 9
for branch in branches {
while let commit = repo.commits(in: branch).next() {
count += 1
}
}
expect(count).to(equal(expected))
}
}