From a87a858073af160a8c2ca6442a7f7907676613c1 Mon Sep 17 00:00:00 2001 From: Piotr Przybylski Date: Sun, 3 May 2026 15:35:19 +0200 Subject: [PATCH 1/3] Enable Windows CI for sbt 2 --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4048d09..11c1e6f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,10 @@ jobs: java: 11 distribution: temurin jobtype: sbt-1 + - os: windows-latest + java: 17 + distribution: temurin + jobtype: sbt-2 env: # define Java options for both official sbt and sbt-extras JAVA_OPTS: -Xms2048M -Xmx2048M -Xss6M -XX:ReservedCodeCacheSize=256M -Dfile.encoding=UTF-8 From e400999bf072f6a601819640c6a643af69aa6a27 Mon Sep 17 00:00:00 2001 From: Piotr Przybylski Date: Sun, 3 May 2026 19:31:38 +0200 Subject: [PATCH 2/3] Fix external JAR files overriding project files when merging on Windows JAR entries are always read using forward slashes, while project files on Windows use backslashes --- src/main/scala/sbtassembly/Assembly.scala | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/scala/sbtassembly/Assembly.scala b/src/main/scala/sbtassembly/Assembly.scala index 89ef0c9..90fab62 100644 --- a/src/main/scala/sbtassembly/Assembly.scala +++ b/src/main/scala/sbtassembly/Assembly.scala @@ -266,9 +266,12 @@ object Assembly { classByParentDir .flatMap { case (parentDir, file) => val originalTarget = parentDir.relativize(file).toString - classShader(originalTarget, () => new BufferedInputStream(new FileInputStream(file.toFile()))) + val sanitizedTarget = + if (originalTarget.contains('\\')) originalTarget.replace('\\', '/') + else originalTarget + classShader(sanitizedTarget, () => new BufferedInputStream(new FileInputStream(file.toFile()))) .map { case (shadedName, stream) => - Project(targetJarName, originalTarget, shadedName, stream) + Project(targetJarName, sanitizedTarget, shadedName, stream) } } } @@ -705,8 +708,7 @@ object PathList { private val sysFileSep = "/" def unapplySeq(path: String): Option[Seq[String]] = { - val sanitizedPath = if (path.contains('\\')) path.replace('\\', '/') else path - val split = sanitizedPath.split(sysFileSep) + val split = path.split(sysFileSep) if (split.isEmpty) Option.empty else Option(split.toList) } From a7bd6e59600907661133dd272c46cead6b4ed8f8 Mon Sep 17 00:00:00 2001 From: Piotr Przybylski Date: Sun, 3 May 2026 20:41:19 +0200 Subject: [PATCH 3/3] Always merge project files before external JARs (fixes #513) Previously order depended on exportJars flag: * false (default) - project files were ordered before external JAR dependencies * true - project files were packaged in JAR and ordered like an external dependency --- src/main/scala/sbtassembly/Assembly.scala | 3 ++- src/sbt-test/merging/merging/build.sbt | 10 +++++++--- src/sbt-test/merging/merging/lib/1.jar | Bin 2086 -> 2571 bytes src/sbt-test/merging/merging/lib/2.jar | Bin 1293 -> 1632 bytes src/sbt-test/merging/merging/lib/3.jar | Bin 1784 -> 1784 bytes .../merging/src/main/1/META-INF/services/srv | 1 + .../merging/src/main/2/META-INF/services/srv | 1 + .../src/main/resources/META-INF/services/srv | 1 + src/sbt-test/merging/merging/test | 9 +++++++-- 9 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 src/sbt-test/merging/merging/src/main/1/META-INF/services/srv create mode 100644 src/sbt-test/merging/merging/src/main/2/META-INF/services/srv create mode 100644 src/sbt-test/merging/merging/src/main/resources/META-INF/services/srv diff --git a/src/main/scala/sbtassembly/Assembly.scala b/src/main/scala/sbtassembly/Assembly.scala index 90fab62..af95005 100644 --- a/src/main/scala/sbtassembly/Assembly.scala +++ b/src/main/scala/sbtassembly/Assembly.scala @@ -288,7 +288,8 @@ object Assembly { log ) val (jarFiles, jarFileEntries) = timed(Level.Debug, "Collect and shade dependency entries") { - filteredJars.par.map { jar => + val (externalJars, projectJars) = filteredJars.partition(externalDeps.contains) + (projectJars ++ externalJars).par.map { jar => val module = jar.metadata .get(moduleIDStr) .map(parseModuleIDStrAttribute) diff --git a/src/sbt-test/merging/merging/build.sbt b/src/sbt-test/merging/merging/build.sbt index 157e942..2f8680c 100644 --- a/src/sbt-test/merging/merging/build.sbt +++ b/src/sbt-test/merging/merging/build.sbt @@ -13,12 +13,15 @@ assemblyMergeStrategy := { oldStrategy(x) } name := "foo" -exportJars := true lazy val testmerge = (project in file(".")) .settings( assembly / assemblyJarName := "foo.jar", TaskKey[Unit]("check") := { + val s = streams.value + val projectAsJar = exportJars.value + val renameSuffix = if (projectAsJar) "foo-0.1" else "foo" + s.log.info(s"Checking with exportJars=$projectAsJar") IO.withTemporaryDirectory { dir => IO.unzip(crossTarget.value / "foo.jar", dir) mustContain(dir / "a", Seq("1", "2", "1", "3")) @@ -27,9 +30,9 @@ lazy val testmerge = (project in file(".")) mustContain(dir / "d", Seq("1", "2", "3")) mustContain(dir / "e", Seq("1")) mustNotExist(dir / "f") - mustContain(dir / "README_foo-0.1", Seq("resources")) + mustContain(dir / s"README_$renameSuffix", Seq("resources")) mustContain(dir / "README_1", Seq("1")) - mustContain(dir / "LICENSE_foo-0.1", Seq("resources")) + mustContain(dir / s"LICENSE_$renameSuffix", Seq("resources")) mustContain(dir / "LICENSE" / "a", Seq("1")) // 80f5a06 -- don't rename License.class mustExist(dir / "com" / "example" / "License.class") @@ -41,6 +44,7 @@ lazy val testmerge = (project in file(".")) mustExist(dir / "com" / "example" / "license" / "PublicDomain.class") mustExist(dir / "NOTICE" / "README_3.txt") mustExist(dir / "NOTICE" / "LICENSE_3.txt") + mustContain(dir / "META-INF" / "services" / "srv", Seq("local", "jar1", "jar2")) } }) diff --git a/src/sbt-test/merging/merging/lib/1.jar b/src/sbt-test/merging/merging/lib/1.jar index a00e34349bb6f03021ba995225823221ef4382d4..036e7610281ac56c5fe44c264a5237a5f5b36053 100644 GIT binary patch literal 2571 zcmbuBO-mb56ozliBskVZ6$ORTrO-t!uDVfh&Y}SI z^ar>o?V^P)3e9imqR@h%2<}?CDNf%rH{;yg%*_O6!kNtGJaf*uhbPI-C$&CC*OOys zedXVaogO?>B-kTnt*z=T`6IJwzb$>RtF;F#p#?!f_ zOqc6)a(cQYp5vg1aO}zfs&Y8%`_bP#g|ZxCr8XOvDF7*kLs?Gcz#EtXw`*0%Fo~YW zNtK{Ryn++ByLEcR+NZd#+DhvdGX)I96&G^|3=|d@^AQ-xEH36ZFwk0D%mgM4!9`=_ zb?jyQq!@e1T%!a`pgPb(HK#r>y-DNeelF1Nb^hrV+#le40Y*34F2A7B8{;{CM!5<> zA{BPnN?8j1!pLrnYLgUb5yVg<1Y?smHq=7=BoPBef*h(ZHF@lg%-C67$NvNB+OO3o zhv_obN{SE-e{sUu03@iWu literal 2086 zcmbuAPfG$(6veMPNt#4~P(ieGS-5HyC^d_)nyD;Wre-0iMPf+1K18)@*9T}3w5Vv& zzg5dNK~PW-MZ4NXb>2L6o^P6&U`Cz{=>5&T=e=`APX&}PvFmMTH!=G)z2e6`TR!Ti z%v?G|fxG){Z9aIZRcjsOQ$Bq}N)&&Hhjqu|te4`Pm*OQa#rgjh-%Ooa1Y0(WyKgVt z1gkEbCZJ*SYKPhrcCZ8{~MXTth>nNgEt zld93gp8Fu@>t~7P6u419$gP(65Z@2i+7A{#IWGbH%)ZPauB7Tny*gjZl-7!QPEj7O zwGfsq51$Tb<7_L|ycrECXZa0B9@+9B9@Q5Suy>Xng-! zCOF`%c_8B0k!hp@T4U+pz_KQTIOs6mF+3+gVmZM{LPnUUQg%#)L{ha*GBX227rV$F zkG2qxC8C)hAphxYvsalMYm%7}Lr6b1b)(k?`L8T-f0nFEU(2%!(zB#ou@k8+2t!aO LK52#M1Q4QM*w>%j diff --git a/src/sbt-test/merging/merging/lib/2.jar b/src/sbt-test/merging/merging/lib/2.jar index 117dbd82ea71babcbb7f78768a9887e0f8dd3950..63468d031289ebc98a32e006cabcf418cfeac0b5 100644 GIT binary patch literal 1632 zcmWIWW@h1H00GS@#o-gy*Z432*&xiwAj6Ot8p6rIeAg{1b!OhS)Y1xW21b?_%nS@* z!iXyXujV95G$&J{IfWF>!G8kNk^P*CPqQHbKd0f-j4#00fT11a>geL@N~{UljW!XW zc!L2>pb5UNA&$D9es20;LqKtcCEgIR7F4|7VO9387)hWRAS{e*gr9$ir?abGNks|R zFrG)p{W*XbEfIudWELv`QAtLsLSBAJW^$@RT7HoNvR9`sUK|5+B#0J5wxu|=s0^s7 z7~oVA%zCCsJ+#`5#+OLO2*RFCiTKzi}y6 bbHOmxgA7ArXb2|*^R2s6{lnOf`j=L4GcdAzWn^Gr z5dkVN;tIg4If)X@$&_eLAw_fWpTKlvKd0i;Y>4FN=YD%J0xS)z+41TTLIEc2kE)ps z7}`OujxN5gU=x-SHo?DmzXLE9;D8fog0E|cqpqi)n?BeO)szO?R zkpd`fFfz$8<4Rf*U}pnU62p>45EGctSRn}wEs+s#j4jX@V3MQMm@1$#z{E$XG24O0 z0Fxnc#-Jua*qYL^f%T#h4hIr7d)yCgQ;&r zW$Krwu8kx(W)v$81DnTqsxaHY{JGeeW%W>xBt*M-37&(+tOTxxM11$H zP8t&)mp?g<8`>Cb)sW}R;8(07C15oq;wi04@{~sgtV+BkDw#Fwe6MsA4?9LQ`tnD zh)k$%VZXiGR3=?#%F0@;usPmr_`ew!^muwbp_1)0m9@n!2!@|#__b6EBbj>Z_G(#w5UNdiSUX5vdwYzz8A+$IX<)qAEx^ zf?SED#va=XFuMq{QaO&@veqi8NrI>YK;8~@Z3^4HRZLEzxFQnq-M2c)qkVE5H?%z1sv*xA!CTCb60jl? s@sw62dCGkgmM3U=u2oCUeK)yWQecY+8VWdFc&tPnK0A2r4Woqk22;IgMF0Q* diff --git a/src/sbt-test/merging/merging/src/main/1/META-INF/services/srv b/src/sbt-test/merging/merging/src/main/1/META-INF/services/srv new file mode 100644 index 0000000..f0d332e --- /dev/null +++ b/src/sbt-test/merging/merging/src/main/1/META-INF/services/srv @@ -0,0 +1 @@ +jar1 diff --git a/src/sbt-test/merging/merging/src/main/2/META-INF/services/srv b/src/sbt-test/merging/merging/src/main/2/META-INF/services/srv new file mode 100644 index 0000000..be67a05 --- /dev/null +++ b/src/sbt-test/merging/merging/src/main/2/META-INF/services/srv @@ -0,0 +1 @@ +jar2 diff --git a/src/sbt-test/merging/merging/src/main/resources/META-INF/services/srv b/src/sbt-test/merging/merging/src/main/resources/META-INF/services/srv new file mode 100644 index 0000000..4083037 --- /dev/null +++ b/src/sbt-test/merging/merging/src/main/resources/META-INF/services/srv @@ -0,0 +1 @@ +local diff --git a/src/sbt-test/merging/merging/test b/src/sbt-test/merging/merging/test index ceec1be..7ae39cc 100644 --- a/src/sbt-test/merging/merging/test +++ b/src/sbt-test/merging/merging/test @@ -1,6 +1,11 @@ -# check if the file gets created +> clean +> set ThisBuild / exportJars := false > assembly $ exists target/**/foo.jar +> check -# check if it says hello +> clean +> set ThisBuild / exportJars := true +> assembly +$ exists target/**/foo.jar > check