Skip to content

Commit

Permalink
feature(config): add support for both configuration versions
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyclonit committed Mar 24, 2024
1 parent 4cd3f3c commit 0bb23b0
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 53 deletions.
1 change: 0 additions & 1 deletion git-cliff-core/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ pub fn run(

#[cfg(test)]
mod test {
use super::*;
#[test]
#[cfg(target_family = "unix")]
fn run_os_command() -> Result<()> {
Expand Down
1 change: 1 addition & 0 deletions git-cliff-core/src/config/models_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub struct Config {
}

/// Changelog configuration.
#[allow(deprecated)]
#[deprecated(since = "3.0.0", note = "deprecated in favor of models_v2")]
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct ChangelogConfig {
Expand Down
14 changes: 9 additions & 5 deletions git-cliff-core/src/config/models_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,11 +276,15 @@ impl Config {
release: ReleaseConfig {
tags_pattern: config_v1.git.tag_pattern,
skip_tags_pattern: config_v1.git.ignore_tags,
order_by: Some(if config_v1.git.topo_order.unwrap() {
TagsOrderBy::Topology
} else {
TagsOrderBy::Time
}),
order_by: Some(
if config_v1.git.topo_order.is_some() &&
config_v1.git.topo_order.unwrap()
{
TagsOrderBy::Topology
} else {
TagsOrderBy::Time
},
),
},
commit: CommitConfig {
sort_order: config_v1.git.sort_commits.map(
Expand Down
2 changes: 1 addition & 1 deletion git-cliff-core/src/config/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn parse_config() -> Result<()> {
.expect("parent directory not found")
.to_path_buf()
.join("config")
.join(crate::DEFAULT_CONFIG);
.join(crate::DEFAULT_CONFIG_FILENAME);

const FOOTER_VALUE: &str = "test";
const RELEASE_TAGS_PATTERN_VALUE: &str = ".*[0-9].*";
Expand Down
2 changes: 1 addition & 1 deletion git-cliff-core/src/embed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub struct EmbeddedConfig;
impl EmbeddedConfig {
/// Extracts the embedded content.
pub fn get_config() -> Result<String> {
match Self::get(crate::DEFAULT_CONFIG) {
match Self::get(crate::DEFAULT_CONFIG_FILENAME) {
Some(v) => Ok(str::from_utf8(&v.data)?.to_string()),
None => Err(Error::EmbeddedError(String::from(
"Embedded config not found",
Expand Down
2 changes: 1 addition & 1 deletion git-cliff-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub mod template;
extern crate log;

/// Default configuration file.
pub const DEFAULT_CONFIG: &str = "cliff.toml";
pub const DEFAULT_CONFIG_FILENAME: &str = "cliff.toml";
/// Default output file.
pub const DEFAULT_OUTPUT: &str = "CHANGELOG.md";
/// Default ignore file.
Expand Down
13 changes: 11 additions & 2 deletions git-cliff/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use git_cliff_core::{
TagsOrderBy,
},
},
DEFAULT_CONFIG,
DEFAULT_CONFIG_FILENAME,
DEFAULT_OUTPUT,
};
use glob::Pattern;
Expand Down Expand Up @@ -107,11 +107,20 @@ pub struct Opt {
long,
env = "GIT_CLIFF_CONFIG",
value_name = "PATH",
default_value = DEFAULT_CONFIG,
default_value = DEFAULT_CONFIG_FILENAME,
value_parser = Opt::parse_dir
)]
pub config: PathBuf,

/// Sets the version of the configuration file given in `--config`.
#[arg(
long,
env = "GIT_CLIFF_CONFIG_VERSION",
value_name = "VERSION",
default_value_t = 2
)]
pub config_version: u8,

/// Sets the working directory.
#[arg(
short,
Expand Down
106 changes: 64 additions & 42 deletions git-cliff/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use args::{
};
use git_cliff_core::changelog::Changelog;
use git_cliff_core::commit::Commit;
#[allow(deprecated)]
use git_cliff_core::config::models_v1::Config as Config_v1;
use git_cliff_core::config::models_v2::{
CommitParser,
CommitSortOrder,
Expand All @@ -37,7 +39,7 @@ use git_cliff_core::error::{
use git_cliff_core::release::Release;
use git_cliff_core::repo::Repository;
use git_cliff_core::{
DEFAULT_CONFIG,
DEFAULT_CONFIG_FILENAME,
IGNORE_FILE,
};
use std::env;
Expand All @@ -49,6 +51,7 @@ use std::io::{
self,
Write,
};
use std::path::PathBuf;
use std::time::{
SystemTime,
UNIX_EPOCH,
Expand Down Expand Up @@ -294,6 +297,62 @@ fn process_repository<'a>(
Ok(releases)
}

pub fn get_config_path(path: PathBuf) -> PathBuf {
if !path.exists() {
if let Some(config_path) = dirs::config_dir().map(|dir| {
dir.join(env!("CARGO_PKG_NAME"))
.join(DEFAULT_CONFIG_FILENAME)
}) {
return config_path;
}
}
path
}

/// Loads the configuration based on the given command line arguments.
pub fn load_config(args: &Opt) -> Result<Config> {
let config_path = get_config_path(args.config.clone());
// If the argument `--config` matches the name of a config in
// ./examples, use it.
if let Ok((builtin_config, name)) =
BuiltinConfig::parse(args.config.to_string_lossy().to_string())
{
info!("Using built-in configuration file {name}.");
return Ok(builtin_config);
}
// If `--config` denotes an existing file, try loading it as configuration.
else if config_path.is_file() {
info!(
"Loading configuration from {}.",
args.config.to_string_lossy()
);

// Default to loading a v2 config.
if args.config_version == 2 {
Ok(parsing::parse::<Config>(&config_path)?)
}
// Load a v1 config and immediately convert it to v2.
else {
warn!(
"Configuration format v1 is deprecated. Consider migrating to v2. \
Refer to https://git-cliff.org/docs/configuration/migration for more information."
);
#[allow(deprecated)]
let config_v1 = parsing::parse::<Config_v1>(&config_path)?;
Ok(Config::from(config_v1))
}
}
// Otherwise fall back to using the embedded configuration from
// ./config/cliff.toml.
else {
warn!(
"{:?} could not be found. Using the default configuration.",
args.config
);
EmbeddedConfig::parse()
}
}

/// Runs `git-cliff`.
pub fn run(mut args: Opt) -> Result<()> {
// Check if there is a new version available.
Expand All @@ -309,16 +368,12 @@ pub fn run(mut args: Opt) -> Result<()> {
info!(
"Saving the configuration file{} to {:?}",
init_config.map(|v| format!(" ({v})")).unwrap_or_default(),
DEFAULT_CONFIG
DEFAULT_CONFIG_FILENAME
);
fs::write(DEFAULT_CONFIG, contents)?;
fs::write(DEFAULT_CONFIG_FILENAME, contents)?;
return Ok(());
}

// Retrieve the built-in configuration.
let builtin_config =
BuiltinConfig::parse(args.config.to_string_lossy().to_string());

// Set the working directory.
if let Some(ref workdir) = args.workdir {
args.config = workdir.join(args.config);
Expand All @@ -335,41 +390,8 @@ pub fn run(mut args: Opt) -> Result<()> {
}
}

// Parse the configuration file.
let mut path = args.config.clone();
if !path.exists() {
if let Some(config_path) = dirs::config_dir()
.map(|dir| dir.join(env!("CARGO_PKG_NAME")).join(DEFAULT_CONFIG))
{
path = config_path;
}
}

// Load the default configuration if necessary.
let mut config = if let Ok((config, name)) = builtin_config {
info!("Using built-in configuration file: {name}");
config
} else if path.exists() {
parsing::parse(&path)?
} else if let Some(contents) = Config::read_from_manifest()? {
Config::parse_from_str(&contents)?
} else {
if !args.context {
warn!(
"{:?} is not found, using the default configuration.",
args.config
);
}
EmbeddedConfig::parse()?
};
if config.changelog.body_template.is_none() && !args.context {
warn!(
"Option `changelog.body_template` is not specified, using the default \
template."
);
config.changelog.body_template =
EmbeddedConfig::parse()?.changelog.body_template;
}
// Load the configuration.
let mut config = load_config(&args)?;

// Update the configuration based on command line arguments and vice versa.
match args.strip {
Expand Down

0 comments on commit 0bb23b0

Please sign in to comment.