Skip to content

Commit 4938231

Browse files
committed
Simplify encroaching version logic
This change eliminates the general regex in favor of building an artifact-specific regex, which is more likely to match only file paths of actually encroaching versions. We also now check only the target installation directory, as opposed to all directories, for encroaching versions, which should help eliminate certain types of false positives.
1 parent d8121b9 commit 4938231

File tree

6 files changed

+65
-273
lines changed

6 files changed

+65
-273
lines changed

src/it/delete-other-versions-in-subdirectory/pom.xml

Lines changed: 0 additions & 66 deletions
This file was deleted.

src/it/delete-other-versions-in-subdirectory/setup.bsh

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/it/delete-other-versions-in-subdirectory/src/main/resources/plugins.config

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/it/delete-other-versions-in-subdirectory/verify.bsh

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/it/handle-missing-version-numbers/verify.bsh

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@
2929
source(new File(basedir, "../../../src/it/lib.bsh").getPath());
3030

3131
jars = new File(ijDir, "jars");
32-
assertTrue("Has missing-version-number-1.0.0.jar",
33-
!new File(jars, "missing-version-number-1.0.0.jar").exists());
34-
35-
buildLog = readFile(new File(basedir, "build.log"));
36-
assertTrue("Should contain 'Impenetrable version suffix':\n" + buildLog,
37-
buildLog.contains("Impenetrable version suffix"));
32+
assertTrue("Unexpectedly absent: missing-version-number-1.0.0.jar",
33+
new File(jars, "missing-version-number-1.0.0.jar").exists());
34+
assertTrue("Unexpectedly present: missing-version-number.jar",
35+
!new File(jars, "missing-version-number.jar").exists());

src/main/java/org/scijava/maven/plugin/install/AbstractInstallMojo.java

Lines changed: 61 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,14 @@
3535
import java.nio.file.Path;
3636
import java.nio.file.Paths;
3737
import java.util.ArrayList;
38-
import java.util.Arrays;
39-
import java.util.Collection;
4038
import java.util.Collections;
39+
import java.util.LinkedHashMap;
4140
import java.util.List;
41+
import java.util.Map;
4242
import java.util.jar.JarEntry;
4343
import java.util.jar.JarFile;
4444
import java.util.regex.Matcher;
4545
import java.util.regex.Pattern;
46-
import java.util.stream.Collectors;
4746

4847
import org.apache.maven.artifact.Artifact;
4948
import org.apache.maven.execution.MavenSession;
@@ -215,48 +214,35 @@ else if (isBioFormatsArtifact(artifact)) {
215214
final File target = new File(targetDirectory, fileName);
216215

217216
boolean newerVersion = false;
218-
final Path directoryPath = Paths.get(appDir.toURI());
219217
final Path targetPath = Paths.get(target.toURI());
220-
final Collection<Path> otherVersions = //
221-
getEncroachingVersions(directoryPath, targetPath);
222-
if (otherVersions != null && !otherVersions.isEmpty()) {
223-
for (final Path other : otherVersions) {
224-
final Path otherName = other.getFileName();
225-
switch (otherVersionsPolicy) {
226-
case never:
227-
getLog().warn("Possibly incompatible version exists: " + otherName);
228-
break;
229-
case older:
230-
final String toInstall = artifact.getVersion();
231-
final Matcher matcher = VERSION_PATTERN.matcher(otherName.toString());
232-
if (!matcher.matches()) break;
233-
final String group = matcher.group(VERSION_INDEX);
234-
if (group == null) {
235-
newerVersion = true;
236-
getLog().warn("Impenetrable version suffix for file: " +
237-
otherName);
238-
}
239-
else {
240-
final String otherVersion = group.substring(1);
241-
newerVersion = VersionUtils.compare(toInstall, otherVersion) < 0;
242-
final String majorVersionToInstall = majorVersion(toInstall);
243-
final String majorVersionOther = majorVersion(otherVersion);
244-
if (!majorVersionToInstall.equals(majorVersionOther)) {
245-
getLog().warn("Version " + otherVersion + " of " + artifact +
246-
" is incompatible according to SemVer: " +
247-
majorVersionToInstall + " != " + majorVersionOther);
248-
}
249-
}
250-
if (newerVersion) break;
251-
//$FALL-THROUGH$
252-
case always:
253-
if (Files.deleteIfExists(other)) {
254-
getLog().info("Deleted overridden " + otherName);
255-
newerVersion = false;
256-
}
257-
else getLog().warn("Could not delete overridden " + otherName);
258-
break;
259-
}
218+
final Map<Path, String> otherVersions = //
219+
getEncroachingVersions(targetPath.getParent(), artifact);
220+
for (final Path other : otherVersions.keySet()) {
221+
final Path otherName = other.getFileName();
222+
switch (otherVersionsPolicy) {
223+
case never:
224+
getLog().warn("Possibly incompatible version exists: " + otherName);
225+
break;
226+
case older:
227+
final String toInstall = artifact.getVersion();
228+
final String otherVersion = otherVersions.get(other);
229+
newerVersion = VersionUtils.compare(toInstall, otherVersion) < 0;
230+
final String majorVersionToInstall = majorVersion(toInstall);
231+
final String majorVersionOther = majorVersion(otherVersion);
232+
if (!majorVersionToInstall.equals(majorVersionOther)) {
233+
getLog().warn("Version " + otherVersion + " of " + artifact +
234+
" is incompatible according to SemVer: " +
235+
majorVersionToInstall + " != " + majorVersionOther);
236+
}
237+
if (newerVersion) break;
238+
//$FALL-THROUGH$
239+
case always:
240+
if (Files.deleteIfExists(other)) {
241+
getLog().info("Deleted overridden " + otherName);
242+
newerVersion = false;
243+
}
244+
else getLog().warn("Could not delete overridden " + otherName);
245+
break;
260246
}
261247
}
262248

@@ -321,34 +307,6 @@ private String subdirectory(final Artifact artifact) {
321307
return null;
322308
}
323309

324-
private final static Pattern VERSION_PATTERN = Pattern.compile(versionPattern());
325-
326-
private static String versionPattern() {
327-
final String[] other = {
328-
"javadoc", "native", "sources", "swing", "swt"
329-
};
330-
final List<String> classifiers = new ArrayList<>();
331-
for (final String family : KnownPlatforms.FAMILIES) {
332-
classifiers.add(family);
333-
classifiers.add("native-" + family);
334-
classifiers.add("natives-" + family);
335-
for (final String arch : KnownPlatforms.ARCHES) {
336-
final String slug = family + "-" + arch;
337-
classifiers.add(slug);
338-
classifiers.add("native-" + slug);
339-
classifiers.add("natives-" + slug);
340-
}
341-
}
342-
classifiers.addAll(Arrays.asList(other));
343-
return "(.+?)"
344-
+ "(-\\d+(\\.\\d+|\\d{7})+[a-z]?\\d?(-[A-Za-z0-9.]+?|\\.GA)*?)?"
345-
+ "((-(" + String.join("|", classifiers) + "))?(\\.jar(-[a-z]*)?))";
346-
}
347-
348-
private final static int PREFIX_INDEX = 1;
349-
private final static int VERSION_INDEX = 2;
350-
private final static int SUFFIX_INDEX = 5;
351-
352310
/**
353311
* Extracts the major version (according to SemVer) from a version string.
354312
* If no dot is found, the input is returned.
@@ -364,38 +322,44 @@ private static String majorVersion( String v )
364322
}
365323

366324
/**
367-
* Looks for files in {@code directory} with the same base name as
368-
* {@code file}.
325+
* Looks for existing versions of the given artifact in {@code directory}.
369326
*
370327
* @param directory The directory to walk to find possible duplicates.
371-
* @param file A {@link Path} to the target (from which the base name is
372-
* derived).
373-
* @return A collection of {@link Path}s to files of the same base name.
328+
* @param artifact The target's Maven {@link Artifact}.
329+
* @return A table identifying other versions of the artifact. Each key is a
330+
* file path to another version, and each value its version string.
374331
*/
375-
private Collection<Path> getEncroachingVersions(final Path directory, final Path file) {
376-
final Matcher matcher = VERSION_PATTERN.matcher(file.getFileName().toString());
377-
if (!matcher.matches()) return null;
332+
private Map<Path, String> getEncroachingVersions(final Path directory,
333+
final Artifact artifact)
334+
{
335+
final Map<Path, String> result = new LinkedHashMap<>();
336+
if (!directory.toFile().exists()) return result;
337+
if (!directory.toFile().isDirectory()) {
338+
throw new IllegalArgumentException("Not a directory: " + directory);
339+
}
378340

379-
final String prefix = matcher.group(PREFIX_INDEX);
380-
final String suffix = matcher.group(SUFFIX_INDEX);
341+
// Construct a regex for the artifact, of the form:
342+
//
343+
// artifactId-version-classifier.type
344+
//
345+
// with '-classifier' absent for the main classifier.
346+
final String classifier = artifact.getClassifier();
347+
final String patternString = artifact.getArtifactId() + "-?(.*)" +
348+
(classifier != null && !classifier.isEmpty() ? "-" + classifier : "") +
349+
"\\." + artifact.getType();
350+
final Pattern pattern = Pattern.compile(patternString);
381351

382-
Collection<Path> result = new ArrayList<>();
383352
try {
384-
result = Files.walk(directory)
385-
.filter(path -> path.getFileName().toString().startsWith(prefix))
386-
.filter(path -> {
387-
final Matcher matcherIterator = VERSION_PATTERN.matcher(path.getFileName().toString());
388-
return matcherIterator.matches() &&
389-
prefix.equals(matcherIterator.group(PREFIX_INDEX)) &&
390-
suffix.equals(matcherIterator.group(SUFFIX_INDEX));
391-
})
392-
.filter(path -> !path.getFileName().toString().equals(file.getFileName().toString()))
393-
.collect(Collectors.toCollection(ArrayList::new));
394-
return result;
395-
} catch (IOException e) {
353+
Files.walk(directory, 1).forEach(path -> {
354+
final Matcher m = pattern.matcher(path.getFileName().toString());
355+
if (m.matches()) {
356+
final String version = m.group(1);
357+
result.put(path, version);
358+
}
359+
});
360+
}
361+
catch (IOException e) {
396362
getLog().error(e);
397-
} finally {
398-
result = new ArrayList<>();
399363
}
400364

401365
return result;

0 commit comments

Comments
 (0)