@@ -19,6 +19,7 @@ use crossterm::{
1919 } ,
2020} ;
2121use objdiff_core:: {
22+ bindings:: diff:: DiffResult ,
2223 build:: {
2324 BuildConfig , BuildStatus ,
2425 watcher:: { Watcher , create_watcher} ,
@@ -28,7 +29,7 @@ use objdiff_core::{
2829 build_globset,
2930 path:: { check_path_buf, platform_path, platform_path_serde_option} ,
3031 } ,
31- diff:: { DiffObjConfig , MappingConfig , ObjectDiff } ,
32+ diff:: { self , DiffObjConfig , DiffSide , MappingConfig , ObjectDiff } ,
3233 jobs:: {
3334 Job , JobQueue , JobResult ,
3435 objdiff:: { ObjDiffConfig , start_build} ,
@@ -40,7 +41,10 @@ use typed_path::{Utf8PlatformPath, Utf8PlatformPathBuf};
4041
4142use crate :: {
4243 cmd:: apply_config_args,
43- util:: term:: crossterm_panic_handler,
44+ util:: {
45+ output:: { OutputFormat , write_output} ,
46+ term:: crossterm_panic_handler,
47+ } ,
4448 views:: { EventControlFlow , EventResult , UiView , function_diff:: FunctionDiffUi } ,
4549} ;
4650
@@ -60,6 +64,12 @@ pub struct Args {
6064 #[ argp( option, short = 'u' ) ]
6165 /// Unit name within project
6266 unit : Option < String > ,
67+ #[ argp( option, short = 'o' , from_str_fn( platform_path) ) ]
68+ /// Output file (one-shot mode) ("-" for stdout)
69+ output : Option < Utf8PlatformPathBuf > ,
70+ #[ argp( option) ]
71+ /// Output format (json, json-pretty, proto) (default: json)
72+ format : Option < String > ,
6373 #[ argp( positional) ]
6474 /// Function symbol to diff
6575 symbol : Option < String > ,
@@ -158,7 +168,41 @@ pub fn run(args: Args) -> Result<()> {
158168 _ => bail ! ( "Either target and base or project and unit must be specified" ) ,
159169 } ;
160170
161- run_interactive ( args, target_path, base_path, project_config, unit_options)
171+ if let Some ( output) = & args. output {
172+ run_oneshot ( & args, output, target_path. as_deref ( ) , base_path. as_deref ( ) , unit_options)
173+ } else {
174+ run_interactive ( args, target_path, base_path, project_config, unit_options)
175+ }
176+ }
177+
178+ fn run_oneshot (
179+ args : & Args ,
180+ output : & Utf8PlatformPath ,
181+ target_path : Option < & Utf8PlatformPath > ,
182+ base_path : Option < & Utf8PlatformPath > ,
183+ unit_options : Option < ProjectOptions > ,
184+ ) -> Result < ( ) > {
185+ let output_format = OutputFormat :: from_option ( args. format . as_deref ( ) ) ?;
186+ let ( diff_config, mapping_config) = build_config_from_args ( args, None , unit_options. as_ref ( ) ) ?;
187+ let target = target_path
188+ . map ( |p| {
189+ obj:: read:: read ( p. as_ref ( ) , & diff_config, DiffSide :: Target )
190+ . with_context ( || format ! ( "Loading {p}" ) )
191+ } )
192+ . transpose ( ) ?;
193+ let base = base_path
194+ . map ( |p| {
195+ obj:: read:: read ( p. as_ref ( ) , & diff_config, DiffSide :: Base )
196+ . with_context ( || format ! ( "Loading {p}" ) )
197+ } )
198+ . transpose ( ) ?;
199+ let result =
200+ diff:: diff_objs ( target. as_ref ( ) , base. as_ref ( ) , None , & diff_config, & mapping_config) ?;
201+ let left = target. as_ref ( ) . and_then ( |o| result. left . as_ref ( ) . map ( |d| ( o, d) ) ) ;
202+ let right = base. as_ref ( ) . and_then ( |o| result. right . as_ref ( ) . map ( |d| ( o, d) ) ) ;
203+ let diff_result = DiffResult :: new ( left, right, & diff_config) ?;
204+ write_output ( & diff_result, Some ( output) , output_format) ?;
205+ Ok ( ( ) )
162206}
163207
164208fn build_config_from_args (
0 commit comments