Skip to content

Commit e78e8de

Browse files
committed
feat(git): WIP: Add push test #12350
1 parent 669f22e commit e78e8de

File tree

3 files changed

+106
-1
lines changed

3 files changed

+106
-1
lines changed

jablib/src/main/java/org/jabref/logic/git/GitHandler.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ public void fetchOnCurrentBranch() throws IOException {
215215

216216
/**
217217
* Try to locate the Git repository root by walking up the directory tree starting from the given path.
218-
* If a directory containing a `.git` folder is found, a new GitHandler is created and returned.
218+
* If a directory containing a .git folder is found, a new GitHandler is created and returned.
219219
*
220220
* @param anyPathInsideRepo Any file or directory path that is assumed to be inside a Git repository
221221
* @return Optional containing a GitHandler initialized with the repository root, or empty if not found
@@ -230,4 +230,8 @@ public static Optional<GitHandler> fromAnyPath(Path anyPathInsideRepo) {
230230
}
231231
return Optional.empty();
232232
}
233+
234+
public File getRepositoryPathAsFile() {
235+
return repositoryPathAsFile;
236+
}
233237
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package org.jabref.logic.git.status;
2+
3+
import java.io.IOException;
4+
import java.nio.file.Path;
5+
import java.util.Optional;
6+
7+
import org.jabref.logic.git.GitHandler;
8+
import org.jabref.logic.git.io.GitRevisionLocator;
9+
10+
import org.eclipse.jgit.api.Git;
11+
import org.eclipse.jgit.api.Status;
12+
import org.eclipse.jgit.api.errors.GitAPIException;
13+
import org.eclipse.jgit.lib.ObjectId;
14+
import org.eclipse.jgit.lib.Repository;
15+
import org.eclipse.jgit.revwalk.RevCommit;
16+
import org.eclipse.jgit.revwalk.RevWalk;
17+
import org.slf4j.Logger;
18+
import org.slf4j.LoggerFactory;
19+
20+
/**
21+
* GitStatusChecker 用于从任意路径检测当前 Git 仓库状态。
22+
* 如果找不到仓库,返回 tracking = false 的 GitStatusSnapshot;
23+
* 否则返回完整状态(tracking + syncStatus + conflict)。
24+
*/
25+
public class GitStatusChecker {
26+
private static final Logger LOGGER = LoggerFactory.getLogger(GitStatusChecker.class);
27+
28+
public static GitStatusSnapshot checkStatus(Path anyPathInsideRepo) {
29+
Optional<GitHandler> maybeHandler = GitHandler.fromAnyPath(anyPathInsideRepo);
30+
31+
if (maybeHandler.isEmpty()) {
32+
return new GitStatusSnapshot(false, SyncStatus.UNTRACKED, false, Optional.empty());
33+
}
34+
GitHandler handler = maybeHandler.get();
35+
36+
try (Git git = Git.open(handler.getRepositoryPathAsFile())) {
37+
Repository repo = git.getRepository();
38+
Status status = git.status().call();
39+
boolean hasConflict = !status.getConflicting().isEmpty();
40+
41+
ObjectId localHead = repo.resolve("HEAD");
42+
ObjectId remoteHead = repo.resolve("@{u}");
43+
SyncStatus syncStatus = determineSyncStatus(repo, localHead, remoteHead);
44+
45+
return new GitStatusSnapshot(
46+
true,
47+
syncStatus,
48+
hasConflict,
49+
Optional.ofNullable(localHead).map(ObjectId::getName)
50+
);
51+
} catch (IOException | GitAPIException e) {
52+
LOGGER.warn("Failed to check Git status: " + e.getMessage());
53+
return new GitStatusSnapshot(
54+
true,
55+
SyncStatus.UNKNOWN,
56+
false,
57+
Optional.empty()
58+
);
59+
}
60+
}
61+
62+
private static SyncStatus determineSyncStatus(Repository repo, ObjectId localHead, ObjectId remoteHead) throws IOException {
63+
if (localHead == null || remoteHead == null) {
64+
return SyncStatus.UNKNOWN;
65+
}
66+
67+
if (localHead.equals(remoteHead)) {
68+
return SyncStatus.UP_TO_DATE;
69+
}
70+
71+
try (RevWalk walk = new RevWalk(repo)) {
72+
RevCommit localCommit = walk.parseCommit(localHead);
73+
RevCommit remoteCommit = walk.parseCommit(remoteHead);
74+
RevCommit mergeBase = GitRevisionLocator.findMergeBase(repo, localCommit, remoteCommit);
75+
76+
boolean ahead = !localCommit.equals(mergeBase);
77+
boolean behind = !remoteCommit.equals(mergeBase);
78+
79+
if (ahead && behind) {
80+
return SyncStatus.DIVERGED;
81+
} else if (ahead) {
82+
return SyncStatus.AHEAD;
83+
} else if (behind) {
84+
return SyncStatus.BEHIND;
85+
} else {
86+
return SyncStatus.UNKNOWN;
87+
}
88+
}
89+
}
90+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.jabref.logic.git.status;
2+
3+
public enum SyncStatus {
4+
UP_TO_DATE, // Local and remote are in sync
5+
BEHIND, // Local is behind remote, pull needed
6+
AHEAD, // Local is ahead of remote, push needed
7+
DIVERGED, // Both local and remote have new commits; merge required
8+
CONFLICT, // Merge conflict detected
9+
UNTRACKED, // Not under Git control
10+
UNKNOWN // Status couldn't be determined
11+
}

0 commit comments

Comments
 (0)