Compare commits

...

13 Commits

Author SHA1 Message Date
hyung-hwan 4b90e82028 more libgit2 version diff handled 2026-06-22 22:39:28 +09:00
hyung-hwan d175c77686 fixed a version check when including git2/sys/errors.h 2026-06-22 22:27:04 +09:00
hyung-hwan 417e82b6c5 renamed the module name 2026-06-22 21:49:40 +09:00
hyung-hwan eb09776b38 minor update to support libgit2 1.9.4 2026-06-22 20:29:40 +09:00
lhchavez 4b14d29c20 Fix the github-tag-action workflow (#932)
This has been failing for a while because of some changes in `git`.
2022-10-04 18:12:23 -07:00
Sanskar Jaiswal c1ec21d89c libgit2 v1.5.0 #major (#929)
Update libgit2 to v1.5.0. Replace `SmartProxyOptions()` with `SmartRemoteConnectOptions()`.

Fixes: https://github.com/libgit2/git2go/issues/899

Signed-off-by: Sanskar Jaiswal <jaiswalsanskar078@gmail.com>
Co-authored-by: lhchavez <lhchavez@lhchavez.com>
2022-10-04 07:50:57 -07:00
Calin 9db5de109c Set BasicAuth in http.go only if username and password are not empty (#914)
This prevents error "read/write on closed pipe".

Go's http.client::send() always closes req.Body, so if the first request attempt
is unsuccessful, any subsequent requests after calling the `CredentialsCallback`
will attempt to read/write on a closed pipe.
2022-07-13 04:50:31 -07:00
lhchavez 7bff4ca7ad Uprev libgit to v1.3.1 (#911)
🔒 This is a security release to provide compatibility with git's
changes to address [CVE
2022-24765](https://github.blog/2022-04-12-git-security-vulnerability-announced/).

libgit2 (and by extension git2go) are not directly affected by this
vulnerability, because libgit2 does not directly invoke any executable.
But we are providing these changes as a security release for any users
that use libgit2 for repository discovery and then also use git on that
repository. In this release, we will now validate that the user opening
the repository is the same user that owns the on-disk repository. This
is to match git's behavior.

In addition, we are providing several correctness fixes where invalid
input can lead to a crash. These may prevent possible denial of service
attacks. At this time there are not known exploits to these issues.
2022-04-14 07:09:59 -07:00
William Bain eae00773cc Add refspec bindings (#898)
This add support for the parse, access, and transform functions for
refspec objects.
2022-02-24 19:21:35 -08:00
Patrick Steinhardt e7d1b2b69f rebase: Add wrapper for git_rebase_inmemory_index() (#900)
* rebase: Fix missing initialization of the repo pointer

While the `Rebase` structure has a pointer to the repository the rebase
is creatde in, this pointer isn't ever initialized. Fix this.

* rebase: Add wrapper for `git_rebase_inmemory_index()`

Add a new wrapper for `git_rebase_inmemory_index()`, which can be used
to retrieve the index for an in-memory rebase.

Co-authored-by: Patrick Steinhardt <psteinhardt@gitlab.com>
2022-02-24 05:27:26 -08:00
Dylan Richardson c598ea5718 readme: link to godoc for current main branch (#886)
The GoDoc link currently refers to the initial version of this package, but usually folks are looking
for whatever matches the current main branch. This should be updated whenever the package
version changes.
2022-01-22 17:54:04 -08:00
Aurélien 5eca48cda9 Add ProxyOptions for push operations (#872)
Analog to #623 but for push operations rather than fetch.
2022-01-17 19:02:14 -08:00
James Fargher 1fcc9d8743 Add EnableFsyncGitDir to enable synchronized writes to the gitdir (#874)
This adds support for the GIT_OPT_ENABLE_FSYNC_GITDIR option in libgit2.

Co-authored-by: James Fargher <jfargher@gitlab.com>
2022-01-17 18:51:39 -08:00
21 changed files with 403 additions and 41 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
branch: [ 'release-1.2', 'release-1.1', 'release-1.0', 'release-0.28', 'release-0.27' ] branch: [ 'release-1.3', 'release-1.2', 'release-1.1', 'release-1.0', 'release-0.28', 'release-0.27' ]
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
+1 -1
View File
@@ -62,7 +62,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
libgit2: libgit2:
- 'v1.3.0' - 'v1.5.0'
name: Go (system-wide, dynamic) name: Go (system-wide, dynamic)
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- name: Bump version and push tag - name: Bump version and push tag
id: bump-version id: bump-version
uses: anothrNick/github-tag-action@9aaabdb5e989894e95288328d8b17a6347217ae3 uses: anothrNick/github-tag-action@43ed073f5c1445ca8b80d920ce2f8fa550ae4e8d
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
WITH_V: true WITH_V: true
-3
View File
@@ -1,3 +0,0 @@
[submodule "vendor/libgit2"]
path = vendor/libgit2
url = https://github.com/libgit2/libgit2
+3 -3
View File
@@ -10,8 +10,8 @@ package git
#cgo CFLAGS: -DLIBGIT2_STATIC #cgo CFLAGS: -DLIBGIT2_STATIC
#include <git2.h> #include <git2.h>
#if LIBGIT2_VER_MAJOR != 1 || LIBGIT2_VER_MINOR < 3 || LIBGIT2_VER_MINOR > 3 //#if LIBGIT2_VER_MAJOR != 1 || LIBGIT2_VER_MINOR < 5 || LIBGIT2_VER_MINOR > 5
# error "Invalid libgit2 version; this git2go supports libgit2 between v1.3.0 and v1.3.0" //# error "Invalid libgit2 version; this git2go supports libgit2 between v1.5.0 and v1.5.0"
#endif //#endif
*/ */
import "C" import "C"
+3 -3
View File
@@ -8,8 +8,8 @@ package git
#cgo CFLAGS: -DLIBGIT2_DYNAMIC #cgo CFLAGS: -DLIBGIT2_DYNAMIC
#include <git2.h> #include <git2.h>
#if LIBGIT2_VER_MAJOR != 1 || LIBGIT2_VER_MINOR < 3 || LIBGIT2_VER_MINOR > 3 //#if LIBGIT2_VER_MAJOR != 1 || LIBGIT2_VER_MINOR < 5 || LIBGIT2_VER_MINOR > 5
# error "Invalid libgit2 version; this git2go supports libgit2 between v1.3.0 and v1.3.0" //# error "Invalid libgit2 version; this git2go supports libgit2 between v1.5.0 and v1.5.0"
#endif //#endif
*/ */
import "C" import "C"
+3 -3
View File
@@ -8,8 +8,8 @@ package git
#cgo CFLAGS: -DLIBGIT2_STATIC #cgo CFLAGS: -DLIBGIT2_STATIC
#include <git2.h> #include <git2.h>
#if LIBGIT2_VER_MAJOR != 1 || LIBGIT2_VER_MINOR < 3 || LIBGIT2_VER_MINOR > 3 //#if LIBGIT2_VER_MAJOR != 1 || LIBGIT2_VER_MINOR < 5 || LIBGIT2_VER_MINOR > 5
# error "Invalid libgit2 version; this git2go supports libgit2 between v1.3.0 and v1.3.0" //# error "Invalid libgit2 version; this git2go supports libgit2 between v1.5.0 and v1.5.0"
#endif //#endif
*/ */
import "C" import "C"
+8 -7
View File
@@ -1,6 +1,6 @@
git2go git2go
====== ======
[![GoDoc](https://godoc.org/github.com/libgit2/git2go?status.svg)](http://godoc.org/github.com/libgit2/git2go) [![Build Status](https://travis-ci.org/libgit2/git2go.svg?branch=main)](https://travis-ci.org/libgit2/git2go) [![GoDoc](https://godoc.org/github.com/libgit2/git2go?status.svg)](http://godoc.org/github.com/libgit2/git2go/v34) [![Build Status](https://travis-ci.org/libgit2/git2go.svg?branch=main)](https://travis-ci.org/libgit2/git2go)
Go bindings for [libgit2](http://libgit2.github.com/). Go bindings for [libgit2](http://libgit2.github.com/).
@@ -10,7 +10,8 @@ Due to the fact that Go 1.11 module versions have semantic meaning and don't nec
| libgit2 | git2go | | libgit2 | git2go |
|---------|---------------| |---------|---------------|
| main | (will be v34) | | main | (will be v35) |
| 1.5 | v34 |
| 1.3 | v33 | | 1.3 | v33 |
| 1.2 | v32 | | 1.2 | v32 |
| 1.1 | v31 | | 1.1 | v31 |
@@ -19,13 +20,13 @@ Due to the fact that Go 1.11 module versions have semantic meaning and don't nec
| 0.28 | v28 | | 0.28 | v28 |
| 0.27 | v27 | | 0.27 | v27 |
You can import them in your project with the version's major number as a suffix. For example, if you have libgit2 v1.2 installed, you'd import git2go v33 with: You can import them in your project with the version's major number as a suffix. For example, if you have libgit2 v1.2 installed, you'd import git2go v34 with:
```sh ```sh
go get github.com/libgit2/git2go/v33 go get github.com/libgit2/git2go/v34
``` ```
```go ```go
import "github.com/libgit2/git2go/v33" import "github.com/libgit2/git2go/v34"
``` ```
which will ensure there are no sudden changes to the API. which will ensure there are no sudden changes to the API.
@@ -49,7 +50,7 @@ This project wraps the functionality provided by libgit2. If you're using a vers
When linking dynamically against a released version of libgit2, install it via your system's package manager. CGo will take care of finding its pkg-config file and set up the linking. Import via Go modules, e.g. to work against libgit2 v1.2 When linking dynamically against a released version of libgit2, install it via your system's package manager. CGo will take care of finding its pkg-config file and set up the linking. Import via Go modules, e.g. to work against libgit2 v1.2
```go ```go
import "github.com/libgit2/git2go/v33" import "github.com/libgit2/git2go/v34"
``` ```
### Versioned branch, static linking ### Versioned branch, static linking
@@ -79,7 +80,7 @@ In order to let Go pass the correct flags to `pkg-config`, `-tags static` needs
One thing to take into account is that since Go expects the `pkg-config` file to be within the same directory where `make install-static` was called, so the `go.mod` file may need to have a [`replace` directive](https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive) so that the correct setup is achieved. So if `git2go` is checked out at `$GOPATH/src/github.com/libgit2/git2go` and your project at `$GOPATH/src/github.com/my/project`, the `go.mod` file of `github.com/my/project` might need to have a line like One thing to take into account is that since Go expects the `pkg-config` file to be within the same directory where `make install-static` was called, so the `go.mod` file may need to have a [`replace` directive](https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive) so that the correct setup is achieved. So if `git2go` is checked out at `$GOPATH/src/github.com/libgit2/git2go` and your project at `$GOPATH/src/github.com/my/project`, the `go.mod` file of `github.com/my/project` might need to have a line like
replace github.com/libgit2/git2go/v33 => ../../libgit2/git2go replace github.com/libgit2/git2go/v34 => ../../libgit2/git2go
Parallelism and network operations Parallelism and network operations
---------------------------------- ----------------------------------
+2 -1
View File
@@ -73,7 +73,8 @@ func (t CredentialType) String() string {
} }
if t != 0 { if t != 0 {
parts = append(parts, fmt.Sprintf("CredentialType(%#x)", t)) //parts = append(parts, fmt.Sprintf("CredentialType(%#x)", t))
parts = append(parts, fmt.Sprintf("CredentialType(%#x)", uint32(t)))
} }
return strings.Join(parts, "|") return strings.Join(parts, "|")
+2 -1
View File
@@ -1,4 +1,5 @@
module github.com/libgit2/git2go/v33 //module github.com/libgit2/git2go/v34
module git2go
go 1.13 go 1.13
+6 -4
View File
@@ -38,17 +38,17 @@ func registerManagedHTTP() error {
func httpSmartSubtransportFactory(remote *Remote, transport *Transport) (SmartSubtransport, error) { func httpSmartSubtransportFactory(remote *Remote, transport *Transport) (SmartSubtransport, error) {
var proxyFn func(*http.Request) (*url.URL, error) var proxyFn func(*http.Request) (*url.URL, error)
proxyOpts, err := transport.SmartProxyOptions() remoteConnectOpts, err := transport.SmartRemoteConnectOptions()
if err != nil { if err != nil {
return nil, err return nil, err
} }
switch proxyOpts.Type { switch remoteConnectOpts.ProxyOptions.Type {
case ProxyTypeNone: case ProxyTypeNone:
proxyFn = nil proxyFn = nil
case ProxyTypeAuto: case ProxyTypeAuto:
proxyFn = http.ProxyFromEnvironment proxyFn = http.ProxyFromEnvironment
case ProxyTypeSpecified: case ProxyTypeSpecified:
parsedUrl, err := url.Parse(proxyOpts.Url) parsedUrl, err := url.Parse(remoteConnectOpts.ProxyOptions.Url)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -203,7 +203,9 @@ func (self *httpSmartSubtransportStream) sendRequest() error {
req.ContentLength = -1 req.ContentLength = -1
} }
req.SetBasicAuth(userName, password) if userName != "" && password != "" {
req.SetBasicAuth(userName, password)
}
resp, err = http.DefaultClient.Do(req) resp, err = http.DefaultClient.Do(req)
if err != nil { if err != nil {
return err return err
+25 -4
View File
@@ -318,7 +318,7 @@ func (r *Repository) InitRebase(branch *AnnotatedCommit, upstream *AnnotatedComm
return nil, MakeGitError(ret) return nil, MakeGitError(ret)
} }
return newRebaseFromC(ptr, cOpts), nil return newRebaseFromC(ptr, r, cOpts), nil
} }
// OpenRebase opens an existing rebase that was previously started by either an invocation of InitRebase or by another client. // OpenRebase opens an existing rebase that was previously started by either an invocation of InitRebase or by another client.
@@ -340,7 +340,7 @@ func (r *Repository) OpenRebase(opts *RebaseOptions) (*Rebase, error) {
return nil, MakeGitError(ret) return nil, MakeGitError(ret)
} }
return newRebaseFromC(ptr, cOpts), nil return newRebaseFromC(ptr, r, cOpts), nil
} }
// OperationAt gets the rebase operation specified by the given index. // OperationAt gets the rebase operation specified by the given index.
@@ -392,6 +392,27 @@ func (rebase *Rebase) Next() (*RebaseOperation, error) {
return newRebaseOperationFromC(ptr), nil return newRebaseOperationFromC(ptr), nil
} }
// InmemoryIndex gets the index produced by the last operation, which is the
// result of `Next()` and which will be committed by the next invocation of
// `Commit()`. This is useful for resolving conflicts in an in-memory rebase
// before committing them.
//
// This is only applicable for in-memory rebases; for rebases within a working
// directory, the changes were applied to the repository's index.
func (rebase *Rebase) InmemoryIndex() (*Index, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
var ptr *C.git_index
err := C.git_rebase_inmemory_index(&ptr, rebase.ptr)
runtime.KeepAlive(rebase)
if err < 0 {
return nil, MakeGitError(err)
}
return newIndexFromC(ptr, rebase.r), nil
}
// Commit commits the current patch. // Commit commits the current patch.
// You must have resolved any conflicts that were introduced during the patch application from the Next() invocation. // You must have resolved any conflicts that were introduced during the patch application from the Next() invocation.
func (rebase *Rebase) Commit(ID *Oid, author, committer *Signature, message string) error { func (rebase *Rebase) Commit(ID *Oid, author, committer *Signature, message string) error {
@@ -457,8 +478,8 @@ func (r *Rebase) Free() {
freeRebaseOptions(r.options) freeRebaseOptions(r.options)
} }
func newRebaseFromC(ptr *C.git_rebase, opts *C.git_rebase_options) *Rebase { func newRebaseFromC(ptr *C.git_rebase, repo *Repository, opts *C.git_rebase_options) *Rebase {
rebase := &Rebase{ptr: ptr, options: opts} rebase := &Rebase{ptr: ptr, r: repo, options: opts}
runtime.SetFinalizer(rebase, (*Rebase).Free) runtime.SetFinalizer(rebase, (*Rebase).Free)
return rebase return rebase
} }
+74
View File
@@ -14,6 +14,80 @@ import (
// Tests // Tests
func TestRebaseInMemoryWithConflict(t *testing.T) {
repo := createTestRepo(t)
defer cleanupTestRepo(t, repo)
seedTestRepo(t, repo)
// Create two branches with common history, where both modify "common-file"
// in a conflicting way.
_, err := commitSomething(repo, "common-file", "a\nb\nc\n", commitOptions{})
checkFatal(t, err)
checkFatal(t, createBranch(repo, "branch-a"))
checkFatal(t, createBranch(repo, "branch-b"))
checkFatal(t, repo.SetHead("refs/heads/branch-a"))
_, err = commitSomething(repo, "common-file", "1\nb\nc\n", commitOptions{})
checkFatal(t, err)
checkFatal(t, repo.SetHead("refs/heads/branch-b"))
_, err = commitSomething(repo, "common-file", "x\nb\nc\n", commitOptions{})
checkFatal(t, err)
branchA, err := repo.LookupBranch("branch-a", BranchLocal)
checkFatal(t, err)
onto, err := repo.AnnotatedCommitFromRef(branchA.Reference)
checkFatal(t, err)
// We then rebase "branch-b" onto "branch-a" in-memory, which should result
// in a conflict.
rebase, err := repo.InitRebase(nil, nil, onto, &RebaseOptions{InMemory: 1})
checkFatal(t, err)
_, err = rebase.Next()
checkFatal(t, err)
index, err := rebase.InmemoryIndex()
checkFatal(t, err)
// We simply resolve the conflict and commit the rebase.
if !index.HasConflicts() {
t.Fatal("expected index to have conflicts")
}
conflict, err := index.Conflict("common-file")
checkFatal(t, err)
resolvedBlobID, err := repo.CreateBlobFromBuffer([]byte("resolved contents"))
checkFatal(t, err)
resolvedEntry := *conflict.Our
resolvedEntry.Id = resolvedBlobID
checkFatal(t, index.Add(&resolvedEntry))
checkFatal(t, index.RemoveConflict("common-file"))
var commitID Oid
checkFatal(t, rebase.Commit(&commitID, signature(), signature(), "rebased message"))
checkFatal(t, rebase.Finish())
// And then assert that we can look up the new merge commit, and that the
// "common-file" has the expected contents.
commit, err := repo.LookupCommit(&commitID)
checkFatal(t, err)
if commit.Message() != "rebased message" {
t.Fatalf("unexpected commit message %q", commit.Message())
}
tree, err := commit.Tree()
checkFatal(t, err)
blob, err := repo.LookupBlob(tree.EntryByName("common-file").Id)
checkFatal(t, err)
if string(blob.Contents()) != "resolved contents" {
t.Fatalf("unexpected resolved blob contents %q", string(blob.Contents()))
}
}
func TestRebaseAbort(t *testing.T) { func TestRebaseAbort(t *testing.T) {
// TEST DATA // TEST DATA
+149
View File
@@ -0,0 +1,149 @@
package git
/*
#include <git2.h>
*/
import "C"
import (
"runtime"
"unsafe"
)
type Refspec struct {
doNotCompare
ptr *C.git_refspec
}
// ParseRefspec parses a given refspec string
func ParseRefspec(input string, isFetch bool) (*Refspec, error) {
var ptr *C.git_refspec
cinput := C.CString(input)
defer C.free(unsafe.Pointer(cinput))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ret := C.git_refspec_parse(&ptr, cinput, cbool(isFetch))
if ret < 0 {
return nil, MakeGitError(ret)
}
spec := &Refspec{ptr: ptr}
runtime.SetFinalizer(spec, (*Refspec).Free)
return spec, nil
}
// Free releases a refspec object which has been created by ParseRefspec
func (s *Refspec) Free() {
runtime.SetFinalizer(s, nil)
C.git_refspec_free(s.ptr)
}
// Direction returns the refspec's direction
func (s *Refspec) Direction() ConnectDirection {
direction := C.git_refspec_direction(s.ptr)
return ConnectDirection(direction)
}
// Src returns the refspec's source specifier
func (s *Refspec) Src() string {
var ret string
cstr := C.git_refspec_src(s.ptr)
if cstr != nil {
ret = C.GoString(cstr)
}
runtime.KeepAlive(s)
return ret
}
// Dst returns the refspec's destination specifier
func (s *Refspec) Dst() string {
var ret string
cstr := C.git_refspec_dst(s.ptr)
if cstr != nil {
ret = C.GoString(cstr)
}
runtime.KeepAlive(s)
return ret
}
// Force returns the refspec's force-update setting
func (s *Refspec) Force() bool {
force := C.git_refspec_force(s.ptr)
return force != 0
}
// String returns the refspec's string representation
func (s *Refspec) String() string {
var ret string
cstr := C.git_refspec_string(s.ptr)
if cstr != nil {
ret = C.GoString(cstr)
}
runtime.KeepAlive(s)
return ret
}
// SrcMatches checks if a refspec's source descriptor matches a reference
func (s *Refspec) SrcMatches(refname string) bool {
cname := C.CString(refname)
defer C.free(unsafe.Pointer(cname))
matches := C.git_refspec_src_matches(s.ptr, cname)
return matches != 0
}
// SrcMatches checks if a refspec's destination descriptor matches a reference
func (s *Refspec) DstMatches(refname string) bool {
cname := C.CString(refname)
defer C.free(unsafe.Pointer(cname))
matches := C.git_refspec_dst_matches(s.ptr, cname)
return matches != 0
}
// Transform a reference to its target following the refspec's rules
func (s *Refspec) Transform(refname string) (string, error) {
buf := C.git_buf{}
cname := C.CString(refname)
defer C.free(unsafe.Pointer(cname))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ret := C.git_refspec_transform(&buf, s.ptr, cname)
if ret < 0 {
return "", MakeGitError(ret)
}
defer C.git_buf_dispose(&buf)
return C.GoString(buf.ptr), nil
}
// Rtransform converts a target reference to its source reference following the
// refspec's rules
func (s *Refspec) Rtransform(refname string) (string, error) {
buf := C.git_buf{}
cname := C.CString(refname)
defer C.free(unsafe.Pointer(cname))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
ret := C.git_refspec_rtransform(&buf, s.ptr, cname)
if ret < 0 {
return "", MakeGitError(ret)
}
defer C.git_buf_dispose(&buf)
return C.GoString(buf.ptr), nil
}
+75
View File
@@ -0,0 +1,75 @@
package git
import (
"testing"
)
func TestRefspec(t *testing.T) {
t.Parallel()
const (
input = "+refs/heads/*:refs/remotes/origin/*"
mainLocal = "refs/heads/main"
mainRemote = "refs/remotes/origin/main"
)
refspec, err := ParseRefspec(input, true)
checkFatal(t, err)
// Accessors
s := refspec.String()
if s != input {
t.Errorf("expected string %q, got %q", input, s)
}
if d := refspec.Direction(); d != ConnectDirectionFetch {
t.Errorf("expected fetch refspec, got direction %v", d)
}
if pat, expected := refspec.Src(), "refs/heads/*"; pat != expected {
t.Errorf("expected refspec src %q, got %q", expected, pat)
}
if pat, expected := refspec.Dst(), "refs/remotes/origin/*"; pat != expected {
t.Errorf("expected refspec dst %q, got %q", expected, pat)
}
if !refspec.Force() {
t.Error("expected refspec force flag")
}
// SrcMatches
if !refspec.SrcMatches(mainLocal) {
t.Errorf("refspec source did not match %q", mainLocal)
}
if refspec.SrcMatches("refs/tags/v1.0") {
t.Error("refspec source matched under refs/tags")
}
// DstMatches
if !refspec.DstMatches(mainRemote) {
t.Errorf("refspec destination did not match %q", mainRemote)
}
if refspec.DstMatches("refs/tags/v1.0") {
t.Error("refspec destination matched under refs/tags")
}
// Transforms
fromLocal, err := refspec.Transform(mainLocal)
checkFatal(t, err)
if fromLocal != mainRemote {
t.Errorf("transform by refspec returned %s; expected %s", fromLocal, mainRemote)
}
fromRemote, err := refspec.Rtransform(mainRemote)
checkFatal(t, err)
if fromRemote != mainLocal {
t.Errorf("rtransform by refspec returned %s; expected %s", fromRemote, mainLocal)
}
}
+26 -3
View File
@@ -6,6 +6,10 @@ package git
#include <git2.h> #include <git2.h>
#include <git2/sys/cred.h> #include <git2/sys/cred.h>
static void set_update_fetchhead(git_fetch_options *opts, int v) {
opts->update_fetchhead = v;
}
extern void _go_git_populate_remote_callbacks(git_remote_callbacks *callbacks); extern void _go_git_populate_remote_callbacks(git_remote_callbacks *callbacks);
*/ */
import "C" import "C"
@@ -146,6 +150,17 @@ type FetchOptions struct {
ProxyOptions ProxyOptions ProxyOptions ProxyOptions
} }
type RemoteConnectOptions struct {
// Proxy options to use for this fetch operation
ProxyOptions ProxyOptions
}
func remoteConnectOptionsFromC(copts *C.git_remote_connect_options) *RemoteConnectOptions {
return &RemoteConnectOptions{
ProxyOptions: proxyOptionsFromC(&copts.proxy_opts),
}
}
type ProxyType uint type ProxyType uint
const ( const (
@@ -170,8 +185,8 @@ type ProxyOptions struct {
Url string Url string
} }
func proxyOptionsFromC(copts *C.git_proxy_options) *ProxyOptions { func proxyOptionsFromC(copts *C.git_proxy_options) ProxyOptions {
return &ProxyOptions{ return ProxyOptions{
Type: ProxyType(copts._type), Type: ProxyType(copts._type),
Url: C.GoString(copts.url), Url: C.GoString(copts.url),
} }
@@ -291,6 +306,9 @@ type PushOptions struct {
// Headers are extra headers for the push operation. // Headers are extra headers for the push operation.
Headers []string Headers []string
// Proxy options to use for this push operation
ProxyOptions ProxyOptions
} }
type RemoteHead struct { type RemoteHead struct {
@@ -969,7 +987,10 @@ func populateFetchOptions(copts *C.git_fetch_options, opts *FetchOptions, errorT
} }
populateRemoteCallbacks(&copts.callbacks, &opts.RemoteCallbacks, errorTarget) populateRemoteCallbacks(&copts.callbacks, &opts.RemoteCallbacks, errorTarget)
copts.prune = C.git_fetch_prune_t(opts.Prune) copts.prune = C.git_fetch_prune_t(opts.Prune)
copts.update_fetchhead = cbool(opts.UpdateFetchhead)
// use the helper. the update_fetchhead is signed on libgit2 1.5 but unsigined on 1.9
//copts.update_fetchhead = ucbool(opts.UpdateFetchhead)
C.set_update_fetchhead(copts, C.int(ucbool(opts.UpdateFetchhead)))
copts.download_tags = C.git_remote_autotag_option_t(opts.DownloadTags) copts.download_tags = C.git_remote_autotag_option_t(opts.DownloadTags)
copts.custom_headers = C.git_strarray{ copts.custom_headers = C.git_strarray{
@@ -1001,6 +1022,7 @@ func populatePushOptions(copts *C.git_push_options, opts *PushOptions, errorTarg
strings: makeCStringsFromStrings(opts.Headers), strings: makeCStringsFromStrings(opts.Headers),
} }
populateRemoteCallbacks(&copts.callbacks, &opts.RemoteCallbacks, errorTarget) populateRemoteCallbacks(&copts.callbacks, &opts.RemoteCallbacks, errorTarget)
populateProxyOptions(&copts.proxy_opts, &opts.ProxyOptions)
return copts return copts
} }
@@ -1010,6 +1032,7 @@ func freePushOptions(copts *C.git_push_options) {
} }
untrackCallbacksPayload(&copts.callbacks) untrackCallbacksPayload(&copts.callbacks)
freeStrarray(&copts.custom_headers) freeStrarray(&copts.custom_headers)
freeProxyOptions(&copts.proxy_opts)
} }
// Fetch performs a fetch operation. refspecs specifies which refspecs // Fetch performs a fetch operation. refspecs specifies which refspecs
+8
View File
@@ -101,6 +101,14 @@ func EnableStrictHashVerification(enabled bool) error {
} }
} }
func EnableFsyncGitDir(enabled bool) error {
if enabled {
return setSizet(C.GIT_OPT_ENABLE_FSYNC_GITDIR, 1)
} else {
return setSizet(C.GIT_OPT_ENABLE_FSYNC_GITDIR, 0)
}
}
func CachedMemory() (current int, allowed int, err error) { func CachedMemory() (current int, allowed int, err error) {
return getSizetSizet(C.GIT_OPT_GET_CACHED_MEMORY) return getSizetSizet(C.GIT_OPT_GET_CACHED_MEMORY)
} }
+8
View File
@@ -65,6 +65,14 @@ func TestEnableStrictHashVerification(t *testing.T) {
checkFatal(t, err) checkFatal(t, err)
} }
func TestEnableFsyncGitDir(t *testing.T) {
err := EnableFsyncGitDir(false)
checkFatal(t, err)
err = EnableFsyncGitDir(true)
checkFatal(t, err)
}
func TestCachedMemory(t *testing.T) { func TestCachedMemory(t *testing.T) {
current, allowed, err := CachedMemory() current, allowed, err := CachedMemory()
checkFatal(t, err) checkFatal(t, err)
+5 -5
View File
@@ -84,17 +84,17 @@ type Transport struct {
ptr *C.git_transport ptr *C.git_transport
} }
// SmartProxyOptions gets a copy of the proxy options for this transport. // SmartRemoteConnectOptions gets a copy of the proxy options for this transport.
func (t *Transport) SmartProxyOptions() (*ProxyOptions, error) { func (t *Transport) SmartRemoteConnectOptions() (*RemoteConnectOptions, error) {
runtime.LockOSThread() runtime.LockOSThread()
defer runtime.UnlockOSThread() defer runtime.UnlockOSThread()
var cpopts C.git_proxy_options var copts C.git_remote_connect_options
if ret := C.git_transport_smart_proxy_options(&cpopts, t.ptr); ret < 0 { if ret := C.git_transport_remote_connect_options(&copts, t.ptr); ret < 0 {
return nil, MakeGitError(ret) return nil, MakeGitError(ret)
} }
return proxyOptionsFromC(&cpopts), nil return remoteConnectOptionsFromC(&copts), nil
} }
// SmartCredentials calls the credentials callback for this transport. // SmartCredentials calls the credentials callback for this transport.
-1
Submodule vendor/libgit2 deleted from b7bad55e4b
+3
View File
@@ -4,6 +4,9 @@
#include <git2/sys/odb_backend.h> #include <git2/sys/odb_backend.h>
#include <git2/sys/refdb_backend.h> #include <git2/sys/refdb_backend.h>
#include <git2/sys/cred.h> #include <git2/sys/cred.h>
#if (LIBGIT2_VER_MAJOR > 1) || (LIBGIT2_VER_MAJOR == 1 && LIBGIT2_VER_MINOR >= 9)
#include <git2/sys/errors.h>
#endif
// There are two ways in which to declare a callback: // There are two ways in which to declare a callback:
// //