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
@@ -29,8 +30,8 @@ struct PackageToJSPlugin: CommandPlugin {
2930 return """
3031 Please pass the `--swift-sdk` option to the " swift package " command.
3132
32- Did you mean:
33- \( didYouMean. joined ( separator: " " ) )
33+ Did you mean this?
34+ \( didYouMean. joined ( separator: " " ) )
3435"""
3536 } ) ,
3637 (
@@ -67,22 +68,69 @@ 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+ if filePath. hasPrefix ( packageDir. path) {
99+ // Emit hint for --allow-writing-to-package-directory if the destination path
100+ // is under the package directory
101+ let didYouMean = [
102+ " swift " , " package " , " --swift-sdk " , " wasm32-unknown-wasi " ,
103+ " plugin " , " --allow-writing-to-package-directory " ,
104+ " js " ,
105+ ] + arguments
106+ emitHintMessage (
107+ """
108+ Permission denied to write to \( filePath) .
109+ Please pass the `--allow-writing-to-package-directory` option to the " swift package " command.
110+
111+ Did you mean this?
112+ \( didYouMean. joined ( separator: " " ) )
113+ """
114+ )
115+ } else {
116+ // Emit hint for --allow-writing-to-directory <directory>
117+ // if the destination path is outside the package directory
118+ let didYouMean = [
119+ " swift " , " package " , " --swift-sdk " , " wasm32-unknown-wasi " ,
120+ " plugin " , " --allow-writing-to-directory " , " \( filePath) " ,
121+ " js " ,
122+ ] + arguments
123+ emitHintMessage (
124+ """
125+ Permission denied to write to \( filePath) .
126+ Please pass the `--allow-writing-to-directory <directory>` option to the " swift package " command.
127+
128+ Did you mean this?
129+ \( didYouMean. joined ( separator: " " ) )
130+ """
131+ )
132+ }
133+ }
86134 }
87135
88136 static let JAVASCRIPTKIT_PACKAGE_ID : Package . ID = " javascriptkit "
0 commit comments