更新了代码仓库清单
This commit is contained in:
@@ -20,10 +20,14 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
@@ -55,6 +59,7 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
|
||||
private static final String DEFAULT_BRANCH = "master";
|
||||
private static final long CMD_TIMEOUT_SECONDS = 120;
|
||||
private static final long SYNC_TOTAL_TIMEOUT_MINUTES = 30; // 整体同步超时
|
||||
private static final int PARALLEL = 6; // 并发数
|
||||
|
||||
private final FileOperationHelper fileOperationHelper;
|
||||
@@ -214,8 +219,11 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
final String repoPath = proj.getPath();
|
||||
final String repoName = extractName(repoPath);
|
||||
final String targetBranch = branch;
|
||||
final int taskNum = i + 1; // 固定序号,用于定位卡住的项
|
||||
|
||||
pool.submit(() -> {
|
||||
// 开始处理时立即打印,方便定位卡住的项目
|
||||
System.out.printf("[%d/%d] 处理中 %s ...%n", taskNum, total, repoName);
|
||||
try {
|
||||
SyncResult result = syncOneRepo(repoPath, targetBranch, baseUrlMap);
|
||||
resultMap.put(repoPath, result);
|
||||
@@ -226,13 +234,13 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
case DAMAGED: tag = "损坏"; break;
|
||||
default: tag = "失败"; break;
|
||||
}
|
||||
System.out.printf("[%d/%d] %s >> %s%n", done, total, repoName, tag);
|
||||
System.out.printf("[%d/%d] %s >> %s (完成 %d/%d)%n", taskNum, total, repoName, tag, done, total);
|
||||
} catch (Exception e) {
|
||||
SyncResult r = SyncResult.FAILED;
|
||||
r.error = e.getMessage();
|
||||
resultMap.put(repoPath, r);
|
||||
int done = completed.incrementAndGet();
|
||||
System.out.printf("[%d/%d] %s >> 异常: %s%n", done, total, repoName, e.getMessage());
|
||||
System.out.printf("[%d/%d] %s >> 异常: %s (完成 %d/%d)%n", taskNum, total, repoName, e.getMessage(), done, total);
|
||||
} finally {
|
||||
latch.countDown();
|
||||
}
|
||||
@@ -241,7 +249,12 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
|
||||
pool.shutdown();
|
||||
try {
|
||||
latch.await();
|
||||
boolean allDone = latch.await(SYNC_TOTAL_TIMEOUT_MINUTES, TimeUnit.MINUTES);
|
||||
if (!allDone) {
|
||||
pool.shutdownNow();
|
||||
System.err.println("\n!!! 同步超时(超过 " + SYNC_TOTAL_TIMEOUT_MINUTES + " 分钟),强制终止剩余任务 !!!");
|
||||
// 未完成的任务不再等待,继续输出已有结果
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
pool.shutdownNow();
|
||||
@@ -522,49 +535,71 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
// ==================== Git 命令执行 ====================
|
||||
|
||||
private CmdResult runGit(String workingDir, String command) {
|
||||
CmdResult result = new CmdResult();
|
||||
try {
|
||||
ProcessBuilder pb = isWindows()
|
||||
? new ProcessBuilder("cmd.exe", "/c", command)
|
||||
: new ProcessBuilder("bash", "-c", command);
|
||||
// 用 Future 包一层,防止 readLine() 因进程卡死而永久阻塞
|
||||
ExecutorService singleExecutor = Executors.newSingleThreadExecutor();
|
||||
Future<CmdResult> future = singleExecutor.submit(() -> {
|
||||
CmdResult result = new CmdResult();
|
||||
try {
|
||||
ProcessBuilder pb = isWindows()
|
||||
? new ProcessBuilder("cmd.exe", "/c", command)
|
||||
: new ProcessBuilder("bash", "-c", command);
|
||||
|
||||
if (workingDir != null) {
|
||||
pb.directory(new File(workingDir));
|
||||
}
|
||||
pb.redirectErrorStream(true);
|
||||
|
||||
Process process = pb.start();
|
||||
StringBuilder output = new StringBuilder();
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(process.getInputStream(), java.nio.charset.StandardCharsets.UTF_8))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
output.append(line).append("\n");
|
||||
if (workingDir != null) {
|
||||
pb.directory(new File(workingDir));
|
||||
}
|
||||
}
|
||||
pb.redirectErrorStream(true);
|
||||
|
||||
boolean finished = process.waitFor(CMD_TIMEOUT_SECONDS, TimeUnit.SECONDS);
|
||||
if (!finished) {
|
||||
process.destroyForcibly();
|
||||
Process process = pb.start();
|
||||
StringBuilder output = new StringBuilder();
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(process.getInputStream(), java.nio.charset.StandardCharsets.UTF_8))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
output.append(line).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
boolean finished = process.waitFor(CMD_TIMEOUT_SECONDS, TimeUnit.SECONDS);
|
||||
if (!finished) {
|
||||
process.destroyForcibly();
|
||||
result.ok = false;
|
||||
result.error = "命令超时(" + CMD_TIMEOUT_SECONDS + "s)";
|
||||
return result;
|
||||
}
|
||||
|
||||
int exitCode = process.exitValue();
|
||||
result.ok = (exitCode == 0);
|
||||
result.output = output.toString().trim();
|
||||
if (!result.ok) {
|
||||
String detail = output.toString().trim();
|
||||
result.error = detail.isEmpty()
|
||||
? "exit code " + exitCode
|
||||
: "exit code " + exitCode + ": " + detail;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
result.ok = false;
|
||||
result.error = "命令超时";
|
||||
return result;
|
||||
result.error = e.getMessage();
|
||||
}
|
||||
return result;
|
||||
});
|
||||
|
||||
int exitCode = process.exitValue();
|
||||
result.ok = (exitCode == 0);
|
||||
result.output = output.toString().trim();
|
||||
if (!result.ok) {
|
||||
String detail = output.toString().trim();
|
||||
result.error = detail.isEmpty()
|
||||
? "exit code " + exitCode
|
||||
: "exit code " + exitCode + ": " + detail;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
// 整体超时比内部 waitFor 多给 10 秒缓冲
|
||||
return future.get(CMD_TIMEOUT_SECONDS + 10, TimeUnit.SECONDS);
|
||||
} catch (TimeoutException e) {
|
||||
future.cancel(true);
|
||||
CmdResult result = new CmdResult();
|
||||
result.ok = false;
|
||||
result.error = e.getMessage();
|
||||
result.error = "命令超时(" + (CMD_TIMEOUT_SECONDS + 10) + "s,进程被强制终止)";
|
||||
return result;
|
||||
} catch (InterruptedException | ExecutionException | CancellationException e) {
|
||||
CmdResult result = new CmdResult();
|
||||
result.ok = false;
|
||||
result.error = "执行异常: " + e.getMessage();
|
||||
return result;
|
||||
} finally {
|
||||
singleExecutor.shutdownNow();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String getRemoteUrl(String repoPath, Map<String, String> baseUrlMap) {
|
||||
|
||||
@@ -1,11 +1 @@
|
||||
branch:master
|
||||
ft-loan-core|D:/bestpay-srdcloud/ft-loan-core|master|checkout 失败: exit code 128|https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/cf/cf-trade-core
|
||||
cf-asset-core|D:/bestpay-srdcloud/cf-asset-core|master|checkout 失败: exit code 128|https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/cf/cf-trade-core
|
||||
cf-boss|D:/bestpay-srdcloud/cf-boss|master|checkout 失败: exit code 128|https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/cf/cf-trade-core
|
||||
cf-credit-prod-batch|D:/bestpay-srdcloud/cf-credit-prod-batch|master|checkout 失败: exit code 128|https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/cf/cf-trade-core
|
||||
cf-instalment-mix|D:/bestpay-srdcloud/cf-instalment-mix|master|checkout 失败: exit code 128|https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/cf/cf-trade-core
|
||||
cf-marketing-manage|D:/bestpay-srdcloud/cf-marketing-manage|master|checkout 失败: exit code 128|https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/cf/cf-trade-core
|
||||
cf-risk-control-core|D:/bestpay-srdcloud/cf-risk-control-core|master|checkout 失败: exit code 128|https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/cf/cf-trade-core
|
||||
cf-risktool|D:/bestpay-srdcloud/cf-risktool|master|checkout 失败: exit code 128|https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/cf/cf-trade-core
|
||||
cf-thirdpartybiz-prod|D:/bestpay-srdcloud/cf-thirdpartybiz-prod|master|checkout 失败: exit code 128|https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/cf/cf-trade-core
|
||||
cf-trade-core|D:/bestpay-srdcloud/cf-trade-core|master|checkout 失败: exit code 128|https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/cf/cf-trade-core
|
||||
|
||||
@@ -15,7 +15,6 @@ D:/bestpay-srdcloud/ft-risk-control-core=https://srd17321104074@code.srdcloud.cn
|
||||
D:/bestpay-srdcloud/ft-settlement-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/ft-wechatstage-prod=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-agent-admin=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-asset-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-batch-creditpayment=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-batch-creditpayment-plus=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-blockchain-prod=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
@@ -32,7 +31,6 @@ D:/bestpay-srdcloud/cf-credit-bizfront=https://srd17321104074@code.srdcloud.cn/b
|
||||
D:/bestpay-srdcloud/cf-credit-bizfront-plus=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-credit-front=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-credit-prod=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-credit-prod-batch=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-credit-prod-manage=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-creditstagescore=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-credituse-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
@@ -44,7 +42,6 @@ D:/bestpay-srdcloud/cf-grant-core=https://srd17321104074@code.srdcloud.cn/bestpa
|
||||
D:/bestpay-srdcloud/cf-info-collection=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-instalment-admin=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-instalment-batch=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-instalment-mix=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-invoice-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-lending-management-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-loancapital-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
@@ -55,7 +52,6 @@ D:/bestpay-srdcloud/cf-organmng-core=https://srd17321104074@code.srdcloud.cn/bes
|
||||
D:/bestpay-srdcloud/cf-precredit-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-productcfg-core-plus=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-protocol-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-risk-control-core=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-risktool=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-scheduler=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
D:/bestpay-srdcloud/cf-search=https://srd17321104074@code.srdcloud.cn/bestpay-cf/cf/
|
||||
|
||||
Reference in New Issue
Block a user