aboutsummaryrefslogtreecommitdiff
path: root/snap
diff options
context:
space:
mode:
Diffstat (limited to 'snap')
-rw-r--r--snap/fs.go82
-rw-r--r--snap/parsing.go29
-rw-r--r--snap/parsing_test.go31
3 files changed, 84 insertions, 58 deletions
diff --git a/snap/fs.go b/snap/fs.go
index d0dc83d..b1cf513 100644
--- a/snap/fs.go
+++ b/snap/fs.go
@@ -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