@@ -53,7 +53,7 @@ import scala.cli.commands.shared.{
53
53
}
54
54
import scala .cli .commands .util .{BuildCommandHelpers , ScalaCliSttpBackend }
55
55
import scala .cli .commands .{ScalaCommand , SpecificationLevel , WatchUtil }
56
- import scala .cli .config .{ConfigDb , Keys , PublishCredentials }
56
+ import scala .cli .config .{ConfigDb , Keys , PasswordOption , PublishCredentials }
57
57
import scala .cli .errors .{
58
58
FailedToSignFileError ,
59
59
MalformedChecksumsError ,
@@ -844,97 +844,123 @@ object Publish extends ScalaCommand[PublishOptions] with BuildCommandHelpers {
844
844
}
845
845
}
846
846
847
- val signerOpt = publishOptions.contextual(isCi).signer.orElse {
848
- if (repoParams.supportsSig)
849
- if (publishOptions.contextual(isCi).secretKey.isDefined) Some (PSigner .BouncyCastle )
850
- else if (publishOptions.contextual(isCi).gpgSignatureId.isDefined) Some (PSigner .Gpg )
851
- else if (repoParams.shouldSign) Some (PSigner .BouncyCastle )
852
- else None
853
- else None
847
+ def getBouncyCastleSigner (
848
+ secretKey : PasswordOption ,
849
+ secretKeyPasswordOpt : Option [PasswordOption ]
850
+ ) = {
851
+ val getLauncher : Supplier [Array [String ]] = { () =>
852
+ val buildOptions = builds.headOption.map(_.options)
853
+ val archiveCache = buildOptions.map(_.archiveCache)
854
+ .getOrElse(ArchiveCache ())
855
+ val fileCache = buildOptions.map(_.finalCache).getOrElse(FileCache ())
856
+ PgpExternalCommand .launcher(
857
+ fileCache,
858
+ archiveCache,
859
+ logger,
860
+ () => builds.head.options.javaHome().value.javaCommand,
861
+ publishOptions.signingCli
862
+ ) match {
863
+ case Left (e) => throw new Exception (e)
864
+ case Right (binaryCommand) => binaryCommand.toArray
865
+ }
866
+ }
867
+
868
+ if (secretKeyPasswordOpt.isEmpty)
869
+ logger.diagnostic(" PGP signing with no password is not recommended since it's not stable" )
870
+
871
+ if (forceSigningBinary)
872
+ (new scala.cli.internal.BouncycastleSignerMakerSubst ).get(
873
+ secretKeyPasswordOpt.fold(null )(_.toCliSigning),
874
+ secretKey.toCliSigning,
875
+ getLauncher,
876
+ logger
877
+ )
878
+ else
879
+ (new BouncycastleSignerMaker ).get(
880
+ secretKeyPasswordOpt.fold(null )(_.toCliSigning),
881
+ secretKey.toCliSigning,
882
+ getLauncher,
883
+ logger
884
+ )
854
885
}
855
- val signer : Signer = signerOpt match {
856
- case Some (PSigner .Gpg ) =>
857
- publishOptions.contextual(isCi).gpgSignatureId match {
858
- case Some (gpgSignatureId) =>
859
- GpgSigner (
860
- GpgSigner .Key .Id (gpgSignatureId),
861
- extraOptions = publishOptions.contextual(isCi).gpgOptions
886
+
887
+ val signerKind : PSigner = publishOptions.contextual(isCi).signer.getOrElse {
888
+ if (! repoParams.supportsSig)
889
+ PSigner .Nop
890
+ else if (publishOptions.contextual(isCi).gpgSignatureId.isDefined)
891
+ PSigner .Gpg
892
+ else if (repoParams.shouldSign)
893
+ PSigner .BouncyCastle
894
+ else
895
+ PSigner .Nop
896
+ }
897
+
898
+ def getSecretKeyPasswordOpt : Option [PasswordOption ] = {
899
+ val maybeSecretKeyPass = if (publishOptions.contextual(isCi).secretKeyPassword.isDefined)
900
+ for {
901
+ secretKeyPassConfigOpt <- publishOptions.contextual(isCi).secretKeyPassword
902
+ secretKeyPass <- secretKeyPassConfigOpt.get(configDb()).toOption
903
+ } yield secretKeyPass
904
+ else
905
+ for {
906
+ secretKeyPassOpt <- configDb().get(Keys .pgpSecretKeyPassword).toOption
907
+ secretKeyPass <- secretKeyPassOpt
908
+ } yield secretKeyPass
909
+
910
+ maybeSecretKeyPass
911
+ }
912
+
913
+ val signer : Either [BuildException , Signer ] = signerKind match {
914
+ // user specified --signer=gpg or --gpgKey=...
915
+ case PSigner .Gpg =>
916
+ publishOptions.contextual(isCi).gpgSignatureId.map { gpgSignatureId =>
917
+ GpgSigner (
918
+ GpgSigner .Key .Id (gpgSignatureId),
919
+ extraOptions = publishOptions.contextual(isCi).gpgOptions
920
+ )
921
+ }.toRight(new MissingPublishOptionError (
922
+ " ID of the GPG key" ,
923
+ " --gpgKey" ,
924
+ directiveName = " "
925
+ ))
926
+
927
+ // user specified --signer=bc or --secret-key=... or target repository requires signing
928
+ // --secret-key-password is possibly specified (not mandatory)
929
+ case PSigner .Nop | PSigner .BouncyCastle
930
+ if publishOptions.contextual(isCi).secretKey.isDefined =>
931
+ val secretKeyConfigOpt = publishOptions.contextual(isCi).secretKey.get
932
+ for {
933
+ secretKey <- secretKeyConfigOpt.get(configDb())
934
+ } yield getBouncyCastleSigner(secretKey, getSecretKeyPasswordOpt)
935
+
936
+ // user specified --signer=bc or target repository requires signing
937
+ // --secret-key-password is possibly specified (not mandatory)
938
+ case PSigner .BouncyCastle =>
939
+ val shouldSignMsg =
940
+ if (repoParams.shouldSign) " signing is required for chosen repository" else " "
941
+ for {
942
+ secretKeyOpt <- configDb().get(Keys .pgpSecretKey).wrapConfigException
943
+ secretKey <- secretKeyOpt.toRight(
944
+ new MissingPublishOptionError (
945
+ " secret key" ,
946
+ " --secret-key" ,
947
+ directiveName = " " ,
948
+ configKeys = Seq (Keys .pgpSecretKey.fullName),
949
+ extraMessage = shouldSignMsg
862
950
)
863
- case None => NopSigner
864
- }
865
- case Some (PSigner .BouncyCastle ) =>
866
- val getLauncher : Supplier [Array [String ]] = { () =>
867
- val buildOptions = builds.headOption.map(_.options)
868
- val archiveCache = buildOptions.map(_.archiveCache)
869
- .getOrElse(ArchiveCache ())
870
- val fileCache = buildOptions.map(_.finalCache).getOrElse(FileCache ())
871
- PgpExternalCommand .launcher(
872
- fileCache,
873
- archiveCache,
874
- logger,
875
- () => builds.head.options.javaHome().value.javaCommand,
876
- publishOptions.signingCli
877
- ) match {
878
- case Left (e) => throw new Exception (e)
879
- case Right (binaryCommand) => binaryCommand.toArray
880
- }
881
- }
882
- val secretKeyDetailsOpt = publishOptions.contextual(isCi).secretKey match {
883
- case Some (secretKey0) =>
884
- val secretKey = secretKey0.get(configDb()).orExit(logger).toCliSigning
885
- val secretKeyPassword = publishOptions
886
- .contextual(isCi)
887
- .secretKeyPassword
888
- .orNull
889
- .get(configDb())
890
- .orExit(logger)
891
- .toCliSigning
892
- Some ((secretKey, secretKeyPassword))
893
- case None =>
894
- configDb().get(Keys .pgpSecretKey).wrapConfigException.orExit(logger) match {
895
- case Some (secretKey) =>
896
- val secretKeyPassword =
897
- configDb().get(Keys .pgpSecretKeyPassword).wrapConfigException
898
- .flatMap {
899
- case None =>
900
- Left (new MissingConfigEntryError (Keys .pgpSecretKeyPassword.fullName))
901
- case Some (p) => Right (p)
902
- }
903
- .orExit(logger)
904
- Some ((secretKey.toCliSigning, secretKeyPassword.toCliSigning))
905
- case None =>
906
- None
907
- }
908
- }
909
- secretKeyDetailsOpt match {
910
- case Some ((secretKey, secretKeyPassword)) =>
911
- if (forceSigningBinary)
912
- (new scala.cli.internal.BouncycastleSignerMakerSubst ).get(
913
- secretKeyPassword,
914
- secretKey,
915
- getLauncher,
916
- logger
917
- )
918
- else
919
- (new BouncycastleSignerMaker ).get(
920
- secretKeyPassword,
921
- secretKey,
922
- getLauncher,
923
- logger
924
- )
925
- case None =>
926
- if (repoParams.shouldSign)
927
- logger.diagnostic(
928
- " PGP signatures are disabled, while these are recommended for this repository."
929
- )
930
- NopSigner
931
- }
932
- case Some (PSigner .Nop ) => NopSigner
933
- case None => NopSigner
951
+ )
952
+ } yield getBouncyCastleSigner(secretKey, getSecretKeyPasswordOpt)
953
+ case _ =>
954
+ if (! publishOptions.contextual(isCi).signer.contains(PSigner .Nop ))
955
+ logger.message(
956
+ " \ud83d\udd13 Artifacts NOT signed as it's not required nor has it been specified"
957
+ )
958
+ Right (NopSigner )
934
959
}
960
+
935
961
val signerLogger =
936
962
new InteractiveSignerLogger (new OutputStreamWriter (System .err), verbosity = 1 )
937
- val signRes = signer.signatures(
963
+ val signRes = value( signer) .signatures(
938
964
fileSet0,
939
965
now,
940
966
ChecksumType .all.map(_.extension).toSet,
@@ -1054,7 +1080,7 @@ object Publish extends ScalaCommand[PublishOptions] with BuildCommandHelpers {
1054
1080
Seq (mod.organization.value, mod.name.value, version)
1055
1081
else
1056
1082
mod.organization.value.split('.' ).toSeq ++ Seq (mod.name.value, version)
1057
- elems.map (" /" + _).mkString + " /"
1083
+ elems.mkString (" /" , " / " , " /" )
1058
1084
}
1059
1085
val path = {
1060
1086
val url = checkRepo.root.stripSuffix(" /" ) + relPath
0 commit comments