diff options
author | schneems <richard.schneeman@gmail.com> | 2013-09-22 10:48:59 -0500 |
---|---|---|
committer | schneems <richard.schneeman@gmail.com> | 2013-09-28 14:24:01 -0500 |
commit | a5d870fc6dc166c43a377870bf68e77dfe16f5cf (patch) | |
tree | d99fa366f5da8660e097a5e1e86ef72f2e61beb1 /lib | |
parent | dc7dd9a222cf45732b61604529a11483b7e91ce8 (diff) | |
download | bundler-a5d870fc6dc166c43a377870bf68e77dfe16f5cf.tar.gz |
Retry git commands
Diffstat (limited to 'lib')
-rw-r--r-- | lib/bundler/cli.rb | 10 | ||||
-rw-r--r-- | lib/bundler/installer.rb | 4 | ||||
-rw-r--r-- | lib/bundler/retry.rb | 35 | ||||
-rw-r--r-- | lib/bundler/source/git/git_proxy.rb | 43 |
4 files changed, 57 insertions, 35 deletions
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 2ee78d21b9..c9d2771097 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -15,6 +15,8 @@ module Bundler def initialize(*) super + ENV['BUNDLE_GEMFILE'] = File.expand_path(options[:gemfile]) if options[:gemfile] + Bundler::Retry.attempts = options[:retry] || Bundler.settings[:retry] || Bundler::Retry::DEFAULT_ATTEMPTS Bundler.rubygems.ui = UI::RGProxy.new(Bundler.ui) rescue UnknownArgumentError => e raise InvalidOption, e.message @@ -30,6 +32,8 @@ module Bundler default_task :install class_option "no-color", :type => :boolean, :banner => "Disable colorization in output" class_option "verbose", :type => :boolean, :banner => "Enable verbose output mode", :aliases => "-V" + class_option "retry", :type => :numeric, :aliases => "-r", :banner => + "Specify the number of times you wish to attempt network commands" def help(cli = nil) case cli @@ -106,8 +110,6 @@ module Bundler method_option "dry-run", :type => :boolean, :default => false, :banner => "Lock the Gemfile" def check - ENV['BUNDLE_GEMFILE'] = File.expand_path(options[:gemfile]) if options[:gemfile] - Bundler.settings[:path] = File.expand_path(options[:path]) if options[:path] begin definition = Bundler.definition @@ -180,8 +182,6 @@ module Bundler Bundler.rubygems.security_policies.empty? method_option "jobs", :aliases => "-j", :type => :numeric, :banner => "Specify the number of jobs to run in parallel" - method_option "retry", :aliases => "-r", :type => :numeric, :banner => - "Specify the number of times you wish to attempt a bundle install" def install opts = options.dup @@ -189,8 +189,6 @@ module Bundler opts[:without] = opts[:without].map{|g| g.tr(' ', ':') } end - # Can't use Bundler.settings for this because settings needs gemfile.dirname - ENV['BUNDLE_GEMFILE'] = File.expand_path(opts[:gemfile]) if opts[:gemfile] ENV['RB_USER_INSTALL'] = '1' if Bundler::FREEBSD # Just disable color in deployment mode diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb index 3f2721a483..7470248c3a 100644 --- a/lib/bundler/installer.rb +++ b/lib/bundler/installer.rb @@ -76,15 +76,13 @@ module Bundler end end - retry_times = options[:retry] || 1 - # Since we are installing, we can resolve the definition # using remote specs unless local if options["local"] @definition.resolve_with_cache! else - Bundler::Retry.new("source fetch", retry_times).attempts do + Bundler::Retry.new("source fetch").attempts do @definition.resolve_remotely! end end diff --git a/lib/bundler/retry.rb b/lib/bundler/retry.rb index ff53ff542e..23d95c272e 100644 --- a/lib/bundler/retry.rb +++ b/lib/bundler/retry.rb @@ -1,17 +1,28 @@ module Bundler # General purpose class for retrying code that may fail class Retry - attr_accessor :name, :max_attempts, :current_attempt + DEFAULT_ATTEMPTS = 2 + attr_accessor :name, :total_runs, :current_run - def initialize(name, max_attempts = 1) - @name = name - @max_attempts = max_attempts + class << self + attr_accessor :attempts + end + + def initialize(name, attempts = nil) + @name = name + attempts ||= default_attempts + @total_runs = attempts.next # will run once, then upto attempts.times + end + + def default_attempts + return Integer(self.class.attempts) if self.class.attempts + DEFAULT_ATTEMPTS end def attempt(&block) - @current_attempt = 0 - @failed = false - @error = nil + @current_run = 0 + @failed = false + @error = nil while keep_trying? do run(&block) end @@ -21,8 +32,8 @@ module Bundler private def run(&block) - @failed = false - @current_attempt += 1 + @failed = false + @current_run += 1 @result = block.call rescue => e fail(e) @@ -32,17 +43,17 @@ module Bundler @failed = true raise e if last_attempt? return true unless name - Bundler.ui.warn "Retrying #{name} due to error (#{current_attempt.next}/#{max_attempts}): #{e.message}" + Bundler.ui.warn "Retrying #{name} due to error (#{current_run.next}/#{total_runs}): #{e.message}" end def keep_trying? - return true if current_attempt.zero? + return true if current_run.zero? return false if last_attempt? return true if @failed end def last_attempt? - current_attempt >= max_attempts + current_run >= total_runs end end end diff --git a/lib/bundler/source/git/git_proxy.rb b/lib/bundler/source/git/git_proxy.rb index fa398215bc..919de7bdd2 100644 --- a/lib/bundler/source/git/git_proxy.rb +++ b/lib/bundler/source/git/git_proxy.rb @@ -1,7 +1,31 @@ module Bundler module Source - class Git < Path + class GitNotInstalledError < GitError + def initialize + msg = "You need to install git to be able to use gems from git repositories. " + msg << "For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git" + super msg + end + end + + class GitNotAllowedError < GitError + def initialize(command) + msg = "Bundler is trying to run a `git #{command}` at runtime. You probably need to run `bundle install`. However, " + msg << "this error message could probably be more useful. Please submit a ticket at http://github.com/bundler/bundler/issues " + mag << "with steps to reproduce as well as the following\n\nCALLER: #{caller.join("\n")}" + super msg + end + end + + class GitCommandError < GitError + def initialize(command, path = nil) + msg = "Git error: command `git #{command}` in directory #{Dir.pwd} has failed." + msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path && path.exist? + super msg + end + end + # The GitProxy is responsible to iteract with git repositories. # All actions required by the Git source is encapsualted in this # object. @@ -84,21 +108,12 @@ module Bundler end def git(command, check_errors=true) - if allow? - raise GitError, "You need to install git to be able to use gems from git repositories. For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git" if !Bundler.git_present? - + raise GitNotAllowedError.new(command) unless allow? + raise GitNotInstalledError.new unless Bundler.git_present? + Bundler::Retry.new("git #{command}").attempts do out = SharedHelpers.with_clean_git_env { %x{git #{command}} } - - if check_errors && $?.exitstatus != 0 - msg = "Git error: command `git #{command}` in directory #{Dir.pwd} has failed." - msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path.exist? - raise GitError, msg - end + raise GitCommandError.new(command, path) if check_errors && !$?.success? out - else - raise GitError, "Bundler is trying to run a `git #{command}` at runtime. You probably need to run `bundle install`. However, " \ - "this error message could probably be more useful. Please submit a ticket at http://github.com/bundler/bundler/issues " \ - "with steps to reproduce as well as the following\n\nCALLER: #{caller.join("\n")}" end end |