Repository: sharkdp/bat
File: src/assets/build_assets/acknowledgements.rs (Rust)

Code before:
const PREAMBLE: &str = "Copyright (c) 2018-2021 bat-developers (https://github.com/sharkdp/bat).

bat is made available under the terms of either the MIT License or the Apache
License 2.0, at your option.

See the LICENSE-APACHE and LICENSE-MIT files for license details.
";

/// Looks for LICENSE and NOTICE files in `source_dir`, does some rudimentary
/// analysis, and compiles them together in a single string that is meant to be
/// used in the output to `--acknowledgements`
pub fn build_acknowledgements(source_dir: &Path, acknowledgements: bool) -> Result<Option<String>> {
    if !acknowledgements {
        return Ok(None);
    }

    let mut acknowledgements = String::new();
    acknowledgements.push_str(PREAMBLE);

    // Sort entries so the order is stable over time
    let entries = walkdir::WalkDir::new(source_dir).sort_by(|a, b| a.path().cmp(b.path()));
    for entry in entries {
        let entry = match entry {
            Ok(entry) => entry,
            Err(_) => continue,
        };

        let path = entry.path();
        let stem = match path.file_stem().and_then(|s| s.to_str()) {
            Some(stem) => stem,
            None => continue,
        };

        handle_file(&mut acknowledgements, path, stem)?
    }

    Ok(Some(acknowledgements))
}

fn handle_file(acknowledgements: &mut String, path: &Path, stem: &str) -> Result<()> {
    if stem == "NOTICE" {
        handle_notice(acknowledgements, path)?;
    } else if stem.to_ascii_uppercase() == "LICENSE" {
        handle_license(acknowledgements, path)?;
    }

    Ok(())
}

fn handle_notice(acknowledgements: &mut String, path: &Path) -> Result<()> {
    // Assume NOTICE as defined by Apache License 2.0. These must be part of acknowledgements.

Review comment (suggestion):
I think this could be:
```suggestion
    for entry in entries.iter().flatten() {
```

Code after:

struct PathAndStem {
    path: PathBuf,
    stem: String,
    relative_path: String,
}

/// Looks for LICENSE and NOTICE files in `source_dir`, does some rudimentary
/// analysis, and compiles them together in a single string that is meant to be
/// used in the output to `--acknowledgements`
pub fn build_acknowledgements(
    source_dir: &Path,
    include_acknowledgements: bool,
) -> Result<Option<String>> {
    if !include_acknowledgements {
        return Ok(None);
    }

    let mut acknowledgements = format!("{}\n\n", include_str!("../../../NOTICE"));

    // Sort entries so the order is stable over time
    let entries = walkdir::WalkDir::new(source_dir).sort_by(|a, b| a.path().cmp(b.path()));
    for path_and_stem in entries
        .into_iter()
        .flatten()
        .flat_map(|entry| to_path_and_stem(source_dir, entry))
    {
        if let Some(license_text) = handle_file(&path_and_stem)? {
            append_to_acknowledgements(
                &mut acknowledgements,
                &path_and_stem.relative_path,
                &license_text,
            )
        }
    }

    Ok(Some(acknowledgements))
}

fn to_path_and_stem(source_dir: &Path, entry: DirEntry) -> Option<PathAndStem> {
    let path = entry.path();

    Some(PathAndStem {
        path: path.to_owned(),
        stem: path.file_stem().map(|s| s.to_string_lossy().to_string())?,
        relative_path: path
            .strip_prefix(source_dir)
            .map(|p| p.to_string_lossy().to_string())
            .ok()?,
    })
}