From 39d825a2a85d839ac7ba2a531947166a108d72d4 Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Mon, 18 Aug 2014 19:42:34 -0400 Subject: [PATCH 01/15] status data types --- status.go | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 status.go diff --git a/status.go b/status.go new file mode 100644 index 0000000..5fecdb3 --- /dev/null +++ b/status.go @@ -0,0 +1,69 @@ +package git + +/* +#include +#include +*/ +import "C" + +import ( + "runtime" +) + +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_NEW + StatusWtDeleted = C.GIT_STATUS_WT_DELETED + StatusWtTypeChange = C.GIT_STATUS_WT_TYPECHANGE + StatusWtRenamed = C.GIT_STATUS_WT_RENAMED + StatusIgnored = C.GIT_STATUS_IGNORED +) + +type StatusList struct { + ptr *C.git_status_list +} + +type StatusEntry struct { + Status Status + HeadToIndex DiffDelta + IndexToWorkdir DiffDelta +} + +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() error { + if statusList.ptr == nil { + return ErrInvalid + } + runtime.SetFinalizer(statusList, nil) + C.git_status_list_free(statusList.ptr) + statusList.ptr = nil + return nil +} + +func statusEntryFromC(statusEntry *C.git_status_entry) StatusEntry { + return StatusEntry { + Status: Status(statusEntry.status), + HeadToIndex: diffDeltaFromC(statusEntry.head_to_index), + IndexToWorkdir: diffDeltaFromC(statusEntry.index_to_workdir), + } +} -- 2.45.2 From 37ccc4c00d22391b994190f59230d283509726d1 Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Mon, 18 Aug 2014 20:04:32 -0400 Subject: [PATCH 02/15] add ByIndex, reorder to match other files --- status.go | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/status.go b/status.go index 5fecdb3..e22f533 100644 --- a/status.go +++ b/status.go @@ -27,16 +27,24 @@ const ( StatusIgnored = C.GIT_STATUS_IGNORED ) -type StatusList struct { - ptr *C.git_status_list -} - type StatusEntry struct { Status Status HeadToIndex DiffDelta IndexToWorkdir DiffDelta } +func statusEntryFromC(statusEntry *C.git_status_entry) StatusEntry { + return StatusEntry { + Status: Status(statusEntry.status), + HeadToIndex: diffDeltaFromC(statusEntry.head_to_index), + IndexToWorkdir: diffDeltaFromC(statusEntry.index_to_workdir), + } +} + +type StatusList struct { + ptr *C.git_status_list +} + func newStatusListFromC(ptr *C.git_status_list) *StatusList { if ptr == nil { return nil @@ -60,10 +68,10 @@ func (statusList *StatusList) Free() error { return nil } -func statusEntryFromC(statusEntry *C.git_status_entry) StatusEntry { - return StatusEntry { - Status: Status(statusEntry.status), - HeadToIndex: diffDeltaFromC(statusEntry.head_to_index), - IndexToWorkdir: diffDeltaFromC(statusEntry.index_to_workdir), +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 } -- 2.45.2 From 05136707453db6eb1e075d2b84cb44ec089a10d1 Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Mon, 18 Aug 2014 20:11:14 -0400 Subject: [PATCH 03/15] add StatusList.EntryCount() --- status.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/status.go b/status.go index e22f533..2baf13d 100644 --- a/status.go +++ b/status.go @@ -75,3 +75,10 @@ func (statusList *StatusList) ByIndex(index int) (StatusEntry, error) { 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 +} -- 2.45.2 From b831ae04aaf3af900fe39a93193aa6404ebf4c29 Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Mon, 18 Aug 2014 20:34:57 -0400 Subject: [PATCH 04/15] add StatusList() to Repository --- repository.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/repository.go b/repository.go index 8cc966c..90d71ff 100644 --- a/repository.go +++ b/repository.go @@ -119,6 +119,26 @@ func (v *Repository) Index() (*Index, error) { return newIndexFromC(ptr), nil } +func (v *Repository) StatusList() (*StatusList, error) { + var ptr *C.git_status_list + var options *C.git_status_options + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_status_init_options(options, C.GIT_STATUS_OPTIONS_VERSION) + if ret < 0 { + return nil, MakeGitError(ret) + } + + ret = C.git_status_list_new(&ptr, v.ptr, options) + if ret < 0 { + return nil, MakeGitError(ret) + } + + return newStatusListFromC(ptr), nil +} + func (v *Repository) lookupType(id *Oid, t ObjectType) (Object, error) { var ptr *C.git_object -- 2.45.2 From f954871968ca6df54aab26d6984cc42bb3904ef2 Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Mon, 18 Aug 2014 22:19:06 -0400 Subject: [PATCH 05/15] start on status tests; fix bug in Repository.StatusList() --- repository.go | 6 +++--- status_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 status_test.go diff --git a/repository.go b/repository.go index 90d71ff..83e1fab 100644 --- a/repository.go +++ b/repository.go @@ -121,17 +121,17 @@ func (v *Repository) Index() (*Index, error) { func (v *Repository) StatusList() (*StatusList, error) { var ptr *C.git_status_list - var options *C.git_status_options + options := C.git_status_options{} runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_status_init_options(options, C.GIT_STATUS_OPTIONS_VERSION) + ret := C.git_status_init_options(&options, C.GIT_STATUS_OPTIONS_VERSION) if ret < 0 { return nil, MakeGitError(ret) } - ret = C.git_status_list_new(&ptr, v.ptr, options) + ret = C.git_status_list_new(&ptr, v.ptr, &options) if ret < 0 { return nil, MakeGitError(ret) } diff --git a/status_test.go b/status_test.go new file mode 100644 index 0000000..0cc9de3 --- /dev/null +++ b/status_test.go @@ -0,0 +1,27 @@ +package git + +import ( + "io/ioutil" + "os" + "path" + "testing" +) + +func TestEntryCount(t *testing.T) { + repo := createTestRepo(t) + defer repo.Free() + defer os.RemoveAll(repo.Workdir()) + + err := ioutil.WriteFile(path.Join(path.Dir(repo.Path()), "hello.txt"), []byte("Hello, World"), 0644) + checkFatal(t, err) + + statusList, err := repo.StatusList() + checkFatal(t, err) + + entryCount, err := statusList.EntryCount() + checkFatal(t, err) + + if entryCount != 1 { + t.Fatal("Incorrect number of status entries: ", entryCount) + } +} -- 2.45.2 From a093e20a8812f2cc26fde6d4bc6ee8c21e782c39 Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Mon, 18 Aug 2014 22:58:53 -0400 Subject: [PATCH 06/15] add status option support --- repository.go | 20 -------------- status.go | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ status_test.go | 2 +- 3 files changed, 76 insertions(+), 21 deletions(-) diff --git a/repository.go b/repository.go index 83e1fab..8cc966c 100644 --- a/repository.go +++ b/repository.go @@ -119,26 +119,6 @@ func (v *Repository) Index() (*Index, error) { return newIndexFromC(ptr), nil } -func (v *Repository) StatusList() (*StatusList, error) { - var ptr *C.git_status_list - options := C.git_status_options{} - - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - ret := C.git_status_init_options(&options, C.GIT_STATUS_OPTIONS_VERSION) - if ret < 0 { - return nil, MakeGitError(ret) - } - - ret = C.git_status_list_new(&ptr, v.ptr, &options) - if ret < 0 { - return nil, MakeGitError(ret) - } - - return newStatusListFromC(ptr), nil -} - func (v *Repository) lookupType(id *Oid, t ObjectType) (Object, error) { var ptr *C.git_object diff --git a/status.go b/status.go index 2baf13d..5f4b7e1 100644 --- a/status.go +++ b/status.go @@ -82,3 +82,78 @@ func (statusList *StatusList) EntryCount() (int, error) { } return int(C.git_status_list_entrycount(statusList.ptr)), nil } + +const ( + StatusOptIncludeUntracked = 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 { + Version int + Show StatusShow + Flags int + 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) + } + } + + ret := C.git_status_list_new(&ptr, v.ptr, copts) + if ret < 0 { + return nil, MakeGitError(ret) + } + return newStatusListFromC(ptr), nil +} diff --git a/status_test.go b/status_test.go index 0cc9de3..3fababe 100644 --- a/status_test.go +++ b/status_test.go @@ -15,7 +15,7 @@ func TestEntryCount(t *testing.T) { err := ioutil.WriteFile(path.Join(path.Dir(repo.Path()), "hello.txt"), []byte("Hello, World"), 0644) checkFatal(t, err) - statusList, err := repo.StatusList() + statusList, err := repo.StatusList(nil) checkFatal(t, err) entryCount, err := statusList.EntryCount() -- 2.45.2 From 8fd7c2c60940300b125c40213c82b26dd38e7a78 Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Mon, 18 Aug 2014 23:12:45 -0400 Subject: [PATCH 07/15] add StatusFile function --- status.go | 13 ++++++++++++- status_test.go | 18 +++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/status.go b/status.go index 5f4b7e1..ab0469f 100644 --- a/status.go +++ b/status.go @@ -20,7 +20,7 @@ const ( StatusIndexRenamed = C.GIT_STATUS_INDEX_RENAMED StatusIndexTypeChange = C.GIT_STATUS_INDEX_TYPECHANGE StatusWtNew = C.GIT_STATUS_WT_NEW - StatusWtModified = 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 @@ -157,3 +157,14 @@ func (v *Repository) StatusList(opts *StatusOptions) (*StatusList, error) { } return newStatusListFromC(ptr), nil } + + +func (v *Repository) StatusFile(path string) (Status, error) { + var statusFlags C.uint + cPath := C.CString(path) + ret := C.git_status_file(&statusFlags, v.ptr, cPath) + if ret < 0 { + return 0, MakeGitError(ret) + } + return Status(statusFlags), nil +} diff --git a/status_test.go b/status_test.go index 3fababe..13b778c 100644 --- a/status_test.go +++ b/status_test.go @@ -7,12 +7,28 @@ import ( "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 TestEntryCount(t *testing.T) { repo := createTestRepo(t) defer repo.Free() defer os.RemoveAll(repo.Workdir()) - err := ioutil.WriteFile(path.Join(path.Dir(repo.Path()), "hello.txt"), []byte("Hello, World"), 0644) + err := ioutil.WriteFile(path.Join(path.Dir(repo.Workdir()), "hello.txt"), []byte("Hello, World"), 0644) checkFatal(t, err) statusList, err := repo.StatusList(nil) -- 2.45.2 From fe1e6b83edfa8456f6ed8eb83eaa6fe57771e875 Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Tue, 19 Aug 2014 08:08:46 -0400 Subject: [PATCH 08/15] comment out issue with entry count --- status_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/status_test.go b/status_test.go index 13b778c..228ee0e 100644 --- a/status_test.go +++ b/status_test.go @@ -38,6 +38,7 @@ func TestEntryCount(t *testing.T) { checkFatal(t, err) if entryCount != 1 { - t.Fatal("Incorrect number of status entries: ", entryCount) + // FIXME: this is 0 even though the same setup above returns the correct status, as does a call to StatusFile here + // t.Fatal("Incorrect number of status entries: ", entryCount) } } -- 2.45.2 From 1cb654e4f2ae536f71773dbe0bd808874b832d9c Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Tue, 19 Aug 2014 08:51:18 -0400 Subject: [PATCH 09/15] add git_status_foreach binding --- status.go | 26 ++++++++++++++++++++++++++ status_test.go | 23 +++++++++++++++++++++++ wrapper.c | 7 ++++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/status.go b/status.go index ab0469f..4523cb8 100644 --- a/status.go +++ b/status.go @@ -3,11 +3,14 @@ package git /* #include #include + +int _go_git_status_foreach(git_repository *repo, void *data); */ import "C" import ( "runtime" + "unsafe" ) type Status int @@ -168,3 +171,26 @@ func (v *Repository) StatusFile(path string) (Status, error) { } return Status(statusFlags), nil } + +type StatusCallback func(path string, status Status) int + +//export fileStatusForeach +func fileStatusForeach(_path *C.char, _flags C.uint, _payload unsafe.Pointer) C.int { + path := C.GoString(_path) + flags := Status(_flags) + + cb := (*StatusCallback)(_payload) + return C.int((*cb)(path, flags)) +} + +func (v *Repository) StatusForeach(callback StatusCallback) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C._go_git_status_foreach(v.ptr, unsafe.Pointer(&callback)) + + if ret < 0 { + return MakeGitError(ret) + } + return nil +} diff --git a/status_test.go b/status_test.go index 228ee0e..a0ff1d3 100644 --- a/status_test.go +++ b/status_test.go @@ -23,6 +23,29 @@ func TestStatusFile(t *testing.T) { } } +func TestStatusForeach(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) + + statusFound := false + err = repo.StatusForeach(func (path string, statusFlags Status) int { + if path == "hello.txt" && statusFlags & StatusWtNew != 0 { + statusFound = true + } + + return 0 + }); + checkFatal(t, err) + + if !statusFound { + t.Fatal("Status callback not called with the new file") + } +} + func TestEntryCount(t *testing.T) { repo := createTestRepo(t) defer repo.Free() diff --git a/wrapper.c b/wrapper.c index 2fd8fb7..09dba46 100644 --- a/wrapper.c +++ b/wrapper.c @@ -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; @@ -105,4 +105,9 @@ int _go_git_blob_create_fromchunks(git_oid *id, return git_blob_create_fromchunks(id, repo, hintpath, _go_blob_chunk_cb, payload); } +int _go_git_status_foreach(git_repository *repo, void *data) +{ + return git_status_foreach(repo, (git_status_cb)fileStatusForeach, data); +} + /* EOF */ -- 2.45.2 From c8529e79da002e6c816c0df895edc7ce7a543a37 Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Mon, 25 Aug 2014 17:41:35 -0400 Subject: [PATCH 10/15] don't return anything from StatusList.Free --- status.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/status.go b/status.go index 4523cb8..efe6eb0 100644 --- a/status.go +++ b/status.go @@ -61,14 +61,13 @@ func newStatusListFromC(ptr *C.git_status_list) *StatusList { return statusList } -func (statusList *StatusList) Free() error { +func (statusList *StatusList) Free() { if statusList.ptr == nil { - return ErrInvalid + return } runtime.SetFinalizer(statusList, nil) C.git_status_list_free(statusList.ptr) statusList.ptr = nil - return nil } func (statusList *StatusList) ByIndex(index int) (StatusEntry, error) { -- 2.45.2 From 33ae83f4d9b78501549fc880c1e2dd055466808c Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Mon, 25 Aug 2014 18:15:36 -0400 Subject: [PATCH 11/15] remove status_foreach binding --- status.go | 26 -------------------------- status_test.go | 23 ----------------------- wrapper.c | 5 ----- 3 files changed, 54 deletions(-) diff --git a/status.go b/status.go index efe6eb0..644b13e 100644 --- a/status.go +++ b/status.go @@ -3,14 +3,11 @@ package git /* #include #include - -int _go_git_status_foreach(git_repository *repo, void *data); */ import "C" import ( "runtime" - "unsafe" ) type Status int @@ -170,26 +167,3 @@ func (v *Repository) StatusFile(path string) (Status, error) { } return Status(statusFlags), nil } - -type StatusCallback func(path string, status Status) int - -//export fileStatusForeach -func fileStatusForeach(_path *C.char, _flags C.uint, _payload unsafe.Pointer) C.int { - path := C.GoString(_path) - flags := Status(_flags) - - cb := (*StatusCallback)(_payload) - return C.int((*cb)(path, flags)) -} - -func (v *Repository) StatusForeach(callback StatusCallback) error { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - ret := C._go_git_status_foreach(v.ptr, unsafe.Pointer(&callback)) - - if ret < 0 { - return MakeGitError(ret) - } - return nil -} diff --git a/status_test.go b/status_test.go index a0ff1d3..228ee0e 100644 --- a/status_test.go +++ b/status_test.go @@ -23,29 +23,6 @@ func TestStatusFile(t *testing.T) { } } -func TestStatusForeach(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) - - statusFound := false - err = repo.StatusForeach(func (path string, statusFlags Status) int { - if path == "hello.txt" && statusFlags & StatusWtNew != 0 { - statusFound = true - } - - return 0 - }); - checkFatal(t, err) - - if !statusFound { - t.Fatal("Status callback not called with the new file") - } -} - func TestEntryCount(t *testing.T) { repo := createTestRepo(t) defer repo.Free() diff --git a/wrapper.c b/wrapper.c index 09dba46..45c4358 100644 --- a/wrapper.c +++ b/wrapper.c @@ -105,9 +105,4 @@ int _go_git_blob_create_fromchunks(git_oid *id, return git_blob_create_fromchunks(id, repo, hintpath, _go_blob_chunk_cb, payload); } -int _go_git_status_foreach(git_repository *repo, void *data) -{ - return git_status_foreach(repo, (git_status_cb)fileStatusForeach, data); -} - /* EOF */ -- 2.45.2 From 0059b26255190153337c3ce43c675606a044c1c1 Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Mon, 25 Aug 2014 18:20:54 -0400 Subject: [PATCH 12/15] add thread locking to status api --- status.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/status.go b/status.go index 644b13e..f69cd14 100644 --- a/status.go +++ b/status.go @@ -8,6 +8,7 @@ import "C" import ( "runtime" + "unsafe" ) type Status int @@ -150,6 +151,9 @@ func (v *Repository) StatusList(opts *StatusOptions) (*StatusList, error) { } } + runtime.LockOSThread() + defer runtime.UnlockOSThread() + ret := C.git_status_list_new(&ptr, v.ptr, copts) if ret < 0 { return nil, MakeGitError(ret) @@ -161,6 +165,11 @@ func (v *Repository) StatusList(opts *StatusOptions) (*StatusList, error) { 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) -- 2.45.2 From 80997c6fa55da6a25c30dccab379e808d9f07b28 Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Mon, 25 Aug 2014 23:18:00 -0400 Subject: [PATCH 13/15] fix status list to handle null head_to_index in entries --- status.go | 16 ++++++++++++++-- status_test.go | 22 ++++++++++++++++++---- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/status.go b/status.go index f69cd14..09a06c4 100644 --- a/status.go +++ b/status.go @@ -35,10 +35,21 @@ type StatusEntry struct { } 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: diffDeltaFromC(statusEntry.head_to_index), - IndexToWorkdir: diffDeltaFromC(statusEntry.index_to_workdir), + HeadToIndex: headToIndex, + IndexToWorkdir: indexToWorkdir, } } @@ -158,6 +169,7 @@ func (v *Repository) StatusList(opts *StatusOptions) (*StatusList, error) { if ret < 0 { return nil, MakeGitError(ret) } + return newStatusListFromC(ptr), nil } diff --git a/status_test.go b/status_test.go index 228ee0e..4be4824 100644 --- a/status_test.go +++ b/status_test.go @@ -23,22 +23,36 @@ func TestStatusFile(t *testing.T) { } } -func TestEntryCount(t *testing.T) { +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) - statusList, err := repo.StatusList(nil) + 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 { - // FIXME: this is 0 even though the same setup above returns the correct status, as does a call to StatusFile here - // t.Fatal("Incorrect number of status entries: ", entryCount) + 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) } } -- 2.45.2 From 1520978dcda4b9be7f68ec68d4785c976b677836 Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Thu, 4 Sep 2014 10:15:13 -0400 Subject: [PATCH 14/15] give status option flags their own type --- status.go | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/status.go b/status.go index 09a06c4..d67f297 100644 --- a/status.go +++ b/status.go @@ -94,21 +94,23 @@ func (statusList *StatusList) EntryCount() (int, error) { return int(C.git_status_list_entrycount(statusList.ptr)), nil } +type StatusOpt int + const ( - StatusOptIncludeUntracked = 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 + 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 @@ -122,7 +124,7 @@ const ( type StatusOptions struct { Version int Show StatusShow - Flags int + Flags StatusOpt Pathspec []string } -- 2.45.2 From d4734a41d5647a929c6dbbafbbec369002600de8 Mon Sep 17 00:00:00 2001 From: Ben Navetta Date: Thu, 4 Sep 2014 10:17:31 -0400 Subject: [PATCH 15/15] remove unused status version field --- status.go | 1 - 1 file changed, 1 deletion(-) diff --git a/status.go b/status.go index d67f297..a95c302 100644 --- a/status.go +++ b/status.go @@ -122,7 +122,6 @@ const ( ) type StatusOptions struct { - Version int Show StatusShow Flags StatusOpt Pathspec []string -- 2.45.2