Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CLI] Check with multiple arguments #91

Merged
merged 4 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 99 additions & 22 deletions crates/brioche/src/check.rs
Original file line number Diff line number Diff line change
@@ -1,51 +1,128 @@
use std::path::PathBuf;
use std::process::ExitCode;

use brioche_core::project::ProjectHash;
use brioche_core::project::Projects;
use brioche_core::reporter::ConsoleReporterKind;
use brioche_core::reporter::Reporter;
use brioche_core::Brioche;
use clap::Parser;
use tracing::Instrument;

use crate::consolidate_result;

#[derive(Debug, Parser)]
pub struct CheckArgs {
#[command(flatten)]
project: super::ProjectArgs,
project: super::MultipleProjectArgs,
}

pub async fn check(args: CheckArgs) -> anyhow::Result<ExitCode> {
let (reporter, mut guard) =
brioche_core::reporter::start_console_reporter(ConsoleReporterKind::Auto)?;

let brioche = brioche_core::BriocheBuilder::new(reporter).build().await?;
let brioche = brioche_core::BriocheBuilder::new(reporter.clone())
.build()
.await?;
let projects = brioche_core::project::Projects::default();

let check_future = async {
let project_hash = super::load_project(&brioche, &projects, &args.project).await?;
let mut error_result = Option::None;

let num_lockfiles_updated = projects.commit_dirty_lockfiles().await?;
if num_lockfiles_updated > 0 {
tracing::info!(num_lockfiles_updated, "updated lockfiles");
}
// Handle the case where no projects and no registries are specified
let projects_path =
if args.project.project.is_empty() && args.project.registry_project.is_empty() {
vec![PathBuf::from(".")]
} else {
args.project.project
};

let checked = brioche_core::script::check::check(&brioche, &projects, project_hash).await?;
// Loop over the projects
for project_path in projects_path {
let project_name = format!("project '{name}'", name = project_path.display());

guard.shutdown_console().await;
match projects.load(&brioche, &project_path, true).await {
Ok(project_hash) => {
let result =
run_check(&reporter, &brioche, &projects, project_hash, &project_name).await;
consolidate_result(&reporter, &project_name, result, &mut error_result);
}
Err(e) => {
consolidate_result(&reporter, &project_name, Err(e), &mut error_result);
}
}
}

let result = checked.ensure_ok(brioche_core::script::check::DiagnosticLevel::Message);
// Loop over the registry projects
for registry_project in args.project.registry_project {
let project_name = format!("registry project '{registry_project}'");

match result {
Ok(()) => {
println!("No errors found 🎉");
anyhow::Ok(ExitCode::SUCCESS)
match projects
.load_from_registry(
&brioche,
&registry_project,
&brioche_core::project::Version::Any,
)
.await
{
Ok(project_hash) => {
let result =
run_check(&reporter, &brioche, &projects, project_hash, &project_name).await;
consolidate_result(&reporter, &project_name, result, &mut error_result);
}
Err(diagnostics) => {
diagnostics.write(&brioche.vfs, &mut std::io::stdout())?;
anyhow::Ok(ExitCode::FAILURE)
Err(e) => {
consolidate_result(&reporter, &project_name, Err(e), &mut error_result);
}
}
};
}

let exit_code = check_future
.instrument(tracing::info_span!("check"))
.await?;
guard.shutdown_console().await;

let exit_code = if error_result.is_some() {
ExitCode::FAILURE
} else {
ExitCode::SUCCESS
};

Ok(exit_code)
}

async fn run_check(
reporter: &Reporter,
brioche: &Brioche,
projects: &Projects,
project_hash: ProjectHash,
project_name: &String,
) -> Result<bool, anyhow::Error> {
let num_lockfiles_updated = projects.commit_dirty_lockfiles().await?;
if num_lockfiles_updated > 0 {
tracing::info!(num_lockfiles_updated, "updated lockfiles");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing, I didn't touch this line, but should I?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine as-is, is there a reason it should be changed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I don't think so. I just wanted to raise the attention to this single call to tracing::info.

}

let result =
async { brioche_core::script::check::check(brioche, projects, project_hash).await }
.instrument(tracing::info_span!("check"))
.await?
.ensure_ok(brioche_core::script::check::DiagnosticLevel::Message);

match result {
Ok(()) => {
reporter.emit(superconsole::Lines::from_multiline_string(
&format!("No errors found in {project_name} 🎉",),
superconsole::style::ContentStyle::default(),
));

Ok(true)
}
Err(diagnostics) => {
let mut output = Vec::new();
diagnostics.write(&brioche.vfs, &mut output)?;

reporter.emit(superconsole::Lines::from_multiline_string(
&String::from_utf8(output)?,
superconsole::style::ContentStyle::default(),
));

Ok(false)
}
}
}
80 changes: 38 additions & 42 deletions crates/brioche/src/format.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use std::{
path::{Path, PathBuf},
process::ExitCode,
};
use std::{path::PathBuf, process::ExitCode};

use brioche_core::reporter::{ConsoleReporterKind, Reporter};
use brioche_core::{
project::{ProjectHash, Projects},
reporter::{ConsoleReporterKind, Reporter},
};
use clap::Parser;
use tracing::Instrument;

use crate::consolidate_result;

#[derive(Debug, Parser)]
pub struct FormatArgs {
/// The path to the project directory to format
Expand All @@ -22,28 +24,32 @@ pub async fn format(args: FormatArgs) -> anyhow::Result<ExitCode> {
let (reporter, mut guard) =
brioche_core::reporter::start_console_reporter(ConsoleReporterKind::Auto)?;

let brioche = brioche_core::BriocheBuilder::new(reporter.clone())
.build()
.await?;
let projects = brioche_core::project::Projects::default();

let mut error_result = Option::None;
for project_path in args.project {
match project_format(&reporter, &project_path, args.check).await {
Err(err) => {
reporter.emit(superconsole::Lines::from_multiline_string(
&format!(
"Error occurred while formatting project '{project_path}': {err}",
project_path = project_path.display(),
err = err
),
superconsole::style::ContentStyle {
foreground_color: Some(superconsole::style::Color::Red),
..superconsole::style::ContentStyle::default()
},
));

error_result = Some(());
// Loop over the projects
for project_path in args.project {
let project_name = format!("project '{name}'", name = project_path.display());

match projects.load(&brioche, &project_path, true).await {
Ok(project_hash) => {
let result = run_format(
&reporter,
&projects,
project_hash,
&project_name,
args.check,
)
.await;
consolidate_result(&reporter, &project_name, result, &mut error_result);
}
Ok(false) => {
error_result = Some(());
Err(e) => {
consolidate_result(&reporter, &project_name, Err(e), &mut error_result);
}
_ => {}
}
}

Expand All @@ -58,23 +64,18 @@ pub async fn format(args: FormatArgs) -> anyhow::Result<ExitCode> {
Ok(exit_code)
}

async fn project_format(
async fn run_format(
reporter: &Reporter,
project_path: &Path,
projects: &Projects,
project_hash: ProjectHash,
project_name: &String,
check: bool,
) -> Result<bool, anyhow::Error> {
let brioche = brioche_core::BriocheBuilder::new(reporter.clone())
.build()
.await?;
let projects = brioche_core::project::Projects::default();

let project_hash = projects.load(&brioche, project_path, true).await?;

let result = async {
if check {
brioche_core::script::format::check_format(&projects, project_hash).await
brioche_core::script::format::check_format(projects, project_hash).await
} else {
brioche_core::script::format::format(&projects, project_hash).await
brioche_core::script::format::format(projects, project_hash).await
}
}
.instrument(tracing::info_span!("format"))
Expand All @@ -89,8 +90,7 @@ async fn project_format(
if !files.is_empty() {
reporter.emit(superconsole::Lines::from_multiline_string(
&format!(
"The following files of project '{project_path}' have been formatted:\n{files}",
project_path = project_path.display(),
"The following files of {project_name} have been formatted:\n{files}",
files = files
.iter()
.map(|file| format!("- {}", file.display()))
Expand All @@ -104,19 +104,15 @@ async fn project_format(
Ok(true)
} else if files.is_empty() {
reporter.emit(superconsole::Lines::from_multiline_string(
&format!(
"All files of project '{project_path}' are formatted",
project_path = project_path.display()
),
&format!("All files of {project_name} are formatted",),
superconsole::style::ContentStyle::default(),
));

Ok(true)
} else {
reporter.emit(superconsole::Lines::from_multiline_string(
&format!(
"The following files of project '{project_path}' are not formatted:\n{files}",
project_path = project_path.display(),
"The following files of {project_name} are not formatted:\n{files}",
files = files
.iter()
.map(|file| format!("- {}", file.display()))
Expand Down
37 changes: 37 additions & 0 deletions crates/brioche/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,18 @@ struct ProjectArgs {
registry: Option<String>,
}

#[derive(Debug, clap::Args)]
#[group(required = false, multiple = false)]
struct MultipleProjectArgs {
/// The path of the project directory to build [default: .]
#[clap(short, long)]
project: Vec<PathBuf>,

/// The name of a registry project to build
#[clap(id = "registry", short, long)]
registry_project: Vec<String>,
}

async fn load_project(
brioche: &brioche_core::Brioche,
projects: &brioche_core::project::Projects,
Expand All @@ -253,3 +265,28 @@ async fn load_project(

Ok(project_hash)
}

fn consolidate_result(
reporter: &brioche_core::reporter::Reporter,
project_name: &String,
result: Result<bool, anyhow::Error>,
error_result: &mut Option<()>,
) {
match result {
Err(err) => {
reporter.emit(superconsole::Lines::from_multiline_string(
&format!("Error occurred with {project_name}: {err}", err = err),
superconsole::style::ContentStyle {
foreground_color: Some(superconsole::style::Color::Red),
..superconsole::style::ContentStyle::default()
},
));

*error_result = Some(());
}
Ok(false) => {
*error_result = Some(());
}
_ => {}
}
}