@@ -42,7 +42,8 @@ public struct Linux: Platform {
4242 " tar.gz "
4343 }
4444
45- private static let skipVerificationMessage : String = " To skip signature verification, specify the --no-verify flag. "
45+ private static let skipVerificationMessage : String =
46+ " To skip signature verification, specify the --no-verify flag. "
4647
4748 public func verifySwiftlySystemPrerequisites( ) throws {
4849 // Check if the root CA certificates are installed on this system for NIOSSL to use.
@@ -67,10 +68,15 @@ public struct Linux: Platform {
6768 }
6869 }
6970
70- public func verifySystemPrerequisitesForInstall( _ ctx: SwiftlyCoreContext , platformName: String , version _: ToolchainVersion , requireSignatureValidation: Bool ) async throws -> String ? {
71+ public func verifySystemPrerequisitesForInstall(
72+ _ ctx: SwiftlyCoreContext , platformName: String , version _: ToolchainVersion ,
73+ requireSignatureValidation: Bool
74+ ) async throws -> String ? {
7175 // TODO: these are hard-coded until we have a place to query for these based on the toolchain version
7276 // These lists were copied from the dockerfile sources here: https://github.com/apple/swift-docker/tree/ea035798755cce4ec41e0c6dbdd320904cef0421/5.10
73- let packages : [ String ] = switch platformName {
77+ let packages : [ String ] =
78+ switch platformName
79+ {
7480 case " ubuntu1804 " :
7581 [
7682 " libatomic1 " ,
@@ -221,7 +227,9 @@ public struct Linux: Platform {
221227 [ ]
222228 }
223229
224- let manager : String ? = switch platformName {
230+ let manager : String ? =
231+ switch platformName
232+ {
225233 case " ubuntu1804 " :
226234 " apt-get "
227235 case " ubuntu2004 " :
@@ -259,18 +267,19 @@ public struct Linux: Platform {
259267 }
260268
261269 let tmpFile = self . getTempFilePath ( )
262- let _ = FileManager . default. createFile ( atPath: tmpFile. path, contents: nil , attributes: [ . posixPermissions: 0o600 ] )
270+ let _ = FileManager . default. createFile (
271+ atPath: tmpFile. path, contents: nil , attributes: [ . posixPermissions: 0o600 ]
272+ )
263273 defer {
264274 try ? FileManager . default. removeItem ( at: tmpFile)
265275 }
266276
267- guard let url = URL ( string: " https://www.swift.org/keys/all-keys.asc " ) else {
268- throw SwiftlyError ( message: " malformed URL to the swift gpg keys " )
269- }
270-
271- try await ctx. httpClient. downloadFile ( url: url, to: tmpFile)
277+ try await ctx. httpClient. getGpgKeys ( ) . download ( to: tmpFile)
272278 if let mockedHomeDir = ctx. mockedHomeDir {
273- try self . runProgram ( " gpg " , " --import " , tmpFile. path, quiet: true , env: [ " GNUPGHOME " : mockedHomeDir. appendingPathComponent ( " .gnupg " ) . path] )
279+ try self . runProgram (
280+ " gpg " , " --import " , tmpFile. path, quiet: true ,
281+ env: [ " GNUPGHOME " : mockedHomeDir. appendingPathComponent ( " .gnupg " ) . path]
282+ )
274283 } else {
275284 try self . runProgram ( " gpg " , " --import " , tmpFile. path, quiet: true )
276285 }
@@ -323,13 +332,17 @@ public struct Linux: Platform {
323332 }
324333 }
325334
326- public func install( _ ctx: SwiftlyCoreContext , from tmpFile: URL , version: ToolchainVersion , verbose: Bool ) throws {
335+ public func install(
336+ _ ctx: SwiftlyCoreContext , from tmpFile: URL , version: ToolchainVersion , verbose: Bool
337+ ) throws {
327338 guard tmpFile. fileExists ( ) else {
328339 throw SwiftlyError ( message: " \( tmpFile) doesn't exist " )
329340 }
330341
331342 if !self . swiftlyToolchainsDir ( ctx) . fileExists ( ) {
332- try FileManager . default. createDirectory ( at: self . swiftlyToolchainsDir ( ctx) , withIntermediateDirectories: false )
343+ try FileManager . default. createDirectory (
344+ at: self . swiftlyToolchainsDir ( ctx) , withIntermediateDirectories: false
345+ )
333346 }
334347
335348 ctx. print ( " Extracting toolchain... " )
@@ -375,7 +388,9 @@ public struct Linux: Platform {
375388 try self . runProgram ( tmpDir. appendingPathComponent ( " swiftly " ) . path, " init " )
376389 }
377390
378- public func uninstall( _ ctx: SwiftlyCoreContext , _ toolchain: ToolchainVersion , verbose _: Bool ) throws {
391+ public func uninstall( _ ctx: SwiftlyCoreContext , _ toolchain: ToolchainVersion , verbose _: Bool )
392+ throws
393+ {
379394 let toolchainDir = self . swiftlyToolchainsDir ( ctx) . appendingPathComponent ( toolchain. name)
380395 try FileManager . default. removeItem ( at: toolchainDir)
381396 }
@@ -390,7 +405,9 @@ public struct Linux: Platform {
390405 FileManager . default. temporaryDirectory. appendingPathComponent ( " swiftly- \( UUID ( ) ) " )
391406 }
392407
393- public func verifySignature( _ ctx: SwiftlyCoreContext , archiveDownloadURL: URL , archive: URL , verbose: Bool ) async throws {
408+ public func verifyToolchainSignature(
409+ _ ctx: SwiftlyCoreContext , toolchainFile: ToolchainFile , archive: URL , verbose: Bool
410+ ) async throws {
394411 if verbose {
395412 ctx. print ( " Downloading toolchain signature... " )
396413 }
@@ -401,15 +418,15 @@ public struct Linux: Platform {
401418 try ? FileManager . default. removeItem ( at: sigFile)
402419 }
403420
404- try await ctx. httpClient. downloadFile (
405- url: archiveDownloadURL. appendingPathExtension ( " sig " ) ,
406- to: sigFile
407- )
421+ try await ctx. httpClient. getSwiftToolchainFileSignature ( toolchainFile) . download ( to: sigFile)
408422
409423 ctx. print ( " Verifying toolchain signature... " )
410424 do {
411425 if let mockedHomeDir = ctx. mockedHomeDir {
412- try self . runProgram ( " gpg " , " --verify " , sigFile. path, archive. path, quiet: false , env: [ " GNUPGHOME " : mockedHomeDir. appendingPathComponent ( " .gnupg " ) . path] )
426+ try self . runProgram (
427+ " gpg " , " --verify " , sigFile. path, archive. path, quiet: false ,
428+ env: [ " GNUPGHOME " : mockedHomeDir. appendingPathComponent ( " .gnupg " ) . path]
429+ )
413430 } else {
414431 try self . runProgram ( " gpg " , " --verify " , sigFile. path, archive. path, quiet: !verbose)
415432 }
@@ -418,23 +435,65 @@ public struct Linux: Platform {
418435 }
419436 }
420437
421- private func manualSelectPlatform( _ ctx: SwiftlyCoreContext , _ platformPretty: String ? ) async -> PlatformDefinition {
438+ public func verifySwiftlySignature(
439+ _ ctx: SwiftlyCoreContext , archiveDownloadURL: URL , archive: URL , verbose: Bool
440+ ) async throws {
441+ if verbose {
442+ ctx. print ( " Downloading swiftly signature... " )
443+ }
444+
445+ let sigFile = self . getTempFilePath ( )
446+ let _ = FileManager . default. createFile ( atPath: sigFile. path, contents: nil )
447+ defer {
448+ try ? FileManager . default. removeItem ( at: sigFile)
449+ }
450+
451+ try await ctx. httpClient. getSwiftlyReleaseSignature (
452+ url: archiveDownloadURL. appendingPathExtension ( " sig " )
453+ ) . download ( to: sigFile)
454+
455+ ctx. print ( " Verifying swiftly signature... " )
456+ do {
457+ if let mockedHomeDir = ctx. mockedHomeDir {
458+ try self . runProgram (
459+ " gpg " , " --verify " , sigFile. path, archive. path, quiet: false ,
460+ env: [ " GNUPGHOME " : mockedHomeDir. appendingPathComponent ( " .gnupg " ) . path]
461+ )
462+ } else {
463+ try self . runProgram ( " gpg " , " --verify " , sigFile. path, archive. path, quiet: !verbose)
464+ }
465+ } catch {
466+ throw SwiftlyError ( message: " Signature verification failed: \( error) . " )
467+ }
468+ }
469+
470+ private func manualSelectPlatform( _ ctx: SwiftlyCoreContext , _ platformPretty: String ? ) async
471+ -> PlatformDefinition
472+ {
422473 if let platformPretty {
423- print ( " \( platformPretty) is not an officially supported platform, but the toolchains for another platform may still work on it. " )
474+ print (
475+ " \( platformPretty) is not an officially supported platform, but the toolchains for another platform may still work on it. "
476+ )
424477 } else {
425- print ( " This platform could not be detected, but a toolchain for one of the supported platforms may work on it. " )
478+ print (
479+ " This platform could not be detected, but a toolchain for one of the supported platforms may work on it. "
480+ )
426481 }
427482
428- let selections = self . linuxPlatforms. enumerated ( ) . map { " \( $0 + 1 ) ) \( $1. namePretty) " } . joined ( separator: " \n " )
483+ let selections = self . linuxPlatforms. enumerated ( ) . map { " \( $0 + 1 ) ) \( $1. namePretty) " } . joined (
484+ separator: " \n " )
429485
430- print ( """
431- Please select the platform to use for toolchain downloads:
486+ print (
487+ """
488+ Please select the platform to use for toolchain downloads:
432489
433- 0) Cancel
434- \( selections)
435- """ )
490+ 0) Cancel
491+ \( selections)
492+ """ )
436493
437- let choice = ctx. readLine ( prompt: " Pick one of the available selections [0- \( self . linuxPlatforms. count) ] " ) ?? " 0 "
494+ let choice =
495+ ctx. readLine ( prompt: " Pick one of the available selections [0- \( self . linuxPlatforms. count) ] " )
496+ ?? " 0 "
438497
439498 guard let choiceNum = Int ( choice) else {
440499 fatalError ( " Installation canceled " )
@@ -447,11 +506,15 @@ public struct Linux: Platform {
447506 return self . linuxPlatforms [ choiceNum - 1 ]
448507 }
449508
450- public func detectPlatform( _ ctx: SwiftlyCoreContext , disableConfirmation: Bool , platform: String ? ) async throws -> PlatformDefinition {
509+ public func detectPlatform(
510+ _ ctx: SwiftlyCoreContext , disableConfirmation: Bool , platform: String ?
511+ ) async throws -> PlatformDefinition {
451512 // We've been given a hint to use
452513 if let platform {
453514 guard let pd = linuxPlatforms. first ( where: { $0. nameFull == platform } ) else {
454- fatalError ( " Unrecognized platform \( platform) . Recognized values: \( self . linuxPlatforms. map ( \. nameFull) . joined ( separator: " , " ) ) . " )
515+ fatalError (
516+ " Unrecognized platform \( platform) . Recognized values: \( self . linuxPlatforms. map ( \. nameFull) . joined ( separator: " , " ) ) . "
517+ )
455518 }
456519
457520 return pd
@@ -489,9 +552,13 @@ public struct Linux: Platform {
489552 } else if info. hasPrefix ( " ID_LIKE= " ) {
490553 idlike = String ( info. dropFirst ( " ID_LIKE= " . count) ) . replacingOccurrences ( of: " \" " , with: " " )
491554 } else if info. hasPrefix ( " VERSION_ID= " ) {
492- versionID = String ( info. dropFirst ( " VERSION_ID= " . count) ) . replacingOccurrences ( of: " \" " , with: " " ) . replacingOccurrences ( of: " . " , with: " " )
555+ versionID = String ( info. dropFirst ( " VERSION_ID= " . count) ) . replacingOccurrences (
556+ of: " \" " , with: " "
557+ ) . replacingOccurrences ( of: " . " , with: " " )
493558 } else if info. hasPrefix ( " PRETTY_NAME= " ) {
494- platformPretty = String ( info. dropFirst ( " PRETTY_NAME= " . count) ) . replacingOccurrences ( of: " \" " , with: " " )
559+ platformPretty = String ( info. dropFirst ( " PRETTY_NAME= " . count) ) . replacingOccurrences (
560+ of: " \" " , with: " "
561+ )
495562 }
496563 }
497564
@@ -529,7 +596,9 @@ public struct Linux: Platform {
529596 }
530597
531598 return . rhel9
532- } else if let pd = [ PlatformDefinition . ubuntu1804, . ubuntu2004, . ubuntu2204, . ubuntu2404, . debian12, . fedora39] . first ( where: { $0. name == id + versionID } ) {
599+ } else if let pd = [
600+ PlatformDefinition . ubuntu1804, . ubuntu2004, . ubuntu2204, . ubuntu2404, . debian12, . fedora39,
601+ ] . first ( where: { $0. name == id + versionID } ) {
533602 return pd
534603 }
535604
@@ -559,7 +628,8 @@ public struct Linux: Platform {
559628 return " /bin/bash"
560629 }
561630
562- public func findToolchainLocation( _ ctx: SwiftlyCoreContext, _ toolchain: ToolchainVersion) - > URL {
631+ public func findToolchainLocation( _ ctx: SwiftlyCoreContext, _ toolchain: ToolchainVersion) - > URL
632+ {
563633 self . swiftlyToolchainsDir ( ctx) . appendingPathComponent ( " \( toolchain. name) " )
564634 }
565635
0 commit comments