pray-core 1.22.0

Core library for Prayfile, the package manager for the language placed before inference
Documentation
use crate::paths::validate_destination_path;
use crate::resolve::ResolvedProject;
use crate::{PrayError, PrayResult};
use std::path::PathBuf;

#[derive(Debug, Clone)]
pub struct RenderedTarget {
    pub path: PathBuf,
    pub content: String,
    pub managed_spans: Vec<crate::lockfile::ManagedSpanRecord>,
}

pub fn render_project(project: &ResolvedProject) -> PrayResult<Vec<RenderedTarget>> {
    let mut rendered = Vec::new();
    for target in &project.manifest.targets {
        for output in &target.outputs {
            let relative = validate_destination_path(output)?;
            let rendered_target =
                crate::render_compose::render_target(project, target, relative.as_path())?;
            if let Some(max_bytes) = target.max_bytes {
                let size = rendered_target.content.len() as u64;
                if size > max_bytes {
                    return Err(PrayError::Render(format!(
                        "target `{}` output `{}` is {size} bytes; max_bytes is {max_bytes}",
                        target.name, output
                    )));
                }
            }
            rendered.push(rendered_target);
        }
    }
    Ok(rendered)
}

pub use crate::render_write::{
    layout_rendered_targets, write_rendered_targets, write_rendered_targets_with_previous_lockfile,
};

pub use crate::render_dest::{
    materialize_provisioned_exports, provisioned_destination_status,
    provisioned_destination_statuses, provisioned_lock_records, ProvisionedDestinationStatus,
};
pub use crate::render_provisioned::{
    expected_provisioned_bytes, planned_provisioned_files, PlannedProvisionedFile,
};

pub use crate::render_file::read_destination_text;

#[cfg(test)]
mod patch_tests {
    use crate::render_patch::patch_rendered_content;

    #[test]
    fn preserves_unmarked_text_and_updates_managed_body() {
        let existing = "\
## Shared instructions

User note: keep this line.

<!-- pray:abc123 -->
old body
<!-- pray:abc123 -->
";
        let fresh = "\
## Shared instructions

<!-- pray:abc123 -->
new body
<!-- pray:abc123 -->
";
        let patched = patch_rendered_content(existing, fresh);
        assert!(patched.contains("User note: keep this line."));
        assert!(patched.contains("new body"));
        assert!(!patched.contains("old body"));
    }

    #[test]
    fn rewrites_wholesale_when_existing_has_no_managed_overlap() {
        let existing = "broken rendered output\n";
        let fresh = "\
<!-- pray:abc123 -->
new body
<!-- pray:abc123 -->
";
        assert_eq!(patch_rendered_content(existing, fresh), fresh);
    }

    #[test]
    fn inserts_leading_managed_span_from_fresh_and_drops_stale_unmarked_embed() {
        let existing = "\
header

old local body

<!-- pray:abc123 -->
package body
<!-- pray:abc123 -->
";
        let fresh = "\
header

<!-- pray:local001 -->
new local body
<!-- pray:local001 -->

<!-- pray:abc123 -->
package body
<!-- pray:abc123 -->
";
        let patched = patch_rendered_content(existing, fresh);
        assert!(patched.contains("new local body"));
        assert!(!patched.contains("old local body"));
        assert!(patched.contains("<!-- pray:local001 -->"));
        assert!(patched.contains("package body"));
    }

    #[test]
    fn appends_trailing_managed_span_with_intervening_blank_line_from_fresh() {
        let existing = "\
<!-- pray:abc123 -->
package body
<!-- pray:abc123 -->
";
        let fresh = "\
<!-- pray:abc123 -->
package body
<!-- pray:abc123 -->

<!-- pray:local001 -->
new local body
<!-- pray:local001 -->
";
        assert_eq!(patch_rendered_content(existing, fresh), fresh);
    }

    #[test]
    fn restores_missing_blank_line_between_adjacent_managed_spans() {
        let existing = "\
<!-- pray:abc123 -->
package body
<!-- pray:abc123 -->
<!-- pray:local001 -->
new local body
<!-- pray:local001 -->
";
        let fresh = "\
<!-- pray:abc123 -->
package body
<!-- pray:abc123 -->

<!-- pray:local001 -->
new local body
<!-- pray:local001 -->
";
        assert_eq!(patch_rendered_content(existing, fresh), fresh);
    }
}