Created
April 25, 2019 17:58
-
-
Save Uncommon/ea5de73216ea57516e28e11415a5f4fd to your computer and use it in GitHub Desktop.
Creating a generic factory
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
extension XTRepository | |
{ | |
/// Branches is a sequence, not a collection, because the API does not provide | |
/// a count or indexed access. | |
public struct BranchSequence<BranchType: Branch>: Sequence | |
{ | |
public typealias Element = BranchType | |
let repo: XTRepository | |
let type: git_branch_t | |
public func makeIterator() -> BranchIterator<BranchType> | |
{ | |
return BranchIterator<BranchType>(repo: repo, flags: type) | |
} | |
} | |
public class BranchIterator<BranchType: Branch>: IteratorProtocol | |
{ | |
let repo: XTRepository | |
let iterator: OpaquePointer? | |
init(repo: XTRepository, flags: git_branch_t) | |
{ | |
var result: OpaquePointer? | |
if git_branch_iterator_new(&result, repo.gitRepo, flags) == 0 { | |
self.iterator = result | |
} | |
else { | |
self.iterator = nil | |
} | |
self.repo = repo | |
} | |
// This is specialized in extensions down below | |
fileprivate func makeBranch(_ ref: OpaquePointer) -> BranchType? | |
{ | |
return nil | |
} | |
public func next() -> BranchType? | |
{ | |
guard let iterator = self.iterator | |
else { return nil } | |
var type = git_branch_t(0) | |
var ref: OpaquePointer? | |
guard git_branch_next(&ref, &type, iterator) == 0, | |
let finalRef = ref | |
else { return nil } | |
return makeBranch(finalRef) | |
} | |
deinit | |
{ | |
git_branch_iterator_free(iterator) | |
} | |
} | |
/// The indexable collection of stashes in the repository. | |
public class Stashes: Collection | |
{ | |
public typealias Iterator = StashIterator | |
let repo: XTRepository | |
let refLog: OpaquePointer? | |
public let count: Int | |
static let stashRefName = "refs/stash" | |
init(repo: XTRepository) | |
{ | |
self.repo = repo | |
let refLogPtr = UnsafeMutablePointer<OpaquePointer?>.allocate(capacity: 1) | |
guard git_reflog_read(refLogPtr, repo.gitRepo, Stashes.stashRefName) == 0 | |
else { | |
self.refLog = nil | |
self.count = 0 | |
return | |
} | |
self.refLog = refLogPtr.pointee | |
self.count = git_reflog_entrycount(refLog) | |
} | |
deinit | |
{ | |
git_reflog_free(refLog) | |
} | |
public func makeIterator() -> StashIterator | |
{ | |
return StashIterator(stashes: self) | |
} | |
public subscript(position: Int) -> GitStash | |
{ | |
let entry = git_reflog_entry_byindex(refLog, position) | |
let message = String(cString: git_reflog_entry_message(entry)) | |
return GitStash(repo: repo, index: UInt(position), message: message) | |
} | |
public var startIndex: Int { return 0 } | |
public var endIndex: Int { return count } | |
public func index(after i: Int) -> Int | |
{ | |
return i + 1 | |
} | |
} | |
public class StashIterator: IteratorProtocol | |
{ | |
public typealias Element = GitStash | |
let stashes: Stashes | |
var index: Int | |
init(stashes: Stashes) | |
{ | |
self.stashes = stashes | |
self.index = 0 | |
} | |
public func next() -> GitStash? | |
{ | |
guard index < stashes.count | |
else { return nil } | |
let result = stashes[index] | |
index += 1 | |
return result | |
} | |
} | |
} | |
extension XTRepository.BranchIterator where BranchType: LocalBranch | |
{ | |
fileprivate func makeBranch(_ ref: OpaquePointer) -> BranchType? | |
{ | |
return GitLocalBranch(branch: ref) as? BranchType | |
} | |
} | |
extension XTRepository.BranchIterator where BranchType: RemoteBranch | |
{ | |
fileprivate func makeBranch(_ ref: OpaquePointer) -> BranchType? | |
{ | |
return GitRemoteBranch(branch: ref) as? BranchType | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment