cargo/util/toml/embedded.rs
1use cargo_util_schemas::manifest::PackageName;
2
3use crate::CargoResult;
4use crate::util::frontmatter::ScriptSource;
5use crate::util::restricted_names;
6
7pub(super) fn expand_manifest(content: &str) -> CargoResult<String> {
8 let source = ScriptSource::parse(content)?;
9 if let Some(frontmatter) = source.frontmatter() {
10 match source.info() {
11 Some("cargo") | None => {}
12 Some(other) => {
13 if let Some(remainder) = other.strip_prefix("cargo,") {
14 anyhow::bail!(
15 "cargo does not support frontmatter infostring attributes like `{remainder}` at this time"
16 )
17 } else {
18 anyhow::bail!(
19 "frontmatter infostring `{other}` is unsupported by cargo; specify `cargo` for embedding a manifest"
20 )
21 }
22 }
23 }
24
25 Ok(frontmatter.to_owned())
26 } else {
27 let frontmatter = "";
28 Ok(frontmatter.to_owned())
29 }
30}
31
32/// Ensure the package name matches the validation from `ops::cargo_new::check_name`
33pub fn sanitize_name(name: &str) -> String {
34 let placeholder = if name.contains('_') {
35 '_'
36 } else {
37 // Since embedded manifests only support `[[bin]]`s, prefer arrow-case as that is the
38 // more common convention for CLIs
39 '-'
40 };
41
42 let mut name = PackageName::sanitize(name, placeholder).into_inner();
43
44 loop {
45 if restricted_names::is_keyword(&name) {
46 name.push(placeholder);
47 } else if restricted_names::is_conflicting_artifact_name(&name) {
48 // Being an embedded manifest, we always assume it is a `[[bin]]`
49 name.push(placeholder);
50 } else if name == "test" {
51 name.push(placeholder);
52 } else if restricted_names::is_windows_reserved(&name) {
53 // Go ahead and be consistent across platforms
54 name.push(placeholder);
55 } else {
56 break;
57 }
58 }
59
60 name
61}
62
63#[cfg(test)]
64mod test {
65 use snapbox::assert_data_eq;
66 use snapbox::str;
67
68 use super::*;
69
70 #[track_caller]
71 fn expand(source: &str) -> String {
72 expand_manifest(source).unwrap_or_else(|err| panic!("{}", err))
73 }
74
75 #[test]
76 fn expand_default() {
77 assert_data_eq!(expand(r#"fn main() {}"#), str![""]);
78 }
79
80 #[test]
81 fn expand_dependencies() {
82 assert_data_eq!(
83 expand(
84 r#"---cargo
85[dependencies]
86time="0.1.25"
87---
88fn main() {}
89"#
90 ),
91 str![[r#"
92[dependencies]
93time="0.1.25"
94
95"#]]
96 );
97 }
98}