用java编写如下程序:java中获取同一个类中不同次代码提交变更的方法: 1.代码差异可通过git diff 比对两次commit id获取 2.变更代码解析对应的类文件及内部的方法并存储
时间: 2024-03-27 13:40:44 浏览: 154
code-diff:基于git的差异代码获取
以下是一个示例程序,可以实现获取同一个 Java 类中不同次代码提交变更的方法,以及将变更代码解析对应的类文件及内部的方法并存储:
```java
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
public class JavaCodeChanges {
public static void main(String[] args) throws IOException {
String repoDir = "/path/to/your/repo"; // Git 仓库的本地路径
String filePath = "src/main/java/YourClass.java"; // Java 类文件的路径
try (Git git = Git.open(Paths.get(repoDir))) {
Iterable<RevCommit> commits = git.log().addPath(filePath).call();
Map<String, Set<String>> methodsMap = new HashMap<>(); // 保存方法名的映射
RevCommit prevCommit = null;
for (RevCommit commit : commits) {
if (prevCommit != null) {
RevWalk walk = new RevWalk(git.getRepository());
// 获取两个提交之间的差异
ObjectReader reader = git.getRepository().newObjectReader();
CanonicalTreeParser oldTreeIter = new CanonicalTreeParser();
oldTreeIter.reset(reader, prevCommit.getTree());
CanonicalTreeParser newTreeIter = new CanonicalTreeParser();
newTreeIter.reset(reader, commit.getTree());
List<DiffEntry> diffs = git.diff()
.setOldTree(oldTreeIter)
.setNewTree(newTreeIter)
.setPathFilter(PathFilter.create(filePath))
.call();
// 解析差异中的变更代码
for (DiffEntry diff : diffs) {
String[] lines = git.show().setPath(diff.getNewPath()).call().split("\n");
for (String line : lines) {
if (line.matches("^\\s*public.*\\(.*\\)\\s*\\{\\s*$")) {
String method = line.replaceFirst("^\\s*public\\s*", "")
.replaceFirst("\\(.*\\)\\s*\\{\\s*$", "");
// 将方法名及对应的提交 ID 添加到映射中
if (!methodsMap.containsKey(method)) {
methodsMap.put(method, new HashSet<>());
}
methodsMap.get(method).add(commit.getName());
}
}
}
walk.dispose();
}
prevCommit = commit;
}
// 解析每个提交对应的类文件,并提取其中的方法
for (Map.Entry<String, Set<String>> entry : methodsMap.entrySet()) {
String method = entry.getKey();
Set<String> commitIds = entry.getValue();
for (String commitId : commitIds) {
Path classFilePath = Paths.get(repoDir, ".git", "objects", commitId.substring(0, 2), commitId.substring(2));
byte[] classFileData = git.getRepository().open(classFilePath).getBytes();
byte[] decompressedData = org.eclipse.jgit.util.IO.readFully(classFileData);
byte[] classBytes = org.eclipse.jgit.lib.Constants.encodedTypeString(org.eclipse.jgit.lib.Constants.OBJ_BLOB).getBytes(StandardCharsets.US_ASCII);
byte[] allBytes = new byte[classBytes.length + decompressedData.length];
System.arraycopy(classBytes, 0, allBytes, 0, classBytes.length);
System.arraycopy(decompressedData, 0, allBytes, classBytes.length, decompressedData.length);
// 解析类文件中的方法
ClassReader classReader = new ClassReader(allBytes);
ClassNode classNode = new ClassNode();
classReader.accept(classNode, 0);
for (MethodNode methodNode : classNode.methods) {
if (methodNode.name.equals(method)) {
// 保存方法名及对应的类名和提交 ID
Path outputDir = Paths.get("output");
Files.createDirectories(outputDir);
Path outputFile = outputDir.resolve(method + ".txt");
String output = classNode.name + " (" + commitId + ")";
Files.write(outputFile, Collections.singleton(output), StandardCharsets.UTF_8);
}
}
}
}
}
}
}
```
这个程序使用 JGit 库来访问 Git 仓库,并使用 `git diff` 命令来比较两个提交之间 Java 类文件的差异。它会输出所有变更过的方法名,并将变更代码解析对应的类文件及内部的方法,并存储到一个文本文件中。你需要替换 `repoDir` 和 `filePath` 变量为你自己的值。
阅读全文