diff --git a/main/src/main/scala/sbt/internal/LibraryManagement.scala b/main/src/main/scala/sbt/internal/LibraryManagement.scala
index 57e542aaf..d911e09eb 100644
--- a/main/src/main/scala/sbt/internal/LibraryManagement.scala
+++ b/main/src/main/scala/sbt/internal/LibraryManagement.scala
@@ -872,6 +872,35 @@ private[sbt] object LibraryManagement {
writeChecksumsForFile(targetFile, checksumAlgorithms, log)
else log.warn(s"$targetFile already exists, skipping (overwrite=$overwrite)")
+ if version.endsWith("-SNAPSHOT") then
+ writeMavenMetadataLocal(versionDir, groupId, artifactId, version, log)
+
+ private def writeMavenMetadataLocal(
+ versionDir: File,
+ groupId: String,
+ artifactId: String,
+ version: String,
+ log: Logger
+ ): Unit =
+ val timestamp = new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(new java.util.Date())
+ val metadata =
+ s"""|
+ |
+ | $groupId
+ | $artifactId
+ | $version
+ |
+ |
+ | true
+ |
+ | $timestamp
+ |
+ |
+ |""".stripMargin
+ val metadataFile = new File(versionDir, "maven-metadata-local.xml")
+ IO.write(metadataFile, metadata)
+ log.info(s"Published $metadataFile")
+
/**
* Publishes artifacts to a remote Maven repo (HTTP) without using Apache Ivy.
* Same layout as ivylessPublishMavenToFile; uses HTTP PUT with optional Basic auth.
diff --git a/sbt-app/src/sbt-test/dependency-management/publishm2-metadata/build.sbt b/sbt-app/src/sbt-test/dependency-management/publishm2-metadata/build.sbt
new file mode 100644
index 000000000..221eed115
--- /dev/null
+++ b/sbt-app/src/sbt-test/dependency-management/publishm2-metadata/build.sbt
@@ -0,0 +1,21 @@
+@transient
+lazy val checkMetadata = taskKey[Unit]("check maven-metadata-local.xml is written for SNAPSHOT")
+
+lazy val root = (project in file("."))
+ .settings(
+ scalaVersion := "2.13.16",
+ organization := "com.example.test.scripted",
+ version := "0.1.0-SNAPSHOT",
+ name := "publishm2-metadata-test",
+ checkMetadata := {
+ val m2Dir = new File(
+ System.getProperty("user.home"),
+ ".m2/repository/com/example/test/scripted/publishm2-metadata-test_2.13/0.1.0-SNAPSHOT"
+ )
+ val metadataFile = new File(m2Dir, "maven-metadata-local.xml")
+ assert(metadataFile.exists, s"maven-metadata-local.xml not found at $metadataFile")
+ val content = IO.read(metadataFile)
+ assert(content.contains("true"), s"Missing localCopy element in:\n$content")
+ assert(content.contains("com.example.test.scripted"), s"Wrong groupId in:\n$content")
+ },
+ )
diff --git a/sbt-app/src/sbt-test/dependency-management/publishm2-metadata/test b/sbt-app/src/sbt-test/dependency-management/publishm2-metadata/test
new file mode 100644
index 000000000..edf905720
--- /dev/null
+++ b/sbt-app/src/sbt-test/dependency-management/publishm2-metadata/test
@@ -0,0 +1,2 @@
+> publishM2
+> checkMetadata