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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZDJkMjRhNmU0MmVhN2RmZTllMjVhY2FhYmQxMjA3M2YxZjI0OTJmOA==
4
+ OTE0YTVkMGEwNDI5ZmZlMDA0NTNmMTBiM2VjNGM3M2UyYjk3YTMwOQ==
5
5
  data.tar.gz: !binary |-
6
- YTc0ODliMTUwMjk2MzE0N2NlZTdjNjM4NjIzNjFmZjYyYzdmMmEyMQ==
6
+ MDFhOTI2YWNmZmE0YTVkZWMyNDIyYjFmOTZiMTVhMDMwMDgzOWMwZQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MjIxYWZhZDNiNDU2NzQxZTI5N2NhODhkMGI1ZTA3ZjZiNDk1ODNmMmRjZDc0
10
- NTkwODEzMDhmNzA3NmY0Mjk2ODIyNGEwNDk1NTdkODI4ZjU0NDZlMzE2ZTc0
11
- Y2EyMmIwMzVhYTc0OWQyNjAxN2JjMzA4M2JjNmVhMzY3YmE4NDk=
9
+ ODM0NDFhZjMzOTE5NTlmMDgwYmMzMTYzYmY5OTEyYmUxNDhiZTMxMDg4ZDBl
10
+ NDU4MWIxMzhmMGQwOTg0ZDk1NWVmZmY0MDUwMTA5NzZjYmEyZDgxNWRlMjY5
11
+ YjQwODRjMGE1ZTY4YmQyMTE4Nzk0YmYxMTIyNmQyNTI3YzE0YTY=
12
12
  data.tar.gz: !binary |-
13
- MDUyZDU3NTE0ZWEzMmViMDkxZjM2Zjk0MjdiMWM2ZTNhMDA2YmFkNWI0ZmFm
14
- ZWQ1NmMxMWFjYzVjZjc4MTQyOTUxOGZiOTkyN2RlYzMzZjE0ZGJkZDkzYWMy
15
- YTlhYjczZDg0YmEyOThlNDA4NDEyODFjZjMzNDgyNmJjYzA4ZDY=
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: pauleves
122
- safe_revision: 506a317e59d0ccb5b32d813b74d822f35a55cea9
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: timgentry
162
- safe_revision: 4bb6a2dc2e82d1e2188047c24f098c7811a98edb
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: timgentry
170
- safe_revision: 2665e780ba942e7f0d92f6fd8d0b979e327d1edb
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: timgentry
222
- safe_revision: 506a317e59d0ccb5b32d813b74d822f35a55cea9
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 ArgimentError if args[1].class != Fixnum and args[1].class != String
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 ArgimentError if args[1].class != String or args[2].class != Fixnum
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]
@@ -1,5 +1,5 @@
1
1
  # This defines the NdrSupport version. If you change it, rebuild and commit the gem.
2
2
  # Use "rake build" to build the gem, see rake -T for all bundler rake tasks (and our own).
3
3
  module NdrSupport
4
- VERSION = '3.1.1'
4
+ VERSION = '3.2.0'
5
5
  end
@@ -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["file safety"]
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["file safety"] = file_safety = {}
24
+ safety_cfg['file safety'] = file_safety = {}
26
25
  end
27
- file_safety.each do |k, v|
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{|suffix, alt|
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{|f|
54
- unless file_safety.has_key?(f)
55
- file_safety[f] = {
56
- "comments" => nil,
57
- "reviewed_by" => nil,
58
- "safe_revision" => nil }
59
- end
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["file safety"] = Hash[file_safety.sort]
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["safe_revision"].nil?}
75
- unsafe = file_safety.values.select{|x|
76
- !x["safe_revision"].nil? && x["safe_revision"] != -1 &&
77
- x["last_changed_rev"] != x['safe_revision'] &&
78
- !(x["last_changed_rev"] =~ /^[0-9]+$/ && x['safe_revision'] =~ /^[0-9]+$/ &&
79
- x["last_changed_rev"].to_i < x['safe_revision'].to_i)
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
- if show_in_priority
87
- file_list = file_safety.sort_by {|k,v| v.nil? ? -100 : v["last_changed_rev"].to_i}.map(&:first)
88
- else
89
- file_list = file_safety.keys.sort
90
- end
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{|f|
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{|f|
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 += "File not in audit list" if entry.nil?
115
+ msg += 'File not in audit list' if entry.nil?
114
116
 
115
- if entry["safe_revision"].nil?
116
- msg += "No safe revision known"
117
- msg += ", last changed #{entry['last_changed_rev']}" unless entry["last_changed_rev"].nil?
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["last_changed_rev"] # May have been prepopulated en mass
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 += "Safe: "
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
- return true
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["file safety"]
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.has_key?(f)
146
+ unless file_safety.key?(f)
145
147
  file_safety[f] = {
146
- "comments" => nil,
147
- "reviewed_by" => :dummy, # dummy value, will be overwritten
148
- "safe_revision" => nil }
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["comments"] != comments
153
- entry["comments"] = if entry["comments"].to_s.empty?
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["comments"]}#{'.' unless entry["comments"].end_with?('.')} Revision #{release}: #{comments}"
158
+ "#{entry['comments']}#{'.' unless entry['comments'].end_with?('.')} Revision #{release}: #{comments}"
157
159
  end
158
160
  end
159
- if entry["safe_revision"]
161
+ if entry['safe_revision']
160
162
  unless release
161
- abort("Error: File already has safe revision #{entry["safe_revision"]}: #{f}")
163
+ abort("Error: File already has safe revision #{entry['safe_revision']}: #{f}")
162
164
  end
163
- if release.is_a?(Integer) && release < entry["safe_revision"]
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["safe_revision"] = release
168
- entry["reviewed_by"] = reviewed_by
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["file safety"] = Hash[file_safety.sort]
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
- return 'svn' if Dir.exists?('.svn')
184
- return 'git-svn' if Dir.exists?('.git') && open('.git/config').grep(/svn/).any?
185
- return 'git' if Dir.exists?('.git') && open('.git/config').grep(/git/).any?
186
- return 'not known'
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 = %x[git remote -v]
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
- #%x[git ls-files --modified].split("\n")
214
- %x[git ls-files].split("\n")
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
- #new_files = %x[git ls-files --modified].split("\n")
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]["last_changed_rev"] = -1
244
+ file_safety[f]['last_changed_rev'] = -1
238
245
  else
239
- file_safety[f]["last_changed_rev"] = info
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 "we have an error in the svn info line"
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 "We have an error in getting the revision"
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
- puts %[git --no-pager diff -b #{safe_revision}..#{repolatest} #{fname}]
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
- puts %[svn diff -r #{safe_revision.to_i}:#{repolatest.to_i} -x -b #{repo}/#{fname}]
340
- puts %x[svn diff -r #{safe_revision.to_i}:#{repolatest.to_i} -x -b #{repo}/#{fname}]
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
- return release
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 "Usage: audit:code [max_print=n] [ignore_new=false|true] [show_diffs=false|true] [show_in_priority=false|true] [reviewed_by=usr]"
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, ENV['reviewed_by'])
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 "To show file diffs, run: rake audit:code max_print=-1 show_diffs=true"
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 (:safe) do
405
- required_fields = ["release", "file"]
406
- required_fields << "reviewed_by" unless ENV['release'] == '0'
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
- if !missing.empty?
409
- puts "Usage: rake audit:safe release=revision reviewed_by=usr [comments=...] file=f"
410
- puts "or, to flag a file for review: rake audit:safe release=0 [comments=...] file=f"
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 "Usage: rake audit:safe release=revision reviewed_by=usr [comments=...] file=f"
416
- puts "or, to flag a file for review: rake audit:safe release=0 [comments=...] file=f"
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'
@@ -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 ArgumentError do
29
- SafeFile.new('example_file', 'rw')
30
- end
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.1.1
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-10-09 00:00:00.000000000 Z
11
+ date: 2015-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord