1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
use semver::Version;
use crate::VersionIncrement;
/// This struct allows to increment a version by
/// specifying a configuration.
///
/// Useful if you don't like the default increment rules of the crate.
///
// # Example
///
/// ```
/// use next_version::VersionUpdater;
/// use semver::Version;
///
/// let updated_version = VersionUpdater::new()
/// .with_features_always_increment_minor(false)
/// .with_breaking_always_increment_major(true)
/// .increment(&Version::new(1, 2, 3), ["feat: commit 1", "fix: commit 2"]);
///
/// assert_eq!(Version::new(1, 3, 0), updated_version);
/// ```
#[derive(Debug)]
pub struct VersionUpdater {
pub(crate) features_always_increment_minor: bool,
pub(crate) breaking_always_increment_major: bool,
}
impl Default for VersionUpdater {
fn default() -> Self {
Self::new()
}
}
impl VersionUpdater {
/// Constructs a new instance with the default rules of the crate.
///
/// If you don't customize the struct further, it is equivalent to
/// calling [`crate::NextVersion::next`].
///
/// ```
/// use next_version::{NextVersion, VersionUpdater};
/// use semver::Version;
///
/// let version = Version::new(1, 2, 3);
/// let commits = ["feat: commit 1", "fix: commit 2"];
/// let updated_version1 = VersionUpdater::new()
/// .increment(&version, &commits);
/// let updated_version2 = version.next(&commits);
///
/// assert_eq!(updated_version1, updated_version2);
/// ```
pub fn new() -> Self {
Self {
features_always_increment_minor: false,
breaking_always_increment_major: false,
}
}
/// Configures automatic minor version increments for feature changes.
///
/// - When `true` is passed, a feature will always trigger a minor version update.
/// - When `false` is passed, a feature will trigger:
/// - a patch version update if the major version is 0.
/// - a minor version update otherwise.
///
/// Default: `false`.
///
/// ```rust
/// use semver::Version;
/// use next_version::VersionUpdater;
///
/// let commits = ["feat: make coffee"];
/// let version = Version::new(0, 2, 3);
/// assert_eq!(
/// VersionUpdater::new()
/// .with_features_always_increment_minor(true)
/// .increment(&version, &commits),
/// Version::new(0, 3, 0)
/// );
/// assert_eq!(
/// VersionUpdater::new()
/// .increment(&version, &commits),
/// Version::new(0, 2, 4)
/// );
/// ```
pub fn with_features_always_increment_minor(
mut self,
features_always_increment_minor: bool,
) -> Self {
self.features_always_increment_minor = features_always_increment_minor;
self
}
/// Configures `0 -> 1` major version increments for breaking changes.
///
/// - When `true` is passed, a breaking change commit will always trigger a major version update
/// (including the transition from version 0 to 1)
/// - When `false` is passed, a breaking change commit will trigger:
/// - a minor version update if the major version is 0.
/// - a major version update otherwise.
///
/// Default: `false`.
///
/// ```rust
/// use semver::Version;
/// use next_version::VersionUpdater;
///
/// let commits = ["feat!: incompatible change"];
/// let version = Version::new(0, 2, 3);
/// assert_eq!(
/// VersionUpdater::new()
/// .with_breaking_always_increment_major(true)
/// .increment(&version, &commits),
/// Version::new(1, 0, 0)
/// );
/// assert_eq!(
/// VersionUpdater::new()
/// .increment(&version, &commits),
/// Version::new(0, 3, 0)
/// );
/// ```
pub fn with_breaking_always_increment_major(
mut self,
breaking_always_increment_major: bool,
) -> Self {
self.breaking_always_increment_major = breaking_always_increment_major;
self
}
/// Analyze commits and determine the next version.
pub fn increment<I>(self, version: &Version, commits: I) -> Version
where
I: IntoIterator,
I::Item: AsRef<str>,
{
let increment = VersionIncrement::from_commits_with_updater(&self, version, commits);
match increment {
Some(increment) => increment.bump(version),
None => version.clone(),
}
}
}