Class: Dependabot::FileFetchers::Base

Inherits:
Object
  • Object
show all
Extended by:
T::Helpers, T::Sig
Defined in:
lib/dependabot/file_fetchers/base.rb

Direct Known Subclasses

Config::FileFetcher

Constant Summary collapse

CLIENT_NOT_FOUND_ERRORS =
T.let(
  [
    Octokit::NotFound,
    Gitlab::Error::NotFound,
    Dependabot::Clients::Azure::NotFound,
    Dependabot::Clients::Bitbucket::NotFound,
    Dependabot::Clients::CodeCommit::NotFound
  ].freeze,
  T::Array[T.class_of(StandardError)]
)
GIT_SUBMODULE_INACCESSIBLE_ERROR =
/^fatal: unable to access '(?<url>.*)': The requested URL returned error: (?<code>\d+)$/
GIT_SUBMODULE_CLONE_ERROR =
/^fatal: clone of '(?<url>.*)' into submodule path '.*' failed$/
GIT_SUBMODULE_ERROR_REGEX =
/(#{GIT_SUBMODULE_INACCESSIBLE_ERROR})|(#{GIT_SUBMODULE_CLONE_ERROR})/
GIT_RETRYABLE_ERRORS =
T.let(
  [
    /remote error: Internal Server Error/,
    /fatal: Couldn\'t find remote ref/,
    %r{git fetch_pack: expected ACK/NAK, got},
    /protocol error: bad pack header/,
    /The remote end hung up unexpectedly/,
    /TLS packet with unexpected length was received/,
    /RPC failed; result=\d+, HTTP code = \d+/,
    /Connection timed out/,
    /Connection reset by peer/,
    /Unable to look up/,
    /Couldn\'t resolve host/,
    /The requested URL returned error: (429|5\d{2})/
  ].freeze,
  T::Array[Regexp]
)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source:, credentials:, repo_contents_path: nil, options: {}) ⇒ Base

Returns a new instance of Base.



104
105
106
107
108
109
110
111
112
113
# File 'lib/dependabot/file_fetchers/base.rb', line 104

def initialize(source:, credentials:, repo_contents_path: nil, options: {})
  @source = source
  @credentials = credentials
  @repo_contents_path = repo_contents_path
  @linked_paths = T.let({}, T::Hash[T.untyped, T.untyped])
  @submodules = T.let([], T::Array[T.untyped])
  @options = options

  @files = T.let([], T::Array[DependencyFile])
end

Instance Attribute Details

#credentialsObject (readonly)

Returns the value of attribute credentials.



31
32
33
# File 'lib/dependabot/file_fetchers/base.rb', line 31

def credentials
  @credentials
end

#optionsObject (readonly)

Returns the value of attribute options.



37
38
39
# File 'lib/dependabot/file_fetchers/base.rb', line 37

def options
  @options
end

#repo_contents_pathObject (readonly)

Returns the value of attribute repo_contents_path.



34
35
36
# File 'lib/dependabot/file_fetchers/base.rb', line 34

def repo_contents_path
  @repo_contents_path
end

#sourceObject (readonly)

Returns the value of attribute source.



28
29
30
# File 'lib/dependabot/file_fetchers/base.rb', line 28

def source
  @source
end

Class Method Details

.required_files_in?(filenames) ⇒ Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/dependabot/file_fetchers/base.rb', line 75

def self.required_files_in?(filenames)
  filenames.any?
end

.required_files_messageObject



80
81
82
# File 'lib/dependabot/file_fetchers/base.rb', line 80

def self.required_files_message
  "Required files are missing from configured directory"
end

Instance Method Details

#clone_repo_contentsObject



163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/dependabot/file_fetchers/base.rb', line 163

def clone_repo_contents
  @clone_repo_contents ||= T.let(
    _clone_repo_contents(target_directory: repo_contents_path),
    T.nilable(String)
  )
rescue Dependabot::SharedHelpers::HelperSubprocessFailed => e
  if e.message.include?("fatal: Remote branch #{target_branch} not found in upstream origin")
    raise Dependabot::BranchNotFound, target_branch
  elsif e.message.include?("No space left on device")
    raise Dependabot::OutOfDisk
  end

  raise Dependabot::RepoNotFound.new(source, e.message)
end

#commitObject



148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/dependabot/file_fetchers/base.rb', line 148

def commit
  return T.must(cloned_commit) if cloned_commit
  return T.must(source.commit) if source.commit

  branch = target_branch || default_branch_for_repo

  @commit ||= T.let(T.unsafe(client_for_provider).fetch_commit(repo, branch), T.nilable(String))
rescue *CLIENT_NOT_FOUND_ERRORS
  raise Dependabot::BranchNotFound, branch
rescue Octokit::Conflict => e
  raise unless e.message.include?("Repository is empty")
end

#directoryObject



121
122
123
# File 'lib/dependabot/file_fetchers/base.rb', line 121

def directory
  Pathname.new(source.directory || "/").cleanpath.to_path
end

#ecosystem_versionsObject



179
# File 'lib/dependabot/file_fetchers/base.rb', line 179

def ecosystem_versions; end

#fetch_filesObject



145
# File 'lib/dependabot/file_fetchers/base.rb', line 145

def fetch_files; end

#filesObject



131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/dependabot/file_fetchers/base.rb', line 131

def files
  return @files if @files.any?

  files = fetch_files.compact
  raise Dependabot::DependencyFileNotFound.new(nil, "No files found in #{directory}") unless files.any?

  unless self.class.required_files_in?(files.map(&:name))
    raise DependencyFileNotFound.new(nil, self.class.required_files_message)
  end

  @files = files
end

#repoObject



116
117
118
# File 'lib/dependabot/file_fetchers/base.rb', line 116

def repo
  source.repo
end

#target_branchObject



126
127
128
# File 'lib/dependabot/file_fetchers/base.rb', line 126

def target_branch
  source.branch
end