├── .github
└── ISSUE_TEMPLATE
│ └── bug_report.md
├── .gitignore
├── LICENSE
├── README.md
├── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
├── main
├── java
│ └── ch
│ │ └── repnik
│ │ └── intellij
│ │ ├── CommitPrefixCheckinHandler.java
│ │ ├── GitBaseCheckinHandlerFactory.java
│ │ └── settings
│ │ ├── PluginConfigService.java
│ │ ├── PluginSettingsForm.form
│ │ ├── PluginSettingsForm.java
│ │ ├── Position.java
│ │ └── TicketSystem.java
└── resources
│ └── META-INF
│ └── plugin.xml
└── test
└── java
└── ch
└── repnik
└── intellij
└── CommitPrefixCheckinHandlerTest.java
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | ### Affected Application:
11 | - Product: [e.g. IntelliJ]
12 | - Version [e.g. 2020.3]
13 |
14 | ### Describe the bug
15 | A clear and concise description of what the bug is.
16 |
17 | ### To Reproduce
18 | Steps to reproduce the behavior:
19 | 1. Go to '...'
20 | 2. Click on '....'
21 | 3. Scroll down to '....'
22 | 4. See error
23 |
24 | ### Expected behavior
25 | A clear and concise description of what you expected to happen.
26 |
27 | ### Screenshots
28 | If applicable, add screenshots to help explain your problem.
29 |
30 | ### Stacktraces
31 | If applicable, add stacktraces to help analyze your problem.
32 |
33 | ### Additional context
34 | Add any other context about the problem here.
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | .idea
3 | build
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Thomas Repnik
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Git Auto Prefix (IntelliJ Plugin)
2 | Automatically set the issue key (of the current branch name) as prefix for the commit message
3 |
4 | **Important:** This plugin only works with branches named as follows
5 | - Jira format with alphanumeric project keys (ABC-1234)
6 | - Jira format with numeric project keys (1234-5678)
7 | - Other format that is all numbers (123456)
8 |
9 | ## Installation
10 | Plugin can be downloaded whithin IntelliJ or on the Jetbrains [Plugin Site](https://plugins.jetbrains.com/plugin/14238-git-auto-prefix)
11 |
12 | ## Features
13 | * Automatically change the commit prefix if switching branches (also switching on cli/terminal is recognized)
14 | * If intellij is suggesting a (previous) commit message, only the prefix will be updated
15 | * Set your custom delimiter between the issue key and the commit message (Default ": ")
16 | * Wrap the issue key as you like
17 |
18 | ## Samples
19 | Following prefix for commit messages will automatically be generated:
20 |
21 | | Branch name | Commit prefix (with delimiter) | Commit prefix (wrapped) |
22 | |----------------------------------------|--------------------------------|--------------------------|
23 | | main | no action | no action |
24 | | master | no action | no action |
25 | | bugfix/ABC-1234-app-not-working | ABC-1234: | [ABC-1234] |
26 | | feature/ABC-1234-app-not-working | ABC-1234: | [ABC-1234] |
27 | | release/ABC-1234-app-not-working | ABC-1234: | [ABC-1234] |
28 | | someOtherType/ABC-1234-app-not-working | ABC-1234: | [ABC-1234] |
29 | | ABC-1234-app-not-working | ABC-1234: | [ABC-1234] |
30 | | ABC-1234 | ABC-1234: | [ABC-1234] |
31 | | 12345-app-not-working | 12345: | [12345] |
32 |
33 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java'
3 | id 'org.jetbrains.intellij' version '1.16.0'
4 | }
5 |
6 | group 'ch.repnik'
7 | version '1.4.1'
8 |
9 | repositories {
10 | mavenCentral()
11 | }
12 |
13 | dependencies {
14 | testImplementation 'org.hamcrest:hamcrest:2.2'
15 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.3'
16 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.3'
17 | testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.3'
18 | testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.10.3'
19 | testCompileOnly 'org.projectlombok:lombok:1.18.34'
20 | testAnnotationProcessor 'org.projectlombok:lombok:1.18.34'
21 |
22 | }
23 |
24 | java {
25 | sourceCompatibility = JavaVersion.VERSION_17
26 | targetCompatibility = JavaVersion.VERSION_17
27 | }
28 |
29 | test {
30 | useJUnitPlatform()
31 | testLogging {
32 | events "passed", "skipped", "failed"
33 | }
34 | }
35 |
36 | // See https://github.com/JetBrains/gradle-intellij-plugin/
37 | intellij {
38 | version.set('2023.2.4')
39 | plugins = ['Git4Idea']
40 | }
41 |
42 | runPluginVerifier{
43 | ideVersions = ["IC-2023.2.4"]
44 | }
45 |
46 | patchPluginXml {
47 | sinceBuild.set("232")
48 | untilBuild.set("")
49 | }
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thomasrepnik/idea-commit-prefix-plugin/b2f9b38d1812c5d5590bfb504c272dcb24a24e01/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84 |
85 | APP_NAME="Gradle"
86 | APP_BASE_NAME=${0##*/}
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | MAX_FD=$( ulimit -H -n ) ||
147 | warn "Could not query maximum file descriptor limit"
148 | esac
149 | case $MAX_FD in #(
150 | '' | soft) :;; #(
151 | *)
152 | ulimit -n "$MAX_FD" ||
153 | warn "Could not set maximum file descriptor limit to $MAX_FD"
154 | esac
155 | fi
156 |
157 | # Collect all arguments for the java command, stacking in reverse order:
158 | # * args from the command line
159 | # * the main class name
160 | # * -classpath
161 | # * -D...appname settings
162 | # * --module-path (only if needed)
163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
164 |
165 | # For Cygwin or MSYS, switch paths to Windows format before running java
166 | if "$cygwin" || "$msys" ; then
167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
169 |
170 | JAVACMD=$( cygpath --unix "$JAVACMD" )
171 |
172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
173 | for arg do
174 | if
175 | case $arg in #(
176 | -*) false ;; # don't mess with options #(
177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
178 | [ -e "$t" ] ;; #(
179 | *) false ;;
180 | esac
181 | then
182 | arg=$( cygpath --path --ignore --mixed "$arg" )
183 | fi
184 | # Roll the args list around exactly as many times as the number of
185 | # args, so each arg winds up back in the position where it started, but
186 | # possibly modified.
187 | #
188 | # NB: a `for` loop captures its iteration list before it begins, so
189 | # changing the positional parameters here affects neither the number of
190 | # iterations, nor the values presented in `arg`.
191 | shift # remove old arg
192 | set -- "$@" "$arg" # push replacement arg
193 | done
194 | fi
195 |
196 | # Collect all arguments for the java command;
197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
198 | # shell script including quotes and variable substitutions, so put them in
199 | # double quotes to make sure that they get re-expanded; and
200 | # * put everything else in single quotes, so that it's not re-expanded.
201 |
202 | set -- \
203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
204 | -classpath "$CLASSPATH" \
205 | org.gradle.wrapper.GradleWrapperMain \
206 | "$@"
207 |
208 | # Stop when "xargs" is not available.
209 | if ! command -v xargs >/dev/null 2>&1
210 | then
211 | die "xargs is not available"
212 | fi
213 |
214 | # Use "xargs" to parse quoted args.
215 | #
216 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
217 | #
218 | # In Bash we could simply go:
219 | #
220 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
221 | # set -- "${ARGS[@]}" "$@"
222 | #
223 | # but POSIX shell has neither arrays nor command substitution, so instead we
224 | # post-process each arg (as a line of input to sed) to backslash-escape any
225 | # character that might be a shell metacharacter, then use eval to reverse
226 | # that process (while maintaining the separation between arguments), and wrap
227 | # the whole thing up as a single "set" statement.
228 | #
229 | # This will of course break if any of these variables contains a newline or
230 | # an unmatched quote.
231 | #
232 |
233 | eval "set -- $(
234 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
235 | xargs -n1 |
236 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
237 | tr '\n' ' '
238 | )" '"$@"'
239 |
240 | exec "$JAVACMD" "$@"
241 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if %ERRORLEVEL% equ 0 goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if %ERRORLEVEL% equ 0 goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | set EXIT_CODE=%ERRORLEVEL%
84 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
85 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
86 | exit /b %EXIT_CODE%
87 |
88 | :mainEnd
89 | if "%OS%"=="Windows_NT" endlocal
90 |
91 | :omega
92 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'commit-prefix-plugin'
2 |
3 |
--------------------------------------------------------------------------------
/src/main/java/ch/repnik/intellij/CommitPrefixCheckinHandler.java:
--------------------------------------------------------------------------------
1 | package ch.repnik.intellij;
2 |
3 | import static ch.repnik.intellij.settings.TicketSystem.JIRA;
4 |
5 | import ch.repnik.intellij.settings.PluginConfigService;
6 | import ch.repnik.intellij.settings.Position;
7 | import ch.repnik.intellij.settings.TicketSystem;
8 | import com.intellij.dvcs.DvcsUtil;
9 | import com.intellij.openapi.application.ApplicationManager;
10 | import com.intellij.openapi.diagnostic.Logger;
11 | import com.intellij.openapi.project.Project;
12 | import com.intellij.openapi.vcs.CheckinProjectPanel;
13 | import com.intellij.openapi.vcs.ProjectLevelVcsManager;
14 | import com.intellij.openapi.vcs.checkin.CheckinHandler;
15 | import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl;
16 | import com.intellij.openapi.vcs.ui.RefreshableOnComponent;
17 | import com.intellij.psi.PsiDocumentManager;
18 | import com.intellij.psi.impl.PsiDocumentManagerImpl;
19 | import com.intellij.util.messages.MessageBusConnection;
20 | import git4idea.GitLocalBranch;
21 | import git4idea.branch.GitBranchUtil;
22 | import git4idea.repo.GitRepository;
23 | import git4idea.repo.GitRepositoryChangeListener;
24 | import org.jetbrains.annotations.NotNull;
25 | import org.jetbrains.annotations.Nullable;
26 |
27 | import java.util.Optional;
28 | import java.util.regex.Matcher;
29 | import java.util.regex.Pattern;
30 |
31 | public class CommitPrefixCheckinHandler extends CheckinHandler implements GitRepositoryChangeListener {
32 |
33 | private final Logger log = Logger.getInstance(getClass());
34 | private final CheckinProjectPanel panel;
35 | private static final Pattern jiraBranchNamePattern =
36 | Pattern.compile("(?<=\\/)*([A-Za-z0-9]+-[0-9]+)");
37 | private static final Pattern otherBranchNamePattern = Pattern.compile("(?<=\\/)*(\\d+)");
38 | private static final Pattern jiraPrefixPattern = Pattern.compile("[A-Za-z0-9]+-[0-9]+");
39 | private static final Pattern otherPrefixPattern = Pattern.compile("\\d+");
40 |
41 | public CommitPrefixCheckinHandler(CheckinProjectPanel panel) {
42 | this.panel = panel;
43 |
44 | MessageBusConnection connect = panel.getProject().getMessageBus().connect();
45 | connect.subscribe(GitRepository.GIT_REPO_CHANGE, this);
46 |
47 | // Sets the new message on the new commit UI
48 | updateCommitMessage();
49 | }
50 |
51 | private void updateCommitMessage() {
52 | ApplicationManager.getApplication().invokeLater(() -> {
53 | PsiDocumentManager psiInstance = PsiDocumentManager.getInstance(this.panel.getProject());
54 | if (psiInstance instanceof PsiDocumentManagerImpl) {
55 | if (!((PsiDocumentManagerImpl) psiInstance).isCommitInProgress()) {
56 | panel.setCommitMessage(getNewCommitMessage());
57 | } else {
58 | log.info("PsiDocumentManager reported commit in progress. Skipping Git Auto Prefix");
59 | }
60 | } else {
61 | log.info("PsiDocumentManager is not an instance of PsiDocumentManagerImpl. Skipping Git Auto Prefix");
62 | }
63 | });
64 | }
65 |
66 | @Nullable
67 | @Override
68 | public RefreshableOnComponent getBeforeCheckinConfigurationPanel() {
69 | // Sets the new message on the old commit UI
70 | updateCommitMessage();
71 | return super.getBeforeCheckinConfigurationPanel();
72 | }
73 |
74 | private String getNewCommitMessage() {
75 | String branchName = extractBranchName();
76 | // log.warn("BranchName: " + branchName);
77 |
78 | Optional ticketName = getTicket(getTicketSystem(), branchName);
79 |
80 | if (ticketName.isPresent()) {
81 | // Sets the value for the new Panel UI
82 | return updatePrefix(ticketName.get(), panel.getCommitMessage(), getTicketSystem(), getWrapLeft(), getWrapRight(), getIssueKeyPosition());
83 | }
84 |
85 | return panel.getCommitMessage();
86 | }
87 |
88 | static Optional getTicket(TicketSystem ticketSystem, String branchName) {
89 | Pattern branchNamePattern =
90 | ticketSystem == JIRA ? jiraBranchNamePattern : otherBranchNamePattern;
91 | Matcher matcher = branchNamePattern.matcher(branchName);
92 | if (matcher.find()){
93 | return Optional.ofNullable(matcher.group(1));
94 | }else{
95 | return Optional.empty();
96 | }
97 | }
98 |
99 | static String rTrim(String input) {
100 | int i = input.length() - 1;
101 | while (i >= 0 && Character.isWhitespace(input.charAt(i))) {
102 | i--;
103 | }
104 | return input.substring(0, i + 1);
105 | }
106 |
107 | static String lTrim(String input) {
108 | int i = 0;
109 | while (i <= input.length() - 1 && Character.isWhitespace(input.charAt(i))) {
110 | i++;
111 | }
112 | return input.substring(i, input.length());
113 | }
114 |
115 | static String updatePrefix(String newPrefix, String currentMessage, TicketSystem ticketSystem, String wrapLeft, String wrapRight, Position issueKeyPosition) {
116 | if (currentMessage == null || currentMessage.trim().isEmpty()) {
117 | return wrapLeft + newPrefix + wrapRight;
118 | }
119 |
120 | Pattern prefixPattern = ticketSystem == JIRA ? jiraPrefixPattern : otherPrefixPattern;
121 |
122 | return updatePrefix(
123 | newPrefix, currentMessage, wrapLeft, wrapRight, issueKeyPosition, prefixPattern);
124 | }
125 |
126 | private static String updatePrefix(String newPrefix, String currentMessage, String wrapLeft, String wrapRight,
127 | Position issueKeyPosition, Pattern prefixPattern) {
128 | // If there is already a commit message with a matching prefix only replace the prefix
129 | Matcher matcher = prefixPattern.matcher(currentMessage);
130 | Matcher foundLastMatch = null;
131 |
132 | if (issueKeyPosition == Position.END) {
133 | foundLastMatch = selectLastMatch(matcher, prefixPattern, currentMessage);
134 | }
135 |
136 | if (issueKeyPosition == Position.START && matcher.find() &&
137 | subString(currentMessage,0, matcher.start()).trim().equals(wrapLeft) &&
138 | (subString(currentMessage, matcher.end(), matcher.end() + wrapRight.length()).equals(
139 | wrapRight) ||
140 | subString(currentMessage, matcher.end(), matcher.end() + wrapRight.length()).equals(rTrim(
141 | wrapRight)))
142 | ){
143 | String start = subString(currentMessage, 0, matcher.start());
144 | String end = subString(currentMessage, matcher.end() + wrapRight.length());
145 |
146 | return start + newPrefix + wrapRight + end;
147 | }else if (issueKeyPosition == Position.END && foundLastMatch.find() &&
148 | subString(currentMessage,foundLastMatch.end(), currentMessage.length()).trim().equals(
149 | wrapRight) &&
150 | (subString(currentMessage, foundLastMatch.start()- wrapLeft.length(), foundLastMatch.start()).equals(
151 | wrapLeft) ||
152 | subString(currentMessage, foundLastMatch.start()- wrapLeft.length(), foundLastMatch.start()).equals(lTrim(
153 | wrapLeft)))){
154 |
155 | String start = subString(currentMessage, 0, foundLastMatch.start());
156 | String end = subString(currentMessage, foundLastMatch.end() + wrapRight.length());
157 |
158 | return start + newPrefix + wrapRight + end;
159 |
160 | }
161 |
162 | if (issueKeyPosition == Position.START) {
163 | return wrapLeft + newPrefix + wrapRight + currentMessage;
164 | }
165 | else{
166 | return currentMessage + wrapLeft + newPrefix + wrapRight;
167 | }
168 | }
169 |
170 | private static Matcher selectLastMatch(Matcher matcher, Pattern pattern, String input) {
171 | int foundMatches = 0;
172 | while (matcher.find()) {
173 | foundMatches++;
174 | }
175 |
176 | Matcher newMatcher = pattern.matcher(input);
177 | if (foundMatches > 1) {
178 | for (int i = 1; i < foundMatches; i++) {
179 | newMatcher.find();
180 | }
181 |
182 | return newMatcher;
183 | }
184 |
185 | return pattern.matcher(input);
186 | }
187 |
188 | static String subString(String string, int start) {
189 | if (string.length() < start) {
190 | return "";
191 | } else {
192 | return string.substring(start);
193 | }
194 | }
195 |
196 | static String subString(String string, int start, int end) {
197 | if (end < start) {
198 | throw new IllegalArgumentException("start must be smaller than end");
199 | } else if (string.length() < start || start == end) {
200 | return "";
201 | } else if (string.length() < end) {
202 | return string.substring(start);
203 | } else {
204 | return string.substring(start, end);
205 | }
206 | }
207 |
208 | TicketSystem getTicketSystem() {
209 | return this.panel.getProject().getService(PluginConfigService.class).getState().getTicketSystem();
210 | }
211 |
212 | Position getIssueKeyPosition() {
213 | return this.panel.getProject().getService(PluginConfigService.class).getState().getIssueKeyPosition();
214 | }
215 |
216 | String getWrapRight() {
217 | return this.panel.getProject().getService(PluginConfigService.class).getState().getWrapRight();
218 | }
219 |
220 | String getWrapLeft() {
221 | return this.panel.getProject().getService(PluginConfigService.class).getState().getWrapLeft();
222 | }
223 |
224 | private String extractBranchName() {
225 | Project project = panel.getProject();
226 |
227 | String branch = "";
228 | ProjectLevelVcsManager instance = ProjectLevelVcsManagerImpl.getInstance(project);
229 | if (instance.checkVcsIsActive("Git")) {
230 | GitRepository currentRepository = GitBranchUtil.guessWidgetRepository(project, DvcsUtil.getSelectedFile(project));
231 | if (currentRepository != null) {
232 | GitLocalBranch currentBranch = currentRepository.getCurrentBranch();
233 |
234 | if (currentBranch != null) {
235 | // Branch name matches Ticket Name
236 | branch = currentBranch.getName().trim();
237 | }
238 | }
239 | }
240 |
241 | return branch;
242 | }
243 |
244 | @Override
245 | public void repositoryChanged(@NotNull GitRepository repository) {
246 | updateCommitMessage();
247 | }
248 | }
249 |
--------------------------------------------------------------------------------
/src/main/java/ch/repnik/intellij/GitBaseCheckinHandlerFactory.java:
--------------------------------------------------------------------------------
1 | package ch.repnik.intellij;
2 |
3 | import com.intellij.openapi.vcs.CheckinProjectPanel;
4 | import com.intellij.openapi.vcs.changes.CommitContext;
5 | import com.intellij.openapi.vcs.checkin.CheckinHandler;
6 | import com.intellij.openapi.vcs.checkin.VcsCheckinHandlerFactory;
7 | import git4idea.GitVcs;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | public class GitBaseCheckinHandlerFactory extends VcsCheckinHandlerFactory {
11 |
12 | public GitBaseCheckinHandlerFactory(){
13 | super(GitVcs.getKey());
14 | }
15 |
16 | @NotNull
17 | @Override
18 | protected CheckinHandler createVcsHandler(@NotNull CheckinProjectPanel panel, @NotNull CommitContext commitContext) {
19 | return new CommitPrefixCheckinHandler(panel);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/ch/repnik/intellij/settings/PluginConfigService.java:
--------------------------------------------------------------------------------
1 | package ch.repnik.intellij.settings;
2 |
3 | import com.intellij.openapi.components.PersistentStateComponent;
4 | import com.intellij.openapi.components.State;
5 | import com.intellij.openapi.components.Storage;
6 | import org.jetbrains.annotations.NotNull;
7 |
8 | import java.io.Serializable;
9 |
10 | @State(
11 | name = "ch.repnik.intellij.settings.PluginConfigService",
12 | storages = {
13 | @Storage(value = "git-auto-prefix.xml")
14 | }
15 | )
16 | public class PluginConfigService implements PersistentStateComponent {
17 |
18 | private Configuration configuration = new Configuration();
19 |
20 | @Override
21 | public Configuration getState() {
22 | return configuration;
23 | }
24 |
25 | @Override
26 | public void loadState(@NotNull Configuration configuration) {
27 | this.configuration = configuration;
28 | }
29 |
30 | public static class Configuration implements Serializable {
31 |
32 | private TicketSystem ticketSystem = TicketSystem.JIRA;
33 | private String wrapLeft = "";
34 | private String wrapRight = ": ";
35 | private Position issueKeyPosition = Position.START;
36 |
37 | public TicketSystem getTicketSystem() {
38 | return ticketSystem;
39 | }
40 |
41 | public void setTicketSystem(TicketSystem ticketSystem) {
42 | this.ticketSystem = ticketSystem;
43 | }
44 |
45 | public String getWrapLeft() {
46 | return wrapLeft;
47 | }
48 |
49 | public void setWrapLeft(String wrapLeft) {
50 | this.wrapLeft = wrapLeft;
51 | }
52 |
53 | public String getWrapRight() {
54 | return wrapRight;
55 | }
56 |
57 | public void setWrapRight(String wrapRight) {
58 | this.wrapRight = wrapRight;
59 | }
60 |
61 | public Position getIssueKeyPosition() {
62 | return issueKeyPosition;
63 | }
64 |
65 | public void setIssueKeyPosition(Position issueKeyPosition) {
66 | this.issueKeyPosition = issueKeyPosition;
67 | }
68 | }
69 |
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/ch/repnik/intellij/settings/PluginSettingsForm.form:
--------------------------------------------------------------------------------
1 |
2 |
148 |
--------------------------------------------------------------------------------
/src/main/java/ch/repnik/intellij/settings/PluginSettingsForm.java:
--------------------------------------------------------------------------------
1 | package ch.repnik.intellij.settings;
2 |
3 | import com.intellij.openapi.options.BaseConfigurable;
4 | import com.intellij.openapi.options.ConfigurationException;
5 | import com.intellij.openapi.options.SearchableConfigurable;
6 | import com.intellij.openapi.project.Project;
7 | import com.intellij.openapi.util.NlsContexts;
8 | import org.jetbrains.annotations.NonNls;
9 | import org.jetbrains.annotations.NotNull;
10 | import org.jetbrains.annotations.Nullable;
11 |
12 | import javax.swing.*;
13 | import java.awt.event.KeyAdapter;
14 | import java.awt.event.KeyEvent;
15 | import java.util.Objects;
16 | import java.util.regex.Pattern;
17 |
18 | public class PluginSettingsForm extends BaseConfigurable implements SearchableConfigurable {
19 | private JPanel mainPanel;
20 | private JComboBox cboTicketSystem;
21 | private JTextField txtWrapLeft;
22 | private JTextField txtWrapRight;
23 | private JComboBox cboPosition;
24 |
25 | private Project project;
26 |
27 | private Pattern allowedCharsPattern = Pattern.compile("[ \\[\\]\\(\\)\\{\\}:\\_\\-/\\|,\\.#]+");
28 |
29 |
30 | public PluginSettingsForm(Project project){
31 | txtWrapLeft.addKeyListener(new KeyAdapter() {
32 | public void keyTyped(KeyEvent e) {
33 | if (txtWrapLeft.getText().length() >= 5 ) // limit textfield to 5 characters
34 | e.consume();
35 | }
36 | });
37 |
38 | txtWrapRight.addKeyListener(new KeyAdapter() {
39 | public void keyTyped(KeyEvent e) {
40 | if (txtWrapRight.getText().length() >= 5 ) // limit textfield to 5 characters
41 | e.consume();
42 | }
43 | });
44 |
45 | this.project = project;
46 | }
47 |
48 | public JPanel getPanel(){
49 | return mainPanel;
50 | }
51 |
52 | public TicketSystem getTicketSystem() {
53 | return TicketSystem.parse(cboTicketSystem.getSelectedItem().toString());
54 | }
55 |
56 | public String getWrapRight(){
57 | return txtWrapRight.getText();
58 | }
59 |
60 | public String getWrapLeft() {return txtWrapLeft.getText();}
61 |
62 | public Position getIssueKeyPosition() {
63 | return Position.parse(cboPosition.getSelectedItem().toString());
64 | }
65 |
66 | public void resetEditorFrom(PluginConfigService settings){
67 | this.cboTicketSystem.setSelectedItem(settings.getState().getTicketSystem().getDescription());
68 | this.txtWrapLeft.setText(settings.getState().getWrapLeft());
69 | this.txtWrapRight.setText(settings.getState().getWrapRight());
70 | this.cboPosition.setSelectedItem(settings.getState().getIssueKeyPosition().getStringValue());
71 | }
72 |
73 | @Override
74 | public @NotNull @NonNls String getId() {
75 | return "Git Auto Prefix";
76 | }
77 |
78 | @Override
79 | public @NlsContexts.ConfigurableName String getDisplayName() {
80 | return "Git Auto Prefix";
81 | }
82 |
83 | @Override
84 | public @Nullable JComponent createComponent() {
85 | return mainPanel;
86 | }
87 |
88 | @Override
89 | public boolean isModified() {
90 | PluginConfigService.Configuration state = project.getService(PluginConfigService.class).getState();
91 | TicketSystem oldTicketSystem = state.getTicketSystem();
92 | TicketSystem newTicketSystem = getTicketSystem();
93 | String oldValueRight = state.getWrapRight();
94 | String newValueRight = getWrapRight();
95 | String oldValueLeft = state.getWrapLeft();
96 | String newValueLeft = getWrapRight();
97 | Position oldIssueKeyPosition = state.getIssueKeyPosition();
98 | Position newIssueKeyPosition = getIssueKeyPosition();
99 | return oldTicketSystem != newTicketSystem || !Objects.equals(oldValueRight, newValueRight) || !Objects.equals(oldValueLeft, newValueLeft) || oldIssueKeyPosition != newIssueKeyPosition;
100 | }
101 |
102 | @Override
103 | public void apply() throws ConfigurationException {
104 | if (mainPanel != null) {
105 | if (isModified()) {
106 | validate();
107 | PluginConfigService.Configuration state = project.getService(PluginConfigService.class).getState();
108 | state.setTicketSystem(getTicketSystem());
109 | state.setWrapRight(getWrapRight());
110 | state.setWrapLeft(getWrapLeft());
111 | state.setIssueKeyPosition(getIssueKeyPosition());
112 | }
113 | }
114 | }
115 |
116 | private void validate() throws ConfigurationException {
117 |
118 | if (getWrapRight().isEmpty()){
119 | throw new ConfigurationException("Wrap Right/Delimiter must not be empty", "Validation failed");
120 | }
121 |
122 | if (!allowedCharsPattern.matcher(getWrapRight()).matches()){
123 | throw new ConfigurationException("Wrap Right/Delimiter can only contain following chars: \" [](){}:_-/|,.#\"", "Validation failed");
124 | }
125 |
126 | if (!getWrapLeft().isEmpty() && !allowedCharsPattern.matcher(getWrapLeft()).matches()){
127 | throw new ConfigurationException("Wrap Left can only contain following chars: \" [](){}:_-/|,.#\"", "Validation failed");
128 | }
129 | }
130 |
131 | @Override
132 | public void reset() {
133 | if (mainPanel != null) {
134 | resetEditorFrom(project.getService(PluginConfigService.class));
135 | }
136 | }
137 |
138 | private void createUIComponents() {
139 | // TODO: place custom component creation code here
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/main/java/ch/repnik/intellij/settings/Position.java:
--------------------------------------------------------------------------------
1 | package ch.repnik.intellij.settings;
2 |
3 | public enum Position {
4 | START("start"), END("end");
5 |
6 | private final String position;
7 |
8 | Position(String position){
9 | this.position = position;
10 | }
11 |
12 | public String getStringValue(){
13 | return this.position;
14 | }
15 |
16 | public static Position parse(String position){
17 | for (Position value : Position.values()) {
18 | if (value.position.equals(position)){
19 | return value;
20 | }
21 | }
22 |
23 | throw new IllegalArgumentException("Position '" + position + "' was not found in enum");
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/ch/repnik/intellij/settings/TicketSystem.java:
--------------------------------------------------------------------------------
1 | package ch.repnik.intellij.settings;
2 |
3 | import java.util.Arrays;
4 |
5 | public enum TicketSystem {
6 | JIRA("Jira (ABC-1234)"),OTHER("Other (12345)");
7 |
8 | private final String description;
9 |
10 | TicketSystem(String description) {
11 | this.description = description;
12 | }
13 |
14 | public String getDescription() {
15 | return this.description;
16 | }
17 |
18 | public static TicketSystem parse(String description) {
19 | return Arrays.stream(TicketSystem.values())
20 | .filter(ticketSystem -> ticketSystem.getDescription().equals(description))
21 | .findFirst()
22 | .orElseThrow(() -> new IllegalArgumentException(
23 | "Description '" + description + "' was not found in enum"));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 | commit-prefix-plugin
3 | Git Auto Prefix
4 | 1.4.1
5 | Thomas Repnik
6 |
7 |
9 |
10 | - Added support for lowercase project keys
11 |
12 |
13 |
14 | ]]>
15 |
16 |
18 | Automatically set the issue key (of the current branch name) as prefix for the commit message
19 |
20 | - Choose your own delimiter between the issue key and commit message
21 | - Wrap the issue key if necessary
22 |
23 |
24 |
25 |
26 | Important: This plugin only works with branches named as follows
27 |
28 | - Jira format with alphanumeric project keys (ABC-1234)
29 | - Jira format with numeric project keys (1234-5678)
30 | - Other format that is all numbers (123456)
31 |
32 |
33 |
34 |
35 |
36 | Branch Name |
37 | Commit prefix (with delimiter) |
38 | Commit prefix (wrapped) |
39 |
40 |
41 | main |
42 | no action |
43 | no action |
44 |
45 |
46 | master |
47 | no action |
48 | no action |
49 |
50 |
51 | bugfix/ABC-1234-app-not-working |
52 | ABC-1234: |
53 | [ABC-1234] |
54 |
55 |
56 | feature/ABC-1234-app-not-working |
57 | ABC-1234: |
58 | [ABC-1234] |
59 |
60 |
61 | release/ABC-1234-app-not-working |
62 | ABC-1234: |
63 | [ABC-1234] |
64 |
65 |
66 | someOtherType/ABC-1234-app-not-working |
67 | ABC-1234: |
68 | [ABC-1234] |
69 |
70 |
71 | ABC-1234-app-not-working |
72 | ABC-1234: |
73 | [ABC-1234] |
74 |
75 |
76 | ABC-1234 |
77 | ABC-1234: |
78 | [ABC-1234] |
79 |
80 |
81 | 12345-app-not-working |
82 | 12345: |
83 | [12345] |
84 |
85 |
86 | ]]>
87 |
88 |
90 | com.intellij.modules.platform
91 | Git4Idea
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/src/test/java/ch/repnik/intellij/CommitPrefixCheckinHandlerTest.java:
--------------------------------------------------------------------------------
1 | package ch.repnik.intellij;
2 |
3 | import ch.repnik.intellij.settings.Position;
4 | import ch.repnik.intellij.settings.TicketSystem;
5 | import lombok.AllArgsConstructor;
6 | import lombok.NoArgsConstructor;
7 | import lombok.RequiredArgsConstructor;
8 | import lombok.With;
9 | import org.junit.jupiter.params.ParameterizedTest;
10 | import org.junit.jupiter.params.provider.Arguments;
11 | import org.junit.jupiter.params.provider.MethodSource;
12 |
13 | import java.util.Optional;
14 | import java.util.stream.Stream;
15 |
16 | import static ch.repnik.intellij.settings.TicketSystem.JIRA;
17 | import static ch.repnik.intellij.settings.TicketSystem.OTHER;
18 | import static org.hamcrest.CoreMatchers.is;
19 | import static org.hamcrest.MatcherAssert.assertThat;
20 |
21 | class CommitPrefixCheckinHandlerTest {
22 |
23 | static Stream updatePrefix_noMatch_updatedCorrectly() {
24 | UpdatePrefixTester startTemplate = new UpdatePrefixTester().withWrapLeft("").withWrapRight(": ").withIssueKeyPosition(Position.START);
25 | UpdatePrefixTester endTemplate = new UpdatePrefixTester().withWrapLeft(": ").withWrapRight("").withIssueKeyPosition(Position.END);
26 | return Stream.of(
27 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("Testli").withNewPrefix("ABC-1234"), "Testli: ABC-1234"),
28 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("Testli").withNewPrefix("abc-1234"), "Testli: abc-1234"),
29 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("Testli").withNewPrefix("123-4567"), "Testli: 123-4567"),
30 | Arguments.of(endTemplate.withTicketSystem(OTHER).withCurrentMessage("Testli").withNewPrefix("5678"), "Testli: 5678"),
31 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("Testli").withNewPrefix("ABC-1234"), "ABC-1234: Testli"),
32 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("Testli").withNewPrefix("abc-1234"), "abc-1234: Testli"),
33 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("Testli").withNewPrefix("123-4567"), "123-4567: Testli"),
34 | Arguments.of(startTemplate.withTicketSystem(OTHER).withCurrentMessage("Testli").withNewPrefix("5678"), "5678: Testli")
35 | );
36 | }
37 |
38 | @ParameterizedTest
39 | @MethodSource
40 | public void updatePrefix_noMatch_updatedCorrectly(UpdatePrefixTester tester, String expectedMessage) {
41 | tester.updatePrefix().doAssertion(expectedMessage);
42 | }
43 |
44 | static Stream updatePrefix_existingMessage_updatedCorrectly() {
45 | UpdatePrefixTester startTemplate = new UpdatePrefixTester().withWrapLeft("").withWrapRight(": ").withIssueKeyPosition(Position.START);
46 | UpdatePrefixTester endTemplate = new UpdatePrefixTester().withWrapLeft(": ").withWrapRight("").withIssueKeyPosition(Position.END);
47 | return Stream.of(
48 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("XYXY-837292: This is my text").withNewPrefix("ABC-1234"), "ABC-1234: This is my text"),
49 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("xyxy-837292: This is my text").withNewPrefix("abc-1234"), "abc-1234: This is my text"),
50 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("This is my text: XYXY-837292").withNewPrefix("ABC-1234"), "This is my text: ABC-1234"),
51 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("This is my text: xyxy-837292").withNewPrefix("abc-1234"), "This is my text: abc-1234"),
52 | Arguments.of(startTemplate.withTicketSystem(OTHER).withCurrentMessage("837292: This is my text").withNewPrefix("5678"), "5678: This is my text"),
53 | Arguments.of(endTemplate.withTicketSystem(OTHER).withCurrentMessage("This is my text: 837292").withNewPrefix("5678"), "This is my text: 5678"),
54 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("5678-837292: This is my text").withNewPrefix("2222-1234"), "2222-1234: This is my text"),
55 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("This is my text: 5678-837292").withNewPrefix("2222-1234"), "This is my text: 2222-1234")
56 |
57 | );
58 | }
59 |
60 | @ParameterizedTest
61 | @MethodSource
62 | public void updatePrefix_existingMessage_updatedCorrectly(UpdatePrefixTester tester, String expectedMessage) {
63 | tester.updatePrefix().doAssertion(expectedMessage);
64 | }
65 |
66 | static Stream updatePrefix_delimiterWithoutMessage_updatedCorrectly() {
67 | UpdatePrefixTester startTemplate = new UpdatePrefixTester().withWrapLeft("").withWrapRight(": ").withIssueKeyPosition(Position.START);
68 | UpdatePrefixTester endTemplate = new UpdatePrefixTester().withWrapLeft(": ").withWrapRight("").withIssueKeyPosition(Position.END);
69 | return Stream.of(
70 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("XYXY-837292:").withNewPrefix("ABC-1234"), "ABC-1234: "),
71 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("xyxy-837292:").withNewPrefix("abc-1234"), "abc-1234: "),
72 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(": XYXY-837292").withNewPrefix("ABC-1234"), ": ABC-1234"),
73 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(": xyxy-837292").withNewPrefix("abc-1234"), ": abc-1234"),
74 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("5678-837292:").withNewPrefix("2222-1234"), "2222-1234: "),
75 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(": 5678-837292").withNewPrefix("2222-1234"), ": 2222-1234"),
76 | Arguments.of(startTemplate.withTicketSystem(OTHER).withCurrentMessage("837292: ").withNewPrefix("5678"), "5678: "),
77 | Arguments.of(endTemplate.withTicketSystem(OTHER).withCurrentMessage(": 837292").withNewPrefix("5678"), ": 5678")
78 | );
79 | }
80 |
81 | @ParameterizedTest
82 | @MethodSource
83 | public void updatePrefix_delimiterWithoutMessage_updatedCorrectly(UpdatePrefixTester tester, String expectedMessage) {
84 | tester.updatePrefix().doAssertion(expectedMessage);
85 | }
86 |
87 | static Stream updatePrefix_wrongDelimiter_issueNotRecognized() {
88 | UpdatePrefixTester startTemplate = new UpdatePrefixTester().withWrapLeft("").withWrapRight(" | ").withIssueKeyPosition(Position.START);
89 | UpdatePrefixTester endTemplate = new UpdatePrefixTester().withWrapLeft(" | ").withWrapRight("").withIssueKeyPosition(Position.END);
90 |
91 | return Stream.of(
92 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("XYXY-837292: This is my text").withNewPrefix("ABC-1234"), "ABC-1234 | XYXY-837292: This is my text"),
93 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("xyxy-837292: This is my text").withNewPrefix("abc-1234"), "abc-1234 | xyxy-837292: This is my text"),
94 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("This is my text: XYXY-837292").withNewPrefix("ABC-1234"), "This is my text: XYXY-837292 | ABC-1234"),
95 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("This is my text: xyxy-837292").withNewPrefix("abc-1234"), "This is my text: xyxy-837292 | abc-1234"),
96 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("5678-837292: This is my text").withNewPrefix("2222-1234"), "2222-1234 | 5678-837292: This is my text"),
97 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("This is my text: 5678-837292").withNewPrefix("2222-1234"), "This is my text: 5678-837292 | 2222-1234"),
98 | Arguments.of(startTemplate.withTicketSystem(OTHER).withCurrentMessage("837292: This is my text").withNewPrefix("5678"), "5678 | 837292: This is my text"),
99 | Arguments.of(endTemplate.withTicketSystem(OTHER).withCurrentMessage("This is my text: 837292").withNewPrefix("5678"), "This is my text: 837292 | 5678")
100 | );
101 | }
102 |
103 | @ParameterizedTest
104 | @MethodSource
105 | public void updatePrefix_wrongDelimiter_issueNotRecognized(UpdatePrefixTester tester, String expectedMessage) {
106 | tester.updatePrefix().doAssertion(expectedMessage);
107 | }
108 |
109 | static Stream updatePrefix_specialDelimiter_updatedCorrectly() {
110 | UpdatePrefixTester startTemplate = new UpdatePrefixTester().withWrapLeft(" [](){}:_-/|,.").withWrapRight(" [](){}:_-/|,.").withIssueKeyPosition(Position.START);
111 | UpdatePrefixTester endTemplate = new UpdatePrefixTester().withWrapLeft(" [](){}:_-/|,.").withWrapRight(" [](){}:_-/|,.").withIssueKeyPosition(Position.END);
112 |
113 | return Stream.of(
114 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("ABC-1234"), " [](){}:_-/|,.ABC-1234 [](){}:_-/|,."),
115 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("abc-1234"), " [](){}:_-/|,.abc-1234 [](){}:_-/|,."),
116 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("ABC-1234"), " [](){}:_-/|,.ABC-1234 [](){}:_-/|,."),
117 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("abc-1234"), " [](){}:_-/|,.abc-1234 [](){}:_-/|,."),
118 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("2222-1234"), " [](){}:_-/|,.2222-1234 [](){}:_-/|,."),
119 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("2222-1234"), " [](){}:_-/|,.2222-1234 [](){}:_-/|,."),
120 | Arguments.of(startTemplate.withTicketSystem(OTHER).withCurrentMessage(null).withNewPrefix("5678"), " [](){}:_-/|,.5678 [](){}:_-/|,."),
121 | Arguments.of(endTemplate.withTicketSystem(OTHER).withCurrentMessage(null).withNewPrefix("5678"), " [](){}:_-/|,.5678 [](){}:_-/|,.")
122 | );
123 | }
124 |
125 | @ParameterizedTest
126 | @MethodSource
127 | public void updatePrefix_specialDelimiter_updatedCorrectly(UpdatePrefixTester tester, String expectedMessage) {
128 | tester.updatePrefix().doAssertion(expectedMessage);
129 | }
130 |
131 | static Stream updatePrefix_doubledPattern_updatedCorrectly() {
132 | UpdatePrefixTester startTemplate = new UpdatePrefixTester().withWrapLeft("").withWrapRight(": ").withIssueKeyPosition(Position.START);
133 | UpdatePrefixTester endTemplate = new UpdatePrefixTester().withWrapLeft(": ").withWrapRight("").withIssueKeyPosition(Position.END);
134 |
135 | return Stream.of(
136 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("XYXY-837292: XYZ-11 This is my text").withNewPrefix("ABC-1234"), "ABC-1234: XYZ-11 This is my text"),
137 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("xyxy-837292: xyz-11 This is my text").withNewPrefix("abc-1234"), "abc-1234: xyz-11 This is my text"),
138 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("XYZ-11 This is my text: XYXY-837292").withNewPrefix("ABC-1234"), "XYZ-11 This is my text: ABC-1234"),
139 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("xyz-11 This is my text: xyxy-837292").withNewPrefix("abc-1234"), "xyz-11 This is my text: abc-1234"),
140 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("5678-837292: 55-11 This is my text").withNewPrefix("2222-1234"), "2222-1234: 55-11 This is my text"),
141 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("55-11 This is my text: 5678-837292").withNewPrefix("2222-1234"), "55-11 This is my text: 2222-1234"),
142 | Arguments.of(startTemplate.withTicketSystem(OTHER).withCurrentMessage("1234: 9999 This is my text").withNewPrefix("5678"), "5678: 9999 This is my text"),
143 | Arguments.of(endTemplate.withTicketSystem(OTHER).withCurrentMessage("9999 This is my text: 1234").withNewPrefix("5678"), "9999 This is my text: 5678")
144 |
145 | );
146 | }
147 |
148 |
149 | @ParameterizedTest
150 | @MethodSource
151 | public void updatePrefix_doubledPattern_updatedCorrectly(UpdatePrefixTester tester, String expectedMessage) {
152 | tester.updatePrefix().doAssertion(expectedMessage);
153 | }
154 |
155 |
156 | static Stream updatePrefix_null_updatedCorrectly() {
157 | UpdatePrefixTester startTemplate = new UpdatePrefixTester().withWrapLeft("").withWrapRight(": ").withIssueKeyPosition(Position.START);
158 | UpdatePrefixTester endTemplate = new UpdatePrefixTester().withWrapLeft(": ").withWrapRight("").withIssueKeyPosition(Position.END);
159 |
160 | return Stream.of(
161 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("ABC-1234"), "ABC-1234: "),
162 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("abc-1234"), "abc-1234: "),
163 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("ABC-1234"), ": ABC-1234"),
164 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("abc-1234"), ": abc-1234"),
165 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("2222-1234"), "2222-1234: "),
166 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("2222-1234"), ": 2222-1234"),
167 | Arguments.of(startTemplate.withTicketSystem(OTHER).withCurrentMessage(null).withNewPrefix("5678"), "5678: "),
168 | Arguments.of(endTemplate.withTicketSystem(OTHER).withCurrentMessage(null).withNewPrefix("5678"), ": 5678")
169 |
170 | );
171 | }
172 |
173 | @ParameterizedTest
174 | @MethodSource
175 | public void updatePrefix_null_updatedCorrectly(UpdatePrefixTester tester, String expectedMessage) {
176 | tester.updatePrefix().doAssertion(expectedMessage);
177 | }
178 |
179 | static Stream updatePrefix_emptyMessage_updatedCorrectly() {
180 | UpdatePrefixTester startTemplate = new UpdatePrefixTester().withWrapLeft("").withWrapRight(": ").withIssueKeyPosition(Position.START);
181 | UpdatePrefixTester endTemplate = new UpdatePrefixTester().withWrapLeft(": ").withWrapRight("").withIssueKeyPosition(Position.END);
182 |
183 | return Stream.of(
184 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("").withNewPrefix("ABC-1234"), "ABC-1234: "),
185 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("").withNewPrefix("abc-1234"), "abc-1234: "),
186 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("").withNewPrefix("ABC-1234"), ": ABC-1234"),
187 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("").withNewPrefix("abc-1234"), ": abc-1234"),
188 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage("").withNewPrefix("2222-1234"), "2222-1234: "),
189 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage("").withNewPrefix("2222-1234"), ": 2222-1234"),
190 | Arguments.of(startTemplate.withTicketSystem(OTHER).withCurrentMessage("").withNewPrefix("5678"), "5678: "),
191 | Arguments.of(endTemplate.withTicketSystem(OTHER).withCurrentMessage("").withNewPrefix("5678"), ": 5678")
192 |
193 | );
194 | }
195 |
196 | @ParameterizedTest
197 | @MethodSource
198 | public void updatePrefix_emptyMessage_updatedCorrectly(UpdatePrefixTester tester, String expectedMessage) {
199 | tester.updatePrefix().doAssertion(expectedMessage);
200 | }
201 |
202 | static Stream updatePrefix_blankMessage_updatedCorrectly() {
203 | UpdatePrefixTester startTemplate = new UpdatePrefixTester().withWrapLeft("").withWrapRight(": ").withIssueKeyPosition(Position.START);
204 | UpdatePrefixTester endTemplate = new UpdatePrefixTester().withWrapLeft(": ").withWrapRight("").withIssueKeyPosition(Position.END);
205 |
206 | return Stream.of(
207 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(" ").withNewPrefix("ABC-1234"), "ABC-1234: "),
208 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(" ").withNewPrefix("abc-1234"), "abc-1234: "),
209 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(" ").withNewPrefix("ABC-1234"), ": ABC-1234"),
210 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(" ").withNewPrefix("abc-1234"), ": abc-1234"),
211 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(" ").withNewPrefix("2222-1234"), "2222-1234: "),
212 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(" ").withNewPrefix("2222-1234"), ": 2222-1234"),
213 | Arguments.of(startTemplate.withTicketSystem(OTHER).withCurrentMessage(" ").withNewPrefix("5678"), "5678: "),
214 | Arguments.of(endTemplate.withTicketSystem(OTHER).withCurrentMessage(" ").withNewPrefix("5678"), ": 5678")
215 |
216 | );
217 | }
218 |
219 | @ParameterizedTest
220 | @MethodSource
221 | public void updatePrefix_blankMessage_updatedCorrectly(UpdatePrefixTester tester, String expectedMessage) {
222 | tester.updatePrefix().doAssertion(expectedMessage);
223 | }
224 |
225 |
226 | static Stream updatePrefix_existingMessageWithBlanks_updatedCorrectly() {
227 | UpdatePrefixTester startTemplate = new UpdatePrefixTester().withWrapLeft("").withWrapRight(": ").withIssueKeyPosition(Position.START);
228 | UpdatePrefixTester endTemplate = new UpdatePrefixTester().withWrapLeft(": ").withWrapRight("").withIssueKeyPosition(Position.END);
229 |
230 | return Stream.of(
231 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(" XYXY-837292: This is a Test ").withNewPrefix("ABC-1234"), " ABC-1234: This is a Test "),
232 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(" xyxy-837292: This is a Test ").withNewPrefix("abc-1234"), " abc-1234: This is a Test "),
233 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(" This is a Test : XYXY-837292 ").withNewPrefix("ABC-1234"), " This is a Test : ABC-1234 "),
234 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(" This is a Test : xyxy-837292 ").withNewPrefix("abc-1234"), " This is a Test : abc-1234 "),
235 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(" 5678-837292: This is a Test ").withNewPrefix("2222-1234"), " 2222-1234: This is a Test "),
236 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(" This is a Test : 5678-837292 ").withNewPrefix("2222-1234"), " This is a Test : 2222-1234 "),
237 | Arguments.of(startTemplate.withTicketSystem(OTHER).withCurrentMessage(" 1111: This is a Test ").withNewPrefix("5678"), " 5678: This is a Test "),
238 | Arguments.of(endTemplate.withTicketSystem(OTHER).withCurrentMessage(" This is a Test : 1111 ").withNewPrefix("5678"), " This is a Test : 5678 ")
239 |
240 | );
241 | }
242 |
243 | @ParameterizedTest
244 | @MethodSource
245 | public void updatePrefix_existingMessageWithBlanks_updatedCorrectly(UpdatePrefixTester tester, String expectedMessage) {
246 | tester.updatePrefix().doAssertion(expectedMessage);
247 | }
248 |
249 |
250 | static Stream updatePrefix_existingMessageWithPrefixInText_updatedCorrectly() {
251 | UpdatePrefixTester startTemplate = new UpdatePrefixTester().withWrapLeft("").withWrapRight(": ").withIssueKeyPosition(Position.START);
252 | UpdatePrefixTester endTemplate = new UpdatePrefixTester().withWrapLeft(": ").withWrapRight("").withIssueKeyPosition(Position.END);
253 |
254 | return Stream.of(
255 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(" According to issue XYXY-837292: this fix... ").withNewPrefix("ABC-1234"), "ABC-1234: According to issue XYXY-837292: this fix... "),
256 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(" According to issue xyxy-837292: this fix... ").withNewPrefix("abc-1234"), "abc-1234: According to issue xyxy-837292: this fix... "),
257 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(" According to issue : XYXY-837292 this fix... ").withNewPrefix("ABC-1234"), " According to issue : XYXY-837292 this fix... : ABC-1234"),
258 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(" According to issue : xyxy-837292 this fix... ").withNewPrefix("abc-1234"), " According to issue : xyxy-837292 this fix... : abc-1234"),
259 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(" According to issue 5678-837292: this fix... ").withNewPrefix("2222-1234"), "2222-1234: According to issue 5678-837292: this fix... "),
260 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(" According to issue : 5678-837292 this fix... ").withNewPrefix("2222-1234"), " According to issue : 5678-837292 this fix... : 2222-1234"),
261 | Arguments.of(startTemplate.withTicketSystem(OTHER).withCurrentMessage(" According to issue 1111: this fix... ").withNewPrefix("5678"), "5678: According to issue 1111: this fix... "),
262 | Arguments.of(endTemplate.withTicketSystem(OTHER).withCurrentMessage(" According to issue : 1111 this fix... ").withNewPrefix("5678"), " According to issue : 1111 this fix... : 5678")
263 |
264 | );
265 | }
266 |
267 | @ParameterizedTest
268 | @MethodSource
269 | public void updatePrefix_existingMessageWithPrefixInText_updatedCorrectly(UpdatePrefixTester tester, String expectedMessage) {
270 | tester.updatePrefix().doAssertion(expectedMessage);
271 | }
272 |
273 |
274 |
275 | static Stream updatePrefix_noMessageButWrappedInBlanks_updatedCorrectly() {
276 | UpdatePrefixTester startTemplate = new UpdatePrefixTester().withWrapLeft(" ").withWrapRight(" ").withIssueKeyPosition(Position.START);
277 | UpdatePrefixTester endTemplate = new UpdatePrefixTester().withWrapLeft(" ").withWrapRight(" ").withIssueKeyPosition(Position.END);
278 |
279 | return Stream.of(
280 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("ABC-1234"), " ABC-1234 "),
281 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("abc-1234"), " abc-1234 "),
282 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("ABC-1234"), " ABC-1234 "),
283 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("abc-1234"), " abc-1234 "),
284 | Arguments.of(startTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("2222-1234"), " 2222-1234 "),
285 | Arguments.of(endTemplate.withTicketSystem(JIRA).withCurrentMessage(null).withNewPrefix("2222-1234"), " 2222-1234 "),
286 | Arguments.of(startTemplate.withTicketSystem(OTHER).withCurrentMessage(null).withNewPrefix("5678"), " 5678 "),
287 | Arguments.of(endTemplate.withTicketSystem(OTHER).withCurrentMessage(null).withNewPrefix("5678"), " 5678 ")
288 |
289 | );
290 | }
291 |
292 |
293 | @ParameterizedTest
294 | @MethodSource
295 | public void updatePrefix_noMessageButWrappedInBlanks_updatedCorrectly(UpdatePrefixTester tester, String expectedMessage) {
296 | tester.updatePrefix().doAssertion(expectedMessage);
297 | }
298 |
299 |
300 | static Stream updateAzureBoardsPrefix_digitsInCommitMessage_onlyReplacedIfMatchingPrefixSettings() {
301 | UpdatePrefixTester startTemplate = new UpdatePrefixTester().withTicketSystem(OTHER).withWrapLeft("").withWrapRight(": ").withIssueKeyPosition(Position.START);
302 | UpdatePrefixTester endTemplate = new UpdatePrefixTester().withTicketSystem(OTHER).withWrapLeft(": ").withWrapRight("").withIssueKeyPosition(Position.END);
303 |
304 | return Stream.of(
305 | Arguments.of(startTemplate.withCurrentMessage("Fixed 4 bugs in 3 classes").withNewPrefix("5678"), "5678: Fixed 4 bugs in 3 classes"),
306 | Arguments.of(endTemplate.withCurrentMessage("Fixed 4 bugs in 3 classes").withNewPrefix("5678"), "Fixed 4 bugs in 3 classes: 5678"),
307 | Arguments.of(startTemplate.withCurrentMessage("4 bugs in 3 classes fixed").withNewPrefix("5678"), "5678: 4 bugs in 3 classes fixed"),
308 | Arguments.of(endTemplate.withCurrentMessage("4 bugs in 3 classes fixed").withNewPrefix("5678"), "4 bugs in 3 classes fixed: 5678")
309 | );
310 | }
311 |
312 | @ParameterizedTest
313 | @MethodSource
314 | void updateAzureBoardsPrefix_digitsInCommitMessage_onlyReplacedIfMatchingPrefixSettings(UpdatePrefixTester tester, String expectedMessage) {
315 | tester.updatePrefix().doAssertion(expectedMessage);
316 | }
317 |
318 |
319 | static Stream updatePrefix_existingPrefixFromDifferentTicketSystem_newPrefixAdded() {
320 | UpdatePrefixTester startJiraTemplate = new UpdatePrefixTester().withTicketSystem(JIRA).withWrapLeft("").withWrapRight(": ").withIssueKeyPosition(Position.START);
321 | UpdatePrefixTester endJiraTemplate = new UpdatePrefixTester().withTicketSystem(JIRA).withWrapLeft(": ").withWrapRight("").withIssueKeyPosition(Position.END);
322 | UpdatePrefixTester startOtherTemplate = new UpdatePrefixTester().withTicketSystem(OTHER).withWrapLeft("").withWrapRight(": ").withIssueKeyPosition(Position.START);
323 | UpdatePrefixTester endOtherTemplate = new UpdatePrefixTester().withTicketSystem(OTHER).withWrapLeft(": ").withWrapRight("").withIssueKeyPosition(Position.END);
324 |
325 | return Stream.of(
326 | Arguments.of(startJiraTemplate.withCurrentMessage("5678: Some fix").withNewPrefix("ABC-1234"), "ABC-1234: 5678: Some fix"),
327 | Arguments.of(endJiraTemplate.withCurrentMessage("Some fix: 5678").withNewPrefix("ABC-1234"), "Some fix: 5678: ABC-1234"),
328 | Arguments.of(startJiraTemplate.withCurrentMessage("5678: Some fix").withNewPrefix("1111-1234"), "1111-1234: 5678: Some fix"),
329 | Arguments.of(endJiraTemplate.withCurrentMessage("Some fix: 5678").withNewPrefix("1111-1234"), "Some fix: 5678: 1111-1234"),
330 | Arguments.of(startOtherTemplate.withCurrentMessage("ABC-1234: Some fix").withNewPrefix("5678"), "5678: ABC-1234: Some fix"),
331 | Arguments.of(endOtherTemplate.withCurrentMessage("Some fix: ABC-1234").withNewPrefix("5678"), "Some fix: ABC-1234: 5678")
332 | );
333 | }
334 |
335 | @ParameterizedTest
336 | @MethodSource
337 | void updatePrefix_existingPrefixFromDifferentTicketSystem_newPrefixAdded(UpdatePrefixTester tester, String expectedMessage) {
338 | tester.updatePrefix().doAssertion(expectedMessage);
339 | }
340 |
341 | static Stream getTicketName_withoutBranchType_returnsTicket() {
342 | TicketNameTester jiraTicketTemplate = new TicketNameTester().withTicketSystem(JIRA);
343 | TicketNameTester otherTicketTemplate = new TicketNameTester().withTicketSystem(OTHER);
344 |
345 | return Stream.of(
346 | Arguments.of(jiraTicketTemplate.withBranchName("ABC-1234-app-not-working"), "ABC-1234"),
347 | Arguments.of(jiraTicketTemplate.withBranchName("1111-1234-app-not-working"), "1111-1234"),
348 | Arguments.of(otherTicketTemplate.withBranchName("1234-app-not-working"), "1234")
349 |
350 | );
351 | }
352 |
353 |
354 | @ParameterizedTest
355 | @MethodSource
356 | public void getTicketName_withoutBranchType_returnsTicket(TicketNameTester tester, String expectedMessage) {
357 | tester.readTicket().doAssertion(expectedMessage);
358 | }
359 |
360 |
361 |
362 | static Stream getTicketName_reproduce() {
363 | TicketNameTester jiraTicketTemplate = new TicketNameTester().withTicketSystem(JIRA);
364 | TicketNameTester otherTicketTemplate = new TicketNameTester().withTicketSystem(OTHER);
365 |
366 | return Stream.of(
367 | Arguments.of(jiraTicketTemplate.withBranchName("feature/DATA-4214-ab-CEP3.0-Transition-polling"), "DATA-4214"),
368 | Arguments.of(jiraTicketTemplate.withBranchName("feature/1111-4214-ab-CEP3.0-Transition-polling"), "1111-4214"),
369 | Arguments.of(otherTicketTemplate.withBranchName("feature/1111-ab-CEP3.0-Transition-polling"), "1111")
370 |
371 | );
372 | }
373 |
374 | @ParameterizedTest
375 | @MethodSource
376 | public void getTicketName_reproduce(TicketNameTester tester, String expectedMessage) {
377 | tester.readTicket().doAssertion(expectedMessage);
378 | }
379 |
380 | static Stream getTicketName_featureBranchType_returnsTicket() {
381 | TicketNameTester jiraTicketTemplate = new TicketNameTester().withTicketSystem(JIRA);
382 | TicketNameTester otherTicketTemplate = new TicketNameTester().withTicketSystem(OTHER);
383 |
384 | return Stream.of(
385 | Arguments.of(jiraTicketTemplate.withBranchName("feature/ABC-1234-app-not-working"), "ABC-1234"),
386 | Arguments.of(jiraTicketTemplate.withBranchName("feature/1111-1234-app-not-working"), "1111-1234"),
387 | Arguments.of(otherTicketTemplate.withBranchName("feature/1111-app-not-working"), "1111")
388 |
389 | );
390 | }
391 |
392 | @ParameterizedTest
393 | @MethodSource
394 | public void getTicketName_featureBranchType_returnsTicket(TicketNameTester tester, String expectedMessage) {
395 | tester.readTicket().doAssertion(expectedMessage);
396 | }
397 |
398 | static Stream getTicketName_releaseBranchType_returnsTicket() {
399 | TicketNameTester jiraTicketTemplate = new TicketNameTester().withTicketSystem(JIRA);
400 | TicketNameTester otherTicketTemplate = new TicketNameTester().withTicketSystem(OTHER);
401 |
402 | return Stream.of(
403 | Arguments.of(jiraTicketTemplate.withBranchName("release/ABC-1234-app-not-working"), "ABC-1234"),
404 | Arguments.of(jiraTicketTemplate.withBranchName("release/1111-1234-app-not-working"), "1111-1234"),
405 | Arguments.of(otherTicketTemplate.withBranchName("release/1111-app-not-working"), "1111")
406 |
407 | );
408 | }
409 |
410 | @ParameterizedTest
411 | @MethodSource
412 | public void getTicketName_releaseBranchType_returnsTicket(TicketNameTester tester, String expectedMessage) {
413 | tester.readTicket().doAssertion(expectedMessage);
414 | }
415 |
416 | static Stream getTicketName_bugfixBranchType_returnsTicket() {
417 | TicketNameTester jiraTicketTemplate = new TicketNameTester().withTicketSystem(JIRA);
418 | TicketNameTester otherTicketTemplate = new TicketNameTester().withTicketSystem(OTHER);
419 |
420 | return Stream.of(
421 | Arguments.of(jiraTicketTemplate.withBranchName("bugfix/ABC-1234-app-not-working"), "ABC-1234"),
422 | Arguments.of(jiraTicketTemplate.withBranchName("bugfix/1111-1234-app-not-working"), "1111-1234"),
423 | Arguments.of(otherTicketTemplate.withBranchName("bugfix/1111-app-not-working"), "1111")
424 |
425 | );
426 | }
427 |
428 | @ParameterizedTest
429 | @MethodSource
430 | public void getTicketName_bugfixBranchType_returnsTicket(TicketNameTester tester, String expectedMessage) {
431 | tester.readTicket().doAssertion(expectedMessage);
432 | }
433 |
434 | static Stream getTicketName_someOtherBranchType_returnsTicket() {
435 | TicketNameTester jiraTicketTemplate = new TicketNameTester().withTicketSystem(JIRA);
436 | TicketNameTester otherTicketTemplate = new TicketNameTester().withTicketSystem(OTHER);
437 |
438 | return Stream.of(
439 | Arguments.of(jiraTicketTemplate.withBranchName("someOtherType/ABC-1234-app-not-working"), "ABC-1234"),
440 | Arguments.of(jiraTicketTemplate.withBranchName("someOtherType/1111-1234-app-not-working"), "1111-1234"),
441 | Arguments.of(otherTicketTemplate.withBranchName("someOtherType/1111-app-not-working"), "1111")
442 |
443 | );
444 | }
445 |
446 | @ParameterizedTest
447 | @MethodSource
448 | public void getTicketName_someOtherBranchType_returnsTicket(TicketNameTester tester, String expectedMessage) {
449 | tester.readTicket().doAssertion(expectedMessage);
450 | }
451 |
452 | static Stream getTicketName_emptyType_returnsTicket() {
453 | TicketNameTester jiraTicketTemplate = new TicketNameTester().withTicketSystem(JIRA);
454 | TicketNameTester otherTicketTemplate = new TicketNameTester().withTicketSystem(OTHER);
455 |
456 | return Stream.of(
457 | Arguments.of(jiraTicketTemplate.withBranchName("/ABC-1234-app-not-working"), "ABC-1234"),
458 | Arguments.of(jiraTicketTemplate.withBranchName("/1111-1234-app-not-working"), "1111-1234"),
459 | Arguments.of(otherTicketTemplate.withBranchName("/1111-app-not-working"), "1111")
460 |
461 | );
462 | }
463 |
464 | @ParameterizedTest
465 | @MethodSource
466 | public void getTicketName_emptyType_returnsTicket(TicketNameTester tester, String expectedMessage) {
467 | tester.readTicket().doAssertion(expectedMessage);
468 | }
469 |
470 | static Stream getTicketName_emptySuffix_returnsTicket() {
471 | TicketNameTester jiraTicketTemplate = new TicketNameTester().withTicketSystem(JIRA);
472 | TicketNameTester otherTicketTemplate = new TicketNameTester().withTicketSystem(OTHER);
473 |
474 | return Stream.of(
475 | Arguments.of(jiraTicketTemplate.withBranchName("feature/ABC-1234"), "ABC-1234"),
476 | Arguments.of(jiraTicketTemplate.withBranchName("feature/1111-1234"), "1111-1234"),
477 | Arguments.of(otherTicketTemplate.withBranchName("feature/1111"), "1111")
478 |
479 | );
480 | }
481 |
482 | @ParameterizedTest
483 | @MethodSource
484 | public void getTicketName_emptySuffix_returnsTicket(TicketNameTester tester, String expectedMessage) {
485 | tester.readTicket().doAssertion(expectedMessage);
486 | }
487 |
488 | static Stream getTicketName_branchNameStartingWithDigit_returnsTicket() {
489 | TicketNameTester jiraTicketTemplate = new TicketNameTester().withTicketSystem(JIRA);
490 | TicketNameTester otherTicketTemplate = new TicketNameTester().withTicketSystem(OTHER);
491 |
492 | return Stream.of(
493 | Arguments.of(jiraTicketTemplate.withBranchName("ABC-1234-3-small-fixes"), "ABC-1234"),
494 | Arguments.of(jiraTicketTemplate.withBranchName("1111-1234-3-small-fixes"), "1111-1234"),
495 | Arguments.of(otherTicketTemplate.withBranchName("1111-3-small-fixes"), "1111")
496 |
497 | );
498 | }
499 |
500 | @ParameterizedTest
501 | @MethodSource
502 | public void getTicketName_branchNameStartingWithDigit_returnsTicket(TicketNameTester tester, String expectedMessage) {
503 | tester.readTicket().doAssertion(expectedMessage);
504 | }
505 |
506 |
507 |
508 | @With
509 | @AllArgsConstructor
510 | @NoArgsConstructor
511 | static class UpdatePrefixTester {
512 |
513 | private String currentMessage;
514 | private String newPrefix;
515 | private TicketSystem ticketSystem;
516 | private String wrapLeft;
517 | private String wrapRight;
518 | private Position issueKeyPosition;
519 |
520 |
521 | UpdatePrefixAsserter updatePrefix() {
522 | String newMessage =
523 | CommitPrefixCheckinHandler.updatePrefix(
524 | newPrefix, currentMessage, ticketSystem, wrapLeft, wrapRight, issueKeyPosition);
525 | return new UpdatePrefixAsserter(newMessage);
526 | }
527 |
528 | @Override
529 | public String toString() {
530 | return String.format("%s, %s", ticketSystem.toString(), issueKeyPosition.toString());
531 | }
532 | }
533 |
534 | @RequiredArgsConstructor
535 | static class UpdatePrefixAsserter {
536 |
537 | private final String actualMessage;
538 |
539 | void doAssertion(String expectedValue) {
540 | assertThat(actualMessage, is(expectedValue));
541 | }
542 | }
543 |
544 |
545 | @With
546 | @AllArgsConstructor
547 | @NoArgsConstructor
548 | static class TicketNameTester {
549 |
550 | private TicketSystem ticketSystem;
551 | private String branchName;
552 |
553 | TicketNameAsserter readTicket() {
554 | Optional ticket =
555 | CommitPrefixCheckinHandler.getTicket(ticketSystem, branchName);
556 | return new TicketNameAsserter(ticket);
557 | }
558 |
559 | @Override
560 | public String toString() {
561 | return String.format("%s, %s", ticketSystem.toString(), branchName);
562 | }
563 | }
564 |
565 | @RequiredArgsConstructor
566 | static class TicketNameAsserter {
567 |
568 | private final Optional actualTicketName;
569 |
570 | void doAssertion(String expectedTicketName) {
571 | assertThat(actualTicketName.isPresent(), is(true));
572 | assertThat(actualTicketName.get(), is(expectedTicketName));
573 | }
574 | }
575 | }
576 |
--------------------------------------------------------------------------------