summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--.travis.yml11
-rw-r--r--Makefile11
-rw-r--r--README.md2
-rw-r--r--branch.go36
-rw-r--r--checkout.go15
-rw-r--r--cherrypick_test.go2
-rw-r--r--clone.go12
-rw-r--r--clone_test.go10
-rw-r--r--git.go5
-rw-r--r--index.go42
-rw-r--r--merge.go10
-rw-r--r--merge_test.go4
-rw-r--r--note.go121
-rw-r--r--note_test.go14
-rw-r--r--odb.go8
-rw-r--r--odb_test.go2
-rw-r--r--push_test.go8
-rw-r--r--reference.go154
-rw-r--r--reference_test.go31
-rw-r--r--remote.go261
-rw-r--r--remote_test.go78
-rw-r--r--repository.go337
-rw-r--r--reset.go26
-rw-r--r--reset_test.go45
-rw-r--r--revparse_test.go2
-rwxr-xr-xscript/build-libgit2-static.sh19
-rw-r--r--script/check-MakeGitError-thread-lock.go2
-rwxr-xr-xscript/install-libgit2.sh21
-rwxr-xr-xscript/with-static.sh12
-rw-r--r--submodule.go120
-rw-r--r--submodule_test.go4
m---------vendor/libgit20
-rw-r--r--wrapper.c4
34 files changed, 723 insertions, 709 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..8eb5872
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "vendor/libgit2"]
+ path = vendor/libgit2
+ url = https://github.com/libgit2/libgit2
diff --git a/.travis.yml b/.travis.yml
index f8b7e93..fb080b9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,13 +1,8 @@
language: go
-install:
- - cd "${HOME}"
- - wget -O libgit2-0.22.1.tar.gz https://github.com/libgit2/libgit2/archive/v0.22.1.tar.gz
- - tar -xzvf libgit2-0.22.1.tar.gz
- - cd libgit2-0.22.1 && mkdir build && cd build
- - cmake -DTHREADSAFE=ON -DBUILD_CLAR=OFF -DCMAKE_C_FLAGS=-fPIC -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DCMAKE_INSTALL_PREFIX=/usr/local .. && make && sudo make install
- - sudo ldconfig
- - cd "${TRAVIS_BUILD_DIR}"
+sudo: false
+
+install: ./script/install-libgit2.sh
go:
- 1.1
diff --git a/Makefile b/Makefile
index 9c42283..3040857 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,11 @@
default: test
-test:
+build-libgit2:
+ ./script/build-libgit2-static.sh
+
+test: build-libgit2
go run script/check-MakeGitError-thread-lock.go
- go test ./...
+ ./script/with-static.sh go test ./...
-install:
- go install ./...
+install: build-libgit2
+ ./script/with-static.sh go install ./...
diff --git a/README.md b/README.md
index 386ff83..c604eaf 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@ Paralellism and network operations
----------------------------------
libgit2 uses OpenSSL and LibSSH2 for performing encrypted network connections. For now, git2go asks libgit2 to set locking for OpenSSL. This makes HTTPS connections thread-safe, but it is fragile and will likely stop doing it soon. This may also make SSH connections thread-safe if your copy of libssh2 is linked against OpenSSL. Check libgit2's `THREADSAFE.md` for more information.
-
+[
Running the tests
-----------------
diff --git a/branch.go b/branch.go
index 42e1216..d0a0835 100644
--- a/branch.go
+++ b/branch.go
@@ -90,30 +90,16 @@ func (repo *Repository) NewBranchIterator(flags BranchType) (*BranchIterator, er
return newBranchIteratorFromC(repo, ptr), nil
}
-func (repo *Repository) CreateBranch(branchName string, target *Commit, force bool, signature *Signature, msg string) (*Branch, error) {
+func (repo *Repository) CreateBranch(branchName string, target *Commit, force bool) (*Branch, error) {
var ptr *C.git_reference
cBranchName := C.CString(branchName)
cForce := cbool(force)
- cSignature, err := signature.toC()
- if err != nil {
- return nil, err
- }
- defer C.git_signature_free(cSignature)
-
- var cmsg *C.char
- if msg == "" {
- cmsg = nil
- } else {
- cmsg = C.CString(msg)
- defer C.free(unsafe.Pointer(cmsg))
- }
-
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_branch_create(&ptr, repo.ptr, cBranchName, target.cast_ptr, cForce, cSignature, cmsg)
+ ret := C.git_branch_create(&ptr, repo.ptr, cBranchName, target.cast_ptr, cForce)
if ret < 0 {
return nil, MakeGitError(ret)
}
@@ -131,29 +117,15 @@ func (b *Branch) Delete() error {
return nil
}
-func (b *Branch) Move(newBranchName string, force bool, signature *Signature, msg string) (*Branch, error) {
+func (b *Branch) Move(newBranchName string, force bool) (*Branch, error) {
var ptr *C.git_reference
cNewBranchName := C.CString(newBranchName)
cForce := cbool(force)
- cSignature, err := signature.toC()
- if err != nil {
- return nil, err
- }
- defer C.git_signature_free(cSignature)
-
- var cmsg *C.char
- if msg == "" {
- cmsg = nil
- } else {
- cmsg = C.CString(msg)
- defer C.free(unsafe.Pointer(cmsg))
- }
-
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_branch_move(&ptr, b.Reference.ptr, cNewBranchName, cForce, cSignature, cmsg)
+ ret := C.git_branch_move(&ptr, b.Reference.ptr, cNewBranchName, cForce)
if ret < 0 {
return nil, MakeGitError(ret)
}
diff --git a/checkout.go b/checkout.go
index 9874d2b..d747344 100644
--- a/checkout.go
+++ b/checkout.go
@@ -15,18 +15,23 @@ type CheckoutStrategy uint
const (
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
- CheckoutSafeCreate CheckoutStrategy = C.GIT_CHECKOUT_SAFE_CREATE // Allow safe updates plus creation of missing files
- CheckoutForce CheckoutStrategy = C.GIT_CHECKOUT_FORCE // Allow all updates to force working directory to look like index
+ CheckoutRecreateMissing CheckoutStrategy = C.GIT_CHECKOUT_RECREATE_MISSING // Allow checkout to recreate missing files
CheckoutAllowConflicts CheckoutStrategy = C.GIT_CHECKOUT_ALLOW_CONFLICTS // Allow checkout to make safe updates even if conflicts are found
CheckoutRemoveUntracked CheckoutStrategy = C.GIT_CHECKOUT_REMOVE_UNTRACKED // Remove untracked files not in index (that are not ignored)
CheckoutRemoveIgnored CheckoutStrategy = C.GIT_CHECKOUT_REMOVE_IGNORED // Remove ignored files not in index
CheckoutUpdateOnly CheckoutStrategy = C.GIT_CHECKOUT_UPDATE_ONLY // Only update existing files, don't create new ones
CheckoutDontUpdateIndex CheckoutStrategy = C.GIT_CHECKOUT_DONT_UPDATE_INDEX // Normally checkout updates index entries as it goes; this stops that
CheckoutNoRefresh CheckoutStrategy = C.GIT_CHECKOUT_NO_REFRESH // Don't refresh index/config/etc before doing checkout
+ CheckoutSkipUnmerged CheckoutStrategy = C.GIT_CHECKOUT_SKIP_UNMERGED // Allow checkout to skip unmerged files
+ CheckoutUserOurs CheckoutStrategy = C.GIT_CHECKOUT_USE_OURS // For unmerged files, checkout stage 2 from index
+ CheckoutUseTheirs CheckoutStrategy = C.GIT_CHECKOUT_USE_THEIRS // For unmerged files, checkout stage 3 from index
CheckoutDisablePathspecMatch CheckoutStrategy = C.GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH // Treat pathspec as simple list of exact match file paths
- CheckoutSkipUnmerged CheckoutStrategy = C.GIT_CHECKOUT_SKIP_UNMERGED // Allow checkout to skip unmerged files (NOT IMPLEMENTED)
- CheckoutUserOurs CheckoutStrategy = C.GIT_CHECKOUT_USE_OURS // For unmerged files, checkout stage 2 from index (NOT IMPLEMENTED)
- CheckoutUseTheirs CheckoutStrategy = C.GIT_CHECKOUT_USE_THEIRS // For unmerged files, checkout stage 3 from index (NOT IMPLEMENTED)
+ CheckoutSkipLockedDirectories CheckoutStrategy = C.GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES // Ignore directories in use, they will be left empty
+ CheckoutDontOverwriteIgnored CheckoutStrategy = C.GIT_CHECKOUT_DONT_OVERWRITE_IGNORED // Don't overwrite ignored files that exist in the checkout target
+ CheckoutConflictStyleMerge CheckoutStrategy = C.GIT_CHECKOUT_CONFLICT_STYLE_MERGE // Write normal merge files for conflicts
+ CheckoutConflictStyleDiff3 CheckoutStrategy = C.GIT_CHECKOUT_CONFLICT_STYLE_DIFF3 // Include common ancestor data in diff3 format files for conflicts
+ CheckoutDontRemoveExisting CheckoutStrategy = C.GIT_CHECKOUT_DONT_REMOVE_EXISTING // Don't overwrite existing files or folders
+ CheckoutDontWriteIndex CheckoutStrategy = C.GIT_CHECKOUT_DONT_WRITE_INDEX // Normally checkout writes the index upon completion; this prevents that
CheckoutUpdateSubmodules CheckoutStrategy = C.GIT_CHECKOUT_UPDATE_SUBMODULES // Recursively checkout submodules with same options (NOT IMPLEMENTED)
CheckoutUpdateSubmodulesIfChanged CheckoutStrategy = C.GIT_CHECKOUT_UPDATE_SUBMODULES_IF_CHANGED // Recursively checkout submodules if HEAD moved in super repo (NOT IMPLEMENTED)
)
diff --git a/cherrypick_test.go b/cherrypick_test.go
index 09bc524..a3246bd 100644
--- a/cherrypick_test.go
+++ b/cherrypick_test.go
@@ -16,7 +16,7 @@ func checkout(t *testing.T, repo *Repository, commit *Commit) {
t.Fatal(err)
}
- err = repo.SetHeadDetached(commit.Id(), commit.Author(), "checkout")
+ err = repo.SetHeadDetached(commit.Id())
if err != nil {
t.Fatal(err)
}
diff --git a/clone.go b/clone.go
index 4de4aea..b5c5a5b 100644
--- a/clone.go
+++ b/clone.go
@@ -12,7 +12,7 @@ import (
type CloneOptions struct {
*CheckoutOpts
- *RemoteCallbacks
+ *FetchOptions
Bare bool
CheckoutBranch string
RemoteCreateCallback C.git_remote_create_cb
@@ -20,8 +20,6 @@ type CloneOptions struct {
}
func Clone(url string, path string, options *CloneOptions) (*Repository, error) {
- repo := new(Repository)
-
curl := C.CString(url)
defer C.free(unsafe.Pointer(curl))
@@ -37,7 +35,8 @@ func Clone(url string, path string, options *CloneOptions) (*Repository, error)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_clone(&repo.ptr, curl, cpath, copts)
+ var ptr *C.git_repository
+ ret := C.git_clone(&ptr, curl, cpath, copts)
freeCheckoutOpts(&copts.checkout_opts)
C.free(unsafe.Pointer(copts.checkout_branch))
C.free(unsafe.Pointer(copts))
@@ -46,8 +45,7 @@ func Clone(url string, path string, options *CloneOptions) (*Repository, error)
return nil, MakeGitError(ret)
}
- runtime.SetFinalizer(repo, (*Repository).Free)
- return repo, nil
+ return newRepositoryFromC(ptr), nil
}
func populateCloneOptions(ptr *C.git_clone_options, opts *CloneOptions) {
@@ -57,7 +55,7 @@ func populateCloneOptions(ptr *C.git_clone_options, opts *CloneOptions) {
return
}
populateCheckoutOpts(&ptr.checkout_opts, opts.CheckoutOpts)
- populateRemoteCallbacks(&ptr.remote_callbacks, opts.RemoteCallbacks)
+ populateFetchOptions(&ptr.fetch_opts, opts.FetchOptions)
ptr.bare = cbool(opts.Bare)
if opts.RemoteCreateCallback != nil {
diff --git a/clone_test.go b/clone_test.go
index fd83fec..7cdc362 100644
--- a/clone_test.go
+++ b/clone_test.go
@@ -15,8 +15,18 @@ func TestClone(t *testing.T) {
path, err := ioutil.TempDir("", "git2go")
checkFatal(t, err)
+ ref, err := repo.References.Lookup("refs/heads/master")
+ checkFatal(t, err)
+
repo2, err := Clone(repo.Path(), path, &CloneOptions{Bare: true})
defer cleanupTestRepo(t, repo2)
checkFatal(t, err)
+
+ ref2, err := repo2.References.Lookup("refs/heads/master")
+ checkFatal(t, err)
+
+ if ref.Cmp(ref2) != 0 {
+ t.Fatal("reference in clone does not match original ref")
+ }
}
diff --git a/git.go b/git.go
index a44459f..34d58e6 100644
--- a/git.go
+++ b/git.go
@@ -3,7 +3,6 @@ package git
/*
#include <git2.h>
#include <git2/sys/openssl.h>
-#cgo pkg-config: libgit2
*/
import "C"
import (
@@ -77,8 +76,8 @@ const (
ErrNonFastForward ErrorCode = C.GIT_ENONFASTFORWARD
// Name/ref spec was not in a valid format
ErrInvalidSpec ErrorCode = C.GIT_EINVALIDSPEC
- // Merge conflicts prevented operation
- ErrMergeConflict ErrorCode = C.GIT_EMERGECONFLICT
+ // Checkout conflicts prevented operation
+ ErrConflict ErrorCode = C.GIT_ECONFLICT
// Lock file prevented operation
ErrLocked ErrorCode = C.GIT_ELOCKED
// Reference value does not match expected
diff --git a/index.go b/index.go
index c1bfb74..0174dc1 100644
--- a/index.go
+++ b/index.go
@@ -12,7 +12,6 @@ import "C"
import (
"fmt"
"runtime"
- "time"
"unsafe"
)
@@ -31,13 +30,18 @@ type Index struct {
ptr *C.git_index
}
+type IndexTime struct {
+ seconds int32
+ nanoseconds uint32
+}
+
type IndexEntry struct {
- Ctime time.Time
- Mtime time.Time
+ Ctime IndexTime
+ Mtime IndexTime
Mode Filemode
- Uid uint
- Gid uint
- Size uint
+ Uid uint32
+ Gid uint32
+ Size uint32
Id *Oid
Path string
}
@@ -47,26 +51,26 @@ func newIndexEntryFromC(entry *C.git_index_entry) *IndexEntry {
return nil
}
return &IndexEntry{
- time.Unix(int64(entry.ctime.seconds), int64(entry.ctime.nanoseconds)),
- time.Unix(int64(entry.mtime.seconds), int64(entry.mtime.nanoseconds)),
+ IndexTime { int32(entry.ctime.seconds), uint32(entry.ctime.nanoseconds) },
+ IndexTime { int32(entry.mtime.seconds), uint32(entry.mtime.nanoseconds) },
Filemode(entry.mode),
- uint(entry.uid),
- uint(entry.gid),
- uint(entry.file_size),
+ uint32(entry.uid),
+ uint32(entry.gid),
+ uint32(entry.file_size),
newOidFromC(&entry.id),
C.GoString(entry.path),
}
}
func populateCIndexEntry(source *IndexEntry, dest *C.git_index_entry) {
- dest.ctime.seconds = C.git_time_t(source.Ctime.Unix())
- dest.ctime.nanoseconds = C.uint(source.Ctime.UnixNano())
- dest.mtime.seconds = C.git_time_t(source.Mtime.Unix())
- dest.mtime.nanoseconds = C.uint(source.Mtime.UnixNano())
- dest.mode = C.uint(source.Mode)
- dest.uid = C.uint(source.Uid)
- dest.gid = C.uint(source.Gid)
- dest.file_size = C.git_off_t(source.Size)
+ dest.ctime.seconds = C.int32_t(source.Ctime.seconds)
+ dest.ctime.nanoseconds = C.uint32_t(source.Ctime.nanoseconds)
+ dest.mtime.seconds = C.int32_t(source.Mtime.seconds)
+ dest.mtime.nanoseconds = C.uint32_t(source.Mtime.nanoseconds)
+ dest.mode = C.uint32_t(source.Mode)
+ dest.uid = C.uint32_t(source.Uid)
+ dest.gid = C.uint32_t(source.Gid)
+ dest.file_size = C.uint32_t(source.Size)
dest.id = *source.Id.toC()
dest.path = C.CString(source.Path)
}
diff --git a/merge.go b/merge.go
index 5b68a8b..65dc03e 100644
--- a/merge.go
+++ b/merge.go
@@ -84,8 +84,8 @@ const (
)
type MergeOptions struct {
- Version uint
- Flags MergeTreeFlag
+ Version uint
+ TreeFlags MergeTreeFlag
RenameThreshold uint
TargetLimit uint
@@ -97,7 +97,7 @@ type MergeOptions struct {
func mergeOptionsFromC(opts *C.git_merge_options) MergeOptions {
return MergeOptions{
Version: uint(opts.version),
- Flags: MergeTreeFlag(opts.flags),
+ TreeFlags: MergeTreeFlag(opts.tree_flags),
RenameThreshold: uint(opts.rename_threshold),
TargetLimit: uint(opts.target_limit),
FileFavor: MergeFileFavor(opts.file_favor),
@@ -123,7 +123,7 @@ func (mo *MergeOptions) toC() *C.git_merge_options {
}
return &C.git_merge_options{
version: C.uint(mo.Version),
- flags: C.git_merge_tree_flag_t(mo.Flags),
+ tree_flags: C.git_merge_tree_flag_t(mo.TreeFlags),
rename_threshold: C.uint(mo.RenameThreshold),
target_limit: C.uint(mo.TargetLimit),
file_favor: C.git_merge_file_favor_t(mo.FileFavor),
@@ -333,7 +333,7 @@ func populateCMergeFileOptions(c *C.git_merge_file_options, options MergeFileOpt
c.our_label = C.CString(options.OurLabel)
c.their_label = C.CString(options.TheirLabel)
c.favor = C.git_merge_file_favor_t(options.Favor)
- c.flags = C.git_merge_file_flags_t(options.Flags)
+ c.flags = C.uint(options.Flags)
}
func freeCMergeFileOptions(c *C.git_merge_file_options) {
diff --git a/merge_test.go b/merge_test.go
index 0b1faca..5c62f5c 100644
--- a/merge_test.go
+++ b/merge_test.go
@@ -10,7 +10,7 @@ func TestMergeWithSelf(t *testing.T) {
seedTestRepo(t, repo)
- master, err := repo.LookupReference("refs/heads/master")
+ master, err := repo.References.Lookup("refs/heads/master")
checkFatal(t, err)
mergeHead, err := repo.AnnotatedCommitFromRef(master)
@@ -28,7 +28,7 @@ func TestMergeAnalysisWithSelf(t *testing.T) {
seedTestRepo(t, repo)
- master, err := repo.LookupReference("refs/heads/master")
+ master, err := repo.References.Lookup("refs/heads/master")
checkFatal(t, err)
mergeHead, err := repo.AnnotatedCommitFromRef(master)
diff --git a/note.go b/note.go
index 3cdd340..a1b15d8 100644
--- a/note.go
+++ b/note.go
@@ -10,6 +10,127 @@ import (
"unsafe"
)
+// This object represents the possible operations which can be
+// performed on the collection of notes for a repository.
+type NoteCollection struct {
+ repo *Repository
+}
+
+// Create adds a note for an object
+func (c *NoteCollection) Create(
+ ref string, author, committer *Signature, id *Oid,
+ note string, force bool) (*Oid, error) {
+
+ oid := new(Oid)
+
+ var cref *C.char
+ if ref == "" {
+ cref = nil
+ } else {
+ cref = C.CString(ref)
+ defer C.free(unsafe.Pointer(cref))
+ }
+
+ authorSig, err := author.toC()
+ if err != nil {
+ return nil, err
+ }
+ defer C.git_signature_free(authorSig)
+
+ committerSig, err := committer.toC()
+ if err != nil {
+ return nil, err
+ }
+ defer C.git_signature_free(committerSig)
+
+ cnote := C.CString(note)
+ defer C.free(unsafe.Pointer(cnote))
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_note_create(
+ oid.toC(), c.repo.ptr, cref, authorSig,
+ committerSig, id.toC(), cnote, cbool(force))
+
+ if ret < 0 {
+ return nil, MakeGitError(ret)
+ }
+ return oid, nil
+}
+
+// Read reads the note for an object
+func (c *NoteCollection) Read(ref string, id *Oid) (*Note, error) {
+ var cref *C.char
+ if ref == "" {
+ cref = nil
+ } else {
+ cref = C.CString(ref)
+ defer C.free(unsafe.Pointer(cref))
+ }
+
+ note := new(Note)
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ if ret := C.git_note_read(&note.ptr, c.repo.ptr, cref, id.toC()); ret < 0 {
+ return nil, MakeGitError(ret)
+ }
+
+ runtime.SetFinalizer(note, (*Note).Free)
+ return note, nil
+}
+
+// Remove removes the note for an object
+func (c *NoteCollection) Remove(ref string, author, committer *Signature, id *Oid) error {
+ var cref *C.char
+ if ref == "" {
+ cref = nil
+ } else {
+ cref = C.CString(ref)
+ defer C.free(unsafe.Pointer(cref))
+ }
+
+ authorSig, err := author.toC()
+ if err != nil {
+ return err
+ }
+ defer C.git_signature_free(authorSig)
+
+ committerSig, err := committer.toC()
+ if err != nil {
+ return err
+ }
+ defer C.git_signature_free(committerSig)
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_note_remove(c.repo.ptr, cref, authorSig, committerSig, id.toC())
+ if ret < 0 {
+ return MakeGitError(ret)
+ }
+ return nil
+}
+
+// DefaultRef returns the default notes reference for a repository
+func (c *NoteCollection) DefaultRef() (string, error) {
+ buf := C.git_buf{}
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ if ret := C.git_note_default_ref(&buf, c.repo.ptr); ret < 0 {
+ return "", MakeGitError(ret)
+ }
+
+ ret := C.GoString(buf.ptr)
+ C.git_buf_free(&buf)
+
+ return ret, nil
+}
+
// Note
type Note struct {
ptr *C.git_note
diff --git a/note_test.go b/note_test.go
index e6c378d..27e04be 100644
--- a/note_test.go
+++ b/note_test.go
@@ -53,7 +53,7 @@ func TestNoteIterator(t *testing.T) {
break
}
- note, err := repo.ReadNote("", commitId)
+ note, err := repo.Notes.Read("", commitId)
checkFatal(t, err)
if !reflect.DeepEqual(note.Id(), noteId) {
@@ -73,13 +73,13 @@ func TestRemoveNote(t *testing.T) {
note, _ := createTestNote(t, repo, commit)
- _, err = repo.ReadNote("", commit.Id())
+ _, err = repo.Notes.Read("", commit.Id())
checkFatal(t, err)
- err = repo.RemoveNote("", note.Author(), note.Committer(), commitId)
+ err = repo.Notes.Remove("", note.Author(), note.Committer(), commitId)
checkFatal(t, err)
- _, err = repo.ReadNote("", commit.Id())
+ _, err = repo.Notes.Read("", commit.Id())
if err == nil {
t.Fatal("note remove failed")
}
@@ -89,7 +89,7 @@ func TestDefaultNoteRef(t *testing.T) {
repo := createTestRepo(t)
defer cleanupTestRepo(t, repo)
- ref, err := repo.DefaultNoteRef()
+ ref, err := repo.Notes.DefaultRef()
checkFatal(t, err)
compareStrings(t, "refs/notes/commits", ref)
@@ -103,10 +103,10 @@ func createTestNote(t *testing.T, repo *Repository, commit *Commit) (*Note, *Oid
When: time.Date(2015, 01, 05, 13, 0, 0, 0, loc),
}
- noteId, err := repo.CreateNote("", sig, sig, commit.Id(), "I am a note\n", false)
+ noteId, err := repo.Notes.Create("", sig, sig, commit.Id(), "I am a note\n", false)
checkFatal(t, err)
- note, err := repo.ReadNote("", commit.Id())
+ note, err := repo.Notes.Read("", commit.Id())
checkFatal(t, err)
return note, noteId
diff --git a/odb.go b/odb.go
index 6b21329..be0870e 100644
--- a/odb.go
+++ b/odb.go
@@ -11,6 +11,7 @@ import (
"reflect"
"runtime"
"unsafe"
+ "fmt"
)
type Odb struct {
@@ -106,7 +107,9 @@ func odbForEachCb(id *C.git_oid, handle unsafe.Pointer) int {
}
err := data.callback(newOidFromC(id))
+ fmt.Println("err %v", err)
if err != nil {
+ fmt.Println("returning EUSER")
data.err = err
return C.GIT_EUSER
}
@@ -127,6 +130,7 @@ func (v *Odb) ForEach(callback OdbForEachCallback) error {
defer pointerHandles.Untrack(handle)
ret := C._go_git_odb_foreach(v.ptr, handle)
+ fmt.Println("ret %v", ret);
if ret == C.GIT_EUSER {
return data.err
} else if ret < 0 {
@@ -172,13 +176,13 @@ func (v *Odb) NewReadStream(id *Oid) (*OdbReadStream, error) {
// NewWriteStream opens a write stream to the ODB, which allows you to
// create a new object in the database. The size and type must be
// known in advance
-func (v *Odb) NewWriteStream(size int, otype ObjectType) (*OdbWriteStream, error) {
+func (v *Odb) NewWriteStream(size int64, otype ObjectType) (*OdbWriteStream, error) {
stream := new(OdbWriteStream)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_odb_open_wstream(&stream.ptr, v.ptr, C.size_t(size), C.git_otype(otype))
+ ret := C.git_odb_open_wstream(&stream.ptr, v.ptr, C.git_off_t(size), C.git_otype(otype))
if ret < 0 {
return nil, MakeGitError(ret)
}
diff --git a/odb_test.go b/odb_test.go
index 2fb6840..0d765b9 100644
--- a/odb_test.go
+++ b/odb_test.go
@@ -17,7 +17,7 @@ func TestOdbStream(t *testing.T) {
str := "hello, world!"
- stream, error := odb.NewWriteStream(len(str), ObjectBlob)
+ stream, error := odb.NewWriteStream(int64(len(str)), ObjectBlob)
checkFatal(t, error)
n, error := io.WriteString(stream, str)
checkFatal(t, error)
diff --git a/push_test.go b/push_test.go
index e36e407..8f6e806 100644
--- a/push_test.go
+++ b/push_test.go
@@ -11,17 +11,17 @@ func TestRemotePush(t *testing.T) {
localRepo := createTestRepo(t)
defer cleanupTestRepo(t, localRepo)
- remote, err := localRepo.CreateRemote("test_push", repo.Path())
+ remote, err := localRepo.Remotes.Create("test_push", repo.Path())
checkFatal(t, err)
seedTestRepo(t, localRepo)
- err = remote.Push([]string{"refs/heads/master"}, nil, nil, "")
+ err = remote.Push([]string{"refs/heads/master"}, nil)
checkFatal(t, err)
- _, err = localRepo.LookupReference("refs/remotes/test_push/master")
+ _, err = localRepo.References.Lookup("refs/remotes/test_push/master")
checkFatal(t, err)
- _, err = repo.LookupReference("refs/heads/master")
+ _, err = repo.References.Lookup("refs/heads/master")
checkFatal(t, err)
}
diff --git a/reference.go b/reference.go
index ac3580c..d24e054 100644
--- a/reference.go
+++ b/reference.go
@@ -21,13 +21,137 @@ type Reference struct {
repo *Repository
}
+type ReferenceCollection struct {
+ repo *Repository
+}
+
+func (c *ReferenceCollection) Lookup(name string) (*Reference, error) {
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+ var ptr *C.git_reference
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ecode := C.git_reference_lookup(&ptr, c.repo.ptr, cname)
+ if ecode < 0 {
+ return nil, MakeGitError(ecode)
+ }
+
+ return newReferenceFromC(ptr, c.repo), nil
+}
+
+func (c *ReferenceCollection) Create(name string, id *Oid, force bool, msg string) (*Reference, error) {
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+
+ var cmsg *C.char
+ if msg == "" {
+ cmsg = nil
+ } else {
+ cmsg = C.CString(msg)
+ defer C.free(unsafe.Pointer(cmsg))
+ }
+
+ var ptr *C.git_reference
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ecode := C.git_reference_create(&ptr, c.repo.ptr, cname, id.toC(), cbool(force), cmsg)
+ if ecode < 0 {
+ return nil, MakeGitError(ecode)
+ }
+
+ return newReferenceFromC(ptr, c.repo), nil
+}
+
+func (c *ReferenceCollection) CreateSymbolic(name, target string, force bool, msg string) (*Reference, error) {
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+
+ ctarget := C.CString(target)
+ defer C.free(unsafe.Pointer(ctarget))
+
+ var cmsg *C.char
+ if msg == "" {
+ cmsg = nil
+ } else {
+ cmsg = C.CString(msg)
+ defer C.free(unsafe.Pointer(cmsg))
+ }
+
+ var ptr *C.git_reference
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ecode := C.git_reference_symbolic_create(&ptr, c.repo.ptr, cname, ctarget, cbool(force), cmsg)
+ if ecode < 0 {
+ return nil, MakeGitError(ecode)
+ }
+
+ return newReferenceFromC(ptr, c.repo), nil
+}
+
+// EnsureLog ensures that there is a reflog for the given reference
+// name and creates an empty one if necessary.
+func (c *ReferenceCollection) EnsureLog(name string) error {
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_reference_ensure_log(c.repo.ptr, cname)
+ if ret < 0 {
+ return MakeGitError(ret)
+ }
+
+ return nil
+}
+
+// HasLog returns whether there is a reflog for the given reference
+// name
+func (c *ReferenceCollection) HasLog(name string) (bool, error) {
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_reference_has_log(c.repo.ptr, cname)
+ if ret < 0 {
+ return false, MakeGitError(ret)
+ }
+
+ return ret == 1, nil
+}
+
+// Dwim looks up a reference by DWIMing its short name
+func (c *ReferenceCollection) Dwim(name string) (*Reference, error) {
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ var ptr *C.git_reference
+ ret := C.git_reference_dwim(&ptr, c.repo.ptr, cname)
+ if ret < 0 {
+ return nil, MakeGitError(ret)
+ }
+
+ return newReferenceFromC(ptr, c.repo), nil
+}
+
func newReferenceFromC(ptr *C.git_reference, repo *Repository) *Reference {
ref := &Reference{ptr: ptr, repo: repo}
runtime.SetFinalizer(ref, (*Reference).Free)
return ref
}
-func (v *Reference) SetSymbolicTarget(target string, sig *Signature, msg string) (*Reference, error) {
+func (v *Reference) SetSymbolicTarget(target string, msg string) (*Reference, error) {
var ptr *C.git_reference
ctarget := C.CString(target)
@@ -36,12 +160,6 @@ func (v *Reference) SetSymbolicTarget(target string, sig *Signature, msg string)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- csig, err := sig.toC()
- if err != nil {
- return nil, err
- }
- defer C.git_signature_free(csig)
-
var cmsg *C.char
if msg == "" {
cmsg = nil
@@ -50,7 +168,7 @@ func (v *Reference) SetSymbolicTarget(target string, sig *Signature, msg string)
defer C.free(unsafe.Pointer(cmsg))
}
- ret := C.git_reference_symbolic_set_target(&ptr, v.ptr, ctarget, csig, cmsg)
+ ret := C.git_reference_symbolic_set_target(&ptr, v.ptr, ctarget, cmsg)
if ret < 0 {
return nil, MakeGitError(ret)
}
@@ -58,18 +176,12 @@ func (v *Reference) SetSymbolicTarget(target string, sig *Signature, msg string)
return newReferenceFromC(ptr, v.repo), nil
}
-func (v *Reference) SetTarget(target *Oid, sig *Signature, msg string) (*Reference, error) {
+func (v *Reference) SetTarget(target *Oid, msg string) (*Reference, error) {
var ptr *C.git_reference
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- csig, err := sig.toC()
- if err != nil {
- return nil, err
- }
- defer C.git_signature_free(csig)
-
var cmsg *C.char
if msg == "" {
cmsg = nil
@@ -78,7 +190,7 @@ func (v *Reference) SetTarget(target *Oid, sig *Signature, msg string) (*Referen
defer C.free(unsafe.Pointer(cmsg))
}
- ret := C.git_reference_set_target(&ptr, v.ptr, target.toC(), csig, cmsg)
+ ret := C.git_reference_set_target(&ptr, v.ptr, target.toC(), cmsg)
if ret < 0 {
return nil, MakeGitError(ret)
}
@@ -100,17 +212,11 @@ func (v *Reference) Resolve() (*Reference, error) {
return newReferenceFromC(ptr, v.repo), nil
}
-func (v *Reference) Rename(name string, force bool, sig *Signature, msg string) (*Reference, error) {
+func (v *Reference) Rename(name string, force bool, msg string) (*Reference, error) {
var ptr *C.git_reference
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
- csig, err := sig.toC()
- if err != nil {
- return nil, err
- }
- defer C.git_signature_free(csig)
-
var cmsg *C.char
if msg == "" {
cmsg = nil
@@ -122,7 +228,7 @@ func (v *Reference) Rename(name string, force bool, sig *Signature, msg string)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_reference_rename(&ptr, v.ptr, cname, cbool(force), csig, cmsg)
+ ret := C.git_reference_rename(&ptr, v.ptr, cname, cbool(force), cmsg)
if ret < 0 {
return nil, MakeGitError(ret)
diff --git a/reference_test.go b/reference_test.go
index 5720a66..f1546e2 100644
--- a/reference_test.go
+++ b/reference_test.go
@@ -13,21 +13,14 @@ func TestRefModification(t *testing.T) {
commitId, treeId := seedTestRepo(t, repo)
- loc, err := time.LoadLocation("Europe/Berlin")
- checkFatal(t, err)
- sig := &Signature{
- Name: "Rand Om Hacker",
- Email: "[email protected]",
- When: time.Date(2013, 03, 06, 14, 30, 0, 0, loc),
- }
- _, err = repo.CreateReference("refs/tags/tree", treeId, true, sig, "testTreeTag")
+ _, err := repo.References.Create("refs/tags/tree", treeId, true, "testTreeTag")
checkFatal(t, err)
- tag, err := repo.LookupReference("refs/tags/tree")
+ tag, err := repo.References.Lookup("refs/tags/tree")
checkFatal(t, err)
checkRefType(t, tag, ReferenceOid)
- ref, err := repo.LookupReference("HEAD")
+ ref, err := repo.References.Lookup("HEAD")
checkFatal(t, err)
checkRefType(t, ref, ReferenceSymbolic)
@@ -51,9 +44,9 @@ func TestRefModification(t *testing.T) {
t.Fatalf("Wrong ref target")
}
- _, err = tag.Rename("refs/tags/renamed", false, nil, "")
+ _, err = tag.Rename("refs/tags/renamed", false, "")
checkFatal(t, err)
- tag, err = repo.LookupReference("refs/tags/renamed")
+ tag, err = repo.References.Lookup("refs/tags/renamed")
checkFatal(t, err)
checkRefType(t, ref, ReferenceOid)
@@ -84,13 +77,13 @@ func TestReferenceIterator(t *testing.T) {
commitId, err := repo.CreateCommit("HEAD", sig, sig, message, tree)
checkFatal(t, err)
- _, err = repo.CreateReference("refs/heads/one", commitId, true, sig, "headOne")
+ _, err = repo.References.Create("refs/heads/one", commitId, true, "headOne")
checkFatal(t, err)
- _, err = repo.CreateReference("refs/heads/two", commitId, true, sig, "headTwo")
+ _, err = repo.References.Create("refs/heads/two", commitId, true, "headTwo")
checkFatal(t, err)
- _, err = repo.CreateReference("refs/heads/three", commitId, true, sig, "headThree")
+ _, err = repo.References.Create("refs/heads/three", commitId, true, "headThree")
checkFatal(t, err)
iter, err := repo.NewReferenceIterator()
@@ -143,7 +136,7 @@ func TestReferenceOwner(t *testing.T) {
commitId, _ := seedTestRepo(t, repo)
- ref, err := repo.CreateReference("refs/heads/foo", commitId, true, nil, "")
+ ref, err := repo.References.Create("refs/heads/foo", commitId, true, "")
checkFatal(t, err)
owner := ref.Owner()
@@ -162,10 +155,10 @@ func TestUtil(t *testing.T) {
commitId, _ := seedTestRepo(t, repo)
- ref, err := repo.CreateReference("refs/heads/foo", commitId, true, nil, "")
+ ref, err := repo.References.Create("refs/heads/foo", commitId, true, "")
checkFatal(t, err)
- ref2, err := repo.DwimReference("foo")
+ ref2, err := repo.References.Dwim("foo")
checkFatal(t, err)
if ref.Cmp(ref2) != 0 {
@@ -176,7 +169,7 @@ func TestUtil(t *testing.T) {
t.Fatalf("refs/heads/foo has no foo shorthand")
}
- hasLog, err := repo.HasLog("refs/heads/foo")
+ hasLog, err := repo.References.HasLog("refs/heads/foo")
checkFatal(t, err)
if !hasLog {
t.Fatalf("branches have logs by default")
diff --git a/remote.go b/remote.go
index 0635608..6f3c9ea 100644
--- a/remote.go
+++ b/remote.go
@@ -69,6 +69,51 @@ type RemoteCallbacks struct {
PushUpdateReferenceCallback
}
+type FetchPrune uint
+
+const (
+ // Use the setting from the configuration
+ FetchPruneUnspecified FetchPrune = C.GIT_FETCH_PRUNE_UNSPECIFIED
+ // Force pruning on
+ FetchPruneOn FetchPrune = C.GIT_FETCH_PRUNE
+ // Force pruning off
+ FetchNoPrune FetchPrune = C.GIT_FETCH_NO_PRUNE
+)
+
+type DownloadTags uint
+
+const (
+
+ // Use the setting from the configuration.
+ DownloadTagsUnspecified DownloadTags = C.GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED
+ // Ask the server for tags pointing to objects we're already
+ // downloading.
+ DownloadTagsAuto DownloadTags = C.GIT_REMOTE_DOWNLOAD_TAGS_AUTO
+
+ // Don't ask for any tags beyond the refspecs.
+ DownloadTagsNone DownloadTags = C.GIT_REMOTE_DOWNLOAD_TAGS_NONE
+
+ // Ask for the all the tags.
+ DownloadTagsAll DownloadTags = C.GIT_REMOTE_DOWNLOAD_TAGS_ALL
+)
+
+type FetchOptions struct {
+ // Callbacks to use for this fetch operation
+ RemoteCallbacks RemoteCallbacks
+ // Whether to perform a prune after the fetch
+ Prune FetchPrune
+ // Whether to write the results to FETCH_HEAD. Defaults to
+ // on. Leave this default in order to behave like git.
+ UpdateFetchhead bool
+
+ // Determines how to behave regarding tags on the remote, such
+ // as auto-downloading tags for objects we're downloading or
+ // downloading all of them.
+ //
+ // The default is to auto-follow tags.
+ DownloadTags DownloadTags
+}
+
type Remote struct {
ptr *C.git_remote
callbacks RemoteCallbacks
@@ -123,6 +168,12 @@ func newRemoteHeadFromC(ptr *C.git_remote_head) RemoteHead {
}
}
+func untrackCalbacksPayload(callbacks *C.git_remote_callbacks) {
+ if callbacks != nil && callbacks.payload != nil {
+ pointerHandles.Untrack(callbacks.payload)
+ }
+}
+
func populateRemoteCallbacks(ptr *C.git_remote_callbacks, callbacks *RemoteCallbacks) {
C.git_remote_init_callbacks(ptr, C.GIT_REMOTE_CALLBACKS_VERSION)
if callbacks == nil {
@@ -267,41 +318,22 @@ func RemoteIsValidName(name string) bool {
return false
}
-func (r *Remote) SetCallbacks(callbacks *RemoteCallbacks) error {
- r.callbacks = *callbacks
-
- var ccallbacks C.git_remote_callbacks
- populateRemoteCallbacks(&ccallbacks, &r.callbacks)
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ecode := C.git_remote_set_callbacks(r.ptr, &ccallbacks)
- if ecode < 0 {
- return MakeGitError(ecode)
- }
-
- return nil
-}
-
func (r *Remote) Free() {
runtime.SetFinalizer(r, nil)
-
- callbacks := C.git_remote_get_callbacks(r.ptr)
- if callbacks != nil && callbacks.payload != nil {
- pointerHandles.Untrack(callbacks.payload)
- }
-
C.git_remote_free(r.ptr)
}
-func (repo *Repository) ListRemotes() ([]string, error) {
+type RemoteCollection struct {
+ repo *Repository
+}
+
+func (c *RemoteCollection) List() ([]string, error) {
var r C.git_strarray
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ecode := C.git_remote_list(&r, repo.ptr)
+ ecode := C.git_remote_list(&r, c.repo.ptr)
if ecode < 0 {
return nil, MakeGitError(ecode)
}
@@ -311,7 +343,7 @@ func (repo *Repository) ListRemotes() ([]string, error) {
return remotes, nil
}
-func (repo *Repository) CreateRemote(name string, url string) (*Remote, error) {
+func (c *RemoteCollection) Create(name string, url string) (*Remote, error) {
remote := &Remote{}
cname := C.CString(name)
@@ -322,7 +354,7 @@ func (repo *Repository) CreateRemote(name string, url string) (*Remote, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_remote_create(&remote.ptr, repo.ptr, cname, curl)
+ ret := C.git_remote_create(&remote.ptr, c.repo.ptr, cname, curl)
if ret < 0 {
return nil, MakeGitError(ret)
}
@@ -330,21 +362,21 @@ func (repo *Repository) CreateRemote(name string, url string) (*Remote, error) {
return remote, nil
}
-func (repo *Repository) DeleteRemote(name string) error {
+func (c *RemoteCollection) Delete(name string) error {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_remote_delete(repo.ptr, cname)
+ ret := C.git_remote_delete(c.repo.ptr, cname)
if ret < 0 {
return MakeGitError(ret)
}
return nil
}
-func (repo *Repository) CreateRemoteWithFetchspec(name string, url string, fetch string) (*Remote, error) {
+func (c *RemoteCollection) CreateWithFetchspec(name string, url string, fetch string) (*Remote, error) {
remote := &Remote{}
cname := C.CString(name)
@@ -357,7 +389,7 @@ func (repo *Repository) CreateRemoteWithFetchspec(name string, url string, fetch
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_remote_create_with_fetchspec(&remote.ptr, repo.ptr, cname, curl, cfetch)
+ ret := C.git_remote_create_with_fetchspec(&remote.ptr, c.repo.ptr, cname, curl, cfetch)
if ret < 0 {
return nil, MakeGitError(ret)
}
@@ -365,18 +397,16 @@ func (repo *Repository) CreateRemoteWithFetchspec(name string, url string, fetch
return remote, nil
}
-func (repo *Repository) CreateAnonymousRemote(url, fetch string) (*Remote, error) {
+func (c *RemoteCollection) CreateAnonymous(url string) (*Remote, error) {
remote := &Remote{}
curl := C.CString(url)
defer C.free(unsafe.Pointer(curl))
- cfetch := C.CString(fetch)
- defer C.free(unsafe.Pointer(cfetch))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_remote_create_anonymous(&remote.ptr, repo.ptr, curl, cfetch)
+ ret := C.git_remote_create_anonymous(&remote.ptr, c.repo.ptr, curl)
if ret < 0 {
return nil, MakeGitError(ret)
}
@@ -384,7 +414,7 @@ func (repo *Repository) CreateAnonymousRemote(url, fetch string) (*Remote, error
return remote, nil
}
-func (repo *Repository) LookupRemote(name string) (*Remote, error) {
+func (c *RemoteCollection) Lookup(name string) (*Remote, error) {
remote := &Remote{}
cname := C.CString(name)
@@ -393,7 +423,7 @@ func (repo *Repository) LookupRemote(name string) (*Remote, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_remote_lookup(&remote.ptr, repo.ptr, cname)
+ ret := C.git_remote_lookup(&remote.ptr, c.repo.ptr, cname)
if ret < 0 {
return nil, MakeGitError(ret)
}
@@ -401,22 +431,6 @@ func (repo *Repository) LookupRemote(name string) (*Remote, error) {
return remote, nil
}
-func (o *Remote) Save() error {
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ret := C.git_remote_save(o.ptr)
- if ret < 0 {
- return MakeGitError(ret)
- }
- return nil
-}
-
-func (o *Remote) Owner() Repository {
- return Repository{C.git_remote_owner(o.ptr)}
-}
-
func (o *Remote) Name() string {
return C.GoString(C.git_remote_name(o.ptr))
}
@@ -429,42 +443,48 @@ func (o *Remote) PushUrl() string {
return C.GoString(C.git_remote_pushurl(o.ptr))
}
-func (o *Remote) SetUrl(url string) error {
+func (c *RemoteCollection) SetUrl(remote, url string) error {
curl := C.CString(url)
defer C.free(unsafe.Pointer(curl))
+ cremote := C.CString(remote)
+ defer C.free(unsafe.Pointer(cremote))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_remote_set_url(o.ptr, curl)
+ ret := C.git_remote_set_url(c.repo.ptr, cremote, curl)
if ret < 0 {
return MakeGitError(ret)
}
return nil
}
-func (o *Remote) SetPushUrl(url string) error {
+func (c *RemoteCollection) SetPushUrl(remote, url string) error {
curl := C.CString(url)
defer C.free(unsafe.Pointer(curl))
+ cremote := C.CString(remote)
+ defer C.free(unsafe.Pointer(cremote))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_remote_set_pushurl(o.ptr, curl)
+ ret := C.git_remote_set_pushurl(c.repo.ptr, cremote, curl)
if ret < 0 {
return MakeGitError(ret)
}
return nil
}
-func (o *Remote) AddFetch(refspec string) error {
+func (c *RemoteCollection) AddFetch(remote, refspec string) error {
crefspec := C.CString(refspec)
defer C.free(unsafe.Pointer(crefspec))
+ cremote := C.CString(remote)
+ defer C.free(unsafe.Pointer(cremote))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_remote_add_fetch(o.ptr, crefspec)
+ ret := C.git_remote_add_fetch(c.repo.ptr, cremote, crefspec)
if ret < 0 {
return MakeGitError(ret)
}
@@ -525,30 +545,16 @@ func (o *Remote) FetchRefspecs() ([]string, error) {
return refspecs, nil
}
-func (o *Remote) SetFetchRefspecs(refspecs []string) error {
- crefspecs := C.git_strarray{}
- crefspecs.count = C.size_t(len(refspecs))
- crefspecs.strings = makeCStringsFromStrings(refspecs)
- defer freeStrarray(&crefspecs)
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ret := C.git_remote_set_fetch_refspecs(o.ptr, &crefspecs)
- if ret < 0 {
- return MakeGitError(ret)
- }
- return nil
-}
-
-func (o *Remote) AddPush(refspec string) error {
+func (c *RemoteCollection) AddPush(remote, refspec string) error {
crefspec := C.CString(refspec)
defer C.free(unsafe.Pointer(crefspec))
+ cremote := C.CString(remote)
+ defer C.free(unsafe.Pointer(cremote))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_remote_add_push(o.ptr, crefspec)
+ ret := C.git_remote_add_push(c.repo.ptr, cremote, crefspec)
if ret < 0 {
return MakeGitError(ret)
}
@@ -570,53 +576,26 @@ func (o *Remote) PushRefspecs() ([]string, error) {
return refspecs, nil
}
-func (o *Remote) SetPushRefspecs(refspecs []string) error {
- crefspecs := C.git_strarray{}
- crefspecs.count = C.size_t(len(refspecs))
- crefspecs.strings = makeCStringsFromStrings(refspecs)
- defer freeStrarray(&crefspecs)
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ret := C.git_remote_set_push_refspecs(o.ptr, &crefspecs)
- if ret < 0 {
- return MakeGitError(ret)
- }
- return nil
-}
-
-func (o *Remote) ClearRefspecs() {
- C.git_remote_clear_refspecs(o.ptr)
-}
-
func (o *Remote) RefspecCount() uint {
return uint(C.git_remote_refspec_count(o.ptr))
}
-func (o *Remote) SetUpdateFetchHead(val bool) {
- C.git_remote_set_update_fetchhead(o.ptr, cbool(val))
-}
-
-func (o *Remote) UpdateFetchHead() bool {
- return C.git_remote_update_fetchhead(o.ptr) > 0
+func populateFetchOptions(options *C.git_fetch_options, opts *FetchOptions) {
+ C.git_fetch_init_options(options, C.GIT_FETCH_OPTIONS_VERSION)
+ if opts == nil {
+ return;
+ }
+ populateRemoteCallbacks(&options.callbacks, &opts.RemoteCallbacks)
+ 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)
}
// Fetch performs a fetch operation. refspecs specifies which refspecs
// to use for this fetch, use an empty list to use the refspecs from
-// the configuration; sig and msg specify what to use for the reflog
-// entries. Leave nil and "" to use defaults.
-func (o *Remote) Fetch(refspecs []string, sig *Signature, msg string) error {
-
- var csig *C.git_signature = nil
- if sig != nil {
- csig, err := sig.toC()
- if err != nil {
- return err
- }
- defer C.git_signature_free(csig)
- }
-
+// the configuration; msg specifies what to use for the reflog
+// entries. Leave "" to use defaults.
+func (o *Remote) Fetch(refspecs []string, opts *FetchOptions, msg string) error {
var cmsg *C.char = nil
if msg != "" {
cmsg = C.CString(msg)
@@ -628,29 +607,36 @@ func (o *Remote) Fetch(refspecs []string, sig *Signature, msg string) error {
crefspecs.strings = makeCStringsFromStrings(refspecs)
defer freeStrarray(&crefspecs)
+ var coptions C.git_fetch_options
+ populateFetchOptions(&coptions, opts);
+ defer untrackCalbacksPayload(&coptions.callbacks)
+
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_remote_fetch(o.ptr, &crefspecs, csig, cmsg)
+ ret := C.git_remote_fetch(o.ptr, &crefspecs, &coptions, cmsg)
if ret < 0 {
return MakeGitError(ret)
}
return nil
}
-func (o *Remote) ConnectFetch() error {
- return o.Connect(ConnectDirectionFetch)
+func (o *Remote) ConnectFetch(callbacks *RemoteCallbacks) error {
+ return o.Connect(ConnectDirectionFetch, callbacks)
}
-func (o *Remote) ConnectPush() error {
- return o.Connect(ConnectDirectionPush)
+func (o *Remote) ConnectPush(callbacks *RemoteCallbacks) error {
+ return o.Connect(ConnectDirectionPush, callbacks)
}
-func (o *Remote) Connect(direction ConnectDirection) error {
+func (o *Remote) Connect(direction ConnectDirection, callbacks *RemoteCallbacks) error {
+ var ccallbacks C.git_remote_callbacks;
+ populateRemoteCallbacks(&ccallbacks, callbacks)
+
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- if ret := C.git_remote_connect(o.ptr, C.git_direction(direction)); ret != 0 {
+ if ret := C.git_remote_connect(o.ptr, C.git_direction(direction), &ccallbacks); ret != 0 {
return MakeGitError(ret)
}
return nil
@@ -702,24 +688,7 @@ func (o *Remote) Ls(filterRefs ...string) ([]RemoteHead, error) {
return heads, nil
}
-func (o *Remote) Push(refspecs []string, opts *PushOptions, sig *Signature, msg string) error {
- var csig *C.git_signature = nil
- if sig != nil {
- csig, err := sig.toC()
- if err != nil {
- return err
- }
- defer C.git_signature_free(csig)
- }
-
- var cmsg *C.char
- if msg == "" {
- cmsg = nil
- } else {
- cmsg = C.CString(msg)
- defer C.free(unsafe.Pointer(cmsg))
- }
-
+func (o *Remote) Push(refspecs []string, opts *PushOptions) error {
var copts C.git_push_options
C.git_push_init_options(&copts, C.GIT_PUSH_OPTIONS_VERSION)
if opts != nil {
@@ -733,8 +702,9 @@ func (o *Remote) Push(refspecs []string, opts *PushOptions, sig *Signature, msg
runtime.LockOSThread()
defer runtime.UnlockOSThread()
+ defer untrackCalbacksPayload(&copts.callbacks)
- ret := C.git_remote_push(o.ptr, &crefspecs, &copts, csig, cmsg)
+ ret := C.git_remote_push(o.ptr, &crefspecs, &copts)
if ret < 0 {
return MakeGitError(ret)
}
@@ -745,11 +715,14 @@ func (o *Remote) PruneRefs() bool {
return C.git_remote_prune_refs(o.ptr) > 0
}
-func (o *Remote) Prune() error {
+func (o *Remote) Prune(callbacks *RemoteCallbacks) error {
+ var ccallbacks C.git_remote_callbacks;
+ populateRemoteCallbacks(&ccallbacks, callbacks)
+
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_remote_prune(o.ptr)
+ ret := C.git_remote_prune(o.ptr, &ccallbacks)
if ret < 0 {
return MakeGitError(ret)
}
diff --git a/remote_test.go b/remote_test.go
index 25ee13d..73c637f 100644
--- a/remote_test.go
+++ b/remote_test.go
@@ -3,35 +3,13 @@ package git
import (
"fmt"
"testing"
- "time"
)
-func TestRefspecs(t *testing.T) {
- repo := createTestRepo(t)
- defer cleanupTestRepo(t, repo)
-
- remote, err := repo.CreateAnonymousRemote("git://foo/bar", "refs/heads/*:refs/heads/*")
- checkFatal(t, err)
-
- expected := []string{
- "refs/heads/*:refs/remotes/origin/*",
- "refs/pull/*/head:refs/remotes/origin/*",
- }
-
- err = remote.SetFetchRefspecs(expected)
- checkFatal(t, err)
-
- actual, err := remote.FetchRefspecs()
- checkFatal(t, err)
-
- compareStringList(t, expected, actual)
-}
-
func TestListRemotes(t *testing.T) {
repo := createTestRepo(t)
defer cleanupTestRepo(t, repo)
- _, err := repo.CreateRemote("test", "git://foo/bar")
+ _, err := repo.Remotes.Create("test", "git://foo/bar")
checkFatal(t, err)
@@ -39,7 +17,7 @@ func TestListRemotes(t *testing.T) {
"test",
}
- actual, err := repo.ListRemotes()
+ actual, err := repo.Remotes.List()
checkFatal(t, err)
compareStringList(t, expected, actual)
@@ -58,18 +36,18 @@ func TestCertificateCheck(t *testing.T) {
repo := createTestRepo(t)
defer cleanupTestRepo(t, repo)
- remote, err := repo.CreateRemote("origin", "https://github.com/libgit2/TestGitRepository")
+ remote, err := repo.Remotes.Create("origin", "https://github.com/libgit2/TestGitRepository")
checkFatal(t, err)
- callbacks := RemoteCallbacks{
- CertificateCheckCallback: func(cert *Certificate, valid bool, hostname string) ErrorCode {
- return assertHostname(cert, valid, hostname, t)
+ options := FetchOptions {
+ RemoteCallbacks: RemoteCallbacks{
+ CertificateCheckCallback: func(cert *Certificate, valid bool, hostname string) ErrorCode {
+ return assertHostname(cert, valid, hostname, t)
+ },
},
}
- err = remote.SetCallbacks(&callbacks)
- checkFatal(t, err)
- err = remote.Fetch([]string{}, nil, "")
+ err = remote.Fetch([]string{}, &options, "")
checkFatal(t, err)
}
@@ -77,10 +55,10 @@ func TestRemoteConnect(t *testing.T) {
repo := createTestRepo(t)
defer cleanupTestRepo(t, repo)
- remote, err := repo.CreateRemote("origin", "https://github.com/libgit2/TestGitRepository")
+ remote, err := repo.Remotes.Create("origin", "https://github.com/libgit2/TestGitRepository")
checkFatal(t, err)
- err = remote.ConnectFetch()
+ err = remote.ConnectFetch(nil)
checkFatal(t, err)
}
@@ -88,10 +66,10 @@ func TestRemoteLs(t *testing.T) {
repo := createTestRepo(t)
defer cleanupTestRepo(t, repo)
- remote, err := repo.CreateRemote("origin", "https://github.com/libgit2/TestGitRepository")
+ remote, err := repo.Remotes.Create("origin", "https://github.com/libgit2/TestGitRepository")
checkFatal(t, err)
- err = remote.ConnectFetch()
+ err = remote.ConnectFetch(nil)
checkFatal(t, err)
heads, err := remote.Ls()
@@ -106,10 +84,10 @@ func TestRemoteLsFiltering(t *testing.T) {
repo := createTestRepo(t)
defer cleanupTestRepo(t, repo)
- remote, err := repo.CreateRemote("origin", "https://github.com/libgit2/TestGitRepository")
+ remote, err := repo.Remotes.Create("origin", "https://github.com/libgit2/TestGitRepository")
checkFatal(t, err)
- err = remote.ConnectFetch()
+ err = remote.ConnectFetch(nil)
checkFatal(t, err)
heads, err := remote.Ls("master")
@@ -139,10 +117,10 @@ func TestRemotePruneRefs(t *testing.T) {
err = config.SetBool("remote.origin.prune", true)
checkFatal(t, err)
- _, err = repo.CreateRemote("origin", "https://github.com/libgit2/TestGitRepository")
+ _, err = repo.Remotes.Create("origin", "https://github.com/libgit2/TestGitRepository")
checkFatal(t, err)
- remote, err := repo.LookupRemote("origin")
+ remote, err := repo.Remotes.Lookup("origin")
checkFatal(t, err)
if !remote.PruneRefs() {
@@ -159,13 +137,7 @@ func TestRemotePrune(t *testing.T) {
checkFatal(t, err)
defer commit.Free()
- sig := &Signature{
- Name: "Rand Om Hacker",
- Email: "[email protected]",
- When: time.Now(),
- }
-
- remoteRef, err := remoteRepo.CreateBranch("test-prune", commit, true, sig, "branch test-prune")
+ remoteRef, err := remoteRepo.CreateBranch("test-prune", commit, true)
checkFatal(t, err)
repo := createTestRepo(t)
@@ -176,13 +148,13 @@ func TestRemotePrune(t *testing.T) {
defer config.Free()
remoteUrl := fmt.Sprintf("file://%s", remoteRepo.Workdir())
- remote, err := repo.CreateRemote("origin", remoteUrl)
+ remote, err := repo.Remotes.Create("origin", remoteUrl)
checkFatal(t, err)
- err = remote.Fetch([]string{"test-prune"}, sig, "")
+ err = remote.Fetch([]string{"test-prune"}, nil, "")
checkFatal(t, err)
- _, err = repo.CreateReference("refs/remotes/origin/test-prune", head, true, sig, "remote reference")
+ _, err = repo.References.Create("refs/remotes/origin/test-prune", head, true, "remote reference")
checkFatal(t, err)
err = remoteRef.Delete()
@@ -191,16 +163,16 @@ func TestRemotePrune(t *testing.T) {
err = config.SetBool("remote.origin.prune", true)
checkFatal(t, err)
- rr, err := repo.LookupRemote("origin")
+ rr, err := repo.Remotes.Lookup("origin")
checkFatal(t, err)
- err = rr.ConnectFetch()
+ err = rr.ConnectFetch(nil)
checkFatal(t, err)
- err = rr.Prune()
+ err = rr.Prune(nil)
checkFatal(t, err)
- _, err = repo.LookupReference("refs/remotes/origin/test-prune")
+ _, err = repo.References.Lookup("refs/remotes/origin/test-prune")
if err == nil {
t.Fatal("Expected error getting a pruned reference")
}
diff --git a/repository.go b/repository.go
index 996e966..44509af 100644
--- a/repository.go
+++ b/repository.go
@@ -12,76 +12,95 @@ import (
// Repository
type Repository struct {
- ptr *C.git_repository
+ ptr *C.git_repository
+ // Remotes represents the collection of remotes and can be
+ // used to add, remove and configure remotes for this
+ // repository.
+ Remotes RemoteCollection
+ // Submodules represents the collection of submodules and can
+ // be used to add, remove and configure submodules in this
+ // repostiory.
+ Submodules SubmoduleCollection
+ // References represents the collection of references and can
+ // be used to create, remove or update refernces for this repository.
+ References ReferenceCollection
+ // Notes represents the collection of notes and can be used to
+ // read, write and delete notes from this repository.
+ Notes NoteCollection
}
-func OpenRepository(path string) (*Repository, error) {
- repo := new(Repository)
+func newRepositoryFromC(ptr *C.git_repository) *Repository {
+ repo := &Repository{ptr: ptr}
+
+ repo.Remotes.repo = repo
+ repo.Submodules.repo = repo
+ repo.References.repo = repo
+ repo.Notes.repo = repo
+
+ runtime.SetFinalizer(repo, (*Repository).Free)
+ return repo
+}
+
+func OpenRepository(path string) (*Repository, error) {
cpath := C.CString(path)
defer C.free(unsafe.Pointer(cpath))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_repository_open(&repo.ptr, cpath)
+ var ptr *C.git_repository
+ ret := C.git_repository_open(&ptr, cpath)
if ret < 0 {
return nil, MakeGitError(ret)
}
- runtime.SetFinalizer(repo, (*Repository).Free)
- return repo, nil
+ return newRepositoryFromC(ptr), nil
}
func OpenRepositoryExtended(path string) (*Repository, error) {
- repo := new(Repository)
-
cpath := C.CString(path)
defer C.free(unsafe.Pointer(cpath))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_repository_open_ext(&repo.ptr, cpath, 0, nil)
+ var ptr *C.git_repository
+ ret := C.git_repository_open_ext(&ptr, cpath, 0, nil)
if ret < 0 {
return nil, MakeGitError(ret)
}
- runtime.SetFinalizer(repo, (*Repository).Free)
- return repo, nil
+ return newRepositoryFromC(ptr), nil
}
func InitRepository(path string, isbare bool) (*Repository, error) {
- repo := new(Repository)
-
cpath := C.CString(path)
defer C.free(unsafe.Pointer(cpath))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_repository_init(&repo.ptr, cpath, ucbool(isbare))
+ var ptr *C.git_repository
+ ret := C.git_repository_init(&ptr, cpath, ucbool(isbare))
if ret < 0 {
return nil, MakeGitError(ret)
}
- runtime.SetFinalizer(repo, (*Repository).Free)
- return repo, nil
+ return newRepositoryFromC(ptr), nil
}
func NewRepositoryWrapOdb(odb *Odb) (repo *Repository, err error) {
- repo = new(Repository)
-
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_repository_wrap_odb(&repo.ptr, odb.ptr)
+ var ptr *C.git_repository
+ ret := C.git_repository_wrap_odb(&ptr, odb.ptr)
if ret < 0 {
return nil, MakeGitError(ret)
}
- runtime.SetFinalizer(repo, (*Repository).Free)
- return repo, nil
+ return newRepositoryFromC(ptr), nil
}
func (v *Repository) SetRefdb(refdb *Refdb) {
@@ -176,22 +195,6 @@ func (v *Repository) LookupTag(id *Oid) (*Tag, error) {
return obj.(*Tag), nil
}
-func (v *Repository) LookupReference(name string) (*Reference, error) {
- cname := C.CString(name)
- defer C.free(unsafe.Pointer(cname))
- var ptr *C.git_reference
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ecode := C.git_reference_lookup(&ptr, v.ptr, cname)
- if ecode < 0 {
- return nil, MakeGitError(ecode)
- }
-
- return newReferenceFromC(ptr, v), nil
-}
-
func (v *Repository) Head() (*Reference, error) {
var ptr *C.git_reference
@@ -206,49 +209,25 @@ func (v *Repository) Head() (*Reference, error) {
return newReferenceFromC(ptr, v), nil
}
-func (v *Repository) SetHead(refname string, sig *Signature, msg string) error {
+func (v *Repository) SetHead(refname string) error {
cname := C.CString(refname)
defer C.free(unsafe.Pointer(cname))
- csig, err := sig.toC()
- if err != nil {
- return err
- }
- defer C.git_signature_free(csig)
-
- var cmsg *C.char
- if msg != "" {
- cmsg = C.CString(msg)
- defer C.free(unsafe.Pointer(cmsg))
- }
-
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ecode := C.git_repository_set_head(v.ptr, cname, csig, cmsg)
+ ecode := C.git_repository_set_head(v.ptr, cname)
if ecode != 0 {
return MakeGitError(ecode)
}
return nil
}
-func (v *Repository) SetHeadDetached(id *Oid, sig *Signature, msg string) error {
- csig, err := sig.toC()
- if err != nil {
- return err
- }
- defer C.git_signature_free(csig)
-
- var cmsg *C.char
- if msg != "" {
- cmsg = C.CString(msg)
- defer C.free(unsafe.Pointer(cmsg))
- }
-
+func (v *Repository) SetHeadDetached(id *Oid) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ecode := C.git_repository_set_head_detached(v.ptr, id.toC(), csig, cmsg)
+ ecode := C.git_repository_set_head_detached(v.ptr, id.toC())
if ecode != 0 {
return MakeGitError(ecode)
}
@@ -267,71 +246,6 @@ func (v *Repository) IsHeadDetached() (bool, error) {
return ret != 0, nil
}
-func (v *Repository) CreateReference(name string, id *Oid, force bool, sig *Signature, msg string) (*Reference, error) {
- cname := C.CString(name)
- defer C.free(unsafe.Pointer(cname))
-
- csig, err := sig.toC()
- if err != nil {
- return nil, err
- }
- defer C.git_signature_free(csig)
-
- var cmsg *C.char
- if msg == "" {
- cmsg = nil
- } else {
- cmsg = C.CString(msg)
- defer C.free(unsafe.Pointer(cmsg))
- }
-
- var ptr *C.git_reference
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ecode := C.git_reference_create(&ptr, v.ptr, cname, id.toC(), cbool(force), csig, cmsg)
- if ecode < 0 {
- return nil, MakeGitError(ecode)
- }
-
- return newReferenceFromC(ptr, v), nil
-}
-
-func (v *Repository) CreateSymbolicReference(name, target string, force bool, sig *Signature, msg string) (*Reference, error) {
- cname := C.CString(name)
- defer C.free(unsafe.Pointer(cname))
-
- ctarget := C.CString(target)
- defer C.free(unsafe.Pointer(ctarget))
-
- csig, err := sig.toC()
- if err != nil {
- return nil, err
- }
- defer C.git_signature_free(csig)
-
- var cmsg *C.char
- if msg == "" {
- cmsg = nil
- } else {
- cmsg = C.CString(msg)
- defer C.free(unsafe.Pointer(cmsg))
- }
-
- var ptr *C.git_reference
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ecode := C.git_reference_symbolic_create(&ptr, v.ptr, cname, ctarget, cbool(force), csig, cmsg)
- if ecode < 0 {
- return nil, MakeGitError(ecode)
- }
-
- return newReferenceFromC(ptr, v), nil
-}
-
func (v *Repository) Walk() (*RevWalk, error) {
var walkPtr *C.git_revwalk
@@ -513,169 +427,6 @@ func (v *Repository) TreeBuilderFromTree(tree *Tree) (*TreeBuilder, error) {
return bld, nil
}
-// EnsureLog ensures that there is a reflog for the given reference
-// name and creates an empty one if necessary.
-func (v *Repository) EnsureLog(name string) error {
- cname := C.CString(name)
- defer C.free(unsafe.Pointer(cname))
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ret := C.git_reference_ensure_log(v.ptr, cname)
- if ret < 0 {
- return MakeGitError(ret)
- }
-
- return nil
-}
-
-// HasLog returns whether there is a reflog for the given reference
-// name
-func (v *Repository) HasLog(name string) (bool, error) {
- cname := C.CString(name)
- defer C.free(unsafe.Pointer(cname))
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ret := C.git_reference_has_log(v.ptr, cname)
- if ret < 0 {
- return false, MakeGitError(ret)
- }
-
- return ret == 1, nil
-}
-
-// DwimReference looks up a reference by DWIMing its short name
-func (v *Repository) DwimReference(name string) (*Reference, error) {
- cname := C.CString(name)
- defer C.free(unsafe.Pointer(cname))
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- var ptr *C.git_reference
- ret := C.git_reference_dwim(&ptr, v.ptr, cname)
- if ret < 0 {
- return nil, MakeGitError(ret)
- }
-
- return newReferenceFromC(ptr, v), nil
-}
-
-// CreateNote adds a note for an object
-func (v *Repository) CreateNote(
- ref string, author, committer *Signature, id *Oid,
- note string, force bool) (*Oid, error) {
-
- oid := new(Oid)
-
- var cref *C.char
- if ref == "" {
- cref = nil
- } else {
- cref = C.CString(ref)
- defer C.free(unsafe.Pointer(cref))
- }
-
- authorSig, err := author.toC()
- if err != nil {
- return nil, err
- }
- defer C.git_signature_free(authorSig)
-
- committerSig, err := committer.toC()
- if err != nil {
- return nil, err
- }
- defer C.git_signature_free(committerSig)
-
- cnote := C.CString(note)
- defer C.free(unsafe.Pointer(cnote))
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ret := C.git_note_create(
- oid.toC(), v.ptr, cref, authorSig,
- committerSig, id.toC(), cnote, cbool(force))
-
- if ret < 0 {
- return nil, MakeGitError(ret)
- }
- return oid, nil
-}
-
-// ReadNote reads the note for an object
-func (v *Repository) ReadNote(ref string, id *Oid) (*Note, error) {
- var cref *C.char
- if ref == "" {
- cref = nil
- } else {
- cref = C.CString(ref)
- defer C.free(unsafe.Pointer(cref))
- }
-
- note := new(Note)
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- if ret := C.git_note_read(&note.ptr, v.ptr, cref, id.toC()); ret < 0 {
- return nil, MakeGitError(ret)
- }
-
- runtime.SetFinalizer(note, (*Note).Free)
- return note, nil
-}
-
-// RemoveNote removes the note for an object
-func (v *Repository) RemoveNote(ref string, author, committer *Signature, id *Oid) error {
- var cref *C.char
- if ref == "" {
- cref = nil
- } else {
- cref = C.CString(ref)
- defer C.free(unsafe.Pointer(cref))
- }
-
- authorSig, err := author.toC()
- if err != nil {
- return err
- }
- defer C.git_signature_free(authorSig)
-
- committerSig, err := committer.toC()
- if err != nil {
- return err
- }
- defer C.git_signature_free(committerSig)
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ret := C.git_note_remove(v.ptr, cref, authorSig, committerSig, id.toC())
- if ret < 0 {
- return MakeGitError(ret)
- }
- return nil
-}
-
-// DefaultNoteRef returns the default notes reference for a repository
-func (v *Repository) DefaultNoteRef() (string, error) {
- var ptr *C.char
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- if ret := C.git_note_default_ref(&ptr, v.ptr); ret < 0 {
- return "", MakeGitError(ret)
- }
-
- return C.GoString(ptr), nil
-}
-
type RepositoryState int
const (
diff --git a/reset.go b/reset.go
new file mode 100644
index 0000000..b5b7435
--- /dev/null
+++ b/reset.go
@@ -0,0 +1,26 @@
+package git
+
+/*
+#include <git2.h>
+*/
+import "C"
+import "runtime"
+
+type ResetType int
+
+const (
+ ResetSoft ResetType = C.GIT_RESET_SOFT
+ ResetMixed ResetType = C.GIT_RESET_MIXED
+ ResetHard ResetType = C.GIT_RESET_HARD
+)
+
+func (r *Repository) ResetToCommit(commit *Commit, resetType ResetType, opts *CheckoutOpts) error {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+ ret := C.git_reset(r.ptr, commit.gitObject.ptr, C.git_reset_t(resetType), opts.toC())
+
+ if ret < 0 {
+ return MakeGitError(ret)
+ }
+ return nil
+}
diff --git a/reset_test.go b/reset_test.go
new file mode 100644
index 0000000..ec578bd
--- /dev/null
+++ b/reset_test.go
@@ -0,0 +1,45 @@
+package git
+
+import (
+ "io/ioutil"
+ "testing"
+)
+
+func TestResetToCommit(t *testing.T) {
+ repo := createTestRepo(t)
+ seedTestRepo(t, repo)
+ // create commit to reset to
+ commitId, _ := updateReadme(t, repo, "testing reset")
+ // create commit to reset from
+ nextCommitId, _ := updateReadme(t, repo, "will be reset")
+
+ // confirm that we wrote "will be reset" to the readme
+ newBytes, err := ioutil.ReadFile(pathInRepo(repo, "README"))
+ checkFatal(t, err)
+ if string(newBytes) != "will be reset" {
+ t.Fatalf("expected %s to equal 'will be reset'", string(newBytes))
+ }
+
+ // confirm that the head of the repo is the next commit id
+ head, err := repo.Head()
+ checkFatal(t, err)
+ if head.Target().String() != nextCommitId.String() {
+ t.Fatalf(
+ "expected to be at latest commit %s, but was %s",
+ nextCommitId.String(),
+ head.Target().String(),
+ )
+ }
+
+ commitToResetTo, err := repo.LookupCommit(commitId)
+ checkFatal(t, err)
+
+ repo.ResetToCommit(commitToResetTo, ResetHard, &CheckoutOpts{})
+
+ // check that the file now reads "testing reset" like it did before
+ bytes, err := ioutil.ReadFile(pathInRepo(repo, "README"))
+ checkFatal(t, err)
+ if string(bytes) != "testing reset" {
+ t.Fatalf("expected %s to equal 'testing reset'", string(bytes))
+ }
+}
diff --git a/revparse_test.go b/revparse_test.go
index 2ccdca2..091a76b 100644
--- a/revparse_test.go
+++ b/revparse_test.go
@@ -34,7 +34,7 @@ func TestRevparseExt(t *testing.T) {
_, treeId := seedTestRepo(t, repo)
- ref, err := repo.CreateReference("refs/heads/master", treeId, true, nil, "")
+ ref, err := repo.References.Create("refs/heads/master", treeId, true, "")
checkFatal(t, err)
obj, ref, err := repo.RevparseExt("master")
diff --git a/script/build-libgit2-static.sh b/script/build-libgit2-static.sh
new file mode 100755
index 0000000..5723721
--- /dev/null
+++ b/script/build-libgit2-static.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+set -ex
+
+VENDORED_PATH=vendor/libgit2
+
+cd $VENDORED_PATH &&
+mkdir -p install/lib &&
+mkdir -p build &&
+cd build &&
+cmake -DTHREADSAFE=ON \
+ -DBUILD_CLAR=OFF \
+ -DBUILD_SHARED_LIBS=OFF \
+ -DCMAKE_C_FLAGS=-fPIC \
+ -DCMAKE_BUILD_TYPE="RelWithDebInfo" \
+ -DCMAKE_INSTALL_PREFIX=../install \
+ .. &&
+
+cmake --build .
diff --git a/script/check-MakeGitError-thread-lock.go b/script/check-MakeGitError-thread-lock.go
index f6b01b3..77411f7 100644
--- a/script/check-MakeGitError-thread-lock.go
+++ b/script/check-MakeGitError-thread-lock.go
@@ -1,3 +1,5 @@
+// +build ignore
+
package main
import (
diff --git a/script/install-libgit2.sh b/script/install-libgit2.sh
new file mode 100755
index 0000000..a6c3202
--- /dev/null
+++ b/script/install-libgit2.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+#
+# Install libgit2 to git2go in dynamic mode on Travis
+#
+
+set -ex
+
+# We don't want to build libgit2 on the next branch, as we carry a
+# submodule with the exact version we support
+if [ "x$TRAVIS_BRANCH" = "xnext" ]; then
+ exit 0
+fi
+
+cd "${HOME}"
+wget -O libgit2-0.22.3.tar.gz https://github.com/libgit2/libgit2/archive/v0.22.1.tar.gz
+tar -xzvf libgit2-0.22.3.tar.gz
+cd libgit2-0.22.1 && mkdir build && cd build
+cmake -DTHREADSAFE=ON -DBUILD_CLAR=OFF -DCMAKE_BUILD_TYPE="RelWithDebInfo" .. && make && sudo make install
+sudo ldconfig
+cd "${TRAVIS_BUILD_DIR}"
diff --git a/script/with-static.sh b/script/with-static.sh
new file mode 100755
index 0000000..3f60e31
--- /dev/null
+++ b/script/with-static.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+set -ex
+
+export BUILD="$PWD/vendor/libgit2/build"
+export PCFILE="$BUILD/libgit2.pc"
+
+FLAGS=$(pkg-config --static --libs $PCFILE) || exit 1
+export CGO_LDFLAGS="$BUILD/libgit2.a -L$BUILD ${FLAGS}"
+export CGO_CFLAGS="-I$PWD/vendor/libgit2/include"
+
+$@
diff --git a/submodule.go b/submodule.go
index 3882462..4a32ce4 100644
--- a/submodule.go
+++ b/submodule.go
@@ -14,9 +14,8 @@ import (
// SubmoduleUpdateOptions
type SubmoduleUpdateOptions struct {
*CheckoutOpts
- *RemoteCallbacks
+ *FetchOptions
CloneCheckoutStrategy CheckoutStrategy
- Signature *Signature
}
// Submodule
@@ -27,7 +26,6 @@ type Submodule struct {
type SubmoduleUpdate int
const (
- SubmoduleUpdateReset SubmoduleUpdate = C.GIT_SUBMODULE_UPDATE_RESET
SubmoduleUpdateCheckout SubmoduleUpdate = C.GIT_SUBMODULE_UPDATE_CHECKOUT
SubmoduleUpdateRebase SubmoduleUpdate = C.GIT_SUBMODULE_UPDATE_REBASE
SubmoduleUpdateMerge SubmoduleUpdate = C.GIT_SUBMODULE_UPDATE_MERGE
@@ -37,7 +35,6 @@ const (
type SubmoduleIgnore int
const (
- SubmoduleIgnoreReset SubmoduleIgnore = C.GIT_SUBMODULE_IGNORE_RESET
SubmoduleIgnoreNone SubmoduleIgnore = C.GIT_SUBMODULE_IGNORE_NONE
SubmoduleIgnoreUntracked SubmoduleIgnore = C.GIT_SUBMODULE_IGNORE_UNTRACKED
SubmoduleIgnoreDirty SubmoduleIgnore = C.GIT_SUBMODULE_IGNORE_DIRTY
@@ -71,13 +68,17 @@ const (
SubmoduleRecurseOndemand SubmoduleRecurse = C.GIT_SUBMODULE_RECURSE_ONDEMAND
)
+type SubmoduleCollection struct {
+ repo *Repository
+}
+
func SubmoduleStatusIsUnmodified(status int) bool {
o := SubmoduleStatus(status) & ^(SubmoduleStatusInHead | SubmoduleStatusInIndex |
SubmoduleStatusInConfig | SubmoduleStatusInWd)
return o == 0
}
-func (repo *Repository) LookupSubmodule(name string) (*Submodule, error) {
+func (c *SubmoduleCollection) Lookup(name string) (*Submodule, error) {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
@@ -86,7 +87,7 @@ func (repo *Repository) LookupSubmodule(name string) (*Submodule, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_submodule_lookup(&sub.ptr, repo.ptr, cname)
+ ret := C.git_submodule_lookup(&sub.ptr, c.repo.ptr, cname)
if ret < 0 {
return nil, MakeGitError(ret)
}
@@ -107,21 +108,21 @@ func SubmoduleVisitor(csub unsafe.Pointer, name *C.char, handle unsafe.Pointer)
}
}
-func (repo *Repository) ForeachSubmodule(cbk SubmoduleCbk) error {
+func (c *SubmoduleCollection) Foreach(cbk SubmoduleCbk) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
handle := pointerHandles.Track(cbk)
defer pointerHandles.Untrack(handle)
- ret := C._go_git_visit_submodule(repo.ptr, handle)
+ ret := C._go_git_visit_submodule(c.repo.ptr, handle)
if ret < 0 {
return MakeGitError(ret)
}
return nil
}
-func (repo *Repository) AddSubmodule(url, path string, use_git_link bool) (*Submodule, error) {
+func (c *SubmoduleCollection) Add(url, path string, use_git_link bool) (*Submodule, error) {
curl := C.CString(url)
defer C.free(unsafe.Pointer(curl))
cpath := C.CString(path)
@@ -132,7 +133,7 @@ func (repo *Repository) AddSubmodule(url, path string, use_git_link bool) (*Subm
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_submodule_add_setup(&sub.ptr, repo.ptr, curl, cpath, cbool(use_git_link))
+ ret := C.git_submodule_add_setup(&sub.ptr, c.repo.ptr, curl, cpath, cbool(use_git_link))
if ret < 0 {
return nil, MakeGitError(ret)
}
@@ -161,23 +162,6 @@ func (sub *Submodule) AddToIndex(write_index bool) error {
return nil
}
-func (sub *Submodule) Save() error {
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ret := C.git_submodule_save(sub.ptr)
- if ret < 0 {
- return MakeGitError(ret)
- }
- return nil
-}
-
-func (sub *Submodule) Owner() *Repository {
- repo := C.git_submodule_owner(sub.ptr)
- //FIXME: how to handle dangling references ?
- return &Repository{repo}
-}
-
func (sub *Submodule) Name() string {
n := C.git_submodule_name(sub.ptr)
return C.GoString(n)
@@ -193,14 +177,16 @@ func (sub *Submodule) Url() string {
return C.GoString(n)
}
-func (sub *Submodule) SetUrl(url string) error {
+func (c *SubmoduleCollection) SetUrl(submodule, url string) error {
+ csubmodule := C.CString(submodule)
+ defer C.free(unsafe.Pointer(csubmodule))
curl := C.CString(url)
defer C.free(unsafe.Pointer(curl))
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_submodule_set_url(sub.ptr, curl)
+ ret := C.git_submodule_set_url(c.repo.ptr, csubmodule, curl)
if ret < 0 {
return MakeGitError(ret)
}
@@ -236,9 +222,19 @@ func (sub *Submodule) Ignore() SubmoduleIgnore {
return SubmoduleIgnore(o)
}
-func (sub *Submodule) SetIgnore(ignore SubmoduleIgnore) SubmoduleIgnore {
- o := C.git_submodule_set_ignore(sub.ptr, C.git_submodule_ignore_t(ignore))
- return SubmoduleIgnore(o)
+func (c *SubmoduleCollection) SetIgnore(submodule string, ignore SubmoduleIgnore) error {
+ csubmodule := C.CString(submodule)
+ defer C.free(unsafe.Pointer(csubmodule))
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_submodule_set_ignore(c.repo.ptr, csubmodule, C.git_submodule_ignore_t(ignore))
+ if ret < 0 {
+ return MakeGitError(ret)
+ }
+
+ return nil
}
func (sub *Submodule) UpdateStrategy() SubmoduleUpdate {
@@ -246,20 +242,33 @@ func (sub *Submodule) UpdateStrategy() SubmoduleUpdate {
return SubmoduleUpdate(o)
}
-func (sub *Submodule) SetUpdate(update SubmoduleUpdate) SubmoduleUpdate {
- o := C.git_submodule_set_update(sub.ptr, C.git_submodule_update_t(update))
- return SubmoduleUpdate(o)
+func (c *SubmoduleCollection) SetUpdate(submodule string, update SubmoduleUpdate) error {
+ csubmodule := C.CString(submodule)
+ defer C.free(unsafe.Pointer(csubmodule))
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_submodule_set_update(c.repo.ptr, csubmodule, C.git_submodule_update_t(update))
+ if ret < 0 {
+ return MakeGitError(ret)
+ }
+
+ return nil
}
func (sub *Submodule) FetchRecurseSubmodules() SubmoduleRecurse {
return SubmoduleRecurse(C.git_submodule_fetch_recurse_submodules(sub.ptr))
}
-func (sub *Submodule) SetFetchRecurseSubmodules(recurse SubmoduleRecurse) error {
+func (c *SubmoduleCollection) SetFetchRecurseSubmodules(submodule string, recurse SubmoduleRecurse) error {
+ csubmodule := C.CString(submodule)
+ defer C.free(unsafe.Pointer(csubmodule))
+
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_submodule_set_fetch_recurse_submodules(sub.ptr, C.git_submodule_recurse_t(recurse))
+ ret := C.git_submodule_set_fetch_recurse_submodules(c.repo.ptr, csubmodule, C.git_submodule_recurse_t(recurse))
if ret < 0 {
return MakeGitError(C.int(ret))
}
@@ -289,38 +298,15 @@ func (sub *Submodule) Sync() error {
}
func (sub *Submodule) Open() (*Repository, error) {
- repo := new(Repository)
-
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C.git_submodule_open(&repo.ptr, sub.ptr)
+ var ptr *C.git_repository
+ ret := C.git_submodule_open(&ptr, sub.ptr)
if ret < 0 {
return nil, MakeGitError(ret)
}
- return repo, nil
-}
-
-func (sub *Submodule) Reload(force bool) error {
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ret := C.git_submodule_reload(sub.ptr, cbool(force))
- if ret < 0 {
- return MakeGitError(ret)
- }
- return nil
-}
-
-func (repo *Repository) ReloadAllSubmodules(force bool) error {
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ret := C.git_submodule_reload_all(repo.ptr, cbool(force))
- if ret < 0 {
- return MakeGitError(ret)
- }
- return nil
+ return newRepositoryFromC(ptr), nil
}
func (sub *Submodule) Update(init bool, opts *SubmoduleUpdateOptions) error {
@@ -349,14 +335,8 @@ func populateSubmoduleUpdateOptions(ptr *C.git_submodule_update_options, opts *S
}
populateCheckoutOpts(&ptr.checkout_opts, opts.CheckoutOpts)
- populateRemoteCallbacks(&ptr.remote_callbacks, opts.RemoteCallbacks)
+ populateFetchOptions(&ptr.fetch_opts, opts.FetchOptions)
ptr.clone_checkout_strategy = C.uint(opts.CloneCheckoutStrategy)
- sig, err := opts.Signature.toC()
- if err != nil {
- return err
- }
- ptr.signature = sig
-
return nil
}
diff --git a/submodule_test.go b/submodule_test.go
index 27bc193..43c890a 100644
--- a/submodule_test.go
+++ b/submodule_test.go
@@ -10,11 +10,11 @@ func TestSubmoduleForeach(t *testing.T) {
seedTestRepo(t, repo)
- _, err := repo.AddSubmodule("http://example.org/submodule", "submodule", true)
+ _, err := repo.Submodules.Add("http://example.org/submodule", "submodule", true)
checkFatal(t, err)
i := 0
- err = repo.ForeachSubmodule(func(sub *Submodule, name string) int {
+ err = repo.Submodules.Foreach(func(sub *Submodule, name string) int {
i++
return 0
})
diff --git a/vendor/libgit2 b/vendor/libgit2
new file mode 160000
+Subproject fb84cde81e11947add4ff8bb9b4084f7d76e656
diff --git a/wrapper.c b/wrapper.c
index 017168d..75cc03c 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -59,7 +59,7 @@ int _go_git_diff_foreach(git_diff *diff, int eachFile, int eachHunk, int eachLin
lcb = (git_diff_line_cb)&diffForEachLineCb;
}
- return git_diff_foreach(diff, fcb, hcb, lcb, payload);
+ return git_diff_foreach(diff, fcb, NULL, hcb, lcb, payload);
}
int _go_git_diff_blobs(git_blob *old, const char *old_path, git_blob *new, const char *new_path, git_diff_options *opts, int eachFile, int eachHunk, int eachLine, void *payload)
@@ -80,7 +80,7 @@ int _go_git_diff_blobs(git_blob *old, const char *old_path, git_blob *new, const
lcb = (git_diff_line_cb)&diffForEachLineCb;
}
- return git_diff_blobs(old, old_path, new, new_path, opts, fcb, hcb, lcb, payload);
+ return git_diff_blobs(old, old_path, new, new_path, opts, fcb, NULL, hcb, lcb, payload);
}
void _go_git_setup_diff_notify_callbacks(git_diff_options *opts) {