diff options
Diffstat (limited to 'snap')
-rw-r--r-- | snap/fs.go | 82 | ||||
-rw-r--r-- | snap/parsing.go | 29 | ||||
-rw-r--r-- | snap/parsing_test.go | 31 |
3 files changed, 84 insertions, 58 deletions
@@ -5,6 +5,7 @@ import ( "path/filepath" "os" "sort" + "io" ) type Snapshot struct { @@ -36,6 +37,19 @@ func getZFSRoot(reference string) string { return cursor } +func (snap * Snapshot) tryReference(reference string) { + if _, err := os.Stat(reference); err != nil { + + if !os.IsNotExist(err) { + die.Fatalf("Error encountered while attempting to read reference file in snapshot:\n%v", err) + } + + snap.Reference = "" + } else { + snap.Reference = reference + } +} + func getSnapshots(reference string) []*Snapshot { zfsRoot := getZFSRoot(reference) @@ -43,15 +57,16 @@ func getSnapshots(reference string) []*Snapshot { files, err := os.ReadDir(snapshotDir) if err != nil { - die.Fatalf("Could not find the snapshots directory inside %s", snapshotDir); + die.Fatalf("Could not find the snapshots directory inside \"%s\"", snapshotDir); } relPath, err := filepath.Rel(zfsRoot, reference) if err != nil { - die.Fatal("Could not find relative path to reference file: %v", err) + die.Fatalf("Could not find relative path to reference file: %v", err) } - snaps := make([]*Snapshot, len(files)) + n_snaps := len(files) + 1 + snaps := make([]*Snapshot, n_snaps) for i, file := range files { @@ -68,16 +83,17 @@ func getSnapshots(reference string) []*Snapshot { pathInSnap := filepath.Join(snapshotDir, name, relPath) - if _, err := os.Stat(pathInSnap); err != nil { - if !os.IsNotExist(err) { - die.Fatalf("Error encountered while attempting to read reference file in snapshot:\n%v", err) - } - } else { - snaps[i].Reference = pathInSnap - } + snaps[i].tryReference(pathInSnap) + } + + snaps[n_snaps - 1] = &Snapshot { + ModTime: time.Now(), + Name: "@", } + snaps[n_snaps - 1].tryReference(reference) + return snaps } @@ -97,6 +113,18 @@ func GetTimeseries(reference string) []*Snapshot { return snaps } +func referenceMap(snapTs []*Snapshot) []int { + var trimmed []int + + for i, snap := range snapTs { + if snap.Reference != "" { + trimmed = append(trimmed, i) + } + } + + return trimmed +} + func buildNameMap(snapTs []*Snapshot) map[string] int { namemap := make(map[string] int) @@ -123,15 +151,25 @@ func GetOracle(reference string) *SnapshotOracle { } } -func (oracle *SnapshotOracle) ResolveRelative(ref *Relative) string { +func (oracle *SnapshotOracle) PathTo(ref *Relative) string { n_ts := len(oracle.timeseries) - wanted := n_ts - 1 + nthRef := referenceMap(oracle.timeseries) - if ref.snapshot != "" { + if len(nthRef) == 0 { + die.Fatalf("The reference file is not contained in any snapshot.") + } + + var wanted int + switch (ref.snapshot) { + case "@": + wanted = nthRef[len(nthRef) - 1] + case "%": + wanted = nthRef[0] + default: id, ok := oracle.namemap[ref.snapshot] if !ok { - die.Fatal("Could not find the snapshot %s", ref.snapshot) + die.Fatalf("Could not find the snapshot \"%s\"", ref.snapshot) } wanted = id @@ -144,4 +182,18 @@ func (oracle *SnapshotOracle) ResolveRelative(ref *Relative) string { } return oracle.timeseries[wanted].Reference -}
\ No newline at end of file +} + +func (oracle *SnapshotOracle) ReadAll(ref *Relative) string { + path := oracle.PathTo(ref) + + file, err := os.Open(path) + + data, err := io.ReadAll(file) + + if err != nil { + die.Fatalf("Can't read snapshot.\n%v", err) + } + + return string(data) +} diff --git a/snap/parsing.go b/snap/parsing.go index fcacec9..0d1f09f 100644 --- a/snap/parsing.go +++ b/snap/parsing.go @@ -18,11 +18,6 @@ func parseEscaped(snapish string) *Relative { if isEscaped(snapish) { snapshot := strings.Trim(snapish, `"`); - if(snapshot == "") { - die.Fatal("Snapshot cannot be empty \"\"") - - } - return &Relative { snapshot: snapshot, } @@ -69,7 +64,7 @@ func parseRelativeSyntax(snapish, directionToken string) *Relative { } } -func ToRelative(snapish string) * Relative { +func toRelative(snapish string) * Relative { if ref := parseEscaped(snapish); ref != nil { return ref; } @@ -78,7 +73,7 @@ func ToRelative(snapish string) * Relative { return ref; } - if ref := parseRelativeSyntax(snapish, "^"); ref != nil { + if ref := parseRelativeSyntax(snapish, "-"); ref != nil { ref.offset = -ref.offset; return ref; } @@ -88,16 +83,26 @@ func ToRelative(snapish string) * Relative { }; } -func ParseDiff(snapdiff string) (fromRel, toRel *Relative) { - snapishes := strings.Split(snapdiff, "..") +func ToRelative(snapish string) * Relative { + rel := toRelative(snapish) + + if rel.snapshot == "" { + die.Fatal("Please provide a snapshot. You can use @ for the current filesystem and $ for the last snapshot.") + } + + return rel +} + +func ParseDiff(snapishdiff string) (fromRel, toRel *Relative) { + snapishes := strings.Split(snapishdiff, "..") - if(len(snapishes) > 2) { + if len(snapishes) > 2 { die.Fatal("Cannot diff more than two snapshots"); } fromRel = ToRelative(snapishes[0]) - toRel = &Relative{} - if(len(snapishes) == 2) { + toRel = &Relative{snapshot: "@"} + if len(snapishes) == 2 { toRel = ToRelative(snapishes[1]) } diff --git a/snap/parsing_test.go b/snap/parsing_test.go deleted file mode 100644 index 4aa232e..0000000 --- a/snap/parsing_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package snap - -import "testing" - -func TestRelativeParsing(t * testing.T) { - cases := []struct { - snapish string - snapshot string - offset int - } { - {"snapshot", "snapshot", 0}, - {"testing~~", "testing", -2}, - {"%SNAPSHOT%^+++", "%SNAPSHOT%^", 3}, - {"~~prefixed", "~~prefixed", 0}, - {"+++", "", 3}, - {"~~~", "", -3}, - {"+5", "", 5}, - {"~3", "", -3}, - {"+", "", 1}, - {"~", "", -1}, - {`"~"`, "~", 0}, - } - - for _, c := range cases { - got := ToRelative(c.snapish) - - if got.offset != c.offset || got.snapshot != c.snapshot { - t.Errorf("ToRelative(%s) == %+v, wanted %+v", c.snapish, got, c) - } - } -}
\ No newline at end of file |