mirror of
https://github.com/Hopiu/lychee.git
synced 2026-04-30 18:04:46 +00:00
Bump clap from 3.2.23 to 4.0.22 (#813)
* Bump clap from 3.2.23 to 4.0.22 Bumps [clap](https://github.com/clap-rs/clap) from 3.2.23 to 4.0.22. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v3.2.23...v4.0.22) * The `headers` option got renamed to `header` to align with the rest of the options, which are singular. * The short option for `header` (`-h`) was removed to avoid a conflict with help (`lychee -h`). * Update and simplify readme check Co-authored-by: Matthias <matthias-endler@gmx.net>
This commit is contained in:
parent
fbf0e9faea
commit
2ce1a9ae06
8 changed files with 254 additions and 200 deletions
75
Cargo.lock
generated
75
Cargo.lock
generated
|
|
@ -595,22 +595,32 @@ version = "3.2.23"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"clap_lex 0.2.4",
|
||||
"indexmap",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"textwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.2.18"
|
||||
name = "clap"
|
||||
version = "4.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
|
||||
checksum = "91b9970d7505127a162fdaa9b96428d28a479ba78c9ec7550a63a5d9863db682"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex 0.3.0",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
|
|
@ -628,6 +638,15 @@ dependencies = [
|
|||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "client_pool"
|
||||
version = "0.1.0"
|
||||
|
|
@ -747,7 +766,7 @@ dependencies = [
|
|||
"atty",
|
||||
"cast",
|
||||
"ciborium",
|
||||
"clap",
|
||||
"clap 3.2.23",
|
||||
"criterion-plot",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
|
|
@ -1011,6 +1030,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "difflib"
|
||||
version = "0.4.0"
|
||||
|
|
@ -1873,7 +1898,7 @@ version = "0.10.3"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
"clap",
|
||||
"clap 4.0.22",
|
||||
"console",
|
||||
"const_format",
|
||||
"csv",
|
||||
|
|
@ -1890,6 +1915,7 @@ dependencies = [
|
|||
"openssl-sys",
|
||||
"pad",
|
||||
"predicates",
|
||||
"pretty_assertions",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"ring",
|
||||
|
|
@ -2256,6 +2282,15 @@ version = "6.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3baf96e39c5359d2eb0dd6ccb42c62b91d9678aa68160d261b9e0ccbf9e9dea9"
|
||||
|
||||
[[package]]
|
||||
name = "output_vt100"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pad"
|
||||
version = "0.1.6"
|
||||
|
|
@ -2511,6 +2546,18 @@ dependencies = [
|
|||
"termtree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pretty_assertions"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
|
||||
dependencies = [
|
||||
"ctor",
|
||||
"diff",
|
||||
"output_vt100",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
|
|
@ -3918,6 +3965,12 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.5.7"
|
||||
|
|
|
|||
207
README.md
207
README.md
|
|
@ -207,138 +207,161 @@ There is an extensive list of commandline parameters to customize the behavior.
|
|||
See below for a full list.
|
||||
|
||||
```text
|
||||
USAGE:
|
||||
lychee [OPTIONS] <inputs>...
|
||||
A fast, async link checker
|
||||
|
||||
ARGS:
|
||||
<inputs>... The inputs (where to get links to check from). These can be: files (e.g.
|
||||
`README.md`), file globs (e.g. `"~/git/*/README.md"`), remote URLs (e.g.
|
||||
`https://example.com/README.md`) or standard input (`-`). NOTE: Use `--` to
|
||||
separate inputs from options that allow multiple arguments
|
||||
Finds broken URLs and mail addresses inside Markdown, HTML, `reStructuredText`, websites and more!
|
||||
|
||||
OPTIONS:
|
||||
-a, --accept <ACCEPT>
|
||||
Comma-separated list of accepted status codes for valid links
|
||||
Usage: lychee [OPTIONS] <inputs>...
|
||||
|
||||
-b, --base <BASE>
|
||||
Base URL or website root directory to check relative URLs e.g. https://example.com or
|
||||
`/path/to/public`
|
||||
Arguments:
|
||||
<inputs>...
|
||||
The inputs (where to get links to check from). These can be: files (e.g. `README.md`), file globs (e.g. `"~/git/*/README.md"`), remote URLs (e.g. `https://example.com/README.md`) or standard input (`-`). NOTE: Use `--` to separate inputs from options that allow multiple arguments
|
||||
|
||||
--basic-auth <BASIC_AUTH>
|
||||
Basic authentication support. E.g. `username:password`
|
||||
Options:
|
||||
-c, --config <CONFIG_FILE>
|
||||
Configuration file to use
|
||||
|
||||
[default: ./lychee.toml]
|
||||
|
||||
-c, --config <CONFIG_FILE>
|
||||
Configuration file to use [default: ./lychee.toml]
|
||||
-v, --verbose
|
||||
Verbose program output
|
||||
|
||||
--cache
|
||||
Use request cache stored on disk at `.lycheecache`
|
||||
-n, --no-progress
|
||||
Do not show progress bar.
|
||||
This is recommended for non-interactive shells (e.g. for continuous integration)
|
||||
|
||||
--dump
|
||||
Don't perform any link checking. Instead, dump all the links extracted from inputs that
|
||||
would be checked
|
||||
--cache
|
||||
Use request cache stored on disk at `.lycheecache`
|
||||
|
||||
-E, --exclude-all-private
|
||||
Exclude all private IPs from checking.
|
||||
Equivalent to `--exclude-private --exclude-link-local --exclude-loopback`
|
||||
--max-cache-age <MAX_CACHE_AGE>
|
||||
Discard all cached requests older than this duration
|
||||
|
||||
[default: 1d]
|
||||
|
||||
--exclude <EXCLUDE>
|
||||
Exclude URLs and mail addresses from checking (supports regex)
|
||||
--dump
|
||||
Don't perform any link checking. Instead, dump all the links extracted from inputs that would be checked
|
||||
|
||||
--exclude-file <EXCLUDE_FILE>
|
||||
Deprecated; use `--exclude-path` instead
|
||||
-m, --max-redirects <MAX_REDIRECTS>
|
||||
Maximum number of allowed redirects
|
||||
|
||||
[default: 5]
|
||||
|
||||
--exclude-link-local
|
||||
Exclude link-local IP address range from checking
|
||||
--max-retries <MAX_RETRIES>
|
||||
Maximum number of retries per request
|
||||
|
||||
[default: 3]
|
||||
|
||||
--exclude-loopback
|
||||
Exclude loopback IP address range and localhost from checking
|
||||
--max-concurrency <MAX_CONCURRENCY>
|
||||
Maximum number of concurrent network requests
|
||||
|
||||
[default: 128]
|
||||
|
||||
--exclude-mail
|
||||
Exclude all mail addresses from checking
|
||||
-T, --threads <THREADS>
|
||||
Number of threads to utilize. Defaults to number of cores available to the system
|
||||
|
||||
--exclude-path <EXCLUDE_PATH>
|
||||
Exclude file path from getting checked
|
||||
-u, --user-agent <USER_AGENT>
|
||||
User agent
|
||||
|
||||
[default: lychee/0.10.3]
|
||||
|
||||
--exclude-private
|
||||
Exclude private IP address ranges from checking
|
||||
-i, --insecure
|
||||
Proceed for server connections considered insecure (invalid TLS)
|
||||
|
||||
-f, --format <FORMAT>
|
||||
Output format of final status report (compact, detailed, json, markdown) [default:
|
||||
compact]
|
||||
-s, --scheme <SCHEME>
|
||||
Only test links with the given schemes (e.g. http and https)
|
||||
|
||||
--github-token <GITHUB_TOKEN>
|
||||
GitHub API token to use when checking github.com links, to avoid rate limiting [env:
|
||||
GITHUB_TOKEN]
|
||||
--offline
|
||||
Only check local files and block network requests
|
||||
|
||||
--glob-ignore-case
|
||||
Ignore case when expanding filesystem path glob inputs
|
||||
--include <INCLUDE>
|
||||
URLs to check (supports regex). Has preference over all excludes
|
||||
|
||||
-h, --headers <HEADERS>
|
||||
Custom request headers
|
||||
--exclude <EXCLUDE>
|
||||
Exclude URLs and mail addresses from checking (supports regex)
|
||||
|
||||
--help
|
||||
Print help information
|
||||
--exclude-file <EXCLUDE_FILE>
|
||||
Deprecated; use `--exclude-path` instead
|
||||
|
||||
-i, --insecure
|
||||
Proceed for server connections considered insecure (invalid TLS)
|
||||
--exclude-path <EXCLUDE_PATH>
|
||||
Exclude file path from getting checked
|
||||
|
||||
--include <INCLUDE>
|
||||
URLs to check (supports regex). Has preference over all excludes
|
||||
-E, --exclude-all-private
|
||||
Exclude all private IPs from checking.
|
||||
Equivalent to `--exclude-private --exclude-link-local --exclude-loopback`
|
||||
|
||||
--include-verbatim
|
||||
Find links in verbatim sections like `pre`- and `code` blocks
|
||||
--exclude-private
|
||||
Exclude private IP address ranges from checking
|
||||
|
||||
-m, --max-redirects <MAX_REDIRECTS>
|
||||
Maximum number of allowed redirects [default: 5]
|
||||
--exclude-link-local
|
||||
Exclude link-local IP address range from checking
|
||||
|
||||
--max-cache-age <MAX_CACHE_AGE>
|
||||
Discard all cached requests older than this duration [default: 1d]
|
||||
--exclude-loopback
|
||||
Exclude loopback IP address range and localhost from checking
|
||||
|
||||
--max-concurrency <MAX_CONCURRENCY>
|
||||
Maximum number of concurrent network requests [default: 128]
|
||||
--exclude-mail
|
||||
Exclude all mail addresses from checking
|
||||
|
||||
--max-retries <MAX_RETRIES>
|
||||
Maximum number of retries per request [default: 3]
|
||||
--remap <REMAP>
|
||||
Remap URI matching pattern to different URI
|
||||
|
||||
-n, --no-progress
|
||||
Do not show progress bar.
|
||||
This is recommended for non-interactive shells (e.g. for continuous integration)
|
||||
--header <HEADER>
|
||||
Custom request header
|
||||
|
||||
-o, --output <OUTPUT>
|
||||
Output file of status report
|
||||
-a, --accept <ACCEPT>
|
||||
Comma-separated list of accepted status codes for valid links
|
||||
|
||||
--offline
|
||||
Only check local files and block network requests
|
||||
-t, --timeout <TIMEOUT>
|
||||
Website timeout in seconds from connect to response finished
|
||||
|
||||
[default: 20]
|
||||
|
||||
-r, --retry-wait-time <RETRY_WAIT_TIME>
|
||||
Minimum wait time in seconds between retries of failed requests [default: 1]
|
||||
-r, --retry-wait-time <RETRY_WAIT_TIME>
|
||||
Minimum wait time in seconds between retries of failed requests
|
||||
|
||||
[default: 1]
|
||||
|
||||
--remap <REMAP>
|
||||
Remap URI matching pattern to different URI
|
||||
-X, --method <METHOD>
|
||||
Request method
|
||||
|
||||
[default: get]
|
||||
|
||||
--require-https
|
||||
When HTTPS is available, treat HTTP links as errors
|
||||
-b, --base <BASE>
|
||||
Base URL or website root directory to check relative URLs e.g. https://example.com or `/path/to/public`
|
||||
|
||||
-s, --scheme <SCHEME>
|
||||
Only test links with the given schemes (e.g. http and https)
|
||||
--basic-auth <BASIC_AUTH>
|
||||
Basic authentication support. E.g. `username:password`
|
||||
|
||||
--skip-missing
|
||||
Skip missing input files (default is to error if they don't exist)
|
||||
--github-token <GITHUB_TOKEN>
|
||||
GitHub API token to use when checking github.com links, to avoid rate limiting
|
||||
|
||||
[env: GITHUB_TOKEN]
|
||||
|
||||
-t, --timeout <TIMEOUT>
|
||||
Website timeout in seconds from connect to response finished [default: 20]
|
||||
--skip-missing
|
||||
Skip missing input files (default is to error if they don't exist)
|
||||
|
||||
-T, --threads <THREADS>
|
||||
Number of threads to utilize. Defaults to number of cores available to the system
|
||||
--include-verbatim
|
||||
Find links in verbatim sections like `pre`- and `code` blocks
|
||||
|
||||
-u, --user-agent <USER_AGENT>
|
||||
User agent [default: lychee/0.10.3]
|
||||
--glob-ignore-case
|
||||
Ignore case when expanding filesystem path glob inputs
|
||||
|
||||
-v, --verbose
|
||||
Verbose program output
|
||||
-o, --output <OUTPUT>
|
||||
Output file of status report
|
||||
|
||||
-f, --format <FORMAT>
|
||||
Output format of final status report (compact, detailed, json, markdown)
|
||||
|
||||
[default: compact]
|
||||
|
||||
--require-https
|
||||
When HTTPS is available, treat HTTP links as errors
|
||||
|
||||
-h, --help
|
||||
Print help information (use `-h` for a summary)
|
||||
|
||||
-V, --version
|
||||
Print version information
|
||||
|
||||
-X, --method <METHOD>
|
||||
Request method [default: get]
|
||||
```
|
||||
|
||||
### Exit codes
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "lychee"
|
||||
authors = ["Matthias Endler <matthias@endler.dev>"]
|
||||
description = "A glorious link checker"
|
||||
description = "A fast, async link checker"
|
||||
documentation = "https://docs.rs/lychee"
|
||||
homepage = "https://github.com/lycheeverse/lychee"
|
||||
edition = "2021"
|
||||
|
|
@ -50,11 +50,12 @@ supports-color = "1.3.0"
|
|||
log = "0.4.17"
|
||||
|
||||
[dependencies.clap]
|
||||
version = "3.2.23"
|
||||
version = "4.0.22"
|
||||
features = ["env", "derive"]
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = "2.0.5"
|
||||
pretty_assertions = "1.3.0"
|
||||
predicates = "2.1.1"
|
||||
tempfile = "3.3.0"
|
||||
uuid = { version = "1.2.1", features = ["v4"] }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use std::{collections::HashSet, str::FromStr};
|
|||
|
||||
/// Creates a client according to the command-line config
|
||||
pub(crate) fn create(cfg: &Config) -> Result<Client> {
|
||||
let mut headers = parse_headers(&cfg.headers)?;
|
||||
let mut headers = parse_headers(&cfg.header)?;
|
||||
if let Some(auth) = &cfg.basic_auth {
|
||||
let auth_header = parse_basic_auth(auth)?;
|
||||
headers.typed_insert(auth_header);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::parse::{parse_base, parse_statuscodes};
|
||||
use anyhow::{anyhow, Context, Error, Result};
|
||||
use clap::StructOpt;
|
||||
use clap::{arg, Parser};
|
||||
use const_format::{concatcp, formatcp};
|
||||
use lychee_lib::{
|
||||
Base, Input, DEFAULT_MAX_REDIRECTS, DEFAULT_MAX_RETRIES, DEFAULT_RETRY_WAIT_TIME_SECS,
|
||||
|
|
@ -95,24 +95,25 @@ macro_rules! fold_in {
|
|||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[clap(
|
||||
name = "lychee",
|
||||
about = "A glorious link checker.\n\nProject home page: https://github.com/lycheeverse/lychee"
|
||||
)]
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about)]
|
||||
/// A fast, async link checker
|
||||
///
|
||||
/// Finds broken URLs and mail addresses inside Markdown, HTML,
|
||||
/// `reStructuredText`, websites and more!
|
||||
pub(crate) struct LycheeOptions {
|
||||
/// The inputs (where to get links to check from).
|
||||
/// These can be: files (e.g. `README.md`), file globs (e.g. `"~/git/*/README.md"`),
|
||||
/// remote URLs (e.g. `https://example.com/README.md`) or standard input (`-`).
|
||||
/// NOTE: Use `--` to separate inputs from options that allow multiple arguments.
|
||||
#[clap(name = "inputs", required = true)]
|
||||
#[arg(name = "inputs", required = true)]
|
||||
raw_inputs: Vec<String>,
|
||||
|
||||
/// Configuration file to use
|
||||
#[clap(short, long = "config", default_value = "./lychee.toml")]
|
||||
#[arg(short, long = "config", default_value = "./lychee.toml")]
|
||||
pub(crate) config_file: String,
|
||||
|
||||
#[clap(flatten)]
|
||||
#[command(flatten)]
|
||||
pub(crate) config: Config,
|
||||
}
|
||||
|
||||
|
|
@ -136,28 +137,28 @@ impl LycheeOptions {
|
|||
}
|
||||
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
#[derive(Debug, Deserialize, StructOpt, Clone)]
|
||||
#[derive(Parser, Debug, Deserialize, Clone)]
|
||||
pub(crate) struct Config {
|
||||
/// Verbose program output
|
||||
#[clap(short, long)]
|
||||
#[arg(short, long)]
|
||||
#[serde(default)]
|
||||
pub(crate) verbose: bool,
|
||||
|
||||
/// Do not show progress bar.
|
||||
/// This is recommended for non-interactive shells (e.g. for continuous integration)
|
||||
#[clap(short, long, verbatim_doc_comment)]
|
||||
#[arg(short, long, verbatim_doc_comment)]
|
||||
#[serde(default)]
|
||||
pub(crate) no_progress: bool,
|
||||
|
||||
#[clap(help = HELP_MSG_CACHE)]
|
||||
#[clap(long)]
|
||||
#[arg(help = HELP_MSG_CACHE)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) cache: bool,
|
||||
|
||||
/// Discard all cached requests older than this duration
|
||||
#[clap(
|
||||
#[arg(
|
||||
long,
|
||||
parse(try_from_str = humantime::parse_duration),
|
||||
value_parser = humantime::parse_duration,
|
||||
default_value = &MAX_CACHE_AGE_STR
|
||||
)]
|
||||
#[serde(default = "max_cache_age")]
|
||||
|
|
@ -166,171 +167,171 @@ pub(crate) struct Config {
|
|||
|
||||
/// Don't perform any link checking.
|
||||
/// Instead, dump all the links extracted from inputs that would be checked
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) dump: bool,
|
||||
|
||||
/// Maximum number of allowed redirects
|
||||
#[clap(short, long, default_value = &MAX_REDIRECTS_STR)]
|
||||
#[arg(short, long, default_value = &MAX_REDIRECTS_STR)]
|
||||
#[serde(default = "max_redirects")]
|
||||
pub(crate) max_redirects: usize,
|
||||
|
||||
/// Maximum number of retries per request
|
||||
#[clap(long, default_value = &MAX_RETRIES_STR)]
|
||||
#[arg(long, default_value = &MAX_RETRIES_STR)]
|
||||
#[serde(default = "max_retries")]
|
||||
pub(crate) max_retries: u64,
|
||||
|
||||
/// Maximum number of concurrent network requests
|
||||
#[clap(long, default_value = &MAX_CONCURRENCY_STR)]
|
||||
#[arg(long, default_value = &MAX_CONCURRENCY_STR)]
|
||||
#[serde(default = "max_concurrency")]
|
||||
pub(crate) max_concurrency: usize,
|
||||
|
||||
/// Number of threads to utilize.
|
||||
/// Defaults to number of cores available to the system
|
||||
#[clap(short = 'T', long)]
|
||||
#[arg(short = 'T', long)]
|
||||
#[serde(default)]
|
||||
pub(crate) threads: Option<usize>,
|
||||
|
||||
/// User agent
|
||||
#[clap(short, long, default_value = DEFAULT_USER_AGENT)]
|
||||
#[arg(short, long, default_value = DEFAULT_USER_AGENT)]
|
||||
#[serde(default = "user_agent")]
|
||||
pub(crate) user_agent: String,
|
||||
|
||||
/// Proceed for server connections considered insecure (invalid TLS)
|
||||
#[clap(short, long)]
|
||||
#[arg(short, long)]
|
||||
#[serde(default)]
|
||||
pub(crate) insecure: bool,
|
||||
|
||||
/// Only test links with the given schemes (e.g. http and https)
|
||||
#[clap(short, long)]
|
||||
#[arg(short, long)]
|
||||
#[serde(default)]
|
||||
pub(crate) scheme: Vec<String>,
|
||||
|
||||
/// Only check local files and block network requests.
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) offline: bool,
|
||||
|
||||
/// URLs to check (supports regex). Has preference over all excludes.
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) include: Vec<String>,
|
||||
|
||||
/// Exclude URLs and mail addresses from checking (supports regex)
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) exclude: Vec<String>,
|
||||
|
||||
/// Deprecated; use `--exclude-path` instead
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) exclude_file: Vec<String>,
|
||||
|
||||
/// Exclude file path from getting checked.
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) exclude_path: Vec<PathBuf>,
|
||||
|
||||
/// Exclude all private IPs from checking.
|
||||
/// Equivalent to `--exclude-private --exclude-link-local --exclude-loopback`
|
||||
#[clap(short = 'E', long, verbatim_doc_comment)]
|
||||
#[arg(short = 'E', long, verbatim_doc_comment)]
|
||||
#[serde(default)]
|
||||
pub(crate) exclude_all_private: bool,
|
||||
|
||||
/// Exclude private IP address ranges from checking
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) exclude_private: bool,
|
||||
|
||||
/// Exclude link-local IP address range from checking
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) exclude_link_local: bool,
|
||||
|
||||
/// Exclude loopback IP address range and localhost from checking
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) exclude_loopback: bool,
|
||||
|
||||
/// Exclude all mail addresses from checking
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) exclude_mail: bool,
|
||||
|
||||
/// Remap URI matching pattern to different URI
|
||||
#[serde(default)]
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
pub(crate) remap: Vec<String>,
|
||||
|
||||
/// Custom request headers
|
||||
#[clap(short, long)]
|
||||
/// Custom request header
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) headers: Vec<String>,
|
||||
pub(crate) header: Vec<String>,
|
||||
|
||||
/// Comma-separated list of accepted status codes for valid links
|
||||
#[clap(short, long, parse(try_from_str = parse_statuscodes))]
|
||||
#[arg(short, long, value_parser = parse_statuscodes)]
|
||||
#[serde(default)]
|
||||
pub(crate) accept: Option<HashSet<u16>>,
|
||||
|
||||
/// Website timeout in seconds from connect to response finished
|
||||
#[clap(short, long, default_value = &TIMEOUT_STR)]
|
||||
#[arg(short, long, default_value = &TIMEOUT_STR)]
|
||||
#[serde(default = "timeout")]
|
||||
pub(crate) timeout: usize,
|
||||
|
||||
/// Minimum wait time in seconds between retries of failed requests
|
||||
#[clap(short, long, default_value = &RETRY_WAIT_TIME_STR)]
|
||||
#[arg(short, long, default_value = &RETRY_WAIT_TIME_STR)]
|
||||
#[serde(default = "retry_wait_time")]
|
||||
pub(crate) retry_wait_time: usize,
|
||||
|
||||
/// Request method
|
||||
// Using `-X` as a short param similar to curl
|
||||
#[clap(short = 'X', long, default_value = DEFAULT_METHOD)]
|
||||
#[arg(short = 'X', long, default_value = DEFAULT_METHOD)]
|
||||
#[serde(default = "method")]
|
||||
pub(crate) method: String,
|
||||
|
||||
/// Base URL or website root directory to check relative URLs
|
||||
/// e.g. https://example.com or `/path/to/public`
|
||||
#[clap(short, long, parse(try_from_str = parse_base))]
|
||||
#[arg(short, long, value_parser= parse_base)]
|
||||
#[serde(default)]
|
||||
pub(crate) base: Option<Base>,
|
||||
|
||||
/// Basic authentication support. E.g. `username:password`
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) basic_auth: Option<String>,
|
||||
|
||||
/// GitHub API token to use when checking github.com links, to avoid rate limiting
|
||||
#[clap(long, env = "GITHUB_TOKEN", hide_env_values = true)]
|
||||
#[arg(long, env = "GITHUB_TOKEN", hide_env_values = true)]
|
||||
#[serde(default)]
|
||||
pub(crate) github_token: Option<SecretString>,
|
||||
|
||||
/// Skip missing input files (default is to error if they don't exist)
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) skip_missing: bool,
|
||||
|
||||
/// Find links in verbatim sections like `pre`- and `code` blocks
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) include_verbatim: bool,
|
||||
|
||||
/// Ignore case when expanding filesystem path glob inputs
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) glob_ignore_case: bool,
|
||||
|
||||
/// Output file of status report
|
||||
#[clap(short, long, parse(from_os_str))]
|
||||
#[arg(short, long, value_parser)]
|
||||
#[serde(default)]
|
||||
pub(crate) output: Option<PathBuf>,
|
||||
|
||||
/// Output format of final status report (compact, detailed, json, markdown)
|
||||
#[clap(short, long, default_value = "compact")]
|
||||
#[arg(short, long, default_value = "compact")]
|
||||
#[serde(default)]
|
||||
pub(crate) format: Format,
|
||||
|
||||
/// When HTTPS is available, treat HTTP links as errors
|
||||
#[clap(long)]
|
||||
#[arg(long)]
|
||||
#[serde(default)]
|
||||
pub(crate) require_https: bool,
|
||||
}
|
||||
|
|
@ -383,7 +384,7 @@ impl Config {
|
|||
exclude_loopback: false;
|
||||
exclude_mail: false;
|
||||
remap: Vec::<String>::new();
|
||||
headers: Vec::<String>::new();
|
||||
header: Vec::<String>::new();
|
||||
accept: None;
|
||||
timeout: DEFAULT_TIMEOUT_SECS;
|
||||
retry_wait_time: DEFAULT_RETRY_WAIT_TIME_SECS;
|
||||
|
|
|
|||
|
|
@ -53,9 +53,9 @@ pub(crate) fn parse_base(src: &str) -> Result<Base, lychee_lib::ErrorKind> {
|
|||
}
|
||||
|
||||
/// Parse HTTP status codes into a set of `StatusCode`
|
||||
pub(crate) fn parse_statuscodes<T: AsRef<str>>(accept: T) -> Result<HashSet<u16>> {
|
||||
pub(crate) fn parse_statuscodes(accept: &str) -> Result<HashSet<u16>> {
|
||||
let mut statuscodes = HashSet::new();
|
||||
for code in accept.as_ref().split(',') {
|
||||
for code in accept.split(',') {
|
||||
let code: u16 = code.parse::<u16>()?;
|
||||
statuscodes.insert(code);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
#[cfg(test)]
|
||||
mod readme {
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufReader, Read},
|
||||
path::Path,
|
||||
};
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use assert_cmd::Command;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
const USAGE_STRING: &str = "Usage: lychee [OPTIONS] <inputs>...\n";
|
||||
|
||||
fn main_command() -> Command {
|
||||
// this gets the "main" binary name (e.g. `lychee`)
|
||||
|
|
@ -18,15 +17,7 @@ mod readme {
|
|||
.parent()
|
||||
.unwrap()
|
||||
.join("README.md");
|
||||
let file = File::open(readme_path).expect("Couldn't open README.md");
|
||||
let mut buf_reader = BufReader::new(file);
|
||||
let mut text = String::new();
|
||||
|
||||
buf_reader
|
||||
.read_to_string(&mut text)
|
||||
.expect("Unable to read README.md file contents");
|
||||
|
||||
text
|
||||
fs::read_to_string(readme_path).unwrap()
|
||||
}
|
||||
|
||||
/// Test that the USAGE section in `README.md` is up to date with
|
||||
|
|
@ -36,35 +27,20 @@ mod readme {
|
|||
/// involved parsing).
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_readme_usage_up_to_date() {
|
||||
fn test_readme_usage_up_to_date() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut cmd = main_command();
|
||||
|
||||
let result = cmd.env_clear().arg("--help").assert().success();
|
||||
let help_output = std::str::from_utf8(&result.get_output().stdout)
|
||||
.expect("Invalid utf8 output for `--help`");
|
||||
let readme = load_readme_text();
|
||||
|
||||
const BACKTICKS_OFFSET: usize = 7; // marker: ```text
|
||||
const NEWLINE_OFFSET: usize = 1;
|
||||
|
||||
let usage_start = BACKTICKS_OFFSET
|
||||
+ NEWLINE_OFFSET
|
||||
+ readme
|
||||
.find("```text\nUSAGE:\n")
|
||||
.expect("Couldn't find USAGE section in README.md");
|
||||
|
||||
let usage_end = readme[usage_start..]
|
||||
.find("\n```")
|
||||
.expect("Couldn't find USAGE section end in README.md");
|
||||
|
||||
// include final newline in usage text
|
||||
let usage_in_readme = &readme[usage_start..usage_start + usage_end + NEWLINE_OFFSET];
|
||||
|
||||
let usage_in_help_start = help_output
|
||||
.find("USAGE:\n")
|
||||
.expect("Couldn't find USAGE section in `--help` output");
|
||||
let help_cmd = cmd.env_clear().arg("--help").assert().success();
|
||||
let help_output = std::str::from_utf8(&help_cmd.get_output().stdout).unwrap();
|
||||
let usage_in_help_start = help_output.find(USAGE_STRING).unwrap();
|
||||
let usage_in_help = &help_output[usage_in_help_start..];
|
||||
|
||||
let readme = load_readme_text();
|
||||
let usage_start = readme.find(USAGE_STRING).unwrap();
|
||||
let usage_end = readme[usage_start..].find("\n```").unwrap();
|
||||
let usage_in_readme = &readme[usage_start..usage_start + usage_end];
|
||||
|
||||
assert_eq!(usage_in_readme, usage_in_help);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
name = "lychee-lib"
|
||||
authors = ["Matthias Endler <matthias@endler.dev>"]
|
||||
description = "A glorious link checker"
|
||||
description = "A fast, async link checker"
|
||||
documentation = "https://docs.rs/lychee_lib"
|
||||
edition = "2021"
|
||||
homepage = "https://github.com/lycheeverse/lychee"
|
||||
|
|
|
|||
Loading…
Reference in a new issue