1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
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, `"`);
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,
};
}
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 {
die.Fatal("Cannot diff more than two snapshots");
}
fromRel = ToRelative(snapishes[0])
toRel = &Relative{snapshot: "@"}
if len(snapishes) == 2 {
toRel = ToRelative(snapishes[1])
}
return
}
|