theme-juice 0.5.0 → 0.6.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 +4 -4
- data/README.md +3 -3
- data/bin/tj +5 -13
- data/lib/theme-juice/cli.rb +172 -343
- data/lib/theme-juice/command.rb +14 -0
- data/lib/theme-juice/commands/create.rb +17 -0
- data/lib/theme-juice/commands/delete.rb +17 -0
- data/lib/theme-juice/commands/install.rb +17 -0
- data/lib/theme-juice/commands/list.rb +17 -0
- data/lib/theme-juice/commands/subcommand.rb +17 -0
- data/lib/theme-juice/environment.rb +14 -0
- data/lib/theme-juice/interaction.rb +446 -0
- data/lib/theme-juice/interactions/create_site_options.rb +288 -0
- data/lib/theme-juice/interactions/delete_site_options.rb +58 -0
- data/lib/theme-juice/interactions/teejay.rb +6 -0
- data/lib/theme-juice/service.rb +190 -0
- data/lib/theme-juice/services/config_file.rb +44 -0
- data/lib/theme-juice/services/create_site.rb +387 -0
- data/lib/theme-juice/services/delete_site.rb +114 -0
- data/lib/theme-juice/services/list_sites.rb +40 -0
- data/lib/theme-juice/version.rb +1 -1
- data/lib/theme-juice.rb +19 -6
- metadata +33 -6
- data/lib/theme-juice/executor.rb +0 -804
- data/lib/theme-juice/ui.rb +0 -227
- data/lib/theme-juice/utilities.rb +0 -56
@@ -0,0 +1,288 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module ThemeJuice
|
4
|
+
class Interaction::CreateSiteOptions
|
5
|
+
|
6
|
+
#
|
7
|
+
# Set up interactions and environment
|
8
|
+
#
|
9
|
+
# @return {Void}
|
10
|
+
#
|
11
|
+
def initialize
|
12
|
+
@environment = ::ThemeJuice::Environment
|
13
|
+
@interaction = ::ThemeJuice::Interaction
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# Set up needed site options
|
18
|
+
#
|
19
|
+
# @param {Hash} opts
|
20
|
+
#
|
21
|
+
# @return {Hash}
|
22
|
+
#
|
23
|
+
def setup_site_options(opts = {})
|
24
|
+
@opts = opts
|
25
|
+
|
26
|
+
if @environment.yolo
|
27
|
+
@opts[:use_defaults] = true
|
28
|
+
end
|
29
|
+
|
30
|
+
required_opts = [
|
31
|
+
:site_name,
|
32
|
+
:site_name_clean,
|
33
|
+
:site_location,
|
34
|
+
:site_starter_theme,
|
35
|
+
:site_dev_location,
|
36
|
+
:site_dev_url,
|
37
|
+
:site_repository,
|
38
|
+
:site_db_host,
|
39
|
+
:site_db_name,
|
40
|
+
:site_db_user,
|
41
|
+
:site_db_pass
|
42
|
+
]
|
43
|
+
|
44
|
+
required_opts.each do |opt|
|
45
|
+
@opts[opt] = self.send "setup_#{opt}" unless @opts[opt]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Verify that all the options are correct
|
49
|
+
@interaction.list "Your settings :", :yellow, [
|
50
|
+
"Site name: #{@opts[:site_name]}",
|
51
|
+
"Site location: #{@opts[:site_location]}",
|
52
|
+
"Starter theme: #{@opts[:site_starter_theme]}",
|
53
|
+
"Development location: #{@opts[:site_dev_location]}",
|
54
|
+
"Development url: http://#{@opts[:site_dev_url]}",
|
55
|
+
"Initialized repository: #{@opts[:site_repository]}",
|
56
|
+
"Database host: #{@opts[:site_db_host]}",
|
57
|
+
"Database name: #{@opts[:site_db_name]}",
|
58
|
+
"Database username: #{@opts[:site_db_user]}",
|
59
|
+
"Database password: #{@opts[:site_db_pass]}"
|
60
|
+
]
|
61
|
+
|
62
|
+
unless @interaction.agree? "Do the options above look correct?"
|
63
|
+
@interaction.error "Dang typos... aborting mission."
|
64
|
+
end
|
65
|
+
|
66
|
+
@opts
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
#
|
72
|
+
# Site name
|
73
|
+
#
|
74
|
+
# @return {String}
|
75
|
+
#
|
76
|
+
def setup_site_name
|
77
|
+
if @environment.yolo
|
78
|
+
name = Faker::Company.bs.split(" ").sample.downcase
|
79
|
+
else
|
80
|
+
name = @interaction.prompt "What's the site name? (letters, numbers and dashes only)"
|
81
|
+
end
|
82
|
+
|
83
|
+
validate_site_name name
|
84
|
+
|
85
|
+
name
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# Clean site name
|
90
|
+
#
|
91
|
+
# @return {String}
|
92
|
+
#
|
93
|
+
def setup_site_name_clean
|
94
|
+
"#{@opts[:site_name]}".gsub(/[^\w]/, "_")[0..10]
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# Site local location
|
99
|
+
#
|
100
|
+
# @return {String}
|
101
|
+
#
|
102
|
+
def setup_site_location
|
103
|
+
path = "#{Dir.pwd}/"
|
104
|
+
|
105
|
+
if @opts[:use_defaults]
|
106
|
+
location = File.expand_path(path)
|
107
|
+
else
|
108
|
+
location = File.expand_path(@interaction.prompt "Where do you want to setup the site?", default: path, path: true)
|
109
|
+
end
|
110
|
+
|
111
|
+
location
|
112
|
+
end
|
113
|
+
|
114
|
+
#
|
115
|
+
# Site starter theme
|
116
|
+
#
|
117
|
+
# @return {String}
|
118
|
+
#
|
119
|
+
def setup_site_starter_theme
|
120
|
+
if @opts[:site_bare]
|
121
|
+
theme = false
|
122
|
+
else
|
123
|
+
themes = {
|
124
|
+
"theme-juice/theme-juice-starter" => "https://github.com/ezekg/theme-juice-starter.git",
|
125
|
+
"other" => nil,
|
126
|
+
"none" => false
|
127
|
+
}
|
128
|
+
|
129
|
+
if @opts[:use_defaults]
|
130
|
+
return themes["theme-juice/theme-juice-starter"]
|
131
|
+
end
|
132
|
+
|
133
|
+
choice = @interaction.choose "Which starter theme would you like to use?", :blue, themes.keys
|
134
|
+
|
135
|
+
case choice
|
136
|
+
when "theme-juice/theme-juice-starter"
|
137
|
+
@interaction.success "Awesome choice!"
|
138
|
+
when "other"
|
139
|
+
themes[choice] = @interaction.prompt "What is the repository URL for the starter theme you would like to clone?"
|
140
|
+
when "none"
|
141
|
+
@interaction.notice "Next time you need to create a site without a starter theme, you can just run the 'setup' command instead."
|
142
|
+
@opts[:site_bare] = true
|
143
|
+
end
|
144
|
+
|
145
|
+
theme = themes[choice]
|
146
|
+
end
|
147
|
+
|
148
|
+
theme
|
149
|
+
end
|
150
|
+
|
151
|
+
#
|
152
|
+
# Site development location
|
153
|
+
#
|
154
|
+
# @return {String}
|
155
|
+
#
|
156
|
+
def setup_site_dev_location
|
157
|
+
dev_location = File.expand_path("#{@environment.vvv_path}/www/tj-#{@opts[:site_name]}")
|
158
|
+
end
|
159
|
+
|
160
|
+
#
|
161
|
+
# Site development url
|
162
|
+
#
|
163
|
+
# @return {String}
|
164
|
+
#
|
165
|
+
def setup_site_dev_url
|
166
|
+
if @opts[:use_defaults]
|
167
|
+
url = "#{@opts[:site_name]}.dev"
|
168
|
+
else
|
169
|
+
url = @interaction.prompt "What do you want the development url to be? (this should end in '.dev')", default: "#{@opts[:site_name]}.dev"
|
170
|
+
end
|
171
|
+
|
172
|
+
validate_site_dev_url url
|
173
|
+
|
174
|
+
url
|
175
|
+
end
|
176
|
+
|
177
|
+
#
|
178
|
+
# Site repository
|
179
|
+
#
|
180
|
+
# @return {String}
|
181
|
+
#
|
182
|
+
def setup_site_repository
|
183
|
+
if @opts[:use_defaults] || @opts[:skip_repo]
|
184
|
+
repo = false
|
185
|
+
else
|
186
|
+
if @interaction.agree? "Would you like to initialize a new Git repository?"
|
187
|
+
repo = @interaction.prompt "What is the repository's URL?", indent: 2
|
188
|
+
else
|
189
|
+
repo = false
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
repo
|
194
|
+
end
|
195
|
+
|
196
|
+
#
|
197
|
+
# Database host
|
198
|
+
#
|
199
|
+
# @return {String}
|
200
|
+
#
|
201
|
+
def setup_site_db_host
|
202
|
+
if @opts[:use_defaults] || @opts[:skip_db]
|
203
|
+
db_host = "vvv"
|
204
|
+
else
|
205
|
+
db_host = @interaction.prompt "Database host", default: "vvv"
|
206
|
+
end
|
207
|
+
|
208
|
+
db_host
|
209
|
+
end
|
210
|
+
|
211
|
+
#
|
212
|
+
# Database name
|
213
|
+
#
|
214
|
+
# @return {String}
|
215
|
+
#
|
216
|
+
def setup_site_db_name
|
217
|
+
if @opts[:use_defaults] || @opts[:skip_db]
|
218
|
+
db_name = "#{@opts[:site_name_clean]}_db"
|
219
|
+
else
|
220
|
+
db_name = @interaction.prompt "Database name", default: "#{@opts[:site_name_clean]}_db"
|
221
|
+
end
|
222
|
+
|
223
|
+
db_name
|
224
|
+
end
|
225
|
+
|
226
|
+
#
|
227
|
+
# Database username
|
228
|
+
#
|
229
|
+
# @return {String}
|
230
|
+
#
|
231
|
+
def setup_site_db_user
|
232
|
+
if @opts[:use_defaults] || @opts[:skip_db]
|
233
|
+
db_user = "#{@opts[:site_name_clean]}_user"
|
234
|
+
else
|
235
|
+
db_user = @interaction.prompt "Database username", default: "#{@opts[:site_name_clean]}_user"
|
236
|
+
end
|
237
|
+
|
238
|
+
db_user
|
239
|
+
end
|
240
|
+
|
241
|
+
#
|
242
|
+
# Database password
|
243
|
+
#
|
244
|
+
# @return {String}
|
245
|
+
#
|
246
|
+
def setup_site_db_pass
|
247
|
+
pass = Faker::Internet.password 16
|
248
|
+
|
249
|
+
if @opts[:use_defaults] || @opts[:skip_db]
|
250
|
+
db_pass = pass
|
251
|
+
else
|
252
|
+
db_pass = @interaction.prompt "Database password", default: pass
|
253
|
+
end
|
254
|
+
|
255
|
+
db_pass
|
256
|
+
end
|
257
|
+
|
258
|
+
#
|
259
|
+
# Validate site name
|
260
|
+
#
|
261
|
+
# @param {String} name
|
262
|
+
#
|
263
|
+
# @return {Void}
|
264
|
+
#
|
265
|
+
def validate_site_name(name)
|
266
|
+
if name.empty?
|
267
|
+
@interaction.error "Site name '#{name}' is invalid or empty. Aborting mission."
|
268
|
+
end
|
269
|
+
|
270
|
+
"#{name}".match /[^0-9A-Za-z.\-]/ do |char|
|
271
|
+
@interaction.error "Site name contains an invalid character '#{char}'. This name is used for creating directories, so that's not gonna work. Aborting mission."
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
#
|
276
|
+
# Validate site url
|
277
|
+
#
|
278
|
+
# @param {String} url
|
279
|
+
#
|
280
|
+
# @return {Void}
|
281
|
+
#
|
282
|
+
def validate_site_dev_url(url)
|
283
|
+
unless "#{url}".match /(.dev)$/
|
284
|
+
@interaction.error "Your development url '#{url}' doesn't end with '.dev'. This is used internally by Landrush, so that's not gonna work. Aborting mission."
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module ThemeJuice
|
4
|
+
class Interaction::DeleteSiteOptions
|
5
|
+
|
6
|
+
#
|
7
|
+
# Set up interactions and environment
|
8
|
+
#
|
9
|
+
# @return {Void}
|
10
|
+
#
|
11
|
+
def initialize
|
12
|
+
@environment = ::ThemeJuice::Environment
|
13
|
+
@interaction = ::ThemeJuice::Interaction
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# Get needed site options
|
18
|
+
#
|
19
|
+
# @param {Hash} opts
|
20
|
+
#
|
21
|
+
# @return {Hash}
|
22
|
+
#
|
23
|
+
def get_site_options(opts = {})
|
24
|
+
@opts = opts
|
25
|
+
|
26
|
+
required_opts = [
|
27
|
+
:site_name,
|
28
|
+
:site_dev_location
|
29
|
+
]
|
30
|
+
|
31
|
+
required_opts.each do |opt|
|
32
|
+
@opts[opt] = self.send "get_#{opt}" unless @opts[opt]
|
33
|
+
end
|
34
|
+
|
35
|
+
@opts
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
#
|
41
|
+
# Site name
|
42
|
+
#
|
43
|
+
# @return {String}
|
44
|
+
#
|
45
|
+
def get_site_name
|
46
|
+
name = @interaction.choose "Which site would you like to delete?", :red, ::ThemeJuice::Service::ListSites.new.get_sites
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Site development location
|
51
|
+
#
|
52
|
+
# @return {String}
|
53
|
+
#
|
54
|
+
def get_site_dev_location
|
55
|
+
dev_location = File.expand_path("#{@environment.vvv_path}/www/tj-#{@opts[:site_name]}")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module ThemeJuice
|
4
|
+
class Service
|
5
|
+
include ::Thor::Actions
|
6
|
+
include ::Thor::Shell
|
7
|
+
|
8
|
+
#
|
9
|
+
# @param {Hash} opts
|
10
|
+
#
|
11
|
+
def initialize(opts)
|
12
|
+
@environment = ::ThemeJuice::Environment
|
13
|
+
@interaction = ::ThemeJuice::Interaction
|
14
|
+
@opts = opts
|
15
|
+
@config_path = opts[:site_location] || Dir.pwd
|
16
|
+
@config_regex = %r{^(\.)?(tj.y(a)?ml)}
|
17
|
+
rescue => err
|
18
|
+
@interaction.error "Whoops! Something went wrong!" do
|
19
|
+
puts err
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
#
|
26
|
+
# Run system commands
|
27
|
+
#
|
28
|
+
# @param {Array} commands
|
29
|
+
# Array of commands to run
|
30
|
+
# @param {Bool} silent (true)
|
31
|
+
# Silence all output from command
|
32
|
+
#
|
33
|
+
# @return {Void}
|
34
|
+
#
|
35
|
+
def run(commands, silent = true)
|
36
|
+
commands.map! { |cmd| cmd.to_s + " > /dev/null 2>&1" } if silent
|
37
|
+
system commands.join "&&"
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Verify config is properly setup, set global var
|
42
|
+
#
|
43
|
+
# @return {Void}
|
44
|
+
#
|
45
|
+
def use_config
|
46
|
+
|
47
|
+
if config_is_setup?
|
48
|
+
@config = YAML.load_file(Dir["#{@config_path}/*"].select { |f| @config_regex =~ File.basename(f) }.last)
|
49
|
+
else
|
50
|
+
@interaction.notice "Unable to find a 'tj.yml' file in '#{@config_path}'."
|
51
|
+
|
52
|
+
unless @interaction.agree? "Would you like to create one?"
|
53
|
+
@interaction.error "A config file is needed to continue. Aborting mission."
|
54
|
+
end
|
55
|
+
|
56
|
+
setup_config
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# Restart Vagrant
|
62
|
+
#
|
63
|
+
# @note Normally a simple 'vagrant reload' would work, but Landrush requires
|
64
|
+
# a 'vagrant up' to be fired for it to set up the DNS correctly.
|
65
|
+
#
|
66
|
+
# @return {Void}
|
67
|
+
#
|
68
|
+
def restart_vagrant
|
69
|
+
@interaction.log "Restarting VVV"
|
70
|
+
|
71
|
+
run [
|
72
|
+
"cd #{@environment.vvv_path}",
|
73
|
+
"vagrant halt",
|
74
|
+
"vagrant up --provision",
|
75
|
+
], false
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# @return {Bool}
|
80
|
+
#
|
81
|
+
def setup_was_successful?
|
82
|
+
vvv_is_setup? and dev_site_is_setup? and hosts_is_setup? and database_is_setup? and nginx_is_setup?
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# @return {Bool}
|
87
|
+
#
|
88
|
+
def removal_was_successful?
|
89
|
+
!setup_was_successful?
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# @return {Bool}
|
94
|
+
#
|
95
|
+
def project_dir_is_setup?
|
96
|
+
Dir.exist? "#{@opts[:site_location]}"
|
97
|
+
end
|
98
|
+
|
99
|
+
#
|
100
|
+
# @return {Bool}
|
101
|
+
#
|
102
|
+
def config_is_setup?
|
103
|
+
!Dir["#{@config_path}/*"].select { |f| File.basename(f) =~ @config_regex }.empty?
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# @return {Bool}
|
108
|
+
#
|
109
|
+
def vvv_is_setup?
|
110
|
+
File.exist? File.expand_path(@environment.vvv_path)
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# @return {Bool}
|
115
|
+
#
|
116
|
+
def wildcard_subdomains_is_setup?
|
117
|
+
File.readlines(File.expand_path("#{@environment.vvv_path}/Vagrantfile")).grep(/(config.landrush.enabled = true)/m).any?
|
118
|
+
end
|
119
|
+
|
120
|
+
#
|
121
|
+
# @return {Bool}
|
122
|
+
#
|
123
|
+
def dev_site_is_setup?
|
124
|
+
File.exist? "#{@opts[:site_dev_location]}"
|
125
|
+
end
|
126
|
+
|
127
|
+
#
|
128
|
+
# @return {Bool}
|
129
|
+
#
|
130
|
+
def hosts_is_setup?
|
131
|
+
File.exist? "#{@opts[:site_location]}/vvv-hosts"
|
132
|
+
end
|
133
|
+
|
134
|
+
#
|
135
|
+
# @return {Bool}
|
136
|
+
#
|
137
|
+
def database_is_setup?
|
138
|
+
File.readlines(File.expand_path("#{@environment.vvv_path}/database/init-custom.sql")).grep(/(### Begin '#{@opts[:site_name]}')/m).any?
|
139
|
+
end
|
140
|
+
|
141
|
+
#
|
142
|
+
# @return {Bool}
|
143
|
+
#
|
144
|
+
def nginx_is_setup?
|
145
|
+
File.exist? "#{@opts[:site_location]}/vvv-nginx.conf"
|
146
|
+
end
|
147
|
+
|
148
|
+
#
|
149
|
+
# @return {Bool}
|
150
|
+
#
|
151
|
+
def wordpress_is_setup?
|
152
|
+
!Dir["#{@opts[:site_location]}/*"].select { |f| File.basename(f) =~ %r{wp(-content)?|wordpress|app|content} }.empty?
|
153
|
+
end
|
154
|
+
|
155
|
+
#
|
156
|
+
# @return {Bool}
|
157
|
+
#
|
158
|
+
def synced_folder_is_setup?
|
159
|
+
File.readlines(File.expand_path("#{@environment.vvv_path}/Vagrantfile")).grep(/(### Begin '#{@opts[:site_name]}')/m).any?
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
# @return {Bool}
|
164
|
+
#
|
165
|
+
def repo_is_setup?
|
166
|
+
File.exist? File.expand_path("#{@opts[:site_location]}/.git")
|
167
|
+
end
|
168
|
+
|
169
|
+
#
|
170
|
+
# @return {Bool}
|
171
|
+
#
|
172
|
+
def env_is_setup?
|
173
|
+
File.exist? File.expand_path("#{@opts[:site_location]}/.env.development")
|
174
|
+
end
|
175
|
+
|
176
|
+
#
|
177
|
+
# @return {Bool}
|
178
|
+
#
|
179
|
+
def wpcli_is_setup?
|
180
|
+
File.exist? File.expand_path("#{@opts[:site_location]}/wp-cli.local.yml")
|
181
|
+
end
|
182
|
+
|
183
|
+
#
|
184
|
+
# @return {Bool}
|
185
|
+
#
|
186
|
+
def using_repo?
|
187
|
+
!!@opts[:site_repository]
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module ThemeJuice
|
4
|
+
class Service::ConfigFile < ::ThemeJuice::Service
|
5
|
+
|
6
|
+
#
|
7
|
+
# @param {Hash} opts
|
8
|
+
#
|
9
|
+
def initialize(opts = {})
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# Run installation from config
|
15
|
+
#
|
16
|
+
# @return {Void}
|
17
|
+
#
|
18
|
+
def install
|
19
|
+
use_config
|
20
|
+
|
21
|
+
@config["commands"]["install"].each do |command|
|
22
|
+
run ["cd #{@config_path}", command], false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# Run subcommand from config
|
28
|
+
#
|
29
|
+
# @param {String} subcommand
|
30
|
+
# @param {String} command
|
31
|
+
#
|
32
|
+
# @return {Void}
|
33
|
+
#
|
34
|
+
def subcommand(subcommand, command)
|
35
|
+
use_config
|
36
|
+
|
37
|
+
if @config["commands"][subcommand]
|
38
|
+
run ["#{@config["commands"][subcommand]} #{command}"], false
|
39
|
+
else
|
40
|
+
::ThemeJuice::Interaction.error "Unable to find '#{subcommand}' command in '#{@config_path}/tj.yml'. Aborting mission."
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|