methadone-rehab 1.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +11 -0
- data/CHANGES.md +66 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +201 -0
- data/README.rdoc +179 -0
- data/Rakefile +98 -0
- data/TODO.md +3 -0
- data/bin/methadone +157 -0
- data/features/bootstrap.feature +169 -0
- data/features/license.feature +43 -0
- data/features/multilevel_commands.feature +125 -0
- data/features/readme.feature +26 -0
- data/features/rspec_support.feature +27 -0
- data/features/step_definitions/bootstrap_steps.rb +47 -0
- data/features/step_definitions/license_steps.rb +30 -0
- data/features/step_definitions/readme_steps.rb +26 -0
- data/features/step_definitions/version_steps.rb +4 -0
- data/features/support/env.rb +26 -0
- data/features/version.feature +17 -0
- data/lib/methadone.rb +15 -0
- data/lib/methadone/argv_parser.rb +50 -0
- data/lib/methadone/cli.rb +124 -0
- data/lib/methadone/cli_logger.rb +133 -0
- data/lib/methadone/cli_logging.rb +138 -0
- data/lib/methadone/cucumber.rb +174 -0
- data/lib/methadone/error.rb +32 -0
- data/lib/methadone/execution_strategy/base.rb +34 -0
- data/lib/methadone/execution_strategy/jvm.rb +37 -0
- data/lib/methadone/execution_strategy/mri.rb +16 -0
- data/lib/methadone/execution_strategy/open_3.rb +16 -0
- data/lib/methadone/execution_strategy/open_4.rb +22 -0
- data/lib/methadone/execution_strategy/rbx_open_4.rb +12 -0
- data/lib/methadone/exit_now.rb +40 -0
- data/lib/methadone/main.rb +1039 -0
- data/lib/methadone/process_status.rb +45 -0
- data/lib/methadone/sh.rb +223 -0
- data/lib/methadone/version.rb +3 -0
- data/methadone-rehab.gemspec +32 -0
- data/templates/full/.gitignore.erb +4 -0
- data/templates/full/README.rdoc.erb +25 -0
- data/templates/full/Rakefile.erb +74 -0
- data/templates/full/_license_head.txt.erb +2 -0
- data/templates/full/apache_LICENSE.txt.erb +203 -0
- data/templates/full/bin/executable.erb +47 -0
- data/templates/full/custom_LICENSE.txt.erb +0 -0
- data/templates/full/features/executable.feature.erb +13 -0
- data/templates/full/features/step_definitions/executable_steps.rb.erb +1 -0
- data/templates/full/features/support/env.rb.erb +16 -0
- data/templates/full/gplv2_LICENSE.txt.erb +14 -0
- data/templates/full/gplv3_LICENSE.txt.erb +15 -0
- data/templates/full/mit_LICENSE.txt.erb +7 -0
- data/templates/multicommand/bin/executable.erb +52 -0
- data/templates/multicommand/lib/command.rb.erb +40 -0
- data/templates/multicommand/lib/commands.rb.erb +7 -0
- data/templates/rspec/spec/something_spec.rb.erb +5 -0
- data/templates/test_unit/test/tc_something.rb.erb +7 -0
- data/test/base_test.rb +20 -0
- data/test/command_for_tests.sh +7 -0
- data/test/execution_strategy/test_base.rb +24 -0
- data/test/execution_strategy/test_jvm.rb +77 -0
- data/test/execution_strategy/test_mri.rb +32 -0
- data/test/execution_strategy/test_open_3.rb +70 -0
- data/test/execution_strategy/test_open_4.rb +86 -0
- data/test/execution_strategy/test_rbx_open_4.rb +25 -0
- data/test/test_cli_logger.rb +219 -0
- data/test/test_cli_logging.rb +243 -0
- data/test/test_exit_now.rb +37 -0
- data/test/test_main.rb +1213 -0
- data/test/test_multi.rb +405 -0
- data/test/test_sh.rb +404 -0
- metadata +321 -0
@@ -0,0 +1,125 @@
|
|
1
|
+
Feature: Support multi-level commands
|
2
|
+
As a developer who wants to make a multi-level command line app
|
3
|
+
I should be able to create a Methadone class that delegates subcommands to other Methadone classes
|
4
|
+
and each should support their own options, args and potentially other subcommands.
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given the directory "tmp/multigem" does not exist
|
8
|
+
|
9
|
+
Scenario: Bootstrap a multi-level app from scratch
|
10
|
+
When I successfully run `methadone --commands walk,run,crawl,dance tmp/multigem`
|
11
|
+
Then the following directories should exist:
|
12
|
+
|tmp/multigem |
|
13
|
+
|tmp/multigem/bin |
|
14
|
+
|tmp/multigem/lib |
|
15
|
+
|tmp/multigem/lib/multigem |
|
16
|
+
|tmp/multigem/lib/multigem/commands |
|
17
|
+
|tmp/multigem/test |
|
18
|
+
|tmp/multigem/features |
|
19
|
+
|tmp/multigem/features/support |
|
20
|
+
|tmp/multigem/features/step_definitions |
|
21
|
+
Then the following directories should not exist:
|
22
|
+
|tmp/multigem/spec |
|
23
|
+
And the following files should exist:
|
24
|
+
|tmp/multigem/multigem.gemspec |
|
25
|
+
|tmp/multigem/Rakefile |
|
26
|
+
|tmp/multigem/.gitignore |
|
27
|
+
|tmp/multigem/Gemfile |
|
28
|
+
|tmp/multigem/bin/multigem |
|
29
|
+
|tmp/multigem/lib/multigem/version.rb |
|
30
|
+
|tmp/multigem/lib/multigem/commands/walk.rb |
|
31
|
+
|tmp/multigem/lib/multigem/commands/run.rb |
|
32
|
+
|tmp/multigem/lib/multigem/commands/crawl.rb |
|
33
|
+
|tmp/multigem/lib/multigem/commands/dance.rb |
|
34
|
+
|tmp/multigem/features/multigem.feature |
|
35
|
+
|tmp/multigem/features/support/env.rb |
|
36
|
+
|tmp/multigem/features/step_definitions/multigem_steps.rb |
|
37
|
+
|tmp/multigem/test/tc_something.rb |
|
38
|
+
And the file "tmp/multigem/.gitignore" should match /results.html/
|
39
|
+
And the file "tmp/multigem/.gitignore" should match /html/
|
40
|
+
And the file "tmp/multigem/.gitignore" should match /pkg/
|
41
|
+
And the file "tmp/multigem/.gitignore" should match /.DS_Store/
|
42
|
+
And the file "tmp/multigem/multigem.gemspec" should match /add_development_dependency\('aruba'/
|
43
|
+
And the file "tmp/multigem/multigem.gemspec" should match /add_development_dependency\('rdoc'/
|
44
|
+
And the file "tmp/multigem/multigem.gemspec" should match /add_development_dependency "rake", "~> 10.0"/
|
45
|
+
And the file "tmp/multigem/multigem.gemspec" should match /add_dependency\('methadone-rehab'/
|
46
|
+
And the file "tmp/multigem/multigem.gemspec" should use the same block variable throughout
|
47
|
+
And the file "tmp/multigem/bin/multigem" should match /command "walk" => Multigem::Commands::Walk/
|
48
|
+
And the file "tmp/multigem/bin/multigem" should match /command "run" => Multigem::Commands::Run/
|
49
|
+
And the file "tmp/multigem/bin/multigem" should match /command "crawl" => Multigem::Commands::Crawl/
|
50
|
+
And the file "tmp/multigem/bin/multigem" should match /command "dance" => Multigem::Commands::Dance/
|
51
|
+
Given I cd to "tmp/multigem"
|
52
|
+
And my app's name is "multigem"
|
53
|
+
When I successfully run `bin/multigem --help` with "lib" in the library path
|
54
|
+
Then the banner should be present
|
55
|
+
And the banner should document that this app takes options
|
56
|
+
And the banner should document that this app takes commands
|
57
|
+
And the following commands should be documented:
|
58
|
+
|walk |
|
59
|
+
|run |
|
60
|
+
|crawl |
|
61
|
+
|dance |
|
62
|
+
And the following options should be documented:
|
63
|
+
|--version|
|
64
|
+
|--help|
|
65
|
+
|--log-level|
|
66
|
+
|
67
|
+
Scenario: Special characters in subcommands and gem name
|
68
|
+
Given a directory named "tmp"
|
69
|
+
And the directory "tmp/multigem2" does not exist
|
70
|
+
When I run `methadone --add-lib --commands walk,run,crawl_to_bed,tap-dance,@go-crazy tmp/multigem2`
|
71
|
+
Then the exit status should be 0
|
72
|
+
And the following directories should exist:
|
73
|
+
|tmp/multigem2 |
|
74
|
+
|tmp/multigem2/bin |
|
75
|
+
|tmp/multigem2/lib |
|
76
|
+
|tmp/multigem2/lib/multigem2 |
|
77
|
+
|tmp/multigem2/lib/multigem2/commands |
|
78
|
+
|tmp/multigem2/test |
|
79
|
+
|tmp/multigem2/features |
|
80
|
+
|tmp/multigem2/features/support |
|
81
|
+
|tmp/multigem2/features/step_definitions |
|
82
|
+
And the following directories should not exist:
|
83
|
+
|tmp/multigem2/spec |
|
84
|
+
And the following files should exist:
|
85
|
+
|tmp/multigem2/multigem2.gemspec |
|
86
|
+
|tmp/multigem2/Rakefile |
|
87
|
+
|tmp/multigem2/.gitignore |
|
88
|
+
|tmp/multigem2/Gemfile |
|
89
|
+
|tmp/multigem2/bin/multigem2 |
|
90
|
+
|tmp/multigem2/lib/multigem2/version.rb |
|
91
|
+
|tmp/multigem2/lib/multigem2/commands/walk.rb |
|
92
|
+
|tmp/multigem2/lib/multigem2/commands/run.rb |
|
93
|
+
|tmp/multigem2/lib/multigem2/commands/crawl_to_bed.rb |
|
94
|
+
|tmp/multigem2/lib/multigem2/commands/tap_dance.rb |
|
95
|
+
|tmp/multigem2/lib/multigem2/commands/go_crazy.rb |
|
96
|
+
|tmp/multigem2/features/multigem2.feature |
|
97
|
+
|tmp/multigem2/features/support/env.rb |
|
98
|
+
|tmp/multigem2/features/step_definitions/multigem2_steps.rb |
|
99
|
+
|tmp/multigem2/test/tc_something.rb |
|
100
|
+
And the file "tmp/multigem2/bin/multigem2" should match /command "walk" => Multigem2::Commands::Walk/
|
101
|
+
And the file "tmp/multigem2/bin/multigem2" should match /command "run" => Multigem2::Commands::Run/
|
102
|
+
And the file "tmp/multigem2/bin/multigem2" should match /command "crawl_to_bed" => Multigem2::Commands::CrawlToBed/
|
103
|
+
And the file "tmp/multigem2/bin/multigem2" should match /command "tap-dance" => Multigem2::Commands::TapDance/
|
104
|
+
And the file "tmp/multigem2/bin/multigem2" should match /command "@go-crazy" => Multigem2::Commands::GoCrazy/
|
105
|
+
Given I cd to "tmp/multigem2"
|
106
|
+
And my app's name is "multigem2"
|
107
|
+
When I successfully run `bin/multigem2 --help`
|
108
|
+
Then the banner should be present
|
109
|
+
And the banner should document that this app takes options
|
110
|
+
And the banner should document that this app takes commands
|
111
|
+
And the following commands should be documented:
|
112
|
+
|walk |
|
113
|
+
|run |
|
114
|
+
|crawl_to_bed |
|
115
|
+
|tap-dance |
|
116
|
+
|@go-crazy |
|
117
|
+
And the following options should be documented:
|
118
|
+
|--version|
|
119
|
+
|--help|
|
120
|
+
|--log-level|
|
121
|
+
When I successfully run `bin/multigem2 tap-dance -h`
|
122
|
+
Then the banner should be present
|
123
|
+
And the banner should document that this app takes global options
|
124
|
+
And the banner should document that this app takes options
|
125
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
Feature: a README should be generated
|
2
|
+
As a user
|
3
|
+
I want a template README
|
4
|
+
So I don't need to recall the formatting or other info to get started
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given the directory "tmp/newgem" does not exist
|
8
|
+
|
9
|
+
Scenario: I don't want a README
|
10
|
+
When I successfully run `methadone --no-readme tmp/newgem`
|
11
|
+
Then a README should not be generated
|
12
|
+
And the file "tmp/newgem/Rakefile" should not match /rd.main = "README.rdoc"/
|
13
|
+
|
14
|
+
Scenario Outline: Generate README
|
15
|
+
When I successfully run `methadone <flag> tmp/newgem`
|
16
|
+
Then a README should be generated in RDoc
|
17
|
+
And the README should contain the project name
|
18
|
+
And the README should contain my name
|
19
|
+
And the README should contain links to Github and RDoc.info
|
20
|
+
And the README should contain empty sections for common elements of a README
|
21
|
+
And the file "tmp/newgem/Rakefile" should match /rd.main = "README.rdoc"/
|
22
|
+
|
23
|
+
Examples:
|
24
|
+
|flag|
|
25
|
+
| |
|
26
|
+
|--readme|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Feature: Bootstrap a new command-line app using RSpec instead of Test::Unit
|
2
|
+
As an awesome developer who wants to make a command-line app
|
3
|
+
I should be able to use methadone to bootstrap it
|
4
|
+
And get support for RSpec instead of Test::Unit
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given the directory "tmp/newgem" does not exist
|
8
|
+
|
9
|
+
Scenario: Bootstrap a new app from scratch
|
10
|
+
When I successfully run `methadone --rspec tmp/newgem`
|
11
|
+
Then the following directories should exist:
|
12
|
+
|tmp/newgem/spec |
|
13
|
+
And the following directories should not exist:
|
14
|
+
|tmp/newgem/test |
|
15
|
+
And the following files should exist:
|
16
|
+
|tmp/newgem/spec/something_spec.rb |
|
17
|
+
And the file "tmp/newgem/newgem.gemspec" should match /add_development_dependency\('rspec'/
|
18
|
+
When I cd to "tmp/newgem"
|
19
|
+
And I successfully run `rake -T -I../../lib`
|
20
|
+
Then the output should match /rake spec/
|
21
|
+
And the output should not match /rake test/
|
22
|
+
When I run `rake spec -I../../lib`
|
23
|
+
Then the exit status should be 0
|
24
|
+
And the output should contain:
|
25
|
+
"""
|
26
|
+
1 example, 0 failures
|
27
|
+
"""
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
include FileUtils
|
3
|
+
|
4
|
+
Given /^the directory "([^"]*)" does not exist$/ do |dir|
|
5
|
+
dir = File.join(ARUBA_DIR,dir)
|
6
|
+
rm_rf dir,:verbose => false, :secure => true
|
7
|
+
end
|
8
|
+
|
9
|
+
Given /^my app's name is "([^"]*)"$/ do |app_name|
|
10
|
+
@app_name = app_name
|
11
|
+
end
|
12
|
+
|
13
|
+
Then /^the file "([^"]*)" should use the same block variable throughout$/ do |file|
|
14
|
+
prep_for_fs_check do
|
15
|
+
content = IO.read(file)
|
16
|
+
from_bundler = content.match(/(\w+)\.authors/)[1]
|
17
|
+
added_by_methadone = content.match(/(\w+).add_development_dependency\('rdoc'/)[1]
|
18
|
+
from_bundler.should == added_by_methadone
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Then /^the stderr should match \/([^\/]*)\/$/ do |expected|
|
23
|
+
assert_matching_output(expected, all_stderr)
|
24
|
+
end
|
25
|
+
|
26
|
+
Given /^"(.*?)" has configured version to show only the version (.*)and not help$/ do |gemname,extras|
|
27
|
+
lines = File.read("tmp/aruba/tmp/new-gem/#{gemname}").split(/\n/)
|
28
|
+
File.open("tmp/aruba/tmp/new-gem/#{gemname}","w") do |file|
|
29
|
+
lines.each do |line|
|
30
|
+
if line =~ /^\s*version New::Gem::VERSION/
|
31
|
+
if extras =~ /with a custom format/
|
32
|
+
file.puts line + ", :compact => true, :format => '%s V%s'"
|
33
|
+
else
|
34
|
+
file.puts line + ", :compact => true"
|
35
|
+
end
|
36
|
+
else
|
37
|
+
file.puts line
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Then /^the file "(.*?)" should include "(.*?)" if needed$/ do |file, gemname|
|
44
|
+
if RUBY_VERSION =~ /^2\./ && RUBY_VERSION !~ /^2.0/ && RUBY_VERSION !~ /^2.1/
|
45
|
+
step %{the file "#{file}" should match /add_development_dependency\\('#{gemname}/}
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
Then /^the README should not reference a license$/ do
|
2
|
+
step %(the file "tmp/newgem/README.rdoc" should not match /[Ll]icense/)
|
3
|
+
end
|
4
|
+
|
5
|
+
Then /^newgem's license should be the (\w+) license/ do |license|
|
6
|
+
@license = license
|
7
|
+
step %(a file named "tmp/newgem/LICENSE.txt" should exist)
|
8
|
+
step %(the file "tmp/newgem/newgem.gemspec" should match /#{@license}/)
|
9
|
+
end
|
10
|
+
|
11
|
+
Then /^the README should reference this license$/ do
|
12
|
+
step %(the file "tmp/newgem/README.rdoc" should match /License::/)
|
13
|
+
step %(the file "tmp/newgem/README.rdoc" should match /#{@license}/)
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
Then /^newgem's license should be an empty file$/ do
|
18
|
+
step %(a file named "tmp/newgem/LICENSE.txt" should exist)
|
19
|
+
File.read("tmp/aruba/tmp/newgem/LICENSE.txt").should == "\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
Then /^the README should reference the need for a license$/ do
|
23
|
+
step %(the file "tmp/newgem/README.rdoc" should match /License:: INSERT LICENSE HERE/)
|
24
|
+
end
|
25
|
+
|
26
|
+
Then(/^LICENSE\.txt should contain user information and program name$/) do
|
27
|
+
step %(the file "tmp/newgem/LICENSE.txt" should match /#{`git config user.name`}/)
|
28
|
+
step %(the file "tmp/newgem/LICENSE.txt" should match /newgem/)
|
29
|
+
step %(the file "tmp/newgem/LICENSE.txt" should match /#{Time.now.year}/)
|
30
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
Then /^a README should not be generated$/ do
|
2
|
+
step %(the file "tmp/newgem/README.rdoc" should not exist)
|
3
|
+
end
|
4
|
+
|
5
|
+
Then /^a README should be generated in RDoc$/ do
|
6
|
+
step %(a file named "tmp/newgem/README.rdoc" should exist)
|
7
|
+
end
|
8
|
+
|
9
|
+
Then /^the README should contain the project name$/ do
|
10
|
+
step %(the file "tmp/newgem/README.rdoc" should match /newgem/)
|
11
|
+
end
|
12
|
+
|
13
|
+
Then /^the README should contain my name$/ do
|
14
|
+
step %(the file "tmp/newgem/README.rdoc" should match /Author:: YOUR NAME \\\(YOUR EMAIL\\\)/)
|
15
|
+
end
|
16
|
+
|
17
|
+
Then /^the README should contain links to Github and RDoc.info$/ do
|
18
|
+
step %(the file "tmp/newgem/README.rdoc" should match /\\\* \\\{Source on Github\\\}\\\[LINK TO GITHUB\\\]/)
|
19
|
+
step %(the file "tmp/newgem/README.rdoc" should match /RDoc\\\[LINK TO RDOC.INFO\\\]/)
|
20
|
+
end
|
21
|
+
|
22
|
+
Then /^the README should contain empty sections for common elements of a README$/ do
|
23
|
+
step %(the file "tmp/newgem/README.rdoc" should match /^== Install/)
|
24
|
+
step %(the file "tmp/newgem/README.rdoc" should match /^== Examples/)
|
25
|
+
step %(the file "tmp/newgem/README.rdoc" should match /^== Contributing/)
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'aruba/cucumber'
|
2
|
+
require 'methadone/cucumber'
|
3
|
+
|
4
|
+
PROJECT_ROOT = File.join(File.dirname(__FILE__),'..','..')
|
5
|
+
ENV['PATH'] = "#{File.join(PROJECT_ROOT,'bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
|
6
|
+
ARUBA_DIR = File.join(%w(tmp aruba))
|
7
|
+
Before do
|
8
|
+
@dirs = [ARUBA_DIR]
|
9
|
+
@puts = true
|
10
|
+
@aruba_timeout_seconds = 60
|
11
|
+
@original_rubylib = ENV['RUBYLIB']
|
12
|
+
@original_rubyopt = ENV['RUBYOPT']
|
13
|
+
|
14
|
+
# We want to use, hopefully, the methadone from this codebase and not
|
15
|
+
# the gem, so we put it in the RUBYLIB
|
16
|
+
ENV['RUBYLIB'] = File.join(PROJECT_ROOT,'lib') + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
|
17
|
+
|
18
|
+
# We need -rubygems here so that 1.8-style rubies work AND travis-ci doesn't barf with it in the shebang line
|
19
|
+
ENV['RUBYOPT'] = (ENV['RUBYOPT'] || '') + ' -rubygems'
|
20
|
+
end
|
21
|
+
|
22
|
+
After do
|
23
|
+
# Put back how it was
|
24
|
+
ENV['RUBYLIB'] = @original_rubylib
|
25
|
+
ENV['RUBYOPT'] = @original_rubyopt
|
26
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Feature: The version should show up in the banner by default
|
2
|
+
As a developer
|
3
|
+
I should be able to have the current gem version in the banner
|
4
|
+
So I don't have to maintain it in two places
|
5
|
+
And so users can easily see the version from the app itself
|
6
|
+
|
7
|
+
Scenario Outline: Show the gem version
|
8
|
+
Given my app's name is "newgem"
|
9
|
+
And I successfully run `methadone tmp/newgem`
|
10
|
+
When I cd to "tmp/newgem"
|
11
|
+
And I successfully run `bin/newgem <flag>` with "lib" in the library path
|
12
|
+
Then the banner should include the version
|
13
|
+
|
14
|
+
Examples:
|
15
|
+
|flag |
|
16
|
+
|--help |
|
17
|
+
|--version |
|
data/lib/methadone.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'methadone/version'
|
2
|
+
require 'methadone/cli_logger'
|
3
|
+
require 'methadone/cli_logging'
|
4
|
+
require 'methadone/exit_now'
|
5
|
+
require 'methadone/argv_parser'
|
6
|
+
require 'methadone/main'
|
7
|
+
require 'methadone/error'
|
8
|
+
require 'methadone/execution_strategy/base'
|
9
|
+
require 'methadone/execution_strategy/mri'
|
10
|
+
require 'methadone/execution_strategy/open_3'
|
11
|
+
require 'methadone/execution_strategy/open_4'
|
12
|
+
require 'methadone/execution_strategy/rbx_open_4'
|
13
|
+
require 'methadone/execution_strategy/jvm'
|
14
|
+
require 'methadone/sh'
|
15
|
+
# Note: DO NOT require cli.rb OR cucumber.rb here
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Methadone #:nodoc:
|
2
|
+
# Assists with parsing strings in the same way that ARGV might.
|
3
|
+
# This is *not* used to parse the command-line, but used to
|
4
|
+
# parse config files/environment variables so they can be placed into ARGV and properly interpretted by
|
5
|
+
# OptionParser
|
6
|
+
module ARGVParser #:nodoc:
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
# Parses +string+, returning an array that can be placed into ARGV or given to OptionParser
|
11
|
+
def parse_string_for_argv(string) #:nodoc:
|
12
|
+
return [] if string.nil?
|
13
|
+
|
14
|
+
args = [] # return value we are building up
|
15
|
+
current = 0 # pointer to where we are in +string+
|
16
|
+
next_arg = '' # the next arg we are building up to ultimatley put into args
|
17
|
+
inside_quote = nil # quote character we are "inside" of
|
18
|
+
last_char = nil # the last character we saw
|
19
|
+
|
20
|
+
while current < string.length
|
21
|
+
char = string.chars.to_a[current]
|
22
|
+
case char
|
23
|
+
when /["']/
|
24
|
+
if inside_quote.nil? # eat the quote, but remember we are now "inside" one
|
25
|
+
inside_quote = char
|
26
|
+
elsif inside_quote == char # we closed the quote we were "inside"
|
27
|
+
inside_quote = nil
|
28
|
+
else # we got a different quote, so it goes in literally
|
29
|
+
next_arg << char
|
30
|
+
end
|
31
|
+
when /\s/
|
32
|
+
if last_char == "\\" # we have an escaped space, replace the escape char
|
33
|
+
next_arg[-1] = char
|
34
|
+
elsif inside_quote # we are inside a quote so keep the space
|
35
|
+
next_arg << char
|
36
|
+
else # new argument
|
37
|
+
args << next_arg
|
38
|
+
next_arg = ''
|
39
|
+
end
|
40
|
+
else
|
41
|
+
next_arg << char
|
42
|
+
end
|
43
|
+
current += 1
|
44
|
+
last_char = char
|
45
|
+
end
|
46
|
+
args << next_arg unless next_arg == ''
|
47
|
+
args
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Methadone
|
4
|
+
# <b>Methadone Internal - treat as private</b>
|
5
|
+
#
|
6
|
+
# Stuff to implement methadone's CLI app. These
|
7
|
+
# stuff isn't generally for your use and it's not
|
8
|
+
# included when you require 'methadone'
|
9
|
+
module CLI
|
10
|
+
|
11
|
+
# Checks that the basedir can be used, either by
|
12
|
+
# not existing, or by existing and force is true.
|
13
|
+
# In that case, we clean it out entirely
|
14
|
+
#
|
15
|
+
# +basedir+:: base directory where the user wants to create a new project
|
16
|
+
# +force+:: if true, and +basedir+ exists, delete it before proceeding
|
17
|
+
#
|
18
|
+
# This will exit the app if the dir exists and force is false
|
19
|
+
def check_and_prepare_basedir!(basedir,force)
|
20
|
+
if File.exists? basedir
|
21
|
+
if force
|
22
|
+
rm_rf basedir, :verbose => true, :secure => true
|
23
|
+
else
|
24
|
+
exit_now! 1,"error: #{basedir} exists, use --force to override"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
mkdir_p basedir
|
28
|
+
end
|
29
|
+
|
30
|
+
# Add content to a file
|
31
|
+
#
|
32
|
+
# +file+:: path to the file
|
33
|
+
# +lines+:: Array of String representing the lines to add
|
34
|
+
# +options+:: Hash of options:
|
35
|
+
# <tt>:before</tt>:: A regexp that will appear right after the new content. i.e.
|
36
|
+
# this is where to insert said content.
|
37
|
+
def add_to_file(file,lines,options = {})
|
38
|
+
new_lines = []
|
39
|
+
found_line = false
|
40
|
+
File.open(file).readlines.each do |line|
|
41
|
+
line.chomp!
|
42
|
+
if options[:before] && options[:before] === line
|
43
|
+
found_line = true
|
44
|
+
new_lines += lines
|
45
|
+
end
|
46
|
+
new_lines << line
|
47
|
+
end
|
48
|
+
|
49
|
+
raise "No line matched #{options[:before]}" if options[:before] && !found_line
|
50
|
+
|
51
|
+
new_lines += lines unless options[:before]
|
52
|
+
File.open(file,'w') do |fp|
|
53
|
+
new_lines.each { |line| fp.puts line }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Copies a file, running it through ERB
|
58
|
+
#
|
59
|
+
# +relative_path+:: path to the file, relative to the project root, minus the .erb extension
|
60
|
+
# You should use forward slashes to separate paths; this method
|
61
|
+
# will handle making the ultimate path OS independent.
|
62
|
+
# +options+:: Options to affect how the copy is done:
|
63
|
+
# <tt>:from</tt>:: The name of the profile from which to find the file, "full" by default
|
64
|
+
# <tt>:as</tt>:: The name the file should get if not the one in relative_path
|
65
|
+
# <tt>:executable</tt>:: true if this file should be set executable
|
66
|
+
# <tt>:binding</tt>:: the binding to use for the template
|
67
|
+
def copy_file(relative_path,options = {})
|
68
|
+
|
69
|
+
relative_path = File.join(relative_path.split(/\//))
|
70
|
+
|
71
|
+
template_path = File.join(template_dir(options[:from] || :full),relative_path + ".erb")
|
72
|
+
template = ERB.new(File.open(template_path).readlines.join(''), nil ,'-')
|
73
|
+
|
74
|
+
relative_path_parts = File.split(relative_path)
|
75
|
+
relative_path_parts[-1] = options[:as] if options[:as]
|
76
|
+
|
77
|
+
File.open(File.join(relative_path_parts),'w') do |file|
|
78
|
+
file.puts template.result(options[:binding] || binding)
|
79
|
+
file.chmod(0755) if options[:executable]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Get the location of the templates for profile "from"
|
84
|
+
def template_dir(from)
|
85
|
+
File.join(File.dirname(__FILE__),'..','..','templates',from.to_s)
|
86
|
+
end
|
87
|
+
|
88
|
+
def template_dirs_in(profile)
|
89
|
+
template_dir = template_dir(profile)
|
90
|
+
|
91
|
+
Dir["#{template_dir}/**/*"].select { |x|
|
92
|
+
File.directory? x
|
93
|
+
}.map { |dir|
|
94
|
+
dir.gsub(/^#{template_dir}\//,'')
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
# converts string to constant form:
|
99
|
+
# methadone-module_name-class_name => Methadone::ModuleName::ClassName
|
100
|
+
def titlify(name)
|
101
|
+
name.gsub(/(^|-|_)(.)/) {"#{'::' if $1 == '-'}#{$2.upcase}"}
|
102
|
+
end
|
103
|
+
|
104
|
+
def normalize_command(cmd)
|
105
|
+
#Note: not i18n-safe
|
106
|
+
cmd.tr('A-Z','a-z').gsub(/[^a-z0-9_]/,'_').sub(/^_*/,'')
|
107
|
+
end
|
108
|
+
|
109
|
+
def render_license_partial(partial)
|
110
|
+
ERB.new(File.read(template_dir('full/'+partial))).result(binding).strip
|
111
|
+
end
|
112
|
+
|
113
|
+
def gemspec
|
114
|
+
@gemspec || @gemspec=_get_gemspec
|
115
|
+
end
|
116
|
+
private
|
117
|
+
def _get_gemspec
|
118
|
+
files=Dir.glob("*.gemspec")
|
119
|
+
raise "Multiple gemspec files" if files.size>1
|
120
|
+
raise "No gemspec file" if files.size < 1
|
121
|
+
Gem::Specification::load(files.first)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|