diff --git a/errors/types.go b/errors/types.go index e4fafd85..efeca36c 100644 --- a/errors/types.go +++ b/errors/types.go @@ -2,6 +2,7 @@ package errors import ( "fmt" + "net/url" "github.com/pkg/errors" ) @@ -134,6 +135,9 @@ func IsRetriableError(err error) bool { }); ok { return e.RetriableError() } + if cause, ok := Cause(err).(*url.Error); ok { + return cause.Temporary() || cause.Timeout() + } if parent := parentOf(err); parent != nil { return IsRetriableError(parent) } diff --git a/errors/types_test.go b/errors/types_test.go new file mode 100644 index 00000000..a71ab9f1 --- /dev/null +++ b/errors/types_test.go @@ -0,0 +1,46 @@ +package errors_test + +import ( + "net/url" + "testing" + + "github.com/git-lfs/git-lfs/errors" + "github.com/stretchr/testify/assert" +) + +type TemporaryError struct { +} + +func (e TemporaryError) Error() string { + return "" +} + +func (e TemporaryError) Temporary() bool { + return true +} + +type TimeoutError struct { +} + +func (e TimeoutError) Error() string { + return "" +} + +func (e TimeoutError) Timeout() bool { + return true +} + +func TestCanRetryOnTemporaryError(t *testing.T) { + err := &url.Error{Err: TemporaryError{}} + assert.True(t, errors.IsRetriableError(err)) +} + +func TestCanRetryOnTimeoutError(t *testing.T) { + err := &url.Error{Err: TimeoutError{}} + assert.True(t, errors.IsRetriableError(err)) +} + +func TestCannotRetryOnGenericUrlError(t *testing.T) { + err := &url.Error{Err: errors.New("")} + assert.False(t, errors.IsRetriableError(err)) +}