forge/cmd/
flatten.rs
1use clap::{Parser, ValueHint};
2use eyre::Result;
3use foundry_cli::{
4 opts::{BuildOpts, ProjectPathOpts},
5 utils::LoadConfig,
6};
7use foundry_common::{compile::with_compilation_reporter, fs};
8use foundry_compilers::{
9 compilers::solc::SolcLanguage,
10 error::SolcError,
11 flatten::{Flattener, FlattenerError},
12};
13use std::path::PathBuf;
14
15#[derive(Clone, Debug, Parser)]
17pub struct FlattenArgs {
18 #[arg(value_hint = ValueHint::FilePath, value_name = "PATH")]
20 pub target_path: PathBuf,
21
22 #[arg(
26 long,
27 short,
28 value_hint = ValueHint::FilePath,
29 value_name = "PATH",
30 )]
31 pub output: Option<PathBuf>,
32
33 #[command(flatten)]
34 project_paths: ProjectPathOpts,
35}
36
37impl FlattenArgs {
38 pub fn run(self) -> Result<()> {
39 let Self { target_path, output, project_paths } = self;
40
41 let build = BuildOpts { project_paths, ..Default::default() };
43 let config = build.load_config()?;
44 let project = config.ephemeral_project()?;
45
46 let target_path = dunce::canonicalize(target_path)?;
47
48 let flattener =
49 with_compilation_reporter(true, || Flattener::new(project.clone(), &target_path));
50
51 let flattened = match flattener {
52 Ok(flattener) => Ok(flattener.flatten()),
53 Err(FlattenerError::Compilation(_)) => {
54 project.paths.with_language::<SolcLanguage>().flatten(&target_path)
58 }
59 Err(FlattenerError::Other(err)) => Err(err),
60 }
61 .map_err(|err: SolcError| eyre::eyre!("Failed to flatten: {err}"))?;
62
63 match output {
64 Some(output) => {
65 fs::create_dir_all(output.parent().unwrap())?;
66 fs::write(&output, flattened)?;
67 sh_println!("Flattened file written at {}", output.display())?;
68 }
69 None => sh_println!("{flattened}")?,
70 };
71
72 Ok(())
73 }
74}