Unwrap option type

This commit is contained in:
Thomas Zahner 2025-07-10 14:35:50 +02:00
parent 696a7cafc8
commit 1de218a78a
4 changed files with 59 additions and 78 deletions

View file

@ -7,18 +7,10 @@ use tokio_stream::StreamExt;
async fn main() -> Result<()> {
// Collect all links from the following inputs
let inputs = vec![
Input {
source: InputSource::RemoteUrl(Box::new(
Url::parse("https://github.com/lycheeverse/lychee").unwrap(),
)),
file_type_hint: None,
excluded_paths: None,
},
Input {
source: InputSource::FsPath(PathBuf::from("fixtures/TEST.md")),
file_type_hint: None,
excluded_paths: None,
},
Input::from_input_source(InputSource::RemoteUrl(Box::new(
Url::parse("https://github.com/lycheeverse/lychee").unwrap(),
))),
Input::from_input_source(InputSource::FsPath(PathBuf::from("fixtures/TEST.md"))),
];
let links = Collector::default()

View file

@ -331,15 +331,16 @@ impl LycheeOptions {
// accept a `Vec<Input>` in `LycheeOptions` and do the conversion there, but
// we wouldn't get access to `glob_ignore_case`.
pub(crate) fn inputs(&self) -> Result<Vec<Input>> {
let excluded = if self.config.exclude_path.is_empty() {
None
} else {
Some(self.config.exclude_path.clone())
};
self.raw_inputs
.iter()
.map(|s| Input::new(s, None, self.config.glob_ignore_case, excluded.clone()))
.map(|s| {
Input::new(
s,
None,
self.config.glob_ignore_case,
self.config.exclude_path.clone(),
)
})
.collect::<Result<_, _>>()
.context("Cannot parse inputs from arguments")
}

View file

@ -274,7 +274,12 @@ mod tests {
// Treat as plaintext file (no extension)
let file_path = temp_dir.path().join("README");
let _file = File::create(&file_path).unwrap();
let input = Input::new(&file_path.as_path().display().to_string(), None, true, None)?;
let input = Input::new(
&file_path.as_path().display().to_string(),
None,
true,
vec![],
)?;
let contents: Vec<_> = input
.get_contents(
true,
@ -293,7 +298,7 @@ mod tests {
#[tokio::test]
async fn test_url_without_extension_is_html() -> Result<()> {
let input = Input::new("https://example.com/", None, true, None)?;
let input = Input::new("https://example.com/", None, true, vec![])?;
let contents: Vec<_> = input
.get_contents(
true,
@ -330,33 +335,17 @@ mod tests {
let mock_server = mock_server!(StatusCode::OK, set_body_string(TEST_URL));
let inputs = vec![
Input {
source: InputSource::String(TEST_STRING.to_owned()),
file_type_hint: None,
excluded_paths: None,
},
Input {
source: InputSource::RemoteUrl(Box::new(
Url::parse(&mock_server.uri())
.map_err(|e| (mock_server.uri(), e))
.unwrap(),
)),
file_type_hint: None,
excluded_paths: None,
},
Input {
source: InputSource::FsPath(file_path),
file_type_hint: None,
excluded_paths: None,
},
Input {
source: InputSource::FsGlob {
pattern: temp_dir_path.join("glob*").to_str().unwrap().to_owned(),
ignore_case: true,
},
file_type_hint: None,
excluded_paths: None,
},
Input::from_input_source(InputSource::String(TEST_STRING.to_owned())),
Input::from_input_source(InputSource::RemoteUrl(Box::new(
Url::parse(&mock_server.uri())
.map_err(|e| (mock_server.uri(), e))
.unwrap(),
))),
Input::from_input_source(InputSource::FsPath(file_path)),
Input::from_input_source(InputSource::FsGlob {
pattern: temp_dir_path.join("glob*").to_str().unwrap().to_owned(),
ignore_case: true,
}),
];
let links = collect_verbatim(inputs, None, None, FileType::default_extensions())
@ -383,7 +372,7 @@ mod tests {
let input = Input {
source: InputSource::String("This is [a test](https://endler.dev). This is a relative link test [Relative Link Test](relative_link)".to_string()),
file_type_hint: Some(FileType::Markdown),
excluded_paths: None,
excluded_paths: vec![],
};
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
@ -409,7 +398,7 @@ mod tests {
.to_string(),
),
file_type_hint: Some(FileType::Html),
excluded_paths: None,
excluded_paths: vec![],
};
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
@ -438,7 +427,7 @@ mod tests {
.to_string(),
),
file_type_hint: Some(FileType::Html),
excluded_paths: None,
excluded_paths: vec![],
};
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
@ -464,7 +453,7 @@ mod tests {
.to_string(),
),
file_type_hint: Some(FileType::Markdown),
excluded_paths: None,
excluded_paths: vec![],
};
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
@ -487,7 +476,7 @@ mod tests {
let input = Input {
source: InputSource::String(input),
file_type_hint: Some(FileType::Html),
excluded_paths: None,
excluded_paths: vec![],
};
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();
@ -516,11 +505,7 @@ mod tests {
let server_uri = Url::parse(&mock_server.uri()).unwrap();
let input = Input {
source: InputSource::RemoteUrl(Box::new(server_uri.clone())),
file_type_hint: None,
excluded_paths: None,
};
let input = Input::from_input_source(InputSource::RemoteUrl(Box::new(server_uri.clone())));
let links = collect(vec![input], None, None).await.ok().unwrap();
@ -534,13 +519,10 @@ mod tests {
#[tokio::test]
async fn test_email_with_query_params() {
let input = Input {
source: InputSource::String(
"This is a mailto:user@example.com?subject=Hello link".to_string(),
),
file_type_hint: None,
excluded_paths: None,
};
let input = Input::from_input_source(InputSource::String(
"This is a mailto:user@example.com?subject=Hello link".to_string(),
));
let links = collect(vec![input], None, None).await.ok().unwrap();
let expected_links = HashSet::from_iter([mail("user@example.com")]);
@ -569,7 +551,7 @@ mod tests {
.unwrap(),
)),
file_type_hint: Some(FileType::Html),
excluded_paths: None,
excluded_paths: vec![],
},
Input {
source: InputSource::RemoteUrl(Box::new(
@ -580,7 +562,7 @@ mod tests {
.unwrap(),
)),
file_type_hint: Some(FileType::Html),
excluded_paths: None,
excluded_paths: vec![],
},
];
@ -615,7 +597,7 @@ mod tests {
.into(),
),
file_type_hint: Some(FileType::Html),
excluded_paths: None,
excluded_paths: vec![],
};
let links = collect(vec![input], None, Some(base)).await.ok().unwrap();

View file

@ -108,7 +108,7 @@ pub struct Input {
/// Hint to indicate which extractor to use
pub file_type_hint: Option<FileType>,
/// Excluded paths that will be skipped when reading content
pub excluded_paths: Option<Vec<PathBuf>>,
pub excluded_paths: Vec<PathBuf>,
}
impl Input {
@ -124,7 +124,7 @@ impl Input {
value: &str,
file_type_hint: Option<FileType>,
glob_ignore_case: bool,
excluded_paths: Option<Vec<PathBuf>>,
excluded_paths: Vec<PathBuf>,
) -> Result<Self> {
let source = if value == STDIN {
InputSource::Stdin
@ -200,7 +200,16 @@ impl Input {
/// Returns an error if the input does not exist (i.e. invalid path)
/// and the input cannot be parsed as a URL.
pub fn from_value(value: &str) -> Result<Self> {
Self::new(value, None, false, None)
Self::new(value, None, false, vec![])
}
/// Convenience constructor
pub fn from_input_source(source: InputSource) -> Self {
Self {
source,
file_type_hint: None,
excluded_paths: vec![],
}
}
/// Retrieve the contents from the input
@ -360,10 +369,7 @@ impl Input {
/// Check if the given path was excluded from link checking
fn is_excluded_path(&self, path: &PathBuf) -> bool {
let Some(excluded_paths) = &self.excluded_paths else {
return false;
};
is_excluded_path(excluded_paths, path)
is_excluded_path(&self.excluded_paths, path)
}
/// Get the input content of a given path
@ -437,15 +443,15 @@ mod tests {
assert!(path.exists());
assert!(path.is_relative());
let input = Input::new(test_file, None, false, None);
let input = Input::new(test_file, None, false, vec![]);
assert!(input.is_ok());
assert!(matches!(
input,
Ok(Input {
source: InputSource::FsPath(PathBuf { .. }),
file_type_hint: None,
excluded_paths: None,
})
excluded_paths
}) if excluded_paths.is_empty()
));
}