-
Notifications
You must be signed in to change notification settings - Fork 1
/
store.go
130 lines (115 loc) · 3.05 KB
/
store.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package gonix
// #cgo pkg-config: nix-expr-c
// #include <stdlib.h>
// #include <nix_api_store.h>
/*
typedef const char cchar_t;
void nixStoreBuildCallback_cgo(void * userdata, cchar_t * outname, cchar_t * out);
*/
import "C"
import (
"runtime"
"runtime/cgo"
"unsafe"
)
// Store is the interface to the nix store.
type Store struct {
ctx *Context
cstore *C.Store
}
// NewStore creates a new store. See [nix help-stores] for details on the store
// options.
//
// [nix help-stores]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-help-stores.html
func NewStore(ctx *Context, uri string, params map[string]string) (*Store, error) {
cstore := C.nix_store_open(ctx.ccontext, nil, nil)
if cstore == nil {
return nil, ctx.lastError()
}
runtime.SetFinalizer(cstore, finalizeStore)
return &Store{ctx, cstore}, nil
}
func finalizeStore(cstore *C.Store) {
C.nix_store_free(cstore)
}
func (s *Store) context() *Context {
return s.ctx
}
//export nixStoreBuildCallback
func nixStoreBuildCallback(userdata unsafe.Pointer, outname, out *C.cchar_t) {
h := cgo.Handle(userdata)
bo := h.Value().(BuildOutputs)
bo[C.GoString(outname)] = C.GoString(out)
}
// StorePath defines a path in the nix store.
type StorePath struct {
store *Store
cstorepath *C.StorePath
}
// ParsePath parses a path in the nix store.
func (s *Store) ParsePath(path string) (*StorePath, error) {
csp := C.nix_store_parse_path(s.ctx.ccontext, s.cstore, C.CString(path))
err := s.context().lastError()
if err != nil {
return nil, err
}
return &StorePath{s, csp}, nil
}
// Valid returns true if the store path is valid for the owning store.
func (sp *StorePath) Valid() bool {
return bool(C.nix_store_is_valid_path(sp.store.ctx.ccontext, sp.store.cstore, sp.cstorepath))
}
// BuildOutputs is a map for the derivation outputs to output paths.
type BuildOutputs map[string]string
// Build builds the store path, returning the realised outputs.
func (sp *StorePath) Build() (BuildOutputs, error) {
bo := BuildOutputs{}
boh := cgo.NewHandle(bo)
defer boh.Delete()
cerr := C.nix_store_realise(
sp.store.ctx.ccontext,
sp.store.cstore,
sp.cstorepath,
unsafe.Pointer(boh),
(*[0]byte)(C.nixStoreBuildCallback_cgo),
)
err := nixError(cerr, sp.store.context())
if err != nil {
return nil, err
}
return bo, nil
}
// URI returns the URI of the store.
//
// Example:
//
// uri, err := store.URI()
//
// Output:
//
// "daemon", nil
func (s *Store) URI() (string, error) {
var buf *[0]byte
cerr := C.nix_store_get_uri(s.context().ccontext, s.cstore, buf, unsafe.Pointer(nil))
if cerr != C.NIX_OK {
return "", s.context().lastError()
}
return C.GoString((*C.char)(unsafe.Pointer(buf))), nil
}
// Version returns the version of the store.
//
// Example:
//
// ver, err := store.Version()
//
// Output:
//
// "2.13.5", nil
func (s *Store) Version() (string, error) {
var buf *[0]byte
cerr := C.nix_store_get_version(s.context().ccontext, s.cstore, buf, unsafe.Pointer(nil))
if cerr != C.NIX_OK {
return "", s.context().lastError()
}
return C.GoString((*C.char)(unsafe.Pointer(buf))), nil
}