From c6cf273d805140a571e6c7e3e55a3544c4bd73ba Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Sun, 27 Aug 2023 10:17:33 -0700 Subject: [PATCH] Interfaces: add credentials to public interface --- docs/installation.md | 33 +++++++++++++++++++ .../CoursierDependencyDownloader.scala | 12 +++++-- .../scalafmt/dynamic/ScalafmtDynamic.scala | 6 ++++ .../scalafmt/dynamic/ScalafmtProperties.scala | 6 ++++ .../interfaces/RepositoryCredential.java | 18 ++++++++++ .../org/scalafmt/interfaces/Scalafmt.java | 8 +++++ 6 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/RepositoryCredential.java diff --git a/docs/installation.md b/docs/installation.md index a63e494dd5..0bbd18d18e 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -498,6 +498,39 @@ By default, `scalafmt` only formats files that match the val scalafmtThatIgnoresProjectSettings = scalafmt.withRespectProjectFilters(false) ``` +### Alternate repositories and credentials + +`scalafmt` uses some default repositories to download the version specified in +`.scalafmt.conf`; these repositories could be hardcoded or potentially specified +via the environment variables. + +In order to specify explicit repositories as well, one could use + +```scala mdoc:silent +val scalafmtWithRepos = scalafmt.withMavenRepositories( + "https://repo-1/snapshots", + "https://repo-2/public" +) +``` + +In addition, if some of the default or custom repositories require access credentials, +they could be specified via + +```scala mdoc:silent +import org.scalafmt.interfaces._ + +val scalafmtWithCreds = scalafmtWithRepos match { + case x: RepositoryCredential.ScalafmtExtension => + x.withRepositoryCredentials( + new RepositoryCredential("repo-1", "username", "password") + ) + case x => x +} +``` + +This capability was added to the public interface as an extension method, accessible +via a separate sub-interface. + ### Clearing resources Use the `clear()` method to clear up resources of the `scalafmt` instance. diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/CoursierDependencyDownloader.scala b/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/CoursierDependencyDownloader.scala index 3cc3c9fd1a..594c8775ab 100644 --- a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/CoursierDependencyDownloader.scala +++ b/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/CoursierDependencyDownloader.scala @@ -1,14 +1,14 @@ package org.scalafmt.dynamic import java.io.OutputStreamWriter -import java.net.URL +import java.net.{URI, URL} import scala.collection.JavaConverters._ import scala.util.Try import coursierapi.{Dependency => CoursierDependency, _} -class CoursierDependencyDownloader( +private class CoursierDependencyDownloader( downloadProgressWriter: OutputStreamWriter, customRepositories: Seq[Repository] ) extends DependencyDownloader { @@ -38,7 +38,13 @@ object CoursierDependencyDownloader extends DependencyDownloaderFactory { override def create(properties: ScalafmtProperties): DependencyDownloader = { val writer = properties.reporter.downloadOutputStreamWriter() - val repositories = properties.repositories.map(MavenRepository.of) + val repositories = properties.repositories.map { x => + val host = new URI(x).getHost + val repo = MavenRepository.of(x) + properties.repositoryCredentials.find(_.host == host).fold(repo) { cred => + repo.withCredentials(Credentials.of(cred.username, cred.password)) + } + } new CoursierDependencyDownloader(writer, repositories) } diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamic.scala b/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamic.scala index e011415ac0..f844306528 100644 --- a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamic.scala +++ b/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtDynamic.scala @@ -10,6 +10,7 @@ final case class ScalafmtDynamic( moduleLoader: ScalafmtModuleLoader, configLoader: ScalafmtConfigLoader ) extends Scalafmt + with RepositoryCredential.ScalafmtExtension with ScalafmtSessionFactory { def this() = this( @@ -40,6 +41,11 @@ final case class ScalafmtDynamic( override def withMavenRepositories(value: String*): Scalafmt = copy(properties = properties.withMavenRepositories(value)) + override def withRepositoryCredentials( + value: RepositoryCredential* + ): Scalafmt = + copy(properties = properties.withRepositoryCredentials(value)) + override def format(config: Path, file: Path, code: String): String = createSession(config).format(file, code) diff --git a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtProperties.scala b/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtProperties.scala index 04dee3ebf8..46d73a6662 100644 --- a/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtProperties.scala +++ b/scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ScalafmtProperties.scala @@ -8,6 +8,7 @@ import org.scalafmt.interfaces._ final case class ScalafmtProperties( reporter: ScalafmtReporter = ConsoleScalafmtReporter, repositories: Seq[String] = Nil, + repositoryCredentials: Seq[RepositoryCredential] = Nil, respectExcludeFilters: Boolean = true ) { @@ -20,6 +21,11 @@ final case class ScalafmtProperties( def withMavenRepositories(value: Seq[String]): ScalafmtProperties = copy(repositories = value) + def withRepositoryCredentials( + value: Seq[RepositoryCredential] + ): ScalafmtProperties = + copy(repositoryCredentials = value) + def reportError(file: Path, error: ScalafmtDynamicError): Unit = error match { case _: ConfigMissingVersion => diff --git a/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/RepositoryCredential.java b/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/RepositoryCredential.java new file mode 100644 index 0000000000..b439c35f37 --- /dev/null +++ b/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/RepositoryCredential.java @@ -0,0 +1,18 @@ +package org.scalafmt.interfaces; + +public final class RepositoryCredential { + public final String host; + public final String username; + public final String password; + + public RepositoryCredential(String host, String username, String password) { + this.host = host; + this.username = username; + this.password = password; + } + + public interface ScalafmtExtension { + Scalafmt withRepositoryCredentials(RepositoryCredential... credentials); + } + +} diff --git a/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/Scalafmt.java b/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/Scalafmt.java index d45ebfe090..c2de9c6a00 100644 --- a/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/Scalafmt.java +++ b/scalafmt-interfaces/src/main/java/org/scalafmt/interfaces/Scalafmt.java @@ -92,6 +92,14 @@ public interface Scalafmt { */ Scalafmt withMavenRepositories(String ... repositories); + /** + * Builder method. + * + * @param credentials repository credentials to use when resolving + * @return an updated interface instance. + */ + Scalafmt withRepositoryCredentials(RepositoryCredential... credentials); + /** * Clear internal caches such as classloaded Scalafmt instances. */