cargo_generate/
app_config.rs1use anyhow::{Context, Result};
2use console::style;
3use serde::Deserialize;
4use std::{
5 collections::HashMap,
6 fs,
7 path::{Path, PathBuf},
8};
9
10use crate::{info, Vcs};
11
12pub const CONFIG_FILE_NAME: &str = "cargo-generate.toml";
13
14#[derive(Deserialize, Default, Debug)]
15pub struct AppConfig {
16 pub defaults: Option<DefaultsConfig>,
17 pub favorites: Option<HashMap<String, FavoriteConfig>>,
18 pub values: Option<HashMap<String, toml::Value>>,
19}
20
21impl AppConfig {
22 pub fn get_favorite_cfg(&self, favorite_name: &str) -> Option<&FavoriteConfig> {
23 self.favorites.as_ref().and_then(|f| f.get(favorite_name))
24 }
25}
26
27#[derive(Deserialize, Default, Debug)]
28pub struct FavoriteConfig {
29 pub description: Option<String>,
30 pub git: Option<String>,
31 pub branch: Option<String>,
32 pub tag: Option<String>,
33 pub revision: Option<String>,
34 pub subfolder: Option<String>,
35 pub path: Option<PathBuf>,
36 pub values: Option<HashMap<String, toml::Value>>,
37 pub vcs: Option<Vcs>,
38 pub init: Option<bool>,
39 pub overwrite: Option<bool>,
40}
41
42#[derive(Deserialize, Default, Debug)]
43pub struct DefaultsConfig {
44 pub ssh_identity: Option<PathBuf>,
46}
47
48impl TryFrom<&Path> for AppConfig {
49 type Error = anyhow::Error;
50
51 fn try_from(path: &Path) -> Result<Self, Self::Error> {
52 if !path.exists() {
53 return Ok(Default::default());
54 }
55
56 let cfg = fs::read_to_string(path)?;
57 Ok(if cfg.trim().is_empty() {
58 Self::default()
59 } else {
60 info!("Using application config: {}", style(path.display()).bold());
61 toml::from_str(&cfg)?
62 })
63 }
64}
65
66pub fn app_config_path(path: &Option<PathBuf>) -> Result<PathBuf> {
68 path.as_ref()
69 .map(|p| p.canonicalize().unwrap())
70 .or_else(|| {
71 home::cargo_home().map_or(None, |home| {
72 let preferred_path = home.join(CONFIG_FILE_NAME);
73 if preferred_path.exists() {
74 Some(preferred_path)
75 } else {
76 let without_extension = preferred_path.with_extension("");
77 if without_extension.exists() {
78 Some(without_extension)
79 } else {
80 Some(preferred_path)
81 }
82 }
83 })
84 })
85 .with_context(|| {
86 format!(
87 r#"
88Unable to resolve path for configuration file.
89Use --config option, or place {CONFIG_FILE_NAME} in $CARGO_HOME."#
90 )
91 })
92}