toggle 0.0.0.alpha → 1.0.0.rc
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/.gitignore +1 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/CONTRIBUTING.md +14 -0
- data/Gemfile +1 -1
- data/LICENSE +13 -0
- data/README.md +304 -8
- data/Rakefile +27 -0
- data/bin/toggle +200 -0
- data/defaults/config.yml.default +23 -0
- data/defaults/key.yml.default +15 -0
- data/lib/toggle.rb +76 -3
- data/lib/toggle/compiler.rb +31 -0
- data/lib/toggle/parser.rb +17 -0
- data/lib/toggle/parser/yaml.rb +12 -0
- data/lib/toggle/version.rb +2 -2
- data/script/ci +42 -0
- data/spec/cli_spec.rb +427 -0
- data/spec/parser/yaml_spec.rb +16 -0
- data/spec/parser_spec.rb +39 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/test/fixtures/cli/.gitkeep +0 -0
- data/spec/test/fixtures/config.yml +9 -0
- data/spec/test/fixtures/flat-key-local +1 -0
- data/spec/test/fixtures/key-local.yml +2 -0
- data/spec/toggle_spec.rb +94 -0
- data/toggle.gemspec +15 -11
- metadata +104 -11
- data/LICENSE.txt +0 -22
data/.gitignore
CHANGED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Contributing
|
2
|
+
============
|
3
|
+
|
4
|
+
If you would like to contribute code to Toggle you can do so through GitHub by
|
5
|
+
forking the repository and sending a pull request.
|
6
|
+
|
7
|
+
When submitting code, please make every effort to follow existing conventions
|
8
|
+
and style in order to keep the code as readable as possible.
|
9
|
+
|
10
|
+
Before your code can be accepted into the project you must also sign the
|
11
|
+
[Individual Contributor License Agreement (CLA)][1].
|
12
|
+
|
13
|
+
|
14
|
+
[1]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1
|
data/Gemfile
CHANGED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2013 Square Inc.
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
CHANGED
@@ -1,6 +1,37 @@
|
|
1
1
|
# Toggle
|
2
2
|
|
3
|
-
Toggle
|
3
|
+
Toggle provides an organized and flexible framework to set up, manage, and
|
4
|
+
switch between different configuration settings in your Ruby scripts.
|
5
|
+
|
6
|
+
## Why?
|
7
|
+
|
8
|
+
Ensuring that a script has the correct configuration settings can become a real
|
9
|
+
headache. Have you ever had to run a script under different environment
|
10
|
+
specifications or had to share a script that requires different settings based
|
11
|
+
on who is running the code?
|
12
|
+
|
13
|
+
You may have resorted to storing configuration information in a hash to the top
|
14
|
+
of a given script to provide some flexibility. This can work for a script or
|
15
|
+
two and when your on a small team, but as you write more code or increase your
|
16
|
+
team's size the need for organization while still maintaining flexibility
|
17
|
+
quickly arises.
|
18
|
+
|
19
|
+
Having a common pattern around how per-project configurations are handled
|
20
|
+
becomes a big plus. Projects like [rbenv-vars](https://github.com/sstephenson/rbenv-vars)
|
21
|
+
came about to help solve issues like these.
|
22
|
+
|
23
|
+
Toggle provides a project with rbenv-vars-like functionality with two main
|
24
|
+
additions:
|
25
|
+
|
26
|
+
1. rbenv is not required
|
27
|
+
2. you can specify *multiple* environment setups instead of just one on a
|
28
|
+
per-project basis, each of which is easily switchable to either programmatically
|
29
|
+
or at runtime.
|
30
|
+
|
31
|
+
Additionally, Toggle provides a command line interface to facilitate setting up
|
32
|
+
this framework along with a set of options to quickly inspect which variables are
|
33
|
+
available within a project and what each variable is set to for a given environment
|
34
|
+
specification.
|
4
35
|
|
5
36
|
## Installation
|
6
37
|
|
@@ -16,14 +47,279 @@ Or install it yourself as:
|
|
16
47
|
|
17
48
|
$ gem install toggle
|
18
49
|
|
19
|
-
## Usage
|
50
|
+
## Basic Usage
|
51
|
+
|
52
|
+
To start using Toggle you first need a configuration file. This file
|
53
|
+
will typically be in YAML format and can contain inline ERB. The file's content
|
54
|
+
will include all the different configuration sections you want to be able to toggle to.
|
55
|
+
Each section should be namespaced appropriately.
|
56
|
+
|
57
|
+
As an example let's say we have two different script configurations we'd like to
|
58
|
+
have available and we name each `alpha` and `beta` respectively. Then our
|
59
|
+
configuration file might look like:
|
60
|
+
|
61
|
+
```yaml
|
62
|
+
# Sample config.yml demonstrating Toggle usage.
|
63
|
+
# Notice that each section contains the same keys but the values vary.
|
64
|
+
:alpha:
|
65
|
+
:name: mr_alpha
|
66
|
+
:secret: <%= ENV['ALPHA_SECRET'] %> # pretend this is "alpha-secret"
|
67
|
+
|
68
|
+
:beta:
|
69
|
+
:name: mr_beta
|
70
|
+
:secret: <%= ENV['BETA_SECRET'] %> # pretend this is "beta-secret"
|
71
|
+
```
|
72
|
+
|
73
|
+
Now in any script we can leverage Toggle to toggle between each configuration
|
74
|
+
section by setting the `key` attribute, which will load the corresponding
|
75
|
+
configuration section:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
require 'toggle'
|
79
|
+
toggle = Toggle.new config_filepath: './config.yml'
|
80
|
+
|
81
|
+
toggle.key = :alpha
|
82
|
+
puts "#{toggle[:name]} has a secret: #{toggle[:secret]}!"
|
83
|
+
#=> mr_alpha has a secret: alpha-secret
|
84
|
+
|
85
|
+
toggle.key = :beta
|
86
|
+
puts "#{toggle[:name]} has a secret: #{toggle[:secret]}!"
|
87
|
+
#=> mr_beta has a secret: beta-secret
|
88
|
+
```
|
89
|
+
|
90
|
+
Toggle also supports temporary access to a configuration section by passing a
|
91
|
+
block to `#using`:
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
require 'toggle'
|
95
|
+
|
96
|
+
toggle = Toggle.new config_filepath: './config.yml',
|
97
|
+
key: :beta
|
98
|
+
|
99
|
+
toggle.using(:alpha) do |s|
|
100
|
+
puts "#{s[:name]} has a secret: #{s[:secret]}!"
|
101
|
+
#=> mr_alpha has a secret: alpha-secret
|
102
|
+
end
|
103
|
+
|
104
|
+
puts "#{toggle[:name]} has a secret: #{toggle[:secret]}!"
|
105
|
+
#=> mr_beta has a secret: beta-secret
|
106
|
+
```
|
107
|
+
|
108
|
+
As an alternative to specifying the `key` attribute programmatically, you can
|
109
|
+
create a key file:
|
110
|
+
|
111
|
+
```yaml
|
112
|
+
# sample key.yml file
|
113
|
+
alpha
|
114
|
+
```
|
115
|
+
|
116
|
+
and then set Toggle's `key_filepath` attribute to specify where the `key`'s
|
117
|
+
value should be derived from:
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
require 'toggle'
|
121
|
+
|
122
|
+
toggle = Toggle.new config_filepath: './config.yml',
|
123
|
+
key_filepath: './key.yml'
|
124
|
+
|
125
|
+
puts "#{toggle[:name]} has a secret: #{toggle[:secret]}!"
|
126
|
+
#=> mr_alpha has a secret: alpha-secret
|
127
|
+
```
|
128
|
+
|
129
|
+
## Realworld Use Case: Runtime Toggling
|
130
|
+
|
131
|
+
Let's say there is a developer named Jane and she wants to author a script that
|
132
|
+
connects to a database server, pulls in data and does some processing, and then
|
133
|
+
emails the results to her team.
|
134
|
+
|
135
|
+
As she developes the script she wants to pull data from a staging database and
|
136
|
+
just email the results to herself so she can see how the final product would
|
137
|
+
look without bothering the whole team until the finished product is ready.
|
138
|
+
|
139
|
+
Once everything is complete she wants to pull data from a production database
|
140
|
+
and send the email.
|
141
|
+
|
142
|
+
With Toggle, this is easy:
|
143
|
+
|
144
|
+
```yaml
|
145
|
+
# Jane's sample config.yml
|
146
|
+
:development:
|
147
|
+
:who_to_email: 'jane@company.com'
|
148
|
+
|
149
|
+
:database:
|
150
|
+
:host: https://staging.data.company.com
|
151
|
+
:name: some_staging_db
|
152
|
+
:table: some_staging_table
|
153
|
+
:username: jane
|
154
|
+
:password: <%= ENV['DATABASE_PASSWORD'] %>
|
155
|
+
|
156
|
+
:production:
|
157
|
+
:who_to_email: 'team@company.com'
|
158
|
+
|
159
|
+
:database:
|
160
|
+
:host: https://prod.data.company.com
|
161
|
+
:name: some_prod_db
|
162
|
+
:table: some_prod_table
|
163
|
+
:username: jane
|
164
|
+
:password: <%= ENV['DATABASE_PASSWORD'] %>
|
165
|
+
```
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
# Jane's sample email_data.rb script
|
169
|
+
require 'toggle'
|
170
|
+
|
171
|
+
toggle = Toggle.new config_filepath: './config.yml',
|
172
|
+
key: ENV['key']
|
173
|
+
|
174
|
+
connection = SomeDBDriver.connect host: toggle[:database][:host]
|
175
|
+
username: toggle[:database][:username]
|
176
|
+
password: toggle[:database][:password]
|
20
177
|
|
21
|
-
|
178
|
+
data = connection.get_data_from database: toggle[:database][:name],
|
179
|
+
table: toggle[:database][:table]
|
180
|
+
|
181
|
+
SomeEmailer.send to: toggle[:who_to_email],
|
182
|
+
what: data
|
183
|
+
```
|
184
|
+
|
185
|
+
Now running `email_data.rb` under the development configuration settings is a
|
186
|
+
snap:
|
187
|
+
|
188
|
+
$ key=development ruby email_data.rb
|
189
|
+
# => will connect to the staging db + just email jane
|
190
|
+
|
191
|
+
And when it's deemed ready for primetime it can be run with the production
|
192
|
+
configuration settings via:
|
193
|
+
|
194
|
+
$ key=production ruby email_data.rb
|
195
|
+
# => will connect to the prod db + email the team
|
196
|
+
|
197
|
+
## Realworld Use Case: Abstracted Configuration and Sharing
|
198
|
+
|
199
|
+
Continuing with our example from above, let's say that Jane needs to share the
|
200
|
+
script with John who is another developer on her team so he can work on it
|
201
|
+
(perhaps he wants to add in logic that does not send an email if no data is
|
202
|
+
returned so the team doesn't receive an empty email).
|
203
|
+
|
204
|
+
Jane can further abstract her `config.yml` file to faciliate quick sharing
|
205
|
+
between co-workers:
|
206
|
+
|
207
|
+
```yaml
|
208
|
+
# Jane's new sample config.yml
|
209
|
+
#
|
210
|
+
# Notice that we have abstracted out the email address, database username and
|
211
|
+
# password into ENV vars
|
212
|
+
:development:
|
213
|
+
:who_to_email: <%= ENV['USER_EMAIL'] %>
|
214
|
+
|
215
|
+
:database:
|
216
|
+
:host: https://staging.data.company.com
|
217
|
+
:name: some_staging_db
|
218
|
+
:table: some_staging_table
|
219
|
+
:username: <%= ENV['DATABASE_USERNAME'] %>
|
220
|
+
:password: <%= ENV['DATABASE_PASSWORD'] %>
|
221
|
+
|
222
|
+
:production:
|
223
|
+
:who_to_email: 'team@company.com'
|
224
|
+
|
225
|
+
:database:
|
226
|
+
:host: https://prod.data.company.com
|
227
|
+
:name: some_prod_db
|
228
|
+
:table: some_prod_table
|
229
|
+
:username: <%= ENV['DATABASE_USERNAME'] %>
|
230
|
+
:password: <%= ENV['DATABASE_PASSWORD'] %>
|
231
|
+
```
|
232
|
+
|
233
|
+
John is a `git clone` (or whatever vcs he is using) away from having the
|
234
|
+
script downloaded locally and ready to run without requiring any configuration
|
235
|
+
edits.
|
236
|
+
|
237
|
+
In fact, anyone that has `DATABASE_USERNAME`, `DATABASE_PASSWORD`
|
238
|
+
and `USER_EMAIL` set in their environment can run this script without requiring
|
239
|
+
any configuration adjustments.
|
240
|
+
|
241
|
+
In general if your team uses any common variables you should consider
|
242
|
+
abstracting each into environment variables and including them via ERB. Toggle
|
243
|
+
comes with an easy way to set this up on a per-computer basis. First, run:
|
244
|
+
|
245
|
+
$ toggle --init-local
|
246
|
+
|
247
|
+
This will create `~/.toggle.local`, which you can then edit to `export` any
|
248
|
+
variables you want to be available in your environment. Finally, make sure
|
249
|
+
you source this file so your variables are ready to go.
|
250
|
+
|
251
|
+
## Ignoring the Config and Key Files
|
252
|
+
|
253
|
+
If you can effectively abstract out all configuration settings in environment
|
254
|
+
variables, you may be able to just commit your `config.yml` and your `key.yml`
|
255
|
+
files to source control.
|
256
|
+
|
257
|
+
However, consider .gitignore-ing each and providing a `config.yml.default` and
|
258
|
+
key.yml.default` in their place. With these default files in place you provide
|
259
|
+
runtime guidance, but allow each developer to make any local adjustments without
|
260
|
+
running the risk of having these changes committed back to the project's repo
|
261
|
+
and breaking someone else's settings when they pull in the latest changes.
|
262
|
+
|
263
|
+
Again, borrowing from the above example, if Jane were to instead provide
|
264
|
+
`config.yml.default` and `key.yml.default` files in her repo, anyone that
|
265
|
+
downloaded her repo would need to copy each file to their appropriate location
|
266
|
+
(`config.yml` and `key.yml` respectively) so the script could run. This can be
|
267
|
+
easily accomplished via:
|
268
|
+
|
269
|
+
$ toggle --copy-defaults project/path
|
270
|
+
|
271
|
+
or you can do this manually via:
|
272
|
+
|
273
|
+
$ cp project/path/config.yml.default project/project/config.yml
|
274
|
+
$ cp project/path/key.yml.default project/project/key.yml
|
275
|
+
|
276
|
+
## Toggle CLI
|
277
|
+
|
278
|
+
Toggle comes bundled with a commandline interface:
|
279
|
+
|
280
|
+
```
|
281
|
+
$ toggle --help
|
282
|
+
Usage: toggle <args>
|
283
|
+
|
284
|
+
Specific arguments:
|
285
|
+
-g, --init-local [PATH] Adds [PATH]/.toggle.local with var placeholders. Default is $HOME.
|
286
|
+
-k, --keys file Show available keys for the specified config FILE
|
287
|
+
--values FILE,KEY Show values for the KEY in the config FILE
|
288
|
+
--copy-config-defaults [PATH]
|
289
|
+
Copy all toggle config defaults to actuals in PATH. Default is pwd.
|
290
|
+
-c, --copy-defaults [PATH] Copy all .toggle.default to .toggle for PATH. Default is pwd.
|
291
|
+
--ensure-key [PATH] Copies the default key in [PATH] if actual key is not present, does nothing otherwise. Default [PATH] is pwd.
|
292
|
+
-m, --make-defaults [PATH] Create [PATH]/{config|key}{,.*}.default. Default is pwd.
|
293
|
+
-v, --version Show version
|
294
|
+
-h, --help Show this message
|
295
|
+
```
|
22
296
|
|
23
297
|
## Contributing
|
24
298
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
299
|
+
If you would like to contribute code to Toggle you can do so through GitHub by
|
300
|
+
forking the repository and sending a pull request.
|
301
|
+
|
302
|
+
When submitting code, please make every effort to follow existing conventions
|
303
|
+
and style in order to keep the code as readable as possible.
|
304
|
+
|
305
|
+
Before your code can be accepted into the project you must also sign the
|
306
|
+
[Individual Contributor License Agreement (CLA)][1].
|
307
|
+
|
308
|
+
|
309
|
+
[1]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1
|
310
|
+
|
311
|
+
## License
|
312
|
+
|
313
|
+
Copyright 2013 Square Inc.
|
314
|
+
|
315
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
316
|
+
you may not use this file except in compliance with the License.
|
317
|
+
You may obtain a copy of the License at
|
318
|
+
|
319
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
320
|
+
|
321
|
+
Unless required by applicable law or agreed to in writing, software
|
322
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
323
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
324
|
+
See the License for the specific language governing permissions and
|
325
|
+
limitations under the License.
|
data/Rakefile
CHANGED
@@ -1 +1,28 @@
|
|
1
|
+
#!/usr/bin/env rake
|
1
2
|
require "bundler/gem_tasks"
|
3
|
+
begin
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
7
|
+
t.rspec_opts = '-b'
|
8
|
+
end
|
9
|
+
|
10
|
+
task default: :spec
|
11
|
+
rescue LoadError
|
12
|
+
$stderr.puts "rspec not available, spec task not provided"
|
13
|
+
end
|
14
|
+
|
15
|
+
begin
|
16
|
+
require 'cane/rake_task'
|
17
|
+
|
18
|
+
desc "Run cane to check quality metrics"
|
19
|
+
Cane::RakeTask.new(:quality) do |cane|
|
20
|
+
cane.abc_max = 10
|
21
|
+
cane.style_glob = "lib/**/*.rb"
|
22
|
+
cane.no_doc = true
|
23
|
+
end
|
24
|
+
|
25
|
+
task :default => :quality
|
26
|
+
rescue LoadError
|
27
|
+
warn "cane not available, quality task not provided."
|
28
|
+
end
|
data/bin/toggle
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
4
|
+
|
5
|
+
require 'toggle'
|
6
|
+
require 'optparse'
|
7
|
+
require 'fileutils'
|
8
|
+
|
9
|
+
def default_key_filepath
|
10
|
+
File.expand_path('../../defaults/key.yml.default', __FILE__)
|
11
|
+
end
|
12
|
+
|
13
|
+
def default_config_filepath
|
14
|
+
File.expand_path('../../defaults/config.yml.default', __FILE__)
|
15
|
+
end
|
16
|
+
|
17
|
+
def wants_to_force_copy? current_file
|
18
|
+
respond_yes_to? "File #{current_file} exists. Replace?"
|
19
|
+
end
|
20
|
+
|
21
|
+
def actual_key_in path
|
22
|
+
find_file_in path, /^(key(\.yml))?$/
|
23
|
+
end
|
24
|
+
|
25
|
+
def actual_config_in path
|
26
|
+
find_file_in path, /^config\.yml$/
|
27
|
+
end
|
28
|
+
|
29
|
+
# finds the first file in "path" arg that matches "regex" pattern
|
30
|
+
# returns path + filename
|
31
|
+
def find_file_in path, regex
|
32
|
+
file = Dir[File.join(path, '*')].map { |filepath|
|
33
|
+
File.basename filepath
|
34
|
+
}.find { |filename|
|
35
|
+
filename =~ regex
|
36
|
+
}
|
37
|
+
|
38
|
+
file ? File.join(path, file) : nil
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns true if response starts with a 'y' or 'Y' (as in 'yes')
|
42
|
+
# Returns false if response starts with a 'n' or 'N' (as in 'no')
|
43
|
+
# Aborts if response starts with a 'q' or 'Q' (as in 'quit')
|
44
|
+
def respond_yes_to? prompt
|
45
|
+
print "#{prompt} (y/n/q) "
|
46
|
+
normalized_response = gets[0].chomp.downcase
|
47
|
+
normalized_response.eql?('q') ? abort('... quitting') : normalized_response.eql?('y')
|
48
|
+
end
|
49
|
+
|
50
|
+
# The reference file is guaranteed to exist
|
51
|
+
def identical_files? reference_file, other_file
|
52
|
+
File.exists?(other_file) && FileUtils.identical?(reference_file, other_file)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Method requires a path and file_pattern and recursively searchs for matching
|
56
|
+
# files.
|
57
|
+
#
|
58
|
+
# When a match is found, method detects if the default is the same as the
|
59
|
+
# "actual" (the same filename just without the .default).
|
60
|
+
#
|
61
|
+
# If the files are identical, the method does nothing. If the actual file does
|
62
|
+
# not exist OR the user opts to clobber the existing, the default will replace
|
63
|
+
# the actual. Otherwise, the actual is left as is.
|
64
|
+
def recursively_copy_defaults path, file_pattern, options = {}
|
65
|
+
defaults = {attempt_force_copy: true}
|
66
|
+
options = defaults.merge(options)
|
67
|
+
|
68
|
+
attempt_force_copy = options[:attempt_force_copy]
|
69
|
+
|
70
|
+
Dir[File.join(path, '/**/', file_pattern)].each do |default_file|
|
71
|
+
file = default_file.slice(/(.*)\.default$/, 1)
|
72
|
+
|
73
|
+
if identical_files? default_file, file
|
74
|
+
puts "Default is identical to #{file}, skipping!"
|
75
|
+
elsif !File.exists?(file) || (attempt_force_copy && wants_to_force_copy?(file))
|
76
|
+
puts "Copying #{file} from default"
|
77
|
+
FileUtils.cp default_file, file
|
78
|
+
else
|
79
|
+
puts "Not changing #{file}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
opt_parser = OptionParser.new do |opts|
|
85
|
+
opts.banner = "Usage: toggle <args>"
|
86
|
+
opts.separator ""
|
87
|
+
opts.separator "Specific arguments:"
|
88
|
+
|
89
|
+
opts.on('-g', '--init-local [PATH]', String, 'Adds [PATH]/.toggle.local with var placeholders. Default is $HOME.') do |path|
|
90
|
+
path ||= ENV['HOME']
|
91
|
+
|
92
|
+
if path && path.empty?
|
93
|
+
raise RuntimeError, 'You must specify a PATH or have HOME env set!'
|
94
|
+
end
|
95
|
+
|
96
|
+
local_config = File.join(path, '.toggle.local')
|
97
|
+
sourcing_bash_instructions = "if [ -s ~/.toggle.local ] ; then source ~/.toggle.local ; fi"
|
98
|
+
|
99
|
+
if !File.exists?(local_config) || wants_to_force_copy?(local_config)
|
100
|
+
content = <<-EOS.strip_heredoc
|
101
|
+
# Add any variables that you'd like below.
|
102
|
+
#
|
103
|
+
# We've included a few suggestions, but please feel free
|
104
|
+
# to modify as needed.
|
105
|
+
#
|
106
|
+
# Make sure that you source this file in your ~/.bash_profile
|
107
|
+
# or ~/.bashrc (or whereever you'd like) via:
|
108
|
+
#
|
109
|
+
# #{sourcing_bash_instructions}
|
110
|
+
export DATABASE_HOST=''
|
111
|
+
export DATABASE_NAME=''
|
112
|
+
export DATABASE_USERNAME=''
|
113
|
+
export DATABASE_PASSWORD=''
|
114
|
+
export USER_EMAIL=''
|
115
|
+
EOS
|
116
|
+
|
117
|
+
%x(echo "#{content}" > #{local_config})
|
118
|
+
puts "Local toggle config added at #{local_config}"
|
119
|
+
puts "Now edit the file and source it from ~/.bash_profile or ~/.bashrc via: #{sourcing_bash_instructions}"
|
120
|
+
else
|
121
|
+
puts "Not changing #{local_config}"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
opts.on("-k", "--keys file", String, "Show available keys for the specified config FILE") do |file|
|
126
|
+
opts.banner = "Usage: toggle --keys FILE"
|
127
|
+
|
128
|
+
if File.exists? file
|
129
|
+
toggle = Toggle::Compiler.new(file).parsed_content
|
130
|
+
puts toggle.keys.map{|k| "- #{k}"}.join("\n")
|
131
|
+
else
|
132
|
+
puts "toggle config file not found, please check specified path"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# TODO: remove yaml preamble
|
137
|
+
opts.on("--values FILE,KEY", Array, "Show values for the KEY in the config FILE") do |params|
|
138
|
+
opts.banner = "Usage: toggle --values FILE,KEY"
|
139
|
+
|
140
|
+
if File.exists?(file = params[0])
|
141
|
+
toggle = Toggle::Compiler.new(file).parsed_content
|
142
|
+
if toggle.keys.include?(key = params[1].to_sym)
|
143
|
+
puts toggle[key].to_yaml.gsub(/(:password:).+/, "\\1 [redacted]")
|
144
|
+
else
|
145
|
+
puts "#{key} not found in #{file}"
|
146
|
+
end
|
147
|
+
else
|
148
|
+
puts "toggle config file not found, please check specified path"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
opts.on('--copy-config-defaults [PATH]', String, 'Copy all toggle config defaults to actuals in PATH. Default is pwd.') do |path|
|
153
|
+
path ||= Dir.pwd
|
154
|
+
recursively_copy_defaults(path, 'config{,.*}.default')
|
155
|
+
end
|
156
|
+
|
157
|
+
opts.on('-c', '--copy-defaults [PATH]', String, 'Copy all .toggle.default to .toggle for PATH. Default is pwd.') do |path|
|
158
|
+
path ||= Dir.pwd
|
159
|
+
recursively_copy_defaults(path, '{key,config}{,.*}.default')
|
160
|
+
end
|
161
|
+
|
162
|
+
opts.on('--ensure-key [PATH]', String, 'Copies the default key in [PATH] if actual key is not present, does nothing otherwise. Default [PATH] is pwd.') do |path|
|
163
|
+
path ||= Dir.pwd
|
164
|
+
recursively_copy_defaults(path, 'key{,.*}.default', attempt_force_copy: false)
|
165
|
+
end
|
166
|
+
|
167
|
+
opts.on('-m', '--make-defaults [PATH]', String, 'Create [PATH]/{config|key}{,.*}.default. Default is pwd.') do |path|
|
168
|
+
path ||= Dir.pwd
|
169
|
+
|
170
|
+
default_key = actual_key_in(path) || default_key_filepath
|
171
|
+
default_config = actual_config_in(path) || default_config_filepath
|
172
|
+
|
173
|
+
key_destination = File.join(path, 'key.yml.default')
|
174
|
+
config_destination = File.join(path, 'config.yml.default')
|
175
|
+
|
176
|
+
if !File.exists?(key_destination) || wants_to_force_copy?(key_destination)
|
177
|
+
FileUtils.cp(default_key, key_destination) unless identical_files?(default_key, key_destination)
|
178
|
+
puts "Default key written to #{key_destination}"
|
179
|
+
puts "Now go edit it!"
|
180
|
+
end
|
181
|
+
|
182
|
+
if !File.exists?(config_destination) || wants_to_force_copy?(config_destination)
|
183
|
+
FileUtils.cp(default_config, config_destination) unless identical_files?(default_config, key_destination)
|
184
|
+
puts "Default config written to #{config_destination}"
|
185
|
+
puts "Now go edit it!"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
opts.on_tail("-v", "--version", "Show version") do
|
190
|
+
puts "Toggle version #{Toggle::VERSION}"
|
191
|
+
exit
|
192
|
+
end
|
193
|
+
|
194
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
195
|
+
puts opts
|
196
|
+
exit
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
opt_parser.parse!
|