commit
5eda8d6935
|
@ -0,0 +1,191 @@
|
|||
package git
|
||||
|
||||
/*
|
||||
#include <git2.h>
|
||||
#include <git2/errors.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type Status int
|
||||
|
||||
const (
|
||||
StatusCurrent Status = C.GIT_STATUS_CURRENT
|
||||
StatusIndexNew = C.GIT_STATUS_INDEX_NEW
|
||||
StatusIndexModified = C.GIT_STATUS_INDEX_MODIFIED
|
||||
StatusIndexDeleted = C.GIT_STATUS_INDEX_DELETED
|
||||
StatusIndexRenamed = C.GIT_STATUS_INDEX_RENAMED
|
||||
StatusIndexTypeChange = C.GIT_STATUS_INDEX_TYPECHANGE
|
||||
StatusWtNew = C.GIT_STATUS_WT_NEW
|
||||
StatusWtModified = C.GIT_STATUS_WT_MODIFIED
|
||||
StatusWtDeleted = C.GIT_STATUS_WT_DELETED
|
||||
StatusWtTypeChange = C.GIT_STATUS_WT_TYPECHANGE
|
||||
StatusWtRenamed = C.GIT_STATUS_WT_RENAMED
|
||||
StatusIgnored = C.GIT_STATUS_IGNORED
|
||||
)
|
||||
|
||||
type StatusEntry struct {
|
||||
Status Status
|
||||
HeadToIndex DiffDelta
|
||||
IndexToWorkdir DiffDelta
|
||||
}
|
||||
|
||||
func statusEntryFromC(statusEntry *C.git_status_entry) StatusEntry {
|
||||
var headToIndex DiffDelta = DiffDelta{}
|
||||
var indexToWorkdir DiffDelta = DiffDelta{}
|
||||
|
||||
// Based on the libgit2 status example, head_to_index can be null in some cases
|
||||
if statusEntry.head_to_index != nil {
|
||||
headToIndex = diffDeltaFromC(statusEntry.head_to_index)
|
||||
}
|
||||
if statusEntry.index_to_workdir != nil {
|
||||
indexToWorkdir = diffDeltaFromC(statusEntry.index_to_workdir)
|
||||
}
|
||||
|
||||
return StatusEntry {
|
||||
Status: Status(statusEntry.status),
|
||||
HeadToIndex: headToIndex,
|
||||
IndexToWorkdir: indexToWorkdir,
|
||||
}
|
||||
}
|
||||
|
||||
type StatusList struct {
|
||||
ptr *C.git_status_list
|
||||
}
|
||||
|
||||
func newStatusListFromC(ptr *C.git_status_list) *StatusList {
|
||||
if ptr == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
statusList := &StatusList{
|
||||
ptr: ptr,
|
||||
}
|
||||
|
||||
runtime.SetFinalizer(statusList, (*StatusList).Free)
|
||||
return statusList
|
||||
}
|
||||
|
||||
func (statusList *StatusList) Free() {
|
||||
if statusList.ptr == nil {
|
||||
return
|
||||
}
|
||||
runtime.SetFinalizer(statusList, nil)
|
||||
C.git_status_list_free(statusList.ptr)
|
||||
statusList.ptr = nil
|
||||
}
|
||||
|
||||
func (statusList *StatusList) ByIndex(index int) (StatusEntry, error) {
|
||||
if statusList.ptr == nil {
|
||||
return StatusEntry{}, ErrInvalid
|
||||
}
|
||||
ptr := C.git_status_byindex(statusList.ptr, C.size_t(index))
|
||||
return statusEntryFromC(ptr), nil
|
||||
}
|
||||
|
||||
func (statusList *StatusList) EntryCount() (int, error) {
|
||||
if statusList.ptr == nil {
|
||||
return -1, ErrInvalid
|
||||
}
|
||||
return int(C.git_status_list_entrycount(statusList.ptr)), nil
|
||||
}
|
||||
|
||||
type StatusOpt int
|
||||
|
||||
const (
|
||||
StatusOptIncludeUntracked StatusOpt = C.GIT_STATUS_OPT_INCLUDE_UNTRACKED
|
||||
StatusOptIncludeIgnored = C.GIT_STATUS_OPT_INCLUDE_IGNORED
|
||||
StatusOptIncludeUnmodified = C.GIT_STATUS_OPT_INCLUDE_UNMODIFIED
|
||||
StatusOptExcludeSubmodules = C.GIT_STATUS_OPT_EXCLUDE_SUBMODULES
|
||||
StatusOptRecurseUntrackedDirs = C.GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS
|
||||
StatusOptDisablePathspecMatch = C.GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH
|
||||
StatusOptRecurseIgnoredDirs = C.GIT_STATUS_OPT_RECURSE_IGNORED_DIRS
|
||||
StatusOptRenamesHeadToIndex = C.GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX
|
||||
StatusOptRenamesIndexToWorkdir = C.GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR
|
||||
StatusOptSortCaseSensitively = C.GIT_STATUS_OPT_SORT_CASE_SENSITIVELY
|
||||
StatusOptSortCaseInsensitively = C.GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY
|
||||
StatusOptRenamesFromRewrites = C.GIT_STATUS_OPT_RENAMES_FROM_REWRITES
|
||||
StatusOptNoRefresh = C.GIT_STATUS_OPT_NO_REFRESH
|
||||
StatusOptUpdateIndex = C.GIT_STATUS_OPT_UPDATE_INDEX
|
||||
)
|
||||
|
||||
type StatusShow int
|
||||
|
||||
const (
|
||||
StatusShowIndexAndWorkdir StatusShow = C.GIT_STATUS_SHOW_INDEX_AND_WORKDIR
|
||||
StatusShowIndexOnly = C.GIT_STATUS_SHOW_INDEX_ONLY
|
||||
StatusShowWorkdirOnly = C.GIT_STATUS_SHOW_WORKDIR_ONLY
|
||||
)
|
||||
|
||||
type StatusOptions struct {
|
||||
Show StatusShow
|
||||
Flags StatusOpt
|
||||
Pathspec []string
|
||||
}
|
||||
|
||||
func (opts *StatusOptions) toC() *C.git_status_options {
|
||||
if opts == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
cpathspec := C.git_strarray{}
|
||||
if opts.Pathspec != nil {
|
||||
cpathspec.count = C.size_t(len(opts.Pathspec))
|
||||
cpathspec.strings = makeCStringsFromStrings(opts.Pathspec)
|
||||
defer freeStrarray(&cpathspec)
|
||||
}
|
||||
|
||||
copts := &C.git_status_options{
|
||||
version: C.GIT_STATUS_OPTIONS_VERSION,
|
||||
show: C.git_status_show_t(opts.Show),
|
||||
flags: C.uint(opts.Flags),
|
||||
pathspec: cpathspec,
|
||||
}
|
||||
|
||||
return copts
|
||||
}
|
||||
|
||||
func (v *Repository) StatusList(opts *StatusOptions) (*StatusList, error) {
|
||||
var ptr *C.git_status_list
|
||||
var copts *C.git_status_options
|
||||
|
||||
if opts != nil {
|
||||
copts = opts.toC()
|
||||
} else {
|
||||
copts = &C.git_status_options{}
|
||||
ret := C.git_status_init_options(copts, C.GIT_STATUS_OPTIONS_VERSION)
|
||||
if ret < 0 {
|
||||
return nil, MakeGitError(ret)
|
||||
}
|
||||
}
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
ret := C.git_status_list_new(&ptr, v.ptr, copts)
|
||||
if ret < 0 {
|
||||
return nil, MakeGitError(ret)
|
||||
}
|
||||
|
||||
return newStatusListFromC(ptr), nil
|
||||
}
|
||||
|
||||
|
||||
func (v *Repository) StatusFile(path string) (Status, error) {
|
||||
var statusFlags C.uint
|
||||
cPath := C.CString(path)
|
||||
defer C.free(unsafe.Pointer(cPath))
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
ret := C.git_status_file(&statusFlags, v.ptr, cPath)
|
||||
if ret < 0 {
|
||||
return 0, MakeGitError(ret)
|
||||
}
|
||||
return Status(statusFlags), nil
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package git
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStatusFile(t *testing.T) {
|
||||
repo := createTestRepo(t)
|
||||
defer repo.Free()
|
||||
defer os.RemoveAll(repo.Workdir())
|
||||
|
||||
err := ioutil.WriteFile(path.Join(path.Dir(repo.Workdir()), "hello.txt"), []byte("Hello, World"), 0644)
|
||||
checkFatal(t, err)
|
||||
|
||||
status, err := repo.StatusFile("hello.txt")
|
||||
checkFatal(t, err)
|
||||
|
||||
if status != StatusWtNew {
|
||||
t.Fatal("Incorrect status flags: ", status)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatusList(t *testing.T) {
|
||||
repo := createTestRepo(t)
|
||||
// This commits the test repo README, so it doesn't show up in the status list and there's a head to compare to
|
||||
seedTestRepo(t, repo)
|
||||
defer repo.Free()
|
||||
defer os.RemoveAll(repo.Workdir())
|
||||
|
||||
err := ioutil.WriteFile(path.Join(path.Dir(repo.Workdir()), "hello.txt"), []byte("Hello, World"), 0644)
|
||||
checkFatal(t, err)
|
||||
|
||||
opts := &StatusOptions{}
|
||||
opts.Show = StatusShowIndexAndWorkdir
|
||||
opts.Flags = StatusOptIncludeUntracked | StatusOptRenamesHeadToIndex | StatusOptSortCaseSensitively
|
||||
|
||||
statusList, err := repo.StatusList(opts)
|
||||
checkFatal(t, err)
|
||||
|
||||
entryCount, err := statusList.EntryCount()
|
||||
checkFatal(t, err)
|
||||
|
||||
if entryCount != 1 {
|
||||
t.Fatal("Incorrect number of status entries: ", entryCount)
|
||||
}
|
||||
|
||||
entry, err := statusList.ByIndex(0)
|
||||
checkFatal(t, err)
|
||||
if entry.Status != StatusWtNew {
|
||||
t.Fatal("Incorrect status flags: ", entry.Status)
|
||||
}
|
||||
if entry.IndexToWorkdir.NewFile.Path != "hello.txt" {
|
||||
t.Fatal("Incorrect entry path: ", entry.IndexToWorkdir.NewFile.Path)
|
||||
}
|
||||
}
|
|
@ -45,7 +45,7 @@ void _go_git_refdb_backend_free(git_refdb_backend *backend)
|
|||
|
||||
int _go_git_diff_foreach(git_diff *diff, int eachFile, int eachHunk, int eachLine, void *payload)
|
||||
{
|
||||
git_diff_file_cb fcb = NULL;
|
||||
git_diff_file_cb fcb = NULL;
|
||||
git_diff_hunk_cb hcb = NULL;
|
||||
git_diff_line_cb lcb = NULL;
|
||||
|
||||
|
|
Loading…
Reference in New Issue