feat: support theme require halo version. (#544)

* feat: support theme require halo version.

* fix: com.sun.xml.internal.ws.util does not exist error.

* fix: com.sun.xml.internal.ws.util does not exist error again.

* Update ThemeServiceImpl.java
pull/550/head
Ryan Wang 2020-02-04 16:35:02 +08:00 committed by GitHub
parent bb8ee0f074
commit 08c579a095
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 175 additions and 24 deletions

View File

@ -0,0 +1,18 @@
package run.halo.app.exception;
/**
* Theme not support exception.
*
* @author ryanwang
* @date 2020-02-03
*/
public class ThemeNotSupportException extends BadRequestException {
public ThemeNotSupportException(String message) {
super(message);
}
public ThemeNotSupportException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -54,6 +54,11 @@ public class ThemeProperty {
*/
private String version;
/**
* Require halo version.
*/
private String require;
/**
* Theme author.
*/

View File

@ -4,8 +4,13 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.PullResult;
import org.eclipse.jgit.api.ResetCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish;
import org.springframework.context.ApplicationEventPublisher;
@ -31,10 +36,7 @@ import run.halo.app.model.support.HaloConst;
import run.halo.app.model.support.ThemeFile;
import run.halo.app.service.OptionService;
import run.halo.app.service.ThemeService;
import run.halo.app.utils.FileUtils;
import run.halo.app.utils.FilenameUtils;
import run.halo.app.utils.GitUtils;
import run.halo.app.utils.HaloUtils;
import run.halo.app.utils.*;
import java.io.IOException;
import java.net.URISyntaxException;
@ -477,6 +479,11 @@ public class ThemeServiceImpl implements ThemeService {
throw new AlreadyExistsException("当前安装的主题已存在");
}
// Not support current halo version.
if (StringUtils.isNotEmpty(tmpThemeProperty.getRequire()) && !VersionUtil.compareVersion(HaloConst.HALO_VERSION, tmpThemeProperty.getRequire())) {
throw new ThemeNotSupportException("当前主题仅支持 Halo " + tmpThemeProperty.getRequire() + " 以上的版本");
}
// Copy the temporary path to current theme folder
Path targetThemePath = themeWorkDir.resolve(tmpThemeProperty.getId());
FileUtils.copyFolder(themeTmpPath, targetThemePath);
@ -533,6 +540,9 @@ public class ThemeServiceImpl implements ThemeService {
try {
pullFromGit(updatingTheme);
} catch (Exception e) {
if (e instanceof ThemeNotSupportException) {
throw (ThemeNotSupportException) e;
}
throw new ThemeUpdateException("主题更新失败!您与主题作者可能同时更改了同一个文件,您也可以尝试删除主题并重新拉取最新的主题", e).setErrorData(themeId);
}
@ -579,6 +589,11 @@ public class ThemeServiceImpl implements ThemeService {
throw new ServiceException("上传的主题包不是该主题的更新包: " + file.getOriginalFilename());
}
// Not support current halo version.
if (StringUtils.isNotEmpty(prepareThemeProperty.getRequire()) && !VersionUtil.compareVersion(HaloConst.HALO_VERSION, prepareThemeProperty.getRequire())) {
throw new ThemeNotSupportException("新版本主题仅支持 Halo " + prepareThemeProperty.getRequire() + " 以上的版本");
}
// Coping new theme files to old theme folder.
FileUtils.copyFolder(preparePath, Paths.get(updatingTheme.getThemePath()));
@ -605,6 +620,15 @@ public class ThemeServiceImpl implements ThemeService {
try {
git = GitUtils.openOrInit(Paths.get(themeProperty.getThemePath()));
Repository repository = git.getRepository();
RevWalk revWalk = new RevWalk(repository);
Ref ref = repository.getAllRefs().get(Constants.HEAD);
RevCommit lastCommit = revWalk.parseCommit(ref.getObjectId());
// Force to set remote name
git.remoteRemove().setRemoteName(THEME_PROVIDER_REMOTE_NAME).call();
RemoteConfig remoteConfig = git.remoteAdd()
@ -647,6 +671,19 @@ public class ThemeServiceImpl implements ThemeService {
throw new ThemeUpdateException("拉取失败!您与主题作者可能同时更改了同一个文件");
}
// updated successfully.
ThemeProperty updatedThemeProperty = getProperty(Paths.get(themeProperty.getThemePath()));
// Not support current halo version.
if (StringUtils.isNotEmpty(updatedThemeProperty.getRequire()) && !VersionUtil.compareVersion(HaloConst.HALO_VERSION, updatedThemeProperty.getRequire())) {
// reset theme version
git.reset()
.setMode(ResetCommand.ResetType.HARD)
.setRef(lastCommit.getName())
.call();
throw new ThemeNotSupportException("新版本主题仅支持 Halo " + updatedThemeProperty.getRequire() + " 以上的版本");
}
} finally {
GitUtils.closeQuietly(git);
}
@ -826,7 +863,7 @@ public class ThemeServiceImpl implements ThemeService {
// Set screenshots
getScreenshotsFileName(themePath).ifPresent(screenshotsName ->
themeProperty.setScreenshots(StringUtils.join(optionService.getBlogBaseUrl(),
"/",
"/themes/",
FilenameUtils.getBasename(themeProperty.getThemePath()),
"/",
screenshotsName)));

View File

@ -17,7 +17,7 @@ import static run.halo.app.model.support.HaloConst.FILE_SEPARATOR;
*
* @author ryanwang
* @author johnniang
* @date 2017/12/22
* @date 2017-12-22
*/
@Slf4j
public class HaloUtils {
@ -232,22 +232,6 @@ public class HaloUtils {
return String.valueOf(System.currentTimeMillis());
}
/**
* Normalize url.
*
* @param url url must not be blank
* @return normalized url
*/
@NonNull
public static String normalizeUrl(@NonNull String url) {
Assert.hasText(url, "Url must not be blank");
StringUtils.removeEnd(url, "html");
StringUtils.removeEnd(url, "htm");
return SlugUtils.slugify(url);
}
/**
* Gets machine IP address.
*

View File

@ -0,0 +1,81 @@
package run.halo.app.utils;
import cn.hutool.core.util.StrUtil;
import java.util.StringTokenizer;
/**
* @author ryanwang
* @date 2020-02-03
* @see com.sun.xml.internal.ws.util.VersionUtil
*/
public class VersionUtil {
public VersionUtil() {
}
public static int[] getCanonicalVersion(String version) {
int[] canonicalVersion = new int[]{1, 1, 0, 0};
StringTokenizer tokenizer = new StringTokenizer(version, ".");
String token = tokenizer.nextToken();
canonicalVersion[0] = Integer.parseInt(token);
token = tokenizer.nextToken();
StringTokenizer subTokenizer;
if (!token.contains(StrUtil.UNDERLINE)) {
canonicalVersion[1] = Integer.parseInt(token);
} else {
subTokenizer = new StringTokenizer(token, "_");
canonicalVersion[1] = Integer.parseInt(subTokenizer.nextToken());
canonicalVersion[3] = Integer.parseInt(subTokenizer.nextToken());
}
if (tokenizer.hasMoreTokens()) {
token = tokenizer.nextToken();
if (!token.contains(StrUtil.UNDERLINE)) {
canonicalVersion[2] = Integer.parseInt(token);
if (tokenizer.hasMoreTokens()) {
canonicalVersion[3] = Integer.parseInt(tokenizer.nextToken());
}
} else {
subTokenizer = new StringTokenizer(token, "_");
canonicalVersion[2] = Integer.parseInt(subTokenizer.nextToken());
canonicalVersion[3] = Integer.parseInt(subTokenizer.nextToken());
}
}
return canonicalVersion;
}
public static int compare(String version1, String version2) {
int[] canonicalVersion1 = getCanonicalVersion(version1);
int[] canonicalVersion2 = getCanonicalVersion(version2);
if (canonicalVersion1[0] < canonicalVersion2[0]) {
return -1;
} else if (canonicalVersion1[0] > canonicalVersion2[0]) {
return 1;
} else if (canonicalVersion1[1] < canonicalVersion2[1]) {
return -1;
} else if (canonicalVersion1[1] > canonicalVersion2[1]) {
return 1;
} else if (canonicalVersion1[2] < canonicalVersion2[2]) {
return -1;
} else if (canonicalVersion1[2] > canonicalVersion2[2]) {
return 1;
} else if (canonicalVersion1[3] < canonicalVersion2[3]) {
return -1;
} else {
return canonicalVersion1[3] > canonicalVersion2[3] ? 1 : 0;
}
}
/**
* Compare version.
*
* @param current current version.
* @param require require version.
* @return true or false.
*/
public static boolean compareVersion(String current, String require) {
return compare(current, require) >= 0;
}
}

View File

@ -2,7 +2,6 @@ package run.halo.app.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.junit.Assert;
import org.junit.Test;
import java.util.stream.IntStream;
@ -15,7 +14,8 @@ import static org.junit.Assert.assertThat;
* Halo utilities test.
*
* @author johnniang
* @date 3/29/19
* @author ryanwang
* @date 2019-03-29
*/
@Slf4j
public class HaloUtilsTest {

View File

@ -0,0 +1,26 @@
package run.halo.app.utils;
import org.junit.Assert;
import org.junit.Test;
/**
* @author ryanwang
* @date 2020-02-03
*/
public class VersionUtilTest {
@Test
public void compareVersion() {
Assert.assertTrue(VersionUtil.compareVersion("1.2.0", "1.1.1"));
Assert.assertTrue(VersionUtil.compareVersion("1.2.1", "1.2.0"));
Assert.assertTrue(VersionUtil.compareVersion("1.2.0", "1.1.1.0"));
Assert.assertTrue(VersionUtil.compareVersion("1.2.0", "0.4.4"));
Assert.assertFalse(VersionUtil.compareVersion("1.1.1", "1.2.0"));
Assert.assertFalse(VersionUtil.compareVersion("0.0.1", "1.2.0"));
}
}