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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
#!/usr/bin/python3
import glob
import json
import sys
import yaml
def check_string(v):
if not isinstance(v, str):
return 'must be a string'
def check_bool(v):
if not isinstance(v, bool):
return 'must be a boolean'
def check_type_string(v):
err = check_string(v)
if err is not None:
return err
if v not in ['bzr', 'cvs', 'git', 'gzip', 'hg', 'svn', 'tarball', 'zip']:
return '"%s" is not a recognised type' % v
def check_stringlist(v):
if not isinstance(v, list):
return 'must be a list'
for elem in v:
if not isinstance(elem, str):
return 'must have strings as elements'
def check_stringdict(v):
if not isinstance(v, dict):
return 'must be a dictionary'
for key, value in v.items():
if not (isinstance(key, str) and isinstance(value, str)):
return 'must have strings as keys and value'
def check_svn_layout(v):
if v == 'standard':
return
if not isinstance(v, dict):
return 'must be either "standard" or a dictionary'
return check_stringdict(v)
def validate(filename, repo_filenames, strict=True):
is_ok = True
repo_name = None
def diagnostic(level, msg):
if repo_name is None:
print('%s: %s: %s' % (level, filename, msg),
file=sys.stderr)
else:
print('%s: %s: %s: %s' % (level, filename, repo_name, msg),
file=sys.stderr)
def error(msg):
nonlocal is_ok
is_ok = False
diagnostic('E', msg)
def warning(msg):
diagnostic('W', msg)
with open(filename) as f:
try:
try:
obj = yaml.safe_load(f)
except yaml.YAMLError:
f.seek(0)
obj = json.load(f)
except ValueError:
error('not valid YAML or JSON')
return is_ok
if not isinstance(obj, dict):
error('must be a dictionary')
return is_ok
for repo_name, upstream_def in obj.items():
if repo_name in repo_filenames:
error('repository already defined in %s'
% repo_filenames[repo_name])
else:
repo_filenames[repo_name] = filename
if not strict:
continue
upstream_type = upstream_def.get('type')
value_checkers = {
# Keys listed in Lorry's README
'type': check_type_string,
'url': check_string,
'check-certificates': check_bool,
'branches': check_stringdict,
'layout': check_svn_layout,
'module': check_string,
# Undocumented Lorry feature
'refspecs': check_stringlist,
# Lorry Controller extension
'description': check_string,
}
required_keys = set(['type'])
optional_keys = set(['refspecs', 'description'])
if upstream_type != 'bzr':
required_keys.add('url')
else:
optional_keys.add('url')
optional_keys.add('branches')
if upstream_type in ['bzr', 'git', 'hg']:
optional_keys.add('check-certificates')
if upstream_type == 'svn':
required_keys.add('layout')
if upstream_type == 'cvs':
required_keys.add('module')
for key in required_keys:
if key not in upstream_def:
error('missing "%s" key' % key)
# For bzr, exactly one of url and branches keys is required
if upstream_type == 'bzr':
has_url = 'url' in upstream_def
has_branches = 'branches' in upstream_def
if has_url and has_branches:
error('has both "url" and "branches" keys')
elif not has_url and not has_branches:
error('missing both "url" and "branches" keys')
for key, value in upstream_def.items():
if key.startswith('x-products-'):
# Baserock Import extension
msg = check_stringlist(value)
else:
if key not in required_keys and key not in optional_keys:
warning('unexpected "%s" key' % key)
if key in value_checkers:
msg = value_checkers[key](value)
else:
msg = None
if msg:
error('%s: %s' % (key, msg))
return is_ok
def main():
repo_filenames = {}
all_ok = True
for filename in glob.glob('*-lorries/*.lorry'):
if not validate(filename, repo_filenames):
all_ok = False
for filename in glob.glob('*-lorries-disabled/*.lorry'):
if not validate(filename, repo_filenames, strict=False):
all_ok = False
sys.exit(0 if all_ok else 1)
if __name__ == '__main__':
main()
|