diff --git a/pom.xml b/pom.xml index 581dd8e3..410ec67e 100644 --- a/pom.xml +++ b/pom.xml @@ -66,13 +66,12 @@ ${project.groupId} git-commit-id-plugin-core - 6.1.5 + 6.2.0 - com.google.code.findbugs - jsr305 - 3.0.2 - true + org.jspecify + jspecify + 1.0.0 @@ -326,8 +325,8 @@ - com.google.code.findbugs - jsr305 + org.jspecify + jspecify diff --git a/src/main/java/pl/project13/maven/git/GitCommitIdMojo.java b/src/main/java/pl/project13/maven/git/GitCommitIdMojo.java index 9e1557ec..d454de7e 100644 --- a/src/main/java/pl/project13/maven/git/GitCommitIdMojo.java +++ b/src/main/java/pl/project13/maven/git/GitCommitIdMojo.java @@ -24,6 +24,8 @@ import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.Collections; import java.util.Date; import java.util.List; @@ -31,8 +33,6 @@ import java.util.Optional; import java.util.Properties; import java.util.function.Supplier; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecution; @@ -44,7 +44,8 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import org.apache.maven.settings.Settings; -import org.joda.time.DateTime; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; import org.sonatype.plexus.build.incremental.BuildContext; import pl.project13.core.CommitIdGenerationMode; import pl.project13.core.CommitIdPropertiesOutputFormat; @@ -1279,25 +1280,25 @@ public Supplier supplyProjectVersion() { return () -> project.getVersion(); } - @Nonnull + @NonNull @Override public LogInterface getLogInterface() { return log; } - @Nonnull + @NonNull @Override public String getDateFormat() { return dateFormat; } - @Nonnull + @NonNull @Override public String getDateFormatTimeZone() { return dateFormatTimeZone; } - @Nonnull + @NonNull @Override public String getPrefixDot() { String trimmedPrefix = prefix.trim(); @@ -1443,8 +1444,8 @@ public boolean isPerModuleVersions() { } private void publishToAllSystemEnvironments( - @Nonnull LogInterface log, - @Nonnull Properties propertiesToPublish, + @NonNull LogInterface log, + @NonNull Properties propertiesToPublish, @Nullable Properties contextProperties) { publishPropertiesInto(propertiesToPublish, project.getProperties()); // some plugins rely on the user properties (e.g. flatten-maven-plugin) @@ -1505,7 +1506,44 @@ protected static Date parseOutputTimestamp(String outputTimestamp) { // no timestamp configured return null; } - return new DateTime(outputTimestamp).toDate(); + // Normalize the timestamp to handle common variations + String normalized = outputTimestamp.trim(); + + // Handle lowercase designators + normalized = normalized.replace('t', 'T').replace('z', 'Z'); + + // Handle hours-only offsets by adding :00 minutes if needed + if (normalized.matches(".*[+-]\\d{2}$")) { + normalized = normalized.substring(0, normalized.length() - 3) + + normalized.substring(normalized.length() - 3) + ":00"; + } + + // Try parsing with different formatters in order of preference + DateTimeFormatter[] formatters = { + DateTimeFormatter.ISO_INSTANT, // 2022-02-12T15:30:00Z + DateTimeFormatter.ISO_OFFSET_DATE_TIME, // 2022-02-12T15:30+00:00 + DateTimeFormatter.ISO_LOCAL_DATE_TIME, // 2022-02-12T15:30:00 + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mmZ"), // 2019-03-26T10:00-0400 + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"), // 2019-03-26T10:00:00-0400 + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm") // 2022-02-12T15:30 + }; + + for (DateTimeFormatter formatter : formatters) { + try { + if ( + formatter == DateTimeFormatter.ISO_LOCAL_DATE_TIME + && + (normalized.contains("+") || normalized.contains("-") || normalized.endsWith("Z")) + ) { + continue; // Skip local formatter for timestamps with timezones + } + return Date.from(Instant.from(formatter.parse(normalized))); + } catch (DateTimeParseException ignore) { + // Try next formatter + } + } + + throw new IllegalArgumentException("Unable to parse timestamp: " + outputTimestamp); } private void publishPropertiesInto(Properties propertiesToPublish, Properties propertiesTarget) { @@ -1536,7 +1574,7 @@ private void logProperties(LogInterface log, Properties propertiesToPublish) { } } - private boolean isPomProject(@Nonnull MavenProject project) { + private boolean isPomProject(@NonNull MavenProject project) { return project.getPackaging().equalsIgnoreCase("pom"); } } diff --git a/src/test/java/pl/project13/core/jgit/DescribeCommandIntegrationTest.java b/src/test/java/pl/project13/core/jgit/DescribeCommandIntegrationTest.java index 58560703..2772096b 100644 --- a/src/test/java/pl/project13/core/jgit/DescribeCommandIntegrationTest.java +++ b/src/test/java/pl/project13/core/jgit/DescribeCommandIntegrationTest.java @@ -26,12 +26,12 @@ import java.util.Collections; import java.util.Optional; -import javax.annotation.Nonnull; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ResetCommand; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.Test; import pl.project13.log.DummyTestLoggerBridge; import pl.project13.maven.git.AvailableGitTestRepo; @@ -448,11 +448,11 @@ public void shouldReturnJustTheNearestTagWhenAbbrevIsZero() throws Exception { } } - String abbrev(@Nonnull String id) { + String abbrev(@NonNull String id) { return abbrev(id, DEFAULT_ABBREV_LEN); } - String abbrev(@Nonnull String id, int n) { + String abbrev(@NonNull String id, int n) { return id.substring(0, n); } } diff --git a/src/test/java/pl/project13/maven/git/AvailableGitTestRepo.java b/src/test/java/pl/project13/maven/git/AvailableGitTestRepo.java index 0eb5bed3..c61c8657 100644 --- a/src/test/java/pl/project13/maven/git/AvailableGitTestRepo.java +++ b/src/test/java/pl/project13/maven/git/AvailableGitTestRepo.java @@ -19,7 +19,7 @@ package pl.project13.maven.git; import java.io.File; -import javax.annotation.Nonnull; +import org.jspecify.annotations.NonNull; /** * List of available git repositories that we can use to perform tests with. @@ -168,7 +168,7 @@ public enum AvailableGitTestRepo { this.dir = dir; } - @Nonnull + @NonNull public File getDir() { return new File(dir); } diff --git a/src/test/java/pl/project13/maven/git/ContainsKeyCondition.java b/src/test/java/pl/project13/maven/git/ContainsKeyCondition.java index e172a9f2..bf23b944 100644 --- a/src/test/java/pl/project13/maven/git/ContainsKeyCondition.java +++ b/src/test/java/pl/project13/maven/git/ContainsKeyCondition.java @@ -19,8 +19,8 @@ package pl.project13.maven.git; import java.util.Map; -import javax.annotation.Nonnull; import org.assertj.core.api.Condition; +import org.jspecify.annotations.NonNull; class ContainsKeyCondition extends Condition> { @@ -31,7 +31,7 @@ public ContainsKeyCondition(String key) { } @Override - public boolean matches(@Nonnull Map map) { + public boolean matches(@NonNull Map map) { boolean containsKey = map.containsKey(key); if (!containsKey) { throw new RuntimeException( diff --git a/src/test/java/pl/project13/maven/git/DoesNotContainKeyCondition.java b/src/test/java/pl/project13/maven/git/DoesNotContainKeyCondition.java index 49f13b0e..e863a8a8 100644 --- a/src/test/java/pl/project13/maven/git/DoesNotContainKeyCondition.java +++ b/src/test/java/pl/project13/maven/git/DoesNotContainKeyCondition.java @@ -19,8 +19,8 @@ package pl.project13.maven.git; import java.util.Map; -import javax.annotation.Nonnull; import org.assertj.core.api.Condition; +import org.jspecify.annotations.NonNull; class DoesNotContainKeyCondition extends Condition> { @@ -31,7 +31,7 @@ public DoesNotContainKeyCondition(String key) { } @Override - public boolean matches(@Nonnull Map map) { + public boolean matches(@NonNull Map map) { boolean containsKey = map.containsKey(key); if (containsKey) { System.out.println(String.format("Map contained [%s] key! Map is: %s", key, map)); diff --git a/src/test/java/pl/project13/maven/git/FileSystemMavenSandbox.java b/src/test/java/pl/project13/maven/git/FileSystemMavenSandbox.java index 93df7e06..cb0e7975 100644 --- a/src/test/java/pl/project13/maven/git/FileSystemMavenSandbox.java +++ b/src/test/java/pl/project13/maven/git/FileSystemMavenSandbox.java @@ -21,10 +21,10 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import org.apache.commons.io.FileUtils; import org.apache.maven.project.MavenProject; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; /** * Quick and dirty maven projects tree structure to create on disk during integration tests. Can @@ -50,20 +50,20 @@ public FileSystemMavenSandbox(String rootSandboxPath) { this.rootSandboxPath = rootSandboxPath; } - @Nonnull + @NonNull public FileSystemMavenSandbox withParentProject(String parentProjectDirName, String packaging) { parentProject = createProject(new File(rootSandboxPath + File.separator + parentProjectDirName), packaging); return this; } - @Nonnull + @NonNull public FileSystemMavenSandbox withNoChildProject() { // no-op: marker for better tests readability return this; } - @Nonnull + @NonNull public FileSystemMavenSandbox withChildProject(String childProjectDirName, String packaging) { childProject = createProject(new File(parentProject.getBasedir(), childProjectDirName), packaging); @@ -71,8 +71,8 @@ public FileSystemMavenSandbox withChildProject(String childProjectDirName, Strin return this; } - @Nonnull - public FileSystemMavenSandbox withGitRepoInParent(@Nonnull AvailableGitTestRepo repo) { + @NonNull + public FileSystemMavenSandbox withGitRepoInParent(@NonNull AvailableGitTestRepo repo) { System.out.println("TEST: Will prepare sandbox repository based on: [" + repo.getDir() + "]"); gitRepoSourceDir = repo.getDir(); @@ -80,27 +80,27 @@ public FileSystemMavenSandbox withGitRepoInParent(@Nonnull AvailableGitTestRepo return this; } - @Nonnull - public FileSystemMavenSandbox withGitRepoInChild(@Nonnull AvailableGitTestRepo repo) { + @NonNull + public FileSystemMavenSandbox withGitRepoInChild(@NonNull AvailableGitTestRepo repo) { gitRepoSourceDir = repo.getDir(); gitRepoTargetDir = childProject.getBasedir(); return this; } - @Nonnull - public FileSystemMavenSandbox withGitRepoAboveParent(@Nonnull AvailableGitTestRepo repo) { + @NonNull + public FileSystemMavenSandbox withGitRepoAboveParent(@NonNull AvailableGitTestRepo repo) { gitRepoSourceDir = repo.getDir(); gitRepoTargetDir = new File(rootSandboxPath); return this; } - @Nonnull + @NonNull public FileSystemMavenSandbox withNoGitRepoAvailable() { gitRepoTargetDir = null; return this; } - @Nonnull + @NonNull public FileSystemMavenSandbox create() throws RuntimeException { try { createParentDir(); @@ -145,7 +145,7 @@ public MavenProject getChildProject() { return childProject; } - @Nonnull + @NonNull private MavenProject createProject(File basedir, String packaging) { MavenProject project = new MavenProject(); project.setFile(new File(basedir + File.separator + "pom.xml")); @@ -166,7 +166,7 @@ public String toString() { + '}'; } - @Nonnull + @NonNull public FileSystemMavenSandbox withKeepSandboxWhenFinishedTest( boolean keepSandboxWhenFinishedTest) { // if we want to keep the generated sandbox for overwiew the content of it diff --git a/src/test/java/pl/project13/maven/git/GitIntegrationTest.java b/src/test/java/pl/project13/maven/git/GitIntegrationTest.java index f90414b8..88b93e61 100644 --- a/src/test/java/pl/project13/maven/git/GitIntegrationTest.java +++ b/src/test/java/pl/project13/maven/git/GitIntegrationTest.java @@ -18,7 +18,6 @@ package pl.project13.maven.git; -import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -27,18 +26,17 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Optional; import java.util.Properties; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Stream; -import javax.annotation.Nonnull; import org.apache.commons.io.FileUtils; import org.apache.maven.execution.MavenSession; import org.apache.maven.project.MavenProject; import org.apache.maven.settings.Settings; import org.eclipse.jgit.api.Git; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.provider.Arguments; @@ -115,8 +113,8 @@ protected Optional projectDir() { return Optional.empty(); } - @Nonnull - protected File dotGitDir(@Nonnull Optional projectDir) { + @NonNull + protected File dotGitDir(@NonNull Optional projectDir) { if (projectDir.isPresent()) { return new File(currSandbox + File.separator + projectDir.get() + File.separator + ".git"); } else { @@ -143,7 +141,7 @@ public static void initializeMojoWithDefaults(GitCommitIdMojo mojo) { mojo.settings = mockSettings(); } - public void setProjectToExecuteMojoIn(@Nonnull MavenProject project) { + public void setProjectToExecuteMojoIn(@NonNull MavenProject project) { mojo.project = project; mojo.dotGitDirectory = new File(project.getBasedir(), ".git"); mojo.reactorProjects = getReactorProjects(project); @@ -162,7 +160,7 @@ private static Settings mockSettings() { return settings; } - private static List getReactorProjects(@Nonnull MavenProject project) { + private static List getReactorProjects(@NonNull MavenProject project) { List reactorProjects = new ArrayList<>(); MavenProject mavenProject = project; while (mavenProject != null) { diff --git a/src/test/java/pl/project13/maven/jgit/DescribeCommandAbbrevIntegrationTest.java b/src/test/java/pl/project13/maven/jgit/DescribeCommandAbbrevIntegrationTest.java index c17bf536..e745a3d8 100644 --- a/src/test/java/pl/project13/maven/jgit/DescribeCommandAbbrevIntegrationTest.java +++ b/src/test/java/pl/project13/maven/jgit/DescribeCommandAbbrevIntegrationTest.java @@ -21,9 +21,9 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.Optional; -import javax.annotation.Nonnull; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.lib.Repository; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.Test; import pl.project13.core.jgit.DescribeCommand; import pl.project13.core.jgit.DescribeResult; @@ -113,7 +113,7 @@ public void onGitCommitIdsRepo_shouldNoticeThat2CharsIsTooLittleToBeUniqueAndUse } } - String abbrev(@Nonnull String id, int n) { + String abbrev(@NonNull String id, int n) { return id.substring(0, n); } }