diff options
Diffstat (limited to 'lib/bundler/source/git.rb')
| -rw-r--r-- | lib/bundler/source/git.rb | 160 |
1 files changed, 118 insertions, 42 deletions
diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb index 198e335bb6..a002a2570a 100644 --- a/lib/bundler/source/git.rb +++ b/lib/bundler/source/git.rb @@ -32,6 +32,20 @@ module Bundler @local = false end + def remote! + return if @allow_remote + + @local_specs = nil + @allow_remote = true + end + + def cached! + return if @allow_cached + + @local_specs = nil + @allow_cached = true + end + def self.from_lock(options) new(options.merge("uri" => options.delete("remote"))) end @@ -56,13 +70,13 @@ module Bundler end def hash - [self.class, uri, ref, branch, name, version, glob, submodules].hash + [self.class, uri, ref, branch, name, glob, submodules].hash end def eql?(other) other.is_a?(Git) && uri == other.uri && ref == other.ref && branch == other.branch && name == other.name && - version == other.version && glob == other.glob && + glob == other.glob && submodules == other.submodules end @@ -88,7 +102,7 @@ module Bundler end def identifier - uri_with_specifiers([humanized_ref, cached_revision, glob_for_display]) + uri_with_specifiers([humanized_ref, locked_revision, glob_for_display]) end def uri_with_specifiers(specifiers) @@ -150,7 +164,8 @@ module Bundler "does not exist. Run `bundle config unset local.#{override_for(original_path)}` to remove the local override" end - set_local!(path) + @local = true + set_paths!(path) # Create a new git proxy without the cached revision # so the Gemfile.lock always picks up the new revision. @@ -161,10 +176,10 @@ module Bundler "#{current_branch} but Gemfile specifies #{branch}" end - changed = cached_revision && cached_revision != revision + changed = locked_revision && locked_revision != revision - if !Bundler.settings[:disable_local_revision_check] && changed && !@unlocked && !git_proxy.contains?(cached_revision) - raise GitError, "The Gemfile lock is pointing to revision #{shortref_for_display(cached_revision)} " \ + if !Bundler.settings[:disable_local_revision_check] && changed && !@unlocked && !git_proxy.contains?(locked_revision) + raise GitError, "The Gemfile lock is pointing to revision #{shortref_for_display(locked_revision)} " \ "but the current branch in your local override for #{name} does not contain such commit. " \ "Please make sure your branch is up to date." end @@ -173,13 +188,16 @@ module Bundler end def specs(*) - set_local!(app_cache_path) if has_app_cache? && !local? + set_cache_path!(app_cache_path) if use_app_cache? if requires_checkout? && !@copied - fetch - git_proxy.copy_to(install_path, submodules) - serialize_gemspecs_in(install_path) - @copied = true + Plugin.hook(Plugin::Events::GIT_BEFORE_FETCH, self) + begin + fetch unless use_app_cache? + checkout + ensure + Plugin.hook(Plugin::Events::GIT_AFTER_FETCH, self) + end end local_specs @@ -192,27 +210,25 @@ module Bundler print_using_message "Using #{version_message(spec, options[:previous_spec])} from #{self}" if (requires_checkout? && !@copied) || force - Bundler.ui.debug " * Checking out revision: #{ref}" - git_proxy.copy_to(install_path, submodules) - serialize_gemspecs_in(install_path) - @copied = true + checkout end - generate_bin_options = { disable_extensions: !Bundler.rubygems.spec_missing_extensions?(spec), build_args: options[:build_args] } + generate_bin_options = { disable_extensions: !spec.missing_extensions?, build_args: options[:build_args] } generate_bin(spec, generate_bin_options) requires_checkout? ? spec.post_install_message : nil end + def migrate_cache(custom_path = nil, local: false) + if local + cache_to(custom_path, try_migrate: false) + else + cache_to(custom_path, try_migrate: true) + end + end + def cache(spec, custom_path = nil) - app_cache_path = app_cache_path(custom_path) - return unless Bundler.feature_flag.cache_all? - return if path == app_cache_path - cached! - FileUtils.rm_rf(app_cache_path) - git_proxy.checkout if requires_checkout? - git_proxy.copy_to(app_cache_path, @submodules) - serialize_gemspecs_in(app_cache_path) + cache_to(custom_path, try_migrate: false) end def load_spec_files @@ -227,7 +243,7 @@ module Bundler # across different projects, this cache will be shared. # When using local git repos, this is set to the local repo. def cache_path - @cache_path ||= if Bundler.feature_flag.global_gem_cache? + @cache_path ||= if Bundler.settings[:global_gem_cache] Bundler.user_cache else Bundler.bundle_path.join("cache", "bundler") @@ -235,7 +251,7 @@ module Bundler end def app_cache_dirname - "#{base_name}-#{shortref_for_path(cached_revision || revision)}" + "#{base_name}-#{shortref_for_path(locked_revision || revision)}" end def revision @@ -256,6 +272,43 @@ module Bundler private + def cache_to(custom_path, try_migrate: false) + return unless Bundler.settings[:cache_all] + + app_cache_path = app_cache_path(custom_path) + + migrate = try_migrate ? bare_repo?(app_cache_path) : false + + set_cache_path!(nil) if migrate + + return if cache_path == app_cache_path + + cached! + FileUtils.rm_rf(app_cache_path) + git_proxy.checkout if migrate || requires_checkout? + git_proxy.copy_to(app_cache_path, @submodules) + serialize_gemspecs_in(app_cache_path) + end + + def checkout + Bundler.ui.debug " * Checking out revision: #{ref}" + if use_app_cache? && !bare_repo?(app_cache_path) + SharedHelpers.filesystem_access(install_path.dirname) do |p| + FileUtils.mkdir_p(p) + end + FileUtils.cp_r("#{app_cache_path}/.", install_path) + else + if use_app_cache? && bare_repo?(app_cache_path) + Bundler.ui.warn "Installing from cache in old \"bare repository\" format for compatibility. " \ + "Please run `bundle cache` and commit the updated cache to migrate to the new format and get rid of this warning." + end + + git_proxy.copy_to(install_path, submodules) + end + serialize_gemspecs_in(install_path) + @copied = true + end + def humanized_ref if local? path @@ -278,28 +331,45 @@ module Bundler # The gemspecs we cache should already be evaluated. spec = Bundler.load_gemspec(spec_path) next unless spec - Bundler.rubygems.set_installed_by_version(spec) + spec.installed_by_version = Gem::VERSION Bundler.rubygems.validate(spec) File.open(spec_path, "wb") {|file| file.write(spec.to_ruby) } end end - def set_local!(path) - @local = true - @local_specs = @git_proxy = nil - @cache_path = @install_path = path + def set_paths!(path) + set_cache_path!(path) + set_install_path!(path) + end + + def set_cache_path!(path) + @git_proxy = nil + @cache_path = path + end + + def set_install_path!(path) + @local_specs = nil + @install_path = path end def has_app_cache? - cached_revision && super + locked_revision && super + end + + def use_app_cache? + has_app_cache? && !local? end def requires_checkout? - allow_git_ops? && !local? && !cached_revision_checked_out? + allow_git_ops? && !local? && !locked_revision_checked_out? + end + + def locked_revision_checked_out? + locked_revision && locked_revision == revision && installed? end - def cached_revision_checked_out? - cached_revision && cached_revision == revision && install_path.exist? + def installed? + git_proxy.installed_to?(install_path) end def base_name @@ -336,7 +406,7 @@ module Bundler Bundler::Digest.sha1(input) end - def cached_revision + def locked_revision options["revision"] end @@ -345,13 +415,12 @@ module Bundler end def git_proxy - @git_proxy ||= GitProxy.new(cache_path, uri, options, cached_revision, self) + @git_proxy ||= GitProxy.new(cache_path, uri, options, locked_revision, self) end def fetch git_proxy.checkout rescue GitError => e - raise unless Bundler.feature_flag.allow_offline_install? Bundler.ui.warn "Using cached git data because of network errors:\n#{e}" end @@ -359,9 +428,12 @@ module Bundler def validate_spec(_spec); end def load_gemspec(file) - stub = Gem::StubSpecification.gemspec_stub(file, install_path.parent, install_path.parent) - stub.full_gem_path = Pathname.new(file).dirname.expand_path(root).to_s - StubSpecification.from_stub(stub) + dirname = Pathname.new(file).dirname + SharedHelpers.chdir(dirname.to_s) do + stub = Gem::StubSpecification.gemspec_stub(file, install_path.parent, install_path.parent) + stub.full_gem_path = dirname.expand_path(root).to_s + StubSpecification.from_stub(stub) + end end def git_scope @@ -375,6 +447,10 @@ module Bundler def override_for(path) Bundler.settings.local_overrides.key(path) end + + def bare_repo?(path) + File.exist?(path.join("objects")) && File.exist?(path.join("HEAD")) + end end end end |
