mirror of
https://github.com/gosticks/SwiftGit2.git
synced 2025-10-16 11:55:34 +00:00
implement git commit
This commit is contained in:
parent
25f3ecc4e6
commit
b193c80dc0
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import libgit2
|
import libgit2
|
||||||
|
import Result
|
||||||
|
|
||||||
/// A git object.
|
/// A git object.
|
||||||
public protocol ObjectType {
|
public protocol ObjectType {
|
||||||
@ -37,6 +38,14 @@ public struct Signature {
|
|||||||
/// The time zone that `time` should be interpreted relative to.
|
/// The time zone that `time` should be interpreted relative to.
|
||||||
public let timeZone: TimeZone
|
public let timeZone: TimeZone
|
||||||
|
|
||||||
|
/// Create an instance with custom name, email, dates, etc.
|
||||||
|
public init(name: String, email: String, time: Date = Date.init(), timeZone: TimeZone = TimeZone.autoupdatingCurrent) {
|
||||||
|
self.name = name
|
||||||
|
self.email = email
|
||||||
|
self.time = time
|
||||||
|
self.timeZone = timeZone
|
||||||
|
}
|
||||||
|
|
||||||
/// Create an instance with a libgit2 `git_signature`.
|
/// Create an instance with a libgit2 `git_signature`.
|
||||||
public init(_ signature: git_signature) {
|
public init(_ signature: git_signature) {
|
||||||
name = String(validatingUTF8: signature.name)!
|
name = String(validatingUTF8: signature.name)!
|
||||||
@ -44,6 +53,20 @@ public struct Signature {
|
|||||||
time = Date(timeIntervalSince1970: TimeInterval(signature.when.time))
|
time = Date(timeIntervalSince1970: TimeInterval(signature.when.time))
|
||||||
timeZone = TimeZone(secondsFromGMT: 60 * Int(signature.when.offset))!
|
timeZone = TimeZone(secondsFromGMT: 60 * Int(signature.when.offset))!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return an unsafe pointer to the `git_signature` struct.
|
||||||
|
/// Caller is responsible for freeing it with `git_signature_free`.
|
||||||
|
var unsafeSignature: Result<UnsafeMutablePointer<git_signature>, NSError> {
|
||||||
|
var signature: UnsafeMutablePointer<git_signature>? = nil
|
||||||
|
let time = git_time_t(self.time.timeIntervalSince1970) // Unix epoch time
|
||||||
|
let offset: Int32 = 0
|
||||||
|
let signatureResult = git_signature_new(&signature, name, email, time, offset)
|
||||||
|
guard signatureResult == GIT_OK.rawValue, let signatureUnwrap = signature else {
|
||||||
|
let err = NSError(gitError: signatureResult, pointOfFailure: "git_signature_new")
|
||||||
|
return .failure(err)
|
||||||
|
}
|
||||||
|
return .success(signatureUnwrap)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Signature: Hashable {
|
extension Signature: Hashable {
|
||||||
|
|||||||
@ -601,15 +601,96 @@ final public class Repository {
|
|||||||
var paths = git_strarray(strings: &dirPointer, count: 1)
|
var paths = git_strarray(strings: &dirPointer, count: 1)
|
||||||
return unsafeIndex().flatMap { index in
|
return unsafeIndex().flatMap { index in
|
||||||
defer { git_index_free(index) }
|
defer { git_index_free(index) }
|
||||||
let add_result = git_index_add_all(index, &paths, 0, nil, nil)
|
let addResult = git_index_add_all(index, &paths, 0, nil, nil)
|
||||||
guard add_result == GIT_OK.rawValue else {
|
guard addResult == GIT_OK.rawValue else {
|
||||||
let err = NSError(gitError: add_result, pointOfFailure: "git_index_add_all")
|
let err = NSError(gitError: addResult, pointOfFailure: "git_index_add_all")
|
||||||
return .failure(err)
|
return .failure(err)
|
||||||
}
|
}
|
||||||
return .success(())
|
return .success(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Perform a commit with arbitrary numbers of parent commits.
|
||||||
|
public func commit(
|
||||||
|
tree treeOID: git_oid,
|
||||||
|
parents: [Commit],
|
||||||
|
message: String,
|
||||||
|
signature: Signature
|
||||||
|
) -> Result<Commit, NSError> {
|
||||||
|
return unsafeIndex().flatMap { index in
|
||||||
|
defer { git_index_free(index) }
|
||||||
|
// create commit signature
|
||||||
|
return signature.unsafeSignature.flatMap { signature in
|
||||||
|
defer { git_signature_free(signature) }
|
||||||
|
var tree: OpaquePointer? = nil
|
||||||
|
var treeOIDCopy = treeOID
|
||||||
|
let lookupResult = git_tree_lookup(&tree, self.pointer, &treeOIDCopy)
|
||||||
|
guard lookupResult == GIT_OK.rawValue else {
|
||||||
|
let err = NSError(gitError: lookupResult, pointOfFailure: "git_tree_lookup")
|
||||||
|
return .failure(err)
|
||||||
|
}
|
||||||
|
defer { git_tree_free(tree) }
|
||||||
|
|
||||||
|
var msgBuf = git_buf()
|
||||||
|
git_message_prettify(&msgBuf, message, 0, /* ascii for # */ 35)
|
||||||
|
defer { git_buf_free(&msgBuf) }
|
||||||
|
|
||||||
|
// use HEAD as parent
|
||||||
|
var parentC: [OpaquePointer?] = []
|
||||||
|
for parentCommit in parents {
|
||||||
|
var parent: OpaquePointer? = nil
|
||||||
|
var oid = parentCommit.oid.oid
|
||||||
|
git_commit_lookup(&parent, self.pointer, &oid)
|
||||||
|
parentC.append(parent!)
|
||||||
|
}
|
||||||
|
|
||||||
|
let parentsContiguous = ContiguousArray(parentC)
|
||||||
|
return parentsContiguous.withUnsafeBufferPointer { unsafeBuffer in
|
||||||
|
var commitOID = git_oid()
|
||||||
|
let parentsPtr = UnsafeMutablePointer(mutating: unsafeBuffer.baseAddress)
|
||||||
|
let result = git_commit_create(
|
||||||
|
&commitOID,
|
||||||
|
self.pointer,
|
||||||
|
"HEAD",
|
||||||
|
signature,
|
||||||
|
signature,
|
||||||
|
nil,
|
||||||
|
msgBuf.ptr,
|
||||||
|
tree,
|
||||||
|
parents.count,
|
||||||
|
parentsPtr
|
||||||
|
)
|
||||||
|
guard result == GIT_OK.rawValue else {
|
||||||
|
return .failure(NSError(gitError: result, pointOfFailure: "git_commit_create"))
|
||||||
|
}
|
||||||
|
return commit(OID(commitOID))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform a commit of the staged files with the specified message and signature,
|
||||||
|
/// assuming we are not doing a merge and using the current tip as the parent.
|
||||||
|
public func commit(message: String, signature: Signature) -> Result<Commit, NSError> {
|
||||||
|
return unsafeIndex().flatMap { index in
|
||||||
|
defer { git_index_free(index) }
|
||||||
|
var treeOID = git_oid()
|
||||||
|
let treeResult = git_index_write_tree(&treeOID, index)
|
||||||
|
guard treeResult == GIT_OK.rawValue else {
|
||||||
|
let err = NSError(gitError: treeResult, pointOfFailure: "git_index_write_tree")
|
||||||
|
return .failure(err)
|
||||||
|
}
|
||||||
|
var parentID = git_oid()
|
||||||
|
let nameToIDResult = git_reference_name_to_id(&parentID, self.pointer, "HEAD")
|
||||||
|
guard nameToIDResult == GIT_OK.rawValue else {
|
||||||
|
return .failure(NSError(gitError: nameToIDResult, pointOfFailure: "git_reference_name_to_id"))
|
||||||
|
}
|
||||||
|
return commit(OID(parentID)).flatMap { parentCommit in
|
||||||
|
commit(tree: treeOID, parents: [parentCommit], message: message, signature: signature)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Diffs
|
// MARK: - Diffs
|
||||||
|
|
||||||
public func diff(for commit: Commit) -> Result<Diff, NSError> {
|
public func diff(for commit: Commit) -> Result<Diff, NSError> {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user