| use cargo_util_schemas::manifest::PackageName; |
| |
| use crate::util::frontmatter::FrontmatterError; |
| use crate::util::frontmatter::ScriptSource; |
| |
| pub(super) fn expand_manifest(content: &str) -> Result<String, FrontmatterError> { |
| let source = ScriptSource::parse(content)?; |
| if let Some(span) = source.frontmatter_span() { |
| match source.info() { |
| Some("cargo") | None => {} |
| Some(other) => { |
| let info_span = source.info_span().unwrap(); |
| let close_span = source.close_span().unwrap(); |
| if let Some(remainder) = other.strip_prefix("cargo,") { |
| return Err(FrontmatterError::new( |
| format!("unsupported frontmatter infostring attributes: `{remainder}`"), |
| info_span, |
| ) |
| .push_visible_span(close_span)); |
| } else { |
| return Err(FrontmatterError::new( |
| format!( |
| "unsupported frontmatter infostring `{other}`; specify `cargo` for embedding a manifest" |
| ), |
| info_span, |
| ).push_visible_span(close_span)); |
| } |
| } |
| } |
| |
| // Include from file start to frontmatter end when we parse the TOML to get line numbers |
| // correct and so if a TOML error says "entire file", it shows the existing content, rather |
| // than blank lines. |
| // |
| // HACK: Since frontmatter open isn't valid TOML, we insert a comment |
| let mut frontmatter = content[0..span.end].to_owned(); |
| let open_span = source.open_span().unwrap(); |
| frontmatter.insert(open_span.start, '#'); |
| Ok(frontmatter) |
| } else { |
| // Consider the shebang to be part of the frontmatter |
| // so if a TOML error says "entire file", it shows the existing content, rather |
| // than blank lines. |
| let span = source.shebang_span().unwrap_or(0..0); |
| Ok(content[span].to_owned()) |
| } |
| } |
| |
| /// Ensure the package name matches the validation from `ops::cargo_new::check_name` |
| pub fn sanitize_name(name: &str) -> String { |
| let placeholder = if name.contains('_') { |
| '_' |
| } else { |
| // Since embedded manifests only support `[[bin]]`s, prefer arrow-case as that is the |
| // more common convention for CLIs |
| '-' |
| }; |
| |
| PackageName::sanitize(name, placeholder).into_inner() |
| } |
| |
| #[cfg(test)] |
| mod test { |
| use snapbox::assert_data_eq; |
| use snapbox::str; |
| |
| use super::*; |
| |
| #[track_caller] |
| fn expand(source: &str) -> String { |
| expand_manifest(source).unwrap_or_else(|err| panic!("{}", err)) |
| } |
| |
| #[test] |
| fn expand_default() { |
| assert_data_eq!(expand(r#"fn main() {}"#), str![""]); |
| } |
| |
| #[test] |
| fn expand_dependencies() { |
| assert_data_eq!( |
| expand( |
| r#"---cargo |
| [dependencies] |
| time="0.1.25" |
| --- |
| fn main() {} |
| "# |
| ), |
| str![[r##" |
| #---cargo |
| [dependencies] |
| time="0.1.25" |
| |
| "##]] |
| ); |
| } |
| } |