@@ -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 ) async throws {
335+ public func install(
336+ _ ctx: SwiftlyCoreContext , from tmpFile: URL , version: ToolchainVersion , verbose: Bool
337+ ) async 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 await ctx. print ( " Extracting toolchain... " )
@@ -378,7 +391,9 @@ public struct Linux: Platform {
378391 try self . runProgram ( tmpDir. appendingPathComponent ( " swiftly " ) . path, " init " )
379392 }
380393
381- public func uninstall( _ ctx: SwiftlyCoreContext , _ toolchain: ToolchainVersion , verbose _: Bool ) throws {
394+ public func uninstall( _ ctx: SwiftlyCoreContext , _ toolchain: ToolchainVersion , verbose _: Bool )
395+ throws
396+ {
382397 let toolchainDir = self . swiftlyToolchainsDir ( ctx) . appendingPathComponent ( toolchain. name)
383398 try FileManager . default. removeItem ( at: toolchainDir)
384399 }
@@ -393,7 +408,9 @@ public struct Linux: Platform {
393408 FileManager . default. temporaryDirectory. appendingPathComponent ( " swiftly- \( UUID ( ) ) " )
394409 }
395410
396- public func verifySignature( _ ctx: SwiftlyCoreContext , archiveDownloadURL: URL , archive: URL , verbose: Bool ) async throws {
411+ public func verifyToolchainSignature(
412+ _ ctx: SwiftlyCoreContext , toolchainFile: ToolchainFile , archive: URL , verbose: Bool
413+ ) async throws {
397414 if verbose {
398415 await ctx. print ( " Downloading toolchain signature... " )
399416 }
@@ -404,15 +421,15 @@ public struct Linux: Platform {
404421 try ? FileManager . default. removeItem ( at: sigFile)
405422 }
406423
407- try await ctx. httpClient. downloadFile (
408- url: archiveDownloadURL. appendingPathExtension ( " sig " ) ,
409- to: sigFile
410- )
424+ try await ctx. httpClient. getSwiftToolchainFileSignature ( toolchainFile) . download ( to: sigFile)
411425
412426 await ctx. print ( " Verifying toolchain signature... " )
413427 do {
414428 if let mockedHomeDir = ctx. mockedHomeDir {
415- try self . runProgram ( " gpg " , " --verify " , sigFile. path, archive. path, quiet: false , env: [ " GNUPGHOME " : mockedHomeDir. appendingPathComponent ( " .gnupg " ) . path] )
429+ try self . runProgram (
430+ " gpg " , " --verify " , sigFile. path, archive. path, quiet: false ,
431+ env: [ " GNUPGHOME " : mockedHomeDir. appendingPathComponent ( " .gnupg " ) . path]
432+ )
416433 } else {
417434 try self . runProgram ( " gpg " , " --verify " , sigFile. path, archive. path, quiet: !verbose)
418435 }
@@ -421,23 +438,65 @@ public struct Linux: Platform {
421438 }
422439 }
423440
424- private func manualSelectPlatform( _ ctx: SwiftlyCoreContext , _ platformPretty: String ? ) async -> PlatformDefinition {
441+ public func verifySwiftlySignature(
442+ _ ctx: SwiftlyCoreContext , archiveDownloadURL: URL , archive: URL , verbose: Bool
443+ ) async throws {
444+ if verbose {
445+ await ctx. print ( " Downloading swiftly signature... " )
446+ }
447+
448+ let sigFile = self . getTempFilePath ( )
449+ let _ = FileManager . default. createFile ( atPath: sigFile. path, contents: nil )
450+ defer {
451+ try ? FileManager . default. removeItem ( at: sigFile)
452+ }
453+
454+ try await ctx. httpClient. getSwiftlyReleaseSignature (
455+ url: archiveDownloadURL. appendingPathExtension ( " sig " )
456+ ) . download ( to: sigFile)
457+
458+ await ctx. print ( " Verifying swiftly signature... " )
459+ do {
460+ if let mockedHomeDir = ctx. mockedHomeDir {
461+ try self . runProgram (
462+ " gpg " , " --verify " , sigFile. path, archive. path, quiet: false ,
463+ env: [ " GNUPGHOME " : mockedHomeDir. appendingPathComponent ( " .gnupg " ) . path]
464+ )
465+ } else {
466+ try self . runProgram ( " gpg " , " --verify " , sigFile. path, archive. path, quiet: !verbose)
467+ }
468+ } catch {
469+ throw SwiftlyError ( message: " Signature verification failed: \( error) . " )
470+ }
471+ }
472+
473+ private func manualSelectPlatform( _ ctx: SwiftlyCoreContext , _ platformPretty: String ? ) async
474+ -> PlatformDefinition
475+ {
425476 if let platformPretty {
426- print ( " \( platformPretty) is not an officially supported platform, but the toolchains for another platform may still work on it. " )
477+ print (
478+ " \( platformPretty) is not an officially supported platform, but the toolchains for another platform may still work on it. "
479+ )
427480 } else {
428- print ( " This platform could not be detected, but a toolchain for one of the supported platforms may work on it. " )
481+ print (
482+ " This platform could not be detected, but a toolchain for one of the supported platforms may work on it. "
483+ )
429484 }
430485
431- let selections = self . linuxPlatforms. enumerated ( ) . map { " \( $0 + 1 ) ) \( $1. namePretty) " } . joined ( separator: " \n " )
486+ let selections = self . linuxPlatforms. enumerated ( ) . map { " \( $0 + 1 ) ) \( $1. namePretty) " } . joined (
487+ separator: " \n " )
432488
433- print ( """
434- Please select the platform to use for toolchain downloads:
489+ print (
490+ """
491+ Please select the platform to use for toolchain downloads:
435492
436- 0) Cancel
437- \( selections)
438- """ )
493+ 0) Cancel
494+ \( selections)
495+ """ )
439496
440- let choice = await ctx. readLine ( prompt: " Pick one of the available selections [0- \( self . linuxPlatforms. count) ] " ) ?? " 0 "
497+ let choice =
498+ await ctx. readLine ( prompt: " Pick one of the available selections [0- \( self . linuxPlatforms. count) ] " )
499+ ?? " 0 "
441500
442501 guard let choiceNum = Int ( choice) else {
443502 fatalError ( " Installation canceled " )
@@ -450,11 +509,15 @@ public struct Linux: Platform {
450509 return self . linuxPlatforms [ choiceNum - 1 ]
451510 }
452511
453- public func detectPlatform( _ ctx: SwiftlyCoreContext , disableConfirmation: Bool , platform: String ? ) async throws -> PlatformDefinition {
512+ public func detectPlatform(
513+ _ ctx: SwiftlyCoreContext , disableConfirmation: Bool , platform: String ?
514+ ) async throws -> PlatformDefinition {
454515 // We've been given a hint to use
455516 if let platform {
456517 guard let pd = linuxPlatforms. first ( where: { $0. nameFull == platform } ) else {
457- fatalError ( " Unrecognized platform \( platform) . Recognized values: \( self . linuxPlatforms. map ( \. nameFull) . joined ( separator: " , " ) ) . " )
518+ fatalError (
519+ " Unrecognized platform \( platform) . Recognized values: \( self . linuxPlatforms. map ( \. nameFull) . joined ( separator: " , " ) ) . "
520+ )
458521 }
459522
460523 return pd
@@ -492,9 +555,13 @@ public struct Linux: Platform {
492555 } else if info. hasPrefix ( " ID_LIKE= " ) {
493556 idlike = String ( info. dropFirst ( " ID_LIKE= " . count) ) . replacingOccurrences ( of: " \" " , with: " " )
494557 } else if info. hasPrefix ( " VERSION_ID= " ) {
495- versionID = String ( info. dropFirst ( " VERSION_ID= " . count) ) . replacingOccurrences ( of: " \" " , with: " " ) . replacingOccurrences ( of: " . " , with: " " )
558+ versionID = String ( info. dropFirst ( " VERSION_ID= " . count) ) . replacingOccurrences (
559+ of: " \" " , with: " "
560+ ) . replacingOccurrences ( of: " . " , with: " " )
496561 } else if info. hasPrefix ( " PRETTY_NAME= " ) {
497- platformPretty = String ( info. dropFirst ( " PRETTY_NAME= " . count) ) . replacingOccurrences ( of: " \" " , with: " " )
562+ platformPretty = String ( info. dropFirst ( " PRETTY_NAME= " . count) ) . replacingOccurrences (
563+ of: " \" " , with: " "
564+ )
498565 }
499566 }
500567
@@ -532,7 +599,9 @@ public struct Linux: Platform {
532599 }
533600
534601 return . rhel9
535- } else if let pd = [ PlatformDefinition . ubuntu1804, . ubuntu2004, . ubuntu2204, . ubuntu2404, . debian12, . fedora39] . first ( where: { $0. name == id + versionID } ) {
602+ } else if let pd = [
603+ PlatformDefinition . ubuntu1804, . ubuntu2004, . ubuntu2204, . ubuntu2404, . debian12, . fedora39,
604+ ] . first ( where: { $0. name == id + versionID } ) {
536605 return pd
537606 }
538607
@@ -562,7 +631,8 @@ public struct Linux: Platform {
562631 return " /bin/bash"
563632 }
564633
565- public func findToolchainLocation( _ ctx: SwiftlyCoreContext, _ toolchain: ToolchainVersion) - > URL {
634+ public func findToolchainLocation( _ ctx: SwiftlyCoreContext, _ toolchain: ToolchainVersion) - > URL
635+ {
566636 self . swiftlyToolchainsDir ( ctx) . appendingPathComponent ( " \( toolchain. name) " )
567637 }
568638
0 commit comments