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 libgit2
|
||||
import Result
|
||||
|
||||
/// A git object.
|
||||
public protocol ObjectType {
|
||||
@ -37,6 +38,14 @@ public struct Signature {
|
||||
/// The time zone that `time` should be interpreted relative to.
|
||||
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`.
|
||||
public init(_ signature: git_signature) {
|
||||
name = String(validatingUTF8: signature.name)!
|
||||
@ -44,6 +53,20 @@ public struct Signature {
|
||||
time = Date(timeIntervalSince1970: TimeInterval(signature.when.time))
|
||||
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 {
|
||||
|
||||
@ -601,15 +601,96 @@ final public class Repository {
|
||||
var paths = git_strarray(strings: &dirPointer, count: 1)
|
||||
return unsafeIndex().flatMap { index in
|
||||
defer { git_index_free(index) }
|
||||
let add_result = git_index_add_all(index, &paths, 0, nil, nil)
|
||||
guard add_result == GIT_OK.rawValue else {
|
||||
let err = NSError(gitError: add_result, pointOfFailure: "git_index_add_all")
|
||||
let addResult = git_index_add_all(index, &paths, 0, nil, nil)
|
||||
guard addResult == GIT_OK.rawValue else {
|
||||
let err = NSError(gitError: addResult, pointOfFailure: "git_index_add_all")
|
||||
return .failure(err)
|
||||
}
|
||||
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
|
||||
|
||||
public func diff(for commit: Commit) -> Result<Diff, NSError> {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user