sinatra-chassis 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +3 -0
- data/LICENSE +7 -0
- data/README.md +19 -0
- data/Rakefile +1 -0
- data/bin/chassis +73 -0
- data/lib/sinatra/chassis.rb +213 -0
- data/lib/sinatra/chassis/file_manager.rb +151 -0
- data/lib/sinatra/chassis/helpers.rb +237 -0
- data/lib/sinatra/chassis/tasks.rb +7 -0
- data/lib/sinatra/tasks/assets.rake +40 -0
- data/lib/sinatra/tasks/chassis.rake +23 -0
- data/lib/sinatra/tasks/datamapper.rake +117 -0
- data/lib/sinatra/tasks/pony.rake +11 -0
- data/lib/sinatra/tasks/sinatra.rake +23 -0
- data/lib/sinatra/templates/chassis/.gitignore +6 -0
- data/lib/sinatra/templates/chassis/Gemfile +8 -0
- data/lib/sinatra/templates/chassis/README.md +4 -0
- data/lib/sinatra/templates/chassis/Rakefile +2 -0
- data/lib/sinatra/templates/chassis/app.rb +20 -0
- data/lib/sinatra/templates/chassis/config.ru +2 -0
- data/lib/sinatra/templates/chassis/public/favicon.ico +0 -0
- data/lib/sinatra/templates/chassis/public/robots.txt +3 -0
- data/lib/sinatra/templates/chassis/tmp/restart.txt +0 -0
- data/lib/sinatra/templates/chassis/views/layout.erb +18 -0
- data/lib/sinatra/templates/chassis/views/readme.erb +23 -0
- data/lib/sinatra/templates/datamapper/data/migrations/datamapper_migration.rb +13 -0
- data/lib/sinatra/templates/datamapper/data/seeds/seed.rb +1 -0
- data/lib/sinatra/templates/datamapper/models/datamapper.rb +8 -0
- data/lib/sinatra/templates/datamapper/settings/datamapper.rb +16 -0
- data/lib/sinatra/templates/datamapper/tests/models/datamapper_tests.rb +16 -0
- data/lib/sinatra/templates/pony/settings/pony.rb +27 -0
- data/lib/sinatra/templates/sinatra/routes/routes.rb +7 -0
- data/lib/sinatra/templates/sinatra/tests/routes/routes_tests.rb +17 -0
- data/lib/sinatra/views/error.erb +36 -0
- data/sinatra-chassis.gemspec +28 -0
- metadata +149 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (C) 2013 Jarrod Taylor, LLP.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
## Chassis
|
2
|
+
|
3
|
+
Chassis is a mutable framework extension for Sinatra that's designed not just to help you write less code, but to help you focus on less code.
|
4
|
+
|
5
|
+
gem install sinatra-chassis
|
6
|
+
|
7
|
+
### Instructions
|
8
|
+
|
9
|
+
http://jarrodtaylor.github.com/sinatra-chassis/
|
10
|
+
|
11
|
+
### License
|
12
|
+
|
13
|
+
Copyright (C) 2013 Screen Sized, LLP.
|
14
|
+
|
15
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
16
|
+
|
17
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
18
|
+
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/chassis
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'sinatra/chassis/file_manager'
|
5
|
+
|
6
|
+
# Sets the default switches
|
7
|
+
switches = {
|
8
|
+
git: false,
|
9
|
+
heroku: false,
|
10
|
+
bundler: true
|
11
|
+
}
|
12
|
+
|
13
|
+
# Internal: Parses command options and runs associated methods.
|
14
|
+
#
|
15
|
+
# Example
|
16
|
+
# ~: chassis -g -h ~/Projects/my_new_app
|
17
|
+
#
|
18
|
+
# Each command is self documenting.
|
19
|
+
options = OptionParser.new do |opt|
|
20
|
+
opt.banner = 'Options:'
|
21
|
+
|
22
|
+
opt.on('-g', '--git', 'Init a git repo, add the first commit') { switches[:git] = true }
|
23
|
+
|
24
|
+
opt.on('-h', '--heroku', 'Create a Heroku app') { switches[:heroku] = true }
|
25
|
+
|
26
|
+
opt.on('--skip-bundle', 'Don\'t run bundle install') { switches[:bundler] = false }
|
27
|
+
|
28
|
+
opt.parse!
|
29
|
+
end
|
30
|
+
|
31
|
+
# If app name is given, create application.
|
32
|
+
if ARGV[0]
|
33
|
+
app = ARGV[0]
|
34
|
+
|
35
|
+
unless File.exists? app
|
36
|
+
puts " Creating #{app}:"
|
37
|
+
puts LABELS[:add] + app
|
38
|
+
create_directory app
|
39
|
+
else
|
40
|
+
puts "#{app} already exists."
|
41
|
+
exit
|
42
|
+
end
|
43
|
+
|
44
|
+
copy_directory "#{TEMPLATES}/chassis", app
|
45
|
+
|
46
|
+
if switches[:bundler]
|
47
|
+
puts LABELS[:run] + 'bundle'
|
48
|
+
system "cd #{app} && bundle install"
|
49
|
+
end
|
50
|
+
|
51
|
+
puts LABELS[:run] + 'chmod -r 0755'
|
52
|
+
FileUtils.chmod_R 0755, app
|
53
|
+
|
54
|
+
if switches[:git]
|
55
|
+
puts LABELS[:run] + 'git'
|
56
|
+
system "cd #{app} && git init && git add . && git commit -m 'First!'"
|
57
|
+
end
|
58
|
+
|
59
|
+
if switches[:heroku]
|
60
|
+
puts LABELS[:run] + 'heroku'
|
61
|
+
system "cd #{app} && heroku create && git push heroku master"
|
62
|
+
end
|
63
|
+
|
64
|
+
puts "\n Next steps:\n cd #{app}\n ruby app.rb\n\n"
|
65
|
+
exit
|
66
|
+
end
|
67
|
+
|
68
|
+
# If script hasn't exited already, show help.
|
69
|
+
puts "The chassis command creates a new chassis app.\n\n"
|
70
|
+
puts "Usage:\n chassis [options] app_path\n\n"
|
71
|
+
puts "Example:\n chassis -g -h ~/Projects/my_app\n\n"
|
72
|
+
puts options
|
73
|
+
puts ''
|
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
|
5
|
+
# Public: Helpers used in the Chassis module.
|
6
|
+
# Can be overriden from an app.
|
7
|
+
module ChassisHelpers
|
8
|
+
|
9
|
+
# Public: Compares the request user agent against
|
10
|
+
# the mobile_user_agents setting Array items (should contain regexes).
|
11
|
+
#
|
12
|
+
# Example
|
13
|
+
#
|
14
|
+
# mobile_request?
|
15
|
+
# # => true
|
16
|
+
#
|
17
|
+
# Returns true/false.
|
18
|
+
def mobile_request?
|
19
|
+
settings.mobile_user_agents.any? { |agent| request.env['HTTP_USER_AGENT'] =~ agent }
|
20
|
+
end
|
21
|
+
|
22
|
+
# Public: Checks to see if a view template exists.
|
23
|
+
# It will check through all registered view directories.
|
24
|
+
#
|
25
|
+
# template - String of view template filename to look for
|
26
|
+
#
|
27
|
+
# Example
|
28
|
+
#
|
29
|
+
# view_template('show.haml')
|
30
|
+
# # => true
|
31
|
+
#
|
32
|
+
# Returns true/false.
|
33
|
+
def view_exists? template
|
34
|
+
Array(settings.views).each { |v| return true if File.exists?("#{v}/#{template}") }
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
# Public: Prepends the Sinatra find_template method to
|
39
|
+
# find .mobile templates if the mobile_views setting is true
|
40
|
+
# the request is from a mobile device.
|
41
|
+
#
|
42
|
+
# Example
|
43
|
+
#
|
44
|
+
# erb :my_view
|
45
|
+
#
|
46
|
+
# Renders the my_view.mobile.erb instead of my_view.erb.
|
47
|
+
def find_template views, name, engine, &block
|
48
|
+
name = "#{name}.mobile" if
|
49
|
+
(settings.mobile_views) &&
|
50
|
+
(mobile_request?) &&
|
51
|
+
(view_exists?("#{name}.mobile.#{@preferred_extension}"))
|
52
|
+
Array(views).each { |v| super(v, name, engine, &block) }
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
module Chassis
|
58
|
+
|
59
|
+
# Public: Requires all .rb files in a given directory or directories.
|
60
|
+
#
|
61
|
+
# *args - String(s) or Array of String paths to require
|
62
|
+
#
|
63
|
+
# Exmaple
|
64
|
+
#
|
65
|
+
# require_directory('routes', 'models')
|
66
|
+
#
|
67
|
+
# Returns nothing.
|
68
|
+
def require_directory *args
|
69
|
+
args = args.first if args.first.kind_of? Array
|
70
|
+
args.each do |directory|
|
71
|
+
Dir["./#{directory}/**/*.rb"].each { |file| require file }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Public: Additions to the Sinatra app.
|
76
|
+
def self.registered(app)
|
77
|
+
|
78
|
+
# Public: Defines the default load path to be used with require_directory.
|
79
|
+
#
|
80
|
+
# Example
|
81
|
+
#
|
82
|
+
# require_directory(settings.load_path)
|
83
|
+
app.set :load_path, ['config', 'settings', 'helpers', 'libraries', 'models', 'controllers', 'routes']
|
84
|
+
|
85
|
+
# Public: Defines the default mobile user agents.
|
86
|
+
app.set :mobile_user_agents, [/iPhone/, /Android.*AppleWebKit/]
|
87
|
+
|
88
|
+
# Public: Turns on .mobile view templates.
|
89
|
+
app.enable :mobile_views
|
90
|
+
|
91
|
+
# Public: Determines where to load assets from.
|
92
|
+
app.set :assets_path, ['public']
|
93
|
+
|
94
|
+
# Public: Compiles .scss file to .css on request.
|
95
|
+
#
|
96
|
+
# Example
|
97
|
+
#
|
98
|
+
# <link rel="stylesheet" type="text/css" href="theme.css">
|
99
|
+
#
|
100
|
+
# Returns the compiled theme.scss, if it exists.
|
101
|
+
# Note that requests to public files bypass this handler.
|
102
|
+
app.get '*.css/?' do
|
103
|
+
file = params[:splat].first
|
104
|
+
|
105
|
+
found = false
|
106
|
+
type = nil
|
107
|
+
|
108
|
+
settings.assets_path.each do |path|
|
109
|
+
file.sub!("#{path}/", '') unless path == 'public'
|
110
|
+
if File.exists?("./#{path}#{file}.css")
|
111
|
+
found = "#{path}#{file}"
|
112
|
+
type = 'css'
|
113
|
+
break
|
114
|
+
end
|
115
|
+
if File.exists?("./#{path}#{file}.scss")
|
116
|
+
found = "#{path}#{file}"
|
117
|
+
type = 'scss'
|
118
|
+
break
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
if found
|
123
|
+
content_type 'text/css'
|
124
|
+
if type == 'css'
|
125
|
+
File.read "#{found}.css"
|
126
|
+
elsif type == 'scss'
|
127
|
+
scss found.to_sym, views: './'
|
128
|
+
end
|
129
|
+
else
|
130
|
+
pass
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Public: Compiles .coffee file to .js on request.
|
135
|
+
#
|
136
|
+
# Example
|
137
|
+
#
|
138
|
+
# <script type="text/javascript" src"script.js"></script>
|
139
|
+
#
|
140
|
+
# Returns the compiled script.coffee, if it exists.
|
141
|
+
# Note that requests to public files bypass this handler.
|
142
|
+
app.get '*.js/?' do
|
143
|
+
file = params[:splat].first
|
144
|
+
|
145
|
+
found = false
|
146
|
+
type = nil
|
147
|
+
|
148
|
+
settings.assets_path.each do |path|
|
149
|
+
file.sub!("#{path}/", '') unless path == 'public'
|
150
|
+
if File.exists?("./#{path}#{file}.js")
|
151
|
+
found = "#{path}#{file}"
|
152
|
+
type = 'js'
|
153
|
+
break
|
154
|
+
end
|
155
|
+
if File.exists?("./#{path}#{file}.coffee")
|
156
|
+
found = "#{path}#{file}"
|
157
|
+
type = 'coffee'
|
158
|
+
break
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
if found
|
163
|
+
content_type 'text/javascript'
|
164
|
+
if type == 'js'
|
165
|
+
File.read "#{found}.js"
|
166
|
+
elsif type == 'coffee'
|
167
|
+
coffee found.to_sym, views: './'
|
168
|
+
end
|
169
|
+
else
|
170
|
+
pass
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Public: Adds the internal Chassis views directory to the app.
|
175
|
+
# Used for finding the built in error template.
|
176
|
+
app.set :views, ['views', File.dirname(__FILE__) + '/views']
|
177
|
+
|
178
|
+
# Public: Turns on the catch all route in a not_found request.
|
179
|
+
app.enable :catch_all_route
|
180
|
+
|
181
|
+
# Public: Handles 404s.
|
182
|
+
#
|
183
|
+
# If there is no matching route handler, this will return a view template
|
184
|
+
# by matching the request path to a /views directory path and file. If
|
185
|
+
# no template is found, a 404 is called.
|
186
|
+
#
|
187
|
+
# In production, the 404 will render the production error template.
|
188
|
+
not_found do
|
189
|
+
if settings.catch_all_route?
|
190
|
+
view = request.path[1..-1]
|
191
|
+
Tilt.mappings.each do |m|
|
192
|
+
return send(m.first, view.to_sym) if view_exists?("#{view}.#{m.first}")
|
193
|
+
end
|
194
|
+
end
|
195
|
+
erb(:error, layout: false, locals: { code: '404', message: 'Not Found' }) if production?
|
196
|
+
end
|
197
|
+
|
198
|
+
# Public: Makes production errors prettier by rendering a built in template.
|
199
|
+
configure :production do
|
200
|
+
error(400) { erb :error, layout: false, locals: { code: '400', message: 'Bad Request' } }
|
201
|
+
error(401) { erb :error, layout: false, locals: { code: '401', message: 'Unauthorized' } }
|
202
|
+
error(403) { erb :error, layout: false, locals: { code: '403', message: 'Forbidden' } }
|
203
|
+
error(408) { erb :error, layout: false, locals: { code: '408', message: 'Request Timeout' } }
|
204
|
+
error(500) { erb :error, layout: false, locals: { code: '500', message: 'Internal Server Error' } }
|
205
|
+
error(502) { erb :error, layout: false, locals: { code: '502', message: 'Bad Gateway' } }
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
210
|
+
|
211
|
+
helpers ChassisHelpers
|
212
|
+
register Chassis
|
213
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'paint'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
# Public: Hash of colored and aligned Strings for displaying command actions.
|
6
|
+
# If interpolated, don't use any surrounding spaces.
|
7
|
+
LABELS = {
|
8
|
+
add: Paint[' add ', :green],
|
9
|
+
ignore: Paint[' ignore ', :blue],
|
10
|
+
overwrite: Paint[' overwrite ', :yellow],
|
11
|
+
remove: Paint[' remove ', :red],
|
12
|
+
run: Paint[' run ', :magenta]
|
13
|
+
}
|
14
|
+
|
15
|
+
# Public: String path location of the templates directory.
|
16
|
+
TEMPLATES = "#{File.dirname(__FILE__)}/../templates"
|
17
|
+
|
18
|
+
# Public: Asks the user if a file should be overwritten.
|
19
|
+
#
|
20
|
+
# file - Sting path of file in question
|
21
|
+
#
|
22
|
+
# Example
|
23
|
+
#
|
24
|
+
# overwritable? 'path/to/my/file.rb'
|
25
|
+
#
|
26
|
+
# Returns true or false based on user selection.
|
27
|
+
def overwritable? path
|
28
|
+
puts "#{path} already exists. Replace? (yes or no)"
|
29
|
+
decision = gets.strip!.downcase!
|
30
|
+
return false unless (decision == 'yes') || (decision == 'y')
|
31
|
+
return true
|
32
|
+
end
|
33
|
+
|
34
|
+
# Public: Adds to the end of a file.
|
35
|
+
#
|
36
|
+
# file - String path of file to add to
|
37
|
+
# text - text to add
|
38
|
+
#
|
39
|
+
# Example
|
40
|
+
#
|
41
|
+
# appent_to_file 'path/to/file.rb', 'Hello, world!'
|
42
|
+
#
|
43
|
+
# Returns nothing.
|
44
|
+
#
|
45
|
+
# Todo
|
46
|
+
#
|
47
|
+
# - Return true/false based on success.
|
48
|
+
def append_to_file file, text
|
49
|
+
File.open(file, 'a') {|f| f.write(text) }
|
50
|
+
end
|
51
|
+
|
52
|
+
# Public: Copies a file from one location to another.
|
53
|
+
# Asks the user of existing files should be overwritten.
|
54
|
+
#
|
55
|
+
# orignal_file - String path of the file to be copied
|
56
|
+
# new_file - Destination of the copied file
|
57
|
+
#
|
58
|
+
# Example
|
59
|
+
#
|
60
|
+
# copy_file 'path/to/original_file.rb', 'path/to/new/location.rb'
|
61
|
+
#
|
62
|
+
# Returns true if the file was copied, false if not.
|
63
|
+
def copy_file original_file, new_file
|
64
|
+
unless File.exists? new_file
|
65
|
+
puts LABELS[:add] + new_file
|
66
|
+
FileUtils.cp original_file, new_file
|
67
|
+
return true
|
68
|
+
else
|
69
|
+
if overwritable? new_file
|
70
|
+
puts LABELS[:overwrite] + new_file
|
71
|
+
FileUtils.cp original_file, new_file
|
72
|
+
return true
|
73
|
+
else
|
74
|
+
puts LABELS[:ignore] + new_file
|
75
|
+
return false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Public: Copies a file using ERB to insert variables.
|
81
|
+
#
|
82
|
+
# template_file - String path of the template to be copied
|
83
|
+
# new_file - String path of the file to create from the template_file
|
84
|
+
# locals - Hash of variables to pass to the temlate_file
|
85
|
+
#
|
86
|
+
# Example
|
87
|
+
#
|
88
|
+
# copy_template "#{TEMPLATES}/path/to/template.rb",
|
89
|
+
# 'path/to/new/file.rb',
|
90
|
+
# { foo: 'bar' }
|
91
|
+
#
|
92
|
+
# Returns true if the template was copied, false if not.
|
93
|
+
def copy_template template_file, new_file, locals = {}
|
94
|
+
unless File.exists? new_file
|
95
|
+
puts LABELS[:add] + new_file
|
96
|
+
File.open(new_file, 'w') { |f| f.write( ERB.new(File.read(template_file)).result(binding) ) }
|
97
|
+
return true
|
98
|
+
else
|
99
|
+
if overwritable? new_file
|
100
|
+
puts LABELS[:overwrite] + new_file
|
101
|
+
File.open(new_file, 'w') { |f| f.write( ERB.new(File.read(template_file)).result(binding) ) }
|
102
|
+
return true
|
103
|
+
else
|
104
|
+
puts LABELS[:ignore] + new_file
|
105
|
+
return false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Public: Creates a directory if it doesn't already exist.
|
111
|
+
#
|
112
|
+
# *args - path(s) as a String, multiple Strings, or an Array of Strings
|
113
|
+
#
|
114
|
+
# Examples
|
115
|
+
#
|
116
|
+
# create_directory 'path/to/directory'
|
117
|
+
# create_directory 'path/to/directory', 'path/to/other/directory
|
118
|
+
# create_directory ['path/to/directory', 'path/to/other/directory']
|
119
|
+
#
|
120
|
+
# Returns nothing.
|
121
|
+
#
|
122
|
+
# Todo
|
123
|
+
#
|
124
|
+
# - Return true/false based on success.
|
125
|
+
def create_directory *args
|
126
|
+
args = args.first if args.first.kind_of? Array
|
127
|
+
args.each { |dir| FileUtils.mkdir(dir) unless File.exists?(dir) }
|
128
|
+
end
|
129
|
+
|
130
|
+
# Public: Copies a directory (with contents) to another directory.
|
131
|
+
# If the new directory doesn't exist, it will be created.
|
132
|
+
#
|
133
|
+
# original_dir - String path of the directory to be copied from
|
134
|
+
# new_dir - String path of directory to be copied to
|
135
|
+
#
|
136
|
+
# Example
|
137
|
+
#
|
138
|
+
# copy_directory 'path/to/original/directory', 'path/to/new/directory'
|
139
|
+
#
|
140
|
+
# Returns nothing.
|
141
|
+
#
|
142
|
+
# Todo
|
143
|
+
#
|
144
|
+
# - Return true/false based on success.
|
145
|
+
def copy_directory original_dir, new_dir
|
146
|
+
create_directory new_dir
|
147
|
+
Dir.glob("#{original_dir}/**/{*,.gitignore}").each do |path|
|
148
|
+
new_path = path.sub original_dir, new_dir
|
149
|
+
File.directory?(path) ? create_directory(new_path) : copy_file(path, new_path)
|
150
|
+
end
|
151
|
+
end
|