openstudio-extension 0.1.6 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +35 -1
- data/Gemfile +0 -2
- data/Jenkinsfile +1 -1
- data/README.md +21 -16
- data/Rakefile +1 -1
- data/lib/change_log.rb +157 -0
- data/lib/measures/openstudio_extension_test_measure/measure.xml +20 -19
- data/lib/openstudio/extension.rb +27 -10
- data/lib/openstudio/extension/core/os_lib_constructions.rb +6 -1
- data/lib/openstudio/extension/core/os_lib_model_generation.rb +30 -32
- data/lib/openstudio/extension/rake_task.rb +232 -18
- data/lib/openstudio/extension/runner.rb +9 -8
- data/lib/openstudio/extension/version.rb +1 -1
- data/openstudio-extension.gemspec +23 -17
- metadata +38 -35
- data/lib/measures/openstudio_extension_test_measure/tests/openstudio_extension_test_measure_test.rb +0 -74
@@ -283,7 +283,12 @@ module OsLib_Constructions
|
|
283
283
|
# create info message
|
284
284
|
if !runner.nil? # todo - need to look for bad visible transmittance here
|
285
285
|
uFactorSiToIpConversion = OpenStudio.convert(material.uFactor, 'W/m^2*K', 'Btu/ft^2*h*R').get
|
286
|
-
|
286
|
+
# version check to support 2.x and 3.x
|
287
|
+
if Gem::Version.new(OpenStudio::openStudioVersion) > Gem::Version.new("2.9.1")
|
288
|
+
runner.registerInfo("Created #{construction.name} construction. U-factor: #{OpenStudio.toNeatString(uFactorSiToIpConversion, 2, true)}(Btu/ft^2*h*R), SHGC: #{material.solarHeatGainCoefficient}, VT: #{material.getVisibleTransmittance.get}.")
|
289
|
+
else
|
290
|
+
runner.registerInfo("Created #{construction.name} construction. U-factor: #{OpenStudio.toNeatString(uFactorSiToIpConversion, 2, true)}(Btu/ft^2*h*R), SHGC: #{material.getSolarHeatGainCoefficient}, VT: #{material.getVisibleTransmittance.get}.")
|
291
|
+
end
|
287
292
|
end
|
288
293
|
|
289
294
|
result = construction
|
@@ -606,7 +606,7 @@ module OsLib_ModelGeneration
|
|
606
606
|
hash['ER_Trauma'] = { ratio: 0.0025, space_type_gen: true, default: false }
|
607
607
|
hash['ER_Triage'] = { ratio: 0.0050, space_type_gen: true, default: false }
|
608
608
|
hash['ICU_NurseStn'] = { ratio: 0.0298, space_type_gen: true, default: false }
|
609
|
-
hash['
|
609
|
+
hash['ICU_Open'] = { ratio: 0.0275, space_type_gen: true, default: false }
|
610
610
|
hash['ICU_PatRm'] = { ratio: 0.0115, space_type_gen: true, default: false }
|
611
611
|
hash['Kitchen'] = { ratio: 0.0414, space_type_gen: true, default: false }
|
612
612
|
hash['Lab'] = { ratio: 0.0236, space_type_gen: true, default: false }
|
@@ -1641,9 +1641,6 @@ module OsLib_ModelGeneration
|
|
1641
1641
|
end
|
1642
1642
|
if ! args.has_key?("perim_mult")
|
1643
1643
|
args["perim_mult"] = 1.0 # will not make two bars for extended perimeter
|
1644
|
-
puts "asdf, doesn't have it I'm adding it"
|
1645
|
-
else
|
1646
|
-
puts "asdf, already had it"
|
1647
1644
|
end
|
1648
1645
|
|
1649
1646
|
# lookup and replace argument values from upstream measures
|
@@ -2563,6 +2560,19 @@ module OsLib_ModelGeneration
|
|
2563
2560
|
# Make the standard applier
|
2564
2561
|
standard = Standard.build((args['template']).to_s)
|
2565
2562
|
|
2563
|
+
# validate climate zone
|
2564
|
+
if !args.has_key?('climate_zone') || args['climate_zone'] == 'Lookup From Model'
|
2565
|
+
climate_zone = standard.model_get_building_climate_zone_and_building_type(model)['climate_zone']
|
2566
|
+
runner.registerInfo("Using climate zone #{climate_zone} from model")
|
2567
|
+
else
|
2568
|
+
climate_zone = args['climate_zone']
|
2569
|
+
runner.registerInfo("Using climate zone #{climate_zone} from user arguments")
|
2570
|
+
end
|
2571
|
+
if climate_zone == ''
|
2572
|
+
runner.registerError("Could not determine climate zone from measure arguments or model.")
|
2573
|
+
return false
|
2574
|
+
end
|
2575
|
+
|
2566
2576
|
# make sure daylight savings is turned on up prior to any sizing runs being done.
|
2567
2577
|
if args['enable_dst']
|
2568
2578
|
start_date = '2nd Sunday in March'
|
@@ -2649,13 +2659,6 @@ module OsLib_ModelGeneration
|
|
2649
2659
|
else
|
2650
2660
|
is_residential = 'No'
|
2651
2661
|
end
|
2652
|
-
if !args.has_key?('climate_zone') || args['climate_zone'] == 'Lookup From Model'
|
2653
|
-
climate_zone = standard.model_get_building_climate_zone_and_building_type(model)['climate_zone']
|
2654
|
-
runner.registerInfo("Using climate zone #{climate_zone} from model")
|
2655
|
-
else
|
2656
|
-
climate_zone = args['climate_zone']
|
2657
|
-
runner.registerInfo("Using climate zone #{climate_zone} from user arguments")
|
2658
|
-
end
|
2659
2662
|
bldg_def_const_set = standard.model_add_construction_set(model, climate_zone, lookup_building_type, nil, is_residential)
|
2660
2663
|
if bldg_def_const_set.is_initialized
|
2661
2664
|
bldg_def_const_set = bldg_def_const_set.get
|
@@ -2800,16 +2803,25 @@ module OsLib_ModelGeneration
|
|
2800
2803
|
end
|
2801
2804
|
end
|
2802
2805
|
|
2803
|
-
#
|
2806
|
+
# add_daylighting_controls (since outdated measure don't have this default to true if arg not found)
|
2807
|
+
if !args.has_key?('add_daylighting_controls')
|
2808
|
+
args['add_daylighting_controls'] = true
|
2809
|
+
end
|
2810
|
+
if args['add_daylighting_controls']
|
2811
|
+
# remove add_daylighting_controls objects
|
2812
|
+
if args['remove_objects']
|
2813
|
+
model.getDaylightingControls.each(&:remove)
|
2814
|
+
end
|
2804
2815
|
|
2805
|
-
|
2806
|
-
|
2807
|
-
|
2808
|
-
|
2809
|
-
|
2816
|
+
# add daylight controls, need to perform a sizing run for 2010
|
2817
|
+
if args['template'] == '90.1-2010'
|
2818
|
+
if standard.model_run_sizing_run(model, "#{Dir.pwd}/SRvt") == false
|
2819
|
+
log_messages_to_runner(runner, debug = true)
|
2820
|
+
return false
|
2821
|
+
end
|
2810
2822
|
end
|
2811
|
-
end
|
2812
2823
|
standard.model_add_daylighting_controls(model)
|
2824
|
+
end
|
2813
2825
|
|
2814
2826
|
# add refrigeration
|
2815
2827
|
if args['add_refrigeration']
|
@@ -3037,20 +3049,6 @@ module OsLib_ModelGeneration
|
|
3037
3049
|
end
|
3038
3050
|
end
|
3039
3051
|
|
3040
|
-
# add internal mass
|
3041
|
-
if args['add_internal_mass']
|
3042
|
-
|
3043
|
-
if args['remove_objects']
|
3044
|
-
model.getSpaceLoads.each do |instance|
|
3045
|
-
next unless instance.to_InternalMass.is_initialized
|
3046
|
-
instance.remove
|
3047
|
-
end
|
3048
|
-
end
|
3049
|
-
|
3050
|
-
# add internal mass to conditioned spaces; needs to happen after thermostats are applied
|
3051
|
-
standard.model_add_internal_mass(model, primary_bldg_type)
|
3052
|
-
end
|
3053
|
-
|
3054
3052
|
# set unmet hours tolerance
|
3055
3053
|
unmet_hrs_tol_r = args['unmet_hours_tolerance']
|
3056
3054
|
unmet_hrs_tol_k = OpenStudio.convert(unmet_hrs_tol_r, 'R', 'K').get
|
@@ -49,14 +49,17 @@ module OpenStudio
|
|
49
49
|
setup_subtasks(@name)
|
50
50
|
end
|
51
51
|
|
52
|
-
def set_extension_class(extension_class)
|
52
|
+
def set_extension_class(extension_class, github_repo = '')
|
53
53
|
@extension_class = extension_class
|
54
54
|
@extension = extension_class.new
|
55
55
|
@root_dir = @extension.root_dir
|
56
|
-
|
56
|
+
# Catch if measures_dir is nil, then just make it an empty string
|
57
|
+
@measures_dir = @extension.measures_dir || ''
|
58
|
+
@staged_path = @measures_dir + '/staged'
|
57
59
|
@core_dir = @extension.core_dir
|
58
60
|
@doc_templates_dir = @extension.doc_templates_dir
|
59
61
|
@files_dir = @extension.files_dir
|
62
|
+
@github_repo = github_repo
|
60
63
|
end
|
61
64
|
|
62
65
|
private
|
@@ -65,22 +68,20 @@ module OpenStudio
|
|
65
68
|
namespace name do
|
66
69
|
desc 'Run the CLI task to check for measure updates'
|
67
70
|
task update_measures: ['measures:add_license', 'measures:add_readme', 'measures:copy_resources', 'update_copyright'] do
|
68
|
-
puts 'updating measures
|
71
|
+
puts 'updating measures'
|
69
72
|
runner = OpenStudio::Extension::Runner.new(Dir.pwd)
|
70
73
|
runner.update_measures(@measures_dir)
|
71
74
|
end
|
72
75
|
|
73
76
|
desc 'List measures'
|
74
77
|
task :list_measures do
|
75
|
-
puts 'Listing measures
|
78
|
+
puts 'Listing measures'
|
76
79
|
runner = OpenStudio::Extension::Runner.new(Dir.pwd)
|
77
80
|
runner.list_measures(@measures_dir)
|
78
81
|
end
|
79
82
|
|
80
83
|
desc 'Use openstudio system ruby to run tests'
|
81
84
|
task :test_with_openstudio do
|
82
|
-
# puts Dir.pwd
|
83
|
-
# puts Rake.original_dir
|
84
85
|
puts 'testing with openstudio'
|
85
86
|
runner = OpenStudio::Extension::Runner.new(Dir.pwd)
|
86
87
|
result = runner.test_measures_with_cli(@measures_dir)
|
@@ -90,12 +91,6 @@ module OpenStudio
|
|
90
91
|
end
|
91
92
|
end
|
92
93
|
|
93
|
-
# TODO: Implement this eventually... comment out for now.
|
94
|
-
# desc 'Use openstudio docker image to run tests'
|
95
|
-
# task :test_with_docker do
|
96
|
-
# puts 'testing with docker'
|
97
|
-
# end
|
98
|
-
|
99
94
|
# namespace for measure operations
|
100
95
|
namespace 'measures' do
|
101
96
|
desc 'Copy the resources files to individual measures'
|
@@ -143,14 +138,233 @@ module OpenStudio
|
|
143
138
|
runner.update_copyright(@root_dir, @doc_templates_dir)
|
144
139
|
end
|
145
140
|
|
146
|
-
desc '
|
147
|
-
task :
|
148
|
-
|
141
|
+
desc 'Print the change log from GitHub. Date format: yyyy-mm-dd'
|
142
|
+
task :change_log, [:start_date, :end_date, :apikey] do |t, args|
|
143
|
+
require 'change_log'
|
144
|
+
cl = ChangeLog.new(@github_repo, *args)
|
145
|
+
cl.process
|
146
|
+
cl.print_issues
|
149
147
|
end
|
150
148
|
|
151
|
-
|
152
|
-
|
153
|
-
|
149
|
+
namespace 'bcl' do
|
150
|
+
desc 'Test BCL login'
|
151
|
+
task :test_login do
|
152
|
+
puts 'test BCL login'
|
153
|
+
bcl = ::BCL::ComponentMethods.new
|
154
|
+
bcl.login
|
155
|
+
end
|
156
|
+
|
157
|
+
# for custom search, populate env var: bcl_search_keyword
|
158
|
+
desc 'Search BCL'
|
159
|
+
task :search_measures do
|
160
|
+
puts 'test search BCL'
|
161
|
+
bcl = ::BCL::ComponentMethods.new
|
162
|
+
bcl.login
|
163
|
+
|
164
|
+
# check for env var specifying keyword first
|
165
|
+
if ENV['bcl_search_keyword']
|
166
|
+
keyword = ENV['bcl_search_keyword']
|
167
|
+
else
|
168
|
+
keyword = 'Space'
|
169
|
+
end
|
170
|
+
num_results = 10
|
171
|
+
# bcl.search params: search_string, filter_string, return_all_results?
|
172
|
+
puts "searching BCL measures for keyword: #{keyword}"
|
173
|
+
results = bcl.search(keyword, "fq[]=bundle:nrel_measure&show_rows=#{num_results}", false)
|
174
|
+
puts "there are #{results[:result].count} results"
|
175
|
+
results[:result].each do |res|
|
176
|
+
puts(res[:measure][:name]).to_s
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# to call with argument: "openstudio:bcl:stage[true]" (true = remove existing staged content)
|
181
|
+
desc 'Copy the measures/components to a location that can be uploaded to BCL'
|
182
|
+
task :stage, [:reset] do |t, args|
|
183
|
+
puts 'Staging measures for BCL'
|
184
|
+
# initialize BCL and login
|
185
|
+
bcl = ::BCL::ComponentMethods.new
|
186
|
+
bcl.login
|
187
|
+
|
188
|
+
# process reset options: true to clear out old staged content
|
189
|
+
options = { reset: false }
|
190
|
+
if args[:reset].to_s == 'true'
|
191
|
+
options[:reset] = true
|
192
|
+
end
|
193
|
+
|
194
|
+
# ensure staged dir exists
|
195
|
+
FileUtils.mkdir_p(@staged_path)
|
196
|
+
|
197
|
+
# delete existing tarballs if reset is true
|
198
|
+
if options[:reset]
|
199
|
+
puts 'Deleting existing staged content'
|
200
|
+
FileUtils.rm_rf(Dir.glob("#{@staged_path}/*"))
|
201
|
+
end
|
202
|
+
|
203
|
+
# create new and existing directories
|
204
|
+
FileUtils.mkdir_p(@staged_path.to_s + '/update')
|
205
|
+
FileUtils.mkdir_p(@staged_path.to_s + '/push/component')
|
206
|
+
FileUtils.mkdir_p(@staged_path.to_s + '/push/measure')
|
207
|
+
|
208
|
+
# keep track of noop, update, push
|
209
|
+
noops = 0
|
210
|
+
new_ones = 0
|
211
|
+
updates = 0
|
212
|
+
|
213
|
+
# get all content directories to process
|
214
|
+
dirs = Dir.glob("#{@measures_dir}/*")
|
215
|
+
|
216
|
+
dirs.each do |dir|
|
217
|
+
next if dir.include?('Rakefile') || File.basename(dir) == 'staged'
|
218
|
+
current_d = Dir.pwd
|
219
|
+
content_name = File.basename(dir)
|
220
|
+
puts '', '---'
|
221
|
+
puts "Generating #{content_name}"
|
222
|
+
|
223
|
+
Dir.chdir(dir)
|
224
|
+
|
225
|
+
# figure out whether to upload new or update existing
|
226
|
+
files = Pathname.glob('**/*')
|
227
|
+
uuid = nil
|
228
|
+
vid = nil
|
229
|
+
content_type = 'measure'
|
230
|
+
|
231
|
+
paths = []
|
232
|
+
files.each do |file|
|
233
|
+
# don't tar tests/outputs directory
|
234
|
+
next if file.to_s.start_with?('tests/output') # From measure testing process
|
235
|
+
next if file.to_s.start_with?('tests/test') # From openstudio-measure-tester-gem
|
236
|
+
next if file.to_s.start_with?('tests/coverage') # From openstudio-measure-tester-gem
|
237
|
+
next if file.to_s.start_with?('test_results') # From openstudio-measure-tester-gem
|
238
|
+
paths << file.to_s
|
239
|
+
if file.to_s =~ /^.{0,2}component.xml$/ || file.to_s =~ /^.{0,2}measure.xml$/
|
240
|
+
if file.to_s.match?(/^.{0,2}component.xml$/)
|
241
|
+
content_type = 'component'
|
242
|
+
end
|
243
|
+
# extract uuid and vid
|
244
|
+
uuid, vid = bcl.uuid_vid_from_xml(file)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
puts "UUID: #{uuid}, VID: #{vid}"
|
248
|
+
|
249
|
+
# note: if uuid is missing, will assume new content
|
250
|
+
action = bcl.search_by_uuid(uuid, vid)
|
251
|
+
puts "#{content_name} ACTION TO TAKE: #{action}"
|
252
|
+
# new content functionality needs to know if measure or component. update is agnostic.
|
253
|
+
if action == 'noop' # ignore up-to-date content
|
254
|
+
puts " - WARNING: local #{content_name} uuid and vid match BCL... no update will be performed"
|
255
|
+
noops += 1
|
256
|
+
next
|
257
|
+
elsif action == 'update'
|
258
|
+
# puts "#{content_name} labeled as update for BCL"
|
259
|
+
destination = @staged_path + '/' + action + '/' + "#{content_name}.tar.gz"
|
260
|
+
updates += 1
|
261
|
+
elsif action == 'push'
|
262
|
+
# puts "#{content_name} labeled as new content for BCL"
|
263
|
+
destination = @staged_path + '/' + action + '/' + content_type + "/#{content_name}.tar.gz"
|
264
|
+
new_ones += 1
|
265
|
+
end
|
266
|
+
|
267
|
+
puts "destination: #{destination}"
|
268
|
+
|
269
|
+
# copy over only if 'reset_receipts' is set to TRUE. otherwise ignore if file exists already
|
270
|
+
if File.exist?(destination)
|
271
|
+
if reset
|
272
|
+
FileUtils.rm(destination)
|
273
|
+
::BCL.tarball(destination, paths)
|
274
|
+
else
|
275
|
+
puts "*** WARNING: File #{content_name}.tar.gz already exists in staged directory... keeping existing file. To overwrite, set reset_receipts arg to true ***"
|
276
|
+
end
|
277
|
+
else
|
278
|
+
::BCL.tarball(destination, paths)
|
279
|
+
end
|
280
|
+
Dir.chdir(current_d)
|
281
|
+
end
|
282
|
+
puts '', "****STAGING DONE**** #{new_ones} new content, #{updates} updates, #{noops} skipped (already up-to-date on BCL)", ''
|
283
|
+
end
|
284
|
+
|
285
|
+
desc 'Upload measures from the specified location.'
|
286
|
+
task :push do
|
287
|
+
puts 'Push measures to BCL'
|
288
|
+
|
289
|
+
# initialize BCL and login
|
290
|
+
bcl = ::BCL::ComponentMethods.new
|
291
|
+
bcl.login
|
292
|
+
reset = false
|
293
|
+
|
294
|
+
total_count = 0
|
295
|
+
successes = 0
|
296
|
+
errors = 0
|
297
|
+
skipped = 0
|
298
|
+
|
299
|
+
# grab all the new measure and component tar files and push to bcl
|
300
|
+
['measure', 'component'].each do |content_type|
|
301
|
+
items = []
|
302
|
+
paths = Pathname.glob(@staged_path.to_s + "/push/#{content_type}/*.tar.gz")
|
303
|
+
paths.each do |path|
|
304
|
+
# puts path
|
305
|
+
items << path.to_s
|
306
|
+
end
|
307
|
+
|
308
|
+
items.each do |item|
|
309
|
+
puts item.split('/').last
|
310
|
+
total_count += 1
|
311
|
+
|
312
|
+
receipt_file = File.dirname(item) + '/' + File.basename(item, '.tar.gz') + '.receipt'
|
313
|
+
if !reset && File.exist?(receipt_file)
|
314
|
+
skipped += 1
|
315
|
+
puts 'SKIP: receipt file found'
|
316
|
+
next
|
317
|
+
end
|
318
|
+
|
319
|
+
valid, res = bcl.push_content(item, true, "nrel_#{content_type}")
|
320
|
+
if valid
|
321
|
+
successes += 1
|
322
|
+
else
|
323
|
+
errors += 1
|
324
|
+
if res.key?(:error)
|
325
|
+
puts " ERROR MESSAGE: #{res[:error]}"
|
326
|
+
else
|
327
|
+
puts "ERROR: #{res.inspect.chomp}"
|
328
|
+
end
|
329
|
+
end
|
330
|
+
puts '', '---'
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
# grab all the updated content (measures and components) tar files and push to bcl
|
335
|
+
items = []
|
336
|
+
paths = Pathname.glob(@staged_path.to_s + '/update/*.tar.gz')
|
337
|
+
paths.each do |path|
|
338
|
+
# puts path
|
339
|
+
items << path.to_s
|
340
|
+
end
|
341
|
+
items.each do |item|
|
342
|
+
puts item.split('/').last
|
343
|
+
total_count += 1
|
344
|
+
|
345
|
+
receipt_file = File.dirname(item) + '/' + File.basename(item, '.tar.gz') + '.receipt'
|
346
|
+
if !reset && File.exist?(receipt_file)
|
347
|
+
skipped += 1
|
348
|
+
puts 'SKIP: receipt file found'
|
349
|
+
next
|
350
|
+
end
|
351
|
+
|
352
|
+
valid, res = bcl.update_content(item, true)
|
353
|
+
if valid
|
354
|
+
successes += 1
|
355
|
+
else
|
356
|
+
errors += 1
|
357
|
+
if res.key?(:error)
|
358
|
+
puts " ERROR MESSAGE: #{res[:error]}"
|
359
|
+
else
|
360
|
+
puts "ERROR MESSAGE: #{res.inspect.chomp}"
|
361
|
+
end
|
362
|
+
end
|
363
|
+
puts '', '---'
|
364
|
+
end
|
365
|
+
|
366
|
+
puts "****UPLOAD DONE**** #{total_count} total, #{successes} success, #{errors} failures, #{skipped} skipped"
|
367
|
+
end
|
154
368
|
end
|
155
369
|
end
|
156
370
|
end
|
@@ -41,6 +41,7 @@ require 'openstudio'
|
|
41
41
|
require 'yaml'
|
42
42
|
require 'fileutils'
|
43
43
|
require 'parallel'
|
44
|
+
require 'bcl'
|
44
45
|
|
45
46
|
module OpenStudio
|
46
47
|
module Extension
|
@@ -55,7 +56,7 @@ module OpenStudio
|
|
55
56
|
# compatible with the OpenStudio CLI.
|
56
57
|
##
|
57
58
|
# @param [String] dirname Directory to run commands in, defaults to Dir.pwd. If directory includes a Gemfile then create a local bundle.
|
58
|
-
# @param bundle_without [
|
59
|
+
# @param bundle_without [Array] List of strings of the groups to exclude when running the bundle command
|
59
60
|
# @param options [Hash] Hash describing options for running the simulation. These are the defaults for all runs unless overriden within the run_* methods. Note if options is used, then a local runner.conf file will not be loaded.
|
60
61
|
# @option options [String] :max_datapoints Max number of datapoints to run
|
61
62
|
# @option options [String] :num_parallel Number of simulations to run in parallel at a time
|
@@ -560,21 +561,21 @@ module OpenStudio
|
|
560
561
|
puts "Encoding.default_internal = #{Encoding.default_internal}"
|
561
562
|
|
562
563
|
paths.each do |path|
|
563
|
-
Dir[path[:glob]].each do |
|
564
|
-
puts "Updating license in file #{
|
565
|
-
f = File.read(
|
566
|
-
if f
|
564
|
+
Dir[path[:glob]].each do |dir_file|
|
565
|
+
puts "Updating license in file #{dir_file}"
|
566
|
+
f = File.read(dir_file)
|
567
|
+
if f.match?(path[:regex])
|
567
568
|
puts ' License found -- updating'
|
568
|
-
File.open(
|
569
|
+
File.open(dir_file, 'w') { |write| write << f.gsub(path[:regex], path[:license]) }
|
569
570
|
elsif f =~ /\(C\)/i || f =~ /\(Copyright\)/i
|
570
571
|
puts ' File already has copyright -- skipping'
|
571
572
|
else
|
572
573
|
puts ' No license found -- adding'
|
573
|
-
if f
|
574
|
+
if f.match?(/#!/)
|
574
575
|
puts ' CANNOT add license to file automatically, add it manually and it will update automatically in the future'
|
575
576
|
next
|
576
577
|
end
|
577
|
-
File.open(
|
578
|
+
File.open(dir_file, 'w') { |write| write << f.insert(0, path[:license] + "\n") }
|
578
579
|
end
|
579
580
|
end
|
580
581
|
end
|