mirror of https://github.com/halo-dev/halo
Fix the problem of theme version compatibility (#1705)
parent
9897999e51
commit
03006e8f35
|
@ -4,7 +4,6 @@ import static run.halo.app.model.properties.PrimaryProperties.THEME;
|
|||
import static run.halo.app.model.support.HaloConst.DEFAULT_THEME_ID;
|
||||
import static run.halo.app.utils.FileUtils.copyFolder;
|
||||
import static run.halo.app.utils.FileUtils.deleteFolderQuietly;
|
||||
import static run.halo.app.utils.VersionUtil.compareVersion;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
@ -32,6 +31,7 @@ import run.halo.app.model.entity.Option;
|
|||
import run.halo.app.model.support.HaloConst;
|
||||
import run.halo.app.theme.ThemePropertyScanner;
|
||||
import run.halo.app.utils.FileUtils;
|
||||
import run.halo.app.utils.Version;
|
||||
|
||||
/**
|
||||
* Theme repository implementation.
|
||||
|
@ -187,9 +187,10 @@ public class ThemeRepositoryImpl
|
|||
@Override
|
||||
public boolean checkThemePropertyCompatibility(ThemeProperty themeProperty) {
|
||||
// check version compatibility
|
||||
// Not support current halo version.
|
||||
return StringUtils.isNotEmpty(themeProperty.getRequire())
|
||||
&& !compareVersion(HaloConst.HALO_VERSION, themeProperty.getRequire());
|
||||
String requiredVersion = themeProperty.getRequire();
|
||||
return Version.resolve(HaloConst.HALO_VERSION)
|
||||
.map(current -> current.compatible(requiredVersion))
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
private Path getThemeRootPath() {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package run.halo.app.utils;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -21,7 +23,7 @@ import run.halo.app.model.support.HaloConst;
|
|||
@ToString
|
||||
@EqualsAndHashCode
|
||||
@Slf4j
|
||||
public class Version implements Comparable<Version> {
|
||||
public class Version {
|
||||
|
||||
/**
|
||||
* Regex expression.
|
||||
|
@ -156,25 +158,59 @@ public class Version implements Comparable<Version> {
|
|||
StringUtils.isNotBlank(preReleaseMajor) ? Long.parseLong(preReleaseMajor) : null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NonNull Version anotherVersion) {
|
||||
/**
|
||||
* Check if the current version is compatible with the target version.
|
||||
*
|
||||
* @param target target version must not be blank.
|
||||
* @return true if the current version is compatible with the target version; false otherwise.
|
||||
*/
|
||||
public boolean compatible(String target) {
|
||||
Version targetVersion = resolve(target).orElse(emptyVersion());
|
||||
// compare major
|
||||
int majorCompare = Long.compare(major, anotherVersion.major);
|
||||
int majorCompare = Long.compare(major, targetVersion.major);
|
||||
if (majorCompare != 0) {
|
||||
return majorCompare;
|
||||
return majorCompare > 0;
|
||||
}
|
||||
// compare minor
|
||||
int minorCompare = Long.compare(minor, anotherVersion.minor);
|
||||
int minorCompare = Long.compare(minor, targetVersion.minor);
|
||||
if (minorCompare != 0) {
|
||||
return minorCompare;
|
||||
return minorCompare > 0;
|
||||
}
|
||||
// compare patch
|
||||
int patchCompare = Long.compare(patch, anotherVersion.patch);
|
||||
int patchCompare = Long.compare(patch, targetVersion.patch);
|
||||
if (patchCompare != 0) {
|
||||
return patchCompare;
|
||||
return patchCompare > 0;
|
||||
}
|
||||
// if all the major, minor and patch are the same, then compare pre release number
|
||||
return Long.compare(preReleaseMajor, anotherVersion.preReleaseMajor);
|
||||
|
||||
// here means that all major, minor and patch number are the same.
|
||||
if (!this.isPreRelease() || !targetVersion.isPreRelease()) {
|
||||
return true;
|
||||
}
|
||||
// compare pre-release tag
|
||||
int preReleaseTagCompare =
|
||||
PreRelease.ALPHA.compare(
|
||||
Objects.requireNonNull(this.preRelease),
|
||||
Objects.requireNonNull(targetVersion.preRelease));
|
||||
if (preReleaseTagCompare != 0) {
|
||||
return preReleaseTagCompare > 0;
|
||||
}
|
||||
|
||||
// compare pre-release number
|
||||
long preReleaseNumberCompare = this.preReleaseMajor - targetVersion.preReleaseMajor;
|
||||
if (preReleaseNumberCompare != 0) {
|
||||
return preReleaseNumberCompare > 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if current version is a pre-release version.
|
||||
*
|
||||
* @return true if current version is a pre-release version; false otherwise.
|
||||
*/
|
||||
public boolean isPreRelease() {
|
||||
return preRelease != null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -182,22 +218,32 @@ public class Version implements Comparable<Version> {
|
|||
*
|
||||
* @author johnniang
|
||||
*/
|
||||
public enum PreRelease {
|
||||
|
||||
/**
|
||||
* Beta.
|
||||
*/
|
||||
BETA,
|
||||
public enum PreRelease implements Comparator<PreRelease> {
|
||||
|
||||
/**
|
||||
* Alpha.
|
||||
*/
|
||||
ALPHA,
|
||||
ALPHA(1),
|
||||
|
||||
/**
|
||||
* Beta.
|
||||
*/
|
||||
BETA(2),
|
||||
|
||||
/**
|
||||
* Release candidate.
|
||||
*/
|
||||
RC;
|
||||
RC(3);
|
||||
|
||||
/**
|
||||
* Lower priority means the pre-release is earlier than others.
|
||||
* Compare order: ALPHA < BETA < RC
|
||||
*/
|
||||
private final int priority;
|
||||
|
||||
PreRelease(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static PreRelease of(@Nullable String preReleaseStr) {
|
||||
|
@ -209,5 +255,10 @@ public class Version implements Comparable<Version> {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(PreRelease left, PreRelease right) {
|
||||
return left.priority - right.priority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,19 +16,6 @@ public final class VersionUtil {
|
|||
private VersionUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare version.
|
||||
*
|
||||
* @param current current version.
|
||||
* @param require require version.
|
||||
* @return true or false.
|
||||
*/
|
||||
public static boolean compareVersion(String current, String require) {
|
||||
Version leftVersion = Version.resolve(current).orElse(Version.emptyVersion());
|
||||
Version rightVersion = Version.resolve(require).orElse(Version.emptyVersion());
|
||||
return leftVersion.compareTo(rightVersion) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two versions to see if they have the same major and minor versions.
|
||||
*
|
||||
|
|
|
@ -2,10 +2,15 @@ package run.halo.app.utils;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static run.halo.app.utils.Version.PreRelease.ALPHA;
|
||||
import static run.halo.app.utils.Version.PreRelease.BETA;
|
||||
import static run.halo.app.utils.Version.PreRelease.RC;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
@ -118,13 +123,13 @@ class VersionTest {
|
|||
String version = major + "." + minor + "." + patch + "-alpha." + preReleaseMajor;
|
||||
Optional<Version> versionOpt = Version.resolve(version);
|
||||
assertTrue(versionOpt.isPresent());
|
||||
assertEquals(new Version(major, minor, patch, Version.PreRelease.ALPHA, preReleaseMajor),
|
||||
assertEquals(new Version(major, minor, patch, ALPHA, preReleaseMajor),
|
||||
versionOpt.get());
|
||||
|
||||
version = major + "." + minor + "." + patch + "-beta." + preReleaseMajor;
|
||||
versionOpt = Version.resolve(version);
|
||||
assertTrue(versionOpt.isPresent());
|
||||
assertEquals(new Version(major, minor, patch, Version.PreRelease.BETA, preReleaseMajor),
|
||||
assertEquals(new Version(major, minor, patch, BETA, preReleaseMajor),
|
||||
versionOpt.get());
|
||||
|
||||
version = major + "." + minor + "." + patch + "-rc." + preReleaseMajor;
|
||||
|
@ -141,44 +146,72 @@ class VersionTest {
|
|||
unknownVersionOpt.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void compareTest() {
|
||||
final Version leftVersion = getVersion("1.2.3");
|
||||
// compare with own
|
||||
assertEquals(0, leftVersion.compareTo(leftVersion));
|
||||
|
||||
// compare with others
|
||||
Version rightVersion = getVersion("1.2.4");
|
||||
assertTrue(leftVersion.compareTo(rightVersion) < 0);
|
||||
|
||||
rightVersion = getVersion("1.3.3");
|
||||
assertTrue(leftVersion.compareTo(rightVersion) < 0);
|
||||
|
||||
rightVersion = getVersion("2.2.3");
|
||||
assertTrue(leftVersion.compareTo(rightVersion) < 0);
|
||||
|
||||
rightVersion = getVersion("0.2.3");
|
||||
assertTrue(leftVersion.compareTo(rightVersion) > 0);
|
||||
|
||||
rightVersion = getVersion("1.1.3");
|
||||
assertTrue(leftVersion.compareTo(rightVersion) > 0);
|
||||
|
||||
rightVersion = getVersion("1.2.2");
|
||||
assertTrue(leftVersion.compareTo(rightVersion) > 0);
|
||||
|
||||
rightVersion = getVersion("1.2.3-alpha.0");
|
||||
assertTrue(leftVersion.compareTo(rightVersion) > 0);
|
||||
|
||||
rightVersion = getVersion("1.2.4-alpha.0");
|
||||
assertTrue(leftVersion.compareTo(rightVersion) < 0);
|
||||
|
||||
// compare with unknown version
|
||||
assertTrue(leftVersion.compareTo(getVersion(HaloConst.UNKNOWN_VERSION)) < 0);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
Version getVersion(String version) {
|
||||
return Version.resolve(version)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Invalid version"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void compatibleTest() {
|
||||
@Data
|
||||
class Table {
|
||||
final String current;
|
||||
final String required;
|
||||
final boolean wantCompatible;
|
||||
}
|
||||
|
||||
for (Table tt : new Table[] {
|
||||
// compatible
|
||||
new Table("1.5.0", "1.5.0", true),
|
||||
new Table("1.5.0", "1.4.0", true),
|
||||
new Table("1.5.0", "0.5.0", true),
|
||||
new Table("1.5.0-alpha.1", "1.5.0", true),
|
||||
new Table("1.5.0-beta.1", "1.5.0", true),
|
||||
new Table("1.5.0-rc.1", "1.5.0", true),
|
||||
new Table("1.5.0-alpha.2", "1.5.0-alpha.1", true),
|
||||
new Table("1.5.0-beta.1", "1.5.0-alpha.2", true),
|
||||
new Table("1.5.0-rc.1", "1.5.0-beta.2", true),
|
||||
new Table("1.5.0", "1.5.0-alpha.1", true),
|
||||
new Table("1.5.0", "1.5.0-beta.1", true),
|
||||
new Table("1.5.0", "1.5.0-rc.1", true),
|
||||
new Table("1.5.0", "1.5.0-rc.1", true),
|
||||
new Table("1.5.0", "", true),
|
||||
new Table("1.5.0", null, true),
|
||||
new Table(HaloConst.UNKNOWN_VERSION, "1.5.0", true),
|
||||
|
||||
// incompatible
|
||||
new Table("1.5.0", "1.5.1", false),
|
||||
new Table("1.5.0", "1.6.0", false),
|
||||
new Table("1.5.0", "2.5.0", false),
|
||||
new Table("1.5.0-alpha.1", "1.5.0-alpha.2", false),
|
||||
new Table("1.5.0-alpha.2", "1.5.0-beta.1", false),
|
||||
new Table("1.5.0-beta.2", "1.5.0-rc.1", false),
|
||||
}) {
|
||||
Version current = Version.resolve(tt.current).orElse(null);
|
||||
assertNotNull(current);
|
||||
boolean compatible = current.compatible(tt.required);
|
||||
assertEquals(tt.wantCompatible, compatible,
|
||||
() -> String.format("Want: %s, but got compatible: %s", tt, compatible));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void isPreRelease() {
|
||||
assertFalse(new Version(0, 0, 0, null, 0L).isPreRelease());
|
||||
assertTrue(new Version(0, 0, 0, ALPHA, 0L).isPreRelease());
|
||||
}
|
||||
|
||||
@Test
|
||||
void preReleaseTagCompare() {
|
||||
assertTrue(ALPHA.compare(ALPHA, BETA) < 0);
|
||||
assertTrue(ALPHA.compare(ALPHA, RC) < 0);
|
||||
assertTrue(ALPHA.compare(BETA, ALPHA) > 0);
|
||||
assertTrue(ALPHA.compare(BETA, RC) < 0);
|
||||
assertTrue(ALPHA.compare(RC, ALPHA) > 0);
|
||||
assertTrue(ALPHA.compare(RC, BETA) > 0);
|
||||
assertEquals(0, ALPHA.compare(ALPHA, ALPHA));
|
||||
assertEquals(0, ALPHA.compare(BETA, BETA));
|
||||
assertEquals(0, ALPHA.compare(RC, RC));
|
||||
}
|
||||
}
|
|
@ -1,10 +1,7 @@
|
|||
package run.halo.app.utils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import run.halo.app.model.support.HaloConst;
|
||||
|
||||
|
@ -14,26 +11,6 @@ import run.halo.app.model.support.HaloConst;
|
|||
*/
|
||||
class VersionUtilTest {
|
||||
|
||||
@Test
|
||||
void compareVersion() {
|
||||
assertTrue(VersionUtil.compareVersion("1.2.0", "1.1.1"));
|
||||
assertTrue(VersionUtil.compareVersion("1.2.1", "1.2.0"));
|
||||
assertTrue(VersionUtil.compareVersion("1.2.0", "1.1.1"));
|
||||
assertTrue(VersionUtil.compareVersion("1.2.0", "0.4.4"));
|
||||
assertFalse(VersionUtil.compareVersion("1.1.1", "1.2.0"));
|
||||
assertFalse(VersionUtil.compareVersion("0.0.1", "1.2.0"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void unknownVersionCompareTest() {
|
||||
// build a random version
|
||||
String randomVersion = String.join(".",
|
||||
RandomStringUtils.randomNumeric(1),
|
||||
RandomStringUtils.randomNumeric(2),
|
||||
RandomStringUtils.randomNumeric(3));
|
||||
assertTrue(VersionUtil.compareVersion(HaloConst.UNKNOWN_VERSION, randomVersion));
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasSameMajorAndMinorVersionTest() {
|
||||
assertThat(
|
||||
|
@ -53,4 +30,5 @@ class VersionUtilTest {
|
|||
|
||||
assertThat(VersionUtil.hasSameMajorAndMinorVersion(null, null)).isTrue();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue