summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--odb.go23
-rw-r--r--odb_test.go47
2 files changed, 70 insertions, 0 deletions
diff --git a/odb.go b/odb.go
index 994ff2a..d313e3b 100644
--- a/odb.go
+++ b/odb.go
@@ -4,6 +4,7 @@ package git
#include <git2.h>
extern int git_odb_backend_one_pack(git_odb_backend **out, const char *index_file);
+extern int git_odb_backend_loose(git_odb_backend **out, const char *objects_dir, int compression_level, int do_fsync, unsigned int dir_mode, unsigned int file_mode);
extern int _go_git_odb_foreach(git_odb *db, void *payload);
extern void _go_git_odb_backend_free(git_odb_backend *backend);
extern int _go_git_odb_write_pack(git_odb_writepack **out, git_odb *db, void *progress_payload);
@@ -14,6 +15,7 @@ extern void _go_git_odb_writepack_free(git_odb_writepack *writepack);
import "C"
import (
"io"
+ "os"
"reflect"
"runtime"
"unsafe"
@@ -88,6 +90,27 @@ func NewOdbBackendOnePack(packfileIndexPath string) (backend *OdbBackend, err er
return NewOdbBackendFromC(unsafe.Pointer(odbOnePack)), nil
}
+// NewOdbBackendLoose creates a backend for loose objects.
+func NewOdbBackendLoose(objectsDir string, compressionLevel int, doFsync bool, dirMode os.FileMode, fileMode os.FileMode) (backend *OdbBackend, err error) {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ var odbLoose *C.git_odb_backend = nil
+ var doFsyncInt C.int
+ if doFsync {
+ doFsyncInt = C.int(1)
+ }
+
+ cstr := C.CString(objectsDir)
+ defer C.free(unsafe.Pointer(cstr))
+
+ ret := C.git_odb_backend_loose(&odbLoose, cstr, C.int(compressionLevel), doFsyncInt, C.uint(dirMode), C.uint(fileMode))
+ if ret < 0 {
+ return nil, MakeGitError(ret)
+ }
+ return NewOdbBackendFromC(unsafe.Pointer(odbLoose)), nil
+}
+
func (v *Odb) ReadHeader(oid *Oid) (uint64, ObjectType, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
diff --git a/odb_test.go b/odb_test.go
index e44c927..d79afa1 100644
--- a/odb_test.go
+++ b/odb_test.go
@@ -3,8 +3,11 @@ package git
import (
"bytes"
"errors"
+ "fmt"
"io"
"io/ioutil"
+ "os"
+ "path"
"testing"
)
@@ -186,3 +189,47 @@ func TestOdbWritepack(t *testing.T) {
t.Errorf("mismatched indexed objects, expected 3, got %v", finalStats.IndexedObjects)
}
}
+
+func TestOdbBackendLoose(t *testing.T) {
+ t.Parallel()
+ repo := createTestRepo(t)
+ defer cleanupTestRepo(t, repo)
+
+ _, _ = seedTestRepo(t, repo)
+
+ odb, err := repo.Odb()
+ checkFatal(t, err)
+
+ looseObjectsDir, err := ioutil.TempDir("", fmt.Sprintf("loose_objects_%s", path.Base(repo.Path())))
+ checkFatal(t, err)
+ defer os.RemoveAll(looseObjectsDir)
+
+ looseObjectsBackend, err := NewOdbBackendLoose(looseObjectsDir, -1, false, 0, 0)
+ checkFatal(t, err)
+ if err := odb.AddBackend(looseObjectsBackend, 999); err != nil {
+ looseObjectsBackend.Free()
+ checkFatal(t, err)
+ }
+
+ str := "hello, world!"
+
+ writeStream, err := odb.NewWriteStream(int64(len(str)), ObjectBlob)
+ checkFatal(t, err)
+ n, err := io.WriteString(writeStream, str)
+ checkFatal(t, err)
+ if n != len(str) {
+ t.Fatalf("Bad write length %v != %v", n, len(str))
+ }
+
+ err = writeStream.Close()
+ checkFatal(t, err)
+
+ expectedId, err := NewOid("30f51a3fba5274d53522d0f19748456974647b4f")
+ checkFatal(t, err)
+ if !writeStream.Id.Equal(expectedId) {
+ t.Fatalf("writeStream.id = %v; want %v", writeStream.Id, expectedId)
+ }
+
+ _, err = os.Stat(path.Join(looseObjectsDir, expectedId.String()[:2], expectedId.String()[2:]))
+ checkFatal(t, err)
+}