Module: Dependabot::Composer::Helpers

Extended by:
T::Sig
Defined in:
lib/dependabot/composer/helpers.rb

Constant Summary collapse

V1 =
T.let("1", String)
V2 =
T.let("2", String)
DEFAULT =

If we are updating a project with no lock file then the default should be the newest version

T.let(V2, String)
COMPOSER_V2_NAME_REGEX =

From composers json-schema: getcomposer.org/schema.json

T.let(
  %r{^[a-z0-9]([_.-]?[a-z0-9]++)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]++)*$},
  Regexp
)
PLATFORM_PACKAGE_REGEX =
T.let(
  /
  ^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[a-z0-9](?:[_.-]?[a-z0-9]+)*
  |composer-(?:plugin|runtime)-api)$
  /x,
  Regexp
)
FAILED_GIT_CLONE_WITH_MIRROR =
T.let(
  /^Failed to execute git clone --(mirror|checkout)[^']*'(?<url>[^']*?)'/,
  Regexp
)
FAILED_GIT_CLONE =
T.let(/^Failed to clone (?<url>.*?)/, Regexp)

Class Method Summary collapse

Class Method Details

.composer_version(composer_json, parsed_lockfile = nil) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/dependabot/composer/helpers.rb', line 45

def self.composer_version(composer_json, parsed_lockfile = nil)
  v1_unsupported = Dependabot::Experiments.enabled?(:composer_v1_unsupported_error)

  # If the parsed lockfile has a plugin API version, we return either V1 or V2
  # based on the major version of the lockfile.
  if parsed_lockfile && parsed_lockfile["plugin-api-version"]
    version = Composer::Version.new(parsed_lockfile["plugin-api-version"])
    return version.canonical_segments.first == 1 ? V1 : V2
  end

  # Check if the composer name does not follow the Composer V2 naming conventions.
  # This happens if "name" is present in composer.json but doesn't match the required pattern.
  composer_name_invalid = composer_json["name"] && composer_json["name"] !~ COMPOSER_V2_NAME_REGEX

  # If the name is invalid returns the fallback version.
  if composer_name_invalid
    return v1_unsupported ? V2 : V1
  end

  # Check if the composer.json file contains "require" entries that don't follow
  # either the platform package naming conventions or the Composer V2 name conventions.
  invalid_v2 = invalid_v2_requirement?(composer_json)

  # If there are invalid requirements returns fallback version.
  if invalid_v2
    return v1_unsupported ? V2 : V1
  end

  # If no conditions are met return V2 by default.
  V2
end

.dependency_url_from_git_clone_error(message) ⇒ Object



78
79
80
81
# File 'lib/dependabot/composer/helpers.rb', line 78

def self.dependency_url_from_git_clone_error(message)
  extract_and_clean_dependency_url(message, FAILED_GIT_CLONE_WITH_MIRROR) ||
    extract_and_clean_dependency_url(message, FAILED_GIT_CLONE)
end

.extract_and_clean_dependency_url(message, regex) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
# File 'lib/dependabot/composer/helpers.rb', line 84

def self.extract_and_clean_dependency_url(message, regex)
  if (match_data = message.match(regex))
    dependency_url = match_data.named_captures.fetch("url")
    if dependency_url.nil? || dependency_url.empty?
      raise "Could not parse dependency_url from git clone error: #{message}"
    end

    return clean_dependency_url(dependency_url)
  end
  nil
end