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.model.support.HaloConst.DEFAULT_THEME_ID;
|
||||||
import static run.halo.app.utils.FileUtils.copyFolder;
|
import static run.halo.app.utils.FileUtils.copyFolder;
|
||||||
import static run.halo.app.utils.FileUtils.deleteFolderQuietly;
|
import static run.halo.app.utils.FileUtils.deleteFolderQuietly;
|
||||||
import static run.halo.app.utils.VersionUtil.compareVersion;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
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.model.support.HaloConst;
|
||||||
import run.halo.app.theme.ThemePropertyScanner;
|
import run.halo.app.theme.ThemePropertyScanner;
|
||||||
import run.halo.app.utils.FileUtils;
|
import run.halo.app.utils.FileUtils;
|
||||||
|
import run.halo.app.utils.Version;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Theme repository implementation.
|
* Theme repository implementation.
|
||||||
|
@ -187,9 +187,10 @@ public class ThemeRepositoryImpl
|
||||||
@Override
|
@Override
|
||||||
public boolean checkThemePropertyCompatibility(ThemeProperty themeProperty) {
|
public boolean checkThemePropertyCompatibility(ThemeProperty themeProperty) {
|
||||||
// check version compatibility
|
// check version compatibility
|
||||||
// Not support current halo version.
|
String requiredVersion = themeProperty.getRequire();
|
||||||
return StringUtils.isNotEmpty(themeProperty.getRequire())
|
return Version.resolve(HaloConst.HALO_VERSION)
|
||||||
&& !compareVersion(HaloConst.HALO_VERSION, themeProperty.getRequire());
|
.map(current -> current.compatible(requiredVersion))
|
||||||
|
.orElse(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Path getThemeRootPath() {
|
private Path getThemeRootPath() {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package run.halo.app.utils;
|
package run.halo.app.utils;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
@ -21,7 +23,7 @@ import run.halo.app.model.support.HaloConst;
|
||||||
@ToString
|
@ToString
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class Version implements Comparable<Version> {
|
public class Version {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regex expression.
|
* Regex expression.
|
||||||
|
@ -156,25 +158,59 @@ public class Version implements Comparable<Version> {
|
||||||
StringUtils.isNotBlank(preReleaseMajor) ? Long.parseLong(preReleaseMajor) : null));
|
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
|
// compare major
|
||||||
int majorCompare = Long.compare(major, anotherVersion.major);
|
int majorCompare = Long.compare(major, targetVersion.major);
|
||||||
if (majorCompare != 0) {
|
if (majorCompare != 0) {
|
||||||
return majorCompare;
|
return majorCompare > 0;
|
||||||
}
|
}
|
||||||
// compare minor
|
// compare minor
|
||||||
int minorCompare = Long.compare(minor, anotherVersion.minor);
|
int minorCompare = Long.compare(minor, targetVersion.minor);
|
||||||
if (minorCompare != 0) {
|
if (minorCompare != 0) {
|
||||||
return minorCompare;
|
return minorCompare > 0;
|
||||||
}
|
}
|
||||||
// compare patch
|
// compare patch
|
||||||
int patchCompare = Long.compare(patch, anotherVersion.patch);
|
int patchCompare = Long.compare(patch, targetVersion.patch);
|
||||||
if (patchCompare != 0) {
|
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
|
* @author johnniang
|
||||||
*/
|
*/
|
||||||
public enum PreRelease {
|
public enum PreRelease implements Comparator<PreRelease> {
|
||||||
|
|
||||||
/**
|
|
||||||
* Beta.
|
|
||||||
*/
|
|
||||||
BETA,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alpha.
|
* Alpha.
|
||||||
*/
|
*/
|
||||||
ALPHA,
|
ALPHA(1),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Beta.
|
||||||
|
*/
|
||||||
|
BETA(2),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Release candidate.
|
* 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
|
@Nullable
|
||||||
static PreRelease of(@Nullable String preReleaseStr) {
|
static PreRelease of(@Nullable String preReleaseStr) {
|
||||||
|
@ -209,5 +255,10 @@ public class Version implements Comparable<Version> {
|
||||||
}
|
}
|
||||||
return null;
|
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() {
|
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.
|
* 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.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
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 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.Optional;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import lombok.Data;
|
||||||
import org.apache.commons.lang3.RandomUtils;
|
import org.apache.commons.lang3.RandomUtils;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.lang.NonNull;
|
import org.springframework.lang.NonNull;
|
||||||
|
@ -118,13 +123,13 @@ class VersionTest {
|
||||||
String version = major + "." + minor + "." + patch + "-alpha." + preReleaseMajor;
|
String version = major + "." + minor + "." + patch + "-alpha." + preReleaseMajor;
|
||||||
Optional<Version> versionOpt = Version.resolve(version);
|
Optional<Version> versionOpt = Version.resolve(version);
|
||||||
assertTrue(versionOpt.isPresent());
|
assertTrue(versionOpt.isPresent());
|
||||||
assertEquals(new Version(major, minor, patch, Version.PreRelease.ALPHA, preReleaseMajor),
|
assertEquals(new Version(major, minor, patch, ALPHA, preReleaseMajor),
|
||||||
versionOpt.get());
|
versionOpt.get());
|
||||||
|
|
||||||
version = major + "." + minor + "." + patch + "-beta." + preReleaseMajor;
|
version = major + "." + minor + "." + patch + "-beta." + preReleaseMajor;
|
||||||
versionOpt = Version.resolve(version);
|
versionOpt = Version.resolve(version);
|
||||||
assertTrue(versionOpt.isPresent());
|
assertTrue(versionOpt.isPresent());
|
||||||
assertEquals(new Version(major, minor, patch, Version.PreRelease.BETA, preReleaseMajor),
|
assertEquals(new Version(major, minor, patch, BETA, preReleaseMajor),
|
||||||
versionOpt.get());
|
versionOpt.get());
|
||||||
|
|
||||||
version = major + "." + minor + "." + patch + "-rc." + preReleaseMajor;
|
version = major + "." + minor + "." + patch + "-rc." + preReleaseMajor;
|
||||||
|
@ -141,44 +146,72 @@ class VersionTest {
|
||||||
unknownVersionOpt.get());
|
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
|
@NonNull
|
||||||
Version getVersion(String version) {
|
Version getVersion(String version) {
|
||||||
return Version.resolve(version)
|
return Version.resolve(version)
|
||||||
.orElseThrow(() -> new IllegalArgumentException("Invalid 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;
|
package run.halo.app.utils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
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 org.junit.jupiter.api.Test;
|
||||||
import run.halo.app.model.support.HaloConst;
|
import run.halo.app.model.support.HaloConst;
|
||||||
|
|
||||||
|
@ -14,26 +11,6 @@ import run.halo.app.model.support.HaloConst;
|
||||||
*/
|
*/
|
||||||
class VersionUtilTest {
|
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
|
@Test
|
||||||
void hasSameMajorAndMinorVersionTest() {
|
void hasSameMajorAndMinorVersionTest() {
|
||||||
assertThat(
|
assertThat(
|
||||||
|
@ -53,4 +30,5 @@ class VersionUtilTest {
|
||||||
|
|
||||||
assertThat(VersionUtil.hasSameMajorAndMinorVersion(null, null)).isTrue();
|
assertThat(VersionUtil.hasSameMajorAndMinorVersion(null, null)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue