Skip to content

Commit 91946a5

Browse files
committed
Add odb.NewOdbBackendLoose()
This change adds support for odb.NewOdbBackendLoose(). This, together with the git.Packbuilder, can do what Mempack does with a lot less memory.
1 parent 05bc5e3 commit 91946a5

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

odb.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package git
44
#include <git2.h>
55
66
extern int git_odb_backend_one_pack(git_odb_backend **out, const char *index_file);
7+
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);
78
extern int _go_git_odb_foreach(git_odb *db, void *payload);
89
extern void _go_git_odb_backend_free(git_odb_backend *backend);
910
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);
1415
import "C"
1516
import (
1617
"io"
18+
"os"
1719
"reflect"
1820
"runtime"
1921
"unsafe"
@@ -88,6 +90,27 @@ func NewOdbBackendOnePack(packfileIndexPath string) (backend *OdbBackend, err er
8890
return NewOdbBackendFromC(unsafe.Pointer(odbOnePack)), nil
8991
}
9092

93+
// NewOdbBackendLoose creates a backend for loose objects.
94+
func NewOdbBackendLoose(objectsDir string, compressionLevel int, doFsync bool, dirMode os.FileMode, fileMode os.FileMode) (backend *OdbBackend, err error) {
95+
runtime.LockOSThread()
96+
defer runtime.UnlockOSThread()
97+
98+
var odbLoose *C.git_odb_backend = nil
99+
var doFsyncInt C.int
100+
if doFsync {
101+
doFsyncInt = C.int(1)
102+
}
103+
104+
cstr := C.CString(objectsDir)
105+
defer C.free(unsafe.Pointer(cstr))
106+
107+
ret := C.git_odb_backend_loose(&odbLoose, cstr, C.int(compressionLevel), doFsyncInt, C.uint(dirMode), C.uint(fileMode))
108+
if ret < 0 {
109+
return nil, MakeGitError(ret)
110+
}
111+
return NewOdbBackendFromC(unsafe.Pointer(odbLoose)), nil
112+
}
113+
91114
func (v *Odb) ReadHeader(oid *Oid) (uint64, ObjectType, error) {
92115
runtime.LockOSThread()
93116
defer runtime.UnlockOSThread()

odb_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ package git
33
import (
44
"bytes"
55
"errors"
6+
"fmt"
67
"io"
78
"io/ioutil"
9+
"os"
10+
"path"
811
"testing"
912
)
1013

@@ -186,3 +189,47 @@ func TestOdbWritepack(t *testing.T) {
186189
t.Errorf("mismatched indexed objects, expected 3, got %v", finalStats.IndexedObjects)
187190
}
188191
}
192+
193+
func TestOdbBackendLoose(t *testing.T) {
194+
t.Parallel()
195+
repo := createTestRepo(t)
196+
defer cleanupTestRepo(t, repo)
197+
198+
_, _ = seedTestRepo(t, repo)
199+
200+
odb, err := repo.Odb()
201+
checkFatal(t, err)
202+
203+
looseObjectsDir, err := ioutil.TempDir("", fmt.Sprintf("loose_objects_%s", path.Base(repo.Path())))
204+
checkFatal(t, err)
205+
defer os.RemoveAll(looseObjectsDir)
206+
207+
looseObjectsBackend, err := NewOdbBackendLoose(looseObjectsDir, -1, false, 0, 0)
208+
checkFatal(t, err)
209+
if err := odb.AddBackend(looseObjectsBackend, 999); err != nil {
210+
looseObjectsBackend.Free()
211+
checkFatal(t, err)
212+
}
213+
214+
str := "hello, world!"
215+
216+
writeStream, err := odb.NewWriteStream(int64(len(str)), ObjectBlob)
217+
checkFatal(t, err)
218+
n, err := io.WriteString(writeStream, str)
219+
checkFatal(t, err)
220+
if n != len(str) {
221+
t.Fatalf("Bad write length %v != %v", n, len(str))
222+
}
223+
224+
err = writeStream.Close()
225+
checkFatal(t, err)
226+
227+
expectedId, err := NewOid("30f51a3fba5274d53522d0f19748456974647b4f")
228+
checkFatal(t, err)
229+
if !writeStream.Id.Equal(expectedId) {
230+
t.Fatalf("writeStream.id = %v; want %v", writeStream.Id, expectedId)
231+
}
232+
233+
_, err = os.Stat(path.Join(looseObjectsDir, expectedId.String()[:2], expectedId.String()[2:]))
234+
checkFatal(t, err)
235+
}

0 commit comments

Comments
 (0)