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/push_test.go b/push_test.go index a9fc90d..8f6e806 100644 --- a/push_test.go +++ b/push_test.go @@ -19,9 +19,9 @@ func TestRemotePush(t *testing.T) { 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 61e2b26..d24e054 100644 --- a/reference.go +++ b/reference.go @@ -21,6 +21,130 @@ 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) diff --git a/reference_test.go b/reference_test.go index e891e7a..f1546e2 100644 --- a/reference_test.go +++ b/reference_test.go @@ -13,14 +13,14 @@ func TestRefModification(t *testing.T) { commitId, treeId := seedTestRepo(t, repo) - _, err := repo.CreateReference("refs/tags/tree", treeId, true, "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) @@ -46,7 +46,7 @@ func TestRefModification(t *testing.T) { _, 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) @@ -77,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, "headOne") + _, err = repo.References.Create("refs/heads/one", commitId, true, "headOne") checkFatal(t, err) - _, err = repo.CreateReference("refs/heads/two", commitId, true, "headTwo") + _, err = repo.References.Create("refs/heads/two", commitId, true, "headTwo") checkFatal(t, err) - _, err = repo.CreateReference("refs/heads/three", commitId, true, "headThree") + _, err = repo.References.Create("refs/heads/three", commitId, true, "headThree") checkFatal(t, err) iter, err := repo.NewReferenceIterator() @@ -136,7 +136,7 @@ func TestReferenceOwner(t *testing.T) { commitId, _ := seedTestRepo(t, repo) - ref, err := repo.CreateReference("refs/heads/foo", commitId, true, "") + ref, err := repo.References.Create("refs/heads/foo", commitId, true, "") checkFatal(t, err) owner := ref.Owner() @@ -155,10 +155,10 @@ func TestUtil(t *testing.T) { commitId, _ := seedTestRepo(t, repo) - ref, err := repo.CreateReference("refs/heads/foo", commitId, true, "") + 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 { @@ -169,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_test.go b/remote_test.go index 4e64489..73c637f 100644 --- a/remote_test.go +++ b/remote_test.go @@ -154,7 +154,7 @@ func TestRemotePrune(t *testing.T) { err = remote.Fetch([]string{"test-prune"}, nil, "") checkFatal(t, err) - _, err = repo.CreateReference("refs/remotes/origin/test-prune", head, true, "remote reference") + _, err = repo.References.Create("refs/remotes/origin/test-prune", head, true, "remote reference") checkFatal(t, err) err = remoteRef.Delete() @@ -172,7 +172,7 @@ func TestRemotePrune(t *testing.T) { 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 0427d85..8aa39ef 100644 --- a/repository.go +++ b/repository.go @@ -17,15 +17,19 @@ type Repository struct { // used to add, remove and configure remotes for this // repository. Remotes RemoteCollection - // Submodules represents the collectin of submodules and can + // 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 } func initRepositoryObject(repo *Repository) { repo.Remotes.repo = repo repo.Submodules.repo = repo + repo.References.repo = repo runtime.SetFinalizer(repo, (*Repository).Free) } @@ -190,22 +194,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 @@ -245,59 +233,6 @@ func (v *Repository) SetHeadDetached(id *Oid) error { return nil } -func (v *Repository) CreateReference(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, v.ptr, cname, id.toC(), cbool(force), cmsg) - if ecode < 0 { - return nil, MakeGitError(ecode) - } - - return newReferenceFromC(ptr, v), nil -} - -func (v *Repository) CreateSymbolicReference(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, v.ptr, cname, ctarget, cbool(force), cmsg) - if ecode < 0 { - return nil, MakeGitError(ecode) - } - - return newReferenceFromC(ptr, v), nil -} - func (v *Repository) Walk() (*RevWalk, error) { var walkPtr *C.git_revwalk @@ -479,57 +414,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, diff --git a/revparse_test.go b/revparse_test.go index 4bc327c..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, "") + ref, err := repo.References.Create("refs/heads/master", treeId, true, "") checkFatal(t, err) obj, ref, err := repo.RevparseExt("master")