-
Notifications
You must be signed in to change notification settings - Fork 52
/
Copy pathrulelib.go
131 lines (113 loc) · 3.63 KB
/
rulelib.go
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package in_toto
import (
"fmt"
"strings"
)
// An error message issued in UnpackRule if it receives a malformed rule.
var errorMsg = "Wrong rule format, available formats are:\n" +
"\tMATCH <pattern> [IN <source-path-prefix>] WITH (MATERIALS|PRODUCTS)" +
" [IN <destination-path-prefix>] FROM <step>,\n" +
"\tCREATE <pattern>,\n" +
"\tDELETE <pattern>,\n" +
"\tMODIFY <pattern>,\n" +
"\tALLOW <pattern>,\n" +
"\tDISALLOW <pattern>,\n" +
"\tREQUIRE <filename>\n\n"
/*
UnpackRule parses the passed rule and extracts and returns the information
required for rule processing. It can be used to verify if a rule has a valid
format. Available rule formats are:
MATCH <pattern> [IN <source-path-prefix>] WITH (MATERIALS|PRODUCTS)
[IN <destination-path-prefix>] FROM <step>,
CREATE <pattern>,
DELETE <pattern>,
MODIFY <pattern>,
ALLOW <pattern>,
DISALLOW <pattern>
Rule tokens are normalized to lower case before returning. The returned map
has the following format:
{
"type": "match" | "create" | "delete" |"modify" | "allow" | "disallow"
"pattern": "<file name pattern>",
"srcPrefix": "<path or empty string>", // MATCH rule only
"dstPrefix": "<path or empty string>", // MATCH rule only
"dstType": "materials" | "products">, // MATCH rule only
"dstName": "<step name>", // Match rule only
}
If the rule does not match any of the available formats the first return value
is nil and the second return value is the error.
*/
func UnpackRule(rule []string) (map[string]string, error) {
// Cache rule len
ruleLen := len(rule)
// Create all lower rule copy to case-insensitively parse out tokens whose
// position we don't know yet. We keep the original rule to retain the
// non-token elements' case.
ruleLower := make([]string, ruleLen)
for i, val := range rule {
ruleLower[i] = strings.ToLower(val)
}
switch ruleLower[0] {
case "create", "modify", "delete", "allow", "disallow", "require":
if ruleLen != 2 {
return nil,
fmt.Errorf("%s Got:\n\t %s", errorMsg, rule)
}
return map[string]string{
"type": ruleLower[0],
"pattern": rule[1],
}, nil
case "match":
var srcPrefix string
var dstType string
var dstPrefix string
var dstName string
// MATCH <pattern> IN <source-path-prefix> WITH (MATERIALS|PRODUCTS) \
// IN <destination-path-prefix> FROM <step>
if ruleLen == 10 && ruleLower[2] == "in" &&
ruleLower[4] == "with" && ruleLower[6] == "in" &&
ruleLower[8] == "from" {
srcPrefix = rule[3]
dstType = ruleLower[5]
dstPrefix = rule[7]
dstName = rule[9]
// MATCH <pattern> IN <source-path-prefix> WITH (MATERIALS|PRODUCTS) \
// FROM <step>
} else if ruleLen == 8 && ruleLower[2] == "in" &&
ruleLower[4] == "with" && ruleLower[6] == "from" {
srcPrefix = rule[3]
dstType = ruleLower[5]
dstPrefix = ""
dstName = rule[7]
// MATCH <pattern> WITH (MATERIALS|PRODUCTS) IN <destination-path-prefix>
// FROM <step>
} else if ruleLen == 8 && ruleLower[2] == "with" &&
ruleLower[4] == "in" && ruleLower[6] == "from" {
srcPrefix = ""
dstType = ruleLower[3]
dstPrefix = rule[5]
dstName = rule[7]
// MATCH <pattern> WITH (MATERIALS|PRODUCTS) FROM <step>
} else if ruleLen == 6 && ruleLower[2] == "with" &&
ruleLower[4] == "from" {
srcPrefix = ""
dstType = ruleLower[3]
dstPrefix = ""
dstName = rule[5]
} else {
return nil,
fmt.Errorf("%s Got:\n\t %s", errorMsg, rule)
}
return map[string]string{
"type": ruleLower[0],
"pattern": rule[1],
"srcPrefix": srcPrefix,
"dstPrefix": dstPrefix,
"dstType": dstType,
"dstName": dstName,
}, nil
default:
return nil,
fmt.Errorf("%s Got:\n\t %s", errorMsg, rule)
}
}