|
1 | 1 | use std::{
|
| 2 | + collections::BTreeMap, |
2 | 3 | env,
|
3 | 4 | fs::{self, File},
|
4 |
| - io::{Read, Write}, |
| 5 | + io::Write, |
5 | 6 | path::{Path, PathBuf},
|
6 | 7 | process::{Command, Stdio},
|
7 | 8 | };
|
8 | 9 |
|
| 10 | +use serde::{Deserialize, Serialize}; |
| 11 | + |
9 | 12 | use crate::{
|
10 | 13 | build::*,
|
11 | 14 | config::{ContractKind, NewPackageConfig},
|
@@ -68,6 +71,30 @@ fn create_regular_contract(cwd: &Path) -> anyhow::Result<()> {
|
68 | 71 | Ok(())
|
69 | 72 | }
|
70 | 73 |
|
| 74 | +/// Minimal Cargo.toml that only contains fields we need. |
| 75 | +#[derive(Debug, Deserialize, Serialize)] |
| 76 | +#[serde(rename_all = "kebab-case")] |
| 77 | +struct Manifest { |
| 78 | + package: toml::Value, |
| 79 | + dependencies: toml::Value, |
| 80 | + #[serde(default)] |
| 81 | + lib: Option<ManifestLib>, |
| 82 | + #[serde(default)] |
| 83 | + features: Option<BTreeMap<String, Vec<String>>>, |
| 84 | + // Catch-all to ensure we don't drop any fields. |
| 85 | + #[serde(default, flatten)] |
| 86 | + any: Option<BTreeMap<String, toml::Value>>, |
| 87 | +} |
| 88 | + |
| 89 | +#[derive(Debug, Default, Deserialize, Serialize)] |
| 90 | +#[serde(rename_all = "kebab-case")] |
| 91 | +struct ManifestLib { |
| 92 | + name: Option<String>, |
| 93 | + path: Option<PathBuf>, |
| 94 | + crate_type: Option<Vec<String>>, |
| 95 | + required_features: Option<Vec<String>>, |
| 96 | +} |
| 97 | + |
71 | 98 | fn create_rust_crate(cwd: &Path, kind: ContractKind) -> anyhow::Result<()> {
|
72 | 99 | let (dest_path, cmd) = match kind {
|
73 | 100 | ContractKind::WebApp => (cwd.join("container"), &["new"]),
|
@@ -113,20 +140,26 @@ fn create_rust_crate(cwd: &Path, kind: ContractKind) -> anyhow::Result<()> {
|
113 | 140 |
|
114 | 141 | // add any additional config keys
|
115 | 142 | // todo: improve error handling here, in case something fails would have to rollback any changes
|
116 |
| - let mut cargo_file = File::open(dest_path.join("Cargo.toml"))?; |
117 |
| - let mut buf = vec![]; |
118 |
| - cargo_file.read_to_end(&mut buf)?; |
119 |
| - let cargo_file_content = std::str::from_utf8(buf.as_slice()).expect("Found invalid cargo file"); |
120 |
| - let mut cargo_def: toml::Value = toml::from_str(cargo_file_content)?; |
121 |
| - let lib_entry = toml::map::Map::from_iter([( |
122 |
| - "crate-type".into(), |
123 |
| - toml::Value::Array(vec![toml::Value::String("cdylib".into())]), |
124 |
| - )]); |
125 |
| - let root = cargo_def.as_table_mut().unwrap(); |
126 |
| - root.insert("lib".into(), toml::Value::Table(lib_entry)); |
127 |
| - std::mem::drop(cargo_file); |
128 |
| - let mut cargo_file = File::create(dest_path.join("Cargo.toml"))?; |
129 |
| - cargo_file.write_all(toml::to_string(&cargo_def)?.into_bytes().as_slice())?; |
| 143 | + let manifest_path = dest_path.join("Cargo.toml"); |
| 144 | + let toml_str = fs::read_to_string(&manifest_path)?; |
| 145 | + let mut manifest: Manifest = toml::from_str(&toml_str)?; |
| 146 | + |
| 147 | + manifest.lib = Some(ManifestLib { |
| 148 | + crate_type: Some(vec!["cdylib".into()]), |
| 149 | + ..Default::default() |
| 150 | + }); |
| 151 | + manifest.features = Some( |
| 152 | + [ |
| 153 | + ("default".into(), vec!["freenet-main-contract".into()]), |
| 154 | + ("contract".into(), vec!["freenet-stdlib/contract".into()]), |
| 155 | + ("freenet-main-contract".into(), vec![]), |
| 156 | + ("trace".into(), vec!["freenet-stdlib/trace".into()]), |
| 157 | + ] |
| 158 | + .into_iter() |
| 159 | + .collect(), |
| 160 | + ); |
| 161 | + |
| 162 | + fs::write(&manifest_path, toml::to_string(&manifest)?)?; |
130 | 163 | Ok(())
|
131 | 164 | }
|
132 | 165 |
|
|
0 commit comments