Merge pull request #266 from clns/update-libgit2

[next] Update libgit2 to 821131f
diff --git a/config.go b/config.go
index 9d25e35..73365c8 100644
--- a/config.go
+++ b/config.go
@@ -12,6 +12,9 @@
 type ConfigLevel int
 
 const (
+	// System-wide on Windows, for compatibility with portable git
+	ConfigLevelProgramdata ConfigLevel = C.GIT_CONFIG_LEVEL_PROGRAMDATA
+
 	// System-wide configuration file; /etc/gitconfig on Linux systems
 	ConfigLevelSystem ConfigLevel = C.GIT_CONFIG_LEVEL_SYSTEM
 
@@ -410,3 +413,21 @@
 
 	return C.GoString(buf.ptr), nil
 }
+
+// ConfigFindProgramdata locate the path to the configuration file in ProgramData.
+//
+// Look for the file in %PROGRAMDATA%\Git\config used by portable git.
+func ConfigFindProgramdata() (string, error) {
+	var buf C.git_buf
+	defer C.git_buf_free(&buf)
+
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
+
+	ret := C.git_config_find_programdata(&buf)
+	if ret < 0 {
+		return "", MakeGitError(ret)
+	}
+
+	return C.GoString(buf.ptr), nil
+}
diff --git a/git.go b/git.go
index 34d58e6..2b2a909 100644
--- a/git.go
+++ b/git.go
@@ -52,6 +52,7 @@
 
 	// No error
 	ErrOk ErrorCode = C.GIT_OK
+
 	// Generic error
 	ErrGeneric ErrorCode = C.GIT_ERROR
 	// Requested object could not be found
@@ -62,10 +63,12 @@
 	ErrAmbigious ErrorCode = C.GIT_EAMBIGUOUS
 	// Output buffer too short to hold data
 	ErrBuffs ErrorCode = C.GIT_EBUFS
+
 	// GIT_EUSER is a special error that is never generated by libgit2
 	// code.  You can return it from a callback (e.g to stop an iteration)
 	// to know that it was generated by the callback and not by libgit2.
 	ErrUser ErrorCode = C.GIT_EUSER
+
 	// Operation not allowed on bare repository
 	ErrBareRepo ErrorCode = C.GIT_EBAREREPO
 	// HEAD refers to branch with no commits
@@ -82,12 +85,27 @@
 	ErrLocked ErrorCode = C.GIT_ELOCKED
 	// Reference value does not match expected
 	ErrModified ErrorCode = C.GIT_EMODIFIED
+	// Authentication failed
+	ErrAuth ErrorCode = C.GIT_EAUTH
+	// Server certificate is invalid
+	ErrCertificate ErrorCode = C.GIT_ECERTIFICATE
+	// Patch/merge has already been applied
+	ErrApplied ErrorCode = C.GIT_EAPPLIED
+	// The requested peel operation is not possible
+	ErrPeel ErrorCode = C.GIT_EPEEL
+	// Unexpected EOF
+	ErrEOF ErrorCode = C.GIT_EEOF
+	// Uncommitted changes in index prevented operation
+	ErrUncommitted ErrorCode = C.GIT_EUNCOMMITTED
+	// The operation is not valid for a directory
+	ErrDirectory ErrorCode = C.GIT_EDIRECTORY
+	// A merge conflict exists and cannot continue
+	ErrMergeConflict ErrorCode = C.GIT_EMERGECONFLICT
+
 	// Internal only
 	ErrPassthrough ErrorCode = C.GIT_PASSTHROUGH
 	// Signals end of iteration with iterator
 	ErrIterOver ErrorCode = C.GIT_ITEROVER
-	// Authentication failed
-	ErrAuth ErrorCode = C.GIT_EAUTH
 )
 
 var (
diff --git a/index.go b/index.go
index 06495b9..1875e32 100644
--- a/index.go
+++ b/index.go
@@ -26,6 +26,24 @@
 	IndexAddCheckPathspec        IndexAddOpts = C.GIT_INDEX_ADD_CHECK_PATHSPEC
 )
 
+type IndexStageOpts int
+
+const (
+	// IndexStageAny matches any index stage.
+	//
+	// Some index APIs take a stage to match; pass this value to match
+	// any entry matching the path regardless of stage.
+	IndexStageAny IndexStageOpts = C.GIT_INDEX_STAGE_ANY
+	// IndexStageNormal is a normal staged file in the index.
+	IndexStageNormal IndexStageOpts = C.GIT_INDEX_STAGE_NORMAL
+	// IndexStageAncestor is the ancestor side of a conflict.
+	IndexStageAncestor IndexStageOpts = C.GIT_INDEX_STAGE_ANCESTOR
+	// IndexStageOurs is the "ours" side of a conflict.
+	IndexStageOurs IndexStageOpts = C.GIT_INDEX_STAGE_OURS
+	// IndexStageTheirs is the "theirs" side of a conflict.
+	IndexStageTheirs IndexStageOpts = C.GIT_INDEX_STAGE_THEIRS
+)
+
 type Index struct {
 	ptr *C.git_index
 }
diff --git a/merge.go b/merge.go
index a52e8f8..53d5a72 100644
--- a/merge.go
+++ b/merge.go
@@ -81,7 +81,14 @@
 type MergeTreeFlag int
 
 const (
+	// Detect renames that occur between the common ancestor and the "ours"
+	// side or the common ancestor and the "theirs" side.  This will enable
+	// the ability to merge between a modified and renamed file.
 	MergeTreeFindRenames MergeTreeFlag = C.GIT_MERGE_TREE_FIND_RENAMES
+	// If a conflict occurs, exit immediately instead of attempting to
+	// continue resolving conflicts.  The merge operation will fail with
+	// GIT_EMERGECONFLICT and no index will be returned.
+	MergeTreeFailOnConflict MergeTreeFlag = C.GIT_MERGE_TREE_FAIL_ON_CONFLICT
 )
 
 type MergeOptions struct {
diff --git a/remote.go b/remote.go
index b3aba54..a216513 100644
--- a/remote.go
+++ b/remote.go
@@ -112,6 +112,9 @@
 	//
 	// The default is to auto-follow tags.
 	DownloadTags DownloadTags
+
+	// Headers are extra headers for the fetch operation.
+	Headers []string
 }
 
 type Remote struct {
@@ -157,6 +160,9 @@
 	RemoteCallbacks RemoteCallbacks
 
 	PbParallelism uint
+
+	// Headers are extra headers for the push operation.
+	Headers []string
 }
 
 type RemoteHead struct {
@@ -594,6 +600,10 @@
 	options.prune = C.git_fetch_prune_t(opts.Prune)
 	options.update_fetchhead = cbool(opts.UpdateFetchhead)
 	options.download_tags = C.git_remote_autotag_option_t(opts.DownloadTags)
+
+	options.custom_headers = C.git_strarray{}
+	options.custom_headers.count = C.size_t(len(opts.Headers))
+	options.custom_headers.strings = makeCStringsFromStrings(opts.Headers)
 }
 
 func populatePushOptions(options *C.git_push_options, opts *PushOptions) {
@@ -604,6 +614,10 @@
 
 	options.pb_parallelism = C.uint(opts.PbParallelism)
 
+	options.custom_headers = C.git_strarray{}
+	options.custom_headers.count = C.size_t(len(opts.Headers))
+	options.custom_headers.strings = makeCStringsFromStrings(opts.Headers)
+
 	populateRemoteCallbacks(&options.callbacks, &opts.RemoteCallbacks)
 }
 
@@ -626,6 +640,7 @@
 	var coptions C.git_fetch_options
 	populateFetchOptions(&coptions, opts)
 	defer untrackCalbacksPayload(&coptions.callbacks)
+	defer freeStrarray(&coptions.custom_headers)
 
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
@@ -637,22 +652,34 @@
 	return nil
 }
 
-func (o *Remote) ConnectFetch(callbacks *RemoteCallbacks) error {
-	return o.Connect(ConnectDirectionFetch, callbacks)
+func (o *Remote) ConnectFetch(callbacks *RemoteCallbacks, headers []string) error {
+	return o.Connect(ConnectDirectionFetch, callbacks, headers)
 }
 
-func (o *Remote) ConnectPush(callbacks *RemoteCallbacks) error {
-	return o.Connect(ConnectDirectionPush, callbacks)
+func (o *Remote) ConnectPush(callbacks *RemoteCallbacks, headers []string) error {
+	return o.Connect(ConnectDirectionPush, callbacks, headers)
 }
 
-func (o *Remote) Connect(direction ConnectDirection, callbacks *RemoteCallbacks) error {
+// Connect opens a connection to a remote.
+//
+// The transport is selected based on the URL. The direction argument
+// is due to a limitation of the git protocol (over TCP or SSH) which
+// starts up a specific binary which can only do the one or the other.
+//
+// 'headers' are extra HTTP headers to use in this connection.
+func (o *Remote) Connect(direction ConnectDirection, callbacks *RemoteCallbacks, headers []string) error {
 	var ccallbacks C.git_remote_callbacks
 	populateRemoteCallbacks(&ccallbacks, callbacks)
 
+	cheaders := C.git_strarray{}
+	cheaders.count = C.size_t(len(headers))
+	cheaders.strings = makeCStringsFromStrings(headers)
+	defer freeStrarray(&cheaders)
+
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
-	if ret := C.git_remote_connect(o.ptr, C.git_direction(direction), &ccallbacks); ret != 0 {
+	if ret := C.git_remote_connect(o.ptr, C.git_direction(direction), &ccallbacks, &cheaders); ret != 0 {
 		return MakeGitError(ret)
 	}
 	return nil
@@ -713,6 +740,7 @@
 	var coptions C.git_push_options
 	populatePushOptions(&coptions, opts)
 	defer untrackCalbacksPayload(&coptions.callbacks)
+	defer freeStrarray(&coptions.custom_headers)
 
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
diff --git a/remote_test.go b/remote_test.go
index dac3dbe..978b803 100644
--- a/remote_test.go
+++ b/remote_test.go
@@ -58,7 +58,7 @@
 	remote, err := repo.Remotes.Create("origin", "https://github.com/libgit2/TestGitRepository")
 	checkFatal(t, err)
 
-	err = remote.ConnectFetch(nil)
+	err = remote.ConnectFetch(nil, nil)
 	checkFatal(t, err)
 }
 
@@ -69,7 +69,7 @@
 	remote, err := repo.Remotes.Create("origin", "https://github.com/libgit2/TestGitRepository")
 	checkFatal(t, err)
 
-	err = remote.ConnectFetch(nil)
+	err = remote.ConnectFetch(nil, nil)
 	checkFatal(t, err)
 
 	heads, err := remote.Ls()
@@ -87,7 +87,7 @@
 	remote, err := repo.Remotes.Create("origin", "https://github.com/libgit2/TestGitRepository")
 	checkFatal(t, err)
 
-	err = remote.ConnectFetch(nil)
+	err = remote.ConnectFetch(nil, nil)
 	checkFatal(t, err)
 
 	heads, err := remote.Ls("master")
@@ -166,7 +166,7 @@
 	rr, err := repo.Remotes.Lookup("origin")
 	checkFatal(t, err)
 
-	err = rr.ConnectFetch(nil)
+	err = rr.ConnectFetch(nil, nil)
 	checkFatal(t, err)
 
 	err = rr.Prune(nil)
diff --git a/vendor/libgit2 b/vendor/libgit2
index ed38e26..821131f 160000
--- a/vendor/libgit2
+++ b/vendor/libgit2
@@ -1 +1 @@
-Subproject commit ed38e26db5435b519d8b796e4b6c2c660fe982b5
+Subproject commit 821131fdaee74526d84aaf1c6ceddc2139c551df