Skip to content

Commit

Permalink
Reflog support (libgit2#467)
Browse files Browse the repository at this point in the history
  • Loading branch information
pokstad committed Jan 4, 2021
1 parent 4b2ac7c commit b5a87fd
Showing 1 changed file with 175 additions and 0 deletions.
175 changes: 175 additions & 0 deletions reflog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
package git

/*
#include <git2.h>
*/
import "C"
import (
"runtime"
"unsafe"
)

// RefLog is a log of changes for a reference
type RefLog struct {
ptr *C.git_reflog
repo *Repository
name string
}

func newRefLogFromC(ptr *C.git_reflog, repo *Repository, name string) *RefLog {
l := &RefLog{
ptr: ptr,
repo: repo,
name: name,
}
runtime.SetFinalizer(l, (*RefLog).Free)
return l
}

func (repo *Repository) ReadRefLog(name string) (*RefLog, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()

cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))

var ptr *C.git_reflog

ecode := C.git_reflog_read(&ptr, repo.ptr, cname)
runtime.KeepAlive(repo)
if ecode < 0 {
return nil, MakeGitError(ecode)
}

return newRefLogFromC(ptr, repo, name), nil
}

func (repo *Repository) DeleteReflog(name string) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()

cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))

ecode := C.git_reflog_delete(repo.ptr, cname)
runtime.KeepAlive(repo)
if ecode < 0 {
return MakeGitError(ecode)
}

return nil
}

func (repo *Repository) RenameReflog(oldName, newName string) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()

cOldName := C.CString(oldName)
defer C.free(unsafe.Pointer(cOldName))

cNewName := C.CString(newName)
defer C.free(unsafe.Pointer(cNewName))

ecode := C.git_reflog_rename(repo.ptr, cOldName, cNewName)
runtime.KeepAlive(repo)
if ecode < 0 {
return MakeGitError(ecode)
}

return nil
}

func (l *RefLog) Write() error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()

ecode := C.git_reflog_write(l.ptr)
runtime.KeepAlive(l)
if ecode < 0 {
return MakeGitError(ecode)
}
return nil
}

func (l *RefLog) EntryCount() uint {
runtime.LockOSThread()
defer runtime.UnlockOSThread()

count := C.git_reflog_entrycount(l.ptr)
runtime.KeepAlive(l)
return uint(count)
}

// RefLogEntry specifies a reference change
type RefLogEntry struct {
Old *Oid
New *Oid
Committer *Signature
Message string // may be empty
}

func newRefLogEntry(entry *C.git_reflog_entry) *RefLogEntry {
return &RefLogEntry{
New: newOidFromC(C.git_reflog_entry_id_new(entry)),
Old: newOidFromC(C.git_reflog_entry_id_old(entry)),
Committer: newSignatureFromC(C.git_reflog_entry_committer(entry)),
Message: C.GoString(C.git_reflog_entry_message(entry)),
}
}

func (l *RefLog) EntryByIndex(index uint) *RefLogEntry {
runtime.LockOSThread()
defer runtime.UnlockOSThread()

entry := C.git_reflog_entry_byindex(l.ptr, C.size_t(index))
if entry == nil {
return nil
}

goEntry := newRefLogEntry(entry)
runtime.KeepAlive(l)

return goEntry
}

func (l *RefLog) DropEntry(index uint, rewriteHistory bool) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()

var rewriteHistoryInt int
if rewriteHistory {
rewriteHistoryInt = 1
}

ecode := C.git_reflog_drop(l.ptr, C.size_t(index), C.int(rewriteHistoryInt))
runtime.KeepAlive(l)
if ecode < 0 {
return MakeGitError(ecode)
}

return nil
}

func (l *RefLog) AppendEntry(oid *Oid, committer *Signature, message string) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()

cSignature, err := committer.toC()
if err != nil {
return err
}
defer C.git_signature_free(cSignature)

cMsg := C.CString(message)
defer C.free(unsafe.Pointer(cMsg))

C.git_reflog_append(l.ptr, oid.toC(), cSignature, cMsg)
runtime.KeepAlive(l)

return nil
}

func (l *RefLog) Free() {
runtime.SetFinalizer(l, nil)
C.git_reflog_free(l.ptr)
}

0 comments on commit b5a87fd

Please sign in to comment.