class Dependabot::PullRequestCreator::BranchNamer::SoloStrategy
def branch_name_might_be_long?
def branch_name_might_be_long? dependencies.count > 1 && !updating_a_property? && !updating_a_dependency_set? end
def branch_version_suffix
def branch_version_suffix dep = T.must(dependencies.first) if dep.removed? "-removed" elsif library? && ref_changed?(dep) && new_ref(dep) new_ref(dep) elsif library? sanitized_requirement(dep) else new_version(dep) end end
def dependency_digest
def dependency_digest T.let( Digest::MD5.hexdigest( dependencies.map do |dependency| "#{dependency.name}-#{dependency.removed? ? 'removed' : dependency.version}" end.sort.join(",") ).slice(0, 10), T.nilable(String) ) end
def dependency_set
def dependency_set @dependency_set ||= T.let( T.must(dependencies.first).requirements .find { |r| r.dig(:metadata, :dependency_set) } &.dig(:metadata, :dependency_set), T.nilable(T::Hash[String, String]) ) raise "No dependency set!" unless @dependency_set @dependency_set end
def library?
def library? dependencies.any? { |d| !d.appears_in_lockfile? } end
def new_branch_name
def new_branch_name return short_branch_name if branch_name_might_be_long? @name ||= T.let( begin dependency_name_part = if dependencies.count > 1 && updating_a_property? property_name elsif dependencies.count > 1 && updating_a_dependency_set? dependency_set.fetch(:group) else dependencies .map(&:name) .join("-and-") .tr(":[]", "-") .tr("@", "") end "#{dependency_name_part}-#{branch_version_suffix}" end, T.nilable(String) ) sanitize_branch_name(File.join(prefixes, @name)) end
def new_library_requirement(dependency)
def new_library_requirement(dependency) updated_reqs = dependency.requirements - T.must(dependency.previous_requirements) gemspec = updated_reqs.find { |r| r[:file].match?(%r{^[^/]*\.gemspec$}) } return gemspec[:requirement] if gemspec updated_reqs.first&.fetch(:requirement) end
def new_ref(dependency)
def new_ref(dependency) new_refs = dependency.requirements.filter_map do |r| r.dig(:source, "ref") || r.dig(:source, :ref) end.uniq new_refs.first if new_refs.one? end
def new_version(dependency)
def new_version(dependency) # Version looks like a git SHA and we could be updating to a specific # ref in which case we return that otherwise we return a shorthand sha if dependency.version&.match?(/^[0-9a-f]{40}$/) return new_ref(dependency) if ref_changed?(dependency) && new_ref(dependency) T.must(dependency.version)[0..6] elsif dependency.version == dependency.previous_version && package_manager == "docker" dependency.requirements .filter_map { |r| r.dig(:source, "digest") || r.dig(:source, :digest) } .first.split(":").last[0..6] else dependency.version end end
def package_manager
def package_manager T.must(dependencies.first).package_manager end
def prefixes
def prefixes [ prefix, package_manager, files.first&.directory&.tr(" ", "-"), target_branch ].compact end
def previous_ref(dependency)
def previous_ref(dependency) previous_refs = T.must(dependency.previous_requirements).filter_map do |r| r.dig(:source, "ref") || r.dig(:source, :ref) end.uniq previous_refs.first if previous_refs.one? end
def property_name
def property_name @property_name ||= T.let( T.must(dependencies.first).requirements .find { |r| r.dig(:metadata, :property_name) } &.dig(:metadata, :property_name), T.nilable(String) ) raise "No property name!" unless @property_name @property_name end
def ref_changed?(dependency)
def ref_changed?(dependency) # We could go from multiple previous refs (nil) to a single new ref previous_ref(dependency) != new_ref(dependency) end
def requirements_changed?(dependency)
def requirements_changed?(dependency) (dependency.requirements - T.must(dependency.previous_requirements)).any? end
def sanitized_requirement(dependency)
def sanitized_requirement(dependency) new_library_requirement(dependency) .delete(" ") .gsub("!=", "neq-") .gsub(">=", "gte-") .gsub("<=", "lte-") .gsub("~>", "tw-") .gsub("^", "tw-") .gsub("||", "or-") .gsub("~", "approx-") .gsub("~=", "tw-") .gsub(/==*/, "eq-") .gsub(">", "gt-") .gsub("<", "lt-") .gsub("*", "star") .gsub(",", "-and-") end
def short_branch_name
def short_branch_name # Fix long branch names by using a digest of the dependencies instead of their names. sanitize_branch_name(File.join(prefixes, "multi-#{dependency_digest}")) end
def updating_a_dependency_set?
def updating_a_dependency_set? T.must(dependencies.first) .requirements .any? { |r| r.dig(:metadata, :dependency_set) } end
def updating_a_property?
def updating_a_property? T.must(dependencies.first) .requirements .any? { |r| r.dig(:metadata, :property_name) } end