Skip to content

Commit

Permalink
[WIP] add a command to install man pages
Browse files Browse the repository at this point in the history
  • Loading branch information
sunshowers committed Jun 25, 2022
1 parent 3221f1d commit c63671d
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 3 deletions.
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions cargo-nextest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ rust-version = "1.59"
camino = "1.0.9"
cfg-if = "1.0.0"
clap = { version = "3.2.6", features = ["derive", "env"] }
clap_mangen = "0.1.9"
# we don't use the tracing support
color-eyre = { version = "0.6.1", default-features = false }
dialoguer = "0.10.1"
Expand All @@ -23,6 +24,7 @@ enable-ansi-support = "0.1.2"
# we don't use the default formatter so we don't need default features
env_logger = { version = "0.9.0", default-features = false }
guppy = "0.14.2"
home = "0.5.3"
log = "0.4.17"
itertools = "0.10.3"
miette = { version = "4.7.1", features = ["fancy"] }
Expand Down
23 changes: 20 additions & 3 deletions cargo-nextest/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use crate::{
cargo_cli::{CargoCli, CargoOptions},
mangen::install_man,
output::{OutputContext, OutputOpts, OutputWriter},
reuse_build::{make_path_mapper, ArchiveFormatOpt, ReuseBuildOpts},
ExpectedError, Result, ReuseBuildKind,
Expand Down Expand Up @@ -55,14 +56,20 @@ impl CargoNextestApp {
}

#[derive(Debug, Subcommand)]
enum NextestSubcommand {
pub(crate) enum NextestSubcommand {
/// A next-generation test runner for Rust. <https://nexte.st>
Nextest(AppOpts),
}

#[derive(Debug, Args)]
/// cargo-nextest is a next-generation test runner for Rust projects.
///
/// Nextest runs tests in parallel and provides a rich set of features, such as partitioning test
/// runs, JUnit output, and archiving and reusing builds.
///
/// For the full documentation, see the nextest site at <https://nexte.st>.
#[derive(Debug, Parser)]
#[clap(version)]
struct AppOpts {
pub(crate) struct AppOpts {
/// Path to Cargo.toml
#[clap(long, global = true, value_name = "PATH")]
manifest_path: Option<Utf8PathBuf>,
Expand Down Expand Up @@ -1018,6 +1025,12 @@ impl App {

#[derive(Debug, Subcommand)]
enum SelfCommand {
/// Install man pages for nextest.
InstallMan {
/// The output directory [default: <current-exe-path>/../man]
output_dir: Option<Utf8PathBuf>,
},

#[cfg_attr(
not(feature = "self-update"),
doc = "This version of nextest does not have self-update enabled\n\
Expand Down Expand Up @@ -1064,6 +1077,10 @@ impl SelfCommand {
let output = output.init();

match self {
Self::InstallMan { output_dir } => {
install_man(output_dir)?;
Ok(0)
}
Self::Update {
version,
check,
Expand Down
33 changes: 33 additions & 0 deletions cargo-nextest/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@ pub enum ExpectedError {
reason: &'static str,
args: Vec<String>,
},
#[error(transparent)]
InstallManError {
#[from]
error: InstallManError,
},
}

impl ExpectedError {
Expand Down Expand Up @@ -311,6 +316,7 @@ impl ExpectedError {
NextestExitCode::EXPERIMENTAL_FEATURE_NOT_ENABLED
}
Self::FilterExpressionParseError { .. } => NextestExitCode::INVALID_FILTER_EXPRESSION,
Self::InstallManError { .. } => NextestExitCode::INSTALL_MAN_ERROR,
}
}

Expand Down Expand Up @@ -529,6 +535,11 @@ impl ExpectedError {
);
None
}
Self::InstallManError { error } => {
// This is a transparent error.
log::error!("{}", error);
error.source()
}
};

while let Some(err) = next_error {
Expand All @@ -537,3 +548,25 @@ impl ExpectedError {
}
}
}

#[derive(Debug, Error)]
#[doc(hidden)]
pub enum InstallManError {
#[error("could not determine current executable path")]
CurrentExe {
#[source]
error: std::io::Error,
},
#[error("error creating output directory `{path}`")]
CreateOutputDir {
path: Utf8PathBuf,
#[source]
error: std::io::Error,
},
#[error("error writing to `{path}`")]
WriteToFile {
path: Utf8PathBuf,
#[source]
error: std::io::Error,
},
}
1 change: 1 addition & 0 deletions cargo-nextest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
mod cargo_cli;
mod dispatch;
mod errors;
mod mangen;
mod output;
mod reuse_build;
#[cfg(feature = "self-update")]
Expand Down
58 changes: 58 additions & 0 deletions cargo-nextest/src/mangen.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) The nextest Contributors
// SPDX-License-Identifier: MIT OR Apache-2.0

use crate::{AppOpts, InstallManError};
use camino::{Utf8Path, Utf8PathBuf};
use clap::CommandFactory;
use clap_mangen::Man;

pub(crate) fn install_man(output_dir: Option<Utf8PathBuf>) -> Result<(), InstallManError> {
let mut output_dir = match output_dir {
Some(d) => d,
None => {
let mut current_exe = std::env::current_exe()
.and_then(|home| {
Utf8PathBuf::try_from(home).map_err(|error| {
std::io::Error::new(std::io::ErrorKind::InvalidData, error)
})
})
.map_err(|error| InstallManError::CurrentExe { error })?;
// If the current exe is foo/bar/bin/cargo-nextest, the man directory is foo/bar/man.
current_exe.pop();
current_exe.pop();
current_exe.push("man");
current_exe
}
};

// All of nextest's commands go in man1.
output_dir.push("man1");

std::fs::create_dir_all(&output_dir).map_err(|error| InstallManError::CreateOutputDir {
path: output_dir.clone(),
error,
})?;

let command = AppOpts::command();

let man = Man::new(command.clone()).manual("Nextest Manual");
let path = output_dir.join("cargo-nextest.1");
render_to_file(&man, &path).map_err(|error| InstallManError::WriteToFile { path, error })?;

for subcommand in command.get_subcommands() {
let name = subcommand.get_name();
// XXX this line crashes with "Command list: Argument or group 'manifest-path' specified in
// 'conflicts_with*' for 'cargo-metadata' does not exist".
let man = Man::new(subcommand.clone()).manual("Nextest Manual");
let path = output_dir.join(format!("cargo-nextest-{}.1", name));
render_to_file(&man, &path)
.map_err(|error| InstallManError::WriteToFile { path, error })?;
}

Ok(())
}

fn render_to_file(man: &Man, path: &Utf8Path) -> Result<(), std::io::Error> {
let mut writer = std::fs::File::create(&path)?;
man.render(&mut writer)
}
3 changes: 3 additions & 0 deletions nextest-metadata/src/exit_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ impl NextestExitCode {
/// Writing data to stdout or stderr produced an error.
pub const WRITE_OUTPUT_ERROR: i32 = 110;

/// Installing man pages produced an error.
pub const INSTALL_MAN_ERROR: i32 = 120;

/// Downloading an update resulted in an error.
pub const UPDATE_ERROR: i32 = 90;

Expand Down

0 comments on commit c63671d

Please sign in to comment.