Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub const FEATURE_BRANCH: &str = r"^features?[/-](?<BranchName>.+)$";
pub const TAG_PREFIX: &str = r"[vV]?";
pub const PRE_RELEASE_TAG: &str = "pre";
pub const COMMIT_MESSAGE_INCREMENTING: &str = "Disabled";
pub const ASSEMBLY_INFORMATIONAL_FORMAT: &str = "{InformationalVersion}";

pub const NO_BRANCH_NAME: &str = "(no branch)";
pub const PRERELEASE_WEIGHT_MAIN: u64 = 55000;
Expand All @@ -28,6 +29,9 @@ pub trait Configuration {
fn tag_prefix(&self) -> &str;
fn pre_release_tag(&self) -> &str;
fn commit_message_incrementing(&self) -> &str;
fn assembly_informational_format(&self) -> &str {
ASSEMBLY_INFORMATIONAL_FORMAT
}
fn continuous_delivery(&self) -> &bool {
&false
}
Expand All @@ -50,6 +54,7 @@ pub trait Configuration {
tag_prefix: self.tag_prefix().to_string(),
pre_release_tag: self.pre_release_tag().to_string(),
commit_message_incrementing: self.commit_message_incrementing().to_string(),
assembly_informational_format: self.assembly_informational_format().to_string(),
continuous_delivery: *self.continuous_delivery(),
}
}
Expand All @@ -65,6 +70,7 @@ pub struct DefaultConfig {
pub tag_prefix: String,
pub pre_release_tag: String,
pub commit_message_incrementing: String,
pub assembly_informational_format: String,
pub continuous_delivery: bool,
}

Expand All @@ -77,6 +83,8 @@ pub struct ConfigurationFile {
pub tag_prefix: Option<String>,
pub pre_release_tag: Option<String>,
pub commit_message_incrementing: Option<String>,
#[serde(alias = "assembly-informational-format")]
pub assembly_informational_format: Option<String>,
}

#[derive(Parser, Debug)]
Expand Down Expand Up @@ -131,6 +139,13 @@ pub struct Args {
)]
commit_message_incrementing: Option<String>,

#[arg(
long,
value_parser,
help = "Format string for InformationalVersion output"
)]
assembly_informational_format: Option<String>,

#[arg(short, long, help = "Forces release generation instead of pre-release")]
as_release: bool,

Expand Down Expand Up @@ -165,6 +180,7 @@ impl Default for DefaultConfig {
tag_prefix: TAG_PREFIX.to_string(),
pre_release_tag: PRE_RELEASE_TAG.to_string(),
commit_message_incrementing: COMMIT_MESSAGE_INCREMENTING.to_string(),
assembly_informational_format: ASSEMBLY_INFORMATIONAL_FORMAT.to_string(),
continuous_delivery: false,
}
}
Expand Down Expand Up @@ -192,6 +208,9 @@ impl Configuration for DefaultConfig {
fn commit_message_incrementing(&self) -> &str {
&self.commit_message_incrementing
}
fn assembly_informational_format(&self) -> &str {
&self.assembly_informational_format
}
}

impl ConfigurationFile {
Expand Down Expand Up @@ -281,6 +300,7 @@ impl Configuration for ConfigurationLayers {
config_getter!(tag_prefix, str, arg > file > default);
config_getter!(pre_release_tag, str, arg > file > default);
config_getter!(commit_message_incrementing, str, arg > file > default);
config_getter!(assembly_informational_format, str, arg > file > default);
config_getter!(continuous_delivery, bool, arg);
config_getter!(path, PathBuf, arg > default);
config_getter!(as_release, bool, arg);
Expand Down
62 changes: 61 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use regex::Regex;
use semver::{Comparator, Op, Prerelease, Version};
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use std::env;
use std::fmt::{Debug, Display};
use std::time;

Expand Down Expand Up @@ -113,6 +114,7 @@ impl GitVersioner {
source.commit_id,
prerelease_weight,
head,
config.assembly_informational_format(),
))
}

Expand Down Expand Up @@ -687,6 +689,7 @@ impl GitVersion {
source: Oid,
prerelease_weight: u64,
head: Reference,
assembly_informational_format: &str,
) -> Self {
let pre_release_number = version
.pre
Expand All @@ -711,7 +714,7 @@ impl GitVersion {
} else {
source.to_string()
};
Self {
let mut result = Self {
major: version.major,
minor: version.minor,
patch: version.patch,
Expand Down Expand Up @@ -754,7 +757,64 @@ impl GitVersion {
branch_name,
full_build_meta_data: "".to_string(),
uncommitted_changes: 0,
};
result.informational_version = result.format(assembly_informational_format);
result
}

fn format(&self, format: &str) -> String {
let mut values = std::collections::HashMap::new();
if let Ok(serialized) = serde_json::to_value(self)
&& let Some(entries) = serialized.as_object()
{
for (key, raw_value) in entries {
let value = match raw_value {
serde_json::Value::String(value) => value.clone(),
_ => raw_value.to_string(),
};
values.insert(key.clone(), value);
}
}

let expression_pattern = Regex::new(r"\{([^{}]+)\}").unwrap();
expression_pattern
.replace_all(format, |captures: &regex::Captures<'_>| {
let whole = captures.get(0).map(|m| m.as_str()).unwrap_or_default();
let expression = captures.get(1).map(|m| m.as_str()).unwrap_or_default();
Self::resolve_expression(expression, &values).unwrap_or_else(|| whole.to_string())
})
.into_owned()
}

fn resolve_expression(
expression: &str,
values: &std::collections::HashMap<String, String>,
) -> Option<String> {
let (name, fallback) = match expression.split_once("??") {
Some((name, fallback)) => (name.trim(), Some(fallback.trim())),
None => (expression.trim(), None),
};

Self::resolve_atom(name, values).or_else(|| {
fallback.and_then(|fallback| {
Self::resolve_atom(fallback, values).or_else(|| Some(fallback.to_string()))
})
})
}

fn resolve_atom(
atom: &str,
values: &std::collections::HashMap<String, String>,
) -> Option<String> {
if let Some(env_name) = atom.strip_prefix("env:") {
let env_name = env_name.trim();
if env_name.is_empty() {
return None;
}
return env::var(env_name).ok();
}

values.get(atom).cloned()
}
}

Expand Down
12 changes: 12 additions & 0 deletions tests/cli_no_configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,15 @@ fn test_commit_message_incrementing(mut repo: ConfiguredTestRepo) {
repo.inner.config.commit_message_incrementing = "Enabled".to_string();
repo.execute_and_verify(["--commit-message-incrementing", "Enabled"], None);
}

#[rstest]
fn test_argument_assembly_informational_format(mut repo: ConfiguredTestRepo) {
repo.inner.config.assembly_informational_format = "{InformationalVersion}-custom".to_string();
repo.execute_and_verify(
[
"--assembly-informational-format",
"{InformationalVersion}-custom",
],
None,
);
}
31 changes: 31 additions & 0 deletions tests/cli_with_configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,34 @@ fn test_that_cli_argument_overrides_configuration_of_commit_message_incrementing
Some((DEFAULT_CONFIG, ext)),
);
}

#[apply(default)]
fn test_that_config_file_overrides_default_assembly_informational_format(
mut repo: TestRepo,
ext: &str,
) {
repo.config_file.assembly_informational_format =
Some("{InformationalVersion}-custom".to_string());

repo.inner.config.assembly_informational_format = "{InformationalVersion}-custom".to_string();
repo.execute_and_verify([], Some((DEFAULT_CONFIG, ext)));
}

#[apply(default)]
fn test_that_cli_argument_overrides_configuration_of_assembly_informational_format(
mut repo: TestRepo,
ext: &str,
) {
repo.config_file.assembly_informational_format =
Some("{InformationalVersion}-from-config".to_string());

repo.inner.config.assembly_informational_format =
"{InformationalVersion}-from-args".to_string();
repo.execute_and_verify(
[
"--assembly-informational-format",
"{InformationalVersion}-from-args",
],
Some((DEFAULT_CONFIG, ext)),
);
}
5 changes: 5 additions & 0 deletions tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub struct TestConfig {
pub tag_prefix: String,
pub pre_release_tag: String,
pub commit_message_incrementing: String,
pub assembly_informational_format: String,
pub continuous_delivery: bool,
pub as_release: bool,
}
Expand All @@ -47,6 +48,7 @@ impl Configuration for TestConfig {
config_getter!(tag_prefix, str);
config_getter!(pre_release_tag, str);
config_getter!(commit_message_incrementing, str);
config_getter!(assembly_informational_format, str);
config_getter!(continuous_delivery, bool);
config_getter!(as_release, bool);
}
Expand All @@ -62,6 +64,7 @@ impl Default for TestConfig {
tag_prefix: default.tag_prefix,
pre_release_tag: default.pre_release_tag,
commit_message_incrementing: default.commit_message_incrementing,
assembly_informational_format: default.assembly_informational_format,
continuous_delivery: default.continuous_delivery,
as_release: false,
}
Expand Down Expand Up @@ -375,4 +378,6 @@ impl Assertable {
config_assertion!(sha, &str);
config_assertion!(short_sha, &str);
config_assertion!(version_source_sha, &str);
config_assertion!(pre_release_label_with_dash, &str);
config_assertion!(informational_version, &str);
}
2 changes: 1 addition & 1 deletion tests/snapshots/approved__configuration_toml.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
source: tests/approved.rs
assertion_line: 27
expression: default_config_file_content
---
MainBranch = "^(trunk|main|master)$"
Expand All @@ -9,3 +8,4 @@ FeatureBranch = "^features?[/-](?<BranchName>.+)$"
TagPrefix = "[vV]?"
PreReleaseTag = "pre"
CommitMessageIncrementing = "Disabled"
AssemblyInformationalFormat = "{InformationalVersion}"
2 changes: 1 addition & 1 deletion tests/snapshots/approved__configuration_yaml.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
source: tests/approved.rs
assertion_line: 27
expression: default_config_file_content
---
MainBranch: ^(trunk|main|master)$
Expand All @@ -9,3 +8,4 @@ FeatureBranch: ^features?[/-](?<BranchName>.+)$
TagPrefix: '[vV]?'
PreReleaseTag: pre
CommitMessageIncrementing: Disabled
AssemblyInformationalFormat: '{InformationalVersion}'
2 changes: 1 addition & 1 deletion tests/snapshots/approved__configuration_yml.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
source: tests/approved.rs
assertion_line: 27
expression: default_config_file_content
---
MainBranch: ^(trunk|main|master)$
Expand All @@ -9,3 +8,4 @@ FeatureBranch: ^features?[/-](?<BranchName>.+)$
TagPrefix: '[vV]?'
PreReleaseTag: pre
CommitMessageIncrementing: Disabled
AssemblyInformationalFormat: '{InformationalVersion}'
2 changes: 2 additions & 0 deletions tests/snapshots/approved__help_text.snap
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ Options:
Calculate version using continuous delivery mode
--commit-message-incrementing <COMMIT_MESSAGE_INCREMENTING>
Increment based on conventional commits ('Disabled' (default) or 'Enabled')
--assembly-informational-format <ASSEMBLY_INFORMATIONAL_FORMAT>
Format string for InformationalVersion output
-a, --as-release
Forces release generation instead of pre-release
--show-config
Expand Down
3 changes: 3 additions & 0 deletions tests/snapshots/approved__long_help_text.snap
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ Options:
(e.g. v1.2.0), only the patch version will be incremented (e.g. v1.2.1) until a `feat:`
commit is encountered or a release branch is created.

--assembly-informational-format <ASSEMBLY_INFORMATIONAL_FORMAT>
Format string for InformationalVersion output

-a, --as-release
Forces release generation instead of pre-release

Expand Down
3 changes: 2 additions & 1 deletion tests/snapshots/approved__output_from_show_config.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
source: tests/cli_no_configuration.rs
source: tests/approved.rs
info:
program: git-versioner
args:
Expand All @@ -16,6 +16,7 @@ FeatureBranch = "^features?[/-](?<BranchName>.+)$"
TagPrefix = "[vV]?"
PreReleaseTag = "pre"
CommitMessageIncrementing = "Disabled"
AssemblyInformationalFormat = "{InformationalVersion}"
ContinuousDelivery = false


Expand Down
Loading