From fb8aee6c5147b8751a3920f613934d90b79ef4c5 Mon Sep 17 00:00:00 2001 From: flu0r1ne Date: Wed, 21 Jul 2021 23:00:00 -0500 Subject: Added parser for +- syntax for relative references to snapshots --- cmd/cat.go | 5 ++- cmds/list.go | 21 ------------- snap/parsing.go | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++ snap/parsing_test.go | 31 ++++++++++++++++++ snap/snap.go | 6 ++++ 5 files changed, 130 insertions(+), 22 deletions(-) delete mode 100644 cmds/list.go create mode 100644 snap/parsing.go create mode 100644 snap/parsing_test.go create mode 100644 snap/snap.go diff --git a/cmd/cat.go b/cmd/cat.go index 99b48fb..4f54abc 100644 --- a/cmd/cat.go +++ b/cmd/cat.go @@ -2,8 +2,11 @@ package cmd import ( "fmt" + "golang.flu0r1ne.net/zfdiff/snap" ) func Cat(params []string) { - fmt.Println(params) + snapRef := snap.ToRelative(params[0]) + + fmt.Println(snapRef); } \ No newline at end of file diff --git a/cmds/list.go b/cmds/list.go deleted file mode 100644 index 14fa53d..0000000 --- a/cmds/list.go +++ /dev/null @@ -1,21 +0,0 @@ -package cmd - -import ( - "flag" - "fmt" -) - -func List(params []string) { - flags := flag.NewFlagSet("list", flag.ExitOnError) - - var withPaths bool - - const WITH_PATHS_HELP = "print paths to the provided reference within the snapshot" - - flags.BoolVar(&withPaths, "paths", false, WITH_PATHS_HELP); - flags.BoolVar(&withPaths, "p", false, WITH_PATHS_HELP); - - flags.Parse(params); - - fmt.Printf("Your flag is: %t", withPaths); -} 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 -- cgit v1.2.3