feat: 项目整体命名修改cache-schema-checker
All checks were successful
缓存序列化结构检查 / cache-schema-check (push) Has been skipped
All checks were successful
缓存序列化结构检查 / cache-schema-check (push) Has been skipped
This commit is contained in:
117
src/main/java/com/codechecker/cache/git/GitDiffScanner.java
vendored
Normal file
117
src/main/java/com/codechecker/cache/git/GitDiffScanner.java
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
package com.codechecker.cache.git;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 基于 git 命令的差异扫描与双版本文件内容读取。
|
||||
*
|
||||
* <p>通过 {@code git diff --name-only} 获取变更的 .java 文件,通过 {@code git show sha:path}
|
||||
* 读取指定提交下的文件内容,避免检出两个完整 worktree。</p>
|
||||
*/
|
||||
public class GitDiffScanner {
|
||||
|
||||
private final Path repoRoot;
|
||||
|
||||
public GitDiffScanner(Path repoRoot) {
|
||||
this.repoRoot = repoRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回 old..new 之间变更的 Java 文件路径(相对仓库根,使用 / 分隔)。
|
||||
*/
|
||||
public List<String> changedJavaFiles(String oldSha, String newSha) throws GitException {
|
||||
List<String> lines = runLines(
|
||||
"git", "diff", "--name-only", "--diff-filter=ACMR", oldSha, newSha, "--", "*.java");
|
||||
List<String> result = new ArrayList<>();
|
||||
for (String line : lines) {
|
||||
String trimmed = line.trim();
|
||||
if (!trimmed.isEmpty() && trimmed.endsWith(".java")) {
|
||||
result.add(trimmed);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取某提交下指定文件的内容;文件在该提交不存在时返回 null。
|
||||
*/
|
||||
public String fileContentAt(String sha, String path) throws GitException {
|
||||
try {
|
||||
ProcessResult pr = run("git", "show", sha + ":" + path);
|
||||
if (pr.exitCode != 0) {
|
||||
return null;
|
||||
}
|
||||
return pr.stdout;
|
||||
} catch (GitException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> runLines(String... command) throws GitException {
|
||||
ProcessResult pr = run(command);
|
||||
if (pr.exitCode != 0) {
|
||||
throw new GitException("git 命令执行失败(exit=" + pr.exitCode + "): " + String.join(" ", command)
|
||||
+ "\n" + pr.stderr);
|
||||
}
|
||||
List<String> lines = new ArrayList<>();
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(new java.io.ByteArrayInputStream(
|
||||
pr.stdout.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
lines.add(line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new GitException("读取 git 输出失败", e);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
private ProcessResult run(String... command) throws GitException {
|
||||
ProcessBuilder pb = new ProcessBuilder(command);
|
||||
pb.directory(repoRoot.toFile());
|
||||
pb.redirectErrorStream(false);
|
||||
try {
|
||||
Process process = pb.start();
|
||||
String stdout = readStream(process.getInputStream());
|
||||
String stderr = readStream(process.getErrorStream());
|
||||
int exit = process.waitFor();
|
||||
return new ProcessResult(exit, stdout, stderr);
|
||||
} catch (IOException e) {
|
||||
throw new GitException("无法启动 git 进程: " + String.join(" ", command), e);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new GitException("git 进程被中断", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String readStream(InputStream in) throws IOException {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
byte[] chunk = new byte[8192];
|
||||
int read;
|
||||
while ((read = in.read(chunk)) != -1) {
|
||||
buffer.write(chunk, 0, read);
|
||||
}
|
||||
return new String(buffer.toByteArray(), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static final class ProcessResult {
|
||||
final int exitCode;
|
||||
final String stdout;
|
||||
final String stderr;
|
||||
|
||||
ProcessResult(int exitCode, String stdout, String stderr) {
|
||||
this.exitCode = exitCode;
|
||||
this.stdout = stdout;
|
||||
this.stderr = stderr;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user