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  | 
