|
1 |
| -use anyhow::*; |
| 1 | +use anyhow::{Context, *}; |
2 | 2 | use clap::Parser;
|
3 | 3 | use itertools::Itertools;
|
| 4 | +use json_comments::StripComments; |
4 | 5 | use log::*;
|
5 |
| -use serde::Serialize; |
| 6 | +use serde::{Deserialize, Serialize}; |
6 | 7 | use std::{
|
7 | 8 | collections::{HashMap, HashSet},
|
8 | 9 | ffi::{OsStr, OsString},
|
@@ -1357,8 +1358,59 @@ impl Xtasks {
|
1357 | 1358 | Some(Path::new(".")),
|
1358 | 1359 | )?;
|
1359 | 1360 |
|
| 1361 | + // create .vscode settings |
| 1362 | + // read from templates at compile time |
| 1363 | + let vscode_settings = include_str!("../templates/settings.json.tera"); |
| 1364 | + let mut tera = tera::Tera::default(); |
| 1365 | + let mut context = tera::Context::new(); |
| 1366 | + context.insert("dir", &Self::workspace_dir(&app_settings)?); |
| 1367 | + let templated_settings = tera.render_str(vscode_settings, &context)?; |
| 1368 | + let templated_settings_json = Self::read_json_with_comments(templated_settings.as_bytes()) |
| 1369 | + .with_context(|| "reading templated vscode settings")?; |
| 1370 | + let vscode_dir = Self::relative_workspace_dir(&app_settings, ".vscode")?; |
| 1371 | + std::fs::create_dir_all(&vscode_dir)?; |
| 1372 | + let vscode_settings_path = vscode_dir.join("settings.json"); |
| 1373 | + |
| 1374 | + // if the file already exists, merge the settings otherwise create it |
| 1375 | + info!( |
| 1376 | + "Merging vscode settings at {:?}. With overrides generated by template.", |
| 1377 | + vscode_settings_path |
| 1378 | + ); |
| 1379 | + if vscode_settings_path.exists() { |
| 1380 | + let existing_settings = std::fs::read_to_string(&vscode_settings_path)?; |
| 1381 | + let mut existing_settings = Self::read_json_with_comments(existing_settings.as_bytes()) |
| 1382 | + .with_context(|| "reading existing vscode settings file")?; |
| 1383 | + Self::merge_json(templated_settings_json, &mut existing_settings); |
| 1384 | + let merged_settings = serde_json::to_string_pretty(&existing_settings)?; |
| 1385 | + std::fs::write(&vscode_settings_path, merged_settings)?; |
| 1386 | + } else { |
| 1387 | + std::fs::write(&vscode_settings_path, templated_settings)?; |
| 1388 | + } |
| 1389 | + |
1360 | 1390 | Ok(())
|
1361 | 1391 | }
|
| 1392 | + |
| 1393 | + fn read_json_with_comments(bytes: &[u8]) -> Result<serde_json::Value> { |
| 1394 | + let stripped = StripComments::new(bytes); |
| 1395 | + let mut reader = serde_json::Deserializer::from_reader(stripped); |
| 1396 | + let value = serde_json::Value::deserialize(&mut reader)?; |
| 1397 | + Ok(value) |
| 1398 | + } |
| 1399 | + |
| 1400 | + /// Override the target json file with some overrides. Will replace values if they already exist, or insert them otherwise. |
| 1401 | + fn merge_json(overrides: serde_json::Value, target: &mut serde_json::Value) { |
| 1402 | + if let (serde_json::Value::Object(overrides), serde_json::Value::Object(target)) = |
| 1403 | + (overrides, target) |
| 1404 | + { |
| 1405 | + for (key, value) in overrides { |
| 1406 | + // simply replace |
| 1407 | + info!("Replacing json key: {} with value: {}", key, value); |
| 1408 | + target.insert(key.clone(), value.clone()); |
| 1409 | + } |
| 1410 | + } else { |
| 1411 | + warn!("Could not merge json, overrides and target are not objects"); |
| 1412 | + } |
| 1413 | + } |
1362 | 1414 | }
|
1363 | 1415 |
|
1364 | 1416 | /// Because we are likely already runnnig in the context of a cargo invocation,
|
@@ -1400,7 +1452,7 @@ fn try_main() -> Result<()> {
|
1400 | 1452 |
|
1401 | 1453 | fn main() {
|
1402 | 1454 | if let Err(e) = try_main() {
|
1403 |
| - eprintln!("{}", e); |
| 1455 | + eprintln!("{:?}", e); |
1404 | 1456 | std::process::exit(1);
|
1405 | 1457 | }
|
1406 | 1458 | }
|
0 commit comments