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 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