1
//!
2
//! xtask building block operations such as copy, remove, confirm, and more
3
//!
4
//!
5

            
6
use fs_extra as fsx;
7
use glob::glob;
8
use std::env;
9
use std::error::Error;
10
use std::fs::create_dir_all;
11
use std::path::Path;
12
use std::path::PathBuf;
13

            
14
use duct::cmd;
15

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

            
27
///
28
/// Remove a single file
29
///
30
/// # Errors
31
/// Fails if removal fails
32
///
33
fn remove_file<P>(path: P) -> Result<(), Box<dyn Error>>
34
where
35
    P: AsRef<Path>,
36
{
37
    fsx::file::remove(path)?;
38
    Ok(())
39
}
40

            
41
///
42
/// Remove a directory with its contents
43
///
44
/// # Errors
45
/// Fails if removal fails
46
///
47
fn remove_dir<P>(path: P) -> Result<(), Box<dyn Error>>
48
where
49
    P: AsRef<Path>,
50
{
51
    fsx::dir::remove(path)?;
52
    Ok(())
53
}
54

            
55
///
56
/// Run coverage
57
///
58
/// # Errors
59
/// Fails if any command fails
60
///
61
pub fn coverage(cargo_arguments: Vec<String>) -> Result<(), Box<dyn Error>> {
62
    remove_dir("target/coverage")?;
63
    create_dir_all("target/coverage")?;
64

            
65
    println!("=== running coverage ===");
66

            
67
    // The path from which cargo is called.
68
    let mut base_directory = env::current_dir().unwrap();
69
    base_directory.push("target");
70
    base_directory.push("coverage");
71

            
72
    let mut prof_directory = base_directory.clone();
73
    prof_directory.push("cargo-test-%p-%m.profraw");
74

            
75
    cmd("cargo", cargo_arguments)
76
        .env("CARGO_INCREMENTAL", "0")
77
        .env("RUSTFLAGS", "-Cinstrument-coverage")
78
        .env("LLVM_PROFILE_FILE", prof_directory)
79
        .run()?;
80
    println!("ok.");
81

            
82
    println!("=== generating report ===");
83
    let (fmt, file) = ("html", "target/coverage/html");
84
    cmd!(
85
        "grcov",
86
        base_directory,
87
        "--binary-path",
88
        "./target/debug/deps",
89
        "-s",
90
        ".",
91
        "-t",
92
        fmt,
93
        "--branch",
94
        "--ignore-not-existing",
95
        "--ignore",
96
        "**/target/*",
97
        "-o",
98
        file,
99
    )
100
    .run()?;
101
    println!("ok.");
102

            
103
    println!("=== cleaning up ===");
104
    clean_files("**/*.profraw")?;
105
    println!("ok.");
106

            
107
    println!("report location: {file}");
108

            
109
    Ok(())
110
}