# typed: strict# frozen_string_literal: truerequire"digest"require"sorbet-runtime"require"dependabot/metadata_finders"require"dependabot/pull_request_creator/branch_namer/base"moduleDependabotclassPullRequestCreatorclassBranchNamerclassSoloStrategy<BaseextendT::Sigsig{override.returns(String)}defnew_branch_namereturnshort_branch_nameifbranch_name_might_be_long?@name||=T.let(begindependency_name_part=ifdependencies.count>1&&updating_a_property?property_nameelsifdependencies.count>1&&updating_a_dependency_set?dependency_set.fetch(:group)elsedependencies.map(&:name).join("-and-").tr(":[]","-").tr("@","")end"#{dependency_name_part}-#{branch_version_suffix}"end,T.nilable(String))sanitize_branch_name(File.join(prefixes,@name))endprivatesig{returns(T::Array[String])}defprefixes[prefix,package_manager,files.first&.directory&.tr(" ","-"),target_branch].compactendsig{returns(String)}defpackage_managerT.must(dependencies.first).package_managerendsig{returns(T::Boolean)}defupdating_a_property?T.must(dependencies.first).requirements.any?{|r|r.dig(:metadata,:property_name)}endsig{returns(T::Boolean)}defupdating_a_dependency_set?T.must(dependencies.first).requirements.any?{|r|r.dig(:metadata,:dependency_set)}endsig{returns(String)}defproperty_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_nameendsig{returns(T::Hash[Symbol,String])}defdependency_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_setendsig{returns(T.nilable(String))}defbranch_version_suffixdep=T.must(dependencies.first)ifdep.removed?"-removed"elsiflibrary?&&ref_changed?(dep)&&new_ref(dep)new_ref(dep)elsiflibrary?sanitized_requirement(dep)elsenew_version(dep)endendsig{params(dependency: Dependabot::Dependency).returns(String)}defsanitized_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-")endsig{params(dependency: Dependabot::Dependency).returns(T.nilable(String))}defnew_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 shaifdependency.version&.match?(/^[0-9a-f]{40}$/)returnnew_ref(dependency)ifref_changed?(dependency)&&new_ref(dependency)T.must(dependency.version)[0..6]elsifdependency.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]elsedependency.versionendendsig{params(dependency: Dependabot::Dependency).returns(T.nilable(String))}defprevious_ref(dependency)previous_refs=T.must(dependency.previous_requirements).filter_mapdo|r|r.dig(:source,"ref")||r.dig(:source,:ref)end.uniqprevious_refs.firstifprevious_refs.count==1endsig{params(dependency: Dependabot::Dependency).returns(T.nilable(String))}defnew_ref(dependency)new_refs=dependency.requirements.filter_mapdo|r|r.dig(:source,"ref")||r.dig(:source,:ref)end.uniqnew_refs.firstifnew_refs.count==1endsig{params(dependency: Dependabot::Dependency).returns(T::Boolean)}defref_changed?(dependency)# We could go from multiple previous refs (nil) to a single new refprevious_ref(dependency)!=new_ref(dependency)endsig{params(dependency: Dependabot::Dependency).returns(T.untyped)}defnew_library_requirement(dependency)updated_reqs=dependency.requirements-T.must(dependency.previous_requirements)gemspec=updated_reqs.find{|r|r[:file].match?(%r{^[^/]*\.gemspec$})}returngemspec[:requirement]ifgemspecupdated_reqs.first&.fetch(:requirement)end# TODO: Bring this in line with existing library checks that we do in the# update checkers, which are also overridden by passing an explicit# `requirements_update_strategy`.## TODO reuse in MessageBuildersig{returns(T::Boolean)}deflibrary?dependencies.any?{|d|!d.appears_in_lockfile?}endsig{params(dependency: Dependabot::Dependency).returns(T::Boolean)}defrequirements_changed?(dependency)(dependency.requirements-T.must(dependency.previous_requirements)).any?endsig{returns(T::Boolean)}defbranch_name_might_be_long?dependencies.count>1&&!updating_a_property?&&!updating_a_dependency_set?endsig{returns(String)}defshort_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}"))endsig{returns(T.nilable(String))}defdependency_digestT.let(Digest::MD5.hexdigest(dependencies.mapdo|dependency|"#{dependency.name}-#{dependency.removed??'removed':dependency.version}"end.sort.join(",")).slice(0,10),T.nilable(String))endendendendend