chore: use nightly rustfmt rules
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ia3745c82c92a78e8326d2e0e446f20d66a6a6964
This commit is contained in:
parent
b0a9a9ba5b
commit
c3321858c4
11 changed files with 912 additions and 799 deletions
|
|
@ -1 +1,27 @@
|
|||
condense_wildcard_suffixes = true
|
||||
doc_comment_code_block_width = 80
|
||||
edition = "2024" # Keep in sync with Cargo.toml.
|
||||
enum_discrim_align_threshold = 60
|
||||
force_explicit_abi = false
|
||||
force_multiline_blocks = true
|
||||
format_code_in_doc_comments = true
|
||||
format_macro_matchers = true
|
||||
format_strings = true
|
||||
group_imports = "StdExternalCrate"
|
||||
hex_literal_case = "Upper"
|
||||
imports_granularity = "Crate"
|
||||
imports_layout = "HorizontalVertical"
|
||||
inline_attribute_width = 60
|
||||
match_block_trailing_comma = true
|
||||
max_width = 80
|
||||
newline_style = "Unix"
|
||||
normalize_comments = true
|
||||
normalize_doc_attributes = true
|
||||
overflow_delimited_expr = true
|
||||
struct_field_align_threshold = 60
|
||||
tab_spaces = 2
|
||||
unstable_features = true
|
||||
use_field_init_shorthand = true
|
||||
use_try_shorthand = true
|
||||
wrap_comments = true
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
use crate::error::Result;
|
||||
use crate::util::{HashExtractor, NixErrorClassifier, NixFileFixer, handle_nix_with_retry};
|
||||
use crate::{
|
||||
error::Result,
|
||||
util::{
|
||||
HashExtractor,
|
||||
NixErrorClassifier,
|
||||
NixFileFixer,
|
||||
handle_nix_with_retry,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn handle_nix_build(
|
||||
args: &[String],
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
use std::{
|
||||
collections::VecDeque,
|
||||
io::{self, Read, Write},
|
||||
process::{Command, ExitStatus, Output, Stdio},
|
||||
};
|
||||
|
||||
use crate::error::{EhError, Result};
|
||||
use std::collections::VecDeque;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::process::{Command, ExitStatus, Output, Stdio};
|
||||
|
||||
/// Trait for log interception and output handling.
|
||||
pub trait LogInterceptor: Send {
|
||||
|
|
@ -60,7 +63,11 @@ impl NixCommand {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn env<K: Into<String>, V: Into<String>>(mut self, key: K, value: V) -> Self {
|
||||
pub fn env<K: Into<String>, V: Into<String>>(
|
||||
mut self,
|
||||
key: K,
|
||||
value: V,
|
||||
) -> Self {
|
||||
self.env.push((key.into(), value.into()));
|
||||
self
|
||||
}
|
||||
|
|
@ -91,7 +98,9 @@ impl NixCommand {
|
|||
let mut cmd = Command::new("nix");
|
||||
cmd.arg(&self.subcommand);
|
||||
|
||||
if self.print_build_logs && !self.args.iter().any(|a| a == "--no-build-output") {
|
||||
if self.print_build_logs
|
||||
&& !self.args.iter().any(|a| a == "--no-build-output")
|
||||
{
|
||||
cmd.arg("--print-build-logs");
|
||||
}
|
||||
if self.impure {
|
||||
|
|
@ -113,11 +122,15 @@ impl NixCommand {
|
|||
cmd.stderr(Stdio::piped());
|
||||
|
||||
let mut child = cmd.spawn()?;
|
||||
let child_stdout = child.stdout.take().ok_or_else(|| EhError::CommandFailed {
|
||||
let child_stdout = child.stdout.take().ok_or_else(|| {
|
||||
EhError::CommandFailed {
|
||||
command: format!("nix {}", self.subcommand),
|
||||
}
|
||||
})?;
|
||||
let child_stderr = child.stderr.take().ok_or_else(|| EhError::CommandFailed {
|
||||
let child_stderr = child.stderr.take().ok_or_else(|| {
|
||||
EhError::CommandFailed {
|
||||
command: format!("nix {}", self.subcommand),
|
||||
}
|
||||
})?;
|
||||
let mut stdout = child_stdout;
|
||||
let mut stderr = child_stderr;
|
||||
|
|
@ -132,24 +145,24 @@ impl NixCommand {
|
|||
let mut did_something = false;
|
||||
|
||||
match stdout.read(&mut out_buf) {
|
||||
Ok(0) => {}
|
||||
Ok(0) => {},
|
||||
Ok(n) => {
|
||||
interceptor.on_stdout(&out_buf[..n]);
|
||||
out_queue.push_back(Vec::from(&out_buf[..n]));
|
||||
did_something = true;
|
||||
}
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
|
||||
},
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {},
|
||||
Err(e) => return Err(EhError::Io(e)),
|
||||
}
|
||||
|
||||
match stderr.read(&mut err_buf) {
|
||||
Ok(0) => {}
|
||||
Ok(0) => {},
|
||||
Ok(n) => {
|
||||
interceptor.on_stderr(&err_buf[..n]);
|
||||
err_queue.push_back(Vec::from(&err_buf[..n]));
|
||||
did_something = true;
|
||||
}
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
|
||||
},
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {},
|
||||
Err(e) => return Err(EhError::Io(e)),
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +180,9 @@ impl NixCommand {
|
|||
let mut cmd = Command::new("nix");
|
||||
cmd.arg(&self.subcommand);
|
||||
|
||||
if self.print_build_logs && !self.args.iter().any(|a| a == "--no-build-output") {
|
||||
if self.print_build_logs
|
||||
&& !self.args.iter().any(|a| a == "--no-build-output")
|
||||
{
|
||||
cmd.arg("--print-build-logs");
|
||||
}
|
||||
if self.impure {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::{env, path::Path};
|
||||
|
||||
use eh::{Cli, Command, CommandFactory, Parser};
|
||||
use error::Result;
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
|
||||
mod build;
|
||||
mod command;
|
||||
|
|
@ -26,36 +26,45 @@ fn main() {
|
|||
Err(e) => {
|
||||
eprintln!("Error: {e}");
|
||||
std::process::exit(e.exit_code());
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Design partially taken from Stash
|
||||
fn dispatch_multicall(app_name: &str, args: std::env::Args) -> Option<Result<i32>> {
|
||||
fn dispatch_multicall(
|
||||
app_name: &str,
|
||||
args: std::env::Args,
|
||||
) -> Option<Result<i32>> {
|
||||
let rest: Vec<String> = args.collect();
|
||||
let hash_extractor = util::RegexHashExtractor;
|
||||
let fixer = util::DefaultNixFileFixer;
|
||||
let classifier = util::DefaultNixErrorClassifier;
|
||||
|
||||
match app_name {
|
||||
"nr" => Some(run::handle_nix_run(
|
||||
"nr" => {
|
||||
Some(run::handle_nix_run(
|
||||
&rest,
|
||||
&hash_extractor,
|
||||
&fixer,
|
||||
&classifier,
|
||||
)),
|
||||
"ns" => Some(shell::handle_nix_shell(
|
||||
))
|
||||
},
|
||||
"ns" => {
|
||||
Some(shell::handle_nix_shell(
|
||||
&rest,
|
||||
&hash_extractor,
|
||||
&fixer,
|
||||
&classifier,
|
||||
)),
|
||||
"nb" => Some(build::handle_nix_build(
|
||||
))
|
||||
},
|
||||
"nb" => {
|
||||
Some(build::handle_nix_build(
|
||||
&rest,
|
||||
&hash_extractor,
|
||||
&fixer,
|
||||
&classifier,
|
||||
)),
|
||||
))
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -82,20 +91,20 @@ fn run_app() -> Result<i32> {
|
|||
match cli.command {
|
||||
Some(Command::Run { args }) => {
|
||||
run::handle_nix_run(&args, &hash_extractor, &fixer, &classifier)
|
||||
}
|
||||
},
|
||||
|
||||
Some(Command::Shell { args }) => {
|
||||
shell::handle_nix_shell(&args, &hash_extractor, &fixer, &classifier)
|
||||
}
|
||||
},
|
||||
|
||||
Some(Command::Build { args }) => {
|
||||
build::handle_nix_build(&args, &hash_extractor, &fixer, &classifier)
|
||||
}
|
||||
},
|
||||
|
||||
_ => {
|
||||
Cli::command().print_help()?;
|
||||
println!();
|
||||
Ok(0)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
use crate::error::Result;
|
||||
use crate::util::{HashExtractor, NixErrorClassifier, NixFileFixer, handle_nix_with_retry};
|
||||
use crate::{
|
||||
error::Result,
|
||||
util::{
|
||||
HashExtractor,
|
||||
NixErrorClassifier,
|
||||
NixFileFixer,
|
||||
handle_nix_with_retry,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn handle_nix_run(
|
||||
args: &[String],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
use crate::error::Result;
|
||||
use crate::util::{HashExtractor, NixErrorClassifier, NixFileFixer, handle_nix_with_retry};
|
||||
use crate::{
|
||||
error::Result,
|
||||
util::{
|
||||
HashExtractor,
|
||||
NixErrorClassifier,
|
||||
NixFileFixer,
|
||||
handle_nix_with_retry,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn handle_nix_shell(
|
||||
args: &[String],
|
||||
|
|
|
|||
|
|
@ -1,13 +1,19 @@
|
|||
use crate::command::{NixCommand, StdIoInterceptor};
|
||||
use crate::error::{EhError, Result};
|
||||
use std::{
|
||||
fs,
|
||||
io::Write,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use regex::Regex;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tracing::{info, warn};
|
||||
use walkdir::WalkDir;
|
||||
use yansi::Paint;
|
||||
|
||||
use crate::{
|
||||
command::{NixCommand, StdIoInterceptor},
|
||||
error::{EhError, Result},
|
||||
};
|
||||
|
||||
pub trait HashExtractor {
|
||||
fn extract_hash(&self, stderr: &str) -> Option<String>;
|
||||
}
|
||||
|
|
@ -100,8 +106,10 @@ impl NixFileFixer for DefaultNixFileFixer {
|
|||
}
|
||||
}
|
||||
if replaced {
|
||||
fs::write(file_path, new_content).map_err(|_| EhError::HashFixFailed {
|
||||
fs::write(file_path, new_content).map_err(|_| {
|
||||
EhError::HashFixFailed {
|
||||
path: file_path.to_string_lossy().to_string(),
|
||||
}
|
||||
})?;
|
||||
Ok(true)
|
||||
} else {
|
||||
|
|
@ -198,20 +206,21 @@ pub fn handle_nix_with_retry(
|
|||
}
|
||||
let retry_status = retry_cmd.run_with_logs(StdIoInterceptor)?;
|
||||
return Ok(retry_status.code().unwrap_or(1));
|
||||
}
|
||||
},
|
||||
Ok(false) => {
|
||||
// No files were fixed, continue with normal error handling
|
||||
}
|
||||
},
|
||||
Err(EhError::NoNixFilesFound) => {
|
||||
warn!("No .nix files found to fix hash in");
|
||||
// Continue with normal error handling
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
return Err(e);
|
||||
}
|
||||
},
|
||||
}
|
||||
} else if stderr.contains("hash") || stderr.contains("sha256") {
|
||||
// If there's a hash-related error but we couldn't extract it, that's a failure
|
||||
// If there's a hash-related error but we couldn't extract it, that's a
|
||||
// failure
|
||||
return Err(EhError::HashExtractionFailed);
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +228,9 @@ pub fn handle_nix_with_retry(
|
|||
if stderr.contains("has an unfree license") && stderr.contains("refusing") {
|
||||
warn!(
|
||||
"{}",
|
||||
Paint::yellow("⚠ Unfree package detected, retrying with NIXPKGS_ALLOW_UNFREE=1...")
|
||||
Paint::yellow(
|
||||
"⚠ Unfree package detected, retrying with NIXPKGS_ALLOW_UNFREE=1..."
|
||||
)
|
||||
);
|
||||
let mut retry_cmd = NixCommand::new(subcommand)
|
||||
.print_build_logs(true)
|
||||
|
|
@ -232,11 +243,14 @@ pub fn handle_nix_with_retry(
|
|||
let retry_status = retry_cmd.run_with_logs(StdIoInterceptor)?;
|
||||
return Ok(retry_status.code().unwrap_or(1));
|
||||
}
|
||||
if stderr.contains("has been marked as insecure") && stderr.contains("refusing") {
|
||||
if stderr.contains("has been marked as insecure")
|
||||
&& stderr.contains("refusing")
|
||||
{
|
||||
warn!(
|
||||
"{}",
|
||||
Paint::yellow(
|
||||
"⚠ Insecure package detected, retrying with NIXPKGS_ALLOW_INSECURE=1..."
|
||||
"⚠ Insecure package detected, retrying with \
|
||||
NIXPKGS_ALLOW_INSECURE=1..."
|
||||
)
|
||||
);
|
||||
let mut retry_cmd = NixCommand::new(subcommand)
|
||||
|
|
@ -250,10 +264,14 @@ pub fn handle_nix_with_retry(
|
|||
let retry_status = retry_cmd.run_with_logs(StdIoInterceptor)?;
|
||||
return Ok(retry_status.code().unwrap_or(1));
|
||||
}
|
||||
if stderr.contains("has been marked as broken") && stderr.contains("refusing") {
|
||||
if stderr.contains("has been marked as broken")
|
||||
&& stderr.contains("refusing")
|
||||
{
|
||||
warn!(
|
||||
"{}",
|
||||
Paint::yellow("⚠ Broken package detected, retrying with NIXPKGS_ALLOW_BROKEN=1...")
|
||||
Paint::yellow(
|
||||
"⚠ Broken package detected, retrying with NIXPKGS_ALLOW_BROKEN=1..."
|
||||
)
|
||||
);
|
||||
let mut retry_cmd = NixCommand::new(subcommand)
|
||||
.print_build_logs(true)
|
||||
|
|
@ -286,8 +304,11 @@ pub struct DefaultNixErrorClassifier;
|
|||
impl NixErrorClassifier for DefaultNixErrorClassifier {
|
||||
fn should_retry(&self, stderr: &str) -> bool {
|
||||
RegexHashExtractor.extract_hash(stderr).is_some()
|
||||
|| (stderr.contains("has an unfree license") && stderr.contains("refusing"))
|
||||
|| (stderr.contains("has been marked as insecure") && stderr.contains("refusing"))
|
||||
|| (stderr.contains("has been marked as broken") && stderr.contains("refusing"))
|
||||
|| (stderr.contains("has an unfree license")
|
||||
&& stderr.contains("refusing"))
|
||||
|| (stderr.contains("has been marked as insecure")
|
||||
&& stderr.contains("refusing"))
|
||||
|| (stderr.contains("has been marked as broken")
|
||||
&& stderr.contains("refusing"))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
use std::{fs, process::Command};
|
||||
|
||||
use eh::util::{
|
||||
DefaultNixErrorClassifier, DefaultNixFileFixer, HashExtractor, NixErrorClassifier,
|
||||
NixFileFixer, RegexHashExtractor,
|
||||
DefaultNixErrorClassifier,
|
||||
DefaultNixFileFixer,
|
||||
HashExtractor,
|
||||
NixErrorClassifier,
|
||||
NixFileFixer,
|
||||
RegexHashExtractor,
|
||||
};
|
||||
use std::fs;
|
||||
use std::process::Command;
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[test]
|
||||
|
|
@ -38,8 +42,10 @@ fn test_error_classification_for_retry_logic() {
|
|||
|
||||
// These should trigger retries
|
||||
let retry_cases = [
|
||||
"Package 'discord-1.0.0' has an unfree license ('unfree'), refusing to evaluate.",
|
||||
"Package 'openssl-1.1.1' has been marked as insecure, refusing to evaluate.",
|
||||
"Package 'discord-1.0.0' has an unfree license ('unfree'), refusing to \
|
||||
evaluate.",
|
||||
"Package 'openssl-1.1.1' has been marked as insecure, refusing to \
|
||||
evaluate.",
|
||||
"Package 'broken-1.0' has been marked as broken, refusing to evaluate.",
|
||||
"hash mismatch in fixed-output derivation\ngot: sha256-newhash",
|
||||
];
|
||||
|
|
@ -100,7 +106,8 @@ stdenv.mkDerivation {
|
|||
|
||||
assert!(was_fixed, "File should have been modified");
|
||||
|
||||
let updated_content = fs::read_to_string(&file_path).expect("Failed to read updated file");
|
||||
let updated_content =
|
||||
fs::read_to_string(&file_path).expect("Failed to read updated file");
|
||||
|
||||
// All hash formats should be updated
|
||||
assert!(updated_content.contains(&format!(r#"hash = "{}""#, new_hash)));
|
||||
|
|
@ -137,7 +144,9 @@ fn test_multicall_binary_dispatch() {
|
|||
// Should show an error message, not crash
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
assert!(
|
||||
stderr.contains("Error:") || stderr.contains("error:") || stderr.contains("failed"),
|
||||
stderr.contains("Error:")
|
||||
|| stderr.contains("error:")
|
||||
|| stderr.contains("failed"),
|
||||
"{} should show error for invalid package",
|
||||
binary_name
|
||||
);
|
||||
|
|
@ -177,7 +186,9 @@ fn test_invalid_expression_handling() {
|
|||
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
assert!(
|
||||
stderr.contains("Error:") || stderr.contains("error:") || stderr.contains("failed"),
|
||||
stderr.contains("Error:")
|
||||
|| stderr.contains("error:")
|
||||
|| stderr.contains("failed"),
|
||||
"Should show error message for invalid ref '{}': {}",
|
||||
invalid_ref,
|
||||
stderr
|
||||
|
|
@ -192,7 +203,8 @@ fn test_nix_file_discovery() {
|
|||
let fixer = DefaultNixFileFixer;
|
||||
|
||||
// Create directory structure with Nix files
|
||||
fs::create_dir_all(temp_dir.path().join("subdir")).expect("Failed to create subdir");
|
||||
fs::create_dir_all(temp_dir.path().join("subdir"))
|
||||
.expect("Failed to create subdir");
|
||||
|
||||
let files = [
|
||||
("test.nix", "stdenv.mkDerivation { name = \"test\"; }"),
|
||||
|
|
@ -202,12 +214,15 @@ fn test_nix_file_discovery() {
|
|||
];
|
||||
|
||||
for (path, content) in files {
|
||||
fs::write(temp_dir.path().join(path), content).expect("Failed to write file");
|
||||
fs::write(temp_dir.path().join(path), content)
|
||||
.expect("Failed to write file");
|
||||
}
|
||||
|
||||
// Change to temp dir for file discovery
|
||||
let original_dir = std::env::current_dir().expect("Failed to get current dir");
|
||||
std::env::set_current_dir(temp_dir.path()).expect("Failed to change directory");
|
||||
let original_dir =
|
||||
std::env::current_dir().expect("Failed to get current dir");
|
||||
std::env::set_current_dir(temp_dir.path())
|
||||
.expect("Failed to change directory");
|
||||
|
||||
let found_files = fixer.find_nix_files().expect("Failed to find Nix files");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::{
|
||||
error, fs,
|
||||
error,
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
process,
|
||||
};
|
||||
|
|
@ -65,13 +66,13 @@ fn main() {
|
|||
eprintln!("error creating multicall binaries: {error}");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
},
|
||||
Command::Completions { shell, output_dir } => {
|
||||
if let Err(error) = generate_completions(shell, &output_dir) {
|
||||
eprintln!("error generating completions: {error}");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +85,9 @@ fn create_multicall_binaries(
|
|||
fs::create_dir_all(bin_dir)?;
|
||||
|
||||
if !main_binary.exists() {
|
||||
return Err(format!("main binary not found at: {}", main_binary.display()).into());
|
||||
return Err(
|
||||
format!("main binary not found at: {}", main_binary.display()).into(),
|
||||
);
|
||||
}
|
||||
|
||||
let multicall_binaries = [Binary::Nr, Binary::Ns, Binary::Nb];
|
||||
|
|
@ -131,7 +134,10 @@ fn create_multicall_binaries(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_completions(shell: Shell, output_dir: &Path) -> Result<(), Box<dyn error::Error>> {
|
||||
fn generate_completions(
|
||||
shell: Shell,
|
||||
output_dir: &Path,
|
||||
) -> Result<(), Box<dyn error::Error>> {
|
||||
println!("generating {shell} completions...");
|
||||
|
||||
fs::create_dir_all(output_dir)?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue