nkryptic-sandbox 0.2.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/CHANGELOG +10 -0
- data/README.rdoc +117 -0
- data/Rakefile +41 -0
- data/TODO +14 -0
- data/bin/sandbox +6 -0
- data/features/development.feature +13 -0
- data/features/steps/common.rb +174 -0
- data/features/steps/env.rb +15 -0
- data/lib/sandbox/cli.rb +185 -0
- data/lib/sandbox/errors.rb +43 -0
- data/lib/sandbox/installer.rb +156 -0
- data/lib/sandbox/templates/activate_sandbox.erb +91 -0
- data/lib/sandbox/version.rb +15 -0
- data/lib/sandbox.rb +33 -0
- data/sandbox.gemspec +43 -0
- data/spec/sandbox/cli_spec.rb +199 -0
- data/spec/sandbox/installer_spec.rb +219 -0
- data/spec/sandbox_spec.rb +25 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +63 -0
- data/tasks/cucumber.rake +25 -0
- data/tasks/dcov.rake +37 -0
- data/tasks/gem.rake +5 -0
- data/tasks/rspec.rake +51 -0
- metadata +130 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
|
2
|
+
v0.2.0 Functional basic version.
|
3
|
+
Requires rubygems and only installs environment (with optional gem installs).
|
4
|
+
|
5
|
+
v0.1.2 Branched fullversion from master.
|
6
|
+
Full version will include ruby and rubygems installs.
|
7
|
+
|
8
|
+
v0.1.1 Adding rspec and cucumber
|
9
|
+
|
10
|
+
v0.1.0 First version
|
data/README.rdoc
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
= Sandbox
|
2
|
+
|
3
|
+
* http://github.com/nkryptic/sandbox
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Inspired by Python's virtualenv[http://pypi.python.org/pypi/virtualenv]
|
8
|
+
project, Sandbox is a utility to create sandboxed Ruby/Rubygems environments.
|
9
|
+
|
10
|
+
It is meant to address the following issues:
|
11
|
+
|
12
|
+
* Conflicts with unspecified gem dependency versions.
|
13
|
+
* Applications can have their own gem repositories.
|
14
|
+
* Permissions for installing your own gems.
|
15
|
+
* Ability to try gems out without installing into your global repository.
|
16
|
+
* A Simple way to enable this.
|
17
|
+
|
18
|
+
Running from your own gem repositories is fairly straight-forward, but
|
19
|
+
managing the necessary environment is a pain. This utility will create a new
|
20
|
+
environment which may be activated by the script `bin/activate` in your
|
21
|
+
sandbox directory.
|
22
|
+
|
23
|
+
Run the script with the following to enable your new environment:
|
24
|
+
|
25
|
+
$ source bin/activate_sandbox
|
26
|
+
|
27
|
+
When you want to leave the environment:
|
28
|
+
|
29
|
+
$ deactivate_sandbox
|
30
|
+
|
31
|
+
== NOTES:
|
32
|
+
|
33
|
+
* It creates an environment that has its own installation directory for Gems.
|
34
|
+
* It doesn't share gems with other sandbox environments.
|
35
|
+
* It (optionally) doesn't use the globally installed gems either.
|
36
|
+
* It will use a local to the sandbox .gemrc file
|
37
|
+
|
38
|
+
== FEATURES/PROBLEMS:
|
39
|
+
|
40
|
+
Activating your sandbox environment will change your HOME directory
|
41
|
+
temporarily to the sandbox directory. Other environment variables are set to
|
42
|
+
enable this funtionality, so if you may experience odd behavior. Everything
|
43
|
+
should be reset when you deactivate the sandbox.
|
44
|
+
|
45
|
+
== USAGE:
|
46
|
+
|
47
|
+
Create a new sandbox (rake gem installed by default):
|
48
|
+
$ cd ~/ruby-projects
|
49
|
+
$ sandbox my-new-sandbox
|
50
|
+
|
51
|
+
Create a new sandbox with output (rake gem installed by default):
|
52
|
+
$ cd ~/ruby-projects
|
53
|
+
$ sandbox my-new-sandbox -v
|
54
|
+
creating new sandbox in /home/nkryptic/ruby-projects/my-new-sandbox
|
55
|
+
installing gems:
|
56
|
+
gem: rake
|
57
|
+
|
58
|
+
Create a new sandbox with no gems installed:
|
59
|
+
$ cd ~/ruby-projects
|
60
|
+
$ sandbox my-new-sandbox -n
|
61
|
+
creating new sandbox in /home/nkryptic/ruby-projects/my-new-sandbox
|
62
|
+
installing gems:
|
63
|
+
|
64
|
+
Create a new sandbox with specific gems:
|
65
|
+
$ cd ~/ruby-projects
|
66
|
+
$ sandbox my-new-sandbox -g rake,rails
|
67
|
+
creating new sandbox in /home/nkryptic/ruby-projects/my-new-sandbox
|
68
|
+
installing gems:
|
69
|
+
gem: rake
|
70
|
+
gem: rails
|
71
|
+
gem: rspec
|
72
|
+
|
73
|
+
== FUTURE PLANS:
|
74
|
+
|
75
|
+
I hope to expand the full version branch to allow for installing both rubygems
|
76
|
+
and ruby as part of the sandbox. This would enable experimentation with
|
77
|
+
different versions of both and exclude the requirement on needing rubygems in
|
78
|
+
the first place.
|
79
|
+
|
80
|
+
== REQUIREMENTS:
|
81
|
+
|
82
|
+
* ruby
|
83
|
+
* rubygems (currently, until full version complete)
|
84
|
+
|
85
|
+
== INSTALL:
|
86
|
+
|
87
|
+
sudo gem install nkryptic-sandbox -s http://gems.github.com
|
88
|
+
|
89
|
+
or
|
90
|
+
|
91
|
+
sudo gem sources --add http://gems.github.com
|
92
|
+
sudo gem install nkryptic-sandbox
|
93
|
+
|
94
|
+
== LICENSE:
|
95
|
+
|
96
|
+
(The MIT License)
|
97
|
+
|
98
|
+
Copyright (c) 2008 Jacob Radford
|
99
|
+
|
100
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
101
|
+
a copy of this software and associated documentation files (the
|
102
|
+
'Software'), to deal in the Software without restriction, including
|
103
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
104
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
105
|
+
permit persons to whom the Software is furnished to do so, subject to
|
106
|
+
the following conditions:
|
107
|
+
|
108
|
+
The above copyright notice and this permission notice shall be
|
109
|
+
included in all copies or substantial portions of the Software.
|
110
|
+
|
111
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
112
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
113
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
114
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
115
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
116
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
117
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
require 'lib/sandbox' unless defined? Sandbox
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'echoe'
|
8
|
+
|
9
|
+
Echoe.new( 'sandbox', Sandbox::Version::STRING ) do |p|
|
10
|
+
# p.rubyforge_name = 'nkryptic'
|
11
|
+
# p.summary = "Create virtual ruby/rubygems sandboxes."
|
12
|
+
p.description = "Create virtual ruby/rubygems sandboxes."
|
13
|
+
p.url = "http://github.com/nkryptic/sandbox"
|
14
|
+
p.author = "Jacob Radford"
|
15
|
+
p.email = "nkryptic@gmail.com"
|
16
|
+
p.ignore_pattern = [ "tmp/*", "script/*" ]
|
17
|
+
p.development_dependencies = [
|
18
|
+
'echoe ~> 3.0',
|
19
|
+
'rspec ~> 1.1.0',
|
20
|
+
'mocha ~> 0.9',
|
21
|
+
]
|
22
|
+
# p.dependencies = ['ParseTree >=2.1.1', 'ruby2ruby >=1.1.8']
|
23
|
+
end
|
24
|
+
|
25
|
+
rescue LoadError => boom
|
26
|
+
puts "You are missing a dependency required for meta-operations on this gem."
|
27
|
+
puts "#{boom.to_s.capitalize}."
|
28
|
+
end
|
29
|
+
|
30
|
+
Dir[ "#{File.dirname(__FILE__)}/tasks/*.rake" ].sort.each { |ext| load ext }
|
31
|
+
|
32
|
+
# desc 'Generate RDoc documentation for Sandbox.'
|
33
|
+
# Rake::RDocTask.new( :rdoc ) do |rdoc|
|
34
|
+
# files = [ 'README', 'LICENSE', 'lib/**/*.rb' ]
|
35
|
+
# rdoc.rdoc_files.add( files )
|
36
|
+
# rdoc.main = "README" # page to start on
|
37
|
+
# rdoc.title = "sandbox"
|
38
|
+
# # rdoc.template = File.exists?( t="/Users/chris/ruby/projects/err/rock/template.rb" ) ? t : "/var/www/rock/template.rb"
|
39
|
+
# rdoc.rdoc_dir = 'doc' # rdoc output folder
|
40
|
+
# rdoc.options << '--inline-source'
|
41
|
+
# end
|
data/TODO
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
* allow gem versions to be specified when installing
|
3
|
+
* better documentation
|
4
|
+
* of the codebase
|
5
|
+
* more specs
|
6
|
+
* why not try for 100% coverage
|
7
|
+
* improve ui output
|
8
|
+
* use verbosity level
|
9
|
+
* include more messages about status
|
10
|
+
* move to ui class?
|
11
|
+
* user config
|
12
|
+
* list of gems to install
|
13
|
+
~/.sandbox/config
|
14
|
+
|
data/bin/sandbox
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Feature: Development processes of newgem itself (rake tasks)
|
2
|
+
|
3
|
+
As a Newgem maintainer or contributor
|
4
|
+
I want rake tasks to maintain and release the gem
|
5
|
+
So that I can spend time on the tests and code, and not excessive time on maintenance processes
|
6
|
+
|
7
|
+
Scenario: Generate RubyGem
|
8
|
+
Given this project is active project folder
|
9
|
+
And 'pkg' folder is deleted
|
10
|
+
When task 'rake gem' is invoked
|
11
|
+
Then folder 'pkg' is created
|
12
|
+
And file with name matching 'pkg/*.gem' is created else you should run "rake manifest" to fix this
|
13
|
+
And gem spec key 'rdoc_options' contains /--mainREADME.rdoc/
|
@@ -0,0 +1,174 @@
|
|
1
|
+
def in_project_folder(&block)
|
2
|
+
project_folder = @active_project_folder || @tmp_root
|
3
|
+
FileUtils.chdir(project_folder, &block)
|
4
|
+
end
|
5
|
+
|
6
|
+
def in_home_folder(&block)
|
7
|
+
FileUtils.chdir(@home_path, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
Given %r{^a safe folder} do
|
11
|
+
FileUtils.rm_rf @tmp_root = File.dirname(__FILE__) + "/../../tmp"
|
12
|
+
FileUtils.mkdir_p @tmp_root
|
13
|
+
FileUtils.mkdir_p @home_path = File.expand_path(File.join(@tmp_root, "home"))
|
14
|
+
@lib_path = File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
15
|
+
Given "env variable $HOME set to '#{@home_path}'"
|
16
|
+
end
|
17
|
+
|
18
|
+
Given %r{^this project is active project folder} do
|
19
|
+
Given "a safe folder"
|
20
|
+
@active_project_folder = File.expand_path(File.dirname(__FILE__) + "/../..")
|
21
|
+
end
|
22
|
+
|
23
|
+
Given %r{^env variable \$([\w_]+) set to '(.*)'} do |env_var, value|
|
24
|
+
ENV[env_var] = value
|
25
|
+
end
|
26
|
+
|
27
|
+
def force_local_lib_override(project_name = @project_name)
|
28
|
+
rakefile = File.read(File.join(project_name, 'Rakefile'))
|
29
|
+
File.open(File.join(project_name, 'Rakefile'), "w+") do |f|
|
30
|
+
f << "$:.unshift('#{@lib_path}')\n"
|
31
|
+
f << rakefile
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def setup_active_project_folder project_name
|
36
|
+
@active_project_folder = File.join(@tmp_root, project_name)
|
37
|
+
@project_name = project_name
|
38
|
+
end
|
39
|
+
|
40
|
+
Given %r{'(.*)' folder is deleted} do |folder|
|
41
|
+
in_project_folder do
|
42
|
+
FileUtils.rm_rf folder
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
When %r{^'(.*)' generator is invoked with arguments '(.*)'$} do |generator, arguments|
|
47
|
+
FileUtils.chdir(@active_project_folder) do
|
48
|
+
if Object.const_defined?("APP_ROOT")
|
49
|
+
APP_ROOT.replace(FileUtils.pwd)
|
50
|
+
else
|
51
|
+
APP_ROOT = FileUtils.pwd
|
52
|
+
end
|
53
|
+
run_generator(generator, arguments.split(' '), SOURCES)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
When %r{run executable '(.*)' with arguments '(.*)'} do |executable, arguments|
|
58
|
+
@stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
|
59
|
+
FileUtils.chdir(@active_project_folder) do
|
60
|
+
system "ruby #{executable} #{arguments} > #{@stdout}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
When %r{^task 'rake (.*)' is invoked$} do |task|
|
65
|
+
@stdout = File.expand_path(File.join(@tmp_root, "tests.out"))
|
66
|
+
FileUtils.chdir(@active_project_folder) do
|
67
|
+
system "rake #{task} --trace > #{@stdout} 2> #{@stdout}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
Then %r{^folder '(.*)' is created} do |folder|
|
72
|
+
in_project_folder do
|
73
|
+
File.exists?(folder).should be_true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
Then %r{^file '(.*)' (is|is not) created} do |file, is|
|
78
|
+
in_project_folder do
|
79
|
+
File.exists?(file).should(is == 'is' ? be_true : be_false)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
Then %r{^file with name matching '(.*)' is created} do |pattern|
|
84
|
+
in_project_folder do
|
85
|
+
Dir[pattern].should_not be_empty
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
Then %r{gem file '(.*)' and generated file '(.*)' should be the same} do |gem_file, project_file|
|
90
|
+
File.exists?(gem_file).should be_true
|
91
|
+
File.exists?(project_file).should be_true
|
92
|
+
gem_file_contents = File.read(File.dirname(__FILE__) + "/../../#{gem_file}")
|
93
|
+
project_file_contents = File.read(File.join(@active_project_folder, project_file))
|
94
|
+
project_file_contents.should == gem_file_contents
|
95
|
+
end
|
96
|
+
|
97
|
+
Then %r{^output same as contents of '(.*)'$} do |file|
|
98
|
+
expected_output = File.read(File.join(File.dirname(__FILE__) + "/../expected_outputs", file))
|
99
|
+
actual_output = File.read(File.dirname(__FILE__) + "/../../tmp/#{@stdout}")
|
100
|
+
actual_output.should == expected_output
|
101
|
+
end
|
102
|
+
|
103
|
+
Then %r{^(does|does not) invoke generator '(.*)'$} do |does_invoke, generator|
|
104
|
+
actual_output = File.read(File.dirname(__FILE__) + "/../../tmp/#{@stdout}")
|
105
|
+
does_invoke == "does" ?
|
106
|
+
actual_output.should(match(/dependency\s+#{generator}/)) :
|
107
|
+
actual_output.should_not(match(/dependency\s+#{generator}/))
|
108
|
+
end
|
109
|
+
|
110
|
+
Then %r{help options '(.*)' and '(.*)' are displayed} do |opt1, opt2|
|
111
|
+
actual_output = File.read(@stdout)
|
112
|
+
actual_output.should match(/#{opt1}/)
|
113
|
+
actual_output.should match(/#{opt2}/)
|
114
|
+
end
|
115
|
+
|
116
|
+
Then %r{^output (does|does not) match \/(.*)\/} do |does, regex|
|
117
|
+
actual_output = File.read(@stdout)
|
118
|
+
(does == 'does') ?
|
119
|
+
actual_output.should(match(/#{regex}/)) :
|
120
|
+
actual_output.should_not(match(/#{regex}/))
|
121
|
+
end
|
122
|
+
|
123
|
+
Then %r{^contents of file '(.*)' (does|does not) match \/(.*)\/} do |file, does, regex|
|
124
|
+
in_project_folder do
|
125
|
+
actual_output = File.read(file)
|
126
|
+
(does == 'does') ?
|
127
|
+
actual_output.should(match(/#{regex}/)) :
|
128
|
+
actual_output.should_not(match(/#{regex}/))
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
Then %r{^all (\d+) tests pass} do |expected_test_count|
|
133
|
+
expected = %r{^#{expected_test_count} tests, \d+ assertions, 0 failures, 0 errors}
|
134
|
+
actual_output = File.read(@stdout)
|
135
|
+
actual_output.should match(expected)
|
136
|
+
end
|
137
|
+
|
138
|
+
Then %r{^all (\d+) examples pass} do |expected_test_count|
|
139
|
+
expected = %r{^#{expected_test_count} examples?, 0 failures}
|
140
|
+
actual_output = File.read(@stdout)
|
141
|
+
actual_output.should match(expected)
|
142
|
+
end
|
143
|
+
|
144
|
+
Then %r{^yaml file '(.*)' contains (\{.*\})} do |file, yaml|
|
145
|
+
in_project_folder do
|
146
|
+
yaml = eval yaml
|
147
|
+
YAML.load(File.read(file)).should == yaml
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
Then %r{^Rakefile can display tasks successfully} do
|
152
|
+
@stdout = File.expand_path(File.join(@tmp_root, "rakefile.out"))
|
153
|
+
FileUtils.chdir(@active_project_folder) do
|
154
|
+
system "rake -T > #{@stdout} 2> #{@stdout}"
|
155
|
+
end
|
156
|
+
actual_output = File.read(@stdout)
|
157
|
+
actual_output.should match(/^rake\s+\w+\s+#\s.*/)
|
158
|
+
end
|
159
|
+
|
160
|
+
Then %r{^task 'rake (.*)' is executed successfully} do |task|
|
161
|
+
@stdout.should_not be_nil
|
162
|
+
actual_output = File.read(@stdout)
|
163
|
+
actual_output.should_not match(/^Don't know how to build task '#{task}'/)
|
164
|
+
actual_output.should_not match(/Error/i)
|
165
|
+
end
|
166
|
+
|
167
|
+
Then %r{^gem spec key '(.*)' contains \/(.*)\/} do |key, regex|
|
168
|
+
in_project_folder do
|
169
|
+
gem_file = Dir["pkg/*.gem"].first
|
170
|
+
gem_spec = Gem::Specification.from_yaml(`gem spec #{gem_file}`)
|
171
|
+
spec_value = gem_spec.send(key.to_sym)
|
172
|
+
spec_value.to_s.should match(/#{regex}/)
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../../lib/sandbox"
|
2
|
+
|
3
|
+
# gem 'cucumber'
|
4
|
+
# require 'cucumber'
|
5
|
+
# gem 'rspec'
|
6
|
+
# require 'spec'
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'cucumber'
|
10
|
+
require 'spec'
|
11
|
+
rescue LoadError
|
12
|
+
require 'rubygems'
|
13
|
+
require 'cucumber'
|
14
|
+
require 'spec'
|
15
|
+
end
|
data/lib/sandbox/cli.rb
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
|
2
|
+
require 'optparse'
|
3
|
+
require 'sandbox'
|
4
|
+
|
5
|
+
module Sandbox
|
6
|
+
class CLI
|
7
|
+
|
8
|
+
DEFAULTS = {
|
9
|
+
:gems => [ 'rake', ]
|
10
|
+
}
|
11
|
+
|
12
|
+
## CLASS METHODS
|
13
|
+
class << self
|
14
|
+
|
15
|
+
# invokes sandbox via command-line ARGV as the options
|
16
|
+
def execute( args = ARGV )
|
17
|
+
verify_environment!
|
18
|
+
parse( args ).execute!
|
19
|
+
rescue Exception => error
|
20
|
+
handle_error( error )
|
21
|
+
end
|
22
|
+
|
23
|
+
# returns a new CLI instance which has parsed the given arguments.
|
24
|
+
# will load the command to execute based upon the arguements.
|
25
|
+
# if an error occurs, it will print out simple error message and exit
|
26
|
+
def parse( args )
|
27
|
+
cli = new
|
28
|
+
cli.parse_args!( args )
|
29
|
+
cli
|
30
|
+
end
|
31
|
+
|
32
|
+
def verify_environment!
|
33
|
+
raise LoadedSandboxError if ENV[ 'SANDBOX' ]
|
34
|
+
end
|
35
|
+
|
36
|
+
# pretty error handling
|
37
|
+
def handle_error( error )
|
38
|
+
case error
|
39
|
+
when Sandbox::Error
|
40
|
+
puts error.message
|
41
|
+
when StandardError #, Timeout::Error
|
42
|
+
message = [ "Error: #{error.message}" ]
|
43
|
+
message.concat( error.backtrace.collect { |bt| " #{bt}" } ) if Sandbox.really_verbose?
|
44
|
+
puts message.join( "\n" )
|
45
|
+
when Interrupt
|
46
|
+
puts "Interrupted"
|
47
|
+
else
|
48
|
+
raise error
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
## END CLASS METHODS
|
54
|
+
|
55
|
+
## PUBLIC INSTANCE METHODS
|
56
|
+
public
|
57
|
+
|
58
|
+
# The options for this execution.
|
59
|
+
attr_reader :options
|
60
|
+
|
61
|
+
# setup of a new CLI instance
|
62
|
+
def initialize
|
63
|
+
@options = DEFAULTS.dup
|
64
|
+
@parser = nil
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
# perform the sandbox creation
|
69
|
+
def execute!
|
70
|
+
targets = options.delete( :args )
|
71
|
+
|
72
|
+
if targets.size < 1
|
73
|
+
raise Sandbox::Error.new( 'no target specified - see `sandbox --help` for assistance' )
|
74
|
+
elsif targets.size > 1
|
75
|
+
raise Sandbox::Error.new( 'multiple targets specified - see `sandbox --help` for assistance' )
|
76
|
+
end
|
77
|
+
|
78
|
+
options[ :target ] = targets[0]
|
79
|
+
|
80
|
+
Sandbox::Installer.new( options ).populate
|
81
|
+
end
|
82
|
+
|
83
|
+
# processes +args+ to:
|
84
|
+
#
|
85
|
+
# * load global option for the application
|
86
|
+
# * determine command name to lookup in CommandManager
|
87
|
+
# * load command and have it process any add't options
|
88
|
+
# * catches exceptions for unknown switches or commands
|
89
|
+
def parse_args!( args )
|
90
|
+
options[ :original_args ] = args.dup
|
91
|
+
parser.parse!( args )
|
92
|
+
rescue OptionParser::ParseError => ex
|
93
|
+
raise_parse_error( ex.reason, ex.args )
|
94
|
+
else
|
95
|
+
options[ :args ] = args
|
96
|
+
end
|
97
|
+
|
98
|
+
def parser
|
99
|
+
@parser ||= create_parser
|
100
|
+
end
|
101
|
+
|
102
|
+
def create_parser
|
103
|
+
OptionParser.new do |o|
|
104
|
+
o.set_summary_indent(' ')
|
105
|
+
o.program_name = 'sandbox TARGET'
|
106
|
+
o.define_head "Create virtual ruby/rubygems sandboxes."
|
107
|
+
o.separator ""
|
108
|
+
|
109
|
+
o.separator "ARGUMENTS:"
|
110
|
+
o.separator " TARGET Target path to new sandbox. Must not exist beforehand."
|
111
|
+
o.separator ""
|
112
|
+
|
113
|
+
o.separator "OPTIONS"
|
114
|
+
o.on( '-g', '--gems gem1,gem2', Array, 'Gems to install after sandbox is created. (defaults to [rake])' ) { |gems| @options[ :gems ] = gems }
|
115
|
+
o.on( '-n', '--no-gems', 'Do not install any gems after sandbox is created.)' ) { @options[ :gems ] = [] }
|
116
|
+
o.on( '-q', '--quiet', 'Show less output. (multiple allowed)' ) { |f| Sandbox.decrease_verbosity }
|
117
|
+
o.on( '-v', '--verbose', 'Show more output. (multiple allowed)' ) { |f| Sandbox.increase_verbosity }
|
118
|
+
o.on_tail( '-h', '--help', 'Show this help message and exit.' ) { puts o; exit }
|
119
|
+
o.on_tail( '-H', '--long-help', 'Show the full description about the program' ) { puts long_help; exit }
|
120
|
+
o.on_tail( '-V', '--version', 'Display the program version and exit.' ) { puts Sandbox::Version::STRING; exit }
|
121
|
+
o.separator ""
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def show_help
|
126
|
+
puts parser
|
127
|
+
end
|
128
|
+
|
129
|
+
def long_help
|
130
|
+
unindent( <<-HELP )
|
131
|
+
--------------------------------------------------------------------------------
|
132
|
+
Sandbox is a utility to create sandboxed Ruby/Rubygems environments.
|
133
|
+
|
134
|
+
It is meant to address the following issues:
|
135
|
+
1. Conflicts with unspecified gem dependency versions.
|
136
|
+
2. Applications can have their own gem repositories.
|
137
|
+
3. Permissions for installing your own gems.
|
138
|
+
4. Ability to try gems out without installing into your global repository.
|
139
|
+
5. A Simple way to enable this.
|
140
|
+
|
141
|
+
Running from your own gem repositories is fairly straight-forward, but
|
142
|
+
managing the necessary environment is a pain. This utility will create a new
|
143
|
+
environment which may be activated by the script `bin/activate` in your
|
144
|
+
sandbox directory.
|
145
|
+
|
146
|
+
Run the script with the following to enable your new environment:
|
147
|
+
$ source bin/activate
|
148
|
+
|
149
|
+
When you want to leave the environment:
|
150
|
+
$ deactivate
|
151
|
+
|
152
|
+
NOTES:
|
153
|
+
1. It creates an environment that has its own installation directory for Gems.
|
154
|
+
2. It doesn't share gems with other sandbox environments.
|
155
|
+
3. It (optionally) doesn't use the globally installed gems either.
|
156
|
+
4. It will use a local to the sandbox .gemrc file
|
157
|
+
|
158
|
+
WARNINGS:
|
159
|
+
Activating your sandbox environment will change your HOME directory
|
160
|
+
temporarily to the sandbox directory. Other environment variables are set to
|
161
|
+
enable this funtionality, so if you may experience odd behavior. Everything
|
162
|
+
should be reset when you deactivate the sandbox.
|
163
|
+
HELP
|
164
|
+
end
|
165
|
+
|
166
|
+
def unindent( output )
|
167
|
+
indent = output[/\A\s*/]
|
168
|
+
output.strip.gsub(/^#{indent}/, "")
|
169
|
+
end
|
170
|
+
|
171
|
+
## END PUBLIC INSTANCE METHODS
|
172
|
+
|
173
|
+
|
174
|
+
## PRIVATE INSTANCE METHODS
|
175
|
+
private
|
176
|
+
|
177
|
+
def raise_parse_error( reason, args=[] )
|
178
|
+
raise Sandbox::ParseError.new( reason, args )
|
179
|
+
end
|
180
|
+
|
181
|
+
## END PRIVATE INSTANCE METHODS
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
module Sandbox
|
3
|
+
|
4
|
+
class Error < StandardError
|
5
|
+
|
6
|
+
def initialize( msg=nil )
|
7
|
+
super msg
|
8
|
+
end
|
9
|
+
|
10
|
+
def message
|
11
|
+
out = []
|
12
|
+
value = super
|
13
|
+
out << "Sandbox error: #{value}"
|
14
|
+
out.concat( backtrace.collect { |bt| " #{bt}" } ) if Sandbox.really_verbose?
|
15
|
+
out.join( "\n" )
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
class LoadedSandboxError < Sandbox::Error
|
21
|
+
|
22
|
+
def initialize( msg=nil )
|
23
|
+
msg ||= "You cannot run sandbox from a loaded sandbox environment"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
class ParseError < Sandbox::Error
|
29
|
+
|
30
|
+
def initialize( reason=nil, args=[] )
|
31
|
+
if args.is_a?( Array ) and args.size > 0
|
32
|
+
msg = "#{reason} => #{args.join( ' ' )}"
|
33
|
+
elsif args.is_a?( String ) and args.length > 0
|
34
|
+
msg = "#{reason} => #{args}"
|
35
|
+
else
|
36
|
+
msg = reason
|
37
|
+
end
|
38
|
+
super msg
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|