From 231ebb63749a630462e4471062ca67a4caa0cdef Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Sun, 2 Oct 2022 13:12:56 +0300 Subject: [PATCH 01/37] Update git submodules before commit - closes #348 --- .../plugin/gitflow/AbstractGitFlowMojo.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java index 39dc022b..faaf7f45 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java @@ -43,6 +43,7 @@ import org.apache.maven.settings.Settings; import org.apache.maven.shared.release.policy.version.VersionPolicy; import org.codehaus.plexus.components.interactivity.Prompter; +import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.cli.CommandLineException; import org.codehaus.plexus.util.cli.CommandLineUtils; @@ -83,6 +84,9 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo { /** Command line for Maven executable. */ private final Commandline cmdMvn = new Commandline(); + /** Whether .gitmodules file exists in project. */ + private final boolean gitModulesExists; + /** Git flow configuration. */ @Parameter(defaultValue = "${gitFlowConfig}") protected GitFlowConfig gitFlowConfig; @@ -225,6 +229,15 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo { @Parameter(property = "gitPushOptions") private String gitPushOptions; + /** + * Explicitly enable or disable executing submodule update before commit. By + * default plugin tries to automatically determine if update of the Git + * submodules is needed. + * + */ + @Parameter(property = "updateGitSubmodules") + private Boolean updateGitSubmodules; + /** * The path to the Maven executable. Defaults to "mvn". */ @@ -253,6 +266,10 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo { @Component protected Map versionPolicies; + public AbstractGitFlowMojo() { + gitModulesExists = FileUtils.fileExists(".gitmodules"); + } + /** * Initializes command line executables. * @@ -807,6 +824,11 @@ protected void gitCommit(final String message) throws MojoFailureException, Comm */ protected void gitCommit(String message, Map messageProperties) throws MojoFailureException, CommandLineException { + if ((gitModulesExists && updateGitSubmodules == null) || Boolean.TRUE.equals(updateGitSubmodules)) { + getLog().info("Updating git submodules before commit."); + executeGitCommand("submodule", "update"); + } + if (StringUtils.isNotBlank(commitMessagePrefix)) { message = commitMessagePrefix + message; } From 0d9f73c7227cba8df0f41890f822dbfc093345b8 Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Thu, 13 Oct 2022 21:55:22 +0300 Subject: [PATCH 02/37] 1.19.0 release --- CHANGELOG.md | 9 +++++++++ README.md | 8 +++++++- pom.xml | 2 +- .../maven/plugin/gitflow/AbstractGitFlowMojo.java | 3 ++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1aaef90..ee058323 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## v1.19.0 (2022-10-13) + +* Fixed snapshot checking with up-to-date project info - [#345](https://github.com/aleksandr-m/gitflow-maven-plugin/issues/345) +* Improved remote branch fetching comparing and checking out +* Added ability to update git submodules before commit - [#348](https://github.com/aleksandr-m/gitflow-maven-plugin/issues/348) +* Added tag push on hotfix if it isn't pushed with the branch - [#349](https://github.com/aleksandr-m/gitflow-maven-plugin/issues/349) +* Added fetching of remote release branch on hotfix-finish goal - [#318](https://github.com/aleksandr-m/gitflow-maven-plugin/issues/318) +* Added more logs for verbose mode - [#331](https://github.com/aleksandr-m/gitflow-maven-plugin/issues/331) + ## v1.18.0 (2022-02-20) ### Breaking changes diff --git a/README.md b/README.md index c185fe8f..14591e43 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ The plugin is available from Maven Central. com.amashchenko.maven.plugin gitflow-maven-plugin - 1.18.0 + 1.19.0 @@ -81,6 +81,12 @@ mvn gitflow: -DargLine='-DprocessAllModules' ``` +# Git Submodules + +The plugin looks for the `.gitmodules` file and if it exists the `git submodule update` command will be executed before each Git commit. This is needed to avoid leaving working copy in dirty state which can happen when switching between branches. +To explicitly control whether Git submodules will be updated before commit the `updateGitSubmodules` parameter can be used. Setting it to `true` will enable Git submodules update and `false` will disable it even if `.gitmodules` file exists. The default value is not set, meaning the plugin tries to automatically determine if update is needed. + + # Eclipse Plugins build with Tycho Since version `1.1.0` this plugin supports Eclipse plugin projects which are build with [Tycho](https://eclipse.org/tycho/). diff --git a/pom.xml b/pom.xml index d584fc4b..87d1d19e 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ gitflow-maven-plugin maven-plugin gitflow-maven-plugin - 1.18.1-SNAPSHOT + 1.19.0 The Git-Flow Maven Plugin supports various Git workflows, including Vincent Driessen's successful Git branching model and GitHub Flow. This plugin runs Git and Maven commands from the command line. Supports Eclipse Plugins build with Tycho. diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java index faaf7f45..835aa49e 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java @@ -230,10 +230,11 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo { private String gitPushOptions; /** - * Explicitly enable or disable executing submodule update before commit. By + * Explicitly enable or disable executing Git submodule update before commit. By * default plugin tries to automatically determine if update of the Git * submodules is needed. * + * @since 1.19.0 */ @Parameter(property = "updateGitSubmodules") private Boolean updateGitSubmodules; From 20c25305a3725b315a90a56399f72dcb5cbf02a5 Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Thu, 13 Oct 2022 22:10:08 +0300 Subject: [PATCH 03/37] next development version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 87d1d19e..8d68274c 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ gitflow-maven-plugin maven-plugin gitflow-maven-plugin - 1.19.0 + 1.19.1-SNAPSHOT The Git-Flow Maven Plugin supports various Git workflows, including Vincent Driessen's successful Git branching model and GitHub Flow. This plugin runs Git and Maven commands from the command line. Supports Eclipse Plugins build with Tycho. From ff4a4b7342057bf76d2b5cc5390b6a95efd91e77 Mon Sep 17 00:00:00 2001 From: Dennis Roppelt Date: Thu, 3 Nov 2022 18:04:59 +0100 Subject: [PATCH 04/37] #364 drop or update alpha/beta depedencies, apearantly unused "maven-project" as it is superseeded by maven-core, which is present --- pom.xml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 8d68274c..ca29dca8 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,4 @@ - org.apache.maven.plugin-tools maven-plugin-annotations - 3.4 + 3.6.4 provided @@ -242,12 +242,6 @@ plexus-interactivity-api 1.1 compile - - - plexus-utils - org.codehaus.plexus - - org.apache.maven.release @@ -264,7 +258,7 @@ junit junit - 4.13.1 + 4.13.2 test From 26010851491e1d1c268aef60f8767fc6c8a7d014 Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Tue, 3 Jan 2023 22:07:18 +0200 Subject: [PATCH 06/37] Update copyright notice --- pom.xml | 2 +- .../amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java | 2 +- .../com/amashchenko/maven/plugin/gitflow/CommitMessages.java | 2 +- .../com/amashchenko/maven/plugin/gitflow/GitFlowConfig.java | 2 +- .../maven/plugin/gitflow/GitFlowFeatureFinishMojo.java | 2 +- .../maven/plugin/gitflow/GitFlowFeatureStartMojo.java | 2 +- .../maven/plugin/gitflow/GitFlowHotfixFinishMojo.java | 2 +- .../maven/plugin/gitflow/GitFlowHotfixStartMojo.java | 2 +- .../maven/plugin/gitflow/GitFlowReleaseFinishMojo.java | 2 +- .../amashchenko/maven/plugin/gitflow/GitFlowReleaseMojo.java | 2 +- .../maven/plugin/gitflow/GitFlowReleaseStartMojo.java | 2 +- .../maven/plugin/gitflow/GitFlowSupportStartMojo.java | 2 +- .../amashchenko/maven/plugin/gitflow/GitFlowVersionInfo.java | 2 +- .../maven/plugin/gitflow/GitFlowVersionUpdateMojo.java | 2 +- .../maven/plugin/gitflow/StringBufferStreamConsumer.java | 2 +- .../amashchenko/maven/plugin/gitflow/FeatureVersionTest.java | 2 +- .../maven/plugin/gitflow/GitFlowVersionInfoTest.java | 2 +- .../amashchenko/maven/plugin/gitflow/NextHotfixVersionTest.java | 2 +- .../maven/plugin/gitflow/NextSnapshotVersionTest.java | 2 +- .../maven/plugin/gitflow/ValidateConfigurationTest.java | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index d24e6539..621391cf 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ + 3.5.1 org.apache.maven.plugin-tools maven-plugin-annotations - 3.6.4 + 3.8.2 provided - - org.codehaus.plexus - plexus-interactivity-api - 1.1 - compile - org.apache.maven.release maven-release-manager - 2.5.3 + 3.0.0 compile org.apache.maven.release maven-release-oddeven-policy - 2.5.3 + 3.0.0 test From d59ec67e4b7e217761ae9229abf3d7cc45e60621 Mon Sep 17 00:00:00 2001 From: Dennis Roppelt Date: Wed, 3 May 2023 18:46:02 +0200 Subject: [PATCH 14/37] make troubleshooting easier --- .github/workflows/verify.yml | 2 +- .../amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index fab86d0c..d899d129 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -34,5 +34,5 @@ jobs: - uses: actions/upload-artifact@v3 if: failure() with: - name: it-build-logs + name: ${{ runner.os }}-it-build-logs path: target/it/*/*.log diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java index 7a4b4e20..ea059f1e 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java @@ -1344,7 +1344,7 @@ private CommandResult executeCommand(final Commandline cmd, final boolean failOn // not all commands print errors to error stream errorStr += LS + outStr; - throw new MojoFailureException(errorStr); + throw new MojoFailureException("Failed cmd ["+cmd.getExecutable()+"] with args [" + Arrays.toString(cmd.getArguments()) + "], bad exit code [" + exitCode +"]. Out: [" + errorStr+ "]"); } if (verbose && StringUtils.isNotBlank(errorStr)) { From 16b28309565166cf2d9300ad6420f3b796eba730 Mon Sep 17 00:00:00 2001 From: Dennis Roppelt Date: Wed, 3 May 2023 18:46:22 +0200 Subject: [PATCH 15/37] pull up pinned plugin versions that were pinned down for issue 330 for java7 compatibility --- .../maven/plugin/gitflow/AbstractGitFlowMojo.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java index ea059f1e..e704ba76 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java @@ -206,16 +206,16 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo { * * @since 1.18.0 */ - @Parameter(property = "versionsMavenPluginVersion", defaultValue = "2.8.1") - private String versionsMavenPluginVersion = "2.8.1"; + @Parameter(property = "versionsMavenPluginVersion", defaultValue = "2.14.2") + private String versionsMavenPluginVersion = "2.24.2"; /** * Version of tycho-versions-plugin to use. * * @since 1.18.0 */ - @Parameter(property = "tychoVersionsPluginVersion", defaultValue = "0.24.0") - private String tychoVersionsPluginVersion = "0.24.0"; + @Parameter(property = "tychoVersionsPluginVersion", defaultValue = "1.7.0") + private String tychoVersionsPluginVersion = "1.7.0"; /** * Options to pass to Git push command using --push-option. From c250f5aa9a9b54c0df1e35fe974cfa6d3aa1914a Mon Sep 17 00:00:00 2001 From: Dennis Roppelt Date: Wed, 3 May 2023 18:48:56 +0200 Subject: [PATCH 16/37] plexus-utils 1.X -> 3.X changes \"\" would become litellarlly \"\" in Ubuntu, but an empty value on windows my guess: encoding of ', ", \" changed across OSes in newer plexus-utils versions --- .../maven/plugin/gitflow/AbstractGitFlowMojo.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java index e704ba76..fe679f2e 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java @@ -44,6 +44,7 @@ import org.apache.maven.shared.release.policy.version.VersionPolicy; import org.codehaus.plexus.components.interactivity.Prompter; import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.Os; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.cli.CommandLineException; import org.codehaus.plexus.util.cli.CommandLineUtils; @@ -546,7 +547,12 @@ protected void initGitFlowConfig() throws MojoFailureException, CommandLineExcep */ private void gitSetConfig(final String name, String value) throws MojoFailureException, CommandLineException { if (value == null || value.isEmpty()) { - value = "\"\""; + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + value = "\"\""; + } + else { + value = ""; + } } // ignore error exit codes @@ -636,7 +642,7 @@ protected String gitFindTags() throws MojoFailureException, CommandLineException * If command line execution fails. */ protected String gitFindLastTag() throws MojoFailureException, CommandLineException { - String tag = executeGitCommandReturn("for-each-ref", "--sort=\"-version:refname\"", "--sort=-taggerdate", + String tag = executeGitCommandReturn("for-each-ref", "--sort=-version:refname", "--sort=-taggerdate", "--count=1", "--format=\"%(refname:short)\"", "refs/tags/"); // https://github.com/aleksandr-m/gitflow-maven-plugin/issues/3 tag = removeQuotes(tag); From cde892ecfcf795982126e9a129c2db7b1fb490a1 Mon Sep 17 00:00:00 2001 From: Dennis Roppelt Date: Wed, 3 May 2023 18:49:48 +0200 Subject: [PATCH 17/37] plexus-utils 3.X does not like adding empty args and will throw "... Unknown lifecycle phase "". You must specify a valid lifecycle phase or a goal ...", was fine in plexus-utils 1.X or for git, Failed cmd ['git'] with args [[merge, --no-ff, , release/0.0.3, , ]], bad exit code [1]. Out: [merge: - not something we can merge my guess: handling of empty args changes between plexus-utils major versions --- .../plugin/gitflow/AbstractGitFlowMojo.java | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java index fe679f2e..317199ad 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java @@ -18,6 +18,7 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashSet; @@ -25,6 +26,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; +import java.util.Objects; import java.util.Set; import java.util.TimeZone; import java.util.regex.Pattern; @@ -854,12 +856,12 @@ protected void gitCommit(String message, Map messageProperties) protected void gitMerge(final String branchName, boolean rebase, boolean noff, boolean ffonly, String message, Map messageProperties) throws MojoFailureException, CommandLineException { - String sign = ""; + String sign = null; if (gpgSignCommit) { sign = "-S"; } - String msgParam = ""; - String msg = ""; + String msgParam = null; + String msg = null; if (StringUtils.isNotBlank(message)) { if (StringUtils.isNotBlank(commitMessagePrefix)) { message = commitMessagePrefix + message; @@ -1129,15 +1131,9 @@ protected void mvnSetVersions(final String version) throws MojoFailureException, getLog().info("Updating version(s) to '" + version + "'."); String newVersion = "-DnewVersion=" + version; - String grp = ""; - String art = ""; - if (versionsForceUpdate) { - grp = "-DgroupId="; - art = "-DartifactId="; - } if (tychoBuild) { - String prop = ""; + String prop = null; if (StringUtils.isNotBlank(versionProperty)) { prop = "-Dproperties=" + versionProperty; getLog().info("Updating property '" + versionProperty + "' to '" + version + "'."); @@ -1153,8 +1149,10 @@ protected void mvnSetVersions(final String version) throws MojoFailureException, if (!skipUpdateVersion) { runCommand = true; args.add(VERSIONS_MAVEN_PLUGIN + ":" + versionsMavenPluginVersion + ":" + VERSIONS_MAVEN_PLUGIN_SET_GOAL); - args.add(grp); - args.add(art); + if (versionsForceUpdate) { + args.add("-DgroupId="); + args.add("-DartifactId="); + } } if (StringUtils.isNotBlank(versionProperty)) { @@ -1330,7 +1328,8 @@ private CommandResult executeCommand(final Commandline cmd, final boolean failOn } cmd.clearArgs(); - cmd.addArguments(args); + String[] nonNullArgs = Arrays.stream(args).filter(Objects::nonNull).toArray(String[]::new); + cmd.addArguments(nonNullArgs); if (StringUtils.isNotBlank(argStr)) { cmd.createArg().setLine(argStr); From 022b9debd5a9ddd0bb102e9b029b433cacbf2be0 Mon Sep 17 00:00:00 2001 From: Dennis Roppelt Date: Wed, 3 May 2023 21:58:50 +0200 Subject: [PATCH 18/37] modernize junit 4 to 5 --- pom.xml | 6 +- .../plugin/gitflow/FeatureVersionTest.java | 29 +++----- .../gitflow/GitFlowVersionInfoTest.java | 74 ++++++++++--------- .../plugin/gitflow/NextHotfixVersionTest.java | 28 +++---- .../gitflow/NextSnapshotVersionTest.java | 31 +++----- .../gitflow/ValidateConfigurationTest.java | 28 +++---- 6 files changed, 77 insertions(+), 119 deletions(-) diff --git a/pom.xml b/pom.xml index b4576d28..4eff8789 100644 --- a/pom.xml +++ b/pom.xml @@ -251,9 +251,9 @@ test - junit - junit - 4.13.2 + org.junit.jupiter + junit-jupiter + 5.9.3 test diff --git a/src/test/java/com/amashchenko/maven/plugin/gitflow/FeatureVersionTest.java b/src/test/java/com/amashchenko/maven/plugin/gitflow/FeatureVersionTest.java index bf7044db..30ef7de7 100644 --- a/src/test/java/com/amashchenko/maven/plugin/gitflow/FeatureVersionTest.java +++ b/src/test/java/com/amashchenko/maven/plugin/gitflow/FeatureVersionTest.java @@ -18,26 +18,13 @@ import java.util.Arrays; import java.util.Collection; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; -@RunWith(Parameterized.class) -public class FeatureVersionTest { - private final String version; - private final String featureName; - private final String expectedVersion; +import static org.junit.jupiter.api.Assertions.assertEquals; - public FeatureVersionTest(final String version, final String featureName, - final String expectedVersion) { - this.version = version; - this.featureName = featureName; - this.expectedVersion = expectedVersion; - } +public class FeatureVersionTest { - @Parameters public static Collection data() { return Arrays.asList(new Object[][] { { "0.9-SNAPSHOT", "feature", "0.9-feature-SNAPSHOT" }, @@ -48,9 +35,11 @@ public static Collection data() { { "0.9-RC3", null, "0.9-RC3" } }); } - @Test - public void testFeatureVersion() throws Exception { - Assert.assertEquals(expectedVersion, + @ParameterizedTest + @MethodSource("data") + public void testFeatureVersion(final String version, final String featureName, + final String expectedVersion) throws Exception { + assertEquals(expectedVersion, new GitFlowVersionInfo(version, null).featureVersion(featureName)); } } diff --git a/src/test/java/com/amashchenko/maven/plugin/gitflow/GitFlowVersionInfoTest.java b/src/test/java/com/amashchenko/maven/plugin/gitflow/GitFlowVersionInfoTest.java index 293d95f6..596489ec 100644 --- a/src/test/java/com/amashchenko/maven/plugin/gitflow/GitFlowVersionInfoTest.java +++ b/src/test/java/com/amashchenko/maven/plugin/gitflow/GitFlowVersionInfoTest.java @@ -17,105 +17,107 @@ import org.apache.maven.shared.release.policy.oddeven.OddEvenVersionPolicy; import org.apache.maven.shared.release.versions.VersionParseException; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; public class GitFlowVersionInfoTest { @Test public void testCreating() throws Exception { final String version = "0.9"; GitFlowVersionInfo info = new GitFlowVersionInfo(version, null); - Assert.assertNotNull(info); - Assert.assertEquals(version, info.toString()); + Assertions.assertNotNull(info); + Assertions.assertEquals(version, info.toString()); } - @Test(expected = VersionParseException.class) + @Test public void testVersionParseException() throws Exception { - new GitFlowVersionInfo("", null); + Assertions.assertThrows(VersionParseException.class, ()-> new GitFlowVersionInfo("", null)); } @Test public void testIsValidVersion() throws Exception { - Assert.assertTrue(GitFlowVersionInfo.isValidVersion("0.9")); - Assert.assertTrue(GitFlowVersionInfo.isValidVersion("some-SNAPSHOT")); - Assert.assertTrue(GitFlowVersionInfo + Assertions.assertTrue(GitFlowVersionInfo.isValidVersion("0.9")); + Assertions.assertTrue(GitFlowVersionInfo.isValidVersion("some-SNAPSHOT")); + Assertions.assertTrue(GitFlowVersionInfo .isValidVersion("0.9-RC3-feature-SNAPSHOT")); - Assert.assertFalse(GitFlowVersionInfo.isValidVersion("some.0.9")); - Assert.assertFalse(GitFlowVersionInfo.isValidVersion(null)); - Assert.assertFalse(GitFlowVersionInfo.isValidVersion("")); - Assert.assertFalse(GitFlowVersionInfo.isValidVersion(" ")); - Assert.assertFalse(GitFlowVersionInfo.isValidVersion("-1")); + Assertions.assertFalse(GitFlowVersionInfo.isValidVersion("some.0.9")); + Assertions.assertFalse(GitFlowVersionInfo.isValidVersion(null)); + Assertions.assertFalse(GitFlowVersionInfo.isValidVersion("")); + Assertions.assertFalse(GitFlowVersionInfo.isValidVersion(" ")); + Assertions.assertFalse(GitFlowVersionInfo.isValidVersion("-1")); } @Test public void testHotfixVersion() throws Exception { GitFlowVersionInfo info = new GitFlowVersionInfo("0.9", null); - Assert.assertNotNull(info); - Assert.assertEquals("0.10", info.hotfixVersion(false, null)); + Assertions.assertNotNull(info); + Assertions.assertEquals("0.10", info.hotfixVersion(false, null)); } @Test public void testHotfixVersion2() throws Exception { GitFlowVersionInfo info = new GitFlowVersionInfo("0.9-SNAPSHOT", null); - Assert.assertNotNull(info); - Assert.assertEquals("0.10", info.hotfixVersion(false, null)); + Assertions.assertNotNull(info); + Assertions.assertEquals("0.10", info.hotfixVersion(false, null)); } @Test public void testHotfixVersion3() throws Exception { GitFlowVersionInfo info = new GitFlowVersionInfo("0.9", null); - Assert.assertNotNull(info); - Assert.assertEquals("0.10", info.hotfixVersion(true, null)); + Assertions.assertNotNull(info); + Assertions.assertEquals("0.10", info.hotfixVersion(true, null)); } @Test public void testHotfixVersion4() throws Exception { GitFlowVersionInfo info = new GitFlowVersionInfo("0.9-SNAPSHOT", null); - Assert.assertNotNull(info); - Assert.assertEquals("0.10-SNAPSHOT", info.hotfixVersion(true, null)); + Assertions.assertNotNull(info); + Assertions.assertEquals("0.10-SNAPSHOT", info.hotfixVersion(true, null)); } @Test public void testDigitsVersionInfo() throws Exception { GitFlowVersionInfo info = new GitFlowVersionInfo("0.9", null); - Assert.assertNotNull(info); + Assertions.assertNotNull(info); info = info.digitsVersionInfo(); - Assert.assertNotNull(info); - Assert.assertEquals(new GitFlowVersionInfo("0.9", null), info); + Assertions.assertNotNull(info); + Assertions.assertEquals(new GitFlowVersionInfo("0.9", null), info); } @Test public void testDigitsVersionInfo2() throws Exception { GitFlowVersionInfo info = new GitFlowVersionInfo( "0.9-RC3-feature-SNAPSHOT", null); - Assert.assertNotNull(info); + Assertions.assertNotNull(info); info = info.digitsVersionInfo(); - Assert.assertNotNull(info); - Assert.assertEquals(new GitFlowVersionInfo("0.9", null), info); + Assertions.assertNotNull(info); + Assertions.assertEquals(new GitFlowVersionInfo("0.9", null), info); } @Test public void testWithoutVersionPolicy() throws Exception { GitFlowVersionInfo info1 = new GitFlowVersionInfo("1.0.0-SNAPSHOT", null); - Assert.assertEquals("1.0.0", info1.getReleaseVersionString()); - Assert.assertEquals("1.0.1-SNAPSHOT", info1.nextSnapshotVersion()); + Assertions.assertEquals("1.0.0", info1.getReleaseVersionString()); + Assertions.assertEquals("1.0.1-SNAPSHOT", info1.nextSnapshotVersion()); GitFlowVersionInfo info2 = new GitFlowVersionInfo("1.0.1-SNAPSHOT", null); - Assert.assertEquals("1.0.1", info2.getReleaseVersionString()); - Assert.assertEquals("1.0.2-SNAPSHOT", info2.nextSnapshotVersion()); + Assertions.assertEquals("1.0.1", info2.getReleaseVersionString()); + Assertions.assertEquals("1.0.2-SNAPSHOT", info2.nextSnapshotVersion()); } @Test public void testWithVersionPolicy() throws Exception { GitFlowVersionInfo info1 = new GitFlowVersionInfo("1.0.0-SNAPSHOT", new OddEvenVersionPolicy()); - Assert.assertEquals("1.0.0", info1.getReleaseVersionString()); - Assert.assertEquals("1.0.1-SNAPSHOT", info1.nextSnapshotVersion()); + Assertions.assertEquals("1.0.0", info1.getReleaseVersionString()); + Assertions.assertEquals("1.0.1-SNAPSHOT", info1.nextSnapshotVersion()); GitFlowVersionInfo info2 = new GitFlowVersionInfo("1.0.1-SNAPSHOT", new OddEvenVersionPolicy()); - Assert.assertEquals("1.0.2", info2.getReleaseVersionString()); - Assert.assertEquals("1.0.3-SNAPSHOT", info2.nextSnapshotVersion()); + Assertions.assertEquals("1.0.2", info2.getReleaseVersionString()); + Assertions.assertEquals("1.0.3-SNAPSHOT", info2.nextSnapshotVersion()); } } diff --git a/src/test/java/com/amashchenko/maven/plugin/gitflow/NextHotfixVersionTest.java b/src/test/java/com/amashchenko/maven/plugin/gitflow/NextHotfixVersionTest.java index 3d9e20ad..afb16d18 100644 --- a/src/test/java/com/amashchenko/maven/plugin/gitflow/NextHotfixVersionTest.java +++ b/src/test/java/com/amashchenko/maven/plugin/gitflow/NextHotfixVersionTest.java @@ -18,25 +18,14 @@ import java.util.Arrays; import java.util.Collection; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; -@RunWith(Parameterized.class) -public class NextHotfixVersionTest { - private final String version; - private final Integer index; - private final String expectedVersion; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; - public NextHotfixVersionTest(final String version, final Integer index, final String expectedVersion) { - this.version = version; - this.index = index; - this.expectedVersion = expectedVersion; - } - @Parameters(name = "{0}-({1})->{2}") +public class NextHotfixVersionTest { + public static Collection data() { return Arrays .asList(new Object[][] { @@ -61,8 +50,9 @@ public static Collection data() { { "2.3.4", 1, "2.4.0" } }); } - @Test - public void testNextSnapshotVersion() throws Exception { - Assert.assertEquals(expectedVersion, new GitFlowVersionInfo(version, null).hotfixVersion(false, index)); + @ParameterizedTest + @MethodSource("data") + public void testNextSnapshotVersion(final String version, final Integer index, final String expectedVersion) throws Exception { + Assertions.assertEquals(expectedVersion, new GitFlowVersionInfo(version, null).hotfixVersion(false, index)); } } diff --git a/src/test/java/com/amashchenko/maven/plugin/gitflow/NextSnapshotVersionTest.java b/src/test/java/com/amashchenko/maven/plugin/gitflow/NextSnapshotVersionTest.java index e783b20d..8b7aeb3b 100644 --- a/src/test/java/com/amashchenko/maven/plugin/gitflow/NextSnapshotVersionTest.java +++ b/src/test/java/com/amashchenko/maven/plugin/gitflow/NextSnapshotVersionTest.java @@ -15,29 +15,14 @@ */ package com.amashchenko.maven.plugin.gitflow; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + import java.util.Arrays; import java.util.Collection; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -@RunWith(Parameterized.class) public class NextSnapshotVersionTest { - private final String version; - private final Integer index; - private final String expectedVersion; - - public NextSnapshotVersionTest(final String version, final Integer index, - final String expectedVersion) { - this.version = version; - this.index = index; - this.expectedVersion = expectedVersion; - } - - @Parameters public static Collection data() { return Arrays .asList(new Object[][] { @@ -64,9 +49,11 @@ public static Collection data() { { "2.3.4", 1, "2.4.0-SNAPSHOT" } }); } - @Test - public void testNextSnapshotVersion() throws Exception { - Assert.assertEquals(expectedVersion, + @ParameterizedTest + @MethodSource("data") + public void testNextSnapshotVersion(final String version, final Integer index, + final String expectedVersion) throws Exception { + Assertions.assertEquals(expectedVersion, new GitFlowVersionInfo(version, null).nextSnapshotVersion(index)); } } diff --git a/src/test/java/com/amashchenko/maven/plugin/gitflow/ValidateConfigurationTest.java b/src/test/java/com/amashchenko/maven/plugin/gitflow/ValidateConfigurationTest.java index d60c4079..48922e03 100644 --- a/src/test/java/com/amashchenko/maven/plugin/gitflow/ValidateConfigurationTest.java +++ b/src/test/java/com/amashchenko/maven/plugin/gitflow/ValidateConfigurationTest.java @@ -15,27 +15,16 @@ */ package com.amashchenko.maven.plugin.gitflow; +import org.apache.maven.plugin.MojoFailureException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + import java.util.Arrays; import java.util.Collection; -import org.apache.maven.plugin.MojoFailureException; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -@RunWith(Parameterized.class) public class ValidateConfigurationTest { - private final String argLine; - private final boolean expected; - - public ValidateConfigurationTest(String argLine, boolean expected) { - this.argLine = argLine; - this.expected = expected; - } - @Parameters(name = "{0}->{1}") public static Collection data() { return Arrays.asList(new Object[][] { { "-X -e", true }, { "-DsomeArg1=true", true }, { null, true }, @@ -46,8 +35,9 @@ public static Collection data() { { "-DsomeArg ; clean", false } }); } - @Test - public void testValidateConfiguration() throws Exception { + @ParameterizedTest + @MethodSource("data") + public void testValidateConfiguration(String argLine, boolean expected) throws Exception { GitFlowReleaseStartMojo mojo = new GitFlowReleaseStartMojo(); mojo.setArgLine(argLine); @@ -55,7 +45,7 @@ public void testValidateConfiguration() throws Exception { mojo.validateConfiguration(); } catch (MojoFailureException e) { if (expected) { - Assert.fail(); + Assertions.fail(); } } } From fa72893c96ac6cfe6942bf1677a856e17494fc58 Mon Sep 17 00:00:00 2001 From: Dennis Roppelt Date: Tue, 16 May 2023 20:05:44 +0200 Subject: [PATCH 19/37] latest maven-versions plugin --- .../amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java index 317199ad..8e10eb6c 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java @@ -209,8 +209,8 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo { * * @since 1.18.0 */ - @Parameter(property = "versionsMavenPluginVersion", defaultValue = "2.14.2") - private String versionsMavenPluginVersion = "2.24.2"; + @Parameter(property = "versionsMavenPluginVersion", defaultValue = "2.15.0") + private String versionsMavenPluginVersion = "2.25.0"; /** * Version of tycho-versions-plugin to use. From 09346f65e810e236c40c648d993f03632b89e4ad Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Tue, 30 May 2023 10:41:50 +0300 Subject: [PATCH 20/37] Fix creating release branch in hotfix-finish goal - closes #391 --- .../maven/plugin/gitflow/GitFlowHotfixFinishMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowHotfixFinishMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowHotfixFinishMojo.java index f4a0f2f0..8b76de46 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowHotfixFinishMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowHotfixFinishMojo.java @@ -204,7 +204,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { throw new MojoFailureException("More than one remote release branch exists. Cannot finish hotfix."); } - gitCreateBranch(remoteRelease, remoteReleases); + gitFetchRemoteAndCompareCreate(remoteRelease); } } } From 401c69238538fcdbe6c9b4239118b7318b773437 Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Tue, 30 May 2023 11:24:53 +0300 Subject: [PATCH 21/37] Add option to skip merging into development branch in release-finish goal - closes #237 --- .../expected-development-pom.xml | 7 ++ .../expected-production-pom.xml | 7 ++ src/it/release-finish-8-it/gitignorefile | 6 ++ src/it/release-finish-8-it/init.bsh | 41 ++++++++++++ src/it/release-finish-8-it/invoker.properties | 3 + src/it/release-finish-8-it/pom.xml | 7 ++ src/it/release-finish-8-it/verify.bsh | 64 +++++++++++++++++++ .../gitflow/GitFlowReleaseFinishMojo.java | 11 +++- 8 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 src/it/release-finish-8-it/expected-development-pom.xml create mode 100644 src/it/release-finish-8-it/expected-production-pom.xml create mode 100644 src/it/release-finish-8-it/gitignorefile create mode 100644 src/it/release-finish-8-it/init.bsh create mode 100644 src/it/release-finish-8-it/invoker.properties create mode 100644 src/it/release-finish-8-it/pom.xml create mode 100644 src/it/release-finish-8-it/verify.bsh diff --git a/src/it/release-finish-8-it/expected-development-pom.xml b/src/it/release-finish-8-it/expected-development-pom.xml new file mode 100644 index 00000000..9bc33281 --- /dev/null +++ b/src/it/release-finish-8-it/expected-development-pom.xml @@ -0,0 +1,7 @@ + + 4.0.0 + com.amashchenko.maven.plugin + gitflow-maven-test + pom + 0.0.1 + diff --git a/src/it/release-finish-8-it/expected-production-pom.xml b/src/it/release-finish-8-it/expected-production-pom.xml new file mode 100644 index 00000000..b8bb10f1 --- /dev/null +++ b/src/it/release-finish-8-it/expected-production-pom.xml @@ -0,0 +1,7 @@ + + 4.0.0 + com.amashchenko.maven.plugin + gitflow-maven-test + pom + 0.0.3 + diff --git a/src/it/release-finish-8-it/gitignorefile b/src/it/release-finish-8-it/gitignorefile new file mode 100644 index 00000000..3f0b6969 --- /dev/null +++ b/src/it/release-finish-8-it/gitignorefile @@ -0,0 +1,6 @@ +build.log +expected-development-pom.xml +expected-production-pom.xml +invoker.properties +init.bsh +verify.bsh diff --git a/src/it/release-finish-8-it/init.bsh b/src/it/release-finish-8-it/init.bsh new file mode 100644 index 00000000..d8d5f0ee --- /dev/null +++ b/src/it/release-finish-8-it/init.bsh @@ -0,0 +1,41 @@ +import org.codehaus.plexus.util.FileUtils; + +try { + new File(basedir, "gitignorefile").renameTo(new File(basedir, ".gitignore")); + + Process p = Runtime.getRuntime().exec("git --git-dir=" + basedir + "/.git --work-tree=" + basedir + " init"); + p.waitFor(); + + Process p = Runtime.getRuntime().exec("git --git-dir=" + basedir + "/.git --work-tree=" + basedir + " config user.email 'a@a.aa'"); + p.waitFor(); + Process p = Runtime.getRuntime().exec("git --git-dir=" + basedir + "/.git --work-tree=" + basedir + " config user.name 'a'"); + p.waitFor(); + + p = Runtime.getRuntime().exec("git --git-dir=" + basedir + "/.git --work-tree=" + basedir + " add ."); + p.waitFor(); + + p = Runtime.getRuntime().exec("git --git-dir=" + basedir + "/.git --work-tree=" + basedir + " commit -m init"); + p.waitFor(); + + p = Runtime.getRuntime().exec("git --git-dir=" + basedir + "/.git --work-tree=" + basedir + " branch develop"); + p.waitFor(); + + p = Runtime.getRuntime().exec("git --git-dir=" + basedir + "/.git --work-tree=" + basedir + " checkout -b release/0.0.3"); + p.waitFor(); + + File pomfile = new File(basedir, "pom.xml"); + String pomfilestr = FileUtils.fileRead(pomfile, "UTF-8"); + pomfilestr = pomfilestr.replaceAll("0.0.1", "0.0.3"); + FileUtils.fileWrite(basedir + "/pom.xml", "UTF-8", pomfilestr); + + p = Runtime.getRuntime().exec("git --git-dir=" + basedir + "/.git --work-tree=" + basedir + " add ."); + p.waitFor(); + + p = Runtime.getRuntime().exec("git --git-dir=" + basedir + "/.git --work-tree=" + basedir + " commit -m 0.0.3"); + p.waitFor(); + +} catch (Exception e) { + e.printStackTrace(); + return false; +} +return true; diff --git a/src/it/release-finish-8-it/invoker.properties b/src/it/release-finish-8-it/invoker.properties new file mode 100644 index 00000000..461743d8 --- /dev/null +++ b/src/it/release-finish-8-it/invoker.properties @@ -0,0 +1,3 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:release-finish -DpushRemote=false -DskipReleaseMergeDevBranch + +invoker.description=Test release-finish with skipReleaseMergeDevBranch parameter. diff --git a/src/it/release-finish-8-it/pom.xml b/src/it/release-finish-8-it/pom.xml new file mode 100644 index 00000000..9bc33281 --- /dev/null +++ b/src/it/release-finish-8-it/pom.xml @@ -0,0 +1,7 @@ + + 4.0.0 + com.amashchenko.maven.plugin + gitflow-maven-test + pom + 0.0.1 + diff --git a/src/it/release-finish-8-it/verify.bsh b/src/it/release-finish-8-it/verify.bsh new file mode 100644 index 00000000..95707e18 --- /dev/null +++ b/src/it/release-finish-8-it/verify.bsh @@ -0,0 +1,64 @@ +import org.codehaus.plexus.util.FileUtils; + +try { + File gitTag = new File(basedir, ".git/refs/tags/0.0.3"); + if (!gitTag.exists()) { + System.out.println("release-finish .git/refs/tags/0.0.3 doesn't exist"); + return false; + } + + File gitReleaseRef = new File(basedir, ".git/refs/heads/release/0.0.3"); + if (gitReleaseRef.exists()) { + System.out.println("release-finish .git/refs/heads/release/0.0.3 exists"); + return false; + } + File gitDevelopRef = new File(basedir, ".git/refs/heads/develop"); + if (!gitDevelopRef.exists()) { + System.out.println("release-finish .git/refs/heads/develop doesn't exist"); + return false; + } + File gitMasterRef = new File(basedir, ".git/refs/heads/master"); + if (!gitMasterRef.exists()) { + System.out.println("release-finish .git/refs/heads/master doesn't exist"); + return false; + } + + p = Runtime.getRuntime().exec("git --git-dir=" + basedir + "/.git --work-tree=" + basedir + " checkout develop"); + p.waitFor(); + + File file = new File(basedir, "pom.xml"); + File expectedFile = new File(basedir, "expected-development-pom.xml"); + + String actual = FileUtils.fileRead(file, "UTF-8"); + String expected = FileUtils.fileRead(expectedFile, "UTF-8"); + + actual = actual.replaceAll("\\r?\\n", ""); + expected = expected.replaceAll("\\r?\\n", ""); + + if (!expected.equals(actual)) { + System.out.println("release-finish development pom expected: " + expected + " actual was:" + actual); + return false; + } + + p = Runtime.getRuntime().exec("git --git-dir=" + basedir + "/.git --work-tree=" + basedir + " checkout master"); + p.waitFor(); + + file = new File(basedir, "pom.xml"); + expectedFile = new File(basedir, "expected-production-pom.xml"); + + actual = FileUtils.fileRead(file, "UTF-8"); + expected = FileUtils.fileRead(expectedFile, "UTF-8"); + + actual = actual.replaceAll("\\r?\\n", ""); + expected = expected.replaceAll("\\r?\\n", ""); + + if (!expected.equals(actual)) { + System.out.println("release-finish production pom expected: " + expected + " actual was:" + actual); + return false; + } + +} catch (Exception e) { + e.printStackTrace(); + return false; +} +return true; diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseFinishMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseFinishMojo.java index 7b16fbeb..688d28f8 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseFinishMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseFinishMojo.java @@ -179,6 +179,13 @@ public class GitFlowReleaseFinishMojo extends AbstractGitFlowMojo { @Parameter(property = "noBackMerge", defaultValue = "false") private boolean noBackMerge = false; + /** + * Whether to skip merging release into the development branch. + * + */ + @Parameter(property = "skipReleaseMergeDevBranch", defaultValue = "false") + private boolean skipReleaseMergeDevBranch = false; + /** {@inheritDoc} */ @Override public void execute() throws MojoExecutionException, MojoFailureException { @@ -284,7 +291,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { mvnRun(postReleaseGoals); } - if (notSameProdDevName()) { + if (notSameProdDevName() && !skipReleaseMergeDevBranch) { // git checkout develop gitCheckout(gitFlowConfig.getDevelopmentBranch()); @@ -325,7 +332,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { commitDevelopmentVersionAtStart = false; } - if (!commitDevelopmentVersionAtStart) { + if (!commitDevelopmentVersionAtStart && !skipReleaseMergeDevBranch) { // get next snapshot version final String nextSnapshotVersion; if (!settings.isInteractiveMode() && StringUtils.isNotBlank(developmentVersion)) { From d0487e2dbbc12c2a55711f5e5a37c472b93eb194 Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Tue, 30 May 2023 11:25:49 +0300 Subject: [PATCH 22/37] Better verify script in release finish test --- src/it/release-finish-it/verify.bsh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/it/release-finish-it/verify.bsh b/src/it/release-finish-it/verify.bsh index 58f1c6fd..95707e18 100644 --- a/src/it/release-finish-it/verify.bsh +++ b/src/it/release-finish-it/verify.bsh @@ -23,6 +23,9 @@ try { return false; } + p = Runtime.getRuntime().exec("git --git-dir=" + basedir + "/.git --work-tree=" + basedir + " checkout develop"); + p.waitFor(); + File file = new File(basedir, "pom.xml"); File expectedFile = new File(basedir, "expected-development-pom.xml"); @@ -33,7 +36,7 @@ try { expected = expected.replaceAll("\\r?\\n", ""); if (!expected.equals(actual)) { - System.out.println("release-finish expected: " + expected + " actual was:" + actual); + System.out.println("release-finish development pom expected: " + expected + " actual was:" + actual); return false; } @@ -50,7 +53,7 @@ try { expected = expected.replaceAll("\\r?\\n", ""); if (!expected.equals(actual)) { - System.out.println("release-finish expected: " + expected + " actual was:" + actual); + System.out.println("release-finish production pom expected: " + expected + " actual was:" + actual); return false; } From 60d1f0d10b89513b21448f8e86aa1f4f045cf4f6 Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Thu, 1 Jun 2023 13:12:11 +0300 Subject: [PATCH 23/37] 1.20.0 release --- CHANGELOG.md | 8 ++++++++ README.md | 10 +++++++--- pom.xml | 2 +- .../maven/plugin/gitflow/GitFlowReleaseFinishMojo.java | 1 + .../maven/plugin/gitflow/GitFlowReleaseMojo.java | 1 + 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee058323..4810606a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## v1.20.0 (2023-06-01) + +* Fixed creation of the release branch in `hotfix-finish` goal - [#391](https://github.com/aleksandr-m/gitflow-maven-plugin/issues/391) +* Improved console error logs - [#383](https://github.com/aleksandr-m/gitflow-maven-plugin/issues/383) +* Added option to skip merging into development branch in `release-finish` goal - [#237](https://github.com/aleksandr-m/gitflow-maven-plugin/issues/237) +* Added back merge to `release` goal - [#375](https://github.com/aleksandr-m/gitflow-maven-plugin/pull/375) +* Updated dependencies - [#365](https://github.com/aleksandr-m/gitflow-maven-plugin/pull/365) + ## v1.19.0 (2022-10-13) * Fixed snapshot checking with up-to-date project info - [#345](https://github.com/aleksandr-m/gitflow-maven-plugin/issues/345) diff --git a/README.md b/README.md index a53cd24a..e910d957 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ The plugin is available from Maven Central. com.amashchenko.maven.plugin gitflow-maven-plugin - 1.19.0 + 1.20.0 @@ -289,7 +289,9 @@ The `gitflow:release-start` goal has `fromCommit` parameter which allows to star The `gitflow:release-start` and `gitflow:release-finish` goals have `useSnapshotInRelease` parameter which allows to start the release with SNAPSHOT version and finish it without this value in project version. By default the value is `false`. For example, if the release version is `1.0.2` and `useSnapshotInRelease` is set to `true` and using `gitflow:release-start` goal then the release version will be `1.0.2-SNAPSHOT` and when finishing the release with `gitflow:release-finish` goal, the release version will be `1.0.2` -The `gitflow:release` and `gitflow:release-start` goals have `skipReleaseMergeProdBranch` parameter which prevents merging the release branch into the production branch. The default value is `false`. +The `gitflow:release` and `gitflow:release-finish` goals have `skipReleaseMergeProdBranch` parameter which prevents merging the release branch into the production branch. The default value is `false`. + +The `gitflow:release-finish` goal has `skipReleaseMergeDevBranch` parameter which prevents merging the release branch into the development branch. The default value is `false`. The `gitflow:hotfix-start` and `gitflow:hotfix-finish` goals have `useSnapshotInHotfix` parameter which allows to start the hotfix with SNAPSHOT version and finish it without this value in the version. By default the value is `false`. For example, if the hotfix version is `1.0.2.1` and `useSnapshotInHotfix` is set to `true` and using `gitflow:hotfix-start` goal then the hotfix version will be `1.0.2.1-SNAPSHOT` and when finishing the release with `gitflow:hotfix-finish` goal, the release version will be `1.0.2.1` @@ -298,7 +300,9 @@ The `gitflow:hotfix-finish` goal supports the parameter `skipMergeDevBranch` whi The `gitflow:hotfix-finish` goal supports the parameter `skipMergeProdBranch` which prevents merging the hotfix branch into the production branch and deletes the hotfix branch leaving only the tagged commit. Useful, along with `skipMergeDevBranch`, to allow hotfixes to very old code that are not applicable to current development. -The `gitflow:release-finish` and `gitflow:hofix-finish` goals have `noBackMerge` and `noBackMergeHotfix` parameters respectively. They control which branch is merged to development branch. If set to `true` then release or hotfix branch will be merged to development branch. If set to `false` and tag is present (`skipTag` parameter is set to `false`) then tag will be merged. If there is no tag then production branch will be merged to development branch. +The `gitflow:release-finish` and `gitflow:hotfix-finish` goals have `noBackMerge` and `noBackMergeHotfix` parameters respectively. They control which branch is merged to development branch. If set to `true` then release or hotfix branch will be merged to development branch. If set to `false` and tag is present (`skipTag` parameter is set to `false`) then tag will be merged. If there is no tag then production branch will be merged to development branch. + +The `gitflow:release` goal has `noBackMerge` parameter, which controls which branch is merged to development branch. If set to `true` then merge will be skipped. If set to `false` and tag is present (`skipTag` is set to `false`) then tag will be merged. If there is no tag then production branch will be merged to development branch. ### Versioning diff --git a/pom.xml b/pom.xml index 621391cf..c3e5419b 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ gitflow-maven-plugin maven-plugin gitflow-maven-plugin - 1.19.1-SNAPSHOT + 1.20.0 The Git-Flow Maven Plugin supports various Git workflows, including Vincent Driessen's successful Git branching model and GitHub Flow. This plugin runs Git and Maven commands from the command line. Supports Eclipse Plugins build with Tycho. diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseFinishMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseFinishMojo.java index 688d28f8..8153554e 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseFinishMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseFinishMojo.java @@ -182,6 +182,7 @@ public class GitFlowReleaseFinishMojo extends AbstractGitFlowMojo { /** * Whether to skip merging release into the development branch. * + * @since 1.20.0 */ @Parameter(property = "skipReleaseMergeDevBranch", defaultValue = "false") private boolean skipReleaseMergeDevBranch = false; diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseMojo.java index 4d487c73..2831bd69 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseMojo.java @@ -162,6 +162,7 @@ public class GitFlowReleaseMojo extends AbstractGitFlowMojo { * will be merged. If there is no tag then production branch will be merged to * development branch. * + * @since 1.20.0 */ @Parameter(property = "noBackMerge", defaultValue = "false") private boolean noBackMerge = false; From 42fcd1e7d3d235603bf6e80b0cba473061dea9af Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Thu, 1 Jun 2023 13:27:04 +0300 Subject: [PATCH 24/37] Next development version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c3e5419b..2f272cf9 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ gitflow-maven-plugin maven-plugin gitflow-maven-plugin - 1.20.0 + 1.20.1-SNAPSHOT The Git-Flow Maven Plugin supports various Git workflows, including Vincent Driessen's successful Git branching model and GitHub Flow. This plugin runs Git and Maven commands from the command line. Supports Eclipse Plugins build with Tycho. From 184193540b6664306e31c421a8c3a70ce09dfd11 Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Tue, 22 Aug 2023 19:44:27 +0300 Subject: [PATCH 25/37] Update dependencies to latest versions --- .github/workflows/verify.yml | 2 +- .mvn/wrapper/maven-wrapper.jar | Bin 58727 -> 62547 bytes .mvn/wrapper/maven-wrapper.properties | 2 +- pom.xml | 22 +++++++++++----------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index d899d129..9a7a9f3d 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Maven uses: stCarolas/setup-maven@v4.5 with: - maven-version: 3.9.1 + maven-version: 3.9.4 - name: Cache Maven packages uses: actions/cache@v3 diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar index c1dd12f17644411d6e840bd5a10c6ecda0175f18..cb28b0e37c7d206feb564310fdeec0927af4123a 100644 GIT binary patch delta 52871 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≷S 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

St0o*K217#e zeUB5(rQbS+frawg@a^TuxXosIHRjzGizC+K^~|K!hd2mkFeCWuBb`4`!ySPfmN@r- zV}gf#8-{GV*8ROFZ4>-K5x^tPE?vR3M@d&4!7y_w{#$^%bY}H)~#{ux@?pY(rWJAQSo7cxiyqDH5_D7Jf+~8n<+z zwghqP&kH0mJqqfR@>BQO*D^hs!%i9DzG@h!wcuq3s3h6cU3?G)hcncTREM>mvBLM$ zoKBbD_j-3}!Uw|#d<^J#!XZn9gKeT%v1Z)kL z1%t3~fq3Kz0^>-}5G2nSb>emugi~h7&*0b5%-Plm5tBJqPmq65N_hzUVg{ih_=HTQ zK#Y|6)}AnDr}x!d4p+uD{8pG4#IllIr(qPv_@Xeb-^O;jj-lwqY|^1N+1Q&-txcFv zEgE*5P4i3AoR_%6k1)dZ^9nVBk`;-gQ_L&kfR!G`zfga3Vp zv@N4~t{lcRav6(SI_^Gmk;>T)RjdNeG?FMpL*7U^L}ts;vf zXA}-BP3e^XK$-1JG`b~c9Rg`)Pk>4*_|M-8%3s&?=I>ZN^LHti2uMnB7jueH0y?lw z)8YF|L_5H1Dts>$tB@tHR+6zNlsiG1kBZ1Z$6{xq>lH2Y#`|N$k1P}^xBFFtK zF8HoG*}TwE)Mck4$+(=Gnd6_Ixw_o@e0e>m3xbu$TW}c?Mia{;N4%H>L>?voK-K1z z^oV6CjdpDNDM51slVieu^Rs!(t{2#8ucy&(3vZ`zuREKr*>tE4ufKM+bm=*YAa>YI zhJQmjGOE0?e*h-tzs7*-A_+Lrs+Mc_pUI##=SlR6=~dldQt>s8^_y1ABMEr#vYM9S zn0EPXp>AUi8(ed6-!|ZI4@ zSNcpcKct|q)=)~c zFHlr;=anK^|A9y>i)rOqV$W8i+zz%p5hQMxsSbCM09UdzyV$|u$o`kb&|z| z1ToQQOU{!#LKUj9(=jnTmq(=$<3*a`iP@Q2oAX?nJsxQX-6fJn5@gLs3e9HSpsE2p z?Jq$-4#APw^>c!0X4&gr2(W9MFzPHiecQl4chnj(7R7yQ}l z|AEWrmih>Tnx{O{86T3y8vWmga2yk>sru^U*l_ zs1^*s2FL2n5bKut8<>e6;}ic7?4a@^7#<&+&pGPI12Q8?V12uvwqOIG2fp}W2NsmsE4Q%tM^EYslZ>mSPFu@U< z&vjY$jFnif>Uw=LHJ}XfooYs~>aSh3g=%7eVmEFq)4rF{{$&zSs+MzQe%4yoTf^g6 z|0lbB%q6X8y5K$AW|?BjZe&w$i-19AtyY!whPPZpmP<`CID54;3MGuaf;@MJJdbqn z`DH5a-{`MG3!vlr{pFCcea*S8vu%C7%h%nX0+f1+n8$6c)@p3hRIyZc{B@jupFeka zE1*Y)qjFwqhir_3=m_XTWz5t*e!Gh_suHS?oOiKNdKxYW0kpm@sUa)nL`UtRl^yE6 zabOeC(RkhwCiEK$Ro>V)Ec!5!huI$6&0MuuU9R>G3_wgOXI0`gobu-y$2FQdEre-< z&KkTYZGIIkX61zCMb9g`H_Xob7F2 zG3%}==YKM(UHirX+%0(7W|vSs>*HM$b$aT=!IW}A!cPgz7|$AE$mt)^I;ey3+`R(V4^JKInHFyTX|Uil%cy?XJtB=o9>bu zz1JI>jJ5F-&&Hgn4{SCLQQ4Ge$?IHOlf}3QKkuH|r&eycw~ZNeN2P?b4iUVIudm^9 z2-~%09gHn%3NgxN-7pf|K{)YG&pRSyDe1F6k;X91O zrCI1Em3O{%U#rx|8P(>kO;}5YX*e@QSiRnKe&t%)SCfC-r;;4t3 zlo|{XDqI_u+OO2U>~717XUVndWrT4D{X%qqCUaCT z@?M{h98cr~AVm|b`Md{UQfBgdLea`Hl zDvDAUo*0qAL}2+8jJ)*sPWOtO{XVp*|CXJ6_Ak`0r!iVQcW!YBTsjlL^gSX6|D97x|o?eu&X*M#{+*Mmo==-x|0PhA0cMD84=<$Gyk0G5WVj69)FL5 zu-eG)NC?GVlO+2c9`}xbEO&&|Z^#B5^KBb%WC>&(F_-hiK!%pgoE7rmg|S%wEIT== z#L-iyUB8FkLRTsS_&J6;u9EXi9t4MIbRwuTsx-8Hu2zRU79V|lH)ids4xLY*qkoRQA|%- z(iRv8kWYx_uhqipHn=4DQ$ZQSNi@$y=8@ZpR!m{l&{2JhRQ|%2Ce|O1iN#fws*A+6 zT$8#^NiBOrO?y%rbS{>vt3dCT%$UsRPWgNZ0q)M=8g(nd>oY!lO>fbUb+ms{?&+jC z4eA4=Euz0*n@0u^k`m70h#|3(NfV}YqrfixAx}&PZ5jYOgQR&C&TPZKhOZ{~hRP~| zF~^MP)BN>#-X@3tyD0Vl7rp+1Wgi{>&Lj$9ewV$1fTWaVDFXGh@x3s=W*eEOnPny^ z6NNbddaA}<^eD-kh`Zq^*$d7xa^y?ZvyFUVGT#-7mRQN&G+S%$bsU;i8Z~Qcay3!u z6c~PYSPp&f0fO&;QkXski9X({PG@EqJK|=86Z$_+Kb%f;zh3jUuP?rQ?<_$4?x+A) znbZ|SiHkqj(13G4VMxa4Qus6ZwfReZyom}rD7Z~J(O6j>hf@(Cm*w-|kNhDS_dos5 zz*z+&k?+3!7ewhz;K*Tjjj@XSq(>z$I5+DA^{wk6JswVt%znJcBe=}RYzK6y(?8^wgYXAWqM|Noaj0ZHJ(P^HD)A*ha zBlsD&3c3K@cF|?Q<&~@a)D!M*vi;}4X~F~>8wQr53CcE_-B^WfUEaFwCh?z8FG`)B1yyyqVm5g=HZbPL|>v+XO4~U8R{p-Xl;P8~pV>6YN&!X%vWY ze|?cFa?Vrdp6Q>!B9j%izyql#QQu=8lLtG<`56wj(ehD4U%pC+BgC7$w);9!=iBZU z=73_*$bLR&$0h|q@rPMx_amC)if3N9mrkp8bFIx8w4LZunD`=0YV&X#?WsIH4tjj^ z=P4ciCHpAdn6#@M)SZ~n7(3x1aNW)k!Ct|H&ilR`Gd$KeU7>_8zxIrKC?wvijk;Fe z1Qh$STivBN7_>avTDq&VY#C>Ct6=EEHh~Kp009x-K}i2 zK!xv9Q4R+^HAz*aYGm#9?9T8rO;{o2TQPlAXE-Vfea&04Sn3xRN%CIeed(k~1e|!W z`U^htP2x#s4aoIZR5y%_kTqX+t;Dh3P&zoQ+u~peex;=9eJXF6q3Ku+f8rEZMBqPVk@V*A0EBE%J*Io1(L1(!d4*&Cz|pvcA3wpHb`PxmNUUeya?uzXaIm$WdzT&P5eFAnuH^bo;@;47RBB-{~SKvmjBb3B1KNX1T#ti&0JmeCDk&=Fj~ilCqazx zJRtUQu{ftUsLEta5k=~6DsUG0$Vkb5s`Sj3W+Td|L=|7(<6pMOfV<$OZWn!bT@bDL zIQzWnF=x&s`$$$(;h)8A2Db$`TL|^m5^!Mv=?)kw<^kj6yDHgnKo$0V{|c4Jph>aB zqq?T6+wWbBuJz(PGj>0GidHaoshksH$uOT(acorFJgIa1pT)CoiNIn8Hy9~9Q8(&@ zwS{W`&7%#eBSvZQbWto=l_rF?;?P}F9KTUl_9)itVzxYLi+|klpo1maPKzbl4`>Od zyJCc6TN%loAvkdE{?VnkuS3>Ym`eNM64WJ03Pl->KCR?$V5J9i8>|UGwX&NxvbW=F zcPYDTZ9uohb4ew)nSiJhXg8Q`_Mk5CM>lR zm>2v*(eu3kIjn}*CDS-z;6O<*uH=6K2PDl5+ny&t(~FA$aGhCUBLKgx9C!_B8d-B}2-b6=$*1Vyb7 zlBC?29)<-HmT5FoR`f60FnE5b%jIAF>eygUsP{o2{v0vk;Q*7>f)drT^2PI5P7brkY;n4%I5*#3@a6vk zV~oGdt2%ihU6M#yRk>n90MJ*nBa>xK!BH@c6=}iCx0og$2Xq&_-IIC&^$+NMcF+;V z$!NmZ)Q;-u^uwVowyUyxhv@8vYab9vW)&j1aEDpwIHq%(E<6~urqeM%EzUq(v;Ftl zOMmZLWKI(hW*AvY&ur9S*k!QlYd18&oC1uh7JuF~8yvJ*Tx-iBW25h7OH@7bH|eh@ zuY&mestO0pOT|?&L@dn!zd0tDBH2ffe#dNDfm2+aI!Dd6j6O&NIdcQXk!}^$#R82} z3pUdNk!_rjoC_sqYUAnf?K>X1n{3!ISFBNg+#7mo8T8~&j%imZGK>@tc}GrA}} zD~0r$v?x6AEO26wj2AL4Jt{~~7&v_TpzS5qQ4!rqY8=s_-0|6f-xOgeN|)t9om@6& z_)i&mmKnk^V^;Z3U_)sf_h1XN|fspB%YdXqlKsL zM8Xkib_}R9zua;rj=sC;9k_KMp*bPsdqS zurRFe=o1PJj2sGZ%+Vzm;_A+cRSOlgw7;e@KbLfZLIYh3$~eW z=r)oJ+{$*x(gjLteWvjI1mK7VXR8G#DSsWK`4;}0q|hf0PzG(T8u(8o#tBN@r|(;3 z`~{s-n8lGISVs7Nm41d@&z_BFWhQSC1~`W1vPkS`Y|%j+y5tr1p^kG;hMFr!wjRh& z62TXE|2q+M6|yLy!Ea_~3%xd2IQ>vY9#6-OzuR+emeBz41A;m3m0T4^qv#-e$3W|x zt=tsf2NP1By0b|1M}1)>X;gBs4I~#pHGJ98tp}*mWS>%`?INyrO5j+V<(t!x)80?w zU10{dYpwGJhh4v^{eq`r8R=)2o&wiF@ zQ>A^~eo^i{cfqiPppGBXVXLpLij>OY!yJCu5^u%x`~ih6a$P+k&}^6Bu#ExFaNSM$ zDgcD@3Emm%R8N!78K}!4hjrSHFtM(^k8W`58@nnudTVp83sO8@A?{B;_yo|xT%4sCnTHnbUxnvufEO# zD6XUp*SI9OyF<|6Zo%C>NN@}8KDhhf?(XivJvhN3cyJ3I;7-{6cW<_C-BUF+Q!`J0 z-F@1oPj|mxqn;9(fW9VQl8b%{|AVd4d8`4|vH5P%F9RvfQ~4{|;BMn;zAdWe3R{}flo5qKp9c6B75Ktg&v5{WY4W*FGvj{ zoiP~^XKu)X{*^h7N;>X{gA{8fm85s!wMl14?0T_f3|sGMx7E&NpD_eo$EwpW>09q7 zuu-1y;!iDfJw4h*{!FyQKwYjJk7by32U1OsFZV0)xm3`mb1XyibC;~KQCOd`Syzs| zWjVnV70;$_5q_`XJ;R-m%dWtt{F6F6TCAi7S|@y@xYbwcQgVhzOv?1vM~dhFZ1foj z5Dy#$Rd9XKG)?UFQKMZ6HlR@Tuk|d`b`u$kS{=-e9RH@EUIz(khuY}^DHT~u$)DEL zz&hjh6|3gqhzIOnq#bt<;%I&Kf}?Il?LE@vb;}L>w__Q3pGg@K7x4jFQt8pJ!^RpSLdOk2eSx%&Qn6~-GWIB1Z^sU*J<8DLWN;4vr|OL zrT!$%Ne^;>UianvnSQ^{p?>s&zR&AiGx#)KskUV$HXm@+E{|Vja42}&NaSRUuS)%~ z4qslYgNdRkcqJ`0F33M$1~K&lEv>kt*lY8mS1g zJ|wpuwtM;eindKWiM&o=?H9LxCVw*o)}B4Od~sZkmn*zy76{uHgn&%256x86b8ujo zn;w)0Uw_CHYUik-*>H51c4i=mRCcCPT^~^*Pk%L9l*Z&);uYaZw;6g)Y(M&R>>|gb zFlnDbWZ?n$c(A0ND~SV~Q;3&OKt)u@61o?S^ap=9iNhd5)}lYd#>GZYjqvAv(G?OMXa`_bz$f1C{KC5GLVPl9o744ZCyP zM{Q(nFw^wiSc^@!Ul1nxhd#&6W|9QKCHtE}4F)xQh2!7m$Ofr|t5c0uJ zL->2bTVMs6+OPYXi7VV2g7>_LMi4Q>M7`TZ0JKsnxoxWH5Vm?Q77TW2K5sPC8Dl09 zhrl0X;{W}VlD|op4YVp(1?VcweZb&v)^1W%*F;%RfC>r;f(^$bc0yF*WKOg4HHJs- z_?jezJ0qWdK!4fn#d6U@4Dz)sh;!z|NecCe_N1@X(esr1B=w+LP|yd$E$Ax>Vny(I zEuKC@H&5=pyoJdvT-50|=AN_t;`kaa#gC^k^>J(xh6xU4?y*B;`~WQR*6W6Y6;?I0 zB&0Xx4&KzVG+(FQjKzHX)R0t^9bT6pd(Sm2hZZK>Z^km(A2c_uK^`ugMlG*4H(4+H zLuH>wX{m#BiJX2XO~&YUx9~|n9&8fsYC-3=P1`xDN;|OCbl0A$k&?g#c7ID)v~)^} ztwH>tz*XicNOXBJuLE%TeNll{JBwb~!o+t!aAB>DgVDq0v13fPckH457fhd*mEpZq ztM|$3_v03lk10Z|-7uR^)~>**uJ9Xur}st^TPH6PGK-au(}9^D25>je=m*z)cLl-}Ws z+tSLvV4carp6mxjJEAH7Z5 zP)7`n+h7kpMbRK9C#OVMNIq1GvKXO4?c1ciW=0DZiwN%(p@_ z$pi9?eRC%i2On=6(QKp#}|M_wh=GMw! zA+uJ0Ku==nIV7lmVW4N=i=knON4qu{4vmq zWM(`y;4aOxYd0!GEZ;ufgwD|w9+6&0?R2kb}JD+3k~53Y{jsZqfuU1)17R{S}}C* zM1(^p6YIk)U@Mqr=&uNVUtnJ5m4!3U6f%V14ZzOLK3-0Y-?c~?@(&h5V5;c|#>Y{t z8D{bf6T(q`DXX+T(KNN2a7I%zPqgz0Vli|qBer8a-&pD45K#b1P(1prQ-JR#;9P!% zz|(OS2)zjVw%m)-xh?e|AR6jPmetU(2%Bkta0J8uVr(6cSy(S4D6UE@C@MQi=ubF2 z2Ovttf?VV?v;se|LX~O?)Vo9uviQ;G{J}C00hmUOL7I7^&bTdupECP}JSmzu_k<3{ zM|g=(TsY-q$IOX9=qdOa7!mD={g^dEcWc zM9s-@#MlzMbtBoG#DRLpR(m>TeP}%XkqKHq$DTyZ=Wp#1X-@)uO8fs)*<~W=7E6KI zHR^y$RXNZiH;#{K`$=zGP`Dx{Lk?L3#!?cak#uN*(rkgh6k^zVFpCBD%9^Qb#4{oz zZ9k5Up2r157?pT6XwQk4nYI$WWt!WfyWpPtm#ow!#*K9VRE@6*;Zw@D+%Yi`<-SNH z%zB5`TmyLEIYO?nB@iI=m3PJ8pvHX3uv2RT?Np>ojeJsZn&xVm z%9X*wHKXiPBVX{HcwaL?`%Zh3?g;NSjBD#z3xar0Q&4)f{Umx|yN1(h_y~T74yI}5 z*_#!w!%K0I7SmSKR1B^Cns z)PwMKCcE^yzS}46dHv-)RSH};cOgRS<|F&N?{3}mSs%lC@wIvLj`!R6OZ{Qq=t4o~-JbVI74-s1dZd7ZBa}gU^N4}q`aCwk8`maB z(RXek%VO-o&)R0mZlLkY@*Lx!YvMWy9M@xs2WMgm@F9o{Ij{n}PBuQ$*liDPlvf!8 zVFoWwewW*@0N)yH!Z3vbDC*)bNG|H5&)^*z>j5U`{g%Cf=drx8g6bwGrsNR-M_1Y3 zrFx5^u1%aHU?>4s3{PmG6tAf07U?6asHgwIJuL9@jmoG%{OD)nL{3dbB>!Nn6)|2! zsT02UP;yn9WEOAOn|+mZ@-pCMw^%G_EpmQ@+NXO5^(>bYY3JJy@@%hCc!e4}Q9Z#g z(|d>f`1}+EG;a?|X?VvYWfP|=#1mLI3m?@CKJ*k~53OM#82B072WL0x-%EecTS=k*F@r$!LCiH+&c&a4z>Ev&pxKc=W5Q+ihOB`e>Z zc$WTMY#`N5)py!Z_+&eNsxCjwXmp#bvhu;tK9h8hT)B~GqyD)a{PJEC-|(8*6IU~) zfCBTtLBiFjS#_gd{5q!X{upOg`qVux+(wWKi|Z`s!Z-i%bU;r#IB zLWnH69~R&%ILc+#PJDUkeB1&JOm?>!W0CP% zLEDQS8#5VWcNAOEagwHde>v7vV@Vx=s9%pjdWwY;KSq4V!5N{0G0r~ODCSqS)oS!9 zcv^7iLg@-|8jgg;?Cnar*+BO=8fP}B1$5GKXKP6f6^U>i6btMm{rgDwIo|MK9 zQ~L6$e~9tFNQ@1g7l;*5q3FsvvF;ONK7DIg)(k4X{t~;HiuwvEhs(#=-@i z;h%+m(A!%S1_~~0ix!A)3RLN}Bii9s~jE*cW=c)rs;?A8fsOwe_6IZ|XmwD*zzD%I`qH#uWirbb5# z&pdx>Q+d+n(vGa%e%fT?+Pt1am93KW7nCFZ^z=ia#2+kf=g=Y3~O z;CZhG=D1r30d?VL33x6^6D-{mfdstomf*7LjfjzpCSa}wmp~+7H7Gl?N5_JNCd)|T z6S+jZzzEmyq6!~iQljt?c_W(;u0tXk@ zcJVNQ4MuEgLcqd9q0*BLi*aTc9me*xVeLEYnUm2#I^$qc?E6BkCA-=%^`#t-9VLHQ?{Rr!TP> z?J7}f>j>Dh%6w!s4&k-bfr(fU&m&}aNnUGODm`du=H5&@QED$A3;Wg(^m-<-CuI%K;Rp05kj82xBj!%Bh7N%2oK19@(1d5+^6=EkIS-poIQ%2N zMZHM!;&jeKCeF`(PT11HW0j`4HON9)cj>V}e`yb;o1E^I!X!BL#7_cqeVEzwnlhgi z&=q`wtOEo~#gU329Ot7s-rSKd{gOL2gsw#?tZKN49gt>LxSk}cP-C>4d(xjtwiK4F4rlrUX zkDr4T&((#JoMl0NS5hv~l6<(rnodQ7aenAyI%&F_sl{E}ae`K+IEgHgtfR0d8HLgH zW=}!3iVs>-Yu)IvGVT{rQ`ad>KPSk;*7vJ`(?JIGui?h}8!3_vYhhH7vxHG55c>7# z#lA{`>2e>BDCCszzAo#_qVC!{yRg_dFXf&BB}Nr-c9h={#L!}uui9Er&B@R9Nh=oc zRvD5Or^><*p=Y}A5n`}MI0E|$a8nJqPcDK>;J@5w-XQhN$s%Wv#21;|e}^)Ta7>K@ z9IXzwwh3q_&T{GQW&auk)`b|SIBYRX z<_PYBBzt*@p`?_8qc+OY}2#&KL~o~i5Gsa*P;PYf}cc~F+p7Dwr* z-+dg=K(~;^jWB|%9%V=J-rfU!Zmg+RnpfXY{0 zJ{Z`q{FBkvMI#l&4nNE#7vn>nwA{dA;7k$E>~P3JS|Rl_R7lI%B(7leoFuK1y0RerOi1e?w3I-6 zuIh47r&JL<;gZDaD9@XgoQrQySl$jM6JeUG`XFMywB`^)`6B^e+t> zRhuGb@I-ug@~{FS9l;rT52jyYnZy-d1UP;HNv?KHrc0|P;vy&mBy-Qqc@776+EC7W zla)T0{rWb=%~Bse$p_&&xFx?IJA~P6r^)BGG)haesu4x6Xv}<6Z&Vd}fD3JycUXzz zQG9u@f}s)3Sk0wGN&w&z!mV<`Nq&S6V7*0dXTd*pc5Tsks&CYz6uI6lC6=|mTttwd z;QTZ{ntq}QtS7I^ZqPjP=zSPUxeV92jmVStG%NQ=3>^f%GqiAzPJ3dxo^gYLi=4Piq$s>PcHQO~?Dpt_SyRe|bisSjs?~f}lBIa}oNm zvCr&t4yx*Yf|Gx|imusK+#H>(yS#|F3zvP8YrtTNjWdn|#?J>~`4;jnEm+<)B^-E8 zvEGr&_cIAntm*)or#)oOHFS`(m-i#&dXx8>i*q5u*}flSk$|QJdRpPE@eAJCqwla6 zmJ{VG81Q5TwO|p7tfi z=(^gjxfb-eM*n=`hW9G|!Y((Sm=h59eGTI<+FCwKPwPDZLp9S-pHhz-3sGiaJai1+ zchyVXWpMCq)TovigPT!TS=qIfY^-~G$CT~TLal`FllYt@&aU| zbkiFnf-zo&?%9|NfBws&Lue>~AAIBbp>H#`*>Rj1orEpXfEcs(yuzsW*+$^iti&rp$I0QahI zpT}Cw0qodnKg7%|KE`kgNjHI4Gm3HEL#v*O(Uh9SdoaF%RUC*adqzr*E%{bFj&%3H zOcyhOSMGL?hSuofM%UB+Z7Mp3=gUu_1pUBEYd*^AZHs%< ztmKXFAjN`!OYnzXBZOh*j`(DW6Ez~f07J{YzI?aHlc$u(p$jO_$5c1V@f_16UKw2- zo&b;_e)%G-ilJt3wY?a4qvd?P&nScBPXO&Xq*taBjI-UsgT>P0PFKvAqg@lekt_`p zbr$p`PdNVZu8T`;FGvMuh2l}hbGEJ#9WN?)mb62yo2+d~!tiK=B0pPPxAks6@)Xodo)Wdem44VUiurw-9ysoPF?Qn^ zKBz7TuWHVO6w1xhh#n5r@mUdcJHWVjR~EMs)4@rMdtgVO7adw~S(aS4TB*}=ln;v= z!8-1&QUK?T9f%xz>{>CP-k|BcR|0fGm88<1V7X;=C-@3#sNWbNre5n`e*f8@J3Ew( za3?b%82FYth_*t_>XSt7UMIG=6ge!PpTF-?Op%wEATPjAL+FUdq<&_iI7jNUYtbQP z1FLi=Z9XvfUsbwxivTcerYl*q(Yl!B~hEd?|o*&)PT` zhBE18M;bXAO4)`4ojttWuOzk?6kKg@V>XoLBgT*me0M%(jNC93eT_lwR#5b7W`-5q z9l1pk+Q~+xVzU~WbR+2;`}qr6 zgLJaXpA7H{PxFJn^ig<8%vQde_jwqW;7$sL3{b8j%kWPAj9W31V0y;x6_cw&QoZTy zm2E&An+%5tDSN%{O<4N!5!k3!Auib?3}}pPoQv%i^aCFSwHe7~8g0;qwu- zrR7?TiW^dTOPo8_y@7uR3;AOHoq-GzPM};LDU<2kXzeA8ipQT4Dzc9&;M@)ao!zY? z7LXx-Y03Z{ohRAygQt?fKm#_k8efE9d#yB~utvGw^Gw#ZEvwIQPk?z63~a#q1$w+( zB*xnTmN#n3kxMLiZwoNSOz6pd2-HX1I`>DvsL=P6OOA1MFu`jz21GDARz zWBXEeqB&8rl8Mxv_PlYYMnsG}sf2-l=gJKs!s{ph7!&h@30oO30(fIBXe1esI%j{D z@a|^9s=~wB;u%7r)NDq8O(W4`Z_dMc?YrC@q91reQ$ho!^5lva+=;iHW)!vCQbNYr zaMs4|X3xtp7~V%!_{ET~QEGTIDd%$YQh_D%;DHijKUFF1cXhq{_lwbYxsD=g4W25ydwQnTw4BZQ zO%u6%Cqp#ngaI4f0C+;Jd?UNd>`ne~Wx|}ux>7Npy}I;1VtUR;{hxp zge)Sr%TJ=aex#9Ej%OdfIc)YndORT0&tj}c8ydh=ev{Tq;$il~!8bnO@EZ_C(fy^@ zXPXd5yv;e0xc1BDDn&GpWQ-daN@%=k9It_rz3oNwW#Ph;{|l$vrRFlUJ^F#|-YwRQ zE`{E&#Om)apv@ClkWl|_a97HQVG;xFoIpSYJ(?j0BF>@$y~f}G_pTtXJI~?~5=rk| zDkv;7ib~T4l1v6@qi9M`c${Zi>@9gI-*ec|FeOo47Q~AaMrCkKCCy;9)izXEEODy9 z#X3j|4;$PgA^{-3Tqr2Y%a7l#M;edeHTO&GkGG$7wfmf{^X3EAA7(#+5%lg-Z&8;~ zi=lp~#q6w6O~{7>w5OY?E-Hzx$`v9am04@{b6;>(8%hlXQS&H9<`HIp?%P*VyRgE~ z>bpYq5*m1`ROZbbZtbQtAfx1zi_jeG|rSP4}4Bs&HD3K=KpG z4(O&MT$E49QBw+@OB}S~BlcQ}gNj9nA!Ltu+ybYCq}v@vNBJ&Y9}BqgmfOUwdn@2% z9v5mknC4lm07=4`021i%WMkTJ|LO)UxSw(BcP0K!Ja2^j0r1~!gCeFWQ zZL<#V9I|o-FMdlpwWH#vo`lj$LfryzbYpQCtG7FY)jpp^+ga>2yg1WUQF~58N-htNK4gbvi zj;O0T=jEnOov9|Zg8dhmpy~yASK_zrs;wbBAOCFHmKFT`fH25Jr@RYiDmTQ@;=Rc_ zFLv3@gy8JWeJ?F*CL#=|8F<7m-7Li-F~RV%mTo9lcs^mSYQLoW(A|{#s_mtE*4d4G zpW*-uZyVvFvnTP0Ab8g@(D-3#`NQIODI5lIP1BCBlLx(g@;95^H2TiY=R!7Dps>^P z+|lM!F4ZY#Yg5#jXohOF%=+;^7E@6Vl7~!UfG6@CA1g}P;0-lLl$0nmS$h9;;#hPN zlx$*S!n>(Zb^sy>muE+R+hYcG0f;x=h&2#WgDgKX~@ozm-J>@?-qEq~P>@*gEGH}vwZ1An5 zp1^aflB%Yht&j~}+;=~X(R~5Lpaz~Z3p`E_nuWJ}|N1HDtNUZK9$6w~2|g=r{09MR zTX#m52}g(thr#8_1sKeV&1PZ*gSU)sbH(hI&&BABB9plcoc-xN_I(_g=UY@R@~e zOK(VD(wD}M2qgj5>8`37Rc`3CBYds?U{TlM;7#=sv_z7|b6i(AfAT`EVDF2u1d0ii z6j>q_M+lR+6)~y&yF2_Lsb{KG0OAwH%@(tCASDuefx`AS+5udlf>GLqMClWkKu?Fp zG`2D;(E~3^M^H+*R*>d~sPMo$z{dUy7xpRl8+$xYyBHw)_vO^X_V9Ky=x>4KsNID; zT}m`eB6FrD1@;=bM4#T38^!Knc)d|@r~cB%-rtx!c&epx*ltd0j&;_fCgS7fXWJJs}F|m?8;A;54i93K2T%VVwkArgp>G(1{Z`& zA;N4Rok;O=Wm=dPQG30ar0Tl!4U>))^}flEd>ltm4DU!O+OIRqZd~~In6UxqdI4h! z8j>oA12V^n!nH#2*s)6WG2jC2&87P7c!PLb@P`soicQ8txfz2!Sx(1N0Es9ors4s- zXfr_!O@kr22LkUUOlhtn~Kr3HQA`|Vf~P_(&Kb?6%yv+ z?RrmIXO(zhCn3anA0ciHT&Z3x5<+d%PfV$uu+lva(C@E2?5Frta~wW+SfRT6G0NIe z#nY_bBXi~B$W&wUxQmlpXU!nCtjO$Oow$%2Z-VAqhqQ#4q z8zkSU=+>Nk`S4KiL3t`b4_>#}D%mRi1a9;VPcAJ^A0m7}v6=>AfCeB%D5=G3*E`Hp zGhs8pbQH^#rD)f*Y|bBn)sO?O6*%B-&nYzxGsnXZ!6ioRPE;kA?@C(`H z(pZ;lzFYkVK{A|f%#Soa0#$jFeP=_BV4pd=NB6r(+d`Vi`#Dta!7j2}8AA!kgoFj5 zHh1i~yh2sszT_Owj?`$>CUZgb#WG8;4wcv>`Lq@t-se1kJ&^<8oZqkq45O&@h~#Gu zhrjvtgigxLSi;^T3W>9kMjDQ2M1gV@NG9Au_JIm%8msq6U8N|lH!@`5XdlMSkUji} z2(fJpe5>9!>9BqJy#cbr4!PF(foR*LeN$NeG6j3MqKA^NF+bTh;6EEGJhIO(gTcXo z4BylMy&o`wC+)D6pf3FFl{jHSr-Eb{!-REEDSK*&M{5x*c)v2~yV2>Uww!}|QE$_z z8r3MFw{rpZ&t5XQXUC6LuHJ$X^yy(KD~@)n!!)th0E5@q5^xLTgWmn*4sa`6Hi|VL z1!oy<4hmU7Z;m-kx+Qc7x3;h^9!iA!mYX^S5Mef*vXn7NU)}$PBA2W%&3cA;>#bU} z3s;}N1IHjI9F4_gBfYS@PO_L!(@B$BB9DV%^$YH+jTb|~P>yP8lZ4l(T!?4W(!8`A zhuGLg9>bgt7ngnw@rAV&4XVqy%dV)F8>K(w+%uatc?t=v#W0gTAq+P_XkN-2CRuk5 zAZ`xLv$50y9GwzjdqCerh#UYDhsJm5D{)=bisf}QQ#qBbSiPz`M-*%(w8h0 zJ2Ik;S-(KH#cq?56a~9T4-MflmtZWVX;u~%!M2bN9b3Q`*(5{Q2!W%&A9RM}Y7$gJ ztf?`R&8}cv!D|pZIYm81Fxq%l`v&ijogrFT_gLM9NY>16;Ej2_LZL>nt}aZE5fxWw z{mK){2CNTnO7#KLJXov_{lXB05pRbIz#ApZJ)Hcz?kUVsa+s`>Q#&oFr`yqW;NuMz zH?t(344gzm9?>cDxF{9v6$gtBtVwWh;pgz=j^gA?4wN^TJ(Za@l)gPMe#WLWd5;8t zOnDsCq;EeU91{~1l}vy5lZ#O!KSh zDAB2y1&V-82873Aa?+E9JVEitsPQFM0>t`_1B)@IJAD$2rEe1c7T7GFT0`bp*y z8>)^rHBRP1nc!Py%kOCI^`G|RKp1lL3=-Su0y$3Q2Lnc42?825^wtdz{z3JQ5i!V1{(b?A^u3g#ZN zCiZ{|pY%tR5Bp^k)0uvz9biJF_&3JJ)QAdFM5n?_E9(;=rWSseOhd7_?9RDYuQM(b zs^BhaGvpReOGoG}PYb5)T=q@bP{+W05-&;w^S-OcK$rk@fOiP_&Xx;YuRmKhn;O5> zF{j2@dxUNaGp~xHR35!dKqXQt9yQ-5EcGtu3k{-zqvC)>8KXi7bs^}^PW*NsbXL9a zIYu)rD>m$t+3u(O$l3FV2vx%U=welx*q@#~6lJZ85F>GtqF9oQl%JVA(mWQ)jE);c zt=(r_Rdsg(rtCLw<|~-ysleFDRu7^?QUdw!xRBl%5TCxg+Awu>Y$4uQk1oC%Nk%bk zKDXd_;!9O9RngJyaeMfB@6GbG3LE~QkJ2_$xET$VIvqV2WmB4;?!vUI$Q`v9FP4I) z@FreS5{iSHb1haSmDyypI95CIdNQSnAwNT2AZxn~Q1s+TLu6h6uJBePxl{Tol22(} z^(kg4>SY2yMa4J{8-KvXTqXCqbs!TFM&zYB{RoBAwBJO>V)ku|Ozm5fs0FgR0zH)R zCSM+yrIHr5Hmo0;ZJfPT@GPja4ToECPgr*h=?9f0LmrO&b=FuE${6<)M7bM0qPVsU zwIL-4fM0k@TVZonQe;uV@xnolGSz+?UL@bP0LuE>a zQt~}+&Otin2${uN#&@j%9gG`_wOrTda2-}ueijCK zRx91;R+Al{^it_~D?g*(c<^1wLAs8P2Y%5) z0=Q|agevE$63g_M3kk+pU?6uMC*oDsuLr1Y@QD+ zZDD&^6$BAFHkL{+@nwXv*|PI8+Bfjm;;^oo8JY?veHX_3CH&SenMltF`C|J~cbV7h z#=br_fsfXUEALCF&#GlOqvS`ycpgu(UVw}RE5RspY#~Q7=^KJd*&Ul4U0P4=_F_Kc z<>^~Rqx2ExL^($%VK&)AH(2&>H^Cf5Vm&h+8M_v7HJuOh4<8~-i}}f6-O21ohU@EF z!ret9PRA=ogCLh|Jj8L^a^o_M$_kGrRvYp%2l7X&+e;q0D?K>QwY+@gp`_GS)B#$b z8B@Zv8k_GWZlLd~2jVG%D0J2D)UaqyL|NPkPL|$Jb)*jOeg36M?(ubmtaSE0;`Vdo-B%IiYE}2;vUqtEET&dKrwAnTCj(Lq27UX_Rp18(oZ29VLM)C_0s3s<0Tw|&$%&~7F-XaagSP$s zwgPgQ3EJrQoA@Uf=mV%v{`*1!I}v&TeYSNl`~QY``@aBSzeA9MQt~^5ft`Voxyk+gFgbwZxa1=o9s66z;S?^n{>aUA^vYPzrBn8b^T7O9*7hBD;Vt-9z-1ka0&t& zsJn&m*LT)ic;M>5&@E#4-)6E@Nap;2HCveA7r?%&$@~8_D4Gb)R0t}4$50H%E6`b0|e+B#TUl#B{>8u2)ID)FhKUaaDv*0U8wTJTx z;sdO0??9D{7nDxMf3V-TXa;oZ1QfOV9@#61`LXAw7gX(hKo$l50I}s?!Ebxauiziv z+W!FA6<;BWZ1M>f1Szbnk&Za_AFU_d~822LLngS;NV0f`R&suBM>L;wSm`oomE&EGIR zQ2*+$c>k3Y2MNOb0sAr5aG3={-uM>e25A0-ud;%)yu!i>|gz6Ffg`1 ztc;Nh3xb6LUtynkd|=nnU+}9+6R0wZfSRJ}AMki6 z2sV6;{y%~`|6m1vSrM-m=TixQIVXQvd_9a0vN#A@ppgCt{hihk;4A!e^6s^B`S+0X zt4z;7Xo258aO#)^bn5wEqko(i{fGQ*6fy19=;`TSP2u+`yLwPl_}yEG{{ix3zJdaU zFu=-k)PIuu$62mF0w`s_2I#6pqyO)y^Li!*l*eVzT>~i${c{!gS?2v62mz>g{#VEF zdh`GUvw+|a|DeCq?p62-cb*fz-sV5HpZ@_K6~BUX7qqY7KYMd&|63b*%0VC#u<+uq z&g 8 UTF-8 - 3.8.2 + 3.9.0 @@ -78,7 +78,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 2.9 + 3.4.5 @@ -153,7 +153,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.0 attach-sources @@ -178,7 +178,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 3.1.0 sign-artifacts @@ -198,7 +198,7 @@ maven-invoker-plugin - 3.5.1 + 3.6.0 ${project.build.directory}/it ${project.build.directory}/local-repo @@ -224,36 +224,36 @@ org.apache.maven maven-core - 3.9.0 + 3.9.4 provided org.codehaus.plexus plexus-utils - 3.5.1 + 4.0.0 org.apache.maven.plugin-tools maven-plugin-annotations - 3.8.2 + 3.9.0 provided org.apache.maven.release maven-release-manager - 3.0.0 + 3.0.1 compile org.apache.maven.release maven-release-oddeven-policy - 3.0.0 + 3.0.1 test org.junit.jupiter junit-jupiter - 5.9.3 + 5.10.0 test From b2b03e8e8f88c99e8d054391a3db6cc48d556fc9 Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Tue, 22 Aug 2023 19:44:43 +0300 Subject: [PATCH 26/37] Update fluido site skin --- src/site/site.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/site/site.xml b/src/site/site.xml index 56e71651..716b4e5c 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -13,7 +13,7 @@ org.apache.maven.skins maven-fluido-skin - 1.7 + 1.12.0 From 28215609ebc0bad8d550f51d8cdcfd3757fdda29 Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Tue, 22 Aug 2023 19:45:07 +0300 Subject: [PATCH 27/37] Fix versions plugin version --- .../amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java index 8e10eb6c..9e094b84 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java @@ -209,8 +209,8 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo { * * @since 1.18.0 */ - @Parameter(property = "versionsMavenPluginVersion", defaultValue = "2.15.0") - private String versionsMavenPluginVersion = "2.25.0"; + @Parameter(property = "versionsMavenPluginVersion", defaultValue = "2.16.0") + private String versionsMavenPluginVersion = "2.16.0"; /** * Version of tycho-versions-plugin to use. From 99de0bb9ee58838866ba44eea347a85b7fcb9a2c Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Sun, 27 Aug 2023 16:03:52 +0300 Subject: [PATCH 28/37] Fix compiler warnings --- .../amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java | 4 ++-- .../maven/plugin/gitflow/GitFlowVersionInfoTest.java | 2 -- .../maven/plugin/gitflow/NextHotfixVersionTest.java | 2 -- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java index 9e094b84..d98b59d9 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java @@ -15,6 +15,7 @@ */ package com.amashchenko.maven.plugin.gitflow; +import java.io.File; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -31,7 +32,6 @@ import java.util.TimeZone; import java.util.regex.Pattern; -import org.apache.commons.lang3.SystemUtils; import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.execution.MavenSession; import org.apache.maven.model.Dependency; @@ -284,7 +284,7 @@ private void initExecutables() { final boolean wrapper = javaCommand.startsWith("org.apache.maven.wrapper.MavenWrapperMain"); if (wrapper) { - mvnExecutable = "." + SystemUtils.FILE_SEPARATOR + "mvnw"; + mvnExecutable = "." + File.separator + "mvnw"; } else { mvnExecutable = "mvn"; } diff --git a/src/test/java/com/amashchenko/maven/plugin/gitflow/GitFlowVersionInfoTest.java b/src/test/java/com/amashchenko/maven/plugin/gitflow/GitFlowVersionInfoTest.java index 596489ec..352be851 100644 --- a/src/test/java/com/amashchenko/maven/plugin/gitflow/GitFlowVersionInfoTest.java +++ b/src/test/java/com/amashchenko/maven/plugin/gitflow/GitFlowVersionInfoTest.java @@ -20,8 +20,6 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class GitFlowVersionInfoTest { @Test public void testCreating() throws Exception { diff --git a/src/test/java/com/amashchenko/maven/plugin/gitflow/NextHotfixVersionTest.java b/src/test/java/com/amashchenko/maven/plugin/gitflow/NextHotfixVersionTest.java index afb16d18..0fa121ec 100644 --- a/src/test/java/com/amashchenko/maven/plugin/gitflow/NextHotfixVersionTest.java +++ b/src/test/java/com/amashchenko/maven/plugin/gitflow/NextHotfixVersionTest.java @@ -18,12 +18,10 @@ import java.util.Arrays; import java.util.Collection; - import org.junit.jupiter.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; - public class NextHotfixVersionTest { public static Collection data() { From 9d0db4460a2d72adf7d8592531a601be01742405 Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Tue, 29 Aug 2023 18:18:24 +0300 Subject: [PATCH 29/37] Fix site generation and some links --- README.md | 2 +- pom.xml | 6 +++--- src/site/markdown/index.md | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e910d957..e6a0fc6c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ The Maven plugin that supports various Git workflows, including Vincent Driessen's [successful Git branching model](https://nvie.com/posts/a-successful-git-branching-model/) and [GitHub Flow](https://guides.github.com/introduction/flow/). -Currently a Java implementation of Git version control system [JGit](https://www.eclipse.org/jgit/) doesn't support [`.gitattributes`](https://git-scm.com/book/en/Customizing-Git-Git-Attributes). +Currently a Java implementation of Git version control system [JGit](https://eclipse.dev/jgit/) doesn't support [`.gitattributes`](https://git-scm.com/book/en/Customizing-Git-Git-Attributes). This plugin runs Git and Maven commands from the command line ensuring that all Git features work properly. diff --git a/pom.xml b/pom.xml index fe7991cb..e38a74b4 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt + https://www.apache.org/licenses/LICENSE-2.0.txt repo @@ -72,7 +72,7 @@ org.apache.maven.plugins - maven-plugin-plugin + maven-plugin-report-plugin ${maven-plugin-plugin.version} @@ -82,7 +82,7 @@ - license + licenses scm diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md index f2bf40d7..49cd1d4d 100644 --- a/src/site/markdown/index.md +++ b/src/site/markdown/index.md @@ -1,8 +1,8 @@ # Git-Flow Maven Plugin - The Maven plugin that supports various Git workflows, including Vincent Driessen's [successful Git branching model](http://nvie.com/posts/a-successful-git-branching-model/) and [GitHub Flow](https://guides.github.com/introduction/flow/). + The Maven plugin that supports various Git workflows, including Vincent Driessen's [successful Git branching model](https://nvie.com/posts/a-successful-git-branching-model/) and [GitHub Flow](https://guides.github.com/introduction/flow/). - Currently a Java implementation of Git version control system [JGit](https://github.com/eclipse/jgit) doesn't support [`.gitattributes`](http://git-scm.com/book/en/Customizing-Git-Git-Attributes). + Currently a Java implementation of Git version control system [JGit](https://eclipse.dev/jgit/) doesn't support [`.gitattributes`](https://git-scm.com/book/en/Customizing-Git-Git-Attributes). This plugin runs Git and Maven commands from the command line ensuring that all Git features work properly. @@ -16,4 +16,4 @@ entire debug logs, POMs or most preferably little demo projects attached to the issue are very much appreciated. Of course, patches are welcome, too. Contributors can check out the project from our [source repository](https://github.com/aleksandr-m/gitflow-maven-plugin) and will find supplementary information in the - [guide to helping with Maven](http://maven.apache.org/guides/development/guide-helping.html). + [guide to helping with Maven](https://maven.apache.org/guides/development/guide-helping.html). From 7e2dc2bf2c7759e8813e69b6174694519298d250 Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Thu, 5 Oct 2023 21:54:52 +0300 Subject: [PATCH 30/37] Add prompter component --- pom.xml | 14 +++ .../plugin/gitflow/AbstractGitFlowMojo.java | 25 +++- .../gitflow/GitFlowFeatureFinishMojo.java | 37 +----- .../gitflow/GitFlowFeatureStartMojo.java | 15 +-- .../gitflow/GitFlowHotfixFinishMojo.java | 28 +---- .../gitflow/GitFlowHotfixStartMojo.java | 38 +----- .../plugin/gitflow/GitFlowReleaseMojo.java | 15 +-- .../gitflow/GitFlowReleaseStartMojo.java | 15 +-- .../gitflow/GitFlowSupportStartMojo.java | 7 +- .../gitflow/GitFlowVersionUpdateMojo.java | 38 +----- .../gitflow/prompter/ConsolePrompter.java | 119 ++++++++++++++++++ .../gitflow/prompter/GitFlowPrompter.java | 72 +++++++++++ .../gitflow/prompter/PromptValidation.java | 42 +++++++ 13 files changed, 282 insertions(+), 183 deletions(-) create mode 100644 src/main/java/com/amashchenko/maven/plugin/gitflow/prompter/ConsolePrompter.java create mode 100644 src/main/java/com/amashchenko/maven/plugin/gitflow/prompter/GitFlowPrompter.java create mode 100644 src/main/java/com/amashchenko/maven/plugin/gitflow/prompter/PromptValidation.java diff --git a/pom.xml b/pom.xml index e38a74b4..2eb27927 100644 --- a/pom.xml +++ b/pom.xml @@ -142,6 +142,20 @@ + + org.eclipse.sisu + sisu-maven-plugin + 0.3.5 + + + index-project + + main-index + test-index + + + + diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java index d98b59d9..0bf478f2 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java @@ -44,7 +44,6 @@ import org.apache.maven.project.ProjectBuildingResult; import org.apache.maven.settings.Settings; import org.apache.maven.shared.release.policy.version.VersionPolicy; -import org.codehaus.plexus.components.interactivity.Prompter; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.Os; import org.codehaus.plexus.util.StringUtils; @@ -52,6 +51,8 @@ import org.codehaus.plexus.util.cli.CommandLineUtils; import org.codehaus.plexus.util.cli.Commandline; +import com.amashchenko.maven.plugin.gitflow.prompter.GitFlowPrompter; + /** * Abstract git flow mojo. * @@ -261,7 +262,7 @@ public abstract class AbstractGitFlowMojo extends AbstractMojo { /** Default prompter. */ @Component - protected Prompter prompter; + protected GitFlowPrompter prompter; /** Maven settings. */ @Parameter(defaultValue = "${settings}", readonly = true) protected Settings settings; @@ -473,6 +474,26 @@ protected boolean validBranchName(final String branchName) throws MojoFailureExc return res.getExitCode() == SUCCESS_EXIT_CODE; } + /** + * Checks if version is valid. + * + * @param version + * Version to validate. + * @return true when version is valid, false + * otherwise. + * @throws MojoFailureException + * Shouldn't happen, actually. + * @throws CommandLineException + * If command line execution fails. + */ + protected boolean validVersion(final String version) throws MojoFailureException, CommandLineException { + boolean valid = "".equals(version) || (GitFlowVersionInfo.isValidVersion(version) && validBranchName(version)); + if (!valid) { + getLog().info("The version is not valid."); + } + return valid; + } + /** * Executes git commands to check for uncommitted changes. * diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowFeatureFinishMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowFeatureFinishMojo.java index c197c093..25480a1a 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowFeatureFinishMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowFeatureFinishMojo.java @@ -15,16 +15,13 @@ */ package com.amashchenko.maven.plugin.gitflow; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; -import org.codehaus.plexus.components.interactivity.PrompterException; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.cli.CommandLineException; @@ -48,8 +45,7 @@ public class GitFlowFeatureFinishMojo extends AbstractGitFlowMojo { private boolean skipTestProject = false; /** - * Whether to squash feature branch commits into a single commit upon - * merging. + * Whether to squash feature branch commits into a single commit upon merging. * * @since 1.2.3 */ @@ -255,41 +251,12 @@ public void execute() throws MojoExecutionException, MojoFailureException { private String promptBranchName() throws MojoFailureException, CommandLineException { final String featureBranches = gitFindBranches(gitFlowConfig.getFeatureBranchPrefix(), false); - final String currentBranch = gitCurrentBranch(); - if (StringUtils.isBlank(featureBranches)) { throw new MojoFailureException("There are no feature branches."); } final String[] branches = featureBranches.split("\\r?\\n"); - List numberedList = new ArrayList<>(); - String defaultChoice = null; - StringBuilder str = new StringBuilder("Feature branches:").append(LS); - for (int i = 0; i < branches.length; i++) { - str.append((i + 1) + ". " + branches[i] + LS); - numberedList.add(String.valueOf(i + 1)); - if (branches[i].equals(currentBranch)) { - defaultChoice = String.valueOf(i + 1); - } - } - str.append("Choose feature branch to finish"); - - String featureNumber = null; - try { - while (StringUtils.isBlank(featureNumber)) { - featureNumber = prompter.prompt(str.toString(), numberedList, defaultChoice); - } - } catch (PrompterException e) { - throw new MojoFailureException("feature-finish", e); - } - - String featureBranchName = null; - if (featureNumber != null) { - int num = Integer.parseInt(featureNumber); - featureBranchName = branches[num - 1]; - } - - return featureBranchName; + return prompter.prompt(branches, gitCurrentBranch(), "Feature branches:", "Choose feature branch to finish"); } } diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowFeatureStartMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowFeatureStartMojo.java index 74735172..72728b7a 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowFeatureStartMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowFeatureStartMojo.java @@ -23,7 +23,6 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.shared.release.versions.VersionParseException; -import org.codehaus.plexus.components.interactivity.PrompterException; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.cli.CommandLineException; @@ -87,18 +86,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { String featureBranchName = null; if (settings.isInteractiveMode()) { - try { - while (StringUtils.isBlank(featureBranchName)) { - featureBranchName = prompter - .prompt("What is a name of feature branch? " + gitFlowConfig.getFeatureBranchPrefix()); - - if (!validateBranchName(featureBranchName, featureNamePattern, false)) { - featureBranchName = null; - } - } - } catch (PrompterException e) { - throw new MojoFailureException("feature-start", e); - } + featureBranchName = prompter.prompt("What is a name of feature branch? " + gitFlowConfig.getFeatureBranchPrefix(), + res -> StringUtils.isNotBlank(res) && validateBranchName(res, featureNamePattern, false)); } else { validateBranchName(featureName, featureNamePattern, true); featureBranchName = featureName; diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowHotfixFinishMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowHotfixFinishMojo.java index 8b76de46..f3fbd5d1 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowHotfixFinishMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowHotfixFinishMojo.java @@ -15,9 +15,7 @@ */ package com.amashchenko.maven.plugin.gitflow; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import org.apache.maven.artifact.Artifact; @@ -26,7 +24,6 @@ import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; -import org.codehaus.plexus.components.interactivity.PrompterException; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.cli.CommandLineException; @@ -405,29 +402,6 @@ private String promptBranchName() throws MojoFailureException, CommandLineExcept String[] branches = hotfixBranches.split("\\r?\\n"); - List numberedList = new ArrayList<>(); - StringBuilder str = new StringBuilder("Hotfix branches:").append(LS); - for (int i = 0; i < branches.length; i++) { - str.append((i + 1) + ". " + branches[i] + LS); - numberedList.add(String.valueOf(i + 1)); - } - str.append("Choose hotfix branch to finish"); - - String hotfixNumber = null; - try { - while (StringUtils.isBlank(hotfixNumber)) { - hotfixNumber = prompter.prompt(str.toString(), numberedList); - } - } catch (PrompterException e) { - throw new MojoFailureException("hotfix-finish", e); - } - - String hotfixBranchName = null; - if (hotfixNumber != null) { - int num = Integer.parseInt(hotfixNumber); - hotfixBranchName = branches[num - 1]; - } - - return hotfixBranchName; + return prompter.prompt(branches, null, "Hotfix branches:", "Choose hotfix branch to finish"); } } diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowHotfixStartMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowHotfixStartMojo.java index 74ec20c0..96d097a1 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowHotfixStartMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowHotfixStartMojo.java @@ -15,9 +15,7 @@ */ package com.amashchenko.maven.plugin.gitflow; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import org.apache.maven.artifact.Artifact; @@ -27,7 +25,6 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.shared.release.versions.VersionParseException; -import org.codehaus.plexus.components.interactivity.PrompterException; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.cli.CommandLineException; @@ -112,27 +109,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { // add production branch to the list branches[supportBranches.length] = gitFlowConfig.getProductionBranch(); - List numberedList = new ArrayList<>(); - StringBuilder str = new StringBuilder("Branches:").append(LS); - for (int i = 0; i < branches.length; i++) { - str.append((i + 1) + ". " + branches[i] + LS); - numberedList.add(String.valueOf(i + 1)); - } - str.append("Choose branch to hotfix"); - - String branchNumber = null; - try { - while (StringUtils.isBlank(branchNumber)) { - branchNumber = prompter.prompt(str.toString(), numberedList); - } - } catch (PrompterException e) { - throw new MojoFailureException("hotfix-start", e); - } - - if (branchNumber != null) { - int num = Integer.parseInt(branchNumber); - branchName = branches[num - 1]; - } + branchName = prompter.prompt(branches, null, "Branches:", "Choose branch to hotfix"); if (StringUtils.isBlank(branchName)) { throw new MojoFailureException("Branch name is blank."); @@ -167,18 +144,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { String version = null; if (settings.isInteractiveMode()) { - try { - while (version == null) { - version = prompter.prompt("What is the hotfix version? [" + defaultVersion + "]"); - - if (!"".equals(version) && (!GitFlowVersionInfo.isValidVersion(version) || !validBranchName(version))) { - getLog().info("The version is not valid."); - version = null; - } - } - } catch (PrompterException e) { - throw new MojoFailureException("hotfix-start", e); - } + version = prompter.prompt("What is the hotfix version? [" + defaultVersion + "]", this::validVersion); } else { if (StringUtils.isNotBlank(hotfixVersion) && (!GitFlowVersionInfo.isValidVersion(hotfixVersion) || !validBranchName(hotfixVersion))) { diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseMojo.java index 2831bd69..5b7314f5 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseMojo.java @@ -24,7 +24,6 @@ import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; -import org.codehaus.plexus.components.interactivity.PrompterException; import org.codehaus.plexus.util.StringUtils; /** @@ -223,19 +222,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { String version = null; if (settings.isInteractiveMode()) { - try { - while (version == null) { - version = prompter.prompt("What is release version? [" + defaultVersion + "]"); - - if (!"".equals(version) - && (!GitFlowVersionInfo.isValidVersion(version) || !validBranchName(version))) { - getLog().info("The version is not valid."); - version = null; - } - } - } catch (PrompterException e) { - throw new MojoFailureException("release", e); - } + version = prompter.prompt("What is release version? [" + defaultVersion + "]", this::validVersion); } else { version = releaseVersion; } diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseStartMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseStartMojo.java index f3717adc..a4684eca 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseStartMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowReleaseStartMojo.java @@ -25,7 +25,6 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.shared.release.versions.VersionParseException; -import org.codehaus.plexus.components.interactivity.PrompterException; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.cli.CommandLineException; @@ -278,19 +277,7 @@ private String getReleaseVersion() throws MojoFailureException, VersionParseExce String version = null; if (settings.isInteractiveMode()) { - try { - while (version == null) { - version = prompter.prompt("What is release version? [" + defaultVersion + "]"); - - if (!"".equals(version) - && (!GitFlowVersionInfo.isValidVersion(version) || !validBranchName(version))) { - getLog().info("The version is not valid."); - version = null; - } - } - } catch (PrompterException e) { - throw new MojoFailureException("release-start", e); - } + version = prompter.prompt("What is release version? [" + defaultVersion + "]", this::validVersion); } else { version = releaseVersion; } diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowSupportStartMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowSupportStartMojo.java index 800f3b45..70c124e0 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowSupportStartMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowSupportStartMojo.java @@ -25,7 +25,6 @@ import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; -import org.codehaus.plexus.components.interactivity.PrompterException; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.cli.CommandLineException; @@ -90,11 +89,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { throw new MojoFailureException("There are no tags."); } - try { - tag = prompter.prompt("Choose tag to start support branch", Arrays.asList(tagsStr.split("\\r?\\n"))); - } catch (PrompterException e) { - throw new MojoFailureException("support-start", e); - } + tag = prompter.prompt("Choose tag to start support branch", Arrays.asList(tagsStr.split("\\r?\\n"))); } else if (StringUtils.isNotBlank(tagName)) { if (gitCheckTagExists(tagName)) { tag = tagName; diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowVersionUpdateMojo.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowVersionUpdateMojo.java index 205e36cc..2468cb34 100644 --- a/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowVersionUpdateMojo.java +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/GitFlowVersionUpdateMojo.java @@ -15,9 +15,7 @@ */ package com.amashchenko.maven.plugin.gitflow; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import org.apache.maven.plugin.MojoExecutionException; @@ -25,7 +23,6 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.shared.release.versions.VersionParseException; -import org.codehaus.plexus.components.interactivity.PrompterException; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.cli.CommandLineException; @@ -125,27 +122,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { branches[supportBranches.length] = releaseBranch; } - List numberedList = new ArrayList<>(); - StringBuilder str = new StringBuilder("Branches:").append(LS); - for (int i = 0; i < branches.length; i++) { - str.append((i + 1) + ". " + branches[i] + LS); - numberedList.add(String.valueOf(i + 1)); - } - str.append("Choose branch to update"); - - String branchNumber = null; - try { - while (StringUtils.isBlank(branchNumber)) { - branchNumber = prompter.prompt(str.toString(), numberedList); - } - } catch (PrompterException e) { - throw new MojoFailureException("version-update", e); - } - - if (branchNumber != null) { - int num = Integer.parseInt(branchNumber); - branchName = branches[num - 1]; - } + branchName = prompter.prompt(branches, null, "Branches:", "Choose branch to update"); } } else if (StringUtils.isNotBlank(fromBranch)) { if (fromBranch.equals(releaseBranch) || contains(supportBranches, fromBranch)) { @@ -178,18 +155,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { String version = null; if (settings.isInteractiveMode()) { - try { - while (version == null) { - version = prompter.prompt("What is the update version? [" + defaultVersion + "]"); - - if (!"".equals(version) && (!GitFlowVersionInfo.isValidVersion(version) || !validBranchName(version))) { - getLog().info("The version is not valid."); - version = null; - } - } - } catch (PrompterException e) { - throw new MojoFailureException("version-update", e); - } + version = prompter.prompt("What is the update version? [" + defaultVersion + "]", this::validVersion); } else { if (StringUtils.isNotBlank(updateVersion) && (!GitFlowVersionInfo.isValidVersion(updateVersion) || !validBranchName(updateVersion))) { diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/prompter/ConsolePrompter.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/prompter/ConsolePrompter.java new file mode 100644 index 00000000..dfff91a8 --- /dev/null +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/prompter/ConsolePrompter.java @@ -0,0 +1,119 @@ +/* + * Copyright 2014-2023 Aleksandr Mashchenko. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.amashchenko.maven.plugin.gitflow.prompter; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.apache.maven.plugin.MojoFailureException; +import org.codehaus.plexus.components.interactivity.Prompter; +import org.codehaus.plexus.components.interactivity.PrompterException; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.cli.CommandLineException; + +/** + * Default prompter which uses console for input. + * + */ +@Named +@Singleton +public class ConsolePrompter implements GitFlowPrompter { + private static final String LS = System.getProperty("line.separator"); + + private final Prompter prompter; + + @Inject + public ConsolePrompter(Prompter prompter) { + this.prompter = prompter; + } + + /** + * {@inheritDoc} + */ + @Override + public String prompt(String[] choices, final String defaultChoice, String preMessage, String postMessage) throws MojoFailureException { + List numberedList = new ArrayList<>(); + String defChoice = null; + StringBuilder str = new StringBuilder(preMessage).append(LS); + for (int i = 0; i < choices.length; i++) { + str.append(i + 1).append(". ").append(choices[i]).append(LS); + numberedList.add(String.valueOf(i + 1)); + if (choices[i].equals(defaultChoice)) { + defChoice = String.valueOf(i + 1); + } + } + str.append(postMessage); + + String response = null; + try { + while (StringUtils.isBlank(response)) { + if (defaultChoice == null || defChoice == null) { + response = prompter.prompt(str.toString(), numberedList); + } else { + response = prompter.prompt(str.toString(), numberedList, defChoice); + } + } + } catch (PrompterException e) { + throw new MojoFailureException("prompter error", e); + } + + String result = null; + if (response != null) { + int num = Integer.parseInt(response); + result = choices[num - 1]; + } + + return result; + } + + /** + * {@inheritDoc} + */ + @Override + public String prompt(String message, PromptValidation validation) throws MojoFailureException, CommandLineException { + String response = null; + try { + while (response == null) { + response = prompter.prompt(message); + + if (!validation.valid(response)) { + response = null; + } + } + } catch (PrompterException e) { + throw new MojoFailureException("prompter error", e); + } + return response; + } + + /** + * {@inheritDoc} + */ + @Override + public String prompt(String message, List choices) throws MojoFailureException { + String response = null; + try { + response = prompter.prompt(message, choices); + } catch (PrompterException e) { + throw new MojoFailureException("prompter error", e); + } + return response; + } +} diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/prompter/GitFlowPrompter.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/prompter/GitFlowPrompter.java new file mode 100644 index 00000000..f7994ca3 --- /dev/null +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/prompter/GitFlowPrompter.java @@ -0,0 +1,72 @@ +/* + * Copyright 2014-2023 Aleksandr Mashchenko. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.amashchenko.maven.plugin.gitflow.prompter; + +import java.util.List; + +import org.apache.maven.plugin.MojoFailureException; +import org.codehaus.plexus.util.cli.CommandLineException; + +/** + * Git flow prompter interface. + * + */ +public interface GitFlowPrompter { + /** + * Prompts with predefined choices. + * + * @param choices + * Predefined list of choices. + * @param defaultChoice + * The default choice to use. + * @param preMessage + * Text to display before prompt. + * @param postMessage + * Text to display after prompt. + * @return Response obtained from prompting. + * @throws MojoFailureException + * If error happens during prompting. + */ + String prompt(String[] choices, String defaultChoice, String preMessage, String postMessage) throws MojoFailureException; + + /** + * Prompts and validates the response. + * + * @param message + * Text to display on prompt. + * @param validation + * Validation function to validate prompt response. + * @return Response obtained from prompting. + * @throws MojoFailureException + * If error happens during prompting. + * @throws CommandLineException + * If error happens during validation. + */ + String prompt(String message, PromptValidation validation) throws MojoFailureException, CommandLineException; + + /** + * Prompts with predefined choices. + * + * @param message + * Text to display on prompt. + * @param choices + * Predefined list of choices. + * @return Response obtained from prompting. + * @throws MojoFailureException + * If error happens during prompting. + */ + String prompt(String message, List choices) throws MojoFailureException; +} diff --git a/src/main/java/com/amashchenko/maven/plugin/gitflow/prompter/PromptValidation.java b/src/main/java/com/amashchenko/maven/plugin/gitflow/prompter/PromptValidation.java new file mode 100644 index 00000000..fa1d4271 --- /dev/null +++ b/src/main/java/com/amashchenko/maven/plugin/gitflow/prompter/PromptValidation.java @@ -0,0 +1,42 @@ +/* + * Copyright 2014-2023 Aleksandr Mashchenko. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.amashchenko.maven.plugin.gitflow.prompter; + +import org.apache.maven.plugin.MojoFailureException; +import org.codehaus.plexus.util.cli.CommandLineException; + +/** + * Functional interface to validate prompt response. + * + * @param + * Type of the response to validate. + */ +@FunctionalInterface +public interface PromptValidation { + /** + * Validates prompt response. + * + * @param t + * Response to validate. + * @return true when response is valid, false + * otherwise. + * @throws MojoFailureException + * If validation fails. + * @throws CommandLineException + * If validation fails. + */ + boolean valid(T t) throws MojoFailureException, CommandLineException; +} From 35ada462a76142ef13998118459909aa9e922e3e Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Mon, 25 Dec 2023 13:44:24 +0200 Subject: [PATCH 31/37] Fix running some tests --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index 2eb27927..155e6232 100644 --- a/pom.xml +++ b/pom.xml @@ -119,6 +119,11 @@ maven-site-plugin 3.12.1 + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.3 + org.apache.maven.plugins maven-plugin-plugin From b6c391f287c4b02de7effebdf62fa0f2ce3d2a4f Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Mon, 25 Dec 2023 13:57:33 +0200 Subject: [PATCH 32/37] 1.21.0 release --- CHANGELOG.md | 5 +++++ README.md | 2 +- pom.xml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4810606a..fec40951 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## v1.21.0 (2023-12-25) + +* Updated Java minimum version to 8 - [#369](https://github.com/aleksandr-m/gitflow-maven-plugin/issues/369) +* Added console prompter wrapper + ## v1.20.0 (2023-06-01) * Fixed creation of the release branch in `hotfix-finish` goal - [#391](https://github.com/aleksandr-m/gitflow-maven-plugin/issues/391) diff --git a/README.md b/README.md index e6a0fc6c..80c26553 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ The plugin is available from Maven Central. com.amashchenko.maven.plugin gitflow-maven-plugin - 1.20.0 + 1.21.0 diff --git a/pom.xml b/pom.xml index 155e6232..8f49761f 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ gitflow-maven-plugin maven-plugin gitflow-maven-plugin - 1.20.1-SNAPSHOT + 1.21.0 The Git-Flow Maven Plugin supports various Git workflows, including Vincent Driessen's successful Git branching model and GitHub Flow. This plugin runs Git and Maven commands from the command line. Supports Eclipse Plugins build with Tycho. From 5b7af1aa2eae20c4310349f0bfd3615802fcfc24 Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Mon, 25 Dec 2023 14:14:20 +0200 Subject: [PATCH 33/37] Next development version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8f49761f..a6498397 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ gitflow-maven-plugin maven-plugin gitflow-maven-plugin - 1.21.0 + 1.21.1-SNAPSHOT The Git-Flow Maven Plugin supports various Git workflows, including Vincent Driessen's successful Git branching model and GitHub Flow. This plugin runs Git and Maven commands from the command line. Supports Eclipse Plugins build with Tycho. From 444ac422851c32b8972c6fcaf8f16634842c1cae Mon Sep 17 00:00:00 2001 From: Aleksandr Mashchenko Date: Sat, 10 Feb 2024 15:19:45 +0200 Subject: [PATCH 34/37] Update copyright notice --- pom.xml | 2 +- .../amashchenko/maven/plugin/gitflow/AbstractGitFlowMojo.java | 2 +- .../com/amashchenko/maven/plugin/gitflow/CommitMessages.java | 2 +- .../com/amashchenko/maven/plugin/gitflow/GitFlowConfig.java | 2 +- .../maven/plugin/gitflow/GitFlowFeatureFinishMojo.java | 2 +- .../maven/plugin/gitflow/GitFlowFeatureStartMojo.java | 2 +- .../maven/plugin/gitflow/GitFlowHotfixFinishMojo.java | 2 +- .../maven/plugin/gitflow/GitFlowHotfixStartMojo.java | 2 +- .../maven/plugin/gitflow/GitFlowReleaseFinishMojo.java | 2 +- .../amashchenko/maven/plugin/gitflow/GitFlowReleaseMojo.java | 2 +- .../maven/plugin/gitflow/GitFlowReleaseStartMojo.java | 2 +- .../maven/plugin/gitflow/GitFlowSupportStartMojo.java | 2 +- .../amashchenko/maven/plugin/gitflow/GitFlowVersionInfo.java | 2 +- .../maven/plugin/gitflow/GitFlowVersionUpdateMojo.java | 2 +- .../maven/plugin/gitflow/StringBufferStreamConsumer.java | 2 +- .../maven/plugin/gitflow/prompter/ConsolePrompter.java | 2 +- .../maven/plugin/gitflow/prompter/GitFlowPrompter.java | 2 +- .../maven/plugin/gitflow/prompter/PromptValidation.java | 2 +- .../amashchenko/maven/plugin/gitflow/FeatureVersionTest.java | 2 +- .../maven/plugin/gitflow/GitFlowVersionInfoTest.java | 2 +- .../amashchenko/maven/plugin/gitflow/NextHotfixVersionTest.java | 2 +- .../maven/plugin/gitflow/NextSnapshotVersionTest.java | 2 +- .../maven/plugin/gitflow/ValidateConfigurationTest.java | 2 +- 23 files changed, 23 insertions(+), 23 deletions(-) diff --git a/pom.xml b/pom.xml index a6498397..a7bd33fa 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ - - - - - - -# Goals Overview - -- `gitflow:release-start` - Starts a release branch and updates version(s) to release version. -- `gitflow:release-finish` - Merges a release branch and updates version(s) to next development version. -- `gitflow:release` - Releases project w/o creating a release branch. -- `gitflow:feature-start` - Starts a feature branch and optionally updates version(s). -- `gitflow:feature-finish` - Merges a feature branch. -- `gitflow:hotfix-start` - Starts a hotfix branch and updates version(s) to hotfix version. -- `gitflow:hotfix-finish` - Merges a hotfix branch. -- `gitflow:support-start` - Starts a support branch from the production tag. -- `gitflow:version-update` - Updates version in release or support branch, optionally tagging and pushing it to the remote repository. -- `gitflow:help` - Displays help information. - - -# Git Workflows - -The gitflow-maven-plugin is very versatile. It can be easily configured to use different Git workflows. - -## GitHub Flow - -The GitHub Flow is a lightweight, branch-based workflow that supports teams and projects where deployments are made regularly. - -To configure this plugin to use single branch model, such as GitHub Flow, just set the `developmentBranch` parameter to the same value as the `productionBranch` in your pom.xml file. - - - master - - -That's it! - - -# Maven Wrapper support - -The plugin will automatically use Maven Wrapper for internal Maven goals if plugin is started with the wrapper. - - -# Internal Maven plugins - -The `versions-maven-plugin` and `tycho-versions-plugin` are used internally to update versions and properties of the project. To change versions of internal plugins use `versionsMavenPluginVersion` and `tychoVersionsPluginVersion` properties respectively. - -### Handling multi-module projects - -If your project consists of multiple modules with and without parent-child relationships, you have to supply additional arguments if you want to update all module versions. In case of the `versions-maven-plugin`, there is [`processAllModules`](https://www.mojohaus.org/versions-maven-plugin/set-mojo.html#processAllModules), which can be supplied as follows: - -``` -mvn gitflow: -DargLine='-DprocessAllModules' -``` - - -# Git Submodules - -The plugin looks for the `.gitmodules` file and if it exists the `git submodule update` command will be executed before each Git commit. This is needed to avoid leaving working copy in dirty state which can happen when switching between branches. -To explicitly control whether Git submodules will be updated before commit the `updateGitSubmodules` parameter can be used. Setting it to `true` will enable Git submodules update and `false` will disable it even if `.gitmodules` file exists. The default value is not set, meaning the plugin tries to automatically determine if update is needed. - - -# Eclipse Plugins build with Tycho - -Since version `1.1.0` this plugin supports Eclipse plugin projects which are build with [Tycho](https://eclipse.org/tycho/). -To enable this feature put `true` into `` section of this plugin in your pom.xml file. - -### Features of `tychoBuild` - -The [`tycho-versions-plugin`](https://eclipse.org/tycho/sitedocs/tycho-release/tycho-versions-plugin/plugin-info.html) Maven plugin will be used to set versions instead of [`versions-maven-plugin`](https://www.mojohaus.org/versions-maven-plugin/). - -Feature name will not be appended to project version on `gitflow:feature-start` goal even if the `skipFeatureVersion` is set to `false`. - -If version has qualifier then it will not be removed in the release or hotfix goals. - - -# Signing Your Work - -To sign tags and/or commits you need to configure GPG and install personal key. Read more [Git Tools - Signing Your Work](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work). - -Next you need to configure Git to use your personal key. - -``` -git config --global user.signingkey GPG_key_id -``` - -Sometimes you need to tell Git where the GPG program is. Use `gpg.program` option for that. - -``` -git config --global gpg.program "path_to_gpg" -``` - -### Signing Tags - -The `gitflow:release`, `gitflow:release-finish` and `gitflow:hotfix-finish` goals have `gpgSignTag` parameter. Set it to `true` to sign tags with configured personal key. The default value is `false`. - -### Signing Commits - -All goals have `gpgSignCommit` parameter. Set it to `true` to sign commits with configured personal key. The default value is `false`. - - -# Support for Reproducible Builds - -[Reproducible builds](https://reproducible-builds.org/) are a set of software development practices that create an independently-verifiable path from source to binary code. - -To configure your Maven build to support reproducible builds follow [official guide](https://maven.apache.org/guides/mini/guide-reproducible-builds.html). - -If your project has `project.build.outputTimestamp` property this plugin will update its value whenever the versions are updated. - -This can be disabled by setting the configuration parameter `updateOutputTimestamp` to `false`. - - -# Plugin Common Parameters - -All parameters are optional. The `gitFlowConfig` parameters defaults are the same as in the example below. -Maven and Git executables are assumed to be in the PATH, if executables are not available in the PATH or you want to use different version use `mvnExecutable` and `gitExecutable` parameters. -The `installProject` parameter controls whether the Maven `install` goal will be called during the mojo execution. The default value for this parameter is `false` (i.e. the project will NOT be installed). -Since `1.0.7` version of this plugin the output of the executed commands will NOT be printed into the console. This can be changed by setting `verbose` parameter to `true`. - - - path_to_maven_executable - path_to_git_executable - - false - false - - - master - develop - feature/ - release/ - hotfix/ - support/ - - origin - - - - - - - -## Customizing commit messages - -Since `1.2.1` commit messages can be changed in plugin's configuration section in pom.xml. Commit messages defaults are seen below. - - - - Update versions for feature branch - Update versions for development branch - - Update versions for hotfix - Update for next development version - - Update to hotfix version - - Update versions for release - Update for next development version - - Update for next development version - - - - - - - - - - - - - - - - - - Tag hotfix - Tag release - Tag version update - - - Update develop to production version to avoid merge conflicts - Update develop version back to pre-merge state - - Update release to hotfix version to avoid merge conflicts - Update release version back to pre-merge state - - Update feature branch back to feature version - Increment feature version - - Update versions for support branch - - Update versions - - - -Maven properties can be used in commit messages. For example `updating ${project.artifactId} project for feature branch` will produce message where -`${project.artifactId}` will be substituted for projects ``. - -Note that although `${project.version}` can be used, any changes to version introduced by this goal won't be reflected in a commit message for this goal (see Custom properties). - -Commit messages can be prefixed by using `commitMessagePrefix` parameter. Leading or trailing whitespaces can be preserved by using `xml:space="preserve"` attribute e.g. `[gitflow] `. - -### Custom properties in commit messages - -`@{version}` will be replaced with the updated version. - -`@{featureName}` will be replaced in `feature-` goals with the name of the current feature. - -## Maven arguments - -The `argLine` parameter can be used to pass command line arguments to the underlying Maven commands. For example, `-DcreateChecksum` in `mvn gitflow:release-start -DargLine=-DcreateChecksum` -will be passed to all underlying Maven commands. - -## Maven CI friendly versions - -Maven property can be updated with the new version by setting the `versionProperty` parameter with the property you want to update. -For example, `-DversionProperty=revision` will update the `` property defined in the project pom.xml. - -The `skipUpdateVersion` parameter can be used to skip updating `` in the pom.xml. The default value is `false` (i.e. the version will be updated). - -To support [CI friendly versioning](https://maven.apache.org/maven-ci-friendly.html) in projects which use `${revision}` set `versionProperty` to `revision` and `skipUpdateVersion` to `true`. - -## Additional goal parameters - -The `gitflow:release-finish`, `gitflow:release` and `gitflow:hotfix-finish` goals have `skipTag` parameter. This parameter controls whether the release/hotfix will be tagged in Git. -The default value is `false` (i.e. the release/hotfix will be tagged). - -The `gitflow:feature-start` goal has `skipFeatureVersion` parameter which controls whether the feature name will be appended to the project version or not. -The default value is `false` (e.g. if the project version is `1.0.0-SNAPSHOT` and feature name is `feature_name` then after the execution it will be `1.0.0-feature_name-SNAPSHOT`). - -The `gitflow:feature-start` goal has `featureNamePattern` parameter which allows to enforce naming of the feature branches with a regular expression. Doesn't have effect if it isn't set or left blank. -By default it isn't set. - -The `gitflow:feature-finish` goal has `incrementVersionAtFinish` parameter which if set to `true` will increment version number during feature finish. The default is `false`. - -All `-finish` goals have `keepBranch` parameter which controls whether created support branch will be kept in Git after the goal finishes. -The default value is `false` (i.e. the supporting branch will be deleted). If the `pushRemote` parameter is set to `true` and `keepBranch` is `false` remote branch will be deleted as well. - -All `-finish` goals and `gitflow:release` have `skipTestProject` parameter which controls whether Maven `test` goal will be called before merging branches. -The default value is `false` (i.e. the project will be tested before merging branches). - -All `release` goals have `allowSnapshots` parameter which controls whether SNAPSHOT dependencies are allowed. The default value is `false` (i.e. build fails if there SNAPSHOT dependency in project). - -The `gitflow:release-start` and `gitflow:release-finish` have `commitDevelopmentVersionAtStart` parameter which controls whether the next development version is set and committed at start or after finish. -By default the value is `false` which means that the next development version is set on the development branch after the release branch has been merged onto the development branch when finishing the release. -This has the benefit of being able to easily cancel the release process simply by deleting the release branch. -If the value is `true` then versioning happens on `gitflow:release-start`. First the project version is set to the release version on the development branch and the release branch is created. -Then the development branch is set to the next development version. -This allows the development branch to continue immediately with a new version and helps avoid any future merge conflicts related to project versioning. -Has effect only when there are separate development and production branches. - -The `gitflow:release-start` goal has `sameBranchName` parameter which can be used to use the same name for the release branch. The default value is `false`. -By itself the default `releaseBranchPrefix` is not a valid branch name. You must change it when setting `sameBranchName` to `true`. -Will have no effect if the `branchName` parameter is set. - -The `gitflow:release-start` goal has `branchName` parameter which controls how the release branch will be named. - -The `gitflow:release-start` goal has `fromCommit` parameter which allows to start the release from the specific commit (SHA). - -The `gitflow:release-start` and `gitflow:release-finish` goals have `useSnapshotInRelease` parameter which allows to start the release with SNAPSHOT version and finish it without this value in project version. By default the value is `false`. -For example, if the release version is `1.0.2` and `useSnapshotInRelease` is set to `true` and using `gitflow:release-start` goal then the release version will be `1.0.2-SNAPSHOT` and when finishing the release with `gitflow:release-finish` goal, the release version will be `1.0.2` - -The `gitflow:release` and `gitflow:release-finish` goals have `skipReleaseMergeProdBranch` parameter which prevents merging the release branch into the production branch. The default value is `false`. - -The `gitflow:release-finish` goal has `skipReleaseMergeDevBranch` parameter which prevents merging the release branch into the development branch. The default value is `false`. - -The `gitflow:hotfix-start` and `gitflow:hotfix-finish` goals have `useSnapshotInHotfix` parameter which allows to start the hotfix with SNAPSHOT version and finish it without this value in the version. By default the value is `false`. -For example, if the hotfix version is `1.0.2.1` and `useSnapshotInHotfix` is set to `true` and using `gitflow:hotfix-start` goal then the hotfix version will be `1.0.2.1-SNAPSHOT` and when finishing the release with `gitflow:hotfix-finish` goal, the release version will be `1.0.2.1` - -The `gitflow:hotfix-finish` goal supports the parameter `skipMergeDevBranch` which prevents merging the hotfix branch into the development branch. - -The `gitflow:hotfix-finish` goal supports the parameter `skipMergeProdBranch` which prevents merging the hotfix branch into the production branch and deletes the hotfix branch leaving only the tagged commit. Useful, along with `skipMergeDevBranch`, to allow hotfixes to very old code that are not applicable to current development. - -The `gitflow:release-finish` and `gitflow:hotfix-finish` goals have `noBackMerge` and `noBackMergeHotfix` parameters respectively. They control which branch is merged to development branch. If set to `true` then release or hotfix branch will be merged to development branch. If set to `false` and tag is present (`skipTag` parameter is set to `false`) then tag will be merged. If there is no tag then production branch will be merged to development branch. - -The `gitflow:release` goal has `noBackMerge` parameter, which controls which branch is merged to development branch. If set to `true` then merge will be skipped. If set to `false` and tag is present (`skipTag` is set to `false`) then tag will be merged. If there is no tag then production branch will be merged to development branch. - -### Versioning - -The `gitflow:release-finish` and `gitflow:release` goals have `digitsOnlyDevVersion` parameter which will remove qualifiers from the next development version if set to `true`. -For example, if the release version is `1.0.0-Final` then development version will be `1.0.1-SNAPSHOT`. -The default value is `false` (i.e. qualifiers will be preserved in next development version). - -The `gitflow:release-finish` and `gitflow:release` goals have `versionDigitToIncrement` parameter which controls which digit to increment in the next development version. Starts from zero. -For example, if the release version is `1.2.3.4` and `versionDigitToIncrement` is set to `1` then the next development version will be `1.3.0.0-SNAPSHOT`. -If not set or set to not valid value defaults to increment last digit in the version. - -The `gitflow:hotfix-start` goal has `hotfixVersionDigitToIncrement` parameter which controls which digit to increment in the hotfix version. Starts from zero. - -Versioninig can be controlled by using [Maven version policy](https://maven.apache.org/maven-release/maven-release-api/apidocs/org/apache/maven/shared/release/policy/version/VersionPolicy.html) implementation. Create appropriate implementation and add it as dependency to the project, use `projectVersionPolicyId` parameter to set policy id to use. If policy is set then other parameters controlling the generation of version are ignored (i.e. `digitsOnlyDevVersion`, `versionDigitToIncrement`). - -Version update of all modules ignoring groupId and artifactId can be forced by setting `versionsForceUpdate` parameter to `true`. The default value is `false`. - -### Remote interaction - -At the start of the each goal remote branch(es) will be fetched and compared with the local branch(es). If the local branch doesn't exist it will be checked out from the remote. -Both of these options can be turned off by setting `fetchRemote` parameter to `false`. - -At the end of the `-finish` goals development or production and development branches will be pushed to remote. This can be turned off by setting `pushRemote` parameter to `false`. - -At the end of the `-start` goals newly created branch (release / feature / hotfix) can be pushed to the remote. This can be achieved by setting `pushRemote` parameter to `true`. - -The default remote name is `origin`. It can be customized with `custom_origin` configuration in pom.xml. - -Git [push-options](https://git-scm.com/docs/git-push#Documentation/git-push.txt--oltoptiongt) can be added to push command with the `gitPushOptions` parameter. Multiple options can be added separated with a space e.g. `-DgitPushOptions="merge_request.create merge_request.target=develop merge_request.label='Super feature'"`. - -### Rebase, Merge, Fast Forward, Squash - -Release branch can be rebased instead of merged by setting `releaseRebase` parameter to `true`. The default value is `false` (i.e. merge will be performed). - -Release branch can be merged without `--no-ff` option by setting `releaseMergeNoFF` parameter to `false`. The default value is `true` (i.e. `merge --no-ff` will be performed). -The `releaseMergeNoFF` parameter has no effect when `releaseRebase` parameter is set to `true`. - -Release branch can be merged with `--ff-only` option by setting `releaseMergeFFOnly` parameter to `true`. The default value is `false` (i.e. The `--ff-only` option won't be used). - -Feature branch can be squashed before merging by setting `featureSquash` parameter to `true`. The default value is `false` (i.e. merge w/o squash will be performed). - -### Running custom Maven goals - -The `preFeatureFinishGoals` parameter can be used in `gitflow:feature-finish` goal to run defined Maven goals before the finishing and merging a feature. -E.g. `mvn gitflow:feature-finish -DpreFeatureFinishGoals=test` will run `mvn test` goal in the feature branch before merging into the development branch. - -The `postFeatureFinishGoals` parameter can be used in `gitflow:feature-finish` goal to run defined Maven goals after merging a feature. -E.g. `mvn gitflow:feature-finish -postFeatureFinishGoals=test` will run `mvn test` goal in the development branch after merging a feature. - -The `preReleaseGoals` parameter can be used in `gitflow:release-finish` and `gitflow:release` goals to run defined Maven goals before the release. -E.g. `mvn gitflow:release-finish -DpreReleaseGoals=test` will run `mvn test` goal in the release branch before merging into the production branch. - -The `postReleaseGoals` parameter can be used in `gitflow:release-finish` and `gitflow:release` goals to run defined Maven goals after the release. -E.g. `mvn gitflow:release-finish -DpostReleaseGoals=deploy` will run `mvn deploy` goal in the production branch after the release. - -The `gitflow:hotfix-finish` goal has `preHotfixGoals` and `postHotfixGoals` parameters which can be used to run defined Maven goals before and after the hotfix respectively. - -# Non-interactive Mode - -Maven can be run in non-interactive (batch) mode. By using non-interactive mode goals can be run in continuous integration environment. -To put Maven in the batch mode use `-B` or `--batch-mode` option. - -## Non-interactive Release - -Releases could be performed without prompting for the release version during `gitflow:release-start` or `gitflow:release` goals by telling Maven to run in non-interactive (batch) mode. -The `releaseVersion` parameter can be used to set the release version in non-interactive mode. If `releaseVersion` parameter is not set then the default release version will be used. - - mvn -B gitflow:release-start gitflow:release-finish - -To release w/o creating separate release branch use `gitflow:release` goal. - - mvn -B gitflow:release - -This gives the ability to perform releases in non-interactive mode (e.g. in CI server). - -The `gitflow:release-finish` and `gitflow:release` goals have `developmentVersion` parameter which can be used to set the next development version in non-interactive mode. - -## Non-interactive Feature - -The `gitflow:feature-start` and `gitflow:feature-finish` goals have `featureName` parameter which can be used to set a name of the feature in non-interactive mode. - -The `gitflow:feature-finish` goal has `featureBranch` parameter which can be used to set feature branch name in non-interactive mode. It must start with the feature branch prefix. The `featureBranch` will be used instead of `featureName` if both are set. - -## Non-interactive Hotfix - -The `gitflow:hotfix-start` goal has `fromBranch` parameter which can be used to set starting branch of the hotfix. It can be set to production branch or one of the support branches. -If it is left blank then hotfix will be started from the production branch. - -The `gitflow:hotfix-start` and `gitflow:hotfix-finish` goals have `hotfixVersion` parameter which can be used to set version of the hotfix. -If it is left blank in `gitflow:hotfix-start` goal then the default version will be used. - -The `gitflow:hotfix-finish` goal has `hotfixBranch` parameter which can be used to set hotfix branch name in non-interactive mode. It must start with the hotfix branch prefix. The `hotfixBranch` will be used instead of `hotfixVersion` if both are set. - -## Non-interactive Support - -The `gitflow:support-start` goal can be run in non-interactive mode. Use `tagName` parameter to set tag from which supporting branch will be started. -If `tagName` is not set but the goal is running in non-interactive mode then the last tag will be used. - -The `gitflow:support-start` goal has `supportBranchName` parameter which can be used to set branch name to use instead of the default. - -The `gitflow:support-start` goal has `useSnapshotInSupport` parameter which allows to start the support with SNAPSHOT version.