blob: efc506eb84157079f7757b8bedca530443c471e9 [file] [log] [blame]
package git
/*
#include <git2.h>
#include <git2/sys/repository.h>
*/
import "C"
import (
"runtime"
"unsafe"
)
// Repository
type Repository struct {
ptr *C.git_repository
// Remotes represents the collection of remotes and can be
// used to add, remove and configure remotes for this
// repository.
Remotes RemoteCollection
// Submodules represents the collection of submodules and can
// be used to add, remove and configure submodules in this
// repostiory.
Submodules SubmoduleCollection
// References represents the collection of references and can
// be used to create, remove or update refernces for this repository.
References ReferenceCollection
// Notes represents the collection of notes and can be used to
// read, write and delete notes from this repository.
Notes NoteCollection
// Tags represents the collection of tags and can be used to create,
// list, iterate and remove tags in this repository.
Tags TagsCollection
}
func newRepositoryFromC(ptr *C.git_repository) *Repository {
repo := &Repository{ptr: ptr}
repo.Remotes.repo = repo
repo.Submodules.repo = repo
repo.References.repo = repo
repo.Notes.repo = repo
repo.Tags.repo = repo
runtime.SetFinalizer(repo, (*Repository).Free)
return repo
}
func OpenRepository(path string) (*Repository, error) {
cpath := C.CString(path)
defer C.free(unsafe.Pointer(cpath))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
var ptr *C.git_repository
ret := C.git_repository_open(&ptr, cpath)
if ret < 0 {
return nil, MakeGitError(ret)
}
return newRepositoryFromC(ptr), nil
}
type RepositoryOpenFlag int
const (
RepositoryOpenNoSearch RepositoryOpenFlag = C.GIT_REPOSITORY_OPEN_NO_SEARCH
RepositoryOpenCrossFs RepositoryOpenFlag = C.GIT_REPOSITORY_OPEN_CROSS_FS
RepositoryOpenBare RepositoryOpenFlag = C.GIT_REPOSITORY_OPEN_BARE
)
func OpenRepositoryExtended(path string, flags RepositoryOpenFlag, ceiling string) (*Repository, error) {
cpath := C.CString(path)
defer C.free(unsafe.Pointer(cpath))
var cceiling *C.char = nil
if len(ceiling) > 0 {
cceiling = C.CString(ceiling)
defer C.free(unsafe.Pointer(cceiling))
}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
var ptr *C.git_repository
ret := C.git_repository_open_ext(&ptr, cpath, C.uint(flags), cceiling)
if ret < 0 {
return nil, MakeGitError(ret)
}
return newRepositoryFromC(ptr), nil
}
func InitRepository(path string, isbare bool) (*Repository, error) {
cpath := C.CString(path)
defer C.free(unsafe.Pointer(cpath))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
var ptr *C.git_repository
ret := C.git_repository_init(&ptr, cpath, ucbool(isbare))
if ret < 0 {
return nil, MakeGitError(ret)
}
return newRepositoryFromC(ptr), nil
}
func NewRepositoryWrapOdb(odb *Odb) (repo *Repository, err error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
var ptr *C.git_repository
ret := C.git_repository_wrap_odb(&ptr, odb.ptr)
if ret < 0 {
return nil, MakeGitError(ret)
}
return newRepositoryFromC(ptr), nil
}
func (v *Repository) SetRefdb(refdb *Refdb) {
C.git_repository_set_refdb(v.ptr, refdb.ptr)
}
func (v *Repository) Free() {
runtime.SetFinalizer(v, nil)
C.git_repository_free(v.ptr)
}
func (v *Repository) Config() (*Config, error) {
config := new(Config)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ret := C.git_repository_config(&config.ptr, v.ptr)
if ret < 0 {
return nil, MakeGitError(ret)
}
runtime.SetFinalizer(config, (*Config).Free)
return config, nil
}
func (v *Repository) Index() (*Index, error) {
var ptr *C.git_index
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ret := C.git_repository_index(&ptr, v.ptr)
if ret < 0 {
return nil, MakeGitError(ret)
}
return newIndexFromC(ptr), nil
}
func (v *Repository) lookupType(id *Oid, t ObjectType) (*Object, error) {
var ptr *C.git_object
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ret := C.git_object_lookup(&ptr, v.ptr, id.toC(), C.git_otype(t))
if ret < 0 {
return nil, MakeGitError(ret)
}
return allocObject(ptr, v), nil
}
func (v *Repository) Lookup(id *Oid) (*Object, error) {
return v.lookupType(id, ObjectAny)
}
func (v *Repository) LookupTree(id *Oid) (*Tree, error) {
obj, err := v.lookupType(id, ObjectTree)
if err != nil {
return nil, err
}
return obj.AsTree()
}
func (v *Repository) LookupCommit(id *Oid) (*Commit, error) {
obj, err := v.lookupType(id, ObjectCommit)
if err != nil {
return nil, err
}
return obj.AsCommit()
}
func (v *Repository) LookupBlob(id *Oid) (*Blob, error) {
obj, err := v.lookupType(id, ObjectBlob)
if err != nil {
return nil, err
}
return obj.AsBlob()
}
func (v *Repository) LookupTag(id *Oid) (*Tag, error) {
obj, err := v.lookupType(id, ObjectTag)
if err != nil {
return nil, err
}
return obj.AsTag()
}
func (v *Repository) Head() (*Reference, error) {
var ptr *C.git_reference
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ecode := C.git_repository_head(&ptr, v.ptr)
if ecode < 0 {
return nil, MakeGitError(ecode)
}
return newReferenceFromC(ptr, v), nil
}
func (v *Repository) SetHead(refname string) error {
cname := C.CString(refname)
defer C.free(unsafe.Pointer(cname))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ecode := C.git_repository_set_head(v.ptr, cname)
if ecode != 0 {
return MakeGitError(ecode)
}
return nil
}
func (v *Repository) SetHeadDetached(id *Oid) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ecode := C.git_repository_set_head_detached(v.ptr, id.toC())
if ecode != 0 {
return MakeGitError(ecode)
}
return nil
}
func (v *Repository) IsHeadDetached() (bool, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ret := C.git_repository_head_detached(v.ptr)
if ret < 0 {
return false, MakeGitError(ret)
}
return ret != 0, nil
}
func (v *Repository) Walk() (*RevWalk, error) {
var walkPtr *C.git_revwalk
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ecode := C.git_revwalk_new(&walkPtr, v.ptr)
if ecode < 0 {
return nil, MakeGitError(ecode)
}
return revWalkFromC(v, walkPtr), nil
}
func (v *Repository) CreateCommit(
refname string, author, committer *Signature,
message string, tree *Tree, parents ...*Commit) (*Oid, error) {
oid := new(Oid)
var cref *C.char
if refname == "" {
cref = nil
} else {
cref = C.CString(refname)
defer C.free(unsafe.Pointer(cref))
}
cmsg := C.CString(message)
defer C.free(unsafe.Pointer(cmsg))
var cparents []*C.git_commit = nil
var parentsarg **C.git_commit = nil
nparents := len(parents)
if nparents > 0 {
cparents = make([]*C.git_commit, nparents)
for i, v := range parents {
cparents[i] = v.cast_ptr
}
parentsarg = &cparents[0]
}
authorSig, err := author.toC()
if err != nil {
return nil, err
}
defer C.git_signature_free(authorSig)
committerSig, err := committer.toC()
if err != nil {
return nil, err
}
defer C.git_signature_free(committerSig)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ret := C.git_commit_create(
oid.toC(), v.ptr, cref,
authorSig, committerSig,
nil, cmsg, tree.cast_ptr, C.size_t(nparents), parentsarg)
if ret < 0 {
return nil, MakeGitError(ret)
}
return oid, nil
}
func (v *Odb) Free() {
runtime.SetFinalizer(v, nil)
C.git_odb_free(v.ptr)
}
func (v *Refdb) Free() {
runtime.SetFinalizer(v, nil)
C.git_refdb_free(v.ptr)
}
func (v *Repository) Odb() (odb *Odb, err error) {
odb = new(Odb)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if ret := C.git_repository_odb(&odb.ptr, v.ptr); ret < 0 {
return nil, MakeGitError(ret)
}
runtime.SetFinalizer(odb, (*Odb).Free)
return odb, nil
}
func (repo *Repository) Path() string {
return C.GoString(C.git_repository_path(repo.ptr))
}
func (repo *Repository) IsBare() bool {
return C.git_repository_is_bare(repo.ptr) != 0
}
func (repo *Repository) Workdir() string {
return C.GoString(C.git_repository_workdir(repo.ptr))
}
func (repo *Repository) SetWorkdir(workdir string, updateGitlink bool) error {
cstr := C.CString(workdir)
defer C.free(unsafe.Pointer(cstr))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if ret := C.git_repository_set_workdir(repo.ptr, cstr, cbool(updateGitlink)); ret < 0 {
return MakeGitError(ret)
}
return nil
}
func (v *Repository) TreeBuilder() (*TreeBuilder, error) {
bld := new(TreeBuilder)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if ret := C.git_treebuilder_new(&bld.ptr, v.ptr, nil); ret < 0 {
return nil, MakeGitError(ret)
}
runtime.SetFinalizer(bld, (*TreeBuilder).Free)
bld.repo = v
return bld, nil
}
func (v *Repository) TreeBuilderFromTree(tree *Tree) (*TreeBuilder, error) {
bld := new(TreeBuilder)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if ret := C.git_treebuilder_new(&bld.ptr, v.ptr, tree.cast_ptr); ret < 0 {
return nil, MakeGitError(ret)
}
runtime.SetFinalizer(bld, (*TreeBuilder).Free)
bld.repo = v
return bld, nil
}
type RepositoryState int
const (
RepositoryStateNone RepositoryState = C.GIT_REPOSITORY_STATE_NONE
RepositoryStateMerge RepositoryState = C.GIT_REPOSITORY_STATE_MERGE
RepositoryStateRevert RepositoryState = C.GIT_REPOSITORY_STATE_REVERT
RepositoryStateCherrypick RepositoryState = C.GIT_REPOSITORY_STATE_CHERRYPICK
RepositoryStateBisect RepositoryState = C.GIT_REPOSITORY_STATE_BISECT
RepositoryStateRebase RepositoryState = C.GIT_REPOSITORY_STATE_REBASE
RepositoryStateRebaseInteractive RepositoryState = C.GIT_REPOSITORY_STATE_REBASE_INTERACTIVE
RepositoryStateRebaseMerge RepositoryState = C.GIT_REPOSITORY_STATE_REBASE_MERGE
RepositoryStateApplyMailbox RepositoryState = C.GIT_REPOSITORY_STATE_APPLY_MAILBOX
RepositoryStateApplyMailboxOrRebase RepositoryState = C.GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE
)
func (r *Repository) State() RepositoryState {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
return RepositoryState(C.git_repository_state(r.ptr))
}
func (r *Repository) StateCleanup() error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
cErr := C.git_repository_state_cleanup(r.ptr)
if cErr < 0 {
return MakeGitError(cErr)
}
return nil
}
func (r *Repository) AddGitIgnoreRules(rules string) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
crules := C.CString(rules)
defer C.free(unsafe.Pointer(crules))
if ret := C.git_ignore_add_rule(r.ptr, crules); ret < 0 {
return MakeGitError(ret)
}
return nil
}
func (r *Repository) ClearGitIgnoreRules() error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if ret := C.git_ignore_clear_internal_rules(r.ptr); ret < 0 {
return MakeGitError(ret)
}
return nil
}