Skip to content

Commit f6b678e

Browse files
committed
review: make index_files an Option for clearer default behavior
this changes all the `index_files` fields to be `Option<Vec<String>>` instead of only a vec. this lets API users simply pass a None to get the default behaviour. documentation at the higher level interfaces (e.g., the CLI help) is changed to remove reference to `.` as the default behaviour. now, the default behaviour is defined in terms of its observable behaviour without reference to this implementation detail. that said, the index file resolution still has this special case that `.` is allowed in the `index_files` list. this allows the (possibly esoteric) case where a user passes `--index-files index.html,.` to use an index file if it exists but still accept the link regardless. the None case for index_files is still implemented by mapping to an index file list of `["."]`, but this is now only an implementation detail of `apply_index_files`. finally, using an Option is nicer than special-casing the empty `Vec<String>` case, because the empty vec case /should/ reject all directory links. this follows logically because the fewer items in the index file list, the fewer directory links are valid.
1 parent 8d25acd commit f6b678e

File tree

4 files changed

+64
-59
lines changed

4 files changed

+64
-59
lines changed

README.md

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -461,25 +461,20 @@ Options:
461461
Note: This option only takes effect on `file://` URIs which do not exist.
462462
463463
--index-files <INDEX_FILES>
464-
When checking locally, resolves directory links to an index file within the
465-
directory. The argument is a comma-separated list of index file names to search
466-
for. Index files are attempted in the order given, and at least one must exist
467-
in order for a directory link to be considered valid.
464+
When checking locally, resolves directory links to an index file
465+
within the directory. The argument is a comma-separated list of index file
466+
names to search for. Index files are attempted in the order given.
468467
469-
The special name `.` can be used to resolve directory links to the directory
470-
itself. When `.` is specified, a directory link will be accepted as long as the
471-
directory exists. This is the default behavior.
468+
If --index-files is specified, then at least one index file must exist in
469+
order for a directory link to be considered valid.
472470
473-
An empty string can be passed to reject all local directory links. This will
474-
require all links to explicitly name an HTML file, rather than linking to a
475-
directory.
471+
By default, index files are disabled, and directory links are considered valid
472+
as long as the directory exists on disk.
476473
477474
Example: --index-files index.html,readme.md
478475
479476
Note: This option only takes effect on `file://` URIs which exist and point to a directory.
480477
481-
[default: .]
482-
483478
-H, --header <HEADER:VALUE>
484479
Set custom header for requests
485480

lychee-bin/src/options.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -563,26 +563,22 @@ Note: This option only takes effect on `file://` URIs which do not exist."
563563
#[serde(default)]
564564
#[arg(
565565
long,
566-
default_value = ".",
567566
value_delimiter = ',',
568-
long_help = "When checking locally, resolves directory links to an index file within the
569-
directory. The argument is a comma-separated list of index file names to search
570-
for. Index files are attempted in the order given, and at least one must exist
571-
in order for a directory link to be considered valid.
567+
long_help = "When checking locally, resolves directory links to an index file
568+
within the directory. The argument is a comma-separated list of index file
569+
names to search for. Index files are attempted in the order given.
572570
573-
The special name `.` can be used to resolve directory links to the directory
574-
itself. When `.` is specified, a directory link will be accepted as long as the
575-
directory exists. This is the default behavior.
571+
If --index-files is specified, then at least one index file must exist in
572+
order for a directory link to be considered valid.
576573
577-
An empty string can be passed to reject all local directory links. This will
578-
require all links to explicitly name an HTML file, rather than linking to a
579-
directory.
574+
By default, index files are disabled, and directory links are considered valid
575+
as long as the directory exists on disk.
580576
581577
Example: --index-files index.html,readme.md
582578
583579
Note: This option only takes effect on `file://` URIs which exist and point to a directory."
584580
)]
585-
pub(crate) index_files: Vec<String>,
581+
pub(crate) index_files: Option<Vec<String>>,
586582

587583
/// Set custom header for requests
588584
#[arg(

lychee-lib/src/checker/file.rs

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@ pub(crate) struct FileChecker {
1919
base: Option<Base>,
2020
/// List of file extensions to try if the original path doesn't exist.
2121
fallback_extensions: Vec<String>,
22-
/// List of index file names to search for if the path is a directory.
22+
/// If specified, resolves to one of the given index files if the original path
23+
/// is a directory.
2324
///
24-
/// Index files names are required to match regular files, aside from the
25-
/// special `.` name which will match the directory itself. This list
26-
/// *should* be non-empty, otherwise all directory links will be considered
27-
/// invalid due to "cannot find index file".
28-
index_files: Vec<String>,
25+
/// If non-`None`, a directory must contain at least one of the file names
26+
/// in order to be considered a valid link target. Index files names are
27+
/// required to match regular files, aside from the special `.` name which
28+
/// will match the directory itself.
29+
///
30+
/// If `None`, index file checking is disabled and directory links are valid
31+
/// as long as the directory exists on disk.
32+
index_files: Option<Vec<String>>,
2933
/// Whether to check for the existence of fragments (e.g., `#section-id`) in HTML files.
3034
include_fragments: bool,
3135
/// Utility for performing fragment checks in HTML files.
@@ -39,12 +43,12 @@ impl FileChecker {
3943
///
4044
/// * `base` - Optional base path or URL for resolving relative paths.
4145
/// * `fallback_extensions` - List of extensions to try if the original file is not found.
42-
/// * `index_files` - List of index file names to search for if the path is a directory.
46+
/// * `index_files` - Optional list of index file names to search for if the path is a directory.
4347
/// * `include_fragments` - Whether to check for fragment existence in HTML files.
4448
pub(crate) fn new(
4549
base: Option<Base>,
4650
fallback_extensions: Vec<String>,
47-
index_files: Vec<String>,
51+
index_files: Option<Vec<String>>,
4852
include_fragments: bool,
4953
) -> Self {
5054
Self {
@@ -178,26 +182,36 @@ impl FileChecker {
178182
}
179183

180184
/// Tries to find an index file in the given directory, returning the first match.
185+
/// The index file behavior is specified by [`FileChecker::index_files`].
186+
///
187+
/// If this is non-`None`, index files must exist and resolved index files are
188+
/// required to be files, aside from the special name `.` - this will match the
189+
/// directory itself.
181190
///
182-
/// Resolved index files are required to be files, aside from the special
183-
/// name `.` - this will match the directory itself. This permits `.` to be
184-
/// specified in [`FileChecker::index_files`] to treat a directory as its own
185-
/// index file, accepting the link so long as the directory exists.
191+
/// If `None`, index file resolution is disabled and this function simply
192+
/// returns the given path.
186193
///
187194
/// # Arguments
188195
///
189196
/// * `dir_path` - The directory within which to search for index files.
190-
/// This is assumed to be a directory.
197+
/// This is assumed to be an existing directory.
191198
///
192199
/// # Returns
193200
///
194201
/// Returns `Ok(PathBuf)` pointing to the first existing index file, or
195202
/// `Err` if no index file is found. If `Ok` is returned, the contained `PathBuf`
196203
/// is guaranteed to exist. In most cases, the returned path will be a file path.
197-
/// If `.` appears within [`FileChecker::index_files`], then the returned path
198-
/// may also be a directory.
204+
///
205+
/// If index files are disabled, simply returns `Ok(dir_path)`.
199206
fn apply_index_files(&self, dir_path: &Path) -> Result<PathBuf, ErrorKind> {
200-
self.index_files
207+
// this implements the "disabled" case by treating a directory as its
208+
// own index file.
209+
let index_names_to_try = match &self.index_files {
210+
Some(names) => &names[..],
211+
None => &[".".to_owned()],
212+
};
213+
214+
index_names_to_try
201215
.iter()
202216
.find_map(|filename| {
203217
// for some special index file names, we accept directories as well
@@ -304,9 +318,8 @@ mod tests {
304318

305319
#[tokio::test]
306320
async fn test_default() {
307-
// default behaviour from passing "." as index_files.
308-
// this accepts dir links as long as the directory exists.
309-
let checker = FileChecker::new(None, vec![], vec![".".to_owned()], true);
321+
// default behaviour accepts dir links as long as the directory exists.
322+
let checker = FileChecker::new(None, vec![], None, true);
310323

311324
assert_filecheck!(&checker, "filechecker/index_dir", Status::Ok(_));
312325

@@ -338,7 +351,7 @@ mod tests {
338351
let checker = FileChecker::new(
339352
None,
340353
vec![],
341-
vec!["index.html".to_owned(), "index.md".to_owned()],
354+
Some(vec!["index.html".to_owned(), "index.md".to_owned()]),
342355
true,
343356
);
344357

@@ -377,7 +390,7 @@ mod tests {
377390
let checker = FileChecker::new(
378391
None,
379392
vec!["html".to_owned()],
380-
vec!["index".to_owned()],
393+
Some(vec!["index".to_owned()]),
381394
false,
382395
);
383396

@@ -411,7 +424,7 @@ mod tests {
411424
#[tokio::test]
412425
async fn test_empty_index_list_corner() {
413426
// empty index_files list will reject all directory links
414-
let checker_no_indexes = FileChecker::new(None, vec![], vec![], false);
427+
let checker_no_indexes = FileChecker::new(None, vec![], Some(vec![]), false);
415428
assert_filecheck!(
416429
&checker_no_indexes,
417430
"filechecker/index_dir",
@@ -435,7 +448,7 @@ mod tests {
435448
"..".to_owned(),
436449
"/".to_owned(),
437450
];
438-
let checker_dir_indexes = FileChecker::new(None, vec![], dir_names, false);
451+
let checker_dir_indexes = FileChecker::new(None, vec![], Some(dir_names), false);
439452
assert_filecheck!(
440453
&checker_dir_indexes,
441454
"filechecker/index_dir",
@@ -456,7 +469,7 @@ mod tests {
456469
let checker_dotdot = FileChecker::new(
457470
None,
458471
vec![],
459-
vec!["../index_dir/index.html".to_owned()],
472+
Some(vec!["../index_dir/index.html".to_owned()]),
460473
true,
461474
);
462475
assert_filecheck!(

lychee-lib/src/client.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -96,17 +96,18 @@ pub struct ClientBuilder {
9696
/// Index file names to use when resolving `file://` URIs which point to
9797
/// directories.
9898
///
99-
/// For local directory links, at least one index file from this list must
100-
/// exist in order for the link to be considered valid.
101-
///
102-
/// Index files names are required to match regular files, aside from the
103-
/// special `.` name which will match the directory itself. In the
104-
/// [`ClientBuilder`], this defaults to `["."]`.
105-
///
106-
/// This option only takes effect on `file://` URIs which exist and
107-
/// point to a directory.
108-
#[builder(default = vec![".".to_owned()])]
109-
index_files: Vec<String>,
99+
/// For local directory links, if this is non-`None`, then at least one
100+
/// index file from this list must exist in order for the link to be
101+
/// considered valid. Index files names are required to match regular
102+
/// files, aside from the special `.` name which will match the
103+
/// directory itself.
104+
///
105+
/// If `None`, index file checking is disabled and directory links are valid
106+
/// as long as the directory exists on disk.
107+
///
108+
/// In the [`ClientBuilder`], this defaults to `None`.
109+
#[builder(default = None)]
110+
index_files: Option<Vec<String>>,
110111

111112
/// Links matching this set of regular expressions are **always** checked.
112113
///

0 commit comments

Comments
 (0)