Class: Bundler::Runtime
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
|
Instance Chain:
self,
SharedHelpers
|
|
| Inherits: | Object |
| Defined in: | lib/bundler/runtime.rb |
Constant Summary
-
PRUNE_CATEGORIES =
# File 'lib/bundler/runtime.rb', line 7[:cache, :git].freeze
Class Method Summary
- .new(root, definition) ⇒ Runtime constructor
- .definition_method(meth) private
Instance Attribute Summary
Instance Method Summary
- #cache(custom_path = nil, local = false)
- #clean(dry_run = false)
- #gems
- #lock(opts = {})
-
#prune(categories)
Removes the artifacts
::Bundlerkeeps for its own bookkeeping and can rebuild from the lockfile. - #prune_cache(cache_path)
- #require(*groups)
- #setup(*groups)
- #check_for_activated_spec!(spec) private
-
#expand_prune_categories(categories)
private
Anything that is not a category name is read as a boolean with Bundler's usual vocabulary, so
BUNDLE_PRUNE=1selects every category and keeps doing so as categories are added. - #prune_download_cache private
- #prune_gem_cache(resolve, cache_path) private
- #prune_git_and_path_cache(resolve, cache_path) private
- #prune_git_metadata private
- #remove_dir(dir, dry_run) private
- #setup_manpath private
SharedHelpers - Included
| #bundle_bin_path, #chdir, #checksum_for_file, #default_bundle_dir, #default_gemfile, #default_lockfile, #digest, #ensure_same_dependencies, #feature_deprecated!, #feature_removed!, | |
| #filesystem_access | Rescues permissions errors raised by file system operations (ie. |
| #gemspec_path, | |
| #glob_files_in_dir | Globs for entries matching |
| #pretty_dependency, #print_major_deprecations!, #pwd, #relative_gemfile_path, #relative_lockfile_path, #relative_path_to, #root, #set_bundle_environment, #set_env, #with_clean_git_env, #write_to_gemfile, #bundler_ruby_lib, #clean_load_path, #find_directory, #find_file, #find_gemfile, #gemfile_names, #resolve_path, #search_up, #set_bundle_variables, #set_path, #set_rubylib, #set_rubyopt, #source_root, #validate_bundle_path | |
Constructor Details
.new(root, definition) ⇒ Runtime
# File 'lib/bundler/runtime.rb', line 9
def initialize(root, definition) @root = root @definition = definition end
Class Method Details
.definition_method(meth) (private)
[ GitHub ]# File 'lib/bundler/runtime.rb', line 90
def self.definition_method(meth) define_method(meth) do raise ArgumentError, "no definition when calling Runtime##{meth}" unless @definition @definition.send(meth) end end
Instance Method Details
#cache(custom_path = nil, local = false)
[ GitHub ]# File 'lib/bundler/runtime.rb', line 111
def cache(custom_path = nil, local = false) cache_path = Bundler.app_cache(custom_path) SharedHelpers.filesystem_access(cache_path) do |p| FileUtils.mkdir_p(p) end unless File.exist?(cache_path) Bundler.ui.info "Updating files in #{Bundler.settings.app_cache_path}" specs_to_cache = if Bundler.settings[:cache_all_platforms] @definition.resolve.materialized_for_all_platforms else begin specs rescue GemNotFound if local Bundler.ui.warn "Some gems seem to be missing from your #{Bundler.settings.app_cache_path} directory." end raise end end specs_to_cache.each do |spec| next if spec.name == "bundler" source = spec.source next if source.is_a?(Source::Gemspec) if source.respond_to?(:migrate_cache) source.migrate_cache(custom_path, local: local) elsif source.respond_to?(:cache) source.cache(spec, custom_path) end end SharedHelpers.glob_files_in_dir("*/.git", cache_path.to_s).each do |git_dir| FileUtils.rm_rf(git_dir) FileUtils.touch(File.("../.bundlecache", git_dir)) end prune_cache(cache_path) unless Bundler.settings[:keep_outdated_cache] end
#check_for_activated_spec!(spec) (private)
[ GitHub ]# File 'lib/bundler/runtime.rb', line 380
def check_for_activated_spec!(spec) return unless activated_spec = Bundler.rubygems.loaded_specs(spec.name) return if activated_spec.version == spec.version suggestion = if activated_spec.default_gem? "Since #{spec.name} is a default gem, you can either remove your dependency on it" \ " or try updating to a newer version of bundler that supports #{spec.name} as a default gem." else "Prepending `bundle exec` to your command may solve this." end e = Gem::LoadError.new "You have already activated #{activated_spec.name} #{activated_spec.version}, " \ "but your Gemfile requires #{spec.name} #{spec.version}. #{suggestion}" e.name = spec.name e.requirement = Gem::Requirement.new(spec.version.to_s) raise e end
#clean(dry_run = false)
[ GitHub ]# File 'lib/bundler/runtime.rb', line 163
def clean(dry_run = false) gem_bins = SharedHelpers.glob_files_in_dir("bin/*", Gem.dir) git_dirs = SharedHelpers.glob_files_in_dir("bundler/gems/*", Gem.dir) git_cache_dirs = SharedHelpers.glob_files_in_dir("cache/bundler/git/*", Gem.dir) gem_dirs = SharedHelpers.glob_files_in_dir("gems/*", Gem.dir) gem_files = SharedHelpers.glob_files_in_dir("cache/*.gem", Gem.dir) gemspec_files = Gem::SpecificationRecord.dirs_from([Gem.dir]).flat_map do |dir| SharedHelpers.glob_files_in_dir("*.gemspec", dir) end extension_dirs = SharedHelpers.glob_files_in_dir("extensions/*/*/*", Gem.dir) + SharedHelpers.glob_files_in_dir("bundler/gems/extensions/*/*/*", Gem.dir) spec_gem_paths = [] # need to keep git sources around spec_git_paths = @definition.spec_git_paths spec_git_cache_dirs = [] spec_gem_executables = [] spec_cache_paths = [] spec_gemspec_paths = [] spec_extension_paths = [] specs_to_keep = Bundler.rubygems.add_default_gems_to(specs).values current_bundler = Bundler.rubygems.find_bundler(Bundler.gem_version) if current_bundler specs_to_keep << current_bundler end specs_to_keep.each do |spec| spec_gem_paths << spec.full_gem_path # need to check here in case gems are nested like for the rails git repo md = %r{(.bundler/gems/.-[a-f0-9]{7,12})}.match(spec.full_gem_path) spec_git_paths << md[1] if md spec_gem_executables << spec.executables.collect do |executable| e = "#{Bundler.rubygems.gem_bindir}/#{executable}" [e, "#{e}.bat"] end spec_cache_paths << spec.cache_file spec_gemspec_paths << spec.spec_file spec_extension_paths << spec.extension_dir if spec.respond_to?(:extension_dir) spec_git_cache_dirs << spec.source.cache_path.to_s if spec.source.is_a?(Bundler::Source::Git) end spec_gem_paths.uniq! spec_gem_executables.flatten! stale_gem_bins = gem_bins - spec_gem_executables stale_git_dirs = git_dirs - spec_git_paths - ["#{Gem.dir}/bundler/gems/extensions"] stale_git_cache_dirs = git_cache_dirs - spec_git_cache_dirs stale_gem_dirs = gem_dirs - spec_gem_paths stale_gem_files = gem_files - spec_cache_paths stale_gemspec_files = gemspec_files - spec_gemspec_paths stale_extension_dirs = extension_dirs - spec_extension_paths removed_stale_gem_dirs = stale_gem_dirs.collect {|dir| remove_dir(dir, dry_run) } removed_stale_git_dirs = stale_git_dirs.collect {|dir| remove_dir(dir, dry_run) } output = removed_stale_gem_dirs + removed_stale_git_dirs unless dry_run stale_files = stale_gem_bins + stale_gem_files + stale_gemspec_files stale_files.each do |file| SharedHelpers.filesystem_access(File.dirname(file)) do |_p| FileUtils.rm(file) if File.exist?(file) end end stale_dirs = stale_git_cache_dirs + stale_extension_dirs stale_dirs.each do |stale_dir| SharedHelpers.filesystem_access(stale_dir) do |dir| FileUtils.rm_rf(dir) if File.exist?(dir) end end end output end
#expand_prune_categories(categories) (private)
Anything that is not a category name is read as a boolean with Bundler's
usual vocabulary, so BUNDLE_PRUNE=1 selects every category and keeps
doing so as categories are added. That way a tool can set the flag without
tracking this list.
# File 'lib/bundler/runtime.rb', line 263
def (categories) Array(categories).flat_map do |category| name = category.to_s next name.to_sym if PRUNE_CATEGORIES.include?(name.to_sym) Settings.to_bool(name) ? PRUNE_CATEGORIES : [] end.uniq end
#gems
[ GitHub ]# File 'lib/bundler/runtime.rb', line 109
alias_method :gems, :specs
#lock(opts = {})
[ GitHub ]# File 'lib/bundler/runtime.rb', line 104
def lock(opts = {}) return if @definition.no_resolve_needed? @definition.lock(opts[:preserve_unknown_sections]) end
#prune(categories)
# File 'lib/bundler/runtime.rb', line 238
def prune(categories) categories = (categories) return if categories.empty? # Without a bundle path the cache is shared with RubyGems, so it holds gem # files Bundler never put there. if Bundler.use_system_gems? Bundler.ui.warn "The `prune` setting was ignored because this bundle installs into the system gem " \ "directory, which Bundler shares with RubyGems. Run " \ "`bundle config set --local path vendor/bundle` to prune.", wrap: true return end # Git metadata first, because resolving a checkout's install path can need # the mirror that pruning the cache removes. if categories.include?(:git) prune_download_cache if categories.include?(:cache) end
#prune_cache(cache_path)
[ GitHub ]# File 'lib/bundler/runtime.rb', line 154
def prune_cache(cache_path) SharedHelpers.filesystem_access(cache_path) do |p| FileUtils.mkdir_p(p) end unless File.exist?(cache_path) resolve = @definition.resolve prune_gem_cache(resolve, cache_path) prune_git_and_path_cache(resolve, cache_path) end
#prune_download_cache (private)
[ GitHub ]# File 'lib/bundler/runtime.rb', line 272
def prune_download_cache cache_path = File.join(Bundler.bundle_path, "cache") return unless File.exist?(cache_path) Bundler.ui.info "Removing the download cache at #{cache_path}" SharedHelpers.filesystem_access(cache_path) do |p| FileUtils.rm_rf(p) end end
#prune_gem_cache(resolve, cache_path) (private)
[ GitHub ]# File 'lib/bundler/runtime.rb', line 301
def prune_gem_cache(resolve, cache_path) cached = SharedHelpers.glob_files_in_dir("*.gem", cache_path.to_s) cached = cached.delete_if do |path| spec = Bundler.rubygems.spec_from_gem path resolve.any? do |s| s.name == spec.name && s.version == spec.version && !s.source.is_a?(Bundler::Source::Git) end end if cached.any? Bundler.ui.info "Removing outdated .gem files from #{Bundler.settings.app_cache_path}" cached.each do |path| Bundler.ui.info " * #{File.basename(path)}" begin File.delete(path) rescue Errno::ENOENT end end end end
#prune_git_and_path_cache(resolve, cache_path) (private)
[ GitHub ]# File 'lib/bundler/runtime.rb', line 326
def prune_git_and_path_cache(resolve, cache_path) cached = SharedHelpers.glob_files_in_dir("*/.bundlecache", cache_path.to_s) cached = cached.delete_if do |path| name = File.basename(File.dirname(path)) resolve.any? do |s| source = s.source source.respond_to?(:app_cache_dirname) && source.app_cache_dirname == name end end if cached.any? Bundler.ui.info "Removing outdated git and path gems from #{Bundler.settings.app_cache_path}" cached.each do |path| path = File.dirname(path) Bundler.ui.info " * #{File.basename(path)}" FileUtils.rm_rf(path) end end end
#prune_git_metadata (private)
[ GitHub ]# File 'lib/bundler/runtime.rb', line 282
def owned = "#{Bundler.install_path}#{File::SEPARATOR}" git_dirs = @definition.sources.git_sources.reject(&:local?).filter_map do |source| install_path = source.install_path.to_s next unless install_path.start_with?(owned) git_dir = File.join(install_path, ".git") git_dir if File.exist?(git_dir) end return if git_dirs.empty? Bundler.ui.info "Removing git metadata from checked out git gems" git_dirs.each do |git_dir| SharedHelpers.filesystem_access(git_dir) do |p| FileUtils.rm_rf(p) end end end
#remove_dir(dir, dry_run) (private)
[ GitHub ]# File 'lib/bundler/runtime.rb', line 362
def remove_dir(dir, dry_run) full_name = Pathname.new(dir).basename.to_s parts = full_name.split("-") name = parts[0..-2].join("-") version = parts.last output = "#{name} (#{version})" if dry_run Bundler.ui.info "Would have removed #{output}" else Bundler.ui.info "Removing #{output}" FileUtils.rm_rf(dir) end output end
#require(*groups)
[ GitHub ]# File 'lib/bundler/runtime.rb', line 42
def require(*groups) groups.map!(&:to_sym) groups = [:default] if groups.empty? dependencies = @definition.dependencies.select do |dep| # Select the dependency if it is in any of the requested groups, and # for the current platform, and matches the gem constraints. (dep.groups & groups).any? && dep.should_include? end Plugin.hook(Plugin::Events::GEM_BEFORE_REQUIRE_ALL, dependencies) dependencies.each do |dep| Plugin.hook(Plugin::Events::GEM_BEFORE_REQUIRE, dep) # Loop through all the specified autorequires for the # dependency. If there are none, use the dependency's name # as the autorequire. Array(dep.autorequire || dep.name).each do |file| # Allow `require: true` as an alias for `require: <name>` file = dep.name if file == true required_file = file begin Kernel.require required_file rescue LoadError => e if dep.autorequire.nil? && e.path == required_file if required_file.include?("-") required_file = required_file.tr("-", "/") retry end else raise Bundler::GemRequireError.new e, "There was an error while trying to load the gem '#{file}'." end rescue StandardError => e raise Bundler::GemRequireError.new e, "There was an error while trying to load the gem '#{file}'." end end Plugin.hook(Plugin::Events::GEM_AFTER_REQUIRE, dep) end Plugin.hook(Plugin::Events::GEM_AFTER_REQUIRE_ALL, dependencies) dependencies end
#setup(*groups)
[ GitHub ]# File 'lib/bundler/runtime.rb', line 14
def setup(*groups) @definition.ensure_equivalent_gemfile_and_lockfile # Has to happen first clean_load_path specs = @definition.specs_for(groups) SharedHelpers.set_bundle_environment Bundler.rubygems.replace_entrypoints(specs) # Activate the specs load_paths = specs.map do |spec| check_for_activated_spec!(spec) Bundler.rubygems.mark_loaded(spec) spec.load_paths.reject {|path| $LOAD_PATH.include?(path) } end.reverse.flatten Gem.add_to_load_path(*load_paths) setup_manpath lock(preserve_unknown_sections: true) self end
#setup_manpath (private)
[ GitHub ]# File 'lib/bundler/runtime.rb', line 349
def setup_manpath # Add man/ subdirectories from activated bundles to MANPATH for man(1) manuals = $LOAD_PATH.filter_map do |path| man_subdir = path.sub(/lib$/, "man") man_subdir unless SharedHelpers.glob_files_in_dir("man?/", man_subdir).empty? end return if manuals.empty? Bundler::SharedHelpers.set_env "MANPATH", manuals.concat( ENV["MANPATH"] ? ENV["MANPATH"].to_s.split(File::PATH_SEPARATOR) : [""] ).uniq.join(File::PATH_SEPARATOR) end