bundler08 0.8.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/LICENSE +20 -0
- data/README.markdown +284 -0
- data/Rakefile +81 -0
- data/lib/bundler08.rb +49 -0
- data/lib/bundler08/bundle.rb +314 -0
- data/lib/bundler08/cli.rb +89 -0
- data/lib/bundler08/commands/bundle_command.rb +83 -0
- data/lib/bundler08/commands/exec_command.rb +36 -0
- data/lib/bundler08/dependency.rb +62 -0
- data/lib/bundler08/dsl.rb +182 -0
- data/lib/bundler08/environment.rb +87 -0
- data/lib/bundler08/finder.rb +51 -0
- data/lib/bundler08/gem_bundle.rb +11 -0
- data/lib/bundler08/gem_ext.rb +34 -0
- data/lib/bundler08/remote_specification.rb +53 -0
- data/lib/bundler08/resolver.rb +250 -0
- data/lib/bundler08/runtime.rb +2 -0
- data/lib/bundler08/source.rb +365 -0
- data/lib/bundler08/templates/Gemfile +72 -0
- data/lib/bundler08/templates/app_script.erb +3 -0
- data/lib/bundler08/templates/environment.erb +156 -0
- data/lib/bundler08/templates/environment_picker.erb +4 -0
- data/lib/rubygems_plugin.rb +6 -0
- metadata +81 -0
@@ -0,0 +1,89 @@
|
|
1
|
+
require "optparse"
|
2
|
+
|
3
|
+
module Bundler
|
4
|
+
class CLI
|
5
|
+
def self.run(command, options = {})
|
6
|
+
new(options).run(command)
|
7
|
+
rescue DefaultManifestNotFound => e
|
8
|
+
Bundler.logger.error "Could not find a Gemfile to use"
|
9
|
+
exit 3
|
10
|
+
rescue InvalidEnvironmentName => e
|
11
|
+
Bundler.logger.error "Gemfile error: #{e.message}"
|
12
|
+
exit 4
|
13
|
+
rescue InvalidRepository => e
|
14
|
+
Bundler.logger.error e.message
|
15
|
+
exit 5
|
16
|
+
rescue VersionConflict => e
|
17
|
+
Bundler.logger.error e.message
|
18
|
+
exit 6
|
19
|
+
rescue GemNotFound => e
|
20
|
+
Bundler.logger.error e.message
|
21
|
+
exit 7
|
22
|
+
rescue InvalidCacheArgument => e
|
23
|
+
Bundler.logger.error e.message
|
24
|
+
exit 8
|
25
|
+
rescue SourceNotCached => e
|
26
|
+
Bundler.logger.error e.message
|
27
|
+
exit 9
|
28
|
+
rescue ManifestFileNotFound => e
|
29
|
+
Bundler.logger.error e.message
|
30
|
+
exit 10
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(options)
|
34
|
+
Bundler.mode = options[:cached] ? :local : :readwrite
|
35
|
+
@options = options
|
36
|
+
@bundle = Bundle.load(@options[:manifest])
|
37
|
+
end
|
38
|
+
|
39
|
+
def bundle
|
40
|
+
@bundle.install(@options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def cache
|
44
|
+
gemfile = @options[:cache]
|
45
|
+
|
46
|
+
if File.extname(gemfile) == ".gem"
|
47
|
+
if !File.exist?(gemfile)
|
48
|
+
raise InvalidCacheArgument, "'#{gemfile}' does not exist."
|
49
|
+
end
|
50
|
+
@bundle.cache(gemfile)
|
51
|
+
elsif File.directory?(gemfile) || gemfile.include?('/')
|
52
|
+
if !File.directory?(gemfile)
|
53
|
+
raise InvalidCacheArgument, "'#{gemfile}' does not exist."
|
54
|
+
end
|
55
|
+
gemfiles = Dir["#{gemfile}/*.gem"]
|
56
|
+
if gemfiles.empty?
|
57
|
+
raise InvalidCacheArgument, "'#{gemfile}' contains no gemfiles"
|
58
|
+
end
|
59
|
+
@bundle.cache(*gemfiles)
|
60
|
+
else
|
61
|
+
raise InvalidCacheArgument, "w0t? '#{gemfile}' means nothing to me."
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def prune
|
66
|
+
Bundler.mode = :local
|
67
|
+
@bundle.prune(@options)
|
68
|
+
end
|
69
|
+
|
70
|
+
def list
|
71
|
+
@bundle.list(@options)
|
72
|
+
end
|
73
|
+
|
74
|
+
def list_outdated
|
75
|
+
@bundle.list_outdated(@options)
|
76
|
+
end
|
77
|
+
|
78
|
+
def exec
|
79
|
+
@bundle.setup_environment
|
80
|
+
# w0t?
|
81
|
+
super(*$command)
|
82
|
+
end
|
83
|
+
|
84
|
+
def run(command)
|
85
|
+
send(command)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
class Gem::Commands::BundleCommand < Gem::Command
|
2
|
+
|
3
|
+
def initialize
|
4
|
+
super('bundle', 'Create a gem bundle based on your Gemfile', {:manifest => nil, :update => false})
|
5
|
+
|
6
|
+
add_option('-i', '--init',"Create a Gemfile") do
|
7
|
+
options[:init] = true
|
8
|
+
end
|
9
|
+
|
10
|
+
add_option('-m', '--manifest MANIFEST', "Specify the path to the manifest file") do |manifest, options|
|
11
|
+
options[:manifest] = manifest
|
12
|
+
end
|
13
|
+
|
14
|
+
add_option('-u', '--update', "Force a remote check for newer gems") do
|
15
|
+
options[:update] = true
|
16
|
+
end
|
17
|
+
|
18
|
+
add_option('--cached', "Only use cached gems when expanding the bundle") do
|
19
|
+
options[:cached] = true
|
20
|
+
end
|
21
|
+
|
22
|
+
add_option('--cache GEM', "Specify a path to a .gem file to add to the bundled gem cache") do |gem, options|
|
23
|
+
options[:cache] = gem
|
24
|
+
end
|
25
|
+
|
26
|
+
add_option('--prune-cache', "Removes all .gem files that are not a part of the bundle from the cache") do
|
27
|
+
options[:prune] = true
|
28
|
+
end
|
29
|
+
|
30
|
+
add_option('--list', "List all gems that are part of the active bundle") do
|
31
|
+
options[:list] = true
|
32
|
+
end
|
33
|
+
|
34
|
+
add_option('--list-outdated', "List all outdated gems that are part of the active bundle") do
|
35
|
+
options[:list_outdated] = true
|
36
|
+
end
|
37
|
+
|
38
|
+
add_option('-b', '--build-options OPTION_FILE', "Specify a path to a yml file with build options for binary gems") do |option_file, options|
|
39
|
+
if File.exist?(option_file)
|
40
|
+
options[:build_options] = YAML.load_file(option_file)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
add_option('--only ENV', "Only expand the given environment. To specify multiple environments, use --only multiple times.") do |env, options|
|
45
|
+
options[:only] ||= []
|
46
|
+
options[:only] << env
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def usage
|
51
|
+
"#{program_name}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def description # :nodoc:
|
55
|
+
<<-EOF
|
56
|
+
Bundle stuff
|
57
|
+
EOF
|
58
|
+
end
|
59
|
+
|
60
|
+
def execute
|
61
|
+
# Prevent the bundler from getting required unless it is actually being used
|
62
|
+
require 'bundler08'
|
63
|
+
if options[:cache]
|
64
|
+
Bundler::CLI.run(:cache, options)
|
65
|
+
elsif options[:prune]
|
66
|
+
Bundler::CLI.run(:prune, options)
|
67
|
+
elsif options[:list]
|
68
|
+
Bundler::CLI.run(:list, options)
|
69
|
+
elsif options[:list_outdated]
|
70
|
+
Bundler::CLI.run(:list_outdated, options)
|
71
|
+
elsif options[:init]
|
72
|
+
if File.exists?("Gemfile")
|
73
|
+
Bundler.logger.error "The Gemfile already exists"
|
74
|
+
else
|
75
|
+
FileUtils.cp File.expand_path("../../templates/Gemfile", __FILE__), "Gemfile"
|
76
|
+
Bundler.logger.info "Initialized Gemfile in #{Dir.pwd}"
|
77
|
+
end
|
78
|
+
else
|
79
|
+
Bundler::CLI.run(:bundle, options)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
if exec = ARGV.index("exec")
|
2
|
+
$command = ARGV[(exec + 1)..-1]
|
3
|
+
ARGV.replace ARGV[0..exec]
|
4
|
+
end
|
5
|
+
|
6
|
+
class Gem::Commands::ExecCommand < Gem::Command
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super('exec', 'Run a command in context of a gem bundle', {:manifest => nil})
|
10
|
+
|
11
|
+
add_option('-m', '--manifest MANIFEST', "Specify the path to the manifest file") do |manifest, options|
|
12
|
+
options[:manifest] = manifest
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def usage
|
17
|
+
"#{program_name} COMMAND"
|
18
|
+
end
|
19
|
+
|
20
|
+
def arguments # :nodoc:
|
21
|
+
"COMMAND command to run in context of the gem bundle"
|
22
|
+
end
|
23
|
+
|
24
|
+
def description # :nodoc:
|
25
|
+
<<-EOF.gsub(' ', '')
|
26
|
+
Run in context of a bundle
|
27
|
+
EOF
|
28
|
+
end
|
29
|
+
|
30
|
+
def execute
|
31
|
+
# Prevent the bundler from getting required unless it is actually being used
|
32
|
+
require 'bundler08'
|
33
|
+
Bundler::CLI.run(:exec, options)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Bundler
|
2
|
+
class InvalidEnvironmentName < StandardError; end
|
3
|
+
|
4
|
+
class Dependency < Gem::Dependency
|
5
|
+
attr_reader :name, :version, :require_as, :only, :except
|
6
|
+
attr_accessor :source
|
7
|
+
|
8
|
+
def initialize(name, options = {}, &block)
|
9
|
+
options.each do |k, v|
|
10
|
+
options[k.to_s] = v
|
11
|
+
end
|
12
|
+
|
13
|
+
super(name, options["version"] || ">= 0")
|
14
|
+
|
15
|
+
@require_as = options["require_as"]
|
16
|
+
@only = options["only"]
|
17
|
+
@except = options["except"]
|
18
|
+
@source = options["source"]
|
19
|
+
@block = block
|
20
|
+
|
21
|
+
if (@only && @only.include?("rubygems")) || (@except && @except.include?("rubygems"))
|
22
|
+
raise InvalidEnvironmentName, "'rubygems' is not a valid environment name"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def in?(environment)
|
27
|
+
environment = environment.to_s
|
28
|
+
|
29
|
+
return false unless !@only || @only.include?(environment)
|
30
|
+
return false if @except && @except.include?(environment)
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
def require_env(environment)
|
35
|
+
return unless in?(environment)
|
36
|
+
|
37
|
+
if @require_as
|
38
|
+
Array(@require_as).each { |file| require file }
|
39
|
+
else
|
40
|
+
begin
|
41
|
+
require name
|
42
|
+
rescue LoadError
|
43
|
+
# Do nothing
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
@block.call if @block
|
48
|
+
end
|
49
|
+
|
50
|
+
def no_bundle?
|
51
|
+
source == SystemGemSource.instance
|
52
|
+
end
|
53
|
+
|
54
|
+
def ==(o)
|
55
|
+
[name, version, require_as, only, except] ==
|
56
|
+
[o.name, o.version, o.require_as, o.only, o.except]
|
57
|
+
end
|
58
|
+
|
59
|
+
alias version version_requirements
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
module Bundler
|
2
|
+
class ManifestFileNotFound < StandardError; end
|
3
|
+
class InvalidKey < StandardError; end
|
4
|
+
class DefaultManifestNotFound < StandardError; end
|
5
|
+
|
6
|
+
class Dsl
|
7
|
+
def self.evaluate(file, bundle, environment)
|
8
|
+
builder = new(bundle, environment)
|
9
|
+
builder.instance_eval(File.read(file.to_s), file.to_s, 1)
|
10
|
+
environment
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(bundle, environment)
|
14
|
+
@bundle = bundle
|
15
|
+
@environment = environment
|
16
|
+
@directory_sources = []
|
17
|
+
@git_sources = {}
|
18
|
+
@only, @except, @directory, @git = nil, nil, nil, nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def bundle_path(path)
|
22
|
+
@bundle.path = Pathname.new(path)
|
23
|
+
end
|
24
|
+
|
25
|
+
def bin_path(path)
|
26
|
+
@bundle.bindir = Pathname.new(path)
|
27
|
+
end
|
28
|
+
|
29
|
+
def disable_rubygems
|
30
|
+
@environment.rubygems = false
|
31
|
+
end
|
32
|
+
|
33
|
+
def disable_system_gems
|
34
|
+
@environment.system_gems = false
|
35
|
+
end
|
36
|
+
|
37
|
+
def source(source)
|
38
|
+
source = GemSource.new(@bundle, :uri => source)
|
39
|
+
unless @environment.sources.include?(source)
|
40
|
+
@environment.add_source(source)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def only(*env)
|
45
|
+
old, @only = @only, _combine_only(env)
|
46
|
+
yield
|
47
|
+
@only = old
|
48
|
+
end
|
49
|
+
|
50
|
+
def except(*env)
|
51
|
+
old, @except = @except, _combine_except(env)
|
52
|
+
yield
|
53
|
+
@except = old
|
54
|
+
end
|
55
|
+
|
56
|
+
def directory(path, options = {})
|
57
|
+
raise DirectorySourceError, "cannot nest calls to directory or git" if @directory || @git
|
58
|
+
@directory = DirectorySource.new(@bundle, options.merge(:location => path))
|
59
|
+
@directory_sources << @directory
|
60
|
+
@environment.add_priority_source(@directory)
|
61
|
+
retval = yield if block_given?
|
62
|
+
@directory = nil
|
63
|
+
retval
|
64
|
+
end
|
65
|
+
|
66
|
+
def git(uri, options = {})
|
67
|
+
raise DirectorySourceError, "cannot nest calls to directory or git" if @directory || @git
|
68
|
+
@git = GitSource.new(@bundle, options.merge(:uri => uri))
|
69
|
+
@git_sources[uri] = @git
|
70
|
+
@environment.add_priority_source(@git)
|
71
|
+
retval = yield if block_given?
|
72
|
+
@git = nil
|
73
|
+
retval
|
74
|
+
end
|
75
|
+
|
76
|
+
def clear_sources
|
77
|
+
@environment.clear_sources
|
78
|
+
end
|
79
|
+
|
80
|
+
def gem(name, *args)
|
81
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
82
|
+
version = args.last
|
83
|
+
|
84
|
+
keys = :vendored_at, :path, :only, :except, :git, :path, :bundle, :require_as, :tag, :branch, :ref
|
85
|
+
unless (invalid = options.keys - keys).empty?
|
86
|
+
raise InvalidKey, "Only #{keys.join(", ")} are valid options to #gem. You used #{invalid.join(", ")}"
|
87
|
+
end
|
88
|
+
|
89
|
+
if path = options.delete(:vendored_at)
|
90
|
+
options[:path] = path
|
91
|
+
warn "The :vendored_at option is deprecated. Use :path instead.\nFrom #{caller[0]}"
|
92
|
+
end
|
93
|
+
|
94
|
+
options[:only] = _combine_only(options[:only] || options["only"])
|
95
|
+
options[:except] = _combine_except(options[:except] || options["except"])
|
96
|
+
|
97
|
+
dep = Dependency.new(name, options.merge(:version => version))
|
98
|
+
|
99
|
+
if options.key?(:bundle) && !options[:bundle]
|
100
|
+
dep.source = SystemGemSource.new(@bundle)
|
101
|
+
elsif @git || options[:git]
|
102
|
+
dep.source = _handle_git_option(name, version, options)
|
103
|
+
elsif @directory || options[:path]
|
104
|
+
dep.source = _handle_vendored_option(name, version, options)
|
105
|
+
end
|
106
|
+
|
107
|
+
@environment.dependencies << dep
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def _version?(version)
|
113
|
+
version && Gem::Version.new(version) rescue false
|
114
|
+
end
|
115
|
+
|
116
|
+
def _handle_vendored_option(name, version, options)
|
117
|
+
dir, path = _find_directory_source(options[:path])
|
118
|
+
|
119
|
+
if dir
|
120
|
+
dir.required_specs << name
|
121
|
+
dir.add_spec(path, name, version) if _version?(version)
|
122
|
+
dir
|
123
|
+
else
|
124
|
+
directory options[:path] do
|
125
|
+
_handle_vendored_option(name, version, {})
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def _find_directory_source(path)
|
131
|
+
if @directory
|
132
|
+
return @directory, Pathname.new(path || '')
|
133
|
+
end
|
134
|
+
|
135
|
+
path = @bundle.gemfile.dirname.join(path)
|
136
|
+
|
137
|
+
@directory_sources.each do |s|
|
138
|
+
if s.location.expand_path.to_s < path.expand_path.to_s
|
139
|
+
return s, path.relative_path_from(s.location)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
nil
|
144
|
+
end
|
145
|
+
|
146
|
+
def _handle_git_option(name, version, options)
|
147
|
+
git = options[:git].to_s
|
148
|
+
ref = options[:ref] || options[:tag]
|
149
|
+
branch = options[:branch]
|
150
|
+
|
151
|
+
if source = @git || @git_sources[git]
|
152
|
+
if ref && source.ref != ref
|
153
|
+
raise GitSourceError, "'#{git}' already specified with ref: #{source.ref}"
|
154
|
+
elsif branch && source.branch != branch
|
155
|
+
raise GitSourceError, "'#{git}' already specified with branch: #{source.branch}"
|
156
|
+
end
|
157
|
+
|
158
|
+
source.required_specs << name
|
159
|
+
source.add_spec(Pathname.new(options[:path] || '.'), name, version) if _version?(version)
|
160
|
+
source
|
161
|
+
else
|
162
|
+
git(git, :ref => ref, :branch => branch) do
|
163
|
+
_handle_git_option(name, version, options)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def _combine_only(only)
|
169
|
+
return @only unless only
|
170
|
+
only = Array(only).compact.uniq.map { |o| o.to_s }
|
171
|
+
only &= @only if @only
|
172
|
+
only
|
173
|
+
end
|
174
|
+
|
175
|
+
def _combine_except(except)
|
176
|
+
return @except unless except
|
177
|
+
except = Array(except).compact.uniq.map { |o| o.to_s }
|
178
|
+
except |= @except if @except
|
179
|
+
except
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|