@@ -6,6 +6,10 @@ use crate::process::exec_piping;
6
6
use anyhow:: Result ;
7
7
use camino:: Utf8PathBuf ;
8
8
use libloading:: library_filename;
9
+ use scarb_ui:: { Message , OutputFormat } ;
10
+ use serde:: { Serialize , Serializer } ;
11
+ use serde_json:: value:: RawValue ;
12
+ use std:: fmt:: Display ;
9
13
use std:: process:: Command ;
10
14
use tracing:: trace_span;
11
15
@@ -62,6 +66,7 @@ fn run_cargo(action: CargoAction, package: &Package, ws: &Workspace<'_>) -> Resu
62
66
let cmd = CargoCommand {
63
67
action,
64
68
current_dir : package. root ( ) . to_path_buf ( ) ,
69
+ output_format : ws. config ( ) . ui ( ) . output_format ( ) ,
65
70
target_dir : package
66
71
. target_path ( ws. config ( ) )
67
72
. path_unchecked ( )
@@ -83,9 +88,33 @@ enum CargoAction {
83
88
struct CargoCommand {
84
89
current_dir : Utf8PathBuf ,
85
90
target_dir : Utf8PathBuf ,
91
+ output_format : OutputFormat ,
86
92
action : CargoAction ,
87
93
}
88
94
95
+ enum CargoOutputFormat {
96
+ Human ,
97
+ Json ,
98
+ }
99
+
100
+ impl Display for CargoOutputFormat {
101
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
102
+ match self {
103
+ CargoOutputFormat :: Human => write ! ( f, "human" ) ,
104
+ CargoOutputFormat :: Json => write ! ( f, "json" ) ,
105
+ }
106
+ }
107
+ }
108
+
109
+ impl From < OutputFormat > for CargoOutputFormat {
110
+ fn from ( format : OutputFormat ) -> Self {
111
+ match format {
112
+ OutputFormat :: Text => CargoOutputFormat :: Human ,
113
+ OutputFormat :: Json => CargoOutputFormat :: Json ,
114
+ }
115
+ }
116
+ }
117
+
89
118
impl From < CargoCommand > for Command {
90
119
fn from ( args : CargoCommand ) -> Self {
91
120
let mut cmd = Command :: new ( "cargo" ) ;
@@ -99,6 +128,9 @@ impl From<CargoCommand> for Command {
99
128
CargoAction :: Fetch => ( ) ,
100
129
_ => {
101
130
cmd. arg ( "--release" ) ;
131
+ cmd. arg ( "--message-format" ) ;
132
+ let output_format: CargoOutputFormat = args. output_format . into ( ) ;
133
+ cmd. arg ( output_format. to_string ( ) ) ;
102
134
cmd. arg ( "--target-dir" ) ;
103
135
cmd. arg ( args. target_dir ) ;
104
136
}
@@ -111,7 +143,33 @@ fn exec(cmd: &mut Command, config: &Config) -> Result<()> {
111
143
exec_piping (
112
144
cmd,
113
145
config,
114
- |line : & str | config. ui ( ) . print ( line) ,
115
- |line : & str | config. ui ( ) . print ( line) ,
146
+ |line : & str | config. ui ( ) . print ( PipedText :: new ( line) ) ,
147
+ |line : & str | config. ui ( ) . print ( PipedText :: new ( line) ) ,
116
148
)
117
149
}
150
+
151
+ /// This message can be used for piped text from subprocesses.
152
+ ///
153
+ /// It accepts either a string or a JSON string.
154
+ /// If the input is a JSON string, it can be serialized as a structured message.
155
+ /// Otherwise, the structured message will be skipped.
156
+ pub struct PipedText ( String ) ;
157
+
158
+ impl PipedText {
159
+ pub fn new ( text : impl Into < String > ) -> Self {
160
+ Self ( text. into ( ) )
161
+ }
162
+ }
163
+
164
+ impl Message for PipedText {
165
+ fn text ( self ) -> String {
166
+ self . 0
167
+ }
168
+
169
+ fn structured < S : Serializer > ( self , ser : S ) -> Result < S :: Ok , S :: Error > {
170
+ match serde_json:: from_str :: < & RawValue > ( self . 0 . as_str ( ) ) {
171
+ Ok ( value) => value. serialize ( ser) ,
172
+ Err ( _e) => Self :: skip_structured ( ser) ,
173
+ }
174
+ }
175
+ }
0 commit comments