1
use glob::glob;
2
use std::env;
3
use std::error::Error;
4
use std::fs::create_dir_all;
5
use std::fs::remove_dir_all;
6
use std::fs::remove_file;
7
use std::path::PathBuf;
8

            
9
use duct::cmd;
10

            
11
///
12
/// Remove a set of files given a glob
13
///
14
/// # Errors
15
/// Fails if listing or removal fails
16
///
17
fn clean_files(pattern: &str) -> Result<(), Box<dyn Error>> {
18
    let files: Result<Vec<PathBuf>, _> = glob(pattern)?.collect();
19
    files?.iter().try_for_each(|path| {
20
        remove_file(path)?;
21
        Ok(())
22
    })
23
}
24

            
25
///
26
/// Run coverage, pass the given arguments to cargo.
27
///
28
pub fn coverage(arguments: Vec<String>) -> Result<(), Box<dyn Error>> {
29
    // Ignore errors about missing directory.
30
    let _ = remove_dir_all("target/coverage");
31
    create_dir_all("target/coverage")?;
32

            
33
    println!("=== running coverage ===");
34

            
35
    // The path from which cargo is called.
36
    let mut base_directory = env::current_dir().unwrap();
37
    base_directory.push("target");
38
    base_directory.push("coverage");
39

            
40
    let mut prof_directory = base_directory.clone();
41
    prof_directory.push("cargo-test-%p-%m.profraw");
42

            
43
    cmd("cargo", arguments)
44
        .env("CARGO_INCREMENTAL", "0")
45
        .env("RUSTFLAGS", "-C instrument-coverage -Z coverage-options=condition")
46
        .env("LLVM_PROFILE_FILE", prof_directory)
47
        .run()?;
48
    println!("ok.");
49

            
50
    println!("=== generating report ===");
51
    let (fmt, file) = ("html", "target/coverage/html");
52
    cmd!(
53
        "grcov",
54
        base_directory,
55
        "--binary-path",
56
        "./target/debug/deps",
57
        "-s",
58
        ".",
59
        "-t",
60
        fmt,
61
        "--branch",
62
        "--ignore-not-existing",
63
        "--ignore",
64
        "**/target/*",
65
        "-o",
66
        file,
67
    )
68
    .run()?;
69
    println!("ok.");
70

            
71
    println!("=== cleaning up ===");
72
    clean_files("**/*.profraw")?;
73
    println!("ok.");
74

            
75
    println!("report location: {file}");
76

            
77
    Ok(())
78
}