-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgranular.go
More file actions
110 lines (91 loc) · 2.91 KB
/
granular.go
File metadata and controls
110 lines (91 loc) · 2.91 KB
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
package granular
import (
"hash"
"path/filepath"
"sync"
"time"
"github.com/cespare/xxhash/v2"
"github.com/spf13/afero"
)
// HashFunc defines a function that creates a new hash.Hash instance.
type HashFunc func() hash.Hash
// NowFunc defines a function that return the time now.
type NowFunc func() time.Time
// Cache represents the main cache structure.
// It manages the storage and retrieval of cached artifacts.
type Cache struct {
root string // Root directory for the cache
hash hash.Hash // Hash function used for content addressing
now NowFunc // time function to decide what time is now
mu sync.RWMutex // Mutex for concurrent access
fs afero.Fs // Filesystem interface
}
// New creates a new cache instance with the given root directory.
// It uses the default hash function (xxHash) if none is provided.
// It uses the OS filesystem by default, but this can be overridden with WithFs.
func New(root string, options ...Option) (*Cache, error) {
cache := &Cache{
root: root,
fs: afero.NewOsFs(), // Default to OS filesystem
now: time.Now, // Default to stdlib time.Now
hash: defaultHashFunc(), // Default hash provider
}
// Apply options
for _, option := range options {
option(cache)
}
// Create cache directories if they don't exist
if err := cache.fs.MkdirAll(cache.manifestDir(), 0o755); err != nil {
return nil, err
}
if err := cache.fs.MkdirAll(cache.objectsDir(), 0o755); err != nil {
return nil, err
}
return cache, nil
}
// manifestDir returns the path to the manifests directory.
func (c *Cache) manifestDir() string {
return filepath.Join(c.root, "manifests")
}
// objectsDir returns the path to the objects directory.
func (c *Cache) objectsDir() string {
return filepath.Join(c.root, "objects")
}
// Input defines the interface for cache inputs.
// Inputs are used to calculate the cache key.
type Input interface {
// Hash writes the input's content to the hash.
Hash(h hash.Hash) error
// String returns a string representation of the input.
String() string
}
// Key represents a cache key composed of inputs and extra metadata.
type Key struct {
Inputs []Input // Files, globs, raw data
Extra map[string]string // Additional cache key components
}
// Option defines a function that configures a Cache.
type Option func(*Cache)
// WithHashFunc sets the hash function for the cache.
func WithHashFunc(hashFunc HashFunc) Option {
return func(c *Cache) {
c.hash = hashFunc()
}
}
// WithNowFunc sets the Now() function for the cache.
func WithNowFunc(nowFunc NowFunc) Option {
return func(c *Cache) {
c.now = nowFunc
}
}
// WithFs sets the filesystem implementation for the cache.
// This allows using different filesystem implementations like in-memory
// filesystems for testing or remote filesystems.
func WithFs(fs afero.Fs) Option {
return func(c *Cache) {
c.fs = fs
}
}
func defaultHashFunc() hash.Hash {
return xxhash.New()
}