minigems 0.9.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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Fabien Franzen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,40 @@
1
+ MiniGems
2
+ ========
3
+
4
+ A lightweight drop-in replacement for rubygems to facilitate faster loading of
5
+ gems as well as reducing memory consumption considerably. Depending on the
6
+ amount of gems you have installed about 10-20 MB less RAM will be used, compared
7
+ to the full rubygems library version, which keeps a cache of all gems and files
8
+ referenced by them.
9
+
10
+ Minigems handles loading of required gems from your scripts. If however, other
11
+ functionality is needed, the full rubygems library will be loaded automatically
12
+ to continue normal operation.
13
+
14
+ You'll need to run 'sudo minigem setup' to get started; this will install
15
+ minigems.rb in your site_ruby directory, which makes it available to all your
16
+ ruby scripts.
17
+
18
+ MiniGems is enabled on a per-gem basis. To do so, you run 'minigem prepare', for
19
+ example, say we want the binary executables for merb-core (the 'merb' command)
20
+ to use minigems:
21
+
22
+ sudo minigem prepare merb-core
23
+
24
+ And to revert back to rubygems:
25
+
26
+ sudo minigem revert merb-core
27
+
28
+ To use minigems in your own scripts, use the following construct, instead of the
29
+ common 'require "rubygems"' statement:
30
+
31
+ begin
32
+ require 'minigems'
33
+ rescue LoadError
34
+ require 'rubygems'
35
+ end
36
+
37
+ There's currently a patch pending on RubyForge, to get minigems into the
38
+ standard, rubygems system. If you like minigems, please post a vote/followup:
39
+
40
+ http://rubyforge.org/tracker/?func=detail&atid=577&aid=21979&group_id=126
data/Rakefile ADDED
@@ -0,0 +1,83 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require File.join(File.dirname(__FILE__), 'lib', 'minigems')
4
+
5
+ ##############################################################################
6
+ # Package && release
7
+ ##############################################################################
8
+ RUBY_FORGE_PROJECT = "merb"
9
+ PROJECT_URL = "http://merbivore.com"
10
+ PROJECT_SUMMARY = "Lighweight drop-in replacement for rubygems."
11
+ PROJECT_DESCRIPTION = PROJECT_SUMMARY
12
+
13
+ GEM_AUTHOR = "Fabien Franzen"
14
+ GEM_EMAIL = "info@atelierfabien.be"
15
+
16
+ GEM_NAME = "minigems"
17
+ PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
18
+ GEM_VERSION = (Gem::MiniGems::VERSION || "0.9.0") + PKG_BUILD
19
+
20
+ RELEASE_NAME = "REL #{GEM_VERSION}"
21
+
22
+ spec = Gem::Specification.new do |s|
23
+ s.rubyforge_project = RUBY_FORGE_PROJECT
24
+ s.name = GEM_NAME
25
+ s.version = GEM_VERSION
26
+ s.platform = Gem::Platform::RUBY
27
+ s.has_rdoc = true
28
+ s.extra_rdoc_files = ["README", "LICENSE"]
29
+ s.summary = PROJECT_SUMMARY
30
+ s.description = PROJECT_DESCRIPTION
31
+ s.author = GEM_AUTHOR
32
+ s.email = GEM_EMAIL
33
+ s.homepage = PROJECT_URL
34
+ s.bindir = "bin"
35
+ s.executables = %w( minigem )
36
+ s.require_path = "lib"
37
+ s.files = %w(LICENSE README Rakefile) + Dir.glob("{lib,bin,spec}/**/*")
38
+ s.post_install_message = "Run 'minigem' for instructions on how to proceed."
39
+ end
40
+
41
+ def sudo
42
+ ENV['MERB_SUDO'] ||= "sudo"
43
+ sudo = windows? ? "" : ENV['MERB_SUDO']
44
+ end
45
+
46
+ def windows?
47
+ (PLATFORM =~ /win32|cygwin/) rescue nil
48
+ end
49
+
50
+ def install_home
51
+ ENV['GEM_HOME'] ? "-i #{ENV['GEM_HOME']}" : ""
52
+ end
53
+
54
+ Rake::GemPackageTask.new(spec) do |pkg|
55
+ pkg.gem_spec = spec
56
+ end
57
+
58
+ desc "removes any generated content"
59
+ task :clean do
60
+ FileUtils.rm_rf "clobber/*"
61
+ FileUtils.rm_rf "pkg/*"
62
+ end
63
+
64
+ desc "create a gemspec file"
65
+ task :make_spec do
66
+ File.open("#{GEM}.gemspec", "w") do |file|
67
+ file.puts spec.to_ruby
68
+ end
69
+ end
70
+
71
+ desc "Install the gem"
72
+ task :install => [:clean, :package] do
73
+ sh %{#{sudo} gem install #{install_home} pkg/#{GEM_NAME}-#{GEM_VERSION} --no-wrapper --no-update-sources --no-rdoc --no-ri}
74
+ end
75
+
76
+ namespace :jruby do
77
+
78
+ desc "Run :package and install the resulting .gem with jruby"
79
+ task :install => :package do
80
+ sh %{#{sudo} jruby -S gem install #{install_home} pkg/#{GEM_NAME}-#{GEM_VERSION}.gem --no-wrapper --no-rdoc --no-ri}
81
+ end
82
+
83
+ end
data/bin/minigem ADDED
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'minigems/script_helper'
4
+
5
+ include Gem::MiniGems::ScriptHelper
6
+
7
+ if ARGV.empty? || %w[-H --help].detect { |o| ARGV.index(o) }
8
+ # Show some usage information.
9
+ program = File.basename($0)
10
+ puts "Usage:"
11
+ puts " #{program} setup"
12
+ puts " #{program} prepare GEMNAME [GEMNAME ...]"
13
+ puts " #{program} revert GEMNAME [GEMNAME ...]"
14
+ puts " #{program} install GEMNAME [GEMNAME ...] [options] -- --build-flags [options]"
15
+ puts " #{program} update GEMNAME [GEMNAME ...] [options]"
16
+ puts " #{program} <command> GEMNAME [GEMNAME ...] [options]"
17
+ puts " "
18
+ puts "Description:"
19
+ puts " Manage 'minigems': a lightweight drop-in replacement for the rubygems"
20
+ puts " to facilitate faster loading of gems as well as reducing memory"
21
+ puts " consumption considerably. Depending on the amount of gems you have"
22
+ puts " installed about 10-20 MB less RAM will be used, compared to the full"
23
+ puts " rubygems library version, which keeps a cache of all gems and files"
24
+ puts " referenced by them."
25
+ puts " "
26
+ puts " Minigems handles loading of required gems from your scripts. If however,"
27
+ puts " other functionality is needed, the full rubygems library will be loaded"
28
+ puts " automatically to continue normal operation."
29
+ puts " "
30
+ puts " To use minigems in your own scripts, use the following construct,"
31
+ puts " instead of the common 'require \"rubygems\"' statement:"
32
+ puts " "
33
+ puts " begin"
34
+ puts " require 'minigems'"
35
+ puts " rescue LoadError"
36
+ puts " require 'rubygems'"
37
+ puts " end"
38
+ puts " "
39
+ puts "Options:"
40
+ puts " -H, --help Show this message and quit."
41
+ puts " -v, --version Show the program version number and quit."
42
+ elsif ARGV[0] == 'setup'
43
+ # Install minigems.rb in the ruby search path.
44
+ ensure_in_load_path!(true)
45
+ elsif ARGV[0] == 'uninstall'
46
+ command = ARGV.shift.to_sym # skip command argument
47
+ # Uninstall minigems.rb from the ruby search path.
48
+ remove_minigems! if ARGV.empty?
49
+ # Remove any gems that have been specified.
50
+ unless ARGV.empty?
51
+ cmd = Gem::GemRunner.new.run_command(command, ARGV)
52
+ cmd.get_all_referenced_gem_specs.each do |gemspec|
53
+ adapt_executables_for(gemspec)
54
+ end
55
+ end
56
+ elsif ARGV[0] == 'prepare'
57
+ # Adapt a gems' executable wrapper to use minigems.
58
+ ARGV.shift # skip prepare command argument
59
+ ensure_in_load_path!(ARGV.empty?)
60
+ ARGV.each do |gem_name|
61
+ next unless (gem_spec = Gem.source_index.find_name(gem_name).sort_by { |g| g.version }.last)
62
+ adapt_executables_for(gem_spec)
63
+ end
64
+ elsif ARGV[0] == 'revert'
65
+ # Adapt a gems' executable wrapper to use rubygems.
66
+ ARGV.shift # skip prepare command argument
67
+ ensure_in_load_path!(ARGV.empty?)
68
+ ARGV.each do |gem_name|
69
+ next unless (gem_spec = Gem.source_index.find_name(gem_name).sort_by { |g| g.version }.last)
70
+ revert_executables_for(gem_spec)
71
+ end
72
+ elsif ARGV[0] == 'install' || ARGV[0] == 'update'
73
+ # Install or update a rubygem and prepare it for minigems.
74
+ command = ARGV.shift.to_sym # skip command argument
75
+ ensure_in_load_path!(ARGV.empty?)
76
+ # Remove any gems that have been specified.
77
+ unless ARGV.empty?
78
+ cmd = Gem::GemRunner.new.run_command(command, ARGV)
79
+ cmd.get_all_referenced_gem_specs.each do |gemspec|
80
+ adapt_executables_for(gemspec)
81
+ end
82
+ end
83
+ else
84
+ # Proxy to rubygems for any other command.
85
+ #
86
+ # We need to preserve the original ARGV to use for passing gem options
87
+ # to source gems. If there is a -- in the line, strip all options after
88
+ # it...its for the source building process.
89
+ args = !ARGV.include?("--") ? ARGV.clone : ARGV[0...ARGV.index("--")]
90
+ Gem::GemRunner.new.run(args)
91
+ end
data/lib/minigems.rb ADDED
@@ -0,0 +1,267 @@
1
+ module Gem
2
+ module MiniGems
3
+ VERSION = "0.9.0"
4
+
5
+ # The next line needs to be kept exactly as shown; it's being replaced
6
+ # during minigems installation.
7
+ FULL_RUBYGEMS_METHODS = []
8
+
9
+ end
10
+ end
11
+
12
+ # Enable minigems unless rubygems has already loaded.
13
+ unless $LOADED_FEATURES.include?("rubygems.rb")
14
+
15
+ # Prevent full rubygems from loading
16
+ $LOADED_FEATURES << "rubygems.rb"
17
+ require "rubygems/version"
18
+ require "rubygems/rubygems_version"
19
+ require "rubygems/requirement"
20
+ require "rubygems/dependency"
21
+ require "rubygems/specification"
22
+ require "rbconfig"
23
+
24
+ module Kernel
25
+
26
+ def gem(name, *versions)
27
+ Gem.activate(name, *versions)
28
+ end
29
+
30
+ alias :gem_original_require :require
31
+
32
+ # We replace Ruby's require with our own, which is capable of
33
+ # loading gems on demand.
34
+ #
35
+ # When you call <tt>require 'x'</tt>, this is what happens:
36
+ # * If the file can be loaded from the existing Ruby loadpath, it
37
+ # is.
38
+ # * Otherwise, installed gems are searched for a file that matches.
39
+ # If it's found in gem 'y', that gem is activated (added to the
40
+ # loadpath).
41
+ #
42
+ # The normal <tt>require</tt> functionality of returning false if
43
+ # that file has already been loaded is preserved.
44
+ #
45
+ def require(path) # :nodoc:
46
+ gem_original_require path
47
+ rescue LoadError => load_error
48
+ if load_error.message =~ /#{Regexp.escape path}\z/ && Gem.activate(path)
49
+ gem_original_require(path)
50
+ else
51
+ raise load_error
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ module Gem
58
+
59
+ CORE_GEM_METHODS = Gem.methods(false)
60
+
61
+ class Exception < RuntimeError; end
62
+
63
+ class LoadError < ::LoadError
64
+ attr_accessor :name, :version_requirement
65
+ end
66
+
67
+ # Whether minigems is being used or full rubygems has taken over.
68
+ def self.minigems?
69
+ not const_defined?(:SourceIndex)
70
+ end
71
+
72
+ # Keep track of loaded gems, maps gem name to full_name.
73
+ def self.loaded_gems
74
+ @loaded_gems ||= {}
75
+ end
76
+
77
+ # Refresh the current 'cached' gems - in this case
78
+ # just the list of loaded gems.
79
+ def self.refresh
80
+ self.loaded_gems.clear
81
+ end
82
+
83
+ # See if a given gem is available.
84
+ def self.available?(name, *version_requirements)
85
+ version_requirements = Gem::Requirement.default if version_requirements.empty?
86
+ gem = Gem::Dependency.new(name, version_requirements)
87
+ not find(gem).nil?
88
+ end
89
+
90
+ # Activates an installed gem matching +gem+. The gem must satisfy
91
+ # +version_requirements+.
92
+ #
93
+ # Returns true if the gem is activated, false if it is already
94
+ # loaded, or an exception otherwise.
95
+ #
96
+ # Gem#activate adds the library paths in +gem+ to $LOAD_PATH. Before a Gem
97
+ # is activated its required Gems are activated. If the version information
98
+ # is omitted, the highest version Gem of the supplied name is loaded. If a
99
+ # Gem is not found that meets the version requirements or a required Gem is
100
+ # not found, a Gem::LoadError is raised.
101
+ #
102
+ # More information on version requirements can be found in the
103
+ # Gem::Requirement and Gem::Version documentation.
104
+ def self.activate(gem, *version_requirements)
105
+ if match = find(gem, *version_requirements)
106
+ # Load and initialize the gemspec
107
+ gem_spec = Gem::Specification.load(gem_path = match.first)
108
+ gem_spec.loaded_from = gem_path
109
+
110
+ # Raise an exception if the same spec has already been loaded - except for identical matches
111
+ if (already_loaded = self.loaded_gems[gem_spec.name]) && gem_spec.full_name != already_loaded
112
+ raise Gem::Exception, "can't activate #{gem_spec.name}, already activated #{already_loaded}"
113
+ # If it's an identical match, we're done activating
114
+ elsif already_loaded
115
+ return false
116
+ end
117
+
118
+ # Keep track of loaded gems - by name instead of full specs (memory!)
119
+ self.loaded_gems[gem_spec.name] = gem_spec.full_name
120
+
121
+ # Load dependent gems first
122
+ gem_spec.runtime_dependencies.each { |dep_gem| activate(dep_gem) }
123
+
124
+ # bin directory must come before library directories
125
+ gem_spec.require_paths.unshift(gem_spec.bindir) if gem_spec.bindir
126
+
127
+ # Add gem require paths to $LOAD_PATH
128
+ gem_spec.require_paths.reverse.each do |require_path|
129
+ $LOAD_PATH.unshift File.join(gem_spec.full_gem_path, require_path)
130
+ end
131
+ return true
132
+ else
133
+ unless gem.respond_to?(:name) && gem.respond_to?(:version_requirements)
134
+ gem = Gem::Dependency.new(gem, version_requirements)
135
+ end
136
+ report_activate_error(gem)
137
+ end
138
+ end
139
+
140
+ # Helper method to find all current gem paths.
141
+ #
142
+ # Find the most recent gem versions' paths just by looking at the gem's
143
+ # directory version number. This is faster than parsing gemspec files
144
+ # at the expense of being less complete when it comes to require paths.
145
+ # That's why Gem.activate actually parses gemspecs instead of directories.
146
+ def self.latest_gem_paths
147
+ lookup = {}
148
+ gem_path_sets = self.path.map { |path| [path, Dir["#{path}/gems/*"]] }
149
+ gem_path_sets.each do |root_path, gems|
150
+ unless gems.empty?
151
+ gems.each do |gem_path|
152
+ if matches = File.basename(File.basename(gem_path)).match(/^(.*?)-([\d\.]+)$/)
153
+ name, version_no = matches.captures[0,2]
154
+ version = Gem::Version.new(version_no)
155
+ if !lookup[name] || (lookup[name] && lookup[name][1] < version)
156
+ lookup[name] = [gem_path, version]
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
162
+ lookup.collect { |name,(gem_path, version)| gem_path }.sort
163
+ end
164
+
165
+ # Array of paths to search for Gems.
166
+ def self.path
167
+ @path ||= begin
168
+ paths = [ENV['GEM_PATH'] ? ENV['GEM_PATH'] : default_path]
169
+ paths << APPLE_GEM_HOME if defined?(APPLE_GEM_HOME) && !ENV['GEM_PATH']
170
+ paths
171
+ end
172
+ end
173
+
174
+ # Default gem load path.
175
+ def self.default_path
176
+ @default_path ||= if defined? RUBY_FRAMEWORK_VERSION then
177
+ File.join File.dirname(RbConfig::CONFIG["sitedir"]), 'Gems',
178
+ RbConfig::CONFIG["ruby_version"]
179
+ elsif defined? RUBY_ENGINE then
180
+ File.join RbConfig::CONFIG["libdir"], RUBY_ENGINE, 'gems',
181
+ RbConfig::CONFIG["ruby_version"]
182
+ else
183
+ File.join RbConfig::CONFIG["libdir"], 'ruby', 'gems',
184
+ RbConfig::CONFIG["ruby_version"]
185
+ end
186
+ end
187
+
188
+ # Reset the +path+ value. The next time +path+ is requested,
189
+ # the values will be calculated from scratch.
190
+ def self.clear_paths
191
+ @path = nil
192
+ end
193
+
194
+ # Catch calls to full rubygems methods - once accessed
195
+ # the current Gem methods are overridden.
196
+ def self.method_missing(m, *args, &blk)
197
+ if Gem::MiniGems::FULL_RUBYGEMS_METHODS.include?(m.to_s)
198
+ load_full_rubygems!
199
+ return send(m, *args, &blk)
200
+ end
201
+ super
202
+ end
203
+
204
+ # Catch references to full rubygems constants - once accessed
205
+ # the current Gem constants are merged.
206
+ def self.const_missing(const)
207
+ load_full_rubygems!
208
+ if Gem.const_defined?(const)
209
+ Gem.const_get(const)
210
+ else
211
+ super
212
+ end
213
+ end
214
+
215
+ protected
216
+
217
+ # Find all gem specs for the requested gem.
218
+ def self.find(gem, *version_requirements)
219
+ version_requirements = Gem::Requirement.default if version_requirements.empty?
220
+ unless gem.respond_to?(:name) && gem.respond_to?(:version_requirements)
221
+ gem = Gem::Dependency.new(gem, version_requirements)
222
+ end
223
+
224
+ gemspec_sets = self.path.map { |path| [path, Dir["#{path}/specifications/#{gem.name}-*.gemspec"]] }
225
+ versions = gemspec_sets.inject([]) do |versions, (root_path, gems)|
226
+ unless gems.empty?
227
+ gems.each do |gemspec_path|
228
+ if (version_no = gemspec_path[/-([\d\.]+)\.gemspec$/, 1]) &&
229
+ gem.version_requirements.satisfied_by?(version = Gem::Version.new(version_no))
230
+ versions << [gemspec_path, version]
231
+ end
232
+ end
233
+ end
234
+ versions
235
+ end
236
+ # Find the best (highest) matching gem version
237
+ versions.max { |a, b| a.last <=> b.last }
238
+ end
239
+
240
+ # Report a load error during activation.
241
+ def self.report_activate_error(gem)
242
+ error = Gem::LoadError.new("Could not find RubyGem #{gem.name} (#{gem.version_requirements})\n")
243
+ error.name = gem.name
244
+ error.version_requirement = gem.version_requirements
245
+ raise error
246
+ end
247
+
248
+ # Load the full rubygems suite, at which point all minigems logic
249
+ # is being overridden, so all regular methods and classes are available.
250
+ def self.load_full_rubygems!
251
+ # Clear out any minigems methods
252
+ class << self
253
+ (MINIGEMS_METHODS - CORE_GEM_METHODS).each do |method_name|
254
+ undef_method method_name
255
+ end
256
+ end
257
+ # Re-alias the 'require' method back to its original.
258
+ ::Kernel.module_eval { alias_method :require, :gem_original_require }
259
+ require $LOADED_FEATURES.delete("rubygems.rb")
260
+ end
261
+
262
+ # Record all minigems methods - except the minigems? predicate method.
263
+ MINIGEMS_METHODS = Gem.methods(false) - ["minigems?"]
264
+
265
+ end
266
+
267
+ end
@@ -0,0 +1,22 @@
1
+ SHEBANG
2
+
3
+ # This file was generated by MiniGems (standalone version).
4
+ #
5
+ # The application 'EXECUTABLE_NAME' is installed as part of a gem (GEM_NAME),
6
+ # and this file is here to facilitate running it.
7
+
8
+ begin
9
+ require 'GEM_MODE'
10
+ rescue LoadError
11
+ require 'rubygems'
12
+ end
13
+
14
+ version = ">= 0"
15
+
16
+ if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
17
+ version = $1
18
+ ARGV.shift
19
+ end
20
+
21
+ gem 'GEM_NAME', version
22
+ load 'EXECUTABLE_NAME'
@@ -0,0 +1,138 @@
1
+ require 'rubygems/gem_runner'
2
+ require 'rubygems/exceptions'
3
+ require 'rubygems/commands/install_command'
4
+ require 'rubygems/commands/update_command'
5
+ require 'fileutils'
6
+
7
+ module Gem
8
+
9
+ class GemRunner
10
+ def run_command(command_name, args)
11
+ args.unshift command_name.to_s
12
+ do_configuration(args)
13
+ cmd_manager = @command_manager_class.instance
14
+ config_args = Gem.configuration[command_name.to_s]
15
+ config_args = case config_args
16
+ when String
17
+ config_args.split ' '
18
+ else
19
+ Array(config_args)
20
+ end
21
+ Command.add_specific_extra_args(command_name, config_args)
22
+ cmd_manager.run(Gem.configuration.args)
23
+ rescue Gem::SystemExitException
24
+ cmd_manager.cmd
25
+ ensure
26
+ cmd_manager.cmd
27
+ end
28
+ end
29
+
30
+ class Command
31
+ def get_all_referenced_gem_specs
32
+ get_all_gem_names.map { |name| Gem.source_index.search(name).last }.compact
33
+ end
34
+ end
35
+
36
+ class CommandManager
37
+ attr_accessor :cmd
38
+ alias :original_find_command :find_command
39
+ def find_command(cmd_name)
40
+ self.cmd = original_find_command(cmd_name)
41
+ self.cmd
42
+ end
43
+ end
44
+
45
+ module MiniGems
46
+ module ScriptHelper
47
+
48
+ def minigems_path
49
+ @minigems_path ||= begin
50
+ if (gem_spec = Gem.source_index.find_name('minigems').sort_by { |g| g.version }.last)
51
+ gem_spec.full_gem_path
52
+ else
53
+ raise "Minigems gem not found!"
54
+ end
55
+ end
56
+ end
57
+
58
+ def adapt_executables_for(gemspec)
59
+ gemspec.executables.each do |executable|
60
+ next if executable == 'minigem' # better not modify minigem itself
61
+ if File.exists?(wrapper_path = File.join(Gem.bindir, executable))
62
+ wrapper_code = interpolate_wrapper(gemspec.name, executable)
63
+ begin
64
+ if File.open(wrapper_path, 'w') { |f| f.write(wrapper_code) }
65
+ puts "Adapted #{wrapper_path} to use minigems instead of rubygems."
66
+ else
67
+ puts "Failed to adapt #{wrapper_path} - maybe you need sudo permissions?"
68
+ end
69
+ rescue Errno::EACCES => e
70
+ puts "Failed to adapt #{wrapper_path} - maybe you need sudo permissions?"
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ def revert_executables_for(gemspec)
77
+ gemspec.executables.each do |executable|
78
+ next if executable == 'minigem' # better not modify minigem itself
79
+ if File.exists?(wrapper_path = File.join(Gem.bindir, executable))
80
+ wrapper_code = interpolate_wrapper(gemspec.name, executable, 'rubygems')
81
+ begin
82
+ if File.open(wrapper_path, 'w') { |f| f.write(wrapper_code) }
83
+ puts "Reverted #{wrapper_path} to use rubygems instead of minigems."
84
+ else
85
+ puts "Failed to revert #{wrapper_path} - maybe you need sudo permissions?"
86
+ end
87
+ rescue Errno::EACCES => e
88
+ puts "Failed to revert #{wrapper_path} - maybe you need sudo permissions?"
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ def ensure_in_load_path!(force = false)
95
+ install_path = File.join(Gem::ConfigMap[:sitelibdir], 'minigems.rb')
96
+ if force || !File.exists?(install_path)
97
+ if File.exists?(source_path = File.join(minigems_path, 'lib', 'minigems.rb'))
98
+ begin
99
+ minigems_code = File.read(source_path)
100
+ placeholder = "FULL_RUBYGEMS_METHODS = []"
101
+ replacement = "FULL_RUBYGEMS_METHODS = %w[\n "
102
+ replacement << (Gem.methods - Object.methods).sort.join("\n ")
103
+ replacement << "\n ]"
104
+ File.open(install_path, 'w') do |f|
105
+ f.write minigems_code.sub(placeholder, replacement)
106
+ end
107
+ puts "Installed minigems at #{install_path}"
108
+ rescue Errno::EACCES
109
+ puts "Could not install minigems at #{install_path} (try sudo)"
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ def remove_minigems!
116
+ if File.exists?(install_path = File.join(Gem::ConfigMap[:sitelibdir], 'minigems.rb'))
117
+ if FileUtils.rm(install_path)
118
+ puts "Succesfully removed #{install_path}"
119
+ return
120
+ end
121
+ end
122
+ rescue => e
123
+ puts e.message
124
+ puts "Could not remove #{install_path} (try sudo)"
125
+ end
126
+
127
+ def interpolate_wrapper(gem_name, executable_name, mode = 'minigems')
128
+ @template_code ||= File.read(File.join(minigems_path, 'lib', 'minigems', 'executable_wrapper'))
129
+ vars = { 'GEM_NAME' => gem_name, 'EXECUTABLE_NAME' => executable_name }
130
+ vars['SHEBANG'] = "#!/usr/bin/env " + Gem::ConfigMap[:ruby_install_name]
131
+ vars['GEM_MODE'] = mode
132
+ vars.inject(@template_code) { |str,(k,v)| str.gsub(k,v) }
133
+ end
134
+
135
+ end
136
+ end
137
+
138
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 YOUR NAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,4 @@
1
+ gem_with_lib
2
+ ============
3
+
4
+ A gem that provides...
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rubygems/specification'
4
+ require 'date'
5
+
6
+ GEM = "gem_with_lib"
7
+ GEM_VERSION = "0.0.1"
8
+ AUTHOR = "Your Name"
9
+ EMAIL = "Your Email"
10
+ HOMEPAGE = "http://example.com"
11
+ SUMMARY = "A gem that provides..."
12
+
13
+ spec = Gem::Specification.new do |s|
14
+ s.name = GEM
15
+ s.version = GEM_VERSION
16
+ s.platform = Gem::Platform::RUBY
17
+ s.has_rdoc = true
18
+ s.extra_rdoc_files = ["README", "LICENSE", 'TODO']
19
+ s.summary = SUMMARY
20
+ s.description = s.summary
21
+ s.author = AUTHOR
22
+ s.email = EMAIL
23
+ s.homepage = HOMEPAGE
24
+
25
+ # Uncomment this to add a dependency
26
+ # s.add_dependency "foo"
27
+
28
+ s.require_path = 'lib'
29
+ s.autorequire = GEM
30
+ s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{lib,specs}/**/*")
31
+ end
32
+
33
+ Rake::GemPackageTask.new(spec) do |pkg|
34
+ pkg.gem_spec = spec
35
+ end
36
+
37
+ desc "install the gem locally"
38
+ task :install => [:package] do
39
+ sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
40
+ end
41
+
42
+ desc "create a gemspec file"
43
+ task :make_spec do
44
+ File.open("#{GEM}.gemspec", "w") do |file|
45
+ file.puts spec.to_ruby
46
+ end
47
+ end
@@ -0,0 +1,4 @@
1
+ TODO:
2
+ Fix LICENSE with your name
3
+ Fix Rakefile with your name and contact info
4
+ Add your code to lib/<%= name %>.rb
@@ -0,0 +1,5 @@
1
+ module GemWithLib
2
+ VERSION = "0.0.1"
3
+ class Awesome
4
+ end
5
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 YOUR NAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,4 @@
1
+ gem_with_lib
2
+ ============
3
+
4
+ A gem that provides...
@@ -0,0 +1,48 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rubygems/specification'
4
+ require 'date'
5
+
6
+ GEM = "gem_with_lib"
7
+ GEM_VERSION = "0.0.2"
8
+ AUTHOR = "Your Name"
9
+ EMAIL = "Your Email"
10
+ HOMEPAGE = "http://example.com"
11
+ SUMMARY = "A gem that provides..."
12
+
13
+ spec = Gem::Specification.new do |s|
14
+ s.name = GEM
15
+ s.version = GEM_VERSION
16
+ s.platform = Gem::Platform::RUBY
17
+ s.has_rdoc = true
18
+ s.extra_rdoc_files = ["README", "LICENSE", 'TODO']
19
+ s.summary = SUMMARY
20
+ s.description = s.summary
21
+ s.author = AUTHOR
22
+ s.email = EMAIL
23
+ s.homepage = HOMEPAGE
24
+
25
+ # Uncomment this to add a dependency
26
+ # s.add_dependency "foo"
27
+
28
+ s.require_path = 'lib'
29
+ s.executables = %w( gem_with_lib )
30
+ s.autorequire = GEM
31
+ s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{lib,specs}/**/*")
32
+ end
33
+
34
+ Rake::GemPackageTask.new(spec) do |pkg|
35
+ pkg.gem_spec = spec
36
+ end
37
+
38
+ desc "install the gem locally"
39
+ task :install => [:package] do
40
+ sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
41
+ end
42
+
43
+ desc "create a gemspec file"
44
+ task :make_spec do
45
+ File.open("#{GEM}.gemspec", "w") do |file|
46
+ file.puts spec.to_ruby
47
+ end
48
+ end
@@ -0,0 +1,4 @@
1
+ TODO:
2
+ Fix LICENSE with your name
3
+ Fix Rakefile with your name and contact info
4
+ Add your code to lib/<%= name %>.rb
@@ -0,0 +1 @@
1
+ #!/usr/bin/env ruby
@@ -0,0 +1,5 @@
1
+ module GemWithLib
2
+ VERSION = "0.0.2"
3
+ class Awesome
4
+ end
5
+ end
@@ -0,0 +1,28 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{gem_with_lib}
3
+ s.version = "0.0.1"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Your Name"]
7
+ s.autorequire = %q{gem_with_lib}
8
+ s.date = %q{2008-08-17}
9
+ s.description = %q{A gem that provides...}
10
+ s.email = %q{Your Email}
11
+ s.extra_rdoc_files = ["README", "LICENSE", "TODO"]
12
+ s.files = ["LICENSE", "README", "Rakefile", "TODO", "lib/gem_with_lib.rb"]
13
+ s.has_rdoc = true
14
+ s.homepage = %q{http://example.com}
15
+ s.require_paths = ["lib"]
16
+ s.rubygems_version = %q{1.2.0}
17
+ s.summary = %q{A gem that provides...}
18
+
19
+ if s.respond_to? :specification_version then
20
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
21
+ s.specification_version = 2
22
+
23
+ if current_version >= 3 then
24
+ else
25
+ end
26
+ else
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{gem_with_lib}
3
+ s.version = "0.0.2"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Your Name"]
7
+ s.autorequire = %q{gem_with_lib}
8
+ s.date = %q{2008-08-19}
9
+ s.description = %q{A gem that provides...}
10
+ s.email = %q{Your Email}
11
+ s.extra_rdoc_files = ["README", "LICENSE", "TODO"]
12
+ s.files = ["LICENSE", "README", "Rakefile", "TODO", "lib/gem_with_lib.rb"]
13
+ s.has_rdoc = true
14
+ s.homepage = %q{http://example.com}
15
+ s.executables = %w( gem_with_lib )
16
+ s.require_paths = ["lib"]
17
+ s.rubygems_version = %q{1.2.0}
18
+ s.summary = %q{A gem that provides...}
19
+
20
+ if s.respond_to? :specification_version then
21
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
22
+ s.specification_version = 2
23
+
24
+ if current_version >= 3 then
25
+ else
26
+ end
27
+ else
28
+ end
29
+ end
@@ -0,0 +1,105 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'minigems')
2
+
3
+ # We can't use the spec runner, as that will already load or full gems!
4
+ gem "rspec"
5
+ require "spec"
6
+
7
+ describe Gem::MiniGems do
8
+
9
+ before do
10
+ # Setup rubygems from our spec fixtures directory
11
+ Gem.refresh
12
+ @gem_dir = File.join(File.dirname(__FILE__), "fixtures")
13
+ Gem.path.replace([@gem_dir])
14
+ end
15
+
16
+ after do
17
+ # Remove fixture load paths from $LOAD_PATH for specs
18
+ $LOAD_PATH.reject! { |path| path.index(@gem_dir) == 0 }
19
+ $LOADED_FEATURES.delete("gem_with_lib.rb")
20
+ # Make sure any loaded classes are removed
21
+ Object.send(:remove_const, "GemWithLib") if Object.const_defined?("GemWithLib")
22
+ Gem.should be_minigems
23
+ end
24
+
25
+ it "has a replaceable Gem.path" do
26
+ Gem.path.replace(["awesome"])
27
+ Gem.path.should == ["awesome"]
28
+ end
29
+
30
+ it "loads gems through the Kernel#require method" do
31
+ require("gem_with_lib").should be_true
32
+ lambda { GemWithLib::Awesome }.should_not raise_error(NameError)
33
+ GemWithLib::VERSION.should == "0.0.2"
34
+ end
35
+
36
+ it "lets you check for gem availability" do
37
+ Gem.available?("unknown_gem").should be_false
38
+ Gem.available?("gem_with_lib").should be_true
39
+ Gem.available?("gem_with_lib", "0.0.1").should be_true
40
+ Gem.available?("gem_with_lib", "0.0.2").should be_true
41
+ Gem.available?("gem_with_lib", ">0.0.1").should be_true
42
+ Gem.available?("gem_with_lib", ">0.0.2").should be_false
43
+ end
44
+
45
+ it "should raise Gem::LoadError if no matching gem was found" do
46
+ lambda { gem("unknown_gem") }.should raise_error(Gem::LoadError)
47
+ end
48
+
49
+ it "uses 'gem' to setup additional load path entries" do
50
+ gem_lib_path = File.join(@gem_dir, "gems", "gem_with_lib-0.0.2", "lib")
51
+ gem_bin_path = File.join(@gem_dir, "gems", "gem_with_lib-0.0.2", "bin")
52
+ $LOAD_PATH.should_not include(gem_lib_path)
53
+ gem("gem_with_lib").should be_true
54
+ $LOAD_PATH.first.should == gem_bin_path
55
+ $LOAD_PATH.should include(gem_lib_path)
56
+ $LOAD_PATH.select { |path| path == gem_lib_path }.length.should == 1
57
+ lambda { GemWithLib::Awesome }.should raise_error(NameError)
58
+ end
59
+
60
+ it "uses 'gem' to setup additional load path entries (for a specific gem version)" do
61
+ gem_lib_path = File.join(@gem_dir, "gems", "gem_with_lib-0.0.1", "lib")
62
+ gem_bin_path = File.join(@gem_dir, "gems", "gem_with_lib-0.0.1", "bin")
63
+ $LOAD_PATH.should_not include(gem_lib_path)
64
+ gem("gem_with_lib", "0.0.1").should be_true
65
+ $LOAD_PATH.first.should == gem_bin_path
66
+ $LOAD_PATH.should include(gem_lib_path)
67
+ end
68
+
69
+ it "uses 'gem' to setup additional load path entries (for a gem version requirement)" do
70
+ gem_lib_path = File.join(@gem_dir, "gems", "gem_with_lib-0.0.2", "lib")
71
+ gem_bin_path = File.join(@gem_dir, "gems", "gem_with_lib-0.0.2", "bin")
72
+ $LOAD_PATH.should_not include(gem_lib_path)
73
+ gem("gem_with_lib", ">0.0.1").should be_true
74
+ $LOAD_PATH.first.should == gem_bin_path
75
+ $LOAD_PATH.should include(gem_lib_path)
76
+ end
77
+
78
+ it "correctly requires a file from the load path" do
79
+ gem("gem_with_lib").should be_true
80
+ require("gem_with_lib").should be_true
81
+ lambda { GemWithLib::Awesome }.should_not raise_error(NameError)
82
+ GemWithLib::VERSION.should == "0.0.2"
83
+ end
84
+
85
+ it "returns all the latest gem versions' paths" do
86
+ Gem.latest_gem_paths.should == [File.join(@gem_dir, "gems", "gem_with_lib-0.0.2")]
87
+ end
88
+
89
+ # The following specs can only be run in isolation as they load up the
90
+ # full rubygems library - which cannot really be undone!
91
+ # Comment out the specs above, including before/after setup.
92
+
93
+ # it "should load full rubygems if an unimplemented method is called" do
94
+ # Gem.should be_minigems
95
+ # lambda { Gem.source_index }.should_not raise_error(NoMethodError)
96
+ # Gem.should_not be_minigems
97
+ # end
98
+
99
+ # it "should load full rubygems if a missing Gem constant is referenced" do
100
+ # Gem.should be_minigems
101
+ # lambda { Gem::Builder }.should_not raise_error(NameError)
102
+ # Gem.should_not be_minigems
103
+ # end
104
+
105
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: minigems
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Fabien Franzen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-09-19 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Lighweight drop-in replacement for rubygems.
17
+ email: info@atelierfabien.be
18
+ executables:
19
+ - minigem
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ - LICENSE
25
+ files:
26
+ - LICENSE
27
+ - README
28
+ - Rakefile
29
+ - lib/minigems
30
+ - lib/minigems/executable_wrapper
31
+ - lib/minigems/script_helper.rb
32
+ - lib/minigems.rb
33
+ - bin/minigem
34
+ - spec/fixtures
35
+ - spec/fixtures/cache
36
+ - spec/fixtures/cache/gem_with_lib-0.0.1.gem
37
+ - spec/fixtures/cache/gem_with_lib-0.0.2.gem
38
+ - spec/fixtures/gems
39
+ - spec/fixtures/gems/gem_with_lib-0.0.1
40
+ - spec/fixtures/gems/gem_with_lib-0.0.1/lib
41
+ - spec/fixtures/gems/gem_with_lib-0.0.1/lib/gem_with_lib.rb
42
+ - spec/fixtures/gems/gem_with_lib-0.0.1/LICENSE
43
+ - spec/fixtures/gems/gem_with_lib-0.0.1/Rakefile
44
+ - spec/fixtures/gems/gem_with_lib-0.0.1/README
45
+ - spec/fixtures/gems/gem_with_lib-0.0.1/TODO
46
+ - spec/fixtures/gems/gem_with_lib-0.0.2
47
+ - spec/fixtures/gems/gem_with_lib-0.0.2/bin
48
+ - spec/fixtures/gems/gem_with_lib-0.0.2/bin/gem_with_lib
49
+ - spec/fixtures/gems/gem_with_lib-0.0.2/lib
50
+ - spec/fixtures/gems/gem_with_lib-0.0.2/lib/gem_with_lib.rb
51
+ - spec/fixtures/gems/gem_with_lib-0.0.2/LICENSE
52
+ - spec/fixtures/gems/gem_with_lib-0.0.2/Rakefile
53
+ - spec/fixtures/gems/gem_with_lib-0.0.2/README
54
+ - spec/fixtures/gems/gem_with_lib-0.0.2/TODO
55
+ - spec/fixtures/specifications
56
+ - spec/fixtures/specifications/gem_with_lib-0.0.1.gemspec
57
+ - spec/fixtures/specifications/gem_with_lib-0.0.2.gemspec
58
+ - spec/minigems_spec.rb
59
+ has_rdoc: true
60
+ homepage: http://merbivore.com
61
+ minigems: false
62
+ post_install_message: Run 'minigem' for instructions on how to proceed.
63
+ rdoc_options: []
64
+
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ version:
79
+ requirements: []
80
+
81
+ rubyforge_project: merb
82
+ rubygems_version: 1.2.0.1874
83
+ signing_key:
84
+ specification_version: 2
85
+ summary: Lighweight drop-in replacement for rubygems.
86
+ test_files: []
87
+