aboutsummaryrefslogtreecommitdiff
path: root/.run/src/bin/cov-test.rs
blob: a53f74c0292806bd1112f35babff89c14a1af412 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use std::fs;
use tools::{println_cargo_style, run_cmd};

const OUTPUT_DIR: &str = "docs/cov-test";

fn main() {
    let repo_root = find_git_repo().expect("Failed to find git repository root");
    let output_path = repo_root.join(OUTPUT_DIR);

    // Read features from [package.metadata.docs.rs]
    let features = tools::read_features().unwrap_or_else(|e| {
        eprintln!("Error: {}", e);
        std::process::exit(1);
    });

    let features_arg = features.join(",");

    // Ensure output directory exists
    std::fs::create_dir_all(&output_path).expect("Failed to create output directory");

    let cmd = format!(
        "cargo llvm-cov --html --output-dir \"{}\" --workspace --features \"{}\" --color always",
        output_path.to_string_lossy(),
        features_arg,
    );

    println_cargo_style!("Features: {}", features_arg);
    println_cargo_style!("Coverage: {}", output_path.display());

    println_cargo_style!("Running: cargo llvm-cov --html");
    run_cmd!(&cmd).unwrap_or_else(|code| {
        eprintln!("Error: cargo llvm-cov failed with exit code {}", code);
        std::process::exit(code);
    });

    // Move files from <output_path>/html/ to <output_path>
    let html_dir = output_path.join("html");
    if html_dir.exists() && html_dir.is_dir() {
        println_cargo_style!("Moving files from {}/html/ to {}/", OUTPUT_DIR, OUTPUT_DIR);

        // Move each entry in html_dir up one level
        for entry in fs::read_dir(&html_dir).expect("Failed to read html directory") {
            let entry = entry.expect("Failed to read entry");
            let entry_path = entry.path();
            let file_name = entry
                .file_name()
                .to_str()
                .expect("Invalid filename")
                .to_owned();

            let dest_path = output_path.join(&file_name);
            // Remove existing file/directory at destination if any
            if dest_path.exists() {
                if dest_path.is_dir() {
                    fs::remove_dir_all(&dest_path).unwrap_or_else(|e| {
                        eprintln!(
                            "Warning: could not remove directory {}: {}",
                            dest_path.display(),
                            e
                        );
                    });
                } else {
                    fs::remove_file(&dest_path).unwrap_or_else(|e| {
                        eprintln!(
                            "Warning: could not remove file {}: {}",
                            dest_path.display(),
                            e
                        );
                    });
                }
            }
            fs::rename(&entry_path, &dest_path).unwrap_or_else(|e| {
                eprintln!("Warning: could not move {}: {}", entry_path.display(), e);
            });
        }

        // Remove the now-empty html directory
        fs::remove_dir(&html_dir).unwrap_or_else(|e| {
            eprintln!("Warning: could not remove html directory: {}", e);
        });

        println_cargo_style!("Files moved successfully.");
    }

    println_cargo_style!(
        "Done: coverage report generated at {}/index.html",
        OUTPUT_DIR
    );
}

fn find_git_repo() -> Option<std::path::PathBuf> {
    let mut current_dir = std::env::current_dir().ok()?;

    loop {
        let git_dir = current_dir.join(".git");
        if git_dir.exists() && git_dir.is_dir() {
            return Some(current_dir);
        }

        if !current_dir.pop() {
            break;
        }
    }

    None
}