package org.cfpa.i18nupdatemod.git; import static org.cfpa.i18nupdatemod.I18nUpdateMod.logger; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.cfpa.i18nupdatemod.I18nConfig; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.CheckoutCommand; import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode; import org.eclipse.jgit.api.ResetCommand.ResetType; import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.transport.RemoteConfig; public class ResourcePackRepository { private static String[] remoteURLs; private File localPath; public Git gitRepo = null; private String branch; private Set<String> assetDomains; public ResourcePackRepository(String localPath, Set<String> assetDomains) { remoteURLs = I18nConfig.download.remoteRepoURL; this.localPath = new File(localPath); this.assetDomains = assetDomains; this.branch = "1.12.2-release"; initRepo(); } private void initRepo() { if (localPath.exists()) { try { gitRepo = Git.open(localPath); } catch (Exception e) { logger.error("Exception caught while initializing git repository: ", e); } } if (gitRepo == null) { try { gitRepo = Git.init().setDirectory(localPath).call(); } catch (Exception e) { e.printStackTrace(); } } } private void configRemote(String name, String url, String branchName) { try { StoredConfig config = gitRepo.getRepository().getConfig(); config.setString("remote", name, "url", url); config.setString("remote", name, "fetch", "+refs/heads/" + branchName + ":refs/remotes/origin/" + branchName); config.save(); } catch (Exception e) { e.printStackTrace(); } } public void close() { gitRepo.getRepository().close(); } private boolean fetchFromRemote(String remoteName, ProgressMonitor monitor) { try { // fetch gitRepo.fetch() .setProgressMonitor(monitor) .setRemote(remoteName) .call(); return true; } catch (Exception e) { logger.error("Invalid remote repository: ", e); return false; } } public void fetch(ProgressMonitor monitor) { boolean success; List<RemoteConfig> remoteList = new ArrayList<>(); try { remoteList = gitRepo.remoteList().call(); } catch (Exception e) { logger.error("Error while getting remote list: ", e); } for (RemoteConfig remoteConfig : remoteList) { // TODO 检查连接情况 success = fetchFromRemote(remoteConfig.getName(), monitor); if (success) { return; } } for (int i = 0; i < remoteURLs.length; i++) { String remoteName = "origin" + i; String gitURL = remoteURLs[i]; // 解析 HTML 重定向,HTTP 302 重定向用不了 if (remoteURLs[i].endsWith("html") || remoteURLs[i].endsWith("htm")) { CloseableHttpClient closeableHttpClient = HttpClients.createDefault(); HttpGet httpGet = new HttpGet(remoteURLs[i]); CloseableHttpResponse response; try { response = closeableHttpClient.execute(httpGet); if (response.getStatusLine().getStatusCode() == 200) { String result = EntityUtils.toString(response.getEntity(), "UTF-8"); int index = result.indexOf("meta http-equiv=\"refresh\""); int startIndex = index + "meta http-equiv=\"refresh\" content=\"0;url=".length(); int endIndex = result.indexOf("\">", startIndex); gitURL = result.substring(startIndex, endIndex); closeableHttpClient.close(); } else { closeableHttpClient.close(); continue; } } catch (Exception e) { logger.error("Error while fetching resource pack repository: ", e); continue; } } configRemote(remoteName, gitURL, this.branch); success = fetchFromRemote(remoteName, monitor); if (success) { return; } } logger.warn("仓库更新失败"); } public void reset(ProgressMonitor monitor) { try { // create branch and set upstream gitRepo.branchCreate() .setName(branch) .setUpstreamMode(SetupUpstreamMode.SET_UPSTREAM) .setStartPoint("origin/" + branch) .setForce(true) .call(); // reset to remote head gitRepo.reset() .setProgressMonitor(monitor) .setMode(ResetType.SOFT) .setRef("refs/remotes/origin/" + branch) .call(); } catch (Exception e) { logger.error("Exception caught while reseting to remote head: ", e); } } public void sparseCheckout(Collection<String> subPathSet, ProgressMonitor monitor) { try { // sparse checkout CheckoutCommand checkoutCommand = gitRepo.checkout(); checkoutCommand.setProgressMonitor(monitor) .setName(branch) .setStartPoint(branch); subPathSet.forEach(checkoutCommand::addPath); checkoutCommand.call(); } catch (Exception e) { logger.error("Exception caught while checking out: ", e); } } public void sparseCheckout(String subPath, ProgressMonitor monitor) { try { // sparse checkout gitRepo.checkout() .setProgressMonitor(monitor) .setName(branch) .setStartPoint(branch) .addPath(subPath) .call(); } catch (Exception e) { logger.error("Exception caught while checking out: ", e); } } public static String getSubPathOfAsset(String domain) { return "assets/" + domain; } public Collection<String> getSubPaths() { return assetDomains.stream().map(ResourcePackRepository::getSubPathOfAsset).collect(Collectors.toSet()); } public File getLocalPath() { return localPath; } }