1package snapshot
2
3import (
4 "encoding/hex"
5 "fmt"
6 "path/filepath"
7 "strconv"
8 "strings"
9
10 "github.com/bnema/vev/internal/domain"
11 "github.com/bnema/vev/internal/ports"
12)
13
14const maxSnapshotFileSize = 16 + (256 << 20)
15
16func incarnationKey(id domain.IncarnationID) (string, error) {
17 if id == (domain.IncarnationID{}) {
18 return "", fmt.Errorf("snapshot: zero incarnation ID")
19 }
20 return id.String(), nil
21}
22
23func (r *Repository) sessionPath(id domain.IncarnationID) string {
24 return filepath.Join(r.dir, repositorySessionsDir, id.String())
25}
26func (r *Repository) objectPath(id domain.IncarnationID, digest ports.SnapshotDigest) string {
27 hexDigest := hex.EncodeToString(digest[:])
28 return filepath.Join(r.sessionPath(id), repositoryObjectsDir, hexDigest[:2], hexDigest)
29}
30func (r *Repository) manifestPath(id domain.IncarnationID, generation uint64) string {
31 return filepath.Join(r.sessionPath(id), repositoryGenerations, generationFilename(generation))
32}
33func (r *Repository) headPath(id domain.IncarnationID) string {
34 return filepath.Join(r.sessionPath(id), repositoryHead)
35}
36
37func generationFilename(generation uint64) string {
38 return fmt.Sprintf("%0*d.manifest", generationWidth, generation)
39}
40func parseGenerationFilename(name string) (uint64, bool) {
41 if !strings.HasSuffix(name, ".manifest") || len(name) != generationWidth+len(".manifest") {
42 return 0, false
43 }
44 n := strings.TrimSuffix(name, ".manifest")
45 generation, err := strconv.ParseUint(n, 10, 64)
46 return generation, err == nil && generationFilename(generation) == name && generation != 0
47}
48
49func parseObjectDigest(name string) (ports.SnapshotDigest, bool) {
50 var digest ports.SnapshotDigest
51 if len(name) != hex.EncodedLen(len(digest)) || strings.ToLower(name) != name {
52 return digest, false
53 }
54 _, err := hex.Decode(digest[:], []byte(name))
55 return digest, err == nil
56}