ndr_support 3.1.1 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/code_safety.yml +8 -8
- data/lib/ndr_support/safe_file.rb +8 -2
- data/lib/ndr_support/version.rb +1 -1
- data/lib/tasks/audit_code.rake +124 -86
- data/test/safe_file_test.rb +76 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OTE0YTVkMGEwNDI5ZmZlMDA0NTNmMTBiM2VjNGM3M2UyYjk3YTMwOQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MDFhOTI2YWNmZmE0YTVkZWMyNDIyYjFmOTZiMTVhMDMwMDgzOWMwZQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ODM0NDFhZjMzOTE5NTlmMDgwYmMzMTYzYmY5OTEyYmUxNDhiZTMxMDg4ZDBl
|
10
|
+
NDU4MWIxMzhmMGQwOTg0ZDk1NWVmZmY0MDUwMTA5NzZjYmEyZDgxNWRlMjY5
|
11
|
+
YjQwODRjMGE1ZTY4YmQyMTE4Nzk0YmYxMTIyNmQyNTI3YzE0YTY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OGYxOTg3NDc2NjY4MmE3OTIwNzU5Nzc5OWE5YzgyOTYwZjE4YmIzNjNmYWJi
|
14
|
+
Y2I0OGRiZjE0MGMzNTFiOTExZmFjMGE5OWYzNGM5ZTA2NmEzZDFmZWEwY2U4
|
15
|
+
MjUxMDMxZTBjNGRhYTU3ZmQyYWZmYTA4YzA5NDYxNGRhNWM4M2Q=
|
data/code_safety.yml
CHANGED
@@ -118,8 +118,8 @@ file safety:
|
|
118
118
|
safe_revision: f9341d1c7f797f9fe81af937c383d41c23872b2f
|
119
119
|
lib/ndr_support/safe_file.rb:
|
120
120
|
comments:
|
121
|
-
reviewed_by:
|
122
|
-
safe_revision:
|
121
|
+
reviewed_by: josh.pencheon
|
122
|
+
safe_revision: 24ba08d3a8f4b284678244aaffa2aaa347256900
|
123
123
|
lib/ndr_support/safe_path.rb:
|
124
124
|
comments:
|
125
125
|
reviewed_by: pauleves
|
@@ -158,16 +158,16 @@ file safety:
|
|
158
158
|
safe_revision: f7adf44fc2772e1926df37abfd9041d41c303328
|
159
159
|
lib/ndr_support/version.rb:
|
160
160
|
comments:
|
161
|
-
reviewed_by:
|
162
|
-
safe_revision:
|
161
|
+
reviewed_by: josh.pencheon
|
162
|
+
safe_revision: 312e59a33a7d50aa5be72f536951d96f5907456c
|
163
163
|
lib/ndr_support/yaml/serialization_migration.rb:
|
164
164
|
comments:
|
165
165
|
reviewed_by: timgentry
|
166
166
|
safe_revision: 29595e6431587ff9b7db6e3ad3abbb3577bff99c
|
167
167
|
lib/tasks/audit_code.rake:
|
168
168
|
comments:
|
169
|
-
reviewed_by:
|
170
|
-
safe_revision:
|
169
|
+
reviewed_by: josh.pencheon
|
170
|
+
safe_revision: 7f0e16404f65ad531109e7bf8da3663351aabeb5
|
171
171
|
ndr_support.gemspec:
|
172
172
|
comments:
|
173
173
|
reviewed_by: timgentry
|
@@ -218,8 +218,8 @@ file safety:
|
|
218
218
|
safe_revision: 81061f85ccdf8933adc7f104d7eeaef1e2d71e26
|
219
219
|
test/safe_file_test.rb:
|
220
220
|
comments:
|
221
|
-
reviewed_by:
|
222
|
-
safe_revision:
|
221
|
+
reviewed_by: josh.pencheon
|
222
|
+
safe_revision: 24ba08d3a8f4b284678244aaffa2aaa347256900
|
223
223
|
test/safe_path_test.rb:
|
224
224
|
comments:
|
225
225
|
reviewed_by: timgentry
|
@@ -38,6 +38,12 @@ class SafeFile
|
|
38
38
|
@file.write(data)
|
39
39
|
end
|
40
40
|
|
41
|
+
def each(*args, &block)
|
42
|
+
verify @file_name, 'r'
|
43
|
+
@file.each(*args, &block)
|
44
|
+
end
|
45
|
+
alias_method :each_line, :each
|
46
|
+
|
41
47
|
def path
|
42
48
|
@file_name.clone
|
43
49
|
end
|
@@ -155,7 +161,7 @@ class SafeFile
|
|
155
161
|
prms = nil
|
156
162
|
|
157
163
|
when 2
|
158
|
-
fail
|
164
|
+
fail ArgumentError if args[1].class != Fixnum and args[1].class != String
|
159
165
|
|
160
166
|
if args[1].class == Fixnum
|
161
167
|
verify_mode(args[0], 'r')
|
@@ -170,7 +176,7 @@ class SafeFile
|
|
170
176
|
fname = args[0]
|
171
177
|
|
172
178
|
when 3
|
173
|
-
fail
|
179
|
+
fail ArgumentError if args[1].class != String or args[2].class != Fixnum
|
174
180
|
verify_mode(args[0], args[1])
|
175
181
|
|
176
182
|
fname = args[0]
|
data/lib/ndr_support/version.rb
CHANGED
data/lib/tasks/audit_code.rake
CHANGED
@@ -10,7 +10,6 @@ SAFETY_REPOS = [['/svn/era', '/svn/extra/era/external-access']]
|
|
10
10
|
|
11
11
|
require 'yaml'
|
12
12
|
|
13
|
-
|
14
13
|
# Parameter max_print is number of entries to print before truncating output
|
15
14
|
# (negative value => print all)
|
16
15
|
def audit_code_safety(max_print = 20, ignore_new = false, show_diffs = false, show_in_priority = false, user_name = 'usr')
|
@@ -19,12 +18,12 @@ def audit_code_safety(max_print = 20, ignore_new = false, show_diffs = false, sh
|
|
19
18
|
|
20
19
|
max_print = 1_000_000 if max_print < 0
|
21
20
|
safety_cfg = File.exist?(SAFETY_FILE) ? YAML.load_file(SAFETY_FILE) : {}
|
22
|
-
file_safety = safety_cfg[
|
21
|
+
file_safety = safety_cfg['file safety']
|
23
22
|
if file_safety.nil?
|
24
23
|
puts "Creating new 'file safety' block in #{SAFETY_FILE}"
|
25
|
-
safety_cfg[
|
24
|
+
safety_cfg['file safety'] = file_safety = {}
|
26
25
|
end
|
27
|
-
file_safety.each do |
|
26
|
+
file_safety.each do |_k, v|
|
28
27
|
rev = v['safe_revision']
|
29
28
|
v['safe_revision'] = rev.to_s if rev.is_a?(Integer)
|
30
29
|
end
|
@@ -35,13 +34,13 @@ def audit_code_safety(max_print = 20, ignore_new = false, show_diffs = false, sh
|
|
35
34
|
# TODO: below is broken for git-svn
|
36
35
|
# Is it needed?
|
37
36
|
|
38
|
-
SAFETY_REPOS.each
|
37
|
+
SAFETY_REPOS.each do |suffix, alt|
|
39
38
|
# Temporarily override to only audit a different file list
|
40
39
|
if safety_repo.end_with?(suffix)
|
41
|
-
safety_repo = safety_repo[0...-suffix.length]+alt
|
40
|
+
safety_repo = safety_repo[0...-suffix.length] + alt
|
42
41
|
break
|
43
42
|
end
|
44
|
-
|
43
|
+
end
|
45
44
|
|
46
45
|
if ignore_new
|
47
46
|
puts "Not checking for new files in #{safety_repo}"
|
@@ -49,18 +48,17 @@ def audit_code_safety(max_print = 20, ignore_new = false, show_diffs = false, sh
|
|
49
48
|
puts "Checking for new files in #{safety_repo}"
|
50
49
|
new_files = get_new_files(safety_repo)
|
51
50
|
# Ignore subdirectories, and exclude code_safety.yml by default.
|
52
|
-
new_files.delete_if{|f| f =~ /[\/\\]$/ || f == SAFETY_FILE}
|
53
|
-
new_files.each
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
}
|
51
|
+
new_files.delete_if { |f| f =~ /[\/\\]$/ || f == SAFETY_FILE }
|
52
|
+
new_files.each do |f|
|
53
|
+
next if file_safety.key?(f)
|
54
|
+
file_safety[f] = {
|
55
|
+
'comments' => nil,
|
56
|
+
'reviewed_by' => nil,
|
57
|
+
'safe_revision' => nil }
|
58
|
+
end
|
61
59
|
File.open(SAFETY_FILE, 'w') do |file|
|
62
60
|
# Consistent file diffs, as ruby preserves Hash insertion order since v1.9
|
63
|
-
safety_cfg[
|
61
|
+
safety_cfg['file safety'] = Hash[file_safety.sort]
|
64
62
|
YAML.dump(safety_cfg, file) # Save changes before checking latest revisions
|
65
63
|
end
|
66
64
|
end
|
@@ -71,36 +69,40 @@ def audit_code_safety(max_print = 20, ignore_new = false, show_diffs = false, sh
|
|
71
69
|
puts "Number of new files added: #{file_safety.size - orig_count}"
|
72
70
|
|
73
71
|
# Now generate statistics:
|
74
|
-
unknown = file_safety.values.select{|x| x[
|
75
|
-
unsafe = file_safety.values.select
|
76
|
-
!x[
|
77
|
-
x[
|
78
|
-
!(x[
|
79
|
-
x[
|
80
|
-
|
72
|
+
unknown = file_safety.values.select { |x| x['safe_revision'].nil? }
|
73
|
+
unsafe = file_safety.values.select do |x|
|
74
|
+
!x['safe_revision'].nil? && x['safe_revision'] != -1 &&
|
75
|
+
x['last_changed_rev'] != x['safe_revision'] &&
|
76
|
+
!(x['last_changed_rev'] =~ /^[0-9]+$/ && x['safe_revision'] =~ /^[0-9]+$/ &&
|
77
|
+
x['last_changed_rev'].to_i < x['safe_revision'].to_i)
|
78
|
+
end
|
81
79
|
puts "Number of files with no safe version: #{unknown.size}"
|
82
80
|
puts "Number of files which are no longer safe: #{unsafe.size}"
|
83
81
|
puts
|
84
82
|
printed = []
|
85
83
|
# We also print a third category: ones which are no longer in the repository
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
84
|
+
file_list =
|
85
|
+
if show_in_priority
|
86
|
+
file_safety.sort_by { |_k, v| v.nil? ? -100 : v['last_changed_rev'].to_i }.map(&:first)
|
87
|
+
else
|
88
|
+
file_safety.keys.sort
|
89
|
+
end
|
91
90
|
|
92
|
-
file_list.each
|
91
|
+
file_list.each do |f|
|
93
92
|
if print_file_safety(file_safety, trunk_repo, f, false, printed.size >= max_print)
|
94
93
|
printed << f
|
95
94
|
end
|
96
|
-
|
95
|
+
end
|
97
96
|
puts "... and #{printed.size - max_print} others" if printed.size > max_print
|
98
97
|
if show_diffs
|
99
98
|
puts
|
100
|
-
printed.each
|
99
|
+
printed.each do |f|
|
101
100
|
print_file_diffs(file_safety, trunk_repo, f, user_name)
|
102
|
-
|
101
|
+
end
|
103
102
|
end
|
103
|
+
|
104
|
+
# Returns `true` unless there are pending reviews:
|
105
|
+
unsafe.length.zero? && unknown.length.zero?
|
104
106
|
end
|
105
107
|
|
106
108
|
# Print summary details of a file's known safety
|
@@ -110,13 +112,13 @@ end
|
|
110
112
|
def print_file_safety(file_safety, repo, fname, verbose = false, silent = false)
|
111
113
|
msg = "#{fname}\n "
|
112
114
|
entry = file_safety[fname]
|
113
|
-
msg +=
|
115
|
+
msg += 'File not in audit list' if entry.nil?
|
114
116
|
|
115
|
-
if entry[
|
116
|
-
msg +=
|
117
|
-
msg += ", last changed #{entry['last_changed_rev']}" unless entry[
|
117
|
+
if entry['safe_revision'].nil?
|
118
|
+
msg += 'No safe revision known'
|
119
|
+
msg += ", last changed #{entry['last_changed_rev']}" unless entry['last_changed_rev'].nil?
|
118
120
|
else
|
119
|
-
repolatest = entry[
|
121
|
+
repolatest = entry['last_changed_rev'] # May have been prepopulated en mass
|
120
122
|
msg += 'Not in repository: ' if entry['last_changed_rev'] == -1
|
121
123
|
if (repolatest != entry['safe_revision']) &&
|
122
124
|
!(repolatest =~ /^[0-9]+$/ && entry['safe_revision'] =~ /^[0-9]+$/ &&
|
@@ -125,53 +127,53 @@ def print_file_safety(file_safety, repo, fname, verbose = false, silent = false)
|
|
125
127
|
msg += "No longer safe since revision #{repolatest}: "
|
126
128
|
else
|
127
129
|
return false unless verbose
|
128
|
-
msg +=
|
130
|
+
msg += 'Safe: '
|
129
131
|
end
|
130
132
|
msg += "revision #{entry['safe_revision']} reviewed by #{entry['reviewed_by']}"
|
131
133
|
end
|
132
134
|
msg += "\n Comments: #{entry['comments']}" if entry['comments']
|
133
135
|
puts msg unless silent
|
134
|
-
|
136
|
+
true
|
135
137
|
end
|
136
138
|
|
137
139
|
def flag_file_as_safe(release, reviewed_by, comments, f)
|
138
140
|
safety_cfg = YAML.load_file(SAFETY_FILE)
|
139
|
-
file_safety = safety_cfg[
|
141
|
+
file_safety = safety_cfg['file safety']
|
140
142
|
|
141
143
|
unless File.exist?(f)
|
142
144
|
abort("Error: Unable to flag non-existent file as safe: #{f}")
|
143
145
|
end
|
144
|
-
unless file_safety.
|
146
|
+
unless file_safety.key?(f)
|
145
147
|
file_safety[f] = {
|
146
|
-
|
147
|
-
|
148
|
-
|
148
|
+
'comments' => nil,
|
149
|
+
'reviewed_by' => :dummy, # dummy value, will be overwritten
|
150
|
+
'safe_revision' => nil }
|
149
151
|
end
|
150
152
|
entry = file_safety[f]
|
151
153
|
entry_orig = entry.dup
|
152
|
-
if comments.to_s.length > 0 && entry[
|
153
|
-
entry[
|
154
|
+
if comments.to_s.length > 0 && entry['comments'] != comments
|
155
|
+
entry['comments'] = if entry['comments'].to_s.empty?
|
154
156
|
comments
|
155
157
|
else
|
156
|
-
"#{entry[
|
158
|
+
"#{entry['comments']}#{'.' unless entry['comments'].end_with?('.')} Revision #{release}: #{comments}"
|
157
159
|
end
|
158
160
|
end
|
159
|
-
if entry[
|
161
|
+
if entry['safe_revision']
|
160
162
|
unless release
|
161
|
-
abort("Error: File already has safe revision #{entry[
|
163
|
+
abort("Error: File already has safe revision #{entry['safe_revision']}: #{f}")
|
162
164
|
end
|
163
|
-
if release.is_a?(Integer) && release < entry[
|
165
|
+
if release.is_a?(Integer) && release < entry['safe_revision']
|
164
166
|
puts("Warning: Rolling back safe revision from #{entry['safe_revision']} to #{release} for #{f}")
|
165
167
|
end
|
166
168
|
end
|
167
|
-
entry[
|
168
|
-
entry[
|
169
|
+
entry['safe_revision'] = release
|
170
|
+
entry['reviewed_by'] = reviewed_by
|
169
171
|
if entry == entry_orig
|
170
172
|
puts "No changes when updating safe_revision to #{release || '[none]'} for #{f}"
|
171
173
|
else
|
172
174
|
File.open(SAFETY_FILE, 'w') do |file|
|
173
175
|
# Consistent file diffs, as ruby preserves Hash insertion order since v1.9
|
174
|
-
safety_cfg[
|
176
|
+
safety_cfg['file safety'] = Hash[file_safety.sort]
|
175
177
|
YAML.dump(safety_cfg, file) # Save changes before checking latest revisions
|
176
178
|
end
|
177
179
|
puts "Updated safe_revision to #{release || '[none]'} for #{f}"
|
@@ -180,10 +182,15 @@ end
|
|
180
182
|
|
181
183
|
# Determine the type of repository
|
182
184
|
def repository_type
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
185
|
+
@repository_type ||= if Dir.exist?('.svn') || system("svn info . > /dev/null 2>&1")
|
186
|
+
'svn'
|
187
|
+
elsif Dir.exist?('.git') && open('.git/config').grep(/svn/).any?
|
188
|
+
'git-svn'
|
189
|
+
elsif Dir.exist?('.git') && open('.git/config').grep(/git/).any?
|
190
|
+
'git'
|
191
|
+
else
|
192
|
+
'not known'
|
193
|
+
end
|
187
194
|
end
|
188
195
|
|
189
196
|
def get_trunk_repo
|
@@ -191,14 +198,14 @@ def get_trunk_repo
|
|
191
198
|
when 'svn'
|
192
199
|
repo_info = %x[svn info]
|
193
200
|
puts 'svn case'
|
194
|
-
return repo_info.split("\n").select{|x| x=~ /^URL: /}.collect{|x| x[5..-1]}.first
|
201
|
+
return repo_info.split("\n").select { |x| x =~ /^URL: / }.collect { |x| x[5..-1] }.first
|
195
202
|
when 'git-svn'
|
196
203
|
puts 'git-svn case'
|
197
204
|
repo_info = %x[git svn info]
|
198
|
-
return repo_info.split("\n").select{|x| x =~ /^URL: /}.collect{|x| x[5..-1]}.first
|
205
|
+
return repo_info.split("\n").select { |x| x =~ /^URL: / }.collect { |x| x[5..-1] }.first
|
199
206
|
when 'git'
|
200
207
|
puts 'git case'
|
201
|
-
repo_info =
|
208
|
+
repo_info = %x[git remote -v]
|
202
209
|
return repo_info.split("\n").first[7..-9]
|
203
210
|
else
|
204
211
|
return 'Information not available. Unknown repository type'
|
@@ -210,13 +217,13 @@ def get_new_files(safety_repo)
|
|
210
217
|
when 'svn', 'git-svn'
|
211
218
|
%x[svn ls -R "#{safety_repo}"].split("\n")
|
212
219
|
when 'git'
|
213
|
-
|
214
|
-
|
220
|
+
#%x[git ls-files --modified].split("\n")
|
221
|
+
%x[git ls-files].split("\n")
|
215
222
|
|
216
223
|
# TODO: Below is for remote repository - for testing use local files
|
217
224
|
#new_files = %x[git ls-files --modified #{safety_repo}].split("\n")
|
218
225
|
# TODO: Do we need the --modified option?
|
219
|
-
|
226
|
+
#new_files = %x[git ls-files --modified].split("\n")
|
220
227
|
else
|
221
228
|
[]
|
222
229
|
end
|
@@ -234,9 +241,9 @@ def set_last_changed_revision(repo, file_safety, fnames)
|
|
234
241
|
fnames.each_with_index do |f, i|
|
235
242
|
info = %x[git log -n 1 #{f}].split("\n").first[7..-1]
|
236
243
|
if info.nil? || info.empty?
|
237
|
-
file_safety[f][
|
244
|
+
file_safety[f]['last_changed_rev'] = -1
|
238
245
|
else
|
239
|
-
file_safety[f][
|
246
|
+
file_safety[f]['last_changed_rev'] = info
|
240
247
|
end
|
241
248
|
# Show progress
|
242
249
|
print '.' if (i % dot_freq) == 0
|
@@ -279,12 +286,12 @@ def get_last_changed_revision(repo, fname)
|
|
279
286
|
begin
|
280
287
|
svn_info = %x[svn info -r head "#{repo}/#{fname}"]
|
281
288
|
rescue
|
282
|
-
puts
|
289
|
+
puts 'we have an error in the svn info line'
|
283
290
|
end
|
284
291
|
begin
|
285
292
|
svn_info.match('Last Changed Rev: ([0-9]*)').to_a[1]
|
286
293
|
rescue
|
287
|
-
puts
|
294
|
+
puts 'We have an error in getting the revision'
|
288
295
|
end
|
289
296
|
end
|
290
297
|
end
|
@@ -331,13 +338,18 @@ def set_safe_revision
|
|
331
338
|
end
|
332
339
|
|
333
340
|
def print_repo_file_diffs(repolatest, repo, fname, user_name, safe_revision)
|
341
|
+
require 'open3'
|
342
|
+
cmd = nil
|
334
343
|
case repository_type
|
335
344
|
when 'git'
|
336
|
-
|
337
|
-
puts %x[git --no-pager diff -b #{safe_revision}..#{repolatest} #{fname}]
|
345
|
+
cmd = ['git', '--no-pager', 'diff', '-b', "#{safe_revision}..#{repolatest}", fname]
|
338
346
|
when 'git-svn', 'svn'
|
339
|
-
|
340
|
-
|
347
|
+
cmd = ['svn', 'diff', '-r', "#{safe_revision.to_i}:#{repolatest.to_i}", '-x', '-b', "#{repo}/#{fname}"]
|
348
|
+
end
|
349
|
+
if cmd
|
350
|
+
puts(cmd.join(' '))
|
351
|
+
stdout_and_err_str, status = Open3.capture2e(*cmd)
|
352
|
+
puts(stdout_and_err_str)
|
341
353
|
else
|
342
354
|
puts 'Unknown repo'
|
343
355
|
end
|
@@ -369,11 +381,10 @@ def get_release
|
|
369
381
|
else
|
370
382
|
''
|
371
383
|
end
|
372
|
-
|
384
|
+
release
|
373
385
|
end
|
374
386
|
|
375
387
|
namespace :audit do
|
376
|
-
|
377
388
|
desc "Audit safety of source code.
|
378
389
|
Usage: audit:code [max_print=n] [ignore_new=false|true] [show_diffs=false|true] [reviewed_by=usr]
|
379
390
|
|
@@ -381,19 +392,22 @@ File #{SAFETY_FILE} lists the safety and revision information
|
|
381
392
|
of the era source code. This task updates the list, and [TODO] warns about
|
382
393
|
files which have changed since they were last verified as safe."
|
383
394
|
task(:code) do
|
384
|
-
puts
|
395
|
+
puts 'Usage: audit:code [max_print=n] [ignore_new=false|true] [show_diffs=false|true] [show_in_priority=false|true] [reviewed_by=usr]'
|
385
396
|
puts "This is a #{repository_type} repository"
|
386
397
|
|
387
398
|
ignore_new = (ENV['ignore_new'].to_s =~ /\Atrue\Z/i)
|
388
399
|
show_diffs = (ENV['show_diffs'].to_s =~ /\Atrue\Z/i)
|
389
400
|
show_in_priority = (ENV['show_in_priority'].to_s =~ /\Atrue\Z/i)
|
390
401
|
max_print = ENV['max_print'] =~ /\A-?[0-9][0-9]*\Z/ ? ENV['max_print'].to_i : 20
|
402
|
+
reviewer = ENV['reviewed_by']
|
391
403
|
|
392
|
-
audit_code_safety(max_print, ignore_new, show_diffs, show_in_priority,
|
404
|
+
all_safe = audit_code_safety(max_print, ignore_new, show_diffs, show_in_priority, reviewer)
|
393
405
|
|
394
406
|
unless show_diffs
|
395
|
-
puts
|
407
|
+
puts 'To show file diffs, run: rake audit:code max_print=-1 show_diffs=true'
|
396
408
|
end
|
409
|
+
|
410
|
+
exit(1) unless all_safe
|
397
411
|
end
|
398
412
|
|
399
413
|
desc "Flag a source file as safe.
|
@@ -401,23 +415,47 @@ files which have changed since they were last verified as safe."
|
|
401
415
|
Usage:
|
402
416
|
Flag as safe: rake audit:safe release=revision reviewed_by=usr [comments=...] file=f
|
403
417
|
Needs review: rake audit:safe release=0 [comments=...] file=f"
|
404
|
-
task
|
405
|
-
required_fields =
|
406
|
-
required_fields <<
|
407
|
-
missing = required_fields.collect{|f| (f if ENV[f].to_s.empty? || (f=='reviewed_by' && ENV[f] == 'usr'))}.compact # Avoid accidental missing username
|
408
|
-
|
409
|
-
puts
|
410
|
-
puts
|
418
|
+
task(:safe) do
|
419
|
+
required_fields = %w(release file)
|
420
|
+
required_fields << 'reviewed_by' unless ENV['release'] == '0'
|
421
|
+
missing = required_fields.collect { |f| (f if ENV[f].to_s.empty? || (f == 'reviewed_by' && ENV[f] == 'usr')) }.compact # Avoid accidental missing username
|
422
|
+
unless missing.empty?
|
423
|
+
puts 'Usage: rake audit:safe release=revision reviewed_by=usr [comments=...] file=f'
|
424
|
+
puts 'or, to flag a file for review: rake audit:safe release=0 [comments=...] file=f'
|
411
425
|
abort("Error: Missing required argument(s): #{missing.join(', ')}")
|
412
426
|
end
|
413
427
|
|
414
428
|
unless release_valid?
|
415
|
-
puts
|
416
|
-
puts
|
429
|
+
puts 'Usage: rake audit:safe release=revision reviewed_by=usr [comments=...] file=f'
|
430
|
+
puts 'or, to flag a file for review: rake audit:safe release=0 [comments=...] file=f'
|
417
431
|
abort("Error: Invalid release: #{ENV['release']}")
|
418
432
|
end
|
419
433
|
|
420
434
|
release = get_release
|
421
435
|
flag_file_as_safe(release, ENV['reviewed_by'], ENV['comments'], ENV['file'])
|
422
436
|
end
|
437
|
+
|
438
|
+
desc 'Wraps audit:code, and stops if any review is pending/stale.'
|
439
|
+
task(:ensure_safe) do
|
440
|
+
begin
|
441
|
+
puts 'Checking code safety...'
|
442
|
+
|
443
|
+
begin
|
444
|
+
$stdout = $stderr = StringIO.new
|
445
|
+
Rake::Task['audit:code'].invoke
|
446
|
+
ensure
|
447
|
+
$stdout, $stderr = STDOUT, STDERR
|
448
|
+
end
|
449
|
+
rescue SystemExit => ex
|
450
|
+
puts '=============================================================='
|
451
|
+
puts 'Code safety review of some files are not up-to-date; aborting!'
|
452
|
+
puts ' - to review the files in question, run: rake audit:code'
|
453
|
+
puts '=============================================================='
|
454
|
+
|
455
|
+
raise ex
|
456
|
+
end
|
457
|
+
end
|
423
458
|
end
|
459
|
+
|
460
|
+
# Prevent building of un-reviewed gems:
|
461
|
+
task :build => :'audit:ensure_safe'
|
data/test/safe_file_test.rb
CHANGED
@@ -25,9 +25,12 @@ class SafeFileTest < Minitest::Test
|
|
25
25
|
# .new
|
26
26
|
|
27
27
|
test 'constructor should accept safe_path only' do
|
28
|
-
assert_raises
|
29
|
-
|
30
|
-
|
28
|
+
assert_raises(ArgumentError) { SafeFile.new }
|
29
|
+
assert_raises(ArgumentError) { SafeFile.new('example_file', 'rw') }
|
30
|
+
end
|
31
|
+
|
32
|
+
test 'constructor should only allow string or numeric second argument' do
|
33
|
+
assert_raises(ArgumentError) { SafeFile.new(@not_empty_fpath, {}) }
|
31
34
|
end
|
32
35
|
|
33
36
|
test 'should raise exception if try to write in read-only space' do
|
@@ -311,6 +314,76 @@ class SafeFileTest < Minitest::Test
|
|
311
314
|
File.delete p
|
312
315
|
end
|
313
316
|
|
317
|
+
################################################################################
|
318
|
+
# .each / .each_line
|
319
|
+
|
320
|
+
test '#each should check pathspace permissions when called with a block' do
|
321
|
+
p = SafePath.new('test_space_w').join('test_file_rw_not_empty')
|
322
|
+
|
323
|
+
f = SafeFile.new(p, 'w')
|
324
|
+
assert_raises(SecurityError) { f.each { |line| line } }
|
325
|
+
assert_raises(SecurityError) { f.each_line { |line| line } }
|
326
|
+
f.close
|
327
|
+
end
|
328
|
+
|
329
|
+
test '#each should check pathspace permissions when called without a block' do
|
330
|
+
p = SafePath.new('test_space_w').join('test_file_rw_not_empty')
|
331
|
+
|
332
|
+
f = SafeFile.new(p, 'w')
|
333
|
+
assert_raises(SecurityError) { f.each }
|
334
|
+
assert_raises(SecurityError) { f.each_line }
|
335
|
+
f.close
|
336
|
+
end
|
337
|
+
|
338
|
+
test '#each should return an enumerator in read-only namespace' do
|
339
|
+
p = SafePath.new('test_space_r').join('test_file_rw_not_empty')
|
340
|
+
|
341
|
+
f = SafeFile.new(p, 'r')
|
342
|
+
assert f.each.is_a?(Enumerator)
|
343
|
+
assert f.each_line.is_a?(Enumerator)
|
344
|
+
f.close
|
345
|
+
end
|
346
|
+
|
347
|
+
test '#each should read lines from read-only namespace' do
|
348
|
+
p = SafePath.new('test_space_r').join('test_file_rw_not_empty')
|
349
|
+
|
350
|
+
f = SafeFile.new(p, 'r')
|
351
|
+
assert_equal ['I am not empty'], f.each.to_a
|
352
|
+
f.close
|
353
|
+
end
|
354
|
+
|
355
|
+
test '#each handles separator argument when in read-only namespace' do
|
356
|
+
p = SafePath.new('test_space_r').join('test_file_rw_not_empty')
|
357
|
+
|
358
|
+
f = SafeFile.new(p, 'r')
|
359
|
+
assert_equal ['I am', ' not em', 'pty'], f.each('m').to_a
|
360
|
+
f.close
|
361
|
+
end
|
362
|
+
|
363
|
+
test '#each handles limit argument when in read-only namespace' do
|
364
|
+
p = SafePath.new('test_space_r').join('test_file_rw_not_empty')
|
365
|
+
|
366
|
+
f = SafeFile.new(p, 'r')
|
367
|
+
assert_equal ['I a', 'm n', 'ot ', 'emp', 'ty'], f.each(3).to_a
|
368
|
+
f.close
|
369
|
+
end
|
370
|
+
|
371
|
+
test '#each handles separator and limit argument when in read-only namespace' do
|
372
|
+
p = SafePath.new('test_space_r').join('test_file_rw_not_empty')
|
373
|
+
|
374
|
+
f = SafeFile.new(p, 'r')
|
375
|
+
assert_equal ['I am', ' not ', 'em', 'pty'], f.each('m', 5).to_a
|
376
|
+
f.close
|
377
|
+
end
|
378
|
+
|
379
|
+
test '#each_line handles separator and limit argument when in read-only namespace' do
|
380
|
+
p = SafePath.new('test_space_r').join('test_file_rw_not_empty')
|
381
|
+
|
382
|
+
f = SafeFile.new(p, 'r')
|
383
|
+
assert_equal ['I am', ' not ', 'em', 'pty'], f.each_line('m', 5).to_a
|
384
|
+
f.close
|
385
|
+
end
|
386
|
+
|
314
387
|
################################################################################
|
315
388
|
# .path
|
316
389
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ndr_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- NCRS Development Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|