Skip to content

Commit

Permalink
Add optional capture-output writer to run_app()
Browse files Browse the repository at this point in the history
The output and exit code of run_app() are now testable, used for diff test.
  • Loading branch information
th1000s committed Nov 4, 2024
1 parent f846a1a commit 1a4c01b
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 25 deletions.
15 changes: 12 additions & 3 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,9 +1289,18 @@ impl Opt {
}
}

pub fn from_args_and_git_config(env: &DeltaEnv, assets: HighlightingAssets) -> Call<Self> {
let args = std::env::args_os().collect::<Vec<_>>();

pub fn from_args_and_git_config(
args: Vec<OsString>,
env: &DeltaEnv,
assets: HighlightingAssets,
) -> Call<Self> {
#[cfg(test)]
// Set argv[0] when called in tests:
let args = {
let mut args = args;
args.insert(0, OsString::from("delta"));
args
};
let matches = match Self::handle_help_and_version(&args) {
Call::Delta(t) => t,
msg => {
Expand Down
3 changes: 2 additions & 1 deletion src/git_config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ impl GitConfig {

#[cfg(test)]
pub fn try_create(_env: &DeltaEnv) -> Option<Self> {
unreachable!("GitConfig::try_create() is not available when testing");
// Do not read local git configs when testing
None
}

pub fn from_path(env: &DeltaEnv, path: &Path, honor_env_var: bool) -> Self {
Expand Down
30 changes: 22 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,16 @@ mod subcommands;

mod tests;

use std::io::{self, ErrorKind, IsTerminal, Write};
use std::ffi::OsString;
use std::io::{self, Cursor, ErrorKind, IsTerminal, Write};
use std::process;

use bytelines::ByteLinesReader;

use crate::cli::Call;
use crate::delta::delta;
use crate::utils::bat::assets::list_languages;
use crate::utils::bat::output::OutputType;
use crate::utils::bat::output::{OutputType, PagingMode};

pub fn fatal<T>(errmsg: T) -> !
where
Expand Down Expand Up @@ -65,7 +66,7 @@ fn main() -> std::io::Result<()> {
// See https://github.com/dandavison/delta/issues/681
ctrlc::set_handler(|| {})
.unwrap_or_else(|err| eprintln!("Failed to set ctrl-c handler: {err}"));
let exit_code = run_app()?;
let exit_code = run_app(std::env::args_os().collect::<Vec<_>>(), None)?;
// when you call process::exit, no destructors are called, so we want to do it only once, here
process::exit(exit_code);
}
Expand All @@ -74,10 +75,13 @@ fn main() -> std::io::Result<()> {
// An Ok result contains the desired process exit code. Note that 1 is used to
// report that two files differ when delta is called with two positional
// arguments and without standard input; 2 is used to report a real problem.
fn run_app() -> std::io::Result<i32> {
let assets = utils::bat::assets::load_highlighting_assets();
pub fn run_app(
args: Vec<OsString>,
capture_output: Option<&mut Cursor<Vec<u8>>>,
) -> std::io::Result<i32> {
let env = env::DeltaEnv::init();
let opt = cli::Opt::from_args_and_git_config(&env, assets);
let assets = utils::bat::assets::load_highlighting_assets();
let opt = cli::Opt::from_args_and_git_config(args, &env, assets);

let opt = match opt {
Call::Version(msg) => {
Expand Down Expand Up @@ -134,10 +138,20 @@ fn run_app() -> std::io::Result<i32> {
return Ok(0);
}

// The following block structure is because of `writer` and related lifetimes:
let pager_cfg = (&config).into();
let paging_mode = if capture_output.is_some() {
PagingMode::Capture
} else {
config.paging_mode
};
let mut output_type =
OutputType::from_mode(&env, config.paging_mode, config.pager.clone(), &pager_cfg).unwrap();
let mut writer = output_type.handle().unwrap();
OutputType::from_mode(&env, paging_mode, config.pager.clone(), &pager_cfg).unwrap();
let mut writer: &mut dyn Write = if paging_mode == PagingMode::Capture {
&mut capture_output.unwrap()
} else {
output_type.handle().unwrap()
};

if let (Some(minus_file), Some(plus_file)) = (&config.minus_file, &config.plus_file) {
let exit_code = subcommands::diff::diff(minus_file, plus_file, &config, &mut writer);
Expand Down
25 changes: 14 additions & 11 deletions src/subcommands/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,10 @@ where

#[cfg(test)]
mod main_tests {
use std::ffi::OsString;
use std::io::Cursor;
use std::path::PathBuf;

use super::{diff, diff_args_set_unified_context};
use crate::tests::integration_test_utils;
use super::diff_args_set_unified_context;

use rstest::rstest;

Expand Down Expand Up @@ -215,20 +214,24 @@ mod main_tests {
&str,
>,
) {
let config = integration_test_utils::make_config_from_args(&args);
let mut writer = Cursor::new(vec![]);
let exit_code = diff(
&PathBuf::from(file_a),
&PathBuf::from(file_b),
&config,
&mut writer,
);
let mut runargs = vec![OsString::from(file_a), OsString::from(file_b)];
runargs.extend(args.iter().map(OsString::from));
let exit_code = crate::run_app(runargs, Some(&mut writer));

assert_eq!(
exit_code,
exit_code.unwrap(),
match expect_diff {
ExpectDiff::Yes => 1,
ExpectDiff::No => 0,
}
);
assert_eq!(
std::str::from_utf8(writer.get_ref()).unwrap() != "",
match expect_diff {
ExpectDiff::Yes => true,
ExpectDiff::No => false,
}
);
}
}
5 changes: 3 additions & 2 deletions src/subcommands/show_colors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ use crate::utils::bat::output::{OutputType, PagingMode};
pub fn show_colors() -> std::io::Result<()> {
use crate::{delta::DiffType, utils};

let assets = utils::bat::assets::load_highlighting_assets();
let args = std::env::args_os().collect::<Vec<_>>();
let env = DeltaEnv::default();
let assets = utils::bat::assets::load_highlighting_assets();

let opt = match cli::Opt::from_args_and_git_config(&env, assets) {
let opt = match cli::Opt::from_args_and_git_config(args, &env, assets) {
cli::Call::Delta(opt) => opt,
_ => panic!("non-Delta Call variant should not occur here"),
};
Expand Down
1 change: 1 addition & 0 deletions src/subcommands/show_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ pub fn show_config(config: &config::Config, writer: &mut dyn Write) -> std::io::
PagingMode::Always => "always",
PagingMode::Never => "never",
PagingMode::QuitIfOneScreen => "auto",
PagingMode::Capture => unreachable!("capture can not be set"),
},
side_by_side = config.side_by_side,
syntax_theme = config
Expand Down
4 changes: 4 additions & 0 deletions src/utils/bat/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ pub enum PagingMode {
QuitIfOneScreen,
#[default]
Never,
Capture,
}
const LESSUTFCHARDEF: &str = "LESSUTFCHARDEF";
use crate::errors::*;

pub enum OutputType {
Pager(Child),
Stdout(io::Stdout),
Capture,
}

impl Drop for OutputType {
Expand Down Expand Up @@ -84,6 +86,7 @@ impl OutputType {
Ok(match mode {
Always => OutputType::try_pager(env, false, pager, config)?,
QuitIfOneScreen => OutputType::try_pager(env, true, pager, config)?,
Capture => OutputType::Capture,
_ => OutputType::stdout(),
})
}
Expand Down Expand Up @@ -162,6 +165,7 @@ impl OutputType {
.as_mut()
.context("Could not open stdin for pager")?,
OutputType::Stdout(ref mut handle) => handle,
OutputType::Capture => unreachable!("capture can not be set"),
})
}
}
Expand Down

0 comments on commit 1a4c01b

Please sign in to comment.