From 278dc9ac4fe40b37c68ebc3013467255ab1f832f Mon Sep 17 00:00:00 2001 From: Mirko Nosenzo Date: Sun, 29 May 2016 13:33:53 +0200 Subject: [PATCH 1/6] Checkout Callbacks - Added CheckoutNotifyType mapping git_checkout_notify_t - Added CheckoutOpts.NotifyFlags of type CheckoutNotifyType - Added CheckoutNotifyCallback mapping git_checkout_notify_cb - Added CheckoutProgressCallback mapping git_checkout_progress_cb --- checkout.go | 81 +++++++++++++++++++++++++++++++++++++++++++++++------ wrapper.c | 6 ++++ 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/checkout.go b/checkout.go index a2e312b..5a61b54 100644 --- a/checkout.go +++ b/checkout.go @@ -2,6 +2,8 @@ package git /* #include + +extern void _go_git_populate_checkout_cb(git_checkout_options *opts); */ import "C" import ( @@ -10,9 +12,18 @@ import ( "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 @@ const ( 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,9 @@ func checkoutOptionsFromC(c *C.git_checkout_options) CheckoutOpts { 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) + opts.NotifyCallback = pointerHandles.Get(c.notify_payload).(CheckoutOpts).NotifyCallback + opts.ProgressCallback = pointerHandles.Get(c.progress_payload).(CheckoutOpts).ProgressCallback if c.target_directory != nil { opts.TargetDirectory = C.GoString(c.target_directory) } @@ -70,6 +90,35 @@ func (opts *CheckoutOpts) toC() *C.git_checkout_options { return &c } +//export checkoutNotifyCallback +func checkoutNotifyCallback(why C.git_checkout_notify_t, cpath *C.char, cbaseline, ctarget, cworkdir, data unsafe.Pointer) int { + 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 +132,16 @@ func populateCheckoutOpts(ptr *C.git_checkout_options, opts *CheckoutOpts) *C.gi 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) + } + if opts.NotifyCallback != nil { + ptr.notify_payload = pointerHandles.Track(*opts) + } + if opts.ProgressCallback != nil { + ptr.progress_payload = pointerHandles.Track(*opts) + } if opts.TargetDirectory != "" { ptr.target_directory = C.CString(opts.TargetDirectory) } @@ -106,6 +165,12 @@ func freeCheckoutOpts(ptr *C.git_checkout_options) { if ptr.paths.count > 0 { freeStrarray(&ptr.paths) } + if ptr.notify_payload != nil { + pointerHandles.Untrack(ptr.notify_payload) + } + if ptr.progress_payload != nil { + pointerHandles.Untrack(ptr.progress_payload) + } } // Updates files in the index and the working tree to match the content of diff --git a/wrapper.c b/wrapper.c index a0688c0..f4b4ecc 100644 --- a/wrapper.c +++ b/wrapper.c @@ -10,6 +10,12 @@ void _go_git_populate_remote_cb(git_clone_options *opts) 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); -- 2.45.2 From db6f44c71ce60777f5ad6c839f626370abf58799 Mon Sep 17 00:00:00 2001 From: Mirko Nosenzo Date: Sun, 29 May 2016 15:14:16 +0200 Subject: [PATCH 2/6] Checkout Callbacks Payload Check Checking payloads before using them --- checkout.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/checkout.go b/checkout.go index 5a61b54..ba411ff 100644 --- a/checkout.go +++ b/checkout.go @@ -73,8 +73,12 @@ func checkoutOptionsFromC(c *C.git_checkout_options) CheckoutOpts { opts.FileMode = os.FileMode(c.file_mode) opts.FileOpenFlags = int(c.file_open_flags) opts.NotifyFlags = CheckoutNotifyType(c.notify_flags) - opts.NotifyCallback = pointerHandles.Get(c.notify_payload).(CheckoutOpts).NotifyCallback - opts.ProgressCallback = pointerHandles.Get(c.progress_payload).(CheckoutOpts).ProgressCallback + 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) } -- 2.45.2 From 18802c24e363d7f4982af86a3e9be437cb8585b2 Mon Sep 17 00:00:00 2001 From: Mirko Nosenzo Date: Sun, 29 May 2016 15:27:48 +0200 Subject: [PATCH 3/6] Checkout Callbacks Payload Check in Callback Functions Checking payloads in callback functions --- checkout.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/checkout.go b/checkout.go index ba411ff..7377d51 100644 --- a/checkout.go +++ b/checkout.go @@ -96,6 +96,9 @@ func (opts *CheckoutOpts) toC() *C.git_checkout_options { //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 { @@ -116,6 +119,9 @@ func checkoutNotifyCallback(why C.git_checkout_notify_t, cpath *C.char, cbaselin //export checkoutProgressCallback func checkoutProgressCallback(path *C.char, completed_steps, total_steps C.size_t, data unsafe.Pointer) int { + if data == nil { + return 0 + } opts := pointerHandles.Get(data).(CheckoutOpts) if opts.ProgressCallback == nil { return 0 -- 2.45.2 From 6fa4c8ea15887c9a8fc96e9d052112a4ef5170cd Mon Sep 17 00:00:00 2001 From: Mirko Nosenzo Date: Sat, 25 Jun 2016 11:30:35 +0200 Subject: [PATCH 4/6] Checkout Payload Pointer Fix - Tracking pointer once - Tracking pointer and not struct --- checkout.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/checkout.go b/checkout.go index 7377d51..a511306 100644 --- a/checkout.go +++ b/checkout.go @@ -74,10 +74,10 @@ func checkoutOptionsFromC(c *C.git_checkout_options) CheckoutOpts { 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 + opts.NotifyCallback = pointerHandles.Get(c.notify_payload).(*CheckoutOpts).NotifyCallback } if c.progress_payload != nil { - opts.ProgressCallback = pointerHandles.Get(c.progress_payload).(CheckoutOpts).ProgressCallback + opts.ProgressCallback = pointerHandles.Get(c.progress_payload).(*CheckoutOpts).ProgressCallback } if c.target_directory != nil { opts.TargetDirectory = C.GoString(c.target_directory) @@ -110,7 +110,7 @@ func checkoutNotifyCallback(why C.git_checkout_notify_t, cpath *C.char, cbaselin if cworkdir != nil { workdir = diffFileFromC((*C.git_diff_file)(cworkdir)) } - opts := pointerHandles.Get(data).(CheckoutOpts) + opts := pointerHandles.Get(data).(*CheckoutOpts) if opts.NotifyCallback == nil { return 0 } @@ -122,7 +122,7 @@ func checkoutProgressCallback(path *C.char, completed_steps, total_steps C.size_ if data == nil { return 0 } - opts := pointerHandles.Get(data).(CheckoutOpts) + opts := pointerHandles.Get(data).(*CheckoutOpts) if opts.ProgressCallback == nil { return 0 } @@ -146,11 +146,12 @@ func populateCheckoutOpts(ptr *C.git_checkout_options, opts *CheckoutOpts) *C.gi 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 = pointerHandles.Track(*opts) + ptr.notify_payload = payload } if opts.ProgressCallback != nil { - ptr.progress_payload = pointerHandles.Track(*opts) + ptr.progress_payload = payload } if opts.TargetDirectory != "" { ptr.target_directory = C.CString(opts.TargetDirectory) @@ -178,9 +179,6 @@ func freeCheckoutOpts(ptr *C.git_checkout_options) { if ptr.notify_payload != nil { pointerHandles.Untrack(ptr.notify_payload) } - if ptr.progress_payload != nil { - pointerHandles.Untrack(ptr.progress_payload) - } } // Updates files in the index and the working tree to match the content of -- 2.45.2 From aa7dfab1cf7534f7a3b99c2688c874b0af09d9f4 Mon Sep 17 00:00:00 2001 From: Mirko Nosenzo Date: Sun, 24 Jul 2016 14:20:12 +0200 Subject: [PATCH 5/6] Clone Fix freeCheckoutOpts called twice --- clone.go | 1 - 1 file changed, 1 deletion(-) diff --git a/clone.go b/clone.go index e80d14d..1ff5124 100644 --- a/clone.go +++ b/clone.go @@ -41,7 +41,6 @@ func Clone(url string, path string, options *CloneOptions) (*Repository, error) var ptr *C.git_repository ret := C.git_clone(&ptr, curl, cpath, copts) - freeCheckoutOpts(&copts.checkout_opts) if ret < 0 { return nil, MakeGitError(ret) -- 2.45.2 From 6ffad323ba4f723479d04182224297d90c0f9084 Mon Sep 17 00:00:00 2001 From: Mirko Nosenzo Date: Sun, 28 Aug 2016 11:21:10 +0200 Subject: [PATCH 6/6] Removed Useless Argument Check --- checkout.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/checkout.go b/checkout.go index a511306..f5822c9 100644 --- a/checkout.go +++ b/checkout.go @@ -119,9 +119,6 @@ func checkoutNotifyCallback(why C.git_checkout_notify_t, cpath *C.char, cbaselin //export checkoutProgressCallback func checkoutProgressCallback(path *C.char, completed_steps, total_steps C.size_t, data unsafe.Pointer) int { - if data == nil { - return 0 - } opts := pointerHandles.Get(data).(*CheckoutOpts) if opts.ProgressCallback == nil { return 0 -- 2.45.2