Merge pull request #321 from netnose/checkout-callbacks
Checkout callbacks
diff --git a/checkout.go b/checkout.go
index a2e312b..f5822c9 100644
--- a/checkout.go
+++ b/checkout.go
@@ -2,6 +2,8 @@
/*
#include <git2.h>
+
+extern void _go_git_populate_checkout_cb(git_checkout_options *opts);
*/
import "C"
import (
@@ -10,9 +12,18 @@
"unsafe"
)
+type CheckoutNotifyType uint
type CheckoutStrategy uint
const (
+ CheckoutNotifyNone CheckoutNotifyType = C.GIT_CHECKOUT_NOTIFY_NONE
+ CheckoutNotifyConflict CheckoutNotifyType = C.GIT_CHECKOUT_NOTIFY_CONFLICT
+ CheckoutNotifyDirty CheckoutNotifyType = C.GIT_CHECKOUT_NOTIFY_DIRTY
+ CheckoutNotifyUpdated CheckoutNotifyType = C.GIT_CHECKOUT_NOTIFY_UPDATED
+ CheckoutNotifyUntracked CheckoutNotifyType = C.GIT_CHECKOUT_NOTIFY_UNTRACKED
+ CheckoutNotifyIgnored CheckoutNotifyType = C.GIT_CHECKOUT_NOTIFY_IGNORED
+ CheckoutNotifyAll CheckoutNotifyType = C.GIT_CHECKOUT_NOTIFY_ALL
+
CheckoutNone CheckoutStrategy = C.GIT_CHECKOUT_NONE // Dry run, no actual updates
CheckoutSafe CheckoutStrategy = C.GIT_CHECKOUT_SAFE // Allow safe updates that cannot overwrite uncommitted data
CheckoutForce CheckoutStrategy = C.GIT_CHECKOUT_FORCE // Allow all updates to force working directory to look like index
@@ -37,15 +48,21 @@
CheckoutUpdateSubmodulesIfChanged CheckoutStrategy = C.GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED // Recursively checkout submodules if HEAD moved in super repo (NOT IMPLEMENTED)
)
+type CheckoutNotifyCallback func(why CheckoutNotifyType, path string, baseline, target, workdir DiffFile) ErrorCode
+type CheckoutProgressCallback func(path string, completed, total uint) ErrorCode
+
type CheckoutOpts struct {
- Strategy CheckoutStrategy // Default will be a dry run
- DisableFilters bool // Don't apply filters like CRLF conversion
- DirMode os.FileMode // Default is 0755
- FileMode os.FileMode // Default is 0644 or 0755 as dictated by blob
- FileOpenFlags int // Default is O_CREAT | O_TRUNC | O_WRONLY
- TargetDirectory string // Alternative checkout path to workdir
- Paths []string
- Baseline *Tree
+ Strategy CheckoutStrategy // Default will be a dry run
+ DisableFilters bool // Don't apply filters like CRLF conversion
+ DirMode os.FileMode // Default is 0755
+ FileMode os.FileMode // Default is 0644 or 0755 as dictated by blob
+ FileOpenFlags int // Default is O_CREAT | O_TRUNC | O_WRONLY
+ NotifyFlags CheckoutNotifyType // Default will be none
+ NotifyCallback CheckoutNotifyCallback
+ ProgressCallback CheckoutProgressCallback
+ TargetDirectory string // Alternative checkout path to workdir
+ Paths []string
+ Baseline *Tree
}
func checkoutOptionsFromC(c *C.git_checkout_options) CheckoutOpts {
@@ -55,6 +72,13 @@
opts.DirMode = os.FileMode(c.dir_mode)
opts.FileMode = os.FileMode(c.file_mode)
opts.FileOpenFlags = int(c.file_open_flags)
+ opts.NotifyFlags = CheckoutNotifyType(c.notify_flags)
+ if c.notify_payload != nil {
+ opts.NotifyCallback = pointerHandles.Get(c.notify_payload).(*CheckoutOpts).NotifyCallback
+ }
+ if c.progress_payload != nil {
+ opts.ProgressCallback = pointerHandles.Get(c.progress_payload).(*CheckoutOpts).ProgressCallback
+ }
if c.target_directory != nil {
opts.TargetDirectory = C.GoString(c.target_directory)
}
@@ -70,6 +94,38 @@
return &c
}
+//export checkoutNotifyCallback
+func checkoutNotifyCallback(why C.git_checkout_notify_t, cpath *C.char, cbaseline, ctarget, cworkdir, data unsafe.Pointer) int {
+ if data == nil {
+ return 0
+ }
+ path := C.GoString(cpath)
+ var baseline, target, workdir DiffFile
+ if cbaseline != nil {
+ baseline = diffFileFromC((*C.git_diff_file)(cbaseline))
+ }
+ if ctarget != nil {
+ target = diffFileFromC((*C.git_diff_file)(ctarget))
+ }
+ if cworkdir != nil {
+ workdir = diffFileFromC((*C.git_diff_file)(cworkdir))
+ }
+ opts := pointerHandles.Get(data).(*CheckoutOpts)
+ if opts.NotifyCallback == nil {
+ return 0
+ }
+ return int(opts.NotifyCallback(CheckoutNotifyType(why), path, baseline, target, workdir))
+}
+
+//export checkoutProgressCallback
+func checkoutProgressCallback(path *C.char, completed_steps, total_steps C.size_t, data unsafe.Pointer) int {
+ opts := pointerHandles.Get(data).(*CheckoutOpts)
+ if opts.ProgressCallback == nil {
+ return 0
+ }
+ return int(opts.ProgressCallback(C.GoString(path), uint(completed_steps), uint(total_steps)))
+}
+
// Convert the CheckoutOpts struct to the corresponding
// C-struct. Returns a pointer to ptr, or nil if opts is nil, in order
// to help with what to pass.
@@ -83,6 +139,17 @@
ptr.disable_filters = cbool(opts.DisableFilters)
ptr.dir_mode = C.uint(opts.DirMode.Perm())
ptr.file_mode = C.uint(opts.FileMode.Perm())
+ ptr.notify_flags = C.uint(opts.NotifyFlags)
+ if opts.NotifyCallback != nil || opts.ProgressCallback != nil {
+ C._go_git_populate_checkout_cb(ptr)
+ }
+ payload := pointerHandles.Track(opts)
+ if opts.NotifyCallback != nil {
+ ptr.notify_payload = payload
+ }
+ if opts.ProgressCallback != nil {
+ ptr.progress_payload = payload
+ }
if opts.TargetDirectory != "" {
ptr.target_directory = C.CString(opts.TargetDirectory)
}
@@ -106,6 +173,9 @@
if ptr.paths.count > 0 {
freeStrarray(&ptr.paths)
}
+ if ptr.notify_payload != nil {
+ pointerHandles.Untrack(ptr.notify_payload)
+ }
}
// Updates files in the index and the working tree to match the content of
diff --git a/clone.go b/clone.go
index e80d14d..1ff5124 100644
--- a/clone.go
+++ b/clone.go
@@ -41,7 +41,6 @@
var ptr *C.git_repository
ret := C.git_clone(&ptr, curl, cpath, copts)
- freeCheckoutOpts(&copts.checkout_opts)
if ret < 0 {
return nil, MakeGitError(ret)
diff --git a/wrapper.c b/wrapper.c
index a0688c0..f4b4ecc 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -10,6 +10,12 @@
opts->remote_cb = (git_remote_create_cb)remoteCreateCallback;
}
+void _go_git_populate_checkout_cb(git_checkout_options *opts)
+{
+ opts->notify_cb = (git_checkout_notify_cb)checkoutNotifyCallback;
+ opts->progress_cb = (git_checkout_progress_cb)checkoutProgressCallback;
+}
+
int _go_git_visit_submodule(git_repository *repo, void *fct)
{
return git_submodule_foreach(repo, (gogit_submodule_cbk)&SubmoduleVisitor, fct);