Skip to content

Commit

Permalink
Exit with an error if there are check failures (#12735)
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaReiser authored Aug 8, 2024
1 parent dc6aafe commit df7345e
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 37 deletions.
105 changes: 73 additions & 32 deletions crates/red_knot/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::num::NonZeroUsize;
use std::process::ExitCode;
use std::sync::Mutex;

use clap::Parser;
use colored::Colorize;
use crossbeam::channel as crossbeam_channel;
use red_knot_workspace::site_packages::site_packages_dirs_of_venv;

use red_knot_server::run_server;
use red_knot_workspace::db::RootDatabase;
use red_knot_workspace::site_packages::site_packages_dirs_of_venv;
use red_knot_workspace::watch;
use red_knot_workspace::watch::WorkspaceWatcher;
use red_knot_workspace::workspace::WorkspaceMetadata;
Expand Down Expand Up @@ -83,13 +85,34 @@ pub enum Command {
Server,
}

#[allow(
clippy::print_stdout,
clippy::unnecessary_wraps,
clippy::print_stderr,
clippy::dbg_macro
)]
pub fn main() -> anyhow::Result<()> {
#[allow(clippy::print_stdout, clippy::unnecessary_wraps, clippy::print_stderr)]
pub fn main() -> ExitCode {
match run() {
Ok(status) => status.into(),
Err(error) => {
{
use std::io::Write;

// Use `writeln` instead of `eprintln` to avoid panicking when the stderr pipe is broken.
let mut stderr = std::io::stderr().lock();

// This communicates that this isn't a linter error but ruff itself hard-errored for
// some reason (e.g. failed to resolve the configuration)
writeln!(stderr, "{}", "ruff failed".red().bold()).ok();
// Currently we generally only see one error, but e.g. with io errors when resolving
// the configuration it is help to chain errors ("resolving configuration failed" ->
// "failed to read file: subdir/pyproject.toml")
for cause in error.chain() {
writeln!(stderr, " {} {cause}", "Cause:".bold()).ok();
}
}

ExitStatus::Error.into()
}
}
}

fn run() -> anyhow::Result<ExitStatus> {
let Args {
command,
current_directory,
Expand All @@ -101,20 +124,12 @@ pub fn main() -> anyhow::Result<()> {
watch,
} = Args::parse_from(std::env::args().collect::<Vec<_>>());

let verbosity = verbosity.level();
countme::enable(verbosity.is_trace());

if matches!(command, Some(Command::Server)) {
let four = NonZeroUsize::new(4).unwrap();

// by default, we set the number of worker threads to `num_cpus`, with a maximum of 4.
let worker_threads = std::thread::available_parallelism()
.unwrap_or(four)
.max(four);

return red_knot_server::Server::new(worker_threads)?.run();
return run_server().map(|()| ExitStatus::Success);
}

let verbosity = verbosity.level();
countme::enable(verbosity.is_trace());
let _guard = setup_tracing(verbosity)?;

let cwd = if let Some(cwd) = current_directory {
Expand Down Expand Up @@ -167,17 +182,35 @@ pub fn main() -> anyhow::Result<()> {
}
})?;

if watch {
main_loop.watch(&mut db)?;
let exit_status = if watch {
main_loop.watch(&mut db)?
} else {
main_loop.run(&mut db);
main_loop.run(&mut db)
};

tracing::trace!("Counts for entire CLI run :\n{}", countme::get_all());
tracing::trace!("Counts for entire CLI run:\n{}", countme::get_all());

std::mem::forget(db);

Ok(())
Ok(exit_status)
}

#[derive(Copy, Clone)]
pub enum ExitStatus {
/// Checking was successful and there were no errors.
Success = 0,

/// Checking was successful but there were errors.
Failure = 1,

/// Checking failed.
Error = 2,
}

impl From<ExitStatus> for ExitCode {
fn from(status: ExitStatus) -> Self {
ExitCode::from(status as u8)
}
}

struct MainLoop {
Expand Down Expand Up @@ -205,7 +238,7 @@ impl MainLoop {
)
}

fn watch(mut self, db: &mut RootDatabase) -> anyhow::Result<()> {
fn watch(mut self, db: &mut RootDatabase) -> anyhow::Result<ExitStatus> {
tracing::debug!("Starting watch mode");
let sender = self.sender.clone();
let watcher = watch::directory_watcher(move |event| {
Expand All @@ -216,19 +249,21 @@ impl MainLoop {

self.run(db);

Ok(())
Ok(ExitStatus::Success)
}

fn run(mut self, db: &mut RootDatabase) {
fn run(mut self, db: &mut RootDatabase) -> ExitStatus {
self.sender.send(MainLoopMessage::CheckWorkspace).unwrap();

self.main_loop(db);
let result = self.main_loop(db);

tracing::debug!("Exiting main loop");

result
}

#[allow(clippy::print_stderr)]
fn main_loop(&mut self, db: &mut RootDatabase) {
fn main_loop(&mut self, db: &mut RootDatabase) -> ExitStatus {
// Schedule the first check.
tracing::debug!("Starting main loop");

Expand Down Expand Up @@ -263,7 +298,11 @@ impl MainLoop {
}

if self.watcher.is_none() {
return;
return if result.is_empty() {
ExitStatus::Success
} else {
ExitStatus::Failure
};
}

tracing::trace!("Counts after last check:\n{}", countme::get_all());
Expand All @@ -279,12 +318,14 @@ impl MainLoop {
self.sender.send(MainLoopMessage::CheckWorkspace).unwrap();
}
MainLoopMessage::Exit => {
return;
return ExitStatus::Success;
}
}

tracing::debug!("Waiting for next main loop message.");
}

ExitStatus::Success
}
}

Expand Down
20 changes: 19 additions & 1 deletion crates/red_knot_server/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#![allow(dead_code)]

use anyhow::Context;
pub use edit::{DocumentKey, NotebookDocument, PositionEncoding, TextDocument};
pub use server::Server;
pub use session::{ClientSettings, DocumentQuery, DocumentSnapshot, Session};
use std::num::NonZeroUsize;

use crate::server::Server;

#[macro_use]
mod message;
Expand All @@ -23,3 +26,18 @@ pub(crate) type Result<T> = anyhow::Result<T>;
pub(crate) fn version() -> &'static str {
env!("CARGO_PKG_VERSION")
}

pub fn run_server() -> anyhow::Result<()> {
let four = NonZeroUsize::new(4).unwrap();

// by default, we set the number of worker threads to `num_cpus`, with a maximum of 4.
let worker_threads = std::thread::available_parallelism()
.unwrap_or(four)
.max(four);

Server::new(worker_threads)
.context("Failed to start server")?
.run()?;

Ok(())
}
6 changes: 3 additions & 3 deletions crates/red_knot_server/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ pub(crate) use connection::ClientSender;

pub(crate) type Result<T> = std::result::Result<T, api::Error>;

pub struct Server {
pub(crate) struct Server {
connection: Connection,
client_capabilities: ClientCapabilities,
worker_threads: NonZeroUsize,
session: Session,
}

impl Server {
pub fn new(worker_threads: NonZeroUsize) -> crate::Result<Self> {
pub(crate) fn new(worker_threads: NonZeroUsize) -> crate::Result<Self> {
let connection = ConnectionInitializer::stdio();

let (id, init_params) = connection.initialize_start()?;
Expand Down Expand Up @@ -113,7 +113,7 @@ impl Server {
})
}

pub fn run(self) -> crate::Result<()> {
pub(crate) fn run(self) -> crate::Result<()> {
type PanicHook = Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>;
struct RestorePanicHook {
hook: Option<PanicHook>,
Expand Down
1 change: 0 additions & 1 deletion crates/ruff/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ pub fn main() -> ExitCode {
match run(args) {
Ok(code) => code.into(),
Err(err) => {
#[allow(clippy::print_stderr)]
{
use std::io::Write;

Expand Down

0 comments on commit df7345e

Please sign in to comment.