Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/BuildPR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- name: ls Xcode
run: ls -la /Applications/Xcode*
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Set Xcode Version
run: sudo xcode-select -s /Applications/Xcode_15.2.app
- name: Build and test on macOS
Expand Down
54 changes: 7 additions & 47 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,47 +1,7 @@
.vscode/
.build/
.swiftpm/

# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
*.xcscmblueprint
*.idea*

External/libgit2*.a
External/libgit2-mac
External/ios-openssl
External/libgit2-ios
External/libssh2-ios

### fastlane ###
# fastlane - A streamlined workflow tool for Cocoa deployment

# fastlane specific
fastlane/report.xml

# deliver temporary files
fastlane/Preview.html

# snapshot generated screenshots
fastlane/screenshots/**/*.png
fastlane/screenshots/screenshots.html

# scan temporary files
fastlane/test_output
test_output
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
2 changes: 2 additions & 0 deletions .swiftformat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--disable unusedArguments
--indent 4
124 changes: 58 additions & 66 deletions Sources/SwiftGit2/CheckoutStrategy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,97 +11,89 @@ import libgit2
/// The flags defining how a checkout should be performed.
/// More detail is available in the libgit2 documentation for `git_checkout_strategy_t`.
public struct CheckoutStrategy: OptionSet {
private let value: UInt
// MARK: - Properties

// MARK: - Initialization
public let rawValue: UInt

/// Create an instance initialized with `nil`.
public init(nilLiteral: ()) {
self.value = 0
}
// MARK: - Initialization

public init(rawValue value: UInt) {
self.value = value
}
/// Create an instance initialized with `nil`.
public init(nilLiteral: ()) {
rawValue = 0
}

public init(_ strategy: git_checkout_strategy_t) {
self.value = UInt(strategy.rawValue)
}
public init(rawValue: UInt) {
self.rawValue = rawValue
}

public static var allZeros: CheckoutStrategy {
return self.init(rawValue: 0)
}
init(_ strategy: git_checkout_strategy_t) {
rawValue = UInt(strategy.rawValue)
}

// MARK: - Properties
var gitCheckoutStrategy: git_checkout_strategy_t {
git_checkout_strategy_t(UInt32(rawValue))
}

public var rawValue: UInt {
return value
}
// MARK: - Values

public var gitCheckoutStrategy: git_checkout_strategy_t {
return git_checkout_strategy_t(UInt32(self.value))
}
/// Default is a dry run, no actual updates.
public static let none = CheckoutStrategy(GIT_CHECKOUT_NONE)

// MARK: - Values
/// Allow safe updates that cannot overwrite uncommitted data.
public static let safe = CheckoutStrategy(GIT_CHECKOUT_SAFE)

/// Default is a dry run, no actual updates.
public static let None = CheckoutStrategy(GIT_CHECKOUT_NONE)
/// Allow all updates to force working directory to look like index
public static let force = CheckoutStrategy(GIT_CHECKOUT_FORCE)

/// Allow safe updates that cannot overwrite uncommitted data.
public static let Safe = CheckoutStrategy(GIT_CHECKOUT_SAFE)
/// Allow checkout to recreate missing files.
public static let recreateMissing = CheckoutStrategy(GIT_CHECKOUT_RECREATE_MISSING)

/// Allow all updates to force working directory to look like index
public static let Force = CheckoutStrategy(GIT_CHECKOUT_FORCE)
/// Allow checkout to make safe updates even if conflicts are found.
public static let allowConflicts = CheckoutStrategy(GIT_CHECKOUT_ALLOW_CONFLICTS)

/// Allow checkout to recreate missing files.
public static let RecreateMissing = CheckoutStrategy(GIT_CHECKOUT_RECREATE_MISSING)
/// Remove untracked files not in index (that are not ignored).
public static let removeUntracked = CheckoutStrategy(GIT_CHECKOUT_REMOVE_UNTRACKED)

/// Allow checkout to make safe updates even if conflicts are found.
public static let AllowConflicts = CheckoutStrategy(GIT_CHECKOUT_ALLOW_CONFLICTS)
/// Remove ignored files not in index.
public static let removeIgnored = CheckoutStrategy(GIT_CHECKOUT_REMOVE_IGNORED)

/// Remove untracked files not in index (that are not ignored).
public static let RemoveUntracked = CheckoutStrategy(GIT_CHECKOUT_REMOVE_UNTRACKED)
/// Only update existing files, don't create new ones.
public static let updateOnly = CheckoutStrategy(GIT_CHECKOUT_UPDATE_ONLY)

/// Remove ignored files not in index.
public static let RemoveIgnored = CheckoutStrategy(GIT_CHECKOUT_REMOVE_IGNORED)
/// Normally checkout updates index entries as it goes; this stops that.
/// Implies `DontWriteIndex`.
public static let dontUpdateIndex = CheckoutStrategy(GIT_CHECKOUT_DONT_UPDATE_INDEX)

/// Only update existing files, don't create new ones.
public static let UpdateOnly = CheckoutStrategy(GIT_CHECKOUT_UPDATE_ONLY)
/// Don't refresh index/config/etc before doing checkout
public static let noRefresh = CheckoutStrategy(GIT_CHECKOUT_NO_REFRESH)

/// Normally checkout updates index entries as it goes; this stops that.
/// Implies `DontWriteIndex`.
public static let DontUpdateIndex = CheckoutStrategy(GIT_CHECKOUT_DONT_UPDATE_INDEX)
/// Allow checkout to skip unmerged files
public static let skipUnmerged = CheckoutStrategy(GIT_CHECKOUT_SKIP_UNMERGED)

/// Don't refresh index/config/etc before doing checkout
public static let NoRefresh = CheckoutStrategy(GIT_CHECKOUT_NO_REFRESH)
/// For unmerged files, checkout stage 2 from index
public static let useOurs = CheckoutStrategy(GIT_CHECKOUT_USE_OURS)

/// Allow checkout to skip unmerged files
public static let SkipUnmerged = CheckoutStrategy(GIT_CHECKOUT_SKIP_UNMERGED)
/// For unmerged files, checkout stage 3 from index
public static let useTheirs = CheckoutStrategy(GIT_CHECKOUT_USE_THEIRS)

/// For unmerged files, checkout stage 2 from index
public static let UseOurs = CheckoutStrategy(GIT_CHECKOUT_USE_OURS)
/// Treat pathspec as simple list of exact match file paths
public static let disablePathspecMatch = CheckoutStrategy(GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)

/// For unmerged files, checkout stage 3 from index
public static let UseTheirs = CheckoutStrategy(GIT_CHECKOUT_USE_THEIRS)
/// Ignore directories in use, they will be left empty
public static let skipLockedDirectories = CheckoutStrategy(GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES)

/// Treat pathspec as simple list of exact match file paths
public static let DisablePathspecMatch = CheckoutStrategy(GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)
/// Don't overwrite ignored files that exist in the checkout target
public static let dontOverwriteIgnored = CheckoutStrategy(GIT_CHECKOUT_DONT_OVERWRITE_IGNORED)

/// Ignore directories in use, they will be left empty
public static let SkipLockedDirectories = CheckoutStrategy(GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES)
/// Write normal merge files for conflicts
public static let conflictStyleMerge = CheckoutStrategy(GIT_CHECKOUT_CONFLICT_STYLE_MERGE)

/// Don't overwrite ignored files that exist in the checkout target
public static let DontOverwriteIgnored = CheckoutStrategy(GIT_CHECKOUT_DONT_OVERWRITE_IGNORED)
/// Include common ancestor data in diff3 format files for conflicts
public static let conflictStyleDiff3 = CheckoutStrategy(GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)

/// Write normal merge files for conflicts
public static let ConflictStyleMerge = CheckoutStrategy(GIT_CHECKOUT_CONFLICT_STYLE_MERGE)
/// Don't overwrite existing files or folders
public static let dontRemoveExisting = CheckoutStrategy(GIT_CHECKOUT_DONT_REMOVE_EXISTING)

/// Include common ancestor data in diff3 format files for conflicts
public static let ConflictStyleDiff3 = CheckoutStrategy(GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)

/// Don't overwrite existing files or folders
public static let DontRemoveExisting = CheckoutStrategy(GIT_CHECKOUT_DONT_REMOVE_EXISTING)

/// Normally checkout writes the index upon completion; this prevents that.
public static let DontWriteIndex = CheckoutStrategy(GIT_CHECKOUT_DONT_WRITE_INDEX)
/// Normally checkout writes the index upon completion; this prevents that.
public static let dontWriteIndex = CheckoutStrategy(GIT_CHECKOUT_DONT_WRITE_INDEX)
}
109 changes: 55 additions & 54 deletions Sources/SwiftGit2/CommitIterator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,64 +7,65 @@ import Foundation
import libgit2

public class CommitIterator: IteratorProtocol, Sequence {
public typealias Iterator = CommitIterator
public typealias Element = Result<Commit, NSError>
let repo: Repository
private var revisionWalker: OpaquePointer?
public typealias Iterator = CommitIterator
public typealias Element = Result<Commit, NSError>
let repo: Repository
private var revisionWalker: OpaquePointer?

private enum Next {
case over
case okay
case error(NSError)
private enum Next {
case over
case okay
case error(NSError)

init(_ result: Int32, name: String) {
switch result {
case GIT_ITEROVER.rawValue:
self = .over
case GIT_OK.rawValue:
self = .okay
default:
self = .error(NSError(gitError: result, pointOfFailure: name))
}
}
}
init(_ result: Int32, name: String) {
switch result {
case GIT_ITEROVER.rawValue:
self = .over
case GIT_OK.rawValue:
self = .okay
default:
self = .error(NSError(gitError: result, pointOfFailure: name))
}
}
}

init(repo: Repository, root: git_oid) {
self.repo = repo
setupRevisionWalker(root: root)
}
init(repo: Repository, root: git_oid) {
self.repo = repo
setupRevisionWalker(root: root)
}

deinit {
git_revwalk_free(self.revisionWalker)
}
deinit {
git_revwalk_free(self.revisionWalker)
}

private func setupRevisionWalker(root: git_oid) {
var oid = root
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 setupRevisionWalker(root: git_oid) {
var oid = root
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)
}

public func next() -> Element? {
var oid = git_oid()
let revwalkGitResult = git_revwalk_next(&oid, revisionWalker)
let nextResult = Next(revwalkGitResult, name: "git_revwalk_next")
switch nextResult {
case let .error(error):
return Result.failure(error)
case .over:
return nil
case .okay:
var unsafeCommit: OpaquePointer? = nil
let lookupGitResult = git_commit_lookup(&unsafeCommit, repo.pointer, &oid)
guard lookupGitResult == GIT_OK.rawValue,
let unwrapCommit = unsafeCommit else {
return Result.failure(NSError(gitError: lookupGitResult, pointOfFailure: "git_commit_lookup"))
}
let result: Element = Result.success(Commit(unwrapCommit))
git_commit_free(unsafeCommit)
return result
}
}
public func next() -> Element? {
var oid = git_oid()
let revwalkGitResult = git_revwalk_next(&oid, revisionWalker)
let nextResult = Next(revwalkGitResult, name: "git_revwalk_next")
switch nextResult {
case let .error(error):
return Result.failure(error)
case .over:
return nil
case .okay:
var unsafeCommit: OpaquePointer? = nil
let lookupGitResult = git_commit_lookup(&unsafeCommit, repo.pointer, &oid)
guard lookupGitResult == GIT_OK.rawValue,
let unwrapCommit = unsafeCommit
else {
return Result.failure(NSError(gitError: lookupGitResult, pointOfFailure: "git_commit_lookup"))
}
let result: Element = Result.success(Commit(unwrapCommit))
git_commit_free(unsafeCommit)
return result
}
}
}
Loading
Loading