|
| 1 | +package git |
| 2 | + |
| 3 | +/* |
| 4 | +#include <git2.h> |
| 5 | +#include <git2/sys/mempack.h> |
| 6 | +
|
| 7 | +extern int git_mempack_new(git_odb_backend **out); |
| 8 | +extern int git_mempack_dump(git_buf *pack, git_repository *repo, git_odb_backend *backend); |
| 9 | +extern void git_mempack_reset(git_odb_backend *backend); |
| 10 | +extern void _go_git_odb_backend_free(git_odb_backend *backend); |
| 11 | +*/ |
| 12 | +import "C" |
| 13 | + |
| 14 | +import ( |
| 15 | + "runtime" |
| 16 | + "unsafe" |
| 17 | +) |
| 18 | + |
| 19 | +// Mempack is a custom ODB backend that permits packing object in-memory. |
| 20 | +type Mempack struct { |
| 21 | + ptr *C.git_odb_backend |
| 22 | +} |
| 23 | + |
| 24 | +// NewMempack creates a new mempack instance and registers it to the ODB. |
| 25 | +func NewMempack(odb *Odb) (mempack *Mempack, err error) { |
| 26 | + mempack = new(Mempack) |
| 27 | + |
| 28 | + runtime.LockOSThread() |
| 29 | + defer runtime.UnlockOSThread() |
| 30 | + |
| 31 | + ret := C.git_mempack_new(&mempack.ptr) |
| 32 | + if ret < 0 { |
| 33 | + return nil, MakeGitError(ret) |
| 34 | + } |
| 35 | + |
| 36 | + ret = C.git_odb_add_backend(odb.ptr, mempack.ptr, C.int(999)) |
| 37 | + runtime.KeepAlive(odb) |
| 38 | + if ret < 0 { |
| 39 | + // Since git_odb_add_alternate() takes ownership of the ODB backend, the |
| 40 | + // only case in which we free the mempack's memory is if it fails to be |
| 41 | + // added to the ODB. |
| 42 | + C._go_git_odb_backend_free(mempack.ptr) |
| 43 | + return nil, MakeGitError(ret) |
| 44 | + } |
| 45 | + |
| 46 | + return mempack, nil |
| 47 | +} |
| 48 | + |
| 49 | +// Dump dumps all the queued in-memory writes to a packfile. |
| 50 | +// |
| 51 | +// It is the caller's responsibility to ensure that the generated packfile is |
| 52 | +// available to the repository (e.g. by writing it to disk, or doing something |
| 53 | +// crazy like distributing it across several copies of the repository over a |
| 54 | +// network). |
| 55 | +// |
| 56 | +// Once the generated packfile is available to the repository, call |
| 57 | +// Mempack.Reset to cleanup the memory store. |
| 58 | +// |
| 59 | +// Calling Mempack.Reset before the packfile has been written to disk will |
| 60 | +// result in an inconsistent repository (the objects in the memory store won't |
| 61 | +// be accessible). |
| 62 | +func (mempack *Mempack) Dump(repository *Repository) ([]byte, error) { |
| 63 | + buf := C.git_buf{} |
| 64 | + |
| 65 | + runtime.LockOSThread() |
| 66 | + defer runtime.UnlockOSThread() |
| 67 | + |
| 68 | + ret := C.git_mempack_dump(&buf, repository.ptr, mempack.ptr) |
| 69 | + runtime.KeepAlive(repository) |
| 70 | + if ret < 0 { |
| 71 | + return nil, MakeGitError(ret) |
| 72 | + } |
| 73 | + defer C.git_buf_dispose(&buf) |
| 74 | + |
| 75 | + return C.GoBytes(unsafe.Pointer(buf.ptr), C.int(buf.size)), nil |
| 76 | +} |
| 77 | + |
| 78 | +// Reset resets the memory packer by clearing all the queued objects. |
| 79 | +// |
| 80 | +// This assumes that Mempack.Dump has been called before to store all the |
| 81 | +// queued objects into a single packfile. |
| 82 | +func (mempack *Mempack) Reset() { |
| 83 | + C.git_mempack_reset(mempack.ptr) |
| 84 | +} |
0 commit comments