aboutsummaryrefslogtreecommitdiff
path: root/snap
diff options
context:
space:
mode:
Diffstat (limited to 'snap')
-rw-r--r--snap/parsing.go89
-rw-r--r--snap/parsing_test.go31
-rw-r--r--snap/snap.go6
3 files changed, 126 insertions, 0 deletions
diff --git a/snap/parsing.go b/snap/parsing.go
new file mode 100644
index 0000000..a848c33
--- /dev/null
+++ b/snap/parsing.go
@@ -0,0 +1,89 @@
+package snap
+
+import (
+ "strings"
+ "log"
+ "os"
+ "strconv"
+)
+
+var die = log.New(os.Stderr, "", 0)
+
+func isEscaped(str string) bool {
+ n := len(str)
+ return n > 1 && str[0] == '"' && str[n - 1] == '"';
+}
+
+func parseEscaped(snapish string) *Relative {
+ if isEscaped(snapish) {
+ snapshot := strings.Trim(snapish, `"`);
+
+ if(snapshot == "") {
+ die.Fatal("Snapshot cannot be empty \"\"")
+
+ }
+
+ return &Relative {
+ snapshot: snapshot,
+ }
+ }
+
+ return nil
+}
+
+func parseRelativeSyntax(snapish, directionToken string) *Relative {
+ parts := strings.Split(snapish, directionToken)
+ n_parts := len(parts)
+
+ if n_parts == 1 {
+ return nil;
+ }
+
+ // Test if the last the last token is a numeric offset
+ if offset, err := strconv.Atoi(parts[n_parts - 1]);
+ err == nil {
+
+ // Two tokens (e.g. ++ or --) indicates increment syntax
+ if n_parts > 2 && parts[n_parts - 2] == "" {
+ die.Fatal("A snapshot reference cannot be a mix of increment syntax (e.g. my_snap++) and literal syntax (e.g. my_snap+4).")
+ }
+
+ snapshot := strings.TrimRight(snapish, directionToken + "0123456789")
+
+ return &Relative {
+ offset: offset,
+ snapshot: snapshot,
+ }
+ }
+
+ // Parse the increment / decrement syntax
+ // E.g. snapshot+++ or snapshot---
+ offset := 0;
+ for i := n_parts - 1; i >= 1 && parts[i] == ""; i-- {
+ offset += 1
+ }
+
+ return &Relative {
+ offset: offset,
+ snapshot: snapish[:len(snapish) - offset],
+ }
+}
+
+func ToRelative(snapish string) * Relative {
+ if ref := parseEscaped(snapish); ref != nil {
+ return ref;
+ }
+
+ if ref := parseRelativeSyntax(snapish, "+"); ref != nil {
+ return ref;
+ }
+
+ if ref := parseRelativeSyntax(snapish, "-"); ref != nil {
+ ref.offset = -ref.offset;
+ return ref;
+ }
+
+ return &Relative{
+ snapshot: snapish,
+ };
+} \ No newline at end of file
diff --git a/snap/parsing_test.go b/snap/parsing_test.go
new file mode 100644
index 0000000..1a87723
--- /dev/null
+++ b/snap/parsing_test.go
@@ -0,0 +1,31 @@
+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
diff --git a/snap/snap.go b/snap/snap.go
new file mode 100644
index 0000000..fde60c4
--- /dev/null
+++ b/snap/snap.go
@@ -0,0 +1,6 @@
+package snap
+
+type Relative struct {
+ snapshot string
+ offset int
+} \ No newline at end of file