aboutsummaryrefslogtreecommitdiff
path: root/.run/src/bin/deploy-api-docs.rs
blob: 7aa093ca32dd6513888d8ac8840ef454d0bb9c61 (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
use std::path::Path;

use tools::{println_cargo_style, run_cmd};

const OUTPUT_DIR: &str = "docs/api-docs";

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

    // 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
    let output_path = repo_root.join(OUTPUT_DIR);
    std::fs::create_dir_all(&output_path).expect("Failed to create output directory");

    // Build cargo doc command
    let cmd = format!(
        "cargo doc --no-deps --features \"{}\" -p mingling --target-dir \"{}\" --color always",
        features_arg,
        output_path.join("target").to_string_lossy()
    );

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

    // Run cargo doc, then copy generated docs to output directory
    println_cargo_style!("Building: docs (cargo doc --no-deps)");
    run_cmd!(&cmd).unwrap_or_else(|code| {
        eprintln!("Error: cargo doc failed with exit code {}", code);
        std::process::exit(code);
    });

    // Copy generated docs from target/doc to OUTPUT_DIR (top level)
    let doc_source = output_path.join("target").join("doc");
    let doc_dest = &output_path;

    if doc_source.exists() {
        println_cargo_style!("Copying: docs to output directory");
        // Remove old docs in destination (except target/)
        if let Ok(entries) = std::fs::read_dir(doc_dest) {
            for entry in entries.flatten() {
                let path = entry.path();
                if path.file_name().and_then(|n| n.to_str()) == Some("target") {
                    continue;
                }
                if path.is_dir() {
                    std::fs::remove_dir_all(&path).ok();
                } else {
                    std::fs::remove_file(&path).ok();
                }
            }
        }
        copy_dir_recursively(&doc_source, doc_dest).expect("Failed to copy documentation");
    }

    // Clean up the intermediate target directory to save space
    std::fs::remove_dir_all(output_path.join("target")).ok();

    println_cargo_style!("Done: API docs deployed to {}", output_path.display());
}

fn copy_dir_recursively(src: &Path, dst: &Path) -> std::io::Result<()> {
    if !dst.exists() {
        std::fs::create_dir_all(dst)?;
    }

    for entry in std::fs::read_dir(src)? {
        let entry = entry?;
        let file_type = entry.file_type()?;
        let src_path = entry.path();
        let file_name = src_path.file_name().expect("Failed to get file name");
        let dst_path = dst.join(file_name);

        if file_type.is_dir() {
            copy_dir_recursively(&src_path, &dst_path)?;
        } else {
            std::fs::copy(&src_path, &dst_path)?;
        }
    }

    Ok(())
}

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
}