• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

facet-rs / facet / 14452435544

14 Apr 2025 05:59PM UTC coverage: 26.406% (+0.03%) from 26.376%
14452435544

Pull #212

github

web-flow
Merge a15e29d15 into 1fd193c0d
Pull Request #212: Allow implementing Facet on recursive/cyclic types

5 of 27 new or added lines in 8 files covered. (18.52%)

1 existing line in 1 file now uncovered.

1686 of 6385 relevant lines covered (26.41%)

16.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/facet-codegen/src/readmes.rs
1
use facet_ansi::Stylize as _;
2
use log::{error, info};
3
use std::path::Path;
4
use std::time::Instant;
5

6
use crate::Options;
7
use crate::write_if_different;
8

9
pub(crate) fn generate_readme_files(opts: Options) -> bool {
×
10
    let mut has_diffs = false;
×
11

12
    let start = Instant::now();
×
13

14
    // Get all crate directories in the workspace
15
    let workspace_dir = std::env::current_dir().unwrap();
×
16
    let entries = fs_err::read_dir(&workspace_dir).expect("Failed to read workspace directory");
×
17

18
    // Keep track of all crates we generate READMEs for
19
    let mut generated_crates = Vec::new();
×
20

21
    let template_name = "README.md.in";
×
22

23
    // Process each crate in the workspace
24
    for entry in entries {
×
25
        let entry = entry.expect("Failed to read directory entry");
×
NEW
26
        let crate_path = entry.path();
×
27

28
        // Skip non-directories and entries starting with '.' or '_'
NEW
29
        if !crate_path.is_dir()
×
NEW
30
            || crate_path.file_name().is_some_and(|name| {
×
31
                let name = name.to_string_lossy();
×
32
                name.starts_with('.') || name.starts_with('_')
×
33
            })
34
        {
35
            continue;
×
36
        }
37

38
        // Skip target directory
NEW
39
        let dir_name = crate_path.file_name().unwrap().to_string_lossy();
×
40
        if dir_name == "target" {
×
41
            continue;
×
42
        }
43

44
        // Check if this is a crate directory (has a Cargo.toml)
NEW
45
        let cargo_toml_path = crate_path.join("Cargo.toml");
×
46
        if !cargo_toml_path.exists() {
×
47
            continue;
×
48
        }
49

50
        // Get crate name from directory name
51
        let crate_name = dir_name.to_string();
×
52

53
        // Check for templates
54
        let template_path = if crate_name == "facet" {
×
55
            Path::new(template_name).to_path_buf()
×
56
        } else {
NEW
57
            crate_path.join(template_name)
×
58
        };
59

60
        if template_path.exists() {
×
61
            // Get crate name from directory name
NEW
62
            let crate_name = crate_path
×
63
                .file_name()
64
                .unwrap()
65
                .to_string_lossy()
66
                .to_string();
67
            process_readme_template(
NEW
68
                &crate_name,
×
NEW
69
                &crate_path,
×
NEW
70
                &template_path,
×
NEW
71
                &mut has_diffs,
×
NEW
72
                opts.clone(),
×
73
            );
UNCOV
74
            generated_crates.push(crate_name);
×
75
        } else {
76
            error!("🚫 Missing template: {}", template_path.display().red());
×
77
            panic!();
×
78
        }
79
    }
80

81
    // Generate workspace README, too (which is the same as the `facet` crate)
82
    let workspace_template_path = workspace_dir.join(template_name);
×
83
    if !workspace_template_path.exists() {
×
84
        error!(
×
85
            "🚫 {}",
×
86
            format!(
×
87
                "Template file {} not found for workspace. We looked at {}",
×
88
                template_name,
×
89
                workspace_template_path.display()
×
90
            )
91
            .red()
×
92
        );
93
        panic!();
×
94
    }
95

96
    process_readme_template(
97
        "facet",
98
        &workspace_dir,
×
99
        &workspace_template_path,
×
100
        &mut has_diffs,
×
101
        opts.clone(),
×
102
    );
103

104
    // Add workspace to the list of generated READMEs
105
    generated_crates.push("workspace".to_string());
×
106

107
    // Print a comma-separated list of all crates we generated READMEs for
108
    let execution_time = start.elapsed();
×
109
    if opts.check {
×
110
        info!(
×
111
            "📚 Checked READMEs for: {} (took {:?})",
×
112
            generated_crates.join(", ").blue(),
×
113
            execution_time
114
        );
115
    } else if has_diffs {
×
116
        info!(
×
117
            "📚 Generated READMEs for: {} (took {:?})",
×
118
            generated_crates.join(", ").blue(),
×
119
            execution_time
120
        );
121
    } else {
122
        info!(
×
123
            "✅ No changes to READMEs for: {} (took {:?})",
×
124
            generated_crates.join(", ").blue(),
×
125
            execution_time
126
        );
127
    }
128
    has_diffs
×
129
}
130

131
fn process_readme_template(
×
132
    crate_name: &str,
133
    crate_path: &Path,
134
    template_path: &Path,
135
    has_diffs: &mut bool,
136
    opts: Options,
137
) {
138
    // Read the template
139
    let template_content = fs_err::read_to_string(template_path)
×
140
        .unwrap_or_else(|_| panic!("Failed to read template file: {:?}", template_path));
×
141

142
    // Combine header, template content, and footer
NEW
143
    let header = generate_header(crate_name);
×
144
    let footer = generate_footer();
×
145
    let content = format!("{}\n{}\n{}", header, template_content, footer);
×
146

147
    // Save the rendered content to README.md
148
    let readme_path = crate_path.join("README.md");
×
149
    *has_diffs |= write_if_different(&readme_path, content.into_bytes(), opts.check);
×
150
}
151

152
// Define header and footer templates
153
fn generate_header(crate_name: &str) -> String {
×
154
    let template = include_str!("header.md");
×
155
    template.replace("{CRATE}", crate_name)
×
156
}
157

158
fn generate_footer() -> String {
×
159
    include_str!("footer.md").to_string()
×
160
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc