summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorschneems <richard.schneeman@gmail.com>2013-09-22 10:48:59 -0500
committerschneems <richard.schneeman@gmail.com>2013-09-28 14:24:01 -0500
commita5d870fc6dc166c43a377870bf68e77dfe16f5cf (patch)
treed99fa366f5da8660e097a5e1e86ef72f2e61beb1 /lib
parentdc7dd9a222cf45732b61604529a11483b7e91ce8 (diff)
downloadbundler-a5d870fc6dc166c43a377870bf68e77dfe16f5cf.tar.gz
Retry git commands
Diffstat (limited to 'lib')
-rw-r--r--lib/bundler/cli.rb10
-rw-r--r--lib/bundler/installer.rb4
-rw-r--r--lib/bundler/retry.rb35
-rw-r--r--lib/bundler/source/git/git_proxy.rb43
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