mirror of
https://gitee.com/ssssssss-team/magic-api.git
synced 2026-05-09 22:02:37 +08:00
git插件优化
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
package org.ssssssss.magicapi.git;
|
||||
|
||||
import com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.JSchException;
|
||||
import com.jcraft.jsch.Session;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.jgit.api.*;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
|
||||
import org.eclipse.jgit.transport.*;
|
||||
import org.eclipse.jgit.util.FS;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.ssssssss.magicapi.core.exception.MagicAPIException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* git仓库
|
||||
*
|
||||
* @author soriee
|
||||
* @date 2022/2/20 22:48
|
||||
*/
|
||||
public class GitRepo {
|
||||
private static final Logger logger = LoggerFactory.getLogger(GitRepo.class);
|
||||
/**
|
||||
* 文件路径地址
|
||||
*/
|
||||
private String rootPath;
|
||||
private String gitFilePath;
|
||||
private GitStoreProperties properties;
|
||||
private Git git;
|
||||
|
||||
public GitRepo(String rootPath, GitStoreProperties properties) {
|
||||
this.rootPath = rootPath;
|
||||
this.gitFilePath = rootPath + File.separator + ".git";
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
private void valid() {
|
||||
File repoDir = new File(rootPath);
|
||||
File gitFile = new File(gitFilePath);
|
||||
// 如果文件夹不存在 则创建文件夹
|
||||
if (!repoDir.exists()) {
|
||||
repoDir.mkdirs();
|
||||
}
|
||||
if (!gitFile.exists() && repoDir.list().length > 0) {
|
||||
throw new MagicAPIException("初次项目启动时,请保持文件夹为空。");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置ssh秘钥或者账号密码
|
||||
*
|
||||
* @param transportCommand
|
||||
* @return
|
||||
* @author soriee
|
||||
* @date 2022/2/28 20:06
|
||||
*/
|
||||
private void setSshOrCredentials(TransportCommand transportCommand) {
|
||||
if (this.getProperties().getPrivateKey() != null) {
|
||||
// ssh
|
||||
final SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() {
|
||||
@Override
|
||||
protected void configure(OpenSshConfig.Host host, Session session) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSch createDefaultJSch(FS fs) throws JSchException {
|
||||
JSch defaultJSch = super.createDefaultJSch(fs);
|
||||
defaultJSch.addIdentity(GitRepo.this.getProperties().getPrivateKey());
|
||||
return defaultJSch;
|
||||
}
|
||||
};
|
||||
transportCommand.setTransportConfigCallback(new TransportConfigCallback() {
|
||||
@Override
|
||||
public void configure(Transport transport) {
|
||||
SshTransport sshTransport = (SshTransport) transport;
|
||||
sshTransport.setSshSessionFactory(sshSessionFactory);
|
||||
}
|
||||
});
|
||||
} else if (StringUtils.isNotBlank(properties.getUsername())
|
||||
&& StringUtils.isNotBlank(properties.getPassword())) {
|
||||
// 账号密码
|
||||
transportCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(
|
||||
properties.getUsername(),
|
||||
properties.getPassword()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目设置仓库
|
||||
*
|
||||
* @return
|
||||
* @author soriee
|
||||
* @date 2022/2/24 20:43
|
||||
*/
|
||||
public void setupRepo() throws IOException, GitAPIException {
|
||||
this.valid();
|
||||
File gitFile = new File(gitFilePath);
|
||||
try {
|
||||
if (gitFile.exists()) {
|
||||
// 项目存在,则打开为仓库, 并且强制更新一次
|
||||
FileRepositoryBuilder builder = new FileRepositoryBuilder();
|
||||
Repository repository = builder.create(gitFile);
|
||||
git = new Git(repository);
|
||||
// 更新两次,避免删除文件未更新
|
||||
this.update(false);
|
||||
this.update(true);
|
||||
} else {
|
||||
CloneCommand cloneCommand = Git.cloneRepository()
|
||||
.setURI(properties.getUrl())
|
||||
.setDirectory(new File(rootPath))
|
||||
.setBranch(properties.getBranch());
|
||||
this.setSshOrCredentials(cloneCommand);
|
||||
git = cloneCommand.call();
|
||||
}
|
||||
} catch (IOException | GitAPIException e) {
|
||||
logger.error("初始化git仓库失败", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新
|
||||
* 1.git add .
|
||||
* 2.git commit -m "同步数据"
|
||||
* 3.git pull
|
||||
* 4.git push
|
||||
* @param update
|
||||
* @return
|
||||
* @author soriee
|
||||
* @date 2022/2/20 22:54
|
||||
*/
|
||||
public boolean update(boolean update) {
|
||||
try {
|
||||
git.add().setUpdate(update).addFilepattern(".").call();
|
||||
git.commit().setMessage("同步数据").call();
|
||||
PullCommand pull = git.pull();
|
||||
this.setSshOrCredentials(pull);
|
||||
PullResult pullResult = pull.call();
|
||||
if (!pullResult.isSuccessful()) {
|
||||
throw new MagicAPIException("git更新失败, 请重试或尝试手动更新");
|
||||
}
|
||||
PushCommand pushCommand = git.push();
|
||||
this.setSshOrCredentials(pushCommand);
|
||||
pushCommand.call();
|
||||
} catch (GitAPIException e) {
|
||||
logger.error("git更新失败", e);
|
||||
throw new MagicAPIException("git更新失败, 请重试或尝试手动更新");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public GitStoreProperties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package org.ssssssss.magicapi.git;
|
||||
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.ssssssss.magicapi.core.resource.FileResource;
|
||||
import org.ssssssss.magicapi.core.resource.Resource;
|
||||
import org.ssssssss.magicapi.core.resource.ResourceAdapter;
|
||||
import org.ssssssss.magicapi.git.GitStoreProperties;
|
||||
import org.ssssssss.magicapi.utils.IoUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 文件存储实现
|
||||
*
|
||||
* @author mxd
|
||||
*/
|
||||
public class GitResource extends FileResource {
|
||||
private GitRepo gitRepo;
|
||||
|
||||
public static GitResource of(org.ssssssss.magicapi.core.config.Resource config, GitStoreProperties properties) throws IOException, GitAPIException {
|
||||
File file = new File(config.getLocation());
|
||||
GitRepo gitRepo = new GitRepo(file.getAbsolutePath(), properties);
|
||||
GitResource gitResource = new GitResource(config.isReadonly(), file,
|
||||
file.getAbsolutePath(), gitRepo);
|
||||
// 初始化
|
||||
gitResource.setup();
|
||||
return gitResource;
|
||||
}
|
||||
|
||||
|
||||
public GitResource(boolean readonly, File file, String rootPath, GitRepo gitRepo) {
|
||||
super(file, readonly, rootPath);
|
||||
this.gitRepo = gitRepo;
|
||||
}
|
||||
/**
|
||||
* 进行初始化操作, 仅仅在项目启动时进行初始化
|
||||
* @author soriee
|
||||
* @date 2022/2/20 22:30
|
||||
* @return
|
||||
*/
|
||||
private void setup() throws IOException, GitAPIException {
|
||||
synchronized(GitResource.class) {
|
||||
gitRepo.setupRepo();
|
||||
}
|
||||
}
|
||||
private boolean update(boolean update) {
|
||||
return gitRepo.update(update);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean delete() {
|
||||
return super.delete() && this.update(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mkdir() {
|
||||
return super.mkdir() && this.update(false);
|
||||
}
|
||||
@Override
|
||||
public Resource getResource(String name) {
|
||||
return new GitResource(super.readonly(), new File(super.file, name), super.rootPath, this.gitRepo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource getDirectory(String name) {
|
||||
return getResource(name);
|
||||
}
|
||||
@Override
|
||||
public boolean write(byte[] bytes) {
|
||||
return super.write(bytes) && this.update(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean write(String content) {
|
||||
return super.write(content) && this.update(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Resource> resources() {
|
||||
File[] files = this.file.listFiles();
|
||||
return files == null ? Collections.emptyList() : Arrays.stream(files).map(it -> new GitResource(this.readonly(),
|
||||
it, this.rootPath, this.gitRepo)).collect(Collectors.toList());
|
||||
}
|
||||
@Override
|
||||
public Resource parent() {
|
||||
return this.rootPath.equals(this.file.getAbsolutePath()) ? null : new GitResource(this.readonly(),
|
||||
this.file.getParentFile(), this.rootPath, this.gitRepo);
|
||||
}
|
||||
@Override
|
||||
public List<Resource> dirs() {
|
||||
return IoUtils.dirs(this.file).stream().map(it -> new GitResource(this.readonly(),
|
||||
it, this.rootPath, this.gitRepo)).collect(Collectors.toList());
|
||||
}
|
||||
@Override
|
||||
public List<Resource> files(String suffix) {
|
||||
return IoUtils.files(this.file, suffix).stream().map(it -> new GitResource(this.readonly(),
|
||||
it, this.rootPath, this.gitRepo)).collect(Collectors.toList());
|
||||
}
|
||||
@Override
|
||||
public boolean renameTo(Resource resource) {
|
||||
if (!this.readonly()) {
|
||||
File target = ((GitResource) resource).file;
|
||||
if (this.file.renameTo(target)) {
|
||||
this.file = target;
|
||||
// 更新两次,新增文件和删除文件都要更新
|
||||
this.update(false);
|
||||
this.update(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.gitRepo.getProperties().getUrl();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package org.ssssssss.magicapi.git;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix = "magic-api.resource.git")
|
||||
public class GitStoreProperties {
|
||||
/**
|
||||
* git仓库地址
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* git分支
|
||||
*/
|
||||
private String branch;
|
||||
/**
|
||||
* ssh 密钥地址
|
||||
* 仅支持-m PEM参数生产的ssh key
|
||||
*/
|
||||
private String privateKey;
|
||||
/**
|
||||
* git账号
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* git密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getBranch() {
|
||||
return branch;
|
||||
}
|
||||
|
||||
public void setBranch(String branch) {
|
||||
this.branch = branch;
|
||||
}
|
||||
|
||||
public String getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public void setPrivateKey(String privateKey) {
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.ssssssss.magicapi.git;
|
||||
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.ssssssss.magicapi.core.config.MagicAPIProperties;
|
||||
import org.ssssssss.magicapi.core.config.MagicPluginConfiguration;
|
||||
import org.ssssssss.magicapi.core.config.Resource;
|
||||
import org.ssssssss.magicapi.core.model.Plugin;
|
||||
import org.ssssssss.magicapi.git.GitStoreProperties;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(GitStoreProperties.class)
|
||||
public class MagicGitConfiguration implements MagicPluginConfiguration {
|
||||
|
||||
private final MagicAPIProperties properties;
|
||||
private final GitStoreProperties gitStoreProperties;
|
||||
|
||||
public MagicGitConfiguration(MagicAPIProperties properties, GitStoreProperties gitStoreProperties) {
|
||||
this.properties = properties;
|
||||
this.gitStoreProperties = gitStoreProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* git存储
|
||||
* @author soriee
|
||||
* @date 2022/2/28 19:50
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(prefix = "magic-api", name = "resource.type", havingValue = "git")
|
||||
public org.ssssssss.magicapi.core.resource.Resource magicGitResource() throws IOException, GitAPIException {
|
||||
Resource resourceConfig = properties.getResource();
|
||||
return GitResource.of(resourceConfig, this.gitStoreProperties);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Plugin plugin() {
|
||||
return new Plugin("Git");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.ssssssss.magicapi.git.MagicGitConfiguration
|
||||
Reference in New Issue
Block a user