diff --git a/modules/core/src/main/scala/org/scalasteward/core/coursier/CoursierAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/coursier/CoursierAlg.scala index 58142abac8..82dfc70379 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/coursier/CoursierAlg.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/coursier/CoursierAlg.scala @@ -22,8 +22,10 @@ import cats.implicits.* import coursier.cache.{CachePolicy, FileCache} import coursier.core.{Authentication, Project} import coursier.{Fetch, Module, ModuleName, Organization} +import org.http4s.Uri import org.scalasteward.core.data.Resolver.Credentials import org.scalasteward.core.data.{Dependency, Resolver, Version} +import org.scalasteward.core.forge.ForgeType import org.scalasteward.core.util.uri import org.typelevel.log4cats.Logger @@ -146,16 +148,26 @@ object CoursierAlg { ) } - private def metadataFrom(project: Project): DependencyMetadata = + private def metadataFrom(project: Project): DependencyMetadata = { + val updateSchemeMaybe: (Uri.Scheme, Uri.Host) => Option[Uri.Scheme] = + (scheme, host) => + if (uri.httpSchemes.contains_(scheme)) + ForgeType.fromPublicWebHost(host.value).flatMap(_.publicWebScheme) + else + None + DependencyMetadata( - homePage = uri.fromStringWithScheme(project.info.homePage), - scmUrl = project.info.scm.flatMap(_.url).flatMap(uri.fromStringWithScheme), + homePage = uri.fromStringWithScheme(project.info.homePage)(updateSchemeMaybe), + scmUrl = project.info.scm + .flatMap(_.url) + .flatMap(url => uri.fromStringWithScheme(url)(updateSchemeMaybe)), releaseNotesUrl = project.properties .collectFirst { case (key, value) if key.equalsIgnoreCase("info.releaseNotesUrl") => value } - .flatMap(uri.fromStringWithScheme), + .flatMap(url => uri.fromStringWithScheme(url)(updateSchemeMaybe)), versionScheme = project.properties .collectFirst { case (key, value) if key.equalsIgnoreCase("info.versionScheme") => value } ) + } private def parentOf(project: Project): Option[coursier.Dependency] = project.parent.map { case (module, version) => diff --git a/modules/core/src/main/scala/org/scalasteward/core/forge/ForgeType.scala b/modules/core/src/main/scala/org/scalasteward/core/forge/ForgeType.scala index 0effee0334..cdfe38cdde 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/forge/ForgeType.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/forge/ForgeType.scala @@ -29,6 +29,7 @@ import scala.annotation.nowarn sealed trait ForgeType extends Product with Serializable { def publicWebHost: Option[String] + def publicWebScheme: Option[Uri.Scheme] /** Defines how to construct 'diff' urls for this forge type - ie a url that will show the * difference between two git tags. These can be very useful for understanding the difference @@ -67,6 +68,7 @@ object ForgeType { case object AzureRepos extends ForgeType { override val publicWebHost: Some[String] = Some("dev.azure.com") + override val publicWebScheme: Option[Uri.Scheme] = None override def supportsForking: Boolean = false override val maximumPullRequestLength: Int = 4000 val diffs: DiffUriPattern = (from, to) => @@ -81,6 +83,7 @@ object ForgeType { case object Bitbucket extends ForgeType { override val publicWebHost: Some[String] = Some("bitbucket.org") + override val publicWebScheme: Option[Uri.Scheme] = Some(Uri.Scheme.https) override def supportsLabels: Boolean = false val publicApiBaseUrl = uri"https://api.bitbucket.org/2.0" val diffs: DiffUriPattern = (from, to) => _ / "compare" / s"$to..$from" withFragment "diff" @@ -94,6 +97,7 @@ object ForgeType { */ case object BitbucketServer extends ForgeType { override val publicWebHost: None.type = None + override val publicWebScheme: Option[Uri.Scheme] = None override def supportsForking: Boolean = false override def supportsLabels: Boolean = false override val maximumPullRequestLength: Int = 32768 @@ -103,6 +107,7 @@ object ForgeType { case object GitHub extends ForgeType { override val publicWebHost: Some[String] = Some("github.com") + override val publicWebScheme: Option[Uri.Scheme] = Some(Uri.Scheme.https) val publicApiBaseUrl = uri"https://api.github.com" val diffs: DiffUriPattern = (from, to) => _ / "compare" / s"$from...$to" val files: FileUriPattern = fileName => _ / "blob" / "master" / fileName @@ -112,6 +117,7 @@ object ForgeType { case object GitLab extends ForgeType { override val publicWebHost: Some[String] = Some("gitlab.com") + override val publicWebScheme: Option[Uri.Scheme] = Some(Uri.Scheme.https) val publicApiBaseUrl = uri"https://gitlab.com/api/v4" val diffs: DiffUriPattern = GitHub.diffs val files: FileUriPattern = GitHub.files @@ -119,6 +125,7 @@ object ForgeType { case object Gitea extends ForgeType { override val publicWebHost: Option[String] = None + override val publicWebScheme: Option[Uri.Scheme] = None val diffs: DiffUriPattern = GitHub.diffs val files: FileUriPattern = fileName => _ / "src" / "branch" / "master" / fileName } diff --git a/modules/core/src/main/scala/org/scalasteward/core/util/uri.scala b/modules/core/src/main/scala/org/scalasteward/core/util/uri.scala index de06122168..3027897ec0 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/util/uri.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/util/uri.scala @@ -20,7 +20,7 @@ import cats.syntax.all.* import io.circe.{Decoder, Encoder, KeyDecoder, KeyEncoder} import monocle.Optional import org.http4s.Uri -import org.http4s.Uri.{Authority, Scheme, UserInfo} +import org.http4s.Uri.{Authority, Host, Scheme, UserInfo} object uri { implicit val uriDecoder: Decoder[Uri] = @@ -44,9 +44,31 @@ object uri { val withUserInfo: Optional[Uri, UserInfo] = authorityWithUserInfo.compose(withAuthority) - def fromStringWithScheme(s: String): Option[Uri] = - Uri.fromString(s).toOption.filter(_.scheme.isDefined) + /** Parses the given `String` into a `Uri` and overrides its `Uri.Scheme` according to + * `updateSchemeMaybe`. Otherwise, the `Uri.Scheme` remains unchanged after parsing. + */ + def fromStringWithScheme( + s: String + )(updateSchemeMaybe: (Scheme, Host) => Option[Scheme]): Option[Uri] = + Uri + .fromString(s) + .toOption + .filter(_.scheme.isDefined) + .mapOrKeep { case uri @ UriWithSchemeAndHost(scheme, host) => + val newSchemeMaybe = updateSchemeMaybe(scheme, host) + + newSchemeMaybe.fold(uri)(_ => uri.copy(scheme = newSchemeMaybe)) + } val httpSchemes: Set[Scheme] = Set(Scheme.https, Scheme.http) + + private object UriWithSchemeAndHost { + def unapply(uri: Uri): Option[(Scheme, Host)] = uri match { + case Uri(Some(scheme), Some(authority), _, _, _) => + (scheme -> authority.host).some + case _ => + None + } + } } diff --git a/modules/core/src/test/scala/org/scalasteward/core/coursier/CoursierAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/coursier/CoursierAlgTest.scala index 9dc8474b4f..08244ae9b0 100644 --- a/modules/core/src/test/scala/org/scalasteward/core/coursier/CoursierAlgTest.scala +++ b/modules/core/src/test/scala/org/scalasteward/core/coursier/CoursierAlgTest.scala @@ -49,6 +49,16 @@ class CoursierAlgTest extends CatsEffectSuite { assertIO(obtained, expected) } + test("getMetadata: homePage and scmUrl with the https scheme instead of http for github") { + val dep = "io.lettuce".g % "lettuce-core".a % "6.5.3.RELEASE" + val obtained = coursierAlg.getMetadata(dep, resolvers).runA(MockState.empty) + val expected = emptyMetadata.copy( + homePage = Some(uri"https://github.com/lettuce-io/lettuce-core"), + scmUrl = Some(uri"https://github.com/lettuce-io/lettuce-core") + ) + assertIO(obtained, expected) + } + test("getMetadata: homePage from parent") { val dep = "net.bytebuddy".g % "byte-buddy".a % "1.10.5" val obtained = coursierAlg.getMetadata(dep, resolvers).runA(MockState.empty)