package git /* #include */ import "C" import ( "errors" "runtime" "unsafe" ) type Status int const ( StatusCurrent Status = C.GIT_STATUS_CURRENT StatusIndexNew Status = C.GIT_STATUS_INDEX_NEW StatusIndexModified Status = C.GIT_STATUS_INDEX_MODIFIED StatusIndexDeleted Status = C.GIT_STATUS_INDEX_DELETED StatusIndexRenamed Status = C.GIT_STATUS_INDEX_RENAMED StatusIndexTypeChange Status = C.GIT_STATUS_INDEX_TYPECHANGE StatusWtNew Status = C.GIT_STATUS_WT_NEW StatusWtModified Status = C.GIT_STATUS_WT_MODIFIED StatusWtDeleted Status = C.GIT_STATUS_WT_DELETED StatusWtTypeChange Status = C.GIT_STATUS_WT_TYPECHANGE StatusWtRenamed Status = C.GIT_STATUS_WT_RENAMED StatusIgnored Status = C.GIT_STATUS_IGNORED StatusConflicted Status = C.GIT_STATUS_CONFLICTED ) 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 r *Repository } func newStatusListFromC(ptr *C.git_status_list, r *Repository) *StatusList { if ptr == nil { return nil } statusList := &StatusList{ ptr: ptr, r: r, } 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)) if ptr == nil { return StatusEntry{}, errors.New("index out of Bounds") } entry := statusEntryFromC(ptr) runtime.KeepAlive(statusList) return entry, nil } func (statusList *StatusList) EntryCount() (int, error) { if statusList.ptr == nil { return -1, ErrInvalid } ret := int(C.git_status_list_entrycount(statusList.ptr)) runtime.KeepAlive(statusList) return ret, nil } type StatusOpt int const ( StatusOptIncludeUntracked StatusOpt = C.GIT_STATUS_OPT_INCLUDE_UNTRACKED StatusOptIncludeIgnored StatusOpt = C.GIT_STATUS_OPT_INCLUDE_IGNORED StatusOptIncludeUnmodified StatusOpt = C.GIT_STATUS_OPT_INCLUDE_UNMODIFIED StatusOptExcludeSubmodules StatusOpt = C.GIT_STATUS_OPT_EXCLUDE_SUBMODULES StatusOptRecurseUntrackedDirs StatusOpt = C.GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS StatusOptDisablePathspecMatch StatusOpt = C.GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH StatusOptRecurseIgnoredDirs StatusOpt = C.GIT_STATUS_OPT_RECURSE_IGNORED_DIRS StatusOptRenamesHeadToIndex StatusOpt = C.GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX StatusOptRenamesIndexToWorkdir StatusOpt = C.GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR StatusOptSortCaseSensitively StatusOpt = C.GIT_STATUS_OPT_SORT_CASE_SENSITIVELY StatusOptSortCaseInsensitively StatusOpt = C.GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY StatusOptRenamesFromRewrites StatusOpt = C.GIT_STATUS_OPT_RENAMES_FROM_REWRITES StatusOptNoRefresh StatusOpt = C.GIT_STATUS_OPT_NO_REFRESH StatusOptUpdateIndex StatusOpt = C.GIT_STATUS_OPT_UPDATE_INDEX ) type StatusShow int const ( StatusShowIndexAndWorkdir StatusShow = C.GIT_STATUS_SHOW_INDEX_AND_WORKDIR StatusShowIndexOnly StatusShow = C.GIT_STATUS_SHOW_INDEX_ONLY StatusShowWorkdirOnly StatusShow = C.GIT_STATUS_SHOW_WORKDIR_ONLY ) type StatusOptions struct { Show StatusShow Flags StatusOpt Pathspec []string } func (v *Repository) StatusList(opts *StatusOptions) (*StatusList, error) { var ptr *C.git_status_list var copts *C.git_status_options if opts != 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, } } else { copts = &C.git_status_options{} ret := C.git_status_options_init(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, v), 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) runtime.KeepAlive(v) if ret < 0 { return 0, MakeGitError(ret) } return Status(statusFlags), nil }