xd 0.0.4

tool that dumps binary input in a variety of formats
Documentation
//! Generates a README that prepends CARGO_PKG_REPOSITORY, at the tag
//! with the same name as CARGO_PKG_VERSION, to each image URL, then
//! verifies that ../README.registry.md is up to date. We currently
//! only patch images that occupy a source line without any other
//! content (this notably excludes badges, which are image links).
//!
//! rust-lang/crates.io can do this for a CARGO_PKG_REPOSITORY on
//! Bitbucket, but currently hard-codes “master” as the commit, which
//! isn’t the best for Mercurial repositories, and even when valid,
//! might not be the same commit from which a README was rendered.
//!
//! When ../README.md changes, this test changes, or the crate version
//! changes, this test will fail. Run it again with the environment
//! variable UPDATE_README_FOR_REGISTRY= and commit the changes.

use std::env::var_os;
use std::fs::{copy, File};
use std::io::{BufRead, BufReader, Read, Write};

use jane_eyre::Result;
use regex::Regex;

#[test]
fn generate_and_verify_readme() -> Result<()> {
    // mktemp crate is very racy, but this is just dev tooling
    let path = mktemp::Temp::new_file()?;
    let path = path.as_ref();

    generate(File::create(path)?)?;

    let actual_path = "README.registry.md";

    if var_os("UPDATE_README_FOR_REGISTRY").is_some() {
        copy(path, actual_path)?;
    }

    let mut actual = vec![0u8; 0];
    File::open(actual_path)?.read_to_end(&mut actual)?;

    let mut expected = vec![0u8; 0];
    File::open(path)?.read_to_end(&mut expected)?;

    assert_eq!(
        actual,
        expected,
        "{} identical to {}",
        actual_path,
        path.display()
    );

    Ok(())
}

fn generate(mut registry: File) -> Result<()> {
    let pattern = Regex::new(
        r"(?x)^
            !\[
                (?P<alt>[^\]]*)
            \]\(
                (?P<src>[^)]*)
            \)
        $",
    )?;

    let replacement = format!(
        "![$alt]({}/raw/{}/$src)",
        env!("CARGO_PKG_REPOSITORY"),
        env!("CARGO_PKG_VERSION")
    );

    let original = BufReader::new(File::open("README.md")?);

    for line in original.lines() {
        writeln!(registry, "{}", pattern.replace(&line?, &*replacement))?;
    }

    Ok(())
}