mirror of
https://github.com/gosticks/SwiftGit2.git
synced 2025-10-16 11:55:34 +00:00
Merge develop to master
This commit is contained in:
commit
96e9cf61a7
@ -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;
|
||||
};
|
||||
|
||||
67
SwiftGit2/CommitIterator.swift
Normal file
67
SwiftGit2/CommitIterator.swift
Normal 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))
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user