55@preconcurrency import class Foundation. Process
66@preconcurrency import class Foundation. ProcessInfo
77@preconcurrency import class Foundation. FileManager
8+ @preconcurrency import struct Foundation. CocoaError
89@preconcurrency import func Foundation. fputs
910@preconcurrency import func Foundation. exit
1011@preconcurrency import var Foundation. stderr
@@ -27,10 +28,10 @@ struct PackageToJSPlugin: CommandPlugin {
2728 " swift " , " package " , " --swift-sdk " , " wasm32-unknown-wasi " , " js " ,
2829 ] + arguments
2930 return """
30- Please pass the `--swift-sdk` option to the " swift package " command .
31+ Please pass `--swift-sdk` to " swift package " .
3132
32- Did you mean:
33- \( didYouMean. joined ( separator: " " ) )
33+ Did you mean this?
34+ \( didYouMean. joined ( separator: " " ) )
3435"""
3536 } ) ,
3637 (
@@ -67,22 +68,70 @@ struct PackageToJSPlugin: CommandPlugin {
6768"""
6869 } ) ,
6970 ]
71+ 72+ private func emitHintMessage( _ message: String ) {
73+ printStderr ( " \n " + " \u{001B} [1m \u{001B} [97mHint: \u{001B} [0m " + message)
74+ }
75+ 7076 private func reportBuildFailure(
7177 _ build: PackageManager . BuildResult , _ arguments: [ String ]
7278 ) {
7379 for diagnostic in Self . friendlyBuildDiagnostics {
7480 if let message = diagnostic ( build, arguments) {
75- printStderr ( " \n " + " \u{001B} [1m \u{001B} [97mHint: \u{001B} [0m " + message)
81+ emitHintMessage ( message)
82+ return
7683 }
7784 }
7885 }
7986
8087 func performCommand( context: PluginContext , arguments: [ String ] ) throws {
81- if arguments. first == " test " {
82- return try performTestCommand ( context: context, arguments: Array ( arguments. dropFirst ( ) ) )
83- }
88+ do {
89+ if arguments. first == " test " {
90+ return try performTestCommand ( context: context, arguments: Array ( arguments. dropFirst ( ) ) )
91+ }
92+ 93+ return try performBuildCommand ( context: context, arguments: arguments)
94+ } catch let error as CocoaError where error. code == . fileWriteNoPermission {
95+ guard let filePath = error. filePath else { throw error }
8496
85- return try performBuildCommand ( context: context, arguments: arguments)
97+ let packageDir = context. package . directoryURL
98+ printStderr ( " \n \u{001B} [1m \u{001B} [91merror: \u{001B} [0m \( error. localizedDescription) " )
99+ 100+ if filePath. hasPrefix ( packageDir. path) {
101+ // Emit hint for --allow-writing-to-package-directory if the destination path
102+ // is under the package directory
103+ let didYouMean = [
104+ " swift " , " package " , " --swift-sdk " , " wasm32-unknown-wasi " ,
105+ " plugin " , " --allow-writing-to-package-directory " ,
106+ " js " ,
107+ ] + arguments
108+ emitHintMessage (
109+ """
110+ Please pass `--allow-writing-to-package-directory` to " swift package " .
111+
112+ Did you mean this?
113+ \( didYouMean. joined ( separator: " " ) )
114+ """
115+ )
116+ } else {
117+ // Emit hint for --allow-writing-to-directory <directory>
118+ // if the destination path is outside the package directory
119+ let didYouMean = [
120+ " swift " , " package " , " --swift-sdk " , " wasm32-unknown-wasi " ,
121+ " plugin " , " --allow-writing-to-directory " , " \( filePath) " ,
122+ " js " ,
123+ ] + arguments
124+ emitHintMessage (
125+ """
126+ Please pass `--allow-writing-to-directory <directory>` to " swift package " .
127+
128+ Did you mean this?
129+ \( didYouMean. joined ( separator: " " ) )
130+ """
131+ )
132+ }
133+ exit ( 1 )
134+ }
86135 }
87136
88137 static let JAVASCRIPTKIT_PACKAGE_ID : Package . ID = " javascriptkit "
0 commit comments