Skip to content

Commit

Permalink
feat: add {{latest}} tag to hook dsl
Browse files Browse the repository at this point in the history
  • Loading branch information
oknozor committed Nov 30, 2021
1 parent 13eeed9 commit 5eff372
Show file tree
Hide file tree
Showing 14 changed files with 685 additions and 514 deletions.
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ conventional_commit_parser = "^0"
assert_cmd = "1.0.3"
predicates = "1"
rand = "0.7.3"
indoc = "1.0.3"

[features]
default = ["cli"]
Expand Down
31 changes: 22 additions & 9 deletions src/hook/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod parser;
#[derive(Debug, Eq, PartialEq)]
enum Token {
Version,
LatestVersion,
Amount(u32),
Add,
Major,
Expand Down Expand Up @@ -39,9 +40,21 @@ impl fmt::Display for Hook {
}

impl Hook {
pub fn insert_version(&mut self, value: &str) -> Result<()> {
pub fn insert_versions(
&mut self,
current_version: Option<String>,
next_version: &str,
) -> Result<()> {
let next_version = Version::from_str(next_version)?;
let current_version = current_version
.map(|version| Version::from_str(&version))
.map(Result::ok)
.flatten();

for i in 0..self.0.len() {
if let Some((range, version)) = HookExpr::parse(&self.0[i], Version::from_str(value)?) {
if let Some((range, version)) =
HookExpr::parse_version(&self.0[i], current_version.clone(), next_version.clone())
{
self.0[i].replace_range(range, &version);
}
}
Expand Down Expand Up @@ -82,7 +95,7 @@ mod test {
#[test]
fn replace_version_cargo() -> Result<()> {
let mut hook = Hook::from_str("cargo bump {{version}}")?;
hook.insert_version("1.0.0").unwrap();
hook.insert_versions(None, "1.0.0").unwrap();

assert_eq!(&hook.0, &["cargo", "bump", "1.0.0"]);
Ok(())
Expand All @@ -91,7 +104,7 @@ mod test {
#[test]
fn replace_maven_version() -> Result<()> {
let mut hook = Hook::from_str("mvn versions:set -DnewVersion={{version}}")?;
hook.insert_version("1.0.0").unwrap();
hook.insert_versions(None, "1.0.0").unwrap();

assert_eq!(&hook.0, &["mvn", "versions:set", "-DnewVersion=1.0.0"]);
Ok(())
Expand All @@ -100,7 +113,7 @@ mod test {
#[test]
fn replace_maven_version_with_expression() -> Result<()> {
let mut hook = Hook::from_str("mvn versions:set -DnewVersion={{version+1minor-SNAPSHOT}}")?;
hook.insert_version("1.0.0").unwrap();
hook.insert_versions(None, "1.0.0").unwrap();

assert_eq!(
&hook.0,
Expand All @@ -112,7 +125,7 @@ mod test {
#[test]
fn leave_hook_untouched_when_no_version() -> Result<()> {
let mut hook = Hook::from_str("echo \"Hello World\"")?;
hook.insert_version("1.0.0").unwrap();
hook.insert_versions(None, "1.0.0").unwrap();

assert_eq!(&hook.0, &["echo", "Hello World"]);
Ok(())
Expand All @@ -121,7 +134,7 @@ mod test {
#[test]
fn replace_quoted_version() -> Result<()> {
let mut hook = Hook::from_str("echo \"{{version}}\"")?;
hook.insert_version("1.0.0").unwrap();
hook.insert_versions(None, "1.0.0").unwrap();

assert_eq!(&hook.0, &["echo", "1.0.0"]);
Ok(())
Expand All @@ -130,7 +143,7 @@ mod test {
#[test]
fn replace_version_with_nested_simple_quoted_arg() -> Result<()> {
let mut hook = Hook::from_str("coco chore 'bump snapshot to {{version+1minor-pre}}'")?;
hook.insert_version("1.0.0").unwrap();
hook.insert_versions(None, "1.0.0").unwrap();

assert_eq!(&hook.0, &["coco", "chore", "bump snapshot to 1.1.0-pre"]);
Ok(())
Expand All @@ -139,7 +152,7 @@ mod test {
#[test]
fn replace_version_with_nested_double_quoted_arg() -> Result<()> {
let mut hook = Hook::from_str("coco chore \"bump snapshot to {{version+1minor-pre}}\"")?;
hook.insert_version("1.0.0").unwrap();
hook.insert_versions(None, "1.0.0").unwrap();

assert_eq!(&hook.0, &["coco", "chore", "bump snapshot to 1.1.0-pre"]);
Ok(())
Expand Down
42 changes: 33 additions & 9 deletions src/hook/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ impl Token {
fn parse(src: &str) -> Result<(Token, &str)> {
if let Some(remains) = src.strip_prefix("version") {
Ok((Token::Version, remains))
} else if let Some(remains) = src.strip_prefix("latest") {
Ok((Token::LatestVersion, remains))
} else if let Some(remains) = src.strip_prefix('+') {
Ok((Token::Add, remains))
} else if let Some(remains) = src.strip_prefix("major") {
Expand All @@ -43,11 +45,15 @@ impl Token {
}

impl HookExpr {
pub fn parse(src: &str, current_version: Version) -> Option<(Range<usize>, String)> {
pub fn parse_version(
src: &str,
current_version: Option<Version>,
next_version: Version,
) -> Option<(Range<usize>, String)> {
if let Some((range, mut expression)) = HookExpr::scan_hook_entry(src) {
expression.tokenize();
expression
.calculate_version(current_version)
.calculate_version(current_version, next_version)
.ok()
.map(|exp| (range, exp))
} else {
Expand Down Expand Up @@ -111,14 +117,22 @@ impl HookExpr {
version
}

fn calculate_version(&mut self, current_version: Version) -> Result<String> {
fn calculate_version(
&mut self,
current_version: Option<Version>,
next_version: Version,
) -> Result<String> {
ensure!(!self.tokens.is_empty(), "Hook expression must not be empty");
ensure!(
self.tokens.pop_front() == Some(Token::Version),
"Hook expression must start with \"version\""
);

let mut version = current_version;
let mut version = match self.tokens.pop_front() {
Some(Token::Version) => Ok(next_version),
Some(Token::LatestVersion) => current_version
.ok_or_else(|| anyhow!("Not previous tag found to replace {{latest}} version")),
_ => Err(anyhow!(
"Hook expression must start with \"version\" or \"latest\""
)),
}?;

while let Some(token) = self.tokens.pop_front() {
match token {
Token::Add => version = self.calculate_increment(version)?,
Expand Down Expand Up @@ -195,6 +209,16 @@ mod tests {
assert_eq!(expr.tokens, [Token::Version, Token::Add, Token::Minor])
}

#[test]
fn tokenize_latest_version() {
let entry = "echo {{latest}}";

let (range, mut expr) = HookExpr::scan_hook_entry(entry).unwrap();
expr.tokenize();
assert_eq!(range, 5..15);
assert_eq!(expr.tokens, [Token::LatestVersion])
}

#[test]
fn tokenize_exp_with_amount() {
let entry = "echo {{version+2major}}";
Expand Down Expand Up @@ -242,7 +266,7 @@ mod tests {
]),
};

let result = hookexpr.calculate_version(Version::new(1, 0, 0));
let result = hookexpr.calculate_version(None, Version::new(1, 0, 0));
assert_eq!(result.unwrap(), "1.0.33-rc");
}

Expand Down
4 changes: 3 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,8 +620,10 @@ impl CocoGitto {
.try_collect()?,
};

let current_version = self.repository.get_latest_tag().ok();

for mut hook in hooks {
hook.insert_version(next_version)?;
hook.insert_versions(current_version.clone(), next_version)?;
hook.run().context(hook.to_string())?;
}

Expand Down
16 changes: 8 additions & 8 deletions tests/cmd_help_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ use std::process::Command;
#[test]
#[cfg(not(tarpaulin))]
fn cog_display_help() -> Result<()> {
let mut command = Command::cargo_bin("cog")?;

command.arg("--help");
command.assert().success();
Command::cargo_bin("cog")?
.arg("--help")
.assert()
.success();

Ok(())
}

#[test]
#[cfg(not(tarpaulin))]
fn coco_display_help() -> Result<()> {
let mut command = Command::cargo_bin("coco")?;

command.arg("--help");
command.assert().success();
Command::cargo_bin("coco")?
.arg("--help")
.assert()
.success();

Ok(())
}
Loading

0 comments on commit 5eff372

Please sign in to comment.