isolate 2.0.0.pre.1 → 2.0.0.pre.2
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.rdoc +9 -0
- data/Manifest.txt +2 -0
- data/README.rdoc +98 -153
- data/Rakefile +1 -1
- data/lib/hoe/isolate.rb +20 -4
- data/lib/isolate.rb +42 -5
- data/lib/isolate/entry.rb +41 -18
- data/lib/isolate/events.rb +42 -0
- data/lib/isolate/rake.rb +25 -3
- data/lib/isolate/sandbox.rb +58 -24
- data/test/test_isolate_events.rb +44 -0
- metadata +11 -8
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
=== 2.0.0.pre.2 / 2010-05-07
|
2
|
+
|
3
|
+
* Update docs.
|
4
|
+
* Add event hooks for better extension/integration.
|
5
|
+
* Add ISOLATED env var when Isolate is activated.
|
6
|
+
* Teach the Hoe plugin to recognize Isolate files.
|
7
|
+
* Add `env` as an alias for `environment`.
|
8
|
+
* Clean up Rake tasks.
|
9
|
+
|
1
10
|
=== 2.0.0.pre.1 / 2010-05-02
|
2
11
|
|
3
12
|
* Don't provide a special way to set path, options is enough.
|
data/Manifest.txt
CHANGED
@@ -6,6 +6,7 @@ Rakefile
|
|
6
6
|
lib/hoe/isolate.rb
|
7
7
|
lib/isolate.rb
|
8
8
|
lib/isolate/entry.rb
|
9
|
+
lib/isolate/events.rb
|
9
10
|
lib/isolate/now.rb
|
10
11
|
lib/isolate/rake.rb
|
11
12
|
lib/isolate/sandbox.rb
|
@@ -19,4 +20,5 @@ test/fixtures/with-hoe/specifications/rubyforge-1.0.4.gemspec
|
|
19
20
|
test/isolate/test.rb
|
20
21
|
test/test_isolate.rb
|
21
22
|
test/test_isolate_entry.rb
|
23
|
+
test/test_isolate_events.rb
|
22
24
|
test/test_isolate_sandbox.rb
|
data/README.rdoc
CHANGED
@@ -5,18 +5,13 @@
|
|
5
5
|
== Description
|
6
6
|
|
7
7
|
Isolate is a very simple RubyGems sandbox. It provides a way to
|
8
|
-
express and install your
|
8
|
+
express and automatically install your project's Gem dependencies.
|
9
9
|
|
10
|
-
==
|
10
|
+
== Wha?
|
11
11
|
|
12
12
|
When Isolate runs, it uses GEM_HOME, GEM_PATH, and a few other tricks
|
13
|
-
to
|
14
|
-
|
15
|
-
|
16
|
-
While Isolate doesn't make any assumptions about what sort of code
|
17
|
-
you're writing, it was extracted from a few Rails apps, so it's
|
18
|
-
naturally going to be most useful with stuff like Rails, Merb, or
|
19
|
-
Sinatra.
|
13
|
+
to separate your code from the system's RubyGems configuration,
|
14
|
+
leaving it free to run in blissful solitude.
|
20
15
|
|
21
16
|
Isolate is very, very, very stupid simple. For a much more
|
22
17
|
full-featured Gem bundler, check out Yehuda Katz and Carl Lerche's
|
@@ -24,111 +19,116 @@ Bundler[http://github.com/carlhuda/bundler]: It does a lot of fancy
|
|
24
19
|
AOT dependency resolution, supports non-gem (including git) resources,
|
25
20
|
and is probably a better fit for you.
|
26
21
|
|
27
|
-
|
28
|
-
|
22
|
+
== Requirements
|
23
|
+
|
24
|
+
RubyGems 1.3.6 or better, Ruby 1.8.7 or better.
|
29
25
|
|
30
|
-
==
|
26
|
+
== Getting Started
|
31
27
|
|
32
|
-
===
|
28
|
+
=== Rails 2
|
33
29
|
|
34
|
-
|
35
|
-
same name. Version specifiers are optional.
|
30
|
+
In <tt>config/preinitializer.rb</tt>:
|
36
31
|
|
37
32
|
require "rubygems"
|
38
|
-
require "isolate"
|
33
|
+
require "isolate/now"
|
39
34
|
|
40
|
-
|
41
|
-
gem "johnson", "~> 1.1" # or maybe...
|
42
|
-
gem "jbarnette-johnson"
|
43
|
-
end
|
35
|
+
In <tt>Isolate</tt>:
|
44
36
|
|
45
|
-
|
46
|
-
|
47
|
-
your specified gems have been activated.
|
37
|
+
gem "rails", "2.3.5"
|
38
|
+
gem "aasm", "2.0.0"
|
48
39
|
|
49
|
-
|
50
|
-
|
40
|
+
env :development, :test do
|
41
|
+
gem "sqlite3-ruby", "1.2.5"
|
42
|
+
end
|
51
43
|
|
52
|
-
|
44
|
+
env :production do
|
45
|
+
gem "memcached", "0.19.2"
|
46
|
+
end
|
53
47
|
|
54
|
-
|
55
|
-
|
48
|
+
Try running <tt>rake environment</tt>. Before anything else happens,
|
49
|
+
Isolate will make sure you have copies of every gem you need (extend
|
50
|
+
the example above to cover all your dependencies). If they're already
|
51
|
+
installed on your system Isolate will use them, otherwise a private
|
52
|
+
copy will be installed under <tt>tmp/isolate</tt>.
|
56
53
|
|
57
|
-
===
|
54
|
+
=== Rails 3
|
58
55
|
|
59
|
-
|
60
|
-
times. Isolate allows you to restrict gems by 'environment' (which is
|
61
|
-
really just a string passed in when things are activated).
|
56
|
+
In <tt>config/boot.rb</tt>:
|
62
57
|
|
63
|
-
|
64
|
-
|
58
|
+
require "rubygems"
|
59
|
+
require "isolate/now"
|
65
60
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
61
|
+
Construct your <tt>Isolate</tt> file as above. Be sure to remove any
|
62
|
+
references to <tt>Bundler.setup</tt> and <tt>Bundler.require</tt> from
|
63
|
+
<tt>config/boot.rb</tt> and <tt>config/application.rb</tt>.
|
70
64
|
|
71
|
-
|
72
|
-
<tt>test</tt> and <tt>cucumber</tt> environments. See the Rails
|
73
|
-
example below for an example of how to use <tt>RAILS_ENV</tt> to set
|
74
|
-
your environment.
|
65
|
+
=== Sinatra, Rack, and Anything Else
|
75
66
|
|
76
|
-
|
67
|
+
There's nothing special about Rails, it's just an easy first
|
68
|
+
example. You can use Isolate with any library or framework by simply
|
69
|
+
putting an <tt>Isolate</tt> file in the root of your project and
|
70
|
+
requiring <tt>isolate/now</tt> as early as possible in the startup
|
71
|
+
process.
|
77
72
|
|
78
|
-
|
79
|
-
|
80
|
-
|
73
|
+
When you're starting up, Isolate tries to determine its environment by
|
74
|
+
looking at the <tt>ISOLATE_ENV</tt>, <tt>RACK_ENV</tt>, and
|
75
|
+
<tt>RAILS_ENV</tt> env vars. If none are set, it defaults to
|
76
|
+
<tt>development</tt>.
|
81
77
|
|
82
|
-
|
83
|
-
gem "jbarnette-johnson", :source => "http://gems.github.com"
|
78
|
+
=== Library Development
|
84
79
|
|
85
|
-
|
86
|
-
|
80
|
+
If you're using Hoe[http://blog.zenspider.com/hoe] to manage your
|
81
|
+
library, you can use Isolate's Hoe plugin to automatically install
|
82
|
+
your lib's development, runtime, and test dependencies without
|
83
|
+
polluting your system RubyGems, and run your tests/specs in total
|
84
|
+
isolation.
|
87
85
|
|
88
|
-
|
86
|
+
Assuming you have a recent Hoe and isolate's installed, it's as simple
|
87
|
+
as putting:
|
89
88
|
|
90
|
-
|
91
|
-
keep all your stuff in an external file. This is supported by default:
|
89
|
+
Hoe.plugin :isolate
|
92
90
|
|
93
|
-
|
91
|
+
before the <tt>Hoe.spec</tt> call in your <tt>Rakefile</tt>.
|
94
92
|
|
95
|
-
|
96
|
-
the
|
97
|
-
there's another matching file with a `.local` extension, Isolate will
|
98
|
-
grab that one too. This makes it easy to have additional config that's
|
99
|
-
specific to a deployment or developer.
|
93
|
+
If you're not using Hoe, you can use an <tt>Isolate.now!</tt> block at
|
94
|
+
the top of your Rakefile. See the RDoc for details.
|
100
95
|
|
101
|
-
|
96
|
+
== Rake
|
102
97
|
|
103
|
-
|
104
|
-
automatically. You can pass the <tt>:cleanup</tt>, <tt>:install</tt>,
|
105
|
-
and <tt>:verbose</tt> options to control things:
|
98
|
+
Isolate provides a few useful Rake tasks.
|
106
99
|
|
107
|
-
|
108
|
-
Isolate.now!, :cleanup => false
|
100
|
+
=== isolate:env
|
109
101
|
|
110
|
-
|
111
|
-
Isolate.now! :verbose => false
|
102
|
+
This task shows you the current Isolate settings and gems.
|
112
103
|
|
113
|
-
|
114
|
-
Isolate.now! :install => false
|
104
|
+
$ rake isolate:env
|
115
105
|
|
116
|
-
|
106
|
+
path: tmp/isolate/ruby-1.8
|
107
|
+
env: development
|
108
|
+
files: Isolate
|
117
109
|
|
118
|
-
|
110
|
+
cleanup? true
|
111
|
+
enabled? true
|
112
|
+
install? true
|
113
|
+
multiruby? true
|
114
|
+
system? true
|
115
|
+
verbose? true
|
119
116
|
|
120
|
-
|
117
|
+
[all environments]
|
118
|
+
gem rails, = 2.3.5
|
119
|
+
gem aasm, = 2.0.0
|
121
120
|
|
122
|
-
|
123
|
-
|
124
|
-
<tt>require</tt> in your <tt>Rakefile</tt>:
|
121
|
+
[development, test]
|
122
|
+
gem sqlite3-ruby, = 1.2.5
|
125
123
|
|
126
|
-
|
124
|
+
[production]
|
125
|
+
gem memcached, = 0.19.2
|
127
126
|
|
128
|
-
|
127
|
+
=== isolate:sh
|
129
128
|
|
130
|
-
|
131
|
-
|
129
|
+
This task allows you to run a subshell or a command in the isolated
|
130
|
+
environment, making any command-line tools available on your
|
131
|
+
<tt>PATH</tt>.
|
132
132
|
|
133
133
|
# run a single command in an isolated subshell
|
134
134
|
$ rake isolate:sh['gem list']
|
@@ -136,92 +136,37 @@ by any of your gems are available on your PATH.
|
|
136
136
|
# run a new isolated subshell
|
137
137
|
$ rake isolate:sh
|
138
138
|
|
139
|
-
|
140
|
-
|
141
|
-
$ rake isolate:debug
|
142
|
-
|
143
|
-
=== A Rails 2 Example
|
144
|
-
|
145
|
-
Here's a quick example (extracted from a real project) of how to use
|
146
|
-
Isolate with Rails. This project doesn't use vendored Rails, and
|
147
|
-
doesn't want to depend on any system gems (except isolate, of course).
|
148
|
-
|
149
|
-
Let's edit <tt>config/preinitializer.rb</tt>:
|
150
|
-
|
151
|
-
require "rubygems"
|
152
|
-
require "isolate"
|
153
|
-
|
154
|
-
Isolate.now!
|
155
|
-
|
156
|
-
In <tt>config/isolate.rb</tt>:
|
157
|
-
|
158
|
-
gem "rails", "= 2.2.2"
|
139
|
+
=== isolate:stale
|
159
140
|
|
160
|
-
|
161
|
-
|
141
|
+
This task lists gems that have a more recent released version than the
|
142
|
+
one you're using.
|
162
143
|
|
163
|
-
|
164
|
-
|
144
|
+
$ rake isolate:stale
|
145
|
+
aasm (2.0.0 < 2.1.5)
|
165
146
|
|
166
|
-
|
167
|
-
gem "gmail_contacts", "~> 1.7"
|
147
|
+
== Further Reading
|
168
148
|
|
169
|
-
|
170
|
-
|
149
|
+
<tt>require "isolate/now"</tt> is sugar for <tt>Isolate.now!</tt>,
|
150
|
+
which creates, configures, and activates a singleton version of
|
151
|
+
Isolate's sandbox. <tt>Isolate.now!</tt> takes a few useful options,
|
152
|
+
and lets you define an entire environment inline without using an
|
153
|
+
external file.
|
171
154
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
# XML/HTML parsing in Facebooker and tests
|
176
|
-
gem "nokogiri", ">= 1.2.3"
|
177
|
-
|
178
|
-
# Twitter authentication
|
179
|
-
gem "oauth", "~> 0.3"
|
180
|
-
|
181
|
-
environment :cucumber, :development, :test do
|
182
|
-
gem "cucumber" # stories!
|
183
|
-
gem "modelizer" # easy model factories
|
184
|
-
gem "sqlite3-ruby" # database support
|
185
|
-
gem "vlad" # deployment
|
186
|
-
gem "webrat" # integration tests
|
187
|
-
end
|
188
|
-
|
189
|
-
You could specify all this inside the <tt>Isolate.now!</tt> block, of
|
190
|
-
course, but keeping everything in an external file is nicer.
|
191
|
-
|
192
|
-
Since this is loaded in the preinitializer, Isolate will install and
|
193
|
-
activate the all gems before Rails loads. The current environment is
|
194
|
-
determined by looking at the <tt>ISOLATE_ENV</tt>, <tt>RAILS_ENV</tt>,
|
195
|
-
or <tt>RACK_ENV</tt> environment variable. If none are set,
|
196
|
-
<tt>"development"</tt> is the default.
|
197
|
-
|
198
|
-
Pow. Isolated!
|
199
|
-
|
200
|
-
=== A Library Example
|
201
|
-
|
202
|
-
If you're using Hoe[http://blog.zenspider.com/hoe] to manage your
|
203
|
-
library, you can use Isolate's Hoe plugin to automatically install
|
204
|
-
your lib's development, runtime, and test dependencies without
|
205
|
-
polluting your system RubyGems, and run your tests/specs in total
|
206
|
-
isolation.
|
207
|
-
|
208
|
-
Assuming you have a recent Hoe and isolate's installed, it's as simple
|
209
|
-
as putting:
|
210
|
-
|
211
|
-
Hoe.plugin :isolate
|
212
|
-
|
213
|
-
before the <tt>Hoe.spec</tt> call in your <tt>Rakefile</tt>.
|
214
|
-
|
215
|
-
If you're not using Hoe, you can just do a regular
|
216
|
-
<tt>Isolate.now!</tt> block at the top of your Rakefile.
|
155
|
+
For detailed information on <tt>Isolate.now!</tt> and the rest of the
|
156
|
+
public API, please see the RDoc.
|
217
157
|
|
218
158
|
== Installation
|
219
159
|
|
220
160
|
$ gem install isolate
|
221
161
|
|
162
|
+
== Meta
|
163
|
+
|
164
|
+
Bugs:: http://github.com/jbarnette/isolate/issues
|
165
|
+
Email:: isolate@librelist.com
|
166
|
+
|
222
167
|
== License
|
223
168
|
|
224
|
-
Copyright 2009 John Barnette, et al. (jbarnette
|
169
|
+
Copyright 2009-2010 John Barnette, et al. (code@jbarnette.com)
|
225
170
|
|
226
171
|
Permission is hereby granted, free of charge, to any person obtaining
|
227
172
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
data/lib/hoe/isolate.rb
CHANGED
@@ -19,23 +19,39 @@ class Hoe # :nodoc:
|
|
19
19
|
module Isolate
|
20
20
|
|
21
21
|
# Where should Isolate, um, isolate? [default: <tt>"tmp/isolate"</tt>]
|
22
|
+
# FIX: consider removing this and allowing +isolate_options+ instead.
|
22
23
|
|
23
24
|
attr_accessor :isolate_dir
|
24
25
|
|
25
|
-
def initialize_isolate
|
26
|
+
def initialize_isolate
|
26
27
|
# Tee hee! Move ourselves to the front to beat out :test.
|
27
28
|
Hoe.plugins.unshift Hoe.plugins.delete(:isolate)
|
29
|
+
|
28
30
|
self.isolate_dir ||= "tmp/isolate"
|
31
|
+
@sandbox = ::Isolate::Sandbox.new
|
32
|
+
|
33
|
+
@sandbox.entries.each do |entry|
|
34
|
+
dep = [entry.name, *entry.requirement.as_list]
|
35
|
+
|
36
|
+
if entry.environments.include? "development"
|
37
|
+
extra_dev_deps << dep
|
38
|
+
elsif entry.environments.empty?
|
39
|
+
extra_deps << dep
|
40
|
+
end
|
41
|
+
end
|
29
42
|
end
|
30
43
|
|
31
44
|
def define_isolate_tasks # HACK
|
32
|
-
i = ::Isolate::Sandbox.new :path => isolate_dir
|
33
45
|
|
46
|
+
# reset, now that they've had a chance to change it
|
47
|
+
@sandbox.options :path => isolate_dir
|
48
|
+
|
49
|
+
# allows traditional extra{_dev}_deps calls to override
|
34
50
|
(self.extra_deps + self.extra_dev_deps).each do |name, version|
|
35
|
-
|
51
|
+
@sandbox.gem name, *Array(version)
|
36
52
|
end
|
37
53
|
|
38
|
-
|
54
|
+
@sandbox.activate
|
39
55
|
end
|
40
56
|
end
|
41
57
|
end
|
data/lib/isolate.rb
CHANGED
@@ -8,7 +8,7 @@ module Isolate
|
|
8
8
|
|
9
9
|
# Duh.
|
10
10
|
|
11
|
-
VERSION = "2.0.0.pre.
|
11
|
+
VERSION = "2.0.0.pre.2"
|
12
12
|
|
13
13
|
# Disable Isolate. If a block is provided, isolation will be
|
14
14
|
# disabled for the scope of the block.
|
@@ -17,10 +17,17 @@ module Isolate
|
|
17
17
|
sandbox.disable(&block)
|
18
18
|
end
|
19
19
|
|
20
|
+
# What environment should be isolated? Consults environment
|
21
|
+
# variables <tt>ISOLATE_ENV</tt>, <tt>RAILS_ENV</tt>, and
|
22
|
+
# <tt>RACK_ENV</tt>. Defaults to <tt>development"/tt> if none are
|
23
|
+
# set.
|
24
|
+
|
20
25
|
def self.env
|
21
26
|
ENV["ISOLATE_ENV"] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
|
22
27
|
end
|
23
28
|
|
29
|
+
# Deprecated. See Isolate.now!
|
30
|
+
|
24
31
|
def self.gems path, options = {}, &block # :nodoc:
|
25
32
|
warn "Isolate.gems is deprecated, use Isolate.now! instead.\n" +
|
26
33
|
"Isolate.gems will be removed in v3.0."
|
@@ -28,6 +35,8 @@ module Isolate
|
|
28
35
|
now! options.merge(:path => path), &block
|
29
36
|
end
|
30
37
|
|
38
|
+
# Deprecated. See Isolate.sandbox.
|
39
|
+
|
31
40
|
def self.instance
|
32
41
|
warn "Isolate.instance is deprecated, use Isolate.sandbox instead.\n" +
|
33
42
|
"Isolate.instance will be removed in v3.0."
|
@@ -37,21 +46,49 @@ module Isolate
|
|
37
46
|
|
38
47
|
@@sandbox = nil
|
39
48
|
|
49
|
+
# A singleton instance of Isolate::Sandbox.
|
50
|
+
|
40
51
|
def self.sandbox
|
41
52
|
@@sandbox
|
42
53
|
end
|
43
54
|
|
44
55
|
# Declare an isolated RubyGems environment, installed in +path+. Any
|
45
|
-
# block given will be <tt>instance_eval</tt>ed, see
|
46
|
-
# Isolate#environment for the sort
|
56
|
+
# block given will be <tt>instance_eval</tt>ed, see
|
57
|
+
# Isolate::Sandbox#gem and Isolate::Sandbox#environment for the sort
|
58
|
+
# of stuff you can do.
|
59
|
+
#
|
60
|
+
# Valid options:
|
61
|
+
#
|
62
|
+
# :cleanup:: Should obsolete gems be removed? Default is +true+.
|
63
|
+
#
|
64
|
+
# :file:: Specify an Isolate file to +instance_eval+. Default is
|
65
|
+
# <tt>Isolate</tt> or <tt>config/isolate.rb</tt>, whichever
|
66
|
+
# is found first. Passing <tt>false</tt> disables file
|
67
|
+
# loading.
|
68
|
+
#
|
69
|
+
# :install:: Should missing gems be installed? Default is +true+.
|
70
|
+
#
|
71
|
+
# :multiruby:: Should Isolate assume that multiple Ruby versions
|
72
|
+
# will be used simultaneously? If so, gems will be
|
73
|
+
# segregated by Ruby version. Default is +true+.
|
74
|
+
#
|
75
|
+
# :path:: Where should isolated gems be kept? Default is
|
76
|
+
# <tt>tmp/isolate"</tt>, and a Ruby version specifier suffix
|
77
|
+
# will be added if <tt>:multiruby</tt> is +true+.
|
78
|
+
#
|
79
|
+
# :system:: Should system gems be allowed to satisfy dependencies?
|
80
|
+
# Default is +true+.
|
81
|
+
#
|
82
|
+
# :verbose:: Should Isolate be chatty during installs and nukes?
|
83
|
+
# Default is +true+.
|
47
84
|
|
48
85
|
def self.now! options = {}, &block
|
49
86
|
@@sandbox = Isolate::Sandbox.new options, &block
|
50
87
|
@@sandbox.activate
|
51
88
|
end
|
52
89
|
|
53
|
-
# Poke RubyGems, we've probably monkeyed with a bunch of paths
|
54
|
-
# suchlike. Clears paths, loaded specs, and source indexes.
|
90
|
+
# Poke RubyGems, since we've probably monkeyed with a bunch of paths
|
91
|
+
# and suchlike. Clears paths, loaded specs, and source indexes.
|
55
92
|
|
56
93
|
def self.refresh # :nodoc:
|
57
94
|
Gem.loaded_specs.clear
|
data/lib/isolate/entry.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "isolate/events"
|
1
2
|
require "rubygems"
|
2
3
|
require "rubygems/command"
|
3
4
|
require "rubygems/dependency_installer"
|
@@ -7,9 +8,12 @@ require "rubygems/version"
|
|
7
8
|
module Isolate
|
8
9
|
|
9
10
|
# An isolated Gem, with requirement, environment restrictions, and
|
10
|
-
# installation options.
|
11
|
+
# installation options. Generally intended for internal use. This
|
12
|
+
# class exposes lifecycle events for extension, see Isolate::Events
|
13
|
+
# for more information.
|
11
14
|
|
12
15
|
class Entry
|
16
|
+
include Events
|
13
17
|
|
14
18
|
# Which environments does this entry care about? Generally an
|
15
19
|
# Array of Strings. An empty array means "all", not "none".
|
@@ -31,9 +35,14 @@ module Isolate
|
|
31
35
|
attr_reader :requirement
|
32
36
|
|
33
37
|
# Create a new entry. Takes +sandbox+ (currently an instance of
|
34
|
-
# Isolate), +name+ (as above), and any number of optional
|
35
|
-
# requirements (generally
|
36
|
-
# trailing hash.
|
38
|
+
# Isolate::Sandbox), +name+ (as above), and any number of optional
|
39
|
+
# version requirements (generally strings). Options can be passed
|
40
|
+
# as a trailing hash. Well-known keys:
|
41
|
+
#
|
42
|
+
# :args:: Command-line build arguments. Passed to the gem at
|
43
|
+
# installation time.
|
44
|
+
#
|
45
|
+
# :source:: An alternative RubyGems source for this gem.
|
37
46
|
|
38
47
|
def initialize sandbox, name, *requirements
|
39
48
|
@environments = []
|
@@ -53,26 +62,32 @@ module Isolate
|
|
53
62
|
update(*requirements)
|
54
63
|
end
|
55
64
|
|
65
|
+
# Activate this entry. Fires <tt>:activating</tt> and
|
66
|
+
# <tt>:activated</tt>.
|
67
|
+
|
56
68
|
def activate
|
57
|
-
|
69
|
+
fire :activating, :activated do
|
70
|
+
Gem.activate name, *requirement.as_list
|
71
|
+
end
|
58
72
|
end
|
59
73
|
|
60
|
-
# Install this entry in the sandbox.
|
74
|
+
# Install this entry in the sandbox. Fires <tt>:installing</tt>
|
75
|
+
# and <tt>:installed</tt>.
|
61
76
|
|
62
77
|
def install
|
63
78
|
old = Gem.sources.dup
|
64
79
|
|
65
80
|
begin
|
66
|
-
|
81
|
+
fire :installing, :installed do
|
82
|
+
installer = Gem::DependencyInstaller.new :development => false,
|
83
|
+
:generate_rdoc => false, :generate_ri => false,
|
84
|
+
:install_dir => @sandbox.path
|
67
85
|
|
68
|
-
|
69
|
-
|
70
|
-
:install_dir => @sandbox.path
|
86
|
+
Gem.sources += Array(options[:source]) if options[:source]
|
87
|
+
Gem::Command.build_args = Array(options[:args]) if options[:args]
|
71
88
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
installer.install @file || name, requirement
|
89
|
+
installer.install @file || name, requirement
|
90
|
+
end
|
76
91
|
ensure
|
77
92
|
Gem.sources = old
|
78
93
|
Gem::Command.build_args = nil
|
@@ -92,14 +107,22 @@ module Isolate
|
|
92
107
|
name == spec.name and requirement.satisfied_by? spec.version
|
93
108
|
end
|
94
109
|
|
110
|
+
# The Gem::Specification for this entry.
|
111
|
+
|
112
|
+
def specification
|
113
|
+
Gem.source_index.find_name(name, requirement).first
|
114
|
+
end
|
115
|
+
|
95
116
|
# Updates this entry's environments, options, and
|
96
117
|
# requirement. Environments and options are merged, requirement is
|
97
|
-
# replaced.
|
118
|
+
# replaced. Fires <tt>:updating</tt> and <tt>:updated</tt>.
|
98
119
|
|
99
120
|
def update *reqs
|
100
|
-
|
101
|
-
|
102
|
-
|
121
|
+
fire :updating, :updated do
|
122
|
+
@environments |= @sandbox.environments
|
123
|
+
@options.merge! reqs.pop if Hash === reqs.last
|
124
|
+
@requirement = Gem::Requirement.new reqs unless reqs.empty?
|
125
|
+
end
|
103
126
|
|
104
127
|
self
|
105
128
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Isolate
|
2
|
+
|
3
|
+
# A simple way to watch and extend the Isolate lifecycle.
|
4
|
+
#
|
5
|
+
# Isolate::Events.watch Isolate::Sandbox, :initialized do |sandbox|
|
6
|
+
# puts "A sandbox just got initialized: #{sandbox}"
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
# Read the source for Isolate::Sandbox and Isolate::Entry to see
|
10
|
+
# what sort of events are fired.
|
11
|
+
|
12
|
+
module Events
|
13
|
+
|
14
|
+
# Watch for an event called +name+ from an instance of
|
15
|
+
# +klass+. +block+ will be called when the event occurs. Block
|
16
|
+
# args vary by event, but usually an instance of the relevant
|
17
|
+
# class is passed.
|
18
|
+
|
19
|
+
def self.watch klass, name, &block
|
20
|
+
watchers[[klass, name]] << block
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.fire klass, name, *args #:nodoc:
|
24
|
+
watchers[[klass, name]].each do |block|
|
25
|
+
block[*args]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.watchers #:nodoc:
|
30
|
+
@watchers ||= Hash.new { |h, k| h[k] = [] }
|
31
|
+
end
|
32
|
+
|
33
|
+
def fire name, after = nil, *args, &block #:nodoc:
|
34
|
+
Isolate::Events.fire self.class, name, *args
|
35
|
+
|
36
|
+
if after && block_given?
|
37
|
+
yield self
|
38
|
+
Isolate::Events.fire self.class, after, *args
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/isolate/rake.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
namespace :isolate do
|
2
2
|
desc "Show current isolated environment."
|
3
|
-
task :
|
3
|
+
task :env do
|
4
4
|
require "pathname"
|
5
5
|
|
6
6
|
sandbox = Isolate.sandbox
|
@@ -9,10 +9,10 @@ namespace :isolate do
|
|
9
9
|
files = sandbox.files.map { |f| Pathname(f) }
|
10
10
|
|
11
11
|
puts
|
12
|
-
puts "
|
12
|
+
puts " path: #{path}"
|
13
13
|
puts " env: #{Isolate.env}"
|
14
14
|
|
15
|
-
files.
|
15
|
+
files.map! { |f| f.absolute? ? f.relative_path_from(here) : f }
|
16
16
|
puts " files: #{files.join ', '}"
|
17
17
|
puts
|
18
18
|
|
@@ -45,4 +45,26 @@ namespace :isolate do
|
|
45
45
|
task :sh, [:command] do |t, args|
|
46
46
|
exec args.command || ENV["SHELL"]
|
47
47
|
end
|
48
|
+
|
49
|
+
desc "Which isolated gems have updates available?"
|
50
|
+
task :stale do
|
51
|
+
require "rubygems/source_index"
|
52
|
+
require "rubygems/spec_fetcher"
|
53
|
+
|
54
|
+
index = Gem::SourceIndex.new
|
55
|
+
index.add_specs *Isolate.sandbox.entries.map { |e| e.specification }
|
56
|
+
|
57
|
+
outdated = index.outdated.map do |n|
|
58
|
+
Isolate.sandbox.entries.find { |e| e.name == n }
|
59
|
+
end
|
60
|
+
|
61
|
+
outdated.sort_by { |e| e.name }.each do |entry|
|
62
|
+
local = entry.specification.version
|
63
|
+
dep = Gem::Dependency.new entry.name, ">= #{local}"
|
64
|
+
remotes = Gem::SpecFetcher.fetcher.fetch dep
|
65
|
+
remote = remotes.last.first.version
|
66
|
+
|
67
|
+
puts "#{entry.name} (#{local} < #{remote})"
|
68
|
+
end
|
69
|
+
end
|
48
70
|
end
|
data/lib/isolate/sandbox.rb
CHANGED
@@ -1,17 +1,26 @@
|
|
1
1
|
require "fileutils"
|
2
2
|
require "isolate/entry"
|
3
|
+
require "isolate/events"
|
3
4
|
require "rbconfig"
|
4
5
|
require "rubygems/defaults"
|
5
6
|
require "rubygems/uninstaller"
|
6
7
|
|
7
8
|
module Isolate
|
9
|
+
|
10
|
+
# An isolated environment. This class exposes lifecycle events for
|
11
|
+
# extension, see Isolate::Events for more information.
|
12
|
+
|
8
13
|
class Sandbox
|
14
|
+
include Events
|
15
|
+
|
9
16
|
attr_reader :entries # :nodoc:
|
10
17
|
attr_reader :environments # :nodoc:
|
11
18
|
attr_reader :files # :nodoc:
|
12
19
|
|
13
|
-
# Create a new Isolate instance. See Isolate.
|
14
|
-
# API. You probably don't want to use this
|
20
|
+
# Create a new Isolate::Sandbox instance. See Isolate.now! for the
|
21
|
+
# most common use of the API. You probably don't want to use this
|
22
|
+
# constructor directly. Fires <tt>:initializing</tt> and
|
23
|
+
# <tt>:initialized</tt>.
|
15
24
|
|
16
25
|
def initialize options = {}, &block
|
17
26
|
@enabled = false
|
@@ -22,6 +31,8 @@ module Isolate
|
|
22
31
|
|
23
32
|
file, local = nil
|
24
33
|
|
34
|
+
fire :initializing
|
35
|
+
|
25
36
|
unless FalseClass === options[:file]
|
26
37
|
file = options[:file] || Dir["{Isolate,config/isolate.rb}"].first
|
27
38
|
local = "#{file}.local" if file
|
@@ -36,6 +47,7 @@ module Isolate
|
|
36
47
|
end
|
37
48
|
|
38
49
|
load local if local && File.exist?(local)
|
50
|
+
fire :initialized
|
39
51
|
end
|
40
52
|
|
41
53
|
# Activate this set of isolated entries, respecting an optional
|
@@ -44,10 +56,12 @@ module Isolate
|
|
44
56
|
# everything, and removes any superfluous gem (again, if
|
45
57
|
# necessary). If +environment+ isn't specified, +ISOLATE_ENV+,
|
46
58
|
# +RAILS_ENV+, and +RACK_ENV+ are checked before falling back to
|
47
|
-
# <tt>"development"</tt>.
|
59
|
+
# <tt>"development"</tt>. Fires <tt>:activating</tt> and
|
60
|
+
# <tt>:activated</tt>.
|
48
61
|
|
49
62
|
def activate environment = nil
|
50
63
|
enable unless enabled?
|
64
|
+
fire :activating
|
51
65
|
|
52
66
|
env = (environment || Isolate.env).to_s
|
53
67
|
|
@@ -58,38 +72,43 @@ module Isolate
|
|
58
72
|
end
|
59
73
|
|
60
74
|
cleanup if cleanup?
|
75
|
+
fire :activated
|
61
76
|
|
62
77
|
self
|
63
78
|
end
|
64
79
|
|
65
80
|
def cleanup # :nodoc:
|
81
|
+
fire :cleaning
|
82
|
+
|
66
83
|
activated = Gem.loaded_specs.values.map { |s| s.full_name }
|
67
84
|
available = Gem.source_index.gems.values.sort
|
68
85
|
|
69
86
|
extra = available.reject do |spec|
|
70
87
|
active = activated.include? spec.full_name
|
71
|
-
entry = entries.
|
88
|
+
entry = entries.find { |e| e.matches_spec? spec }
|
72
89
|
system = !spec.loaded_from.include?(path)
|
73
90
|
|
74
91
|
active or entry or system
|
75
92
|
end
|
76
93
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
format = "[%0#{padding}d/%s] Nuking %s."
|
94
|
+
unless extra.empty?
|
95
|
+
padding = Math.log10(extra.size).to_i + 1
|
96
|
+
format = "[%0#{padding}d/%s] Nuking %s."
|
81
97
|
|
82
|
-
|
83
|
-
|
98
|
+
extra.each_with_index do |e, i|
|
99
|
+
log format % [i + 1, extra.size, e.full_name]
|
84
100
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
101
|
+
Gem::DefaultUserInteraction.use_ui Gem::SilentUI.new do
|
102
|
+
Gem::Uninstaller.new(e.name,
|
103
|
+
:version => e.version,
|
104
|
+
:ignore => true,
|
105
|
+
:executables => true,
|
106
|
+
:install_dir => path).uninstall
|
107
|
+
end
|
91
108
|
end
|
92
109
|
end
|
110
|
+
|
111
|
+
fire :cleaned
|
93
112
|
end
|
94
113
|
|
95
114
|
def cleanup?
|
@@ -98,9 +117,11 @@ module Isolate
|
|
98
117
|
|
99
118
|
def disable &block
|
100
119
|
return self if not enabled?
|
120
|
+
fire :disabling
|
101
121
|
|
102
122
|
ENV["GEM_PATH"] = @old_gem_path
|
103
123
|
ENV["GEM_HOME"] = @old_gem_home
|
124
|
+
ENV["ISOLATED"] = @old_isolated
|
104
125
|
ENV["PATH"] = @old_path
|
105
126
|
ENV["RUBYOPT"] = @old_ruby_opt
|
106
127
|
|
@@ -109,6 +130,8 @@ module Isolate
|
|
109
130
|
@enabled = false
|
110
131
|
|
111
132
|
Isolate.refresh
|
133
|
+
fire :disabled
|
134
|
+
|
112
135
|
begin; return yield ensure enable end if block_given?
|
113
136
|
|
114
137
|
self
|
@@ -116,9 +139,11 @@ module Isolate
|
|
116
139
|
|
117
140
|
def enable # :nodoc:
|
118
141
|
return self if enabled?
|
142
|
+
fire :enabling
|
119
143
|
|
120
144
|
@old_gem_path = ENV["GEM_PATH"]
|
121
145
|
@old_gem_home = ENV["GEM_HOME"]
|
146
|
+
@old_isolated = ENV["ISOLATED"]
|
122
147
|
@old_path = ENV["PATH"]
|
123
148
|
@old_ruby_opt = ENV["RUBYOPT"]
|
124
149
|
@old_load_path = $LOAD_PATH.dup
|
@@ -151,10 +176,13 @@ module Isolate
|
|
151
176
|
ENV["PATH"] = [bin, ENV["PATH"]].join File::PATH_SEPARATOR
|
152
177
|
end
|
153
178
|
|
179
|
+
ENV["ISOLATED"] = path
|
180
|
+
|
154
181
|
Isolate.refresh
|
155
182
|
Gem.path.unshift path if system?
|
156
183
|
|
157
184
|
@enabled = true
|
185
|
+
fire :enabled
|
158
186
|
|
159
187
|
self
|
160
188
|
end
|
@@ -174,12 +202,14 @@ module Isolate
|
|
174
202
|
@environments = old
|
175
203
|
end
|
176
204
|
|
205
|
+
alias_method :env, :environment
|
206
|
+
|
177
207
|
# Express a gem dependency. Works pretty much like RubyGems' +gem+
|
178
208
|
# method, but respects +environment+ and doesn't activate 'til
|
179
209
|
# later.
|
180
210
|
|
181
211
|
def gem name, *requirements
|
182
|
-
entry = entries.
|
212
|
+
entry = entries.find { |e| e.name == name }
|
183
213
|
return entry.update(*requirements) if entry
|
184
214
|
|
185
215
|
entries << entry = Entry.new(self, name, *requirements)
|
@@ -187,22 +217,26 @@ module Isolate
|
|
187
217
|
end
|
188
218
|
|
189
219
|
def install environment # :nodoc:
|
220
|
+
fire :installing
|
221
|
+
|
190
222
|
installable = entries.select do |e|
|
191
223
|
!Gem.available?(e.name, *e.requirement.as_list) &&
|
192
224
|
e.matches?(environment)
|
193
225
|
end
|
194
226
|
|
195
|
-
|
227
|
+
unless installable.empty?
|
228
|
+
padding = Math.log10(installable.size).to_i + 1
|
229
|
+
format = "[%0#{padding}d/%s] Isolating %s (%s)."
|
196
230
|
|
197
|
-
|
198
|
-
|
231
|
+
installable.each_with_index do |entry, i|
|
232
|
+
log format % [i + 1, installable.size, entry.name, entry.requirement]
|
233
|
+
entry.install
|
234
|
+
end
|
199
235
|
|
200
|
-
|
201
|
-
log format % [i + 1, installable.size, entry.name, entry.requirement]
|
202
|
-
entry.install
|
236
|
+
Gem.source_index.refresh!
|
203
237
|
end
|
204
238
|
|
205
|
-
|
239
|
+
fire :installed
|
206
240
|
|
207
241
|
self
|
208
242
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "isolate/events"
|
2
|
+
require "isolate/test"
|
3
|
+
|
4
|
+
class TestIsolateEvents < Isolate::Test
|
5
|
+
include Isolate::Events
|
6
|
+
|
7
|
+
def setup
|
8
|
+
Isolate::Events.watchers.clear
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_self_watch
|
13
|
+
b = lambda {}
|
14
|
+
Isolate::Events.watch String, :foo, &b
|
15
|
+
assert_equal [b], Isolate::Events.watchers[[String, :foo]]
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_fire
|
19
|
+
count = 0
|
20
|
+
|
21
|
+
Isolate::Events.watch self.class, :increment do
|
22
|
+
count += 1
|
23
|
+
end
|
24
|
+
|
25
|
+
fire :increment
|
26
|
+
assert_equal 1, count
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_fire_block
|
30
|
+
count = 0
|
31
|
+
|
32
|
+
[:increment, :incremented].each do |name|
|
33
|
+
Isolate::Events.watch self.class, name do
|
34
|
+
count += 1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
fire :increment, :incremented do |x|
|
39
|
+
assert_same self, x
|
40
|
+
end
|
41
|
+
|
42
|
+
assert_equal 2, count
|
43
|
+
end
|
44
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: isolate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 1923832045
|
5
5
|
prerelease: true
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 0
|
9
9
|
- 0
|
10
10
|
- pre
|
11
|
-
-
|
12
|
-
version: 2.0.0.pre.
|
11
|
+
- 2
|
12
|
+
version: 2.0.0.pre.2
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- John Barnette
|
@@ -18,7 +18,7 @@ autorequire:
|
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
20
|
|
21
|
-
date: 2010-05-
|
21
|
+
date: 2010-05-07 00:00:00 -07:00
|
22
22
|
default_executable:
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
@@ -45,11 +45,11 @@ dependencies:
|
|
45
45
|
requirements:
|
46
46
|
- - ~>
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
hash:
|
48
|
+
hash: 3
|
49
49
|
segments:
|
50
50
|
- 1
|
51
|
-
-
|
52
|
-
version: "1.
|
51
|
+
- 6
|
52
|
+
version: "1.6"
|
53
53
|
type: :development
|
54
54
|
version_requirements: *id002
|
55
55
|
- !ruby/object:Gem::Dependency
|
@@ -70,7 +70,7 @@ dependencies:
|
|
70
70
|
version_requirements: *id003
|
71
71
|
description: |-
|
72
72
|
Isolate is a very simple RubyGems sandbox. It provides a way to
|
73
|
-
express and install your
|
73
|
+
express and automatically install your project's Gem dependencies.
|
74
74
|
email:
|
75
75
|
- jbarnette@rubyforge.org
|
76
76
|
- ryand-ruby@zenspider.com
|
@@ -91,6 +91,7 @@ files:
|
|
91
91
|
- lib/hoe/isolate.rb
|
92
92
|
- lib/isolate.rb
|
93
93
|
- lib/isolate/entry.rb
|
94
|
+
- lib/isolate/events.rb
|
94
95
|
- lib/isolate/now.rb
|
95
96
|
- lib/isolate/rake.rb
|
96
97
|
- lib/isolate/sandbox.rb
|
@@ -104,6 +105,7 @@ files:
|
|
104
105
|
- test/isolate/test.rb
|
105
106
|
- test/test_isolate.rb
|
106
107
|
- test/test_isolate_entry.rb
|
108
|
+
- test/test_isolate_events.rb
|
107
109
|
- test/test_isolate_sandbox.rb
|
108
110
|
has_rdoc: true
|
109
111
|
homepage: http://github.com/jbarnette/isolate
|
@@ -147,4 +149,5 @@ summary: Isolate is a very simple RubyGems sandbox
|
|
147
149
|
test_files:
|
148
150
|
- test/test_isolate.rb
|
149
151
|
- test/test_isolate_entry.rb
|
152
|
+
- test/test_isolate_events.rb
|
150
153
|
- test/test_isolate_sandbox.rb
|