Fix external file modification warnings during Git merge #13946
Conversation
|
Sorry, this PR has become too large... |
| if (localIsAncestorOfRemote) { // BEHIND (we know remote is ahead of local) | ||
| if (bibEqualsRemote) { | ||
| gitHandler.fastForwardTo(remote); | ||
| return FinalizeResult.fastForward(); |
There was a problem hiding this comment.
The method should not return null. Consider using java.util.Optional to handle cases where a result might not be present.
|
|
||
| private static boolean blobEqualsCommitPath(Git git, RevCommit commit, String relPath, Path file) { | ||
| try { | ||
| Optional<String> content = GitFileReader.readFileFromCommit(git, commit, Path.of(relPath)); |
There was a problem hiding this comment.
Use modern Java best practices such as Path.of() instead of Paths.get() to improve readability and maintainability.
| public static MergePlan empty() { | ||
| return new MergePlan(Map.of(), List.of(), List.of()); | ||
| } |
There was a problem hiding this comment.
The method 'empty' should not return null and should use java.util.Optional to handle empty states more effectively.
There was a problem hiding this comment.
I think, here it returns a valid MergePlan instance with empty fields rather than a missing value, which does not refer to Optional...?
| } | ||
|
|
||
| public record PushResult(boolean successful, boolean noop) { | ||
| /// Created when local branch has commits to push and the push succeeded. |
There was a problem hiding this comment.
The comment is trivial and restates the obvious, which goes against the guideline that comments should add new information and not be plainly derived from the code itself.
| return new PushResult(true, false); | ||
| } | ||
|
|
||
| /// Created when there is nothing to push (local is up to date with remote). |
There was a problem hiding this comment.
The comment is trivial and restates the obvious, which goes against the guideline that comments should add new information and not be plainly derived from the code itself.
…/jabref into fix/files-changed-externally
|
@trag-bot didn't find any issues in the code! ✅✨ |
JabRef/jabref#13946 jablib/src/main/java/org/jabref/logic/git/conflicts/GitConflictResolverStrategy.java
koppor
left a comment
There was a problem hiding this comment.
Some small comments
I think, this really needs to be tested manually 😅. Maybe now - but if no one has time, we merge it into main and see what users say.
| Localization.lang("Fast-forwarded to remote.") | ||
| ); | ||
| } else { | ||
| String stats = Localization.lang( |
There was a problem hiding this comment.
Normally, one uses StringJoiner with " ") as separator.
|
|
||
| private PullResult doPull(BibDatabaseContext databaseContext, Path bibPath, GitHandlerRegistry registry) throws IOException, GitAPIException, JabRefException { | ||
| GitSyncService syncService = buildSyncService(bibPath, registry); | ||
| private Optional<PullPlan> prepareMergeResult(BibDatabaseContext databaseContext, Path bibPath, GitHandlerRegistry registry) throws IOException, GitAPIException, JabRefException { |
There was a problem hiding this comment.
Please add JavaDoc when the optional is empty.
| PullPlan pullPlan) | ||
| throws IOException, GitAPIException, JabRefException { | ||
| GitFileWriter.write(bibPath, databaseContext, guiPreferences.getImportFormatPreferences()); | ||
| // Git bookkeeping |
There was a problem hiding this comment.
Comment can be remoed, can't it? --> The line is self-explanatory, isn't it?
| return gitSyncService.finalizeMerge(bibPath, pullPlan); | ||
| } | ||
|
|
||
| // ------------------- helpers: memory mutations ------------------- |
There was a problem hiding this comment.
Not sure what this comment means.
Since the class is not long - just remove it.
(Otherwise: // region: xyz and then // endregion would be thing to group methods)
| return new GitSyncService(guiPreferences.getImportFormatPreferences(), handlerRegistry, resolver, mergeExecutor); | ||
| /// Apply (remote - base) patches safely into the in-memory DB, plus safe new/deleted entries. | ||
| private static void applyAutoPlan(BibDatabaseContext bibDatabaseContext, MergePlan plan) { | ||
| // new entries |
There was a problem hiding this comment.
Remove the comment - the loop says it.
| import org.eclipse.jgit.lib.Repository; | ||
| import org.eclipse.jgit.revwalk.RevCommit; | ||
|
|
||
| public final class DefaultMergeBookkeeper implements MergeBookkeeper { |
There was a problem hiding this comment.
Please add JavaDoc about the intention of this class.
There was a problem hiding this comment.
Since there is only one implementation of "MergeBookkeeper", I would merge these two classes - or document at "MergeBookkeeper" about the possible implementation variants.
| /** | ||
| * Record the GUI-produced merge result into Git history. | ||
| * Creates the right commit shape based on the merge graph: | ||
| * - BEHIND: fast-forward if content equals remote; | ||
| * otherwise create a new commit on top of `remote`. | ||
| * - DIVERGED: create a merge commit with parents [localHead, remote]. | ||
| * | ||
| * Preconditions: | ||
| * - GUI has already saved the final .bib file to disk. | ||
| * - No unrelated unstaged changes (defensive check recommended). | ||
| */ |
There was a problem hiding this comment.
Convert to /// because the content is Markdown
| author = {author-a}, | ||
| doi = {xya}, |
There was a problem hiding this comment.
Please indent by two to have it consistently formatted. - a non-indent is very strange and seems like an issue
(at "normalize", you do remove the spaces, therefore, the tests work))
| * Apply user-resolved entries into MEMORY: replace or insert by citation key. | ||
| * (Aligned with MergeEntriesAction’s “edit the in-memory database first” philosophy.) | ||
| */ | ||
| private static void applyResolved(BibDatabaseContext bibDatabaseContext, List<BibEntry> resolved) { |
There was a problem hiding this comment.
Please do not duplice methods - you can use "package private" - meaning just leaving out "private" in the method to make it usable for for tests (Annote with @VisibleForTesting)
| } | ||
|
|
||
| /// Apply (remote - base) patches safely into the in-memory DB, plus safe new/deleted entries. | ||
| private static void applyAutoPlan(BibDatabaseContext bibDatabaseContext, MergePlan plan) { |
There was a problem hiding this comment.
Please do not duplice methods - you can use "package private" - meaning just leaving out "private" in the method to make it usable for for tests (Annote with @VisibleForTesting)
subhramit
left a comment
There was a problem hiding this comment.
Tiny suggestions, code reads very pleasant.
rename variables Co-authored-by: Subhramit Basu <subhramit.bb@live.in>
subhramit
left a comment
There was a problem hiding this comment.
Thanks a looot for continuing :)
calixtus
left a comment
There was a problem hiding this comment.
Just five small comments. Please forgive me if some of them were already discussed, I did not follow the reviews before.
| .onSuccess(finalizeResult -> { | ||
| gitStatusViewModel.refresh(bibFilePath); | ||
| if (finalizeResult.isFastForward()) { | ||
| dialogService.showInformationDialogAndWait( | ||
| Localization.lang("Git Pull"), | ||
| Localization.lang("Fast-forwarded to remote.") | ||
| ); | ||
| } else { | ||
| StringJoiner joiner = new StringJoiner(" "); | ||
| joiner.add(Localization.lang( | ||
| "Auto-applied changes: %0 new, %1 modified, %2 deleted.", | ||
| String.valueOf(autoNewCount), | ||
| String.valueOf(autoModifiedCount), | ||
| String.valueOf(autoDeletedCount) | ||
| )); | ||
| if (manualResolvedCount > 0) { | ||
| joiner.add(Localization.lang( | ||
| "%0 conflicts resolved.", | ||
| String.valueOf(manualResolvedCount) | ||
| )); | ||
| } | ||
| String stats = joiner.toString(); | ||
|
|
||
| dialogService.showInformationDialogAndWait( | ||
| Localization.lang("Git Pull"), | ||
| Localization.lang("Merged and updated.") + " " + stats | ||
| ); | ||
| } | ||
| }) |
There was a problem hiding this comment.
For the sake of clean code this code be extracted to a separate method.
| boolean inMerging = (state == RepositoryState.MERGING) || (state == RepositoryState.MERGING_RESOLVED); | ||
|
|
||
| if (dirty) { | ||
| if (!status.isClean()) { |
There was a problem hiding this comment.
For clean code nesting could be reduced by failing fast - meaning `if (status.isClean()) { return false; }
|
Looks really great so far. Very excited to have this merged. |
…/jabref into fix/files-changed-externally
* Changes by koppor * Changes by subhramit * update the JabRef code style * fix git pull action * fix git push action * test: migrate semantic conflict cases to SemanticMergeAnalyzerTest and add unit tests * fix: remove incorrect mention of `computeMergePlan` * fix: remove incorrect mention of `computeMergePlan` * Revert unintended renaming caused by IDE auto-formatting * Address part of trag-bot's suggestions in JabRef#13946 * Add missing English localization keys * remove obsolete inMerging branch in createCommitOnCurrentBranch * test: replace assertTrue with assertEquals * Clean up comments and variable names + Modify a test assertion * Change prepareMerge() to return Optional<PullPlan> for no-op cases * Fix failed tests * Update comments * remove exception control flow, assert presence of PullPlan instead * Handle the optional PullPlan * refactor(git): address review feedback * chore: fix OpenRewrite config and apply code style cleanup * Apply suggestions from code review rename variables Co-authored-by: Subhramit Basu <subhramit.bb@live.in> * fix:remove unnecessary annotation and avoid throwing RuntimeException --------- Co-authored-by: Subhramit Basu <subhramit.bb@live.in>
* Changes by koppor * Changes by subhramit * update the JabRef code style * fix git pull action * fix git push action * test: migrate semantic conflict cases to SemanticMergeAnalyzerTest and add unit tests * fix: remove incorrect mention of `computeMergePlan` * fix: remove incorrect mention of `computeMergePlan` * Revert unintended renaming caused by IDE auto-formatting * Address part of trag-bot's suggestions in JabRef#13946 * Add missing English localization keys * remove obsolete inMerging branch in createCommitOnCurrentBranch * test: replace assertTrue with assertEquals * Clean up comments and variable names + Modify a test assertion * Change prepareMerge() to return Optional<PullPlan> for no-op cases * Fix failed tests * Update comments * remove exception control flow, assert presence of PullPlan instead * Handle the optional PullPlan * refactor(git): address review feedback * chore: fix OpenRewrite config and apply code style cleanup * Apply suggestions from code review rename variables Co-authored-by: Subhramit Basu <subhramit.bb@live.in> * fix:remove unnecessary annotation and avoid throwing RuntimeException --------- Co-authored-by: Subhramit Basu <subhramit.bb@live.in>
JabRef/jabref#13946 jablib/src/main/java/org/jabref/logic/git/conflicts/GitConflictResolverStrategy.java
Closes #12350
Previously, JabRef sometimes showed file has been externally altered warnings after a Git pull.
Possible causes:
This PR changes the workflow:
Next steps
Steps to test
Mandatory checks
CHANGELOG.mdin a way that is understandable for the average user (if change is visible to the user)