bones 2.0.3 → 2.1.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.
- data/History.txt +11 -0
- data/Manifest.txt +20 -25
- data/README.txt +114 -83
- data/Rakefile +7 -6
- data/data/Rakefile.erb +7 -1
- data/data/bin/NAME.erb +1 -1
- data/data/lib/NAME.rb.erb +4 -11
- data/data/spec/NAME_spec.rb.erb +0 -1
- data/data/spec/spec_helper.rb.erb +0 -1
- data/lib/bones.rb +21 -8
- data/lib/bones/annotation_extractor.rb +1 -2
- data/lib/bones/debug.rb +0 -1
- data/lib/bones/main.rb +183 -109
- data/lib/bones/smtp_tls.rb +0 -1
- data/{data → lib/bones}/tasks/ann.rake +0 -1
- data/{data → lib/bones}/tasks/bones.rake +0 -1
- data/lib/bones/tasks/gem.rake +192 -0
- data/{data → lib/bones}/tasks/git.rake +0 -1
- data/{data → lib/bones}/tasks/manifest.rake +3 -4
- data/{data → lib/bones}/tasks/notes.rake +0 -1
- data/{data → lib/bones}/tasks/post_load.rake +2 -2
- data/{data → lib/bones}/tasks/rdoc.rake +0 -1
- data/{data → lib/bones}/tasks/rubyforge.rake +2 -4
- data/{data → lib/bones}/tasks/setup.rb +14 -3
- data/{data → lib/bones}/tasks/spec.rake +1 -2
- data/{data → lib/bones}/tasks/svn.rake +0 -1
- data/{data → lib/bones}/tasks/test.rake +3 -1
- data/spec/bones/main_spec.rb +157 -0
- data/spec/bones_spec.rb +18 -0
- data/spec/data/data/README.txt +0 -0
- data/spec/data/data/Rakefile +0 -0
- data/spec/data/foo/README.txt +0 -0
- data/spec/data/foo/Rakefile +0 -0
- data/spec/spec_helper.rb +22 -0
- data/tasks/ann.rake +0 -1
- data/tasks/bones.rake +0 -1
- data/tasks/gem.rake +98 -32
- data/tasks/git.rake +0 -1
- data/tasks/manifest.rake +3 -4
- data/tasks/notes.rake +0 -1
- data/tasks/post_load.rake +2 -2
- data/tasks/rdoc.rake +0 -1
- data/tasks/rubyforge.rake +2 -4
- data/tasks/setup.rb +14 -3
- data/tasks/spec.rake +1 -2
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +3 -1
- metadata +40 -17
- data/data/tasks/gem.rake +0 -126
data/data/spec/NAME_spec.rb.erb
CHANGED
data/lib/bones.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
# $Id$
|
2
1
|
|
3
2
|
module Bones
|
4
3
|
|
5
4
|
# :stopdoc:
|
6
|
-
VERSION = '2.0
|
5
|
+
VERSION = '2.1.0'
|
7
6
|
PATH = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
8
7
|
WIN32 = %r/win32/ =~ RUBY_PLATFORM
|
9
8
|
DEV_NULL = WIN32 ? 'NUL:' : '/dev/null'
|
@@ -14,7 +13,7 @@ module Bones
|
|
14
13
|
# <tt>File.join</tt>.
|
15
14
|
#
|
16
15
|
def self.path( *args )
|
17
|
-
args.empty? ? PATH : File.join(PATH,
|
16
|
+
args.empty? ? PATH : File.join(PATH, args.flatten)
|
18
17
|
end
|
19
18
|
|
20
19
|
# call-seq:
|
@@ -28,20 +27,34 @@ module Bones
|
|
28
27
|
def self.require_all_libs_relative_to( fname, dir = nil )
|
29
28
|
dir ||= File.basename(fname, '.*')
|
30
29
|
search_me = File.expand_path(
|
31
|
-
File.join(File.dirname(fname), dir, '
|
30
|
+
File.join(File.dirname(fname), dir, '*.rb'))
|
32
31
|
|
33
32
|
Dir.glob(search_me).sort.each {|rb| require rb}
|
34
33
|
end
|
35
34
|
|
35
|
+
#
|
36
|
+
#
|
37
|
+
def self.setup
|
38
|
+
local_setup = File.join(Dir.pwd, %w[tasks setup.rb])
|
39
|
+
|
40
|
+
if test(?e, local_setup)
|
41
|
+
load local_setup
|
42
|
+
return
|
43
|
+
end
|
44
|
+
|
45
|
+
bones_setup = ::Bones.path %w[lib bones tasks setup.rb]
|
46
|
+
load bones_setup
|
47
|
+
|
48
|
+
rakefiles = Dir.glob(File.join(Dir.pwd, %w[tasks *.rake])).sort
|
49
|
+
import(*rakefiles)
|
50
|
+
end
|
51
|
+
|
36
52
|
# TODO: fix file lists for Test::Unit and RSpec
|
37
53
|
# these guys are just grabbing whatever is there and not pulling
|
38
54
|
# the filenames from the manifest
|
39
55
|
|
40
|
-
# TODO: create some tasks to generate e-mails / announcements
|
41
|
-
|
42
56
|
end # module Bones
|
43
57
|
|
44
|
-
|
45
|
-
Bones.require_all_libs_relative_to __FILE__
|
58
|
+
Bones.require_all_libs_relative_to(__FILE__)
|
46
59
|
|
47
60
|
# EOF
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# $Id$
|
2
1
|
|
3
2
|
begin
|
4
3
|
require 'facets/ansicode'
|
@@ -85,7 +84,7 @@ class AnnotationExtractor
|
|
85
84
|
|
86
85
|
text = m[2]
|
87
86
|
if text =~ @id_rgxp
|
88
|
-
text.gsub!(@id_rgxp) {|str|
|
87
|
+
text.gsub!(@id_rgxp) {|str| ANSICode.green(str)} if HAVE_COLOR
|
89
88
|
list << Annotation.new(lineno, m[1], text)
|
90
89
|
end
|
91
90
|
list
|
data/lib/bones/debug.rb
CHANGED
data/lib/bones/main.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# $Id$
|
2
1
|
|
3
2
|
require 'fileutils'
|
4
3
|
require 'optparse'
|
@@ -7,102 +6,161 @@ require 'erb'
|
|
7
6
|
module Bones
|
8
7
|
class Main
|
9
8
|
|
10
|
-
|
11
|
-
attr_accessor :name, :data, :verbose, :output_dir
|
9
|
+
attr_reader :options
|
12
10
|
|
13
11
|
# Create a new instance of Main, and run the +bones+ application given
|
14
12
|
# the command line _args_.
|
15
13
|
#
|
16
14
|
def self.run( args )
|
17
15
|
bones = self.new
|
18
|
-
bones.parse
|
16
|
+
bones.parse(args)
|
17
|
+
bones.run
|
18
|
+
end
|
19
|
+
|
20
|
+
# Create a new main instance using _io_ for standard output and _err_ for
|
21
|
+
# error messages.
|
22
|
+
#
|
23
|
+
def initialize( io = STDOUT, err = STDERR )
|
24
|
+
@io = io
|
25
|
+
@err = err
|
26
|
+
@options = {
|
27
|
+
:skeleton_dir => File.join(mrbones_dir, 'data'),
|
28
|
+
:with_tasks => false,
|
29
|
+
:verbose => false,
|
30
|
+
:name => nil,
|
31
|
+
:output_dir => nil,
|
32
|
+
:action => nil
|
33
|
+
}
|
34
|
+
@options[:skeleton_dir] = ::Bones.path('data') unless test(?d, skeleton_dir)
|
35
|
+
end
|
36
|
+
|
37
|
+
# The output directory where files will be written.
|
38
|
+
#
|
39
|
+
def output_dir
|
40
|
+
options[:output_dir]
|
41
|
+
end
|
19
42
|
|
20
|
-
|
21
|
-
|
43
|
+
# The directory where the project skeleton is located.
|
44
|
+
#
|
45
|
+
def skeleton_dir
|
46
|
+
options[:skeleton_dir]
|
47
|
+
end
|
48
|
+
|
49
|
+
# The project name from the command line.
|
50
|
+
#
|
51
|
+
def name
|
52
|
+
options[:name]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the project name but converted to be usable as a Ruby class
|
56
|
+
# name.
|
57
|
+
#
|
58
|
+
def classname
|
59
|
+
name.tr('-','_').split('_').map {|x| x.capitalize}.join
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns +true+ if we are updating an already existing project. Returns
|
63
|
+
# +false+ if we are creating a new project.
|
64
|
+
#
|
65
|
+
def update?
|
66
|
+
test(?e, output_dir) and with_tasks?
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns +true+ if we are going to copy the Mr Bones tasks into the
|
70
|
+
# destination directory. Normally this will return +false+.
|
71
|
+
#
|
72
|
+
def with_tasks?
|
73
|
+
options[:with_tasks]
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns +true+ if the user has requested verbose messages.
|
77
|
+
#
|
78
|
+
def verbose?
|
79
|
+
options[:verbose]
|
22
80
|
end
|
23
81
|
|
24
82
|
# Parse the command line arguments and store the values for later use by
|
25
83
|
# the +create+ and +update+ methods.
|
26
84
|
#
|
27
85
|
def parse( args )
|
28
|
-
self.data = File.join(mrbones_dir, 'data')
|
29
|
-
self.data = ::Bones.path('data') unless test(?d, data)
|
30
|
-
self.update = false
|
31
|
-
self.verbose = false
|
32
|
-
|
33
86
|
opts = OptionParser.new
|
34
87
|
opts.banner << ' project_name'
|
35
88
|
|
36
89
|
opts.separator ''
|
37
|
-
opts.on('-
|
38
|
-
|
39
|
-
|
40
|
-
'enable verbose output') {self.verbose = true}
|
90
|
+
opts.on('-v', '--verbose', 'enable verbose output') {
|
91
|
+
options[:verbose] = true
|
92
|
+
}
|
41
93
|
opts.on('-d', '--directory DIRECTORY', String,
|
42
|
-
'project directory to create',
|
43
|
-
|
94
|
+
'project directory to create', '(defaults to project_name)') {|dir|
|
95
|
+
options[:output_dir] = dir
|
96
|
+
}
|
44
97
|
opts.on('-s', '--skeleton NAME', String,
|
45
|
-
'project skeleton to use') do |
|
46
|
-
path = File.join(mrbones_dir,
|
98
|
+
'project skeleton to use') do |skeleton_name|
|
99
|
+
path = File.join(mrbones_dir, skeleton_name)
|
47
100
|
if test(?d, path)
|
48
|
-
|
49
|
-
elsif test(?d,
|
50
|
-
|
101
|
+
options[:skeleton_dir] = path
|
102
|
+
elsif test(?d, skeleton_name)
|
103
|
+
options[:skeleton_dir] = skeleton_name
|
51
104
|
else
|
52
|
-
|
105
|
+
@io.puts " unknown skeleton '#{skeleton_name}'"
|
53
106
|
exit
|
54
107
|
end
|
55
108
|
end
|
109
|
+
opts.on('--with-tasks', 'copy rake tasks to the project folder') {
|
110
|
+
options[:with_tasks] = true
|
111
|
+
}
|
56
112
|
|
57
113
|
opts.separator ''
|
58
|
-
opts.on('--freeze', 'freeze the project skeleton') {
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
114
|
+
opts.on('--freeze', 'freeze the project skeleton') {
|
115
|
+
options[:action] = :freeze
|
116
|
+
}
|
117
|
+
opts.on('--unfreeze', 'use the standard project skeleton') {
|
118
|
+
options[:action] = :unfreeze
|
119
|
+
}
|
120
|
+
opts.on('-i', '--info', 'report on the project skeleton being used') {
|
121
|
+
options[:action] = :info
|
122
|
+
}
|
67
123
|
|
68
124
|
opts.separator ''
|
69
125
|
opts.separator 'common options:'
|
70
|
-
|
71
|
-
|
72
|
-
STDOUT.puts opts
|
126
|
+
opts.on_tail( '-h', '--help', 'show this message' ) {
|
127
|
+
@io.puts opts
|
73
128
|
exit
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
STDOUT.puts "Mr Bones #{::Bones::VERSION}"
|
129
|
+
}
|
130
|
+
opts.on_tail( '--version', 'show version' ) {
|
131
|
+
@io.puts "Mr Bones #{::Bones::VERSION}"
|
78
132
|
exit
|
79
|
-
|
133
|
+
}
|
80
134
|
|
81
135
|
# parse the command line arguments
|
82
136
|
opts.parse! args
|
83
|
-
|
137
|
+
options[:name] = args.empty? ? nil : args.join('_')
|
84
138
|
|
85
|
-
if name.nil?
|
86
|
-
|
139
|
+
if options[:action].nil? and name.nil?
|
140
|
+
@io.puts opts
|
87
141
|
::Kernel.abort
|
88
142
|
end
|
89
143
|
|
90
|
-
|
144
|
+
options[:output_dir] = name if output_dir.nil?
|
91
145
|
nil
|
92
146
|
end
|
93
147
|
|
94
|
-
#
|
95
|
-
# +false+ if we are creating a new project.
|
96
|
-
#
|
97
|
-
def update?
|
98
|
-
@update
|
99
|
-
end
|
100
|
-
|
101
|
-
# Returns the project name but converted to be usable as a Ruby class
|
102
|
-
# name.
|
148
|
+
# Run the main application.
|
103
149
|
#
|
104
|
-
def
|
105
|
-
|
150
|
+
def run
|
151
|
+
case options[:action]
|
152
|
+
when :freeze
|
153
|
+
freeze
|
154
|
+
when :unfreeze
|
155
|
+
unfreeze
|
156
|
+
when :info
|
157
|
+
@io.puts "the project skeleton will be copied from"
|
158
|
+
@io.write " "
|
159
|
+
@io.puts skeleton_dir
|
160
|
+
else
|
161
|
+
if update? then update
|
162
|
+
else create end
|
163
|
+
end
|
106
164
|
end
|
107
165
|
|
108
166
|
# Create a new project from the bones/data project template.
|
@@ -113,17 +171,18 @@ class Main
|
|
113
171
|
|
114
172
|
begin
|
115
173
|
files_to_copy.each {|fn| cp fn}
|
174
|
+
copy_tasks(File.join(output_dir, 'tasks')) if with_tasks?
|
116
175
|
|
117
176
|
pwd = File.expand_path(FileUtils.pwd)
|
118
177
|
msg = "created '#{name}'"
|
119
178
|
msg << " in directory '#{output_dir}'" if name != output_dir
|
120
|
-
|
179
|
+
@io.puts msg
|
121
180
|
|
122
181
|
if test(?f, File.join(output_dir, 'Rakefile'))
|
123
182
|
begin
|
124
183
|
FileUtils.cd output_dir
|
125
184
|
system "rake manifest:create 2>&1 > #{::Bones::DEV_NULL}"
|
126
|
-
|
185
|
+
@io.puts "now you need to fix these files"
|
127
186
|
system "rake notes"
|
128
187
|
ensure
|
129
188
|
FileUtils.cd pwd
|
@@ -144,7 +203,7 @@ class Main
|
|
144
203
|
abort "'#{output_dir}' does not exist" unless test ?e, output_dir
|
145
204
|
|
146
205
|
task_dir = File.join(output_dir, 'tasks')
|
147
|
-
|
206
|
+
FileUtils.mkdir_p(task_dir) unless test(?d, task_dir)
|
148
207
|
|
149
208
|
archive_dir = File.join(task_dir, 'archive')
|
150
209
|
FileUtils.rm_rf archive_dir
|
@@ -155,14 +214,11 @@ class Main
|
|
155
214
|
FileUtils.cp fn, archive_dir
|
156
215
|
end
|
157
216
|
|
158
|
-
|
159
|
-
next unless %r/^tasks\// =~ fn
|
160
|
-
cp fn
|
161
|
-
end
|
217
|
+
copy_tasks(task_dir)
|
162
218
|
|
163
219
|
msg = "updated tasks for '#{name}'"
|
164
220
|
msg << " in directory '#{output_dir}'" if name != output_dir
|
165
|
-
|
221
|
+
@io.puts msg
|
166
222
|
end
|
167
223
|
|
168
224
|
# Freeze the project skeleton to the current Mr Bones gem. If the project
|
@@ -173,41 +229,28 @@ class Main
|
|
173
229
|
# Bones skeleton will be copied to the user's data directory.
|
174
230
|
#
|
175
231
|
def freeze
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
tasks_only = false
|
180
|
-
|
181
|
-
if test(?d, data_dir)
|
182
|
-
STDOUT.puts "archiving #{data_dir}" if verbose
|
183
|
-
FileUtils.rm_rf(archive_dir)
|
184
|
-
FileUtils.mkdir(archive_dir)
|
185
|
-
FileUtils.cp_r(File.join(data_dir, '.'), archive_dir)
|
186
|
-
tasks_only = true
|
187
|
-
else
|
188
|
-
FileUtils.mkdir_p(data_dir)
|
189
|
-
end
|
232
|
+
options[:skeleton_dir] = ::Bones.path('data')
|
233
|
+
options[:name] = 'data' if name.nil?
|
234
|
+
options[:output_dir] = File.join(mrbones_dir, name)
|
190
235
|
|
191
|
-
|
192
|
-
|
236
|
+
archive(output_dir, "#{output_dir}.archive")
|
237
|
+
FileUtils.mkdir_p(output_dir)
|
193
238
|
|
194
|
-
|
195
|
-
|
239
|
+
files_to_copy.each do |file|
|
240
|
+
src = File.join(skeleton_dir, file)
|
241
|
+
dst = File.join(output_dir, file)
|
196
242
|
|
197
|
-
|
243
|
+
@io.puts "freezing #{dst}" if verbose?
|
198
244
|
FileUtils.mkdir_p(File.dirname(dst))
|
199
245
|
FileUtils.cp(src, dst)
|
200
246
|
end
|
201
247
|
|
248
|
+
copy_tasks(File.join(output_dir, 'tasks'), 'freezing') if with_tasks?
|
249
|
+
|
202
250
|
File.open(frozen_version_file, 'w') {|fd| fd.puts ::Bones::VERSION}
|
203
251
|
|
204
|
-
|
205
|
-
STDOUT.puts "project skeleton tasks have been updated " <<
|
206
|
-
"from Mr Bones #{::Bones::VERSION}"
|
207
|
-
else
|
208
|
-
STDOUT.puts "project skeleton has been frozen " <<
|
252
|
+
@io.puts "project skeleton has been frozen " <<
|
209
253
|
"to Mr Bones #{::Bones::VERSION}"
|
210
|
-
end
|
211
254
|
end
|
212
255
|
|
213
256
|
# Unfreeze the project skeleton. The default Mr Bones skeleton will be
|
@@ -215,20 +258,14 @@ class Main
|
|
215
258
|
# one exists.
|
216
259
|
#
|
217
260
|
def unfreeze
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
if
|
222
|
-
|
223
|
-
|
224
|
-
FileUtils.mkdir(archive_dir)
|
225
|
-
FileUtils.cp_r(File.join(data_dir, '.'), archive_dir)
|
226
|
-
FileUtils.rm_rf(data_dir)
|
227
|
-
|
228
|
-
STDOUT.puts "project skeleton has been unfrozen"
|
229
|
-
STDOUT.puts "(default Mr Bones #{::Bones::VERSION} sekeleton will be used)"
|
261
|
+
options[:name] = 'data' if name.nil?
|
262
|
+
options[:output_dir] = File.join(mrbones_dir, name)
|
263
|
+
|
264
|
+
if archive(output_dir, "#{output_dir}.archive")
|
265
|
+
@io.puts "project skeleton has been unfrozen"
|
266
|
+
@io.puts "(default Mr Bones #{::Bones::VERSION} skeleton will be used)"
|
230
267
|
else
|
231
|
-
|
268
|
+
@io.puts "project skeleton is not frozen (no action taken)"
|
232
269
|
end
|
233
270
|
FileUtils.rm_f frozen_version_file
|
234
271
|
end
|
@@ -237,10 +274,10 @@ class Main
|
|
237
274
|
# the new project directory
|
238
275
|
#
|
239
276
|
def files_to_copy
|
240
|
-
rgxp = %r/\A#{
|
277
|
+
rgxp = %r/\A#{skeleton_dir}\/?/o
|
241
278
|
exclude = %r/tmp$|bak$|~$|CVS|\.svn/o
|
242
279
|
|
243
|
-
ary = Dir.glob(File.join(
|
280
|
+
ary = Dir.glob(File.join(skeleton_dir, '**', '*')).map do |filename|
|
244
281
|
next if exclude =~ filename
|
245
282
|
next if test(?d, filename)
|
246
283
|
filename.sub rgxp, ''
|
@@ -251,9 +288,6 @@ class Main
|
|
251
288
|
ary
|
252
289
|
end
|
253
290
|
|
254
|
-
|
255
|
-
private
|
256
|
-
|
257
291
|
# Copy a file from the Bones prototype project location to the user
|
258
292
|
# specified project location. A message will be displayed to the screen
|
259
293
|
# indicating that the file is being created.
|
@@ -262,9 +296,9 @@ class Main
|
|
262
296
|
dir = File.dirname(file).sub('NAME', name)
|
263
297
|
dir = (dir == '.' ? output_dir : File.join(output_dir, dir))
|
264
298
|
dst = File.join(dir, File.basename(file, '.erb').sub('NAME', name))
|
265
|
-
src = File.join(
|
299
|
+
src = File.join(skeleton_dir, file)
|
266
300
|
|
267
|
-
|
301
|
+
@io.puts(test(?e, dst) ? "updating #{dst}" : "creating #{dst}") if verbose?
|
268
302
|
FileUtils.mkdir_p(dir)
|
269
303
|
|
270
304
|
if '.erb' == File.extname(file)
|
@@ -277,10 +311,50 @@ class Main
|
|
277
311
|
FileUtils.chmod(File.stat(src).mode, dst)
|
278
312
|
end
|
279
313
|
|
314
|
+
# Archive the contents of the _from_ directory into the _to_ directory.
|
315
|
+
# The _to_ directory will be deleted if it currently exists. After the
|
316
|
+
# copy the _from_ directory will be deleted.
|
317
|
+
#
|
318
|
+
# Returns +true+ if the directory was archived. Returns +false+ if the
|
319
|
+
# directory was not archived.
|
320
|
+
#
|
321
|
+
def archive( from, to )
|
322
|
+
if test(?d, from)
|
323
|
+
@io.puts "archiving #{from}" if verbose?
|
324
|
+
FileUtils.rm_rf(to)
|
325
|
+
FileUtils.mkdir(to)
|
326
|
+
FileUtils.cp_r(File.join(from, '.'), to)
|
327
|
+
FileUtils.rm_rf(from)
|
328
|
+
true
|
329
|
+
else
|
330
|
+
false
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
# Copy the Mr Bones tasks into the _to_ directory. If we are in verbose
|
335
|
+
# mode, then a message will be displayed to the user. This message can be
|
336
|
+
# passed in as the _msg_ argument. The current file being copied is
|
337
|
+
# appened to the end of the message.
|
338
|
+
#
|
339
|
+
def copy_tasks( to, msg = nil )
|
340
|
+
Dir.glob(::Bones.path(%w[lib bones tasks *])).sort.each do |src|
|
341
|
+
dst = File.join(to, File.basename(src))
|
342
|
+
|
343
|
+
if msg
|
344
|
+
@io.puts "#{msg} #{dst}" if verbose?
|
345
|
+
else
|
346
|
+
@io.puts(test(?e, dst) ? "updating #{dst}" : "creating #{dst}") if verbose?
|
347
|
+
end
|
348
|
+
|
349
|
+
FileUtils.mkdir_p(File.dirname(dst))
|
350
|
+
FileUtils.cp(src, dst)
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
280
354
|
# Prints an abort _msg_ to the screen and then exits the Ruby interpreter.
|
281
355
|
#
|
282
356
|
def abort( msg )
|
283
|
-
|
357
|
+
@err.puts msg
|
284
358
|
exit 1
|
285
359
|
end
|
286
360
|
|