ndr_support 3.1.1 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|