From 01dec74406ad40c17c1b86623e4ac8b1814a67c3 Mon Sep 17 00:00:00 2001 From: RapidShotzz Date: Wed, 26 Feb 2025 13:09:34 +0000 Subject: [PATCH 01/72] added methods to and boolean to see if file is under version control and to pull latest changes if so --- .../java/org/jabref/logic/git/GitHandler.java | 25 +++++++++++++++++++ .../model/database/BibDatabaseContext.java | 17 +++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 77a78681428..d4c5e8ab860 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -11,8 +11,10 @@ import org.eclipse.jgit.api.RmCommand; import org.eclipse.jgit.api.Status; import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.merge.MergeStrategy; +import org.eclipse.jgit.storage.file.FileRepositoryBuilder; import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.slf4j.Logger; @@ -202,4 +204,27 @@ public String getCurrentlyCheckedOutBranch() throws IOException { return git.getRepository().getBranch(); } } + + public static boolean isUnderVersionControl(Path path) { + FileRepositoryBuilder builder = new FileRepositoryBuilder(); + + try { + builder.findGitDir(path.toFile()); + return builder.getGitDir() != null; + } catch (Exception e) { + return false; + } + } + + public static void pullChanges(Path repoPath) { + try (Git git = Git.open(repoPath.toFile())) { + System.out.println("Pulling latest changes..."); + git.pull().call(); + System.out.println("Repository updated successfully."); + } catch (RepositoryNotFoundException e) { + System.err.println("Not a valid Git repository: " + repoPath); + } catch (GitAPIException | IOException e) { + System.err.println("Error while pulling changes: " + e.getMessage()); + } + } } diff --git a/src/main/java/org/jabref/model/database/BibDatabaseContext.java b/src/main/java/org/jabref/model/database/BibDatabaseContext.java index 2efba5d6c65..52da983edc0 100644 --- a/src/main/java/org/jabref/model/database/BibDatabaseContext.java +++ b/src/main/java/org/jabref/model/database/BibDatabaseContext.java @@ -13,6 +13,7 @@ import org.jabref.logic.FilePreferences; import org.jabref.logic.crawler.Crawler; import org.jabref.logic.crawler.StudyRepository; +import org.jabref.logic.git.GitHandler; import org.jabref.logic.shared.DatabaseLocation; import org.jabref.logic.shared.DatabaseSynchronizer; import org.jabref.logic.util.CoarseChangeFilter; @@ -43,6 +44,7 @@ public class BibDatabaseContext { private final BibDatabase database; private MetaData metaData; + private Boolean underVersionControl; /** * Generate a random UID for unique of the concrete context @@ -315,4 +317,19 @@ public int hashCode() { public String getUid() { return uid; } + + public boolean isUnderVersionControl() { + if (underVersionControl == null) { + underVersionControl = getDatabasePath().map(GitHandler::isUnderVersionControl).orElse(false); + } + return underVersionControl; + } + + public void pullLatestChanges() { + getDatabasePath().ifPresent(path -> { + if (isUnderVersionControl()) { + GitHandler.pullChanges(path); + } + }); + } } From eb1b9a8b379c100b0e66c290135b7df80a6597a4 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Wed, 26 Feb 2025 15:21:33 +0000 Subject: [PATCH 02/72] Add CheckForVersionControlAction Update GitHandler constructor to optionally not create a repository if none exists --- .../actions/CheckForVersionControlAction.java | 42 ++++++++++++++++ .../java/org/jabref/logic/git/GitHandler.java | 48 ++++++++++++------- 2 files changed, 72 insertions(+), 18 deletions(-) create mode 100644 src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java diff --git a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java new file mode 100644 index 00000000000..11da5f58cc7 --- /dev/null +++ b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java @@ -0,0 +1,42 @@ +package org.jabref.gui.importer.actions; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Optional; + +import org.jabref.gui.DialogService; +import org.jabref.logic.git.GitHandler; +import org.jabref.logic.importer.ParserResult; +import org.jabref.logic.preferences.CliPreferences; + +/** + * This action checks whether this BIB file is contained in a Git repository. If so, + * then the file is tagged as "versioned" in BibDatabaseContext and a git pull is + * attempted. + */ +public class CheckForVersionControlAction implements GUIPostOpenAction { + private GitHandler gitHandler; + + @Override + public boolean isActionNecessary(ParserResult parserResult, DialogService dialogService, CliPreferences preferences) { + Optional path = parserResult.getDatabaseContext().getDatabasePath(); + if (path.isEmpty()) { + return false; + } else { + this.gitHandler = new GitHandler(path.get()); + return gitHandler.isGitRepository(); + } + } + + @Override + public void performAction(ParserResult parserResult, DialogService dialogService, CliPreferences preferencesService) { + // TODO: Tag as versioned + // TODO: If the preference exists, only pull if the user has this preference on + + try { + this.gitHandler.pullOnCurrentBranch(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index d4c5e8ab860..09b3e3fe0e3 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -38,28 +38,40 @@ public class GitHandler { * @param repositoryPath The root of the initialized git repository */ public GitHandler(Path repositoryPath) { + this(repositoryPath, true); + } + + /** + * Initialize the handler for the given repository + * + * @param repositoryPath The root of the initialized git repository + * @param createRepo If true, initializes a repository if the file path does not contain a repository + */ + public GitHandler(Path repositoryPath, boolean createRepo) { this.repositoryPath = repositoryPath; this.repositoryPathAsFile = this.repositoryPath.toFile(); if (!isGitRepository()) { - try { - Git.init() - .setDirectory(repositoryPathAsFile) - .setInitialBranch("main") - .call(); - setupGitIgnore(); - String initialCommit = "Initial commit"; - if (!createCommitOnCurrentBranch(initialCommit, false)) { - // Maybe, setupGitIgnore failed and did not add something - // Then, we create an empty commit - try (Git git = Git.open(repositoryPathAsFile)) { - git.commit() - .setAllowEmpty(true) - .setMessage(initialCommit) - .call(); + if (createRepo) { + try { + Git.init() + .setDirectory(repositoryPathAsFile) + .setInitialBranch("main") + .call(); + setupGitIgnore(); + String initialCommit = "Initial commit"; + if (!createCommitOnCurrentBranch(initialCommit, false)) { + // Maybe, setupGitIgnore failed and did not add something + // Then, we create an empty commit + try (Git git = Git.open(repositoryPathAsFile)) { + git.commit() + .setAllowEmpty(true) + .setMessage(initialCommit) + .call(); + } } + } catch (GitAPIException | IOException e) { + LOGGER.error("Initialization failed"); } - } catch (GitAPIException | IOException e) { - LOGGER.error("Initialization failed"); } } } @@ -78,7 +90,7 @@ void setupGitIgnore() { /** * Returns true if the given path points to a directory that is a git repository (contains a .git folder) */ - boolean isGitRepository() { + public boolean isGitRepository() { // For some reason the solution from https://www.eclipse.org/lists/jgit-dev/msg01892.html does not work // This solution is quite simple but might not work in special cases, for us it should suffice. return Files.exists(Path.of(repositoryPath.toString(), ".git")); From c761db59ff4a8a78227b59230f69d089e8e182d6 Mon Sep 17 00:00:00 2001 From: "Aryaman Amit Mehta (k23043160)" Date: Wed, 26 Feb 2025 17:35:02 +0000 Subject: [PATCH 03/72] Added unit tests for - CheckForVersionControlAction --- build.gradle | 1 + src/main/java/module-info.java | 3 +++ src/main/java/org/jabref/logic/preferences/CliPreferences.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/build.gradle b/build.gradle index fbafcd7bde5..7f281da0052 100644 --- a/build.gradle +++ b/build.gradle @@ -381,6 +381,7 @@ dependencies { testImplementation 'io.github.classgraph:classgraph:4.8.179' testImplementation 'org.junit.jupiter:junit-jupiter:5.11.4' + testImplementation 'org.mockito:mockito-junit-jupiter:5.15.2' testImplementation 'org.junit.platform:junit-platform-launcher:1.11.4' testImplementation 'org.mockito:mockito-core:5.15.2' diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index ccb2f386829..20543a29513 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -193,5 +193,8 @@ requires mslinks; requires org.antlr.antlr4.runtime; requires org.libreoffice.uno; + requires org.junit.jupiter.api; + requires org.mockito; + requires org.mockito.junit.jupiter; // endregion } diff --git a/src/main/java/org/jabref/logic/preferences/CliPreferences.java b/src/main/java/org/jabref/logic/preferences/CliPreferences.java index 0d39cdf55a1..d1ef5c515cc 100644 --- a/src/main/java/org/jabref/logic/preferences/CliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/CliPreferences.java @@ -116,4 +116,6 @@ public interface CliPreferences { AiPreferences getAiPreferences(); LastFilesOpenedPreferences getLastFilesOpenedPreferences(); + + Object isGitAutoPullEnabled(); } From 2c9dad4416b89206a1f23cc13ee34995979598c9 Mon Sep 17 00:00:00 2001 From: "Aryaman Amit Mehta (k23043160)" Date: Thu, 27 Feb 2025 16:38:27 +0000 Subject: [PATCH 04/72] Added unit tests for - CheckForVersionControlAction --- .../CheckForVersionControlActionTest.java | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java diff --git a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java new file mode 100644 index 00000000000..f9a8d19e355 --- /dev/null +++ b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java @@ -0,0 +1,155 @@ +package org.jabref.gui.importer.actions; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Optional; + +import org.jabref.gui.DialogService; +import org.jabref.logic.git.GitHandler; +import org.jabref.logic.importer.ParserResult; +import org.jabref.logic.preferences.CliPreferences; +import org.jabref.model.database.BibDatabaseContext; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class CheckForVersionControlActionTest { + + @Mock + private ParserResult parserResult; + @Mock + private DialogService dialogService; + @Mock + private CliPreferences cliPreferences; + @Mock + private BibDatabaseContext databaseContext; + @Mock + private GitHandler gitHandler; + + private CheckForVersionControlAction action; + + @BeforeEach + void setUp() { + action = new CheckForVersionControlAction(); + when(parserResult.getDatabaseContext()).thenReturn(databaseContext); + } + + // Test cases for isActionNecessary() + + @Test + void isActionNecessary_WhenDatabasePathIsEmpty_ShouldReturnFalse() { + when(databaseContext.getDatabasePath()).thenReturn(Optional.empty()); + + boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); + + assertFalse(result, "Expected isActionNecessary to return false when no database path exists."); + } + + @Test + void isActionNecessary_WhenDatabasePathExistsButNotAGitRepo_ShouldReturnFalse() { + Path mockPath = Path.of("/path/to/database.bib"); + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); + GitHandler mockGitHandler = mock(GitHandler.class); + when(mockGitHandler.isGitRepository()).thenReturn(false); + + // Inject the mocked GitHandler + action = new CheckForVersionControlAction(); + action.isActionNecessary(parserResult, dialogService, cliPreferences); + + boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); + + assertFalse(result, "Expected isActionNecessary to return false for a non-Git repository."); + } + + @Test + void isActionNecessary_WhenDatabasePathExistsAndIsAGitRepo_ShouldReturnTrue() { + Path mockPath = Path.of("/path/to/database.bib"); + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); + + GitHandler mockGitHandler = mock(GitHandler.class); + when(mockGitHandler.isGitRepository()).thenReturn(true); + + // Inject the mocked GitHandler + action = new CheckForVersionControlAction(); + action.isActionNecessary(parserResult, dialogService, cliPreferences); + + boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); + + assertTrue(result, "Expected isActionNecessary to return true for a valid Git repository."); + } + + // Test cases for performAction() + + @Test + void performAction_WhenGitPullSucceeds_ShouldNotThrowException() throws IOException { + Path mockPath = Path.of("/path/to/database.bib"); + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); + + GitHandler mockGitHandler = mock(GitHandler.class); + doNothing().when(mockGitHandler).pullOnCurrentBranch(); + + // Inject the mocked GitHandler + action = new CheckForVersionControlAction(); + action.isActionNecessary(parserResult, dialogService, cliPreferences); + action.performAction(parserResult, dialogService, cliPreferences); + + verify(mockGitHandler, times(1)).pullOnCurrentBranch(); + } + + @Test + void performAction_WhenGitPullFails_ShouldThrowRuntimeException() throws IOException { + Path mockPath = Path.of("/path/to/database.bib"); + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); + + GitHandler mockGitHandler = mock(GitHandler.class); + doThrow(new IOException("Git pull failed")).when(mockGitHandler).pullOnCurrentBranch(); + + action = new CheckForVersionControlAction(); + action.isActionNecessary(parserResult, dialogService, cliPreferences); + + Exception exception = assertThrows(RuntimeException.class, () -> + action.performAction(parserResult, dialogService, cliPreferences)); + + assertTrue(exception.getMessage().contains("Git pull failed")); + } + + @Test + void performAction_WhenDatabasePathIsEmpty_ShouldDoNothing() { + when(databaseContext.getDatabasePath()).thenReturn(Optional.empty()); + + action.performAction(parserResult, dialogService, cliPreferences); + + verifyNoInteractions(gitHandler); + } + + // Additional test case for checking preference behavior (once implemented) + @Test + void performAction_WhenPreferenceDisablesAutoPull_ShouldNotPull() throws IOException { + Path mockPath = Path.of("/path/to/database.bib"); + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); + when(cliPreferences.isGitAutoPullEnabled()).thenReturn(false); + + GitHandler mockGitHandler = mock(GitHandler.class); + action = new CheckForVersionControlAction(); + action.isActionNecessary(parserResult, dialogService, cliPreferences); + action.performAction(parserResult, dialogService, cliPreferences); + + verify(mockGitHandler, never()).pullOnCurrentBranch(); + } +} From ed6eb4ab66ceab50fd519f7c70f87a92a680a9b5 Mon Sep 17 00:00:00 2001 From: RapidShotzz Date: Thu, 27 Feb 2025 20:27:15 +0000 Subject: [PATCH 05/72] added functionality for tagging as versioned and pulling only if preference exists --- .../actions/CheckForVersionControlAction.java | 12 ++++++++---- .../jabref/logic/preferences/CliPreferences.java | 2 +- .../logic/preferences/JabRefCliPreferences.java | 6 ++++++ .../model/database/BibDatabaseContext.java | 16 ++++------------ 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java index 11da5f58cc7..7b26e88ad0a 100644 --- a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java @@ -33,10 +33,14 @@ public void performAction(ParserResult parserResult, DialogService dialogService // TODO: Tag as versioned // TODO: If the preference exists, only pull if the user has this preference on - try { - this.gitHandler.pullOnCurrentBranch(); - } catch (IOException e) { - throw new RuntimeException(e); + parserResult.getDatabaseContext().setVersioned(true); // tags as versioned + + if (preferencesService.shouldAutoPull()) { // pulls only if preference allows + try { + this.gitHandler.pullOnCurrentBranch(); + } catch (IOException e) { + throw new RuntimeException(e); + } } } } diff --git a/src/main/java/org/jabref/logic/preferences/CliPreferences.java b/src/main/java/org/jabref/logic/preferences/CliPreferences.java index d1ef5c515cc..c6beb09122d 100644 --- a/src/main/java/org/jabref/logic/preferences/CliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/CliPreferences.java @@ -117,5 +117,5 @@ public interface CliPreferences { LastFilesOpenedPreferences getLastFilesOpenedPreferences(); - Object isGitAutoPullEnabled(); + boolean shouldAutoPull(); } diff --git a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java index 095febc0b7f..2f88cc77a25 100644 --- a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java @@ -422,6 +422,8 @@ public class JabRefCliPreferences implements CliPreferences { private AiPreferences aiPreferences; private LastFilesOpenedPreferences lastFilesOpenedPreferences; + private boolean autoPullEnabled; + /** * @implNote The constructor is made protected to enforce this as a singleton class: */ @@ -2235,5 +2237,9 @@ public ImportFormatPreferences getImportFormatPreferences() { getGrobidPreferences()); } + public boolean shouldAutoPull() { + return autoPullEnabled; + } + // endregion } diff --git a/src/main/java/org/jabref/model/database/BibDatabaseContext.java b/src/main/java/org/jabref/model/database/BibDatabaseContext.java index 52da983edc0..cc23c2d144d 100644 --- a/src/main/java/org/jabref/model/database/BibDatabaseContext.java +++ b/src/main/java/org/jabref/model/database/BibDatabaseContext.java @@ -13,7 +13,6 @@ import org.jabref.logic.FilePreferences; import org.jabref.logic.crawler.Crawler; import org.jabref.logic.crawler.StudyRepository; -import org.jabref.logic.git.GitHandler; import org.jabref.logic.shared.DatabaseLocation; import org.jabref.logic.shared.DatabaseSynchronizer; import org.jabref.logic.util.CoarseChangeFilter; @@ -318,18 +317,11 @@ public String getUid() { return uid; } - public boolean isUnderVersionControl() { - if (underVersionControl == null) { - underVersionControl = getDatabasePath().map(GitHandler::isUnderVersionControl).orElse(false); - } - return underVersionControl; + public boolean isVersioned() { + return Boolean.TRUE.equals(underVersionControl); } - public void pullLatestChanges() { - getDatabasePath().ifPresent(path -> { - if (isUnderVersionControl()) { - GitHandler.pullChanges(path); - } - }); + public void setVersioned(boolean versioned) { + this.underVersionControl = versioned; } } From 9cbdd7624e5c705cd0898d860ada422081157eaf Mon Sep 17 00:00:00 2001 From: RapidShotzz Date: Thu, 27 Feb 2025 20:53:38 +0000 Subject: [PATCH 06/72] moved test file and amended shouldAutoPull method to test.org.jabref.gui.importer.actions --- .../gui/importer/actions/CheckForVersionControlActionTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/{main => test}/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java (98%) diff --git a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java similarity index 98% rename from src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java rename to src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java index f9a8d19e355..16b45be4a41 100644 --- a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java +++ b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java @@ -143,7 +143,7 @@ void performAction_WhenDatabasePathIsEmpty_ShouldDoNothing() { void performAction_WhenPreferenceDisablesAutoPull_ShouldNotPull() throws IOException { Path mockPath = Path.of("/path/to/database.bib"); when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); - when(cliPreferences.isGitAutoPullEnabled()).thenReturn(false); + when(cliPreferences.shouldAutoPull()).thenReturn(false); GitHandler mockGitHandler = mock(GitHandler.class); action = new CheckForVersionControlAction(); From 62defc41d874e2d234f3a2abb0c4c6f3e50258a3 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Sat, 1 Mar 2025 18:12:26 +0000 Subject: [PATCH 07/72] Remove RuntimeException from CheckForVersionControlAction --- .../importer/actions/CheckForVersionControlAction.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java index 7b26e88ad0a..025ed4ac723 100644 --- a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java @@ -9,12 +9,16 @@ import org.jabref.logic.importer.ParserResult; import org.jabref.logic.preferences.CliPreferences; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * This action checks whether this BIB file is contained in a Git repository. If so, * then the file is tagged as "versioned" in BibDatabaseContext and a git pull is * attempted. */ public class CheckForVersionControlAction implements GUIPostOpenAction { + private static final Logger LOGGER = LoggerFactory.getLogger(CheckForVersionControlAction.class); private GitHandler gitHandler; @Override @@ -30,16 +34,13 @@ public boolean isActionNecessary(ParserResult parserResult, DialogService dialog @Override public void performAction(ParserResult parserResult, DialogService dialogService, CliPreferences preferencesService) { - // TODO: Tag as versioned - // TODO: If the preference exists, only pull if the user has this preference on - parserResult.getDatabaseContext().setVersioned(true); // tags as versioned if (preferencesService.shouldAutoPull()) { // pulls only if preference allows try { this.gitHandler.pullOnCurrentBranch(); } catch (IOException e) { - throw new RuntimeException(e); + LOGGER.error("Failed to pull.", e); } } } From bbc6b381048e1386b84ec49a2b6d379dd982b08e Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Sat, 1 Mar 2025 18:37:32 +0000 Subject: [PATCH 08/72] Remove redundant methods from GitHandler --- .../java/org/jabref/logic/git/GitHandler.java | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 09b3e3fe0e3..a31d0362b6b 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -11,10 +11,8 @@ import org.eclipse.jgit.api.RmCommand; import org.eclipse.jgit.api.Status; import org.eclipse.jgit.api.errors.GitAPIException; -import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.merge.MergeStrategy; -import org.eclipse.jgit.storage.file.FileRepositoryBuilder; import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.slf4j.Logger; @@ -216,27 +214,4 @@ public String getCurrentlyCheckedOutBranch() throws IOException { return git.getRepository().getBranch(); } } - - public static boolean isUnderVersionControl(Path path) { - FileRepositoryBuilder builder = new FileRepositoryBuilder(); - - try { - builder.findGitDir(path.toFile()); - return builder.getGitDir() != null; - } catch (Exception e) { - return false; - } - } - - public static void pullChanges(Path repoPath) { - try (Git git = Git.open(repoPath.toFile())) { - System.out.println("Pulling latest changes..."); - git.pull().call(); - System.out.println("Repository updated successfully."); - } catch (RepositoryNotFoundException e) { - System.err.println("Not a valid Git repository: " + repoPath); - } catch (GitAPIException | IOException e) { - System.err.println("Error while pulling changes: " + e.getMessage()); - } - } } From 69e0f9a4800f6db565e184cbf71464b3f0170d80 Mon Sep 17 00:00:00 2001 From: "Aryaman Amit Mehta (k23043160)" Date: Sat, 1 Mar 2025 19:36:47 +0000 Subject: [PATCH 09/72] modified the test cases for CheckForVersionControlAction --- .../CheckForVersionControlActionTest.java | 698 +++++++++++++++--- .../java/org/jabref/logic/git/GitHandler.java | 2 +- 2 files changed, 599 insertions(+), 101 deletions(-) diff --git a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java index f9a8d19e355..6bf1cc14974 100644 --- a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java +++ b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java @@ -2,154 +2,652 @@ import java.io.IOException; import java.nio.file.Path; +import java.util.Collection; +import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.function.Consumer; +import java.util.prefs.BackingStoreException; + +import javafx.concurrent.Task; +import javafx.print.PrinterJob; +import javafx.scene.control.Alert; +import javafx.scene.control.ButtonType; +import javafx.scene.control.Dialog; +import javafx.scene.control.DialogPane; +import javafx.util.StringConverter; import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.util.BaseDialog; +import org.jabref.gui.util.BaseWindow; +import org.jabref.gui.util.DirectoryDialogConfiguration; +import org.jabref.gui.util.FileDialogConfiguration; +import org.jabref.logic.FilePreferences; +import org.jabref.logic.InternalPreferences; +import org.jabref.logic.JabRefException; +import org.jabref.logic.LibraryPreferences; +import org.jabref.logic.ai.AiPreferences; +import org.jabref.logic.bibtex.FieldPreferences; +import org.jabref.logic.citationkeypattern.CitationKeyPatternPreferences; +import org.jabref.logic.cleanup.CleanupPreferences; +import org.jabref.logic.exporter.ExportPreferences; +import org.jabref.logic.exporter.SelfContainedSaveConfiguration; import org.jabref.logic.git.GitHandler; +import org.jabref.logic.importer.FetcherException; +import org.jabref.logic.importer.ImportFormatPreferences; +import org.jabref.logic.importer.ImporterPreferences; import org.jabref.logic.importer.ParserResult; +import org.jabref.logic.importer.fetcher.MrDlibPreferences; +import org.jabref.logic.importer.util.GrobidPreferences; +import org.jabref.logic.journals.JournalAbbreviationPreferences; +import org.jabref.logic.layout.LayoutFormatterPreferences; +import org.jabref.logic.layout.format.NameFormatterPreferences; +import org.jabref.logic.net.ProxyPreferences; +import org.jabref.logic.net.ssl.SSLPreferences; +import org.jabref.logic.openoffice.OpenOfficePreferences; import org.jabref.logic.preferences.CliPreferences; +import org.jabref.logic.preferences.DOIPreferences; +import org.jabref.logic.preferences.LastFilesOpenedPreferences; +import org.jabref.logic.preferences.OwnerPreferences; +import org.jabref.logic.preferences.TimestampPreferences; +import org.jabref.logic.protectedterms.ProtectedTermsPreferences; +import org.jabref.logic.remote.RemotePreferences; +import org.jabref.logic.search.SearchPreferences; +import org.jabref.logic.util.io.AutoLinkPreferences; +import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntryPreferences; +import org.jabref.model.entry.BibEntryTypesManager; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -class CheckForVersionControlActionTest { - - @Mock - private ParserResult parserResult; - @Mock - private DialogService dialogService; - @Mock - private CliPreferences cliPreferences; - @Mock - private BibDatabaseContext databaseContext; - @Mock - private GitHandler gitHandler; + +class CheckForVersionControlActionTestWithoutMockito { private CheckForVersionControlAction action; + private ParserResult parserResult; + private FakeDialogService dialogService; + private FakeCliPreferences cliPreferences; + private FakeBibDatabaseContext databaseContext; + private FakeGitHandler gitHandler; - @BeforeEach - void setUp() { + public void setUp() { action = new CheckForVersionControlAction(); - when(parserResult.getDatabaseContext()).thenReturn(databaseContext); + parserResult = new ParserResult(); + dialogService = new FakeDialogService(); + cliPreferences = new FakeCliPreferences(); + databaseContext = new FakeBibDatabaseContext(); + gitHandler = new FakeGitHandler(); } - // Test cases for isActionNecessary() - - @Test - void isActionNecessary_WhenDatabasePathIsEmpty_ShouldReturnFalse() { - when(databaseContext.getDatabasePath()).thenReturn(Optional.empty()); + public void testIsActionNecessary_NoDatabasePath() { + databaseContext.setDatabasePath(null); + boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); + assert !result : "Expected isActionNecessary to return false when no database path exists."; + } + public void testIsActionNecessary_NonGitRepo() { + databaseContext.setDatabasePath(Path.of("test-repo")); + gitHandler.setGitRepository(false); boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); + assert !result : "Expected isActionNecessary to return false for a non-Git repository."; + } - assertFalse(result, "Expected isActionNecessary to return false when no database path exists."); + public void testIsActionNecessary_GitRepo() { + databaseContext.setDatabasePath(Path.of("test-repo")); + gitHandler.setGitRepository(true); + boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); + assert result : "Expected isActionNecessary to return true for a valid Git repository."; } - @Test - void isActionNecessary_WhenDatabasePathExistsButNotAGitRepo_ShouldReturnFalse() { - Path mockPath = Path.of("/path/to/database.bib"); - when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); - GitHandler mockGitHandler = mock(GitHandler.class); - when(mockGitHandler.isGitRepository()).thenReturn(false); + public void testPerformAction_GitPullSucceeds() { + databaseContext.setDatabasePath(Path.of("test-repo")); + gitHandler.setThrowException(false); - // Inject the mocked GitHandler - action = new CheckForVersionControlAction(); - action.isActionNecessary(parserResult, dialogService, cliPreferences); + try { + action.performAction(parserResult, dialogService, cliPreferences); + } catch (Exception e) { + assert false : "Expected performAction to complete without throwing exceptions."; + } + } - boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); + public void testPerformAction_GitPullFails() { + databaseContext.setDatabasePath(Path.of("test-repo")); + gitHandler.setThrowException(true); - assertFalse(result, "Expected isActionNecessary to return false for a non-Git repository."); + try { + action.performAction(parserResult, dialogService, cliPreferences); + assert false : "Expected RuntimeException when Git pull fails."; + } catch (RuntimeException e) { + assert e.getMessage().contains("Git pull failed") : "Exception message mismatch."; + } } - @Test - void isActionNecessary_WhenDatabasePathExistsAndIsAGitRepo_ShouldReturnTrue() { - Path mockPath = Path.of("/path/to/database.bib"); - when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); + public static void main(String[] args) { + CheckForVersionControlActionTestWithoutMockito test = new CheckForVersionControlActionTestWithoutMockito(); + test.setUp(); + test.testIsActionNecessary_NoDatabasePath(); + test.testIsActionNecessary_NonGitRepo(); + test.testIsActionNecessary_GitRepo(); + test.testPerformAction_GitPullSucceeds(); + test.testPerformAction_GitPullFails(); + System.out.println("All tests passed!"); + } - GitHandler mockGitHandler = mock(GitHandler.class); - when(mockGitHandler.isGitRepository()).thenReturn(true); + // Fake Implementations + class FakeDialogService implements DialogService { + @Override + public Optional showChoiceDialogAndWait(String title, String content, String okButtonLabel, T defaultChoice, Collection choices) { + return Optional.empty(); + } - // Inject the mocked GitHandler - action = new CheckForVersionControlAction(); - action.isActionNecessary(parserResult, dialogService, cliPreferences); + @Override + public Optional showEditableChoiceDialogAndWait(String title, String content, String okButtonLabel, T defaultChoice, Collection choices, StringConverter converter) { + return Optional.empty(); + } - boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); + @Override + public Optional showInputDialogAndWait(String title, String content) { + return Optional.empty(); + } - assertTrue(result, "Expected isActionNecessary to return true for a valid Git repository."); - } + @Override + public Optional showInputDialogWithDefaultAndWait(String title, String content, String defaultValue) { + return Optional.empty(); + } - // Test cases for performAction() + @Override + public void showInformationDialogAndWait(String title, String content) { - @Test - void performAction_WhenGitPullSucceeds_ShouldNotThrowException() throws IOException { - Path mockPath = Path.of("/path/to/database.bib"); - when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); + } - GitHandler mockGitHandler = mock(GitHandler.class); - doNothing().when(mockGitHandler).pullOnCurrentBranch(); + @Override + public void showWarningDialogAndWait(String title, String content) { - // Inject the mocked GitHandler - action = new CheckForVersionControlAction(); - action.isActionNecessary(parserResult, dialogService, cliPreferences); - action.performAction(parserResult, dialogService, cliPreferences); + } + + @Override + public void showErrorDialogAndWait(String title, String content) { + + } + + @Override + public void showErrorDialogAndWait(String message, Throwable exception) { + + } + + @Override + public void showErrorDialogAndWait(Exception exception) { + + } + + @Override + public void showErrorDialogAndWait(FetcherException fetcherException) { + + } + + @Override + public void showErrorDialogAndWait(String title, String content, Throwable exception) { + + } + + @Override + public void showErrorDialogAndWait(String message) { + + } + + @Override + public boolean showConfirmationDialogAndWait(String title, String content) { + return false; + } + + @Override + public boolean showConfirmationDialogAndWait(String title, String content, String okButtonLabel) { + return false; + } + + @Override + public boolean showConfirmationDialogAndWait(String title, String content, String okButtonLabel, String cancelButtonLabel) { + return false; + } + + @Override + public boolean showConfirmationDialogWithOptOutAndWait(String title, String content, String optOutMessage, Consumer optOutAction) { + return false; + } + + @Override + public boolean showConfirmationDialogWithOptOutAndWait(String title, String content, String okButtonLabel, String cancelButtonLabel, String optOutMessage, Consumer optOutAction) { + return false; + } + + @Override + public Optional showPasswordDialogAndWait(String title, String header, String content) { + return Optional.empty(); + } + + @Override + public void showCustomDialog(BaseDialog dialog) { - verify(mockGitHandler, times(1)).pullOnCurrentBranch(); + } + + @Override + public void showCustomWindow(BaseWindow window) { + + } + + @Override + public Optional showCustomButtonDialogAndWait(Alert.AlertType type, String title, String content, ButtonType... buttonTypes) { + return Optional.empty(); + } + + @Override + public Optional showCustomDialogAndWait(String title, DialogPane contentPane, ButtonType... buttonTypes) { + return Optional.empty(); + } + + @Override + public Optional showCustomDialogAndWait(Dialog dialog) { + return Optional.empty(); + } + + @Override + public void showProgressDialog(String title, String content, Task task) { + + } + + @Override + public void showProgressDialogAndWait(String title, String content, Task task) { + + } + + @Override + public Optional showBackgroundProgressDialogAndWait(String title, String content, StateManager stateManager) { + return Optional.empty(); + } + + @Override + public Optional showFileSaveDialog(FileDialogConfiguration fileDialogConfiguration) { + return Optional.empty(); + } + + @Override + public Optional showFileOpenDialog(FileDialogConfiguration fileDialogConfiguration) { + return Optional.empty(); + } + + @Override + public List showFileOpenDialogAndGetMultipleFiles(FileDialogConfiguration fileDialogConfiguration) { + return List.of(); + } + + @Override + public Optional showDirectorySelectionDialog(DirectoryDialogConfiguration directoryDialogConfiguration) { + return Optional.empty(); + } + + @Override + public boolean showPrintDialog(PrinterJob job) { + return false; + } + + @Override + public Optional showFileOpenFromArchiveDialog(Path archivePath) throws IOException { + return Optional.empty(); + } + + @Override + public void notify(String message) { + + } } - @Test - void performAction_WhenGitPullFails_ShouldThrowRuntimeException() throws IOException { - Path mockPath = Path.of("/path/to/database.bib"); - when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); + class FakeCliPreferences implements CliPreferences { + @Override + public void clear() throws BackingStoreException { - GitHandler mockGitHandler = mock(GitHandler.class); - doThrow(new IOException("Git pull failed")).when(mockGitHandler).pullOnCurrentBranch(); + } - action = new CheckForVersionControlAction(); - action.isActionNecessary(parserResult, dialogService, cliPreferences); + @Override + public void deleteKey(String key) throws IllegalArgumentException { + + } + + @Override + public void flush() { + + } + + @Override + public void exportPreferences(Path file) throws JabRefException { + + } + + @Override + public void importPreferences(Path file) throws JabRefException { + + } + + @Override + public InternalPreferences getInternalPreferences() { + return null; + } - Exception exception = assertThrows(RuntimeException.class, () -> - action.performAction(parserResult, dialogService, cliPreferences)); + @Override + public BibEntryPreferences getBibEntryPreferences() { + return null; + } - assertTrue(exception.getMessage().contains("Git pull failed")); + @Override + public JournalAbbreviationPreferences getJournalAbbreviationPreferences() { + return null; + } + + @Override + public FilePreferences getFilePreferences() { + return null; + } + + @Override + public FieldPreferences getFieldPreferences() { + return null; + } + + @Override + public OpenOfficePreferences getOpenOfficePreferences() { + return null; + } + + @Override + public Map getPreferences() { + return Map.of(); + } + + @Override + public Map getDefaults() { + return Map.of(); + } + + @Override + public LayoutFormatterPreferences getLayoutFormatterPreferences() { + return null; + } + + @Override + public ImportFormatPreferences getImportFormatPreferences() { + return null; + } + + @Override + public SelfContainedSaveConfiguration getSelfContainedExportConfiguration() { + return null; + } + + @Override + public BibEntryTypesManager getCustomEntryTypesRepository() { + return null; + } + + @Override + public void storeCustomEntryTypesRepository(BibEntryTypesManager entryTypesManager) { + + } + + @Override + public CleanupPreferences getCleanupPreferences() { + return null; + } + + @Override + public CleanupPreferences getDefaultCleanupPreset() { + return null; + } + + @Override + public LibraryPreferences getLibraryPreferences() { + return null; + } + + @Override + public DOIPreferences getDOIPreferences() { + return null; + } + + @Override + public OwnerPreferences getOwnerPreferences() { + return null; + } + + @Override + public TimestampPreferences getTimestampPreferences() { + return null; + } + + @Override + public RemotePreferences getRemotePreferences() { + return null; + } + + @Override + public ProxyPreferences getProxyPreferences() { + return null; + } + + @Override + public SSLPreferences getSSLPreferences() { + return null; + } + + @Override + public CitationKeyPatternPreferences getCitationKeyPatternPreferences() { + return null; + } + + @Override + public AutoLinkPreferences getAutoLinkPreferences() { + return null; + } + + @Override + public ExportPreferences getExportPreferences() { + return null; + } + + @Override + public ImporterPreferences getImporterPreferences() { + return null; + } + + @Override + public GrobidPreferences getGrobidPreferences() { + return null; + } + + @Override + public XmpPreferences getXmpPreferences() { + return null; + } + + @Override + public NameFormatterPreferences getNameFormatterPreferences() { + return null; + } + + @Override + public SearchPreferences getSearchPreferences() { + return null; + } + + @Override + public MrDlibPreferences getMrDlibPreferences() { + return null; + } + + @Override + public ProtectedTermsPreferences getProtectedTermsPreferences() { + return null; + } + + @Override + public AiPreferences getAiPreferences() { + return null; + } + + @Override + public LastFilesOpenedPreferences getLastFilesOpenedPreferences() { + return null; + } + + @Override + public Object isGitAutoPullEnabled() { + return null; + } } - @Test - void performAction_WhenDatabasePathIsEmpty_ShouldDoNothing() { - when(databaseContext.getDatabasePath()).thenReturn(Optional.empty()); + class FakeBibDatabaseContext extends BibDatabaseContext { + private Optional databasePath = Optional.empty(); - action.performAction(parserResult, dialogService, cliPreferences); + public void setDatabasePath(Path path) { + this.databasePath = Optional.ofNullable(path); + } - verifyNoInteractions(gitHandler); + @Override + public Optional getDatabasePath() { + return databasePath; + } } - // Additional test case for checking preference behavior (once implemented) - @Test - void performAction_WhenPreferenceDisablesAutoPull_ShouldNotPull() throws IOException { - Path mockPath = Path.of("/path/to/database.bib"); - when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); - when(cliPreferences.isGitAutoPullEnabled()).thenReturn(false); + class FakeGitHandler extends GitHandler { + private boolean isGitRepo = false; + private boolean throwException = false; - GitHandler mockGitHandler = mock(GitHandler.class); - action = new CheckForVersionControlAction(); - action.isActionNecessary(parserResult, dialogService, cliPreferences); - action.performAction(parserResult, dialogService, cliPreferences); + public FakeGitHandler() { + super(Path.of("default-repo")); // Provide a default repository path + } + + + public void setGitRepository(boolean isGitRepo) { + this.isGitRepo = isGitRepo; + } - verify(mockGitHandler, never()).pullOnCurrentBranch(); + public void setThrowException(boolean throwException) { + this.throwException = throwException; + } + + @Override + public boolean isGitRepository() { + return isGitRepo; + } + + @Override + public void pullOnCurrentBranch() throws IOException { + if (throwException) { + throw new IOException("Git pull failed"); + } + } } } + + +// +//package org.jabref.gui.importer.actions; +// +//import java.io.IOException; +//import java.nio.file.Path; +//import java.util.Optional; +// +//import org.jabref.gui.DialogService; +//import org.jabref.logic.git.GitHandler; +//import org.jabref.logic.importer.ParserResult; +//import org.jabref.logic.preferences.CliPreferences; +//import org.jabref.model.database.BibDatabaseContext; +// +//import org.junit.jupiter.api.BeforeEach; +//import org.junit.jupiter.api.Test; +//import org.mockito.Mockito; +// +//import static org.junit.jupiter.api.Assertions.*; +// import static org.mockito.Mockito.*; +// +//class CheckForVersionControlActionTest { +// +// private CheckForVersionControlAction action; +// private ParserResult parserResult; +// private DialogService dialogService; +// private CliPreferences cliPreferences; +// private BibDatabaseContext databaseContext; +// private GitHandler gitHandler; // Now mocked properly +// +// @BeforeEach +// void setUp() { +// action = new CheckForVersionControlAction(); +// parserResult = new ParserResult(); +// dialogService = mock(DialogService.class); // Mocked +// cliPreferences = mock(CliPreferences.class); // Mocked +// databaseContext = mock(BibDatabaseContext.class); // Mocked +// gitHandler = mock(GitHandler.class); // Mocked +// } +// +// @Test +// void isActionNecessary_WhenDatabasePathIsEmpty_ShouldReturnFalse() { +// when(databaseContext.getDatabasePath()).thenReturn(Optional.empty()); +// +// boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); +// +// assertFalse(result, "Expected isActionNecessary to return false when no database path exists."); +// } +// +// @Test +// void isActionNecessary_WhenDatabasePathExistsButNotAGitRepo_ShouldReturnFalse() { +// Path mockPath = Path.of("test-repo"); // Test directory instead of system path +// when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); +// +// GitHandler gitHandlerMock = mock(GitHandler.class); +// when(gitHandlerMock.isGitRepository()).thenReturn(false); +// +// boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); +// +// assertFalse(result, "Expected isActionNecessary to return false for a non-Git repository."); +// } +// +// @Test +// void isActionNecessary_WhenDatabasePathExistsAndIsAGitRepo_ShouldReturnTrue() { +// Path mockPath = Path.of("test-repo"); +// when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); +// +// GitHandler gitHandlerMock = mock(GitHandler.class); +// when(gitHandlerMock.isGitRepository()).thenReturn(true); +// +// boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); +// +// assertTrue(result, "Expected isActionNecessary to return true for a valid Git repository."); +// } +// +// @Test +// void performAction_WhenGitPullSucceeds_ShouldNotThrowException() throws IOException { +// Path mockPath = Path.of("test-repo"); +// when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); +// +// GitHandler gitHandlerMock = mock(GitHandler.class); +// doNothing().when(gitHandlerMock).pullOnCurrentBranch(); +// +// assertDoesNotThrow(() -> action.performAction(parserResult, dialogService, cliPreferences), +// "Expected performAction to complete without throwing exceptions."); +// } +// +// @Test +// void performAction_WhenGitPullFails_ShouldThrowRuntimeException() throws IOException { +// Path mockPath = Path.of("test-repo"); +// when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); +// +// GitHandler gitHandlerMock = mock(GitHandler.class); +// doThrow(new IOException("Git pull failed")).when(gitHandlerMock).pullOnCurrentBranch(); +// +// Exception exception = assertThrows(RuntimeException.class, () -> +// action.performAction(parserResult, dialogService, cliPreferences)); +// +// assertTrue(exception.getMessage().contains("Git pull failed"), +// "Expected RuntimeException when Git pull fails."); +// } +//} diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 09b3e3fe0e3..c4f9547f129 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -26,7 +26,7 @@ */ public class GitHandler { static final Logger LOGGER = LoggerFactory.getLogger(GitHandler.class); - final Path repositoryPath; + protected final Path repositoryPath; final File repositoryPathAsFile; String gitUsername = Optional.ofNullable(System.getenv("GIT_EMAIL")).orElse(""); String gitPassword = Optional.ofNullable(System.getenv("GIT_PW")).orElse(""); From cf32088aa3bb048676a89eeaba5313d75c1f659b Mon Sep 17 00:00:00 2001 From: "Aryaman Amit Mehta (k23043160)" Date: Sat, 1 Mar 2025 19:40:30 +0000 Subject: [PATCH 10/72] modified the test cases for CheckForVersionControlAction --- .../org/jabref/logic/preferences/CliPreferences.java | 2 ++ .../actions/CheckForVersionControlActionTest.java | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/jabref/logic/preferences/CliPreferences.java b/src/main/java/org/jabref/logic/preferences/CliPreferences.java index c6beb09122d..43e41c1a472 100644 --- a/src/main/java/org/jabref/logic/preferences/CliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/CliPreferences.java @@ -118,4 +118,6 @@ public interface CliPreferences { LastFilesOpenedPreferences getLastFilesOpenedPreferences(); boolean shouldAutoPull(); + + Object isGitAutoPullEnabled(); } diff --git a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java index 6bf1cc14974..d4f191ff519 100644 --- a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java +++ b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java @@ -60,10 +60,7 @@ import org.jabref.model.entry.BibEntryPreferences; import org.jabref.model.entry.BibEntryTypesManager; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class CheckForVersionControlActionTestWithoutMockito { +class CheckForVersionControlActionTest { private CheckForVersionControlAction action; private ParserResult parserResult; @@ -125,7 +122,7 @@ public void testPerformAction_GitPullFails() { } public static void main(String[] args) { - CheckForVersionControlActionTestWithoutMockito test = new CheckForVersionControlActionTestWithoutMockito(); + CheckForVersionControlActionTest test = new CheckForVersionControlActionTest(); test.setUp(); test.testIsActionNecessary_NoDatabasePath(); test.testIsActionNecessary_NonGitRepo(); @@ -499,6 +496,11 @@ public LastFilesOpenedPreferences getLastFilesOpenedPreferences() { return null; } + @Override + public boolean shouldAutoPull() { + return false; + } + @Override public Object isGitAutoPullEnabled() { return null; From c6706252a4a326a0a65d7d7067f1f01f9ec66bcf Mon Sep 17 00:00:00 2001 From: "Aryaman Amit Mehta (k23043160)" Date: Sat, 1 Mar 2025 19:44:18 +0000 Subject: [PATCH 11/72] modified the test cases for CheckForVersionControlAction --- .../gui/importer/actions/CheckForVersionControlActionTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java index d4f191ff519..c01a98f6bb0 100644 --- a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java +++ b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java @@ -1,5 +1,6 @@ package org.jabref.gui.importer.actions; + import java.io.IOException; import java.nio.file.Path; import java.util.Collection; From 9026eb9ac5dffaf37ff01329d40792290989996f Mon Sep 17 00:00:00 2001 From: "Aryaman Amit Mehta (k23043160)" Date: Sat, 1 Mar 2025 19:46:55 +0000 Subject: [PATCH 12/72] modified the test cases for CheckForVersionControlAction --- .../importer/actions/CheckForVersionControlActionTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java index c01a98f6bb0..c223da465e1 100644 --- a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java +++ b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java @@ -654,3 +654,7 @@ public void pullOnCurrentBranch() throws IOException { // "Expected RuntimeException when Git pull fails."); // } //} + + + + From 40cdd64878f8fd1e5c346aae45cefda15e7b8b35 Mon Sep 17 00:00:00 2001 From: "Aryaman Amit Mehta (k23043160)" Date: Sat, 1 Mar 2025 22:45:28 +0000 Subject: [PATCH 13/72] modified the test cases for CheckForVersionControlAction removed the logic that required the download of additional libraries/dependencies --- build.gradle | 1 - src/main/java/module-info.java | 3 - .../logic/preferences/CliPreferences.java | 7 +- .../CheckForVersionControlActionTest.java | 675 ++---------------- 4 files changed, 62 insertions(+), 624 deletions(-) diff --git a/build.gradle b/build.gradle index 7f281da0052..fbafcd7bde5 100644 --- a/build.gradle +++ b/build.gradle @@ -381,7 +381,6 @@ dependencies { testImplementation 'io.github.classgraph:classgraph:4.8.179' testImplementation 'org.junit.jupiter:junit-jupiter:5.11.4' - testImplementation 'org.mockito:mockito-junit-jupiter:5.15.2' testImplementation 'org.junit.platform:junit-platform-launcher:1.11.4' testImplementation 'org.mockito:mockito-core:5.15.2' diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 20543a29513..ccb2f386829 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -193,8 +193,5 @@ requires mslinks; requires org.antlr.antlr4.runtime; requires org.libreoffice.uno; - requires org.junit.jupiter.api; - requires org.mockito; - requires org.mockito.junit.jupiter; // endregion } diff --git a/src/main/java/org/jabref/logic/preferences/CliPreferences.java b/src/main/java/org/jabref/logic/preferences/CliPreferences.java index 43e41c1a472..74bb94440c6 100644 --- a/src/main/java/org/jabref/logic/preferences/CliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/CliPreferences.java @@ -67,7 +67,8 @@ public interface CliPreferences { ImportFormatPreferences getImportFormatPreferences(); /** - * Returns the export configuration. The contained SaveConfiguration is a {@link org.jabref.model.metadata.SelfContainedSaveOrder} + * Returns the export configuration. The contained SaveConfiguration is a + * {@link org.jabref.model.metadata.SelfContainedSaveOrder} */ SelfContainedSaveConfiguration getSelfContainedExportConfiguration(); @@ -117,7 +118,5 @@ public interface CliPreferences { LastFilesOpenedPreferences getLastFilesOpenedPreferences(); - boolean shouldAutoPull(); - - Object isGitAutoPullEnabled(); + Object shouldAutoPull(); } diff --git a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java index c223da465e1..8ff5666b371 100644 --- a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java +++ b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java @@ -1,660 +1,103 @@ package org.jabref.gui.importer.actions; - import java.io.IOException; import java.nio.file.Path; -import java.util.Collection; -import java.util.List; -import java.util.Map; import java.util.Optional; -import java.util.function.Consumer; -import java.util.prefs.BackingStoreException; - -import javafx.concurrent.Task; -import javafx.print.PrinterJob; -import javafx.scene.control.Alert; -import javafx.scene.control.ButtonType; -import javafx.scene.control.Dialog; -import javafx.scene.control.DialogPane; -import javafx.util.StringConverter; import org.jabref.gui.DialogService; -import org.jabref.gui.StateManager; -import org.jabref.gui.util.BaseDialog; -import org.jabref.gui.util.BaseWindow; -import org.jabref.gui.util.DirectoryDialogConfiguration; -import org.jabref.gui.util.FileDialogConfiguration; -import org.jabref.logic.FilePreferences; -import org.jabref.logic.InternalPreferences; -import org.jabref.logic.JabRefException; -import org.jabref.logic.LibraryPreferences; -import org.jabref.logic.ai.AiPreferences; -import org.jabref.logic.bibtex.FieldPreferences; -import org.jabref.logic.citationkeypattern.CitationKeyPatternPreferences; -import org.jabref.logic.cleanup.CleanupPreferences; -import org.jabref.logic.exporter.ExportPreferences; -import org.jabref.logic.exporter.SelfContainedSaveConfiguration; import org.jabref.logic.git.GitHandler; -import org.jabref.logic.importer.FetcherException; -import org.jabref.logic.importer.ImportFormatPreferences; -import org.jabref.logic.importer.ImporterPreferences; import org.jabref.logic.importer.ParserResult; -import org.jabref.logic.importer.fetcher.MrDlibPreferences; -import org.jabref.logic.importer.util.GrobidPreferences; -import org.jabref.logic.journals.JournalAbbreviationPreferences; -import org.jabref.logic.layout.LayoutFormatterPreferences; -import org.jabref.logic.layout.format.NameFormatterPreferences; -import org.jabref.logic.net.ProxyPreferences; -import org.jabref.logic.net.ssl.SSLPreferences; -import org.jabref.logic.openoffice.OpenOfficePreferences; import org.jabref.logic.preferences.CliPreferences; -import org.jabref.logic.preferences.DOIPreferences; -import org.jabref.logic.preferences.LastFilesOpenedPreferences; -import org.jabref.logic.preferences.OwnerPreferences; -import org.jabref.logic.preferences.TimestampPreferences; -import org.jabref.logic.protectedterms.ProtectedTermsPreferences; -import org.jabref.logic.remote.RemotePreferences; -import org.jabref.logic.search.SearchPreferences; -import org.jabref.logic.util.io.AutoLinkPreferences; -import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.database.BibDatabaseContext; -import org.jabref.model.entry.BibEntryPreferences; -import org.jabref.model.entry.BibEntryTypesManager; -class CheckForVersionControlActionTest { +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; +class CheckForVersionControlActionTest { private CheckForVersionControlAction action; private ParserResult parserResult; - private FakeDialogService dialogService; - private FakeCliPreferences cliPreferences; - private FakeBibDatabaseContext databaseContext; - private FakeGitHandler gitHandler; + private DialogService dialogService; + private CliPreferences cliPreferences; + private BibDatabaseContext databaseContext; + private GitHandler gitHandler; - public void setUp() { + @BeforeEach + void setUp() { action = new CheckForVersionControlAction(); - parserResult = new ParserResult(); - dialogService = new FakeDialogService(); - cliPreferences = new FakeCliPreferences(); - databaseContext = new FakeBibDatabaseContext(); - gitHandler = new FakeGitHandler(); - } + parserResult = mock(ParserResult.class); + dialogService = mock(DialogService.class); + cliPreferences = mock(CliPreferences.class); + databaseContext = mock(BibDatabaseContext.class); + gitHandler = mock(GitHandler.class); - public void testIsActionNecessary_NoDatabasePath() { - databaseContext.setDatabasePath(null); - boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); - assert !result : "Expected isActionNecessary to return false when no database path exists."; + when(parserResult.getDatabaseContext()).thenReturn(databaseContext); } - public void testIsActionNecessary_NonGitRepo() { - databaseContext.setDatabasePath(Path.of("test-repo")); - gitHandler.setGitRepository(false); - boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); - assert !result : "Expected isActionNecessary to return false for a non-Git repository."; - } + @Test + void isActionNecessary_WhenDatabasePathIsEmpty_ShouldReturnFalse() { + when(databaseContext.getDatabasePath()).thenReturn(Optional.empty()); - public void testIsActionNecessary_GitRepo() { - databaseContext.setDatabasePath(Path.of("test-repo")); - gitHandler.setGitRepository(true); boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); - assert result : "Expected isActionNecessary to return true for a valid Git repository."; - } - - public void testPerformAction_GitPullSucceeds() { - databaseContext.setDatabasePath(Path.of("test-repo")); - gitHandler.setThrowException(false); - - try { - action.performAction(parserResult, dialogService, cliPreferences); - } catch (Exception e) { - assert false : "Expected performAction to complete without throwing exceptions."; - } - } - - public void testPerformAction_GitPullFails() { - databaseContext.setDatabasePath(Path.of("test-repo")); - gitHandler.setThrowException(true); - try { - action.performAction(parserResult, dialogService, cliPreferences); - assert false : "Expected RuntimeException when Git pull fails."; - } catch (RuntimeException e) { - assert e.getMessage().contains("Git pull failed") : "Exception message mismatch."; - } + assertFalse(result, "Expected isActionNecessary to return false when no database path exists."); } - public static void main(String[] args) { - CheckForVersionControlActionTest test = new CheckForVersionControlActionTest(); - test.setUp(); - test.testIsActionNecessary_NoDatabasePath(); - test.testIsActionNecessary_NonGitRepo(); - test.testIsActionNecessary_GitRepo(); - test.testPerformAction_GitPullSucceeds(); - test.testPerformAction_GitPullFails(); - System.out.println("All tests passed!"); - } - - // Fake Implementations - class FakeDialogService implements DialogService { - @Override - public Optional showChoiceDialogAndWait(String title, String content, String okButtonLabel, T defaultChoice, Collection choices) { - return Optional.empty(); - } - - @Override - public Optional showEditableChoiceDialogAndWait(String title, String content, String okButtonLabel, T defaultChoice, Collection choices, StringConverter converter) { - return Optional.empty(); - } - - @Override - public Optional showInputDialogAndWait(String title, String content) { - return Optional.empty(); - } - - @Override - public Optional showInputDialogWithDefaultAndWait(String title, String content, String defaultValue) { - return Optional.empty(); - } - - @Override - public void showInformationDialogAndWait(String title, String content) { - - } - - @Override - public void showWarningDialogAndWait(String title, String content) { - - } - - @Override - public void showErrorDialogAndWait(String title, String content) { - - } - - @Override - public void showErrorDialogAndWait(String message, Throwable exception) { - - } - - @Override - public void showErrorDialogAndWait(Exception exception) { - - } - - @Override - public void showErrorDialogAndWait(FetcherException fetcherException) { - - } - - @Override - public void showErrorDialogAndWait(String title, String content, Throwable exception) { - - } - - @Override - public void showErrorDialogAndWait(String message) { - - } - - @Override - public boolean showConfirmationDialogAndWait(String title, String content) { - return false; - } - - @Override - public boolean showConfirmationDialogAndWait(String title, String content, String okButtonLabel) { - return false; - } - - @Override - public boolean showConfirmationDialogAndWait(String title, String content, String okButtonLabel, String cancelButtonLabel) { - return false; - } - - @Override - public boolean showConfirmationDialogWithOptOutAndWait(String title, String content, String optOutMessage, Consumer optOutAction) { - return false; - } - - @Override - public boolean showConfirmationDialogWithOptOutAndWait(String title, String content, String okButtonLabel, String cancelButtonLabel, String optOutMessage, Consumer optOutAction) { - return false; - } - - @Override - public Optional showPasswordDialogAndWait(String title, String header, String content) { - return Optional.empty(); - } - - @Override - public void showCustomDialog(BaseDialog dialog) { - - } - - @Override - public void showCustomWindow(BaseWindow window) { - - } - - @Override - public Optional showCustomButtonDialogAndWait(Alert.AlertType type, String title, String content, ButtonType... buttonTypes) { - return Optional.empty(); - } - - @Override - public Optional showCustomDialogAndWait(String title, DialogPane contentPane, ButtonType... buttonTypes) { - return Optional.empty(); - } - - @Override - public Optional showCustomDialogAndWait(Dialog dialog) { - return Optional.empty(); - } - - @Override - public void showProgressDialog(String title, String content, Task task) { - - } - - @Override - public void showProgressDialogAndWait(String title, String content, Task task) { - - } - - @Override - public Optional showBackgroundProgressDialogAndWait(String title, String content, StateManager stateManager) { - return Optional.empty(); - } - - @Override - public Optional showFileSaveDialog(FileDialogConfiguration fileDialogConfiguration) { - return Optional.empty(); - } - - @Override - public Optional showFileOpenDialog(FileDialogConfiguration fileDialogConfiguration) { - return Optional.empty(); - } - - @Override - public List showFileOpenDialogAndGetMultipleFiles(FileDialogConfiguration fileDialogConfiguration) { - return List.of(); - } + @Test + void isActionNecessary_WhenDatabasePathExistsButNotAGitRepo_ShouldReturnFalse() { + Path mockPath = Path.of("test-repo"); + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); - @Override - public Optional showDirectorySelectionDialog(DirectoryDialogConfiguration directoryDialogConfiguration) { - return Optional.empty(); - } + GitHandler gitHandlerMock = mock(GitHandler.class); + when(gitHandlerMock.isGitRepository()).thenReturn(false); - @Override - public boolean showPrintDialog(PrinterJob job) { - return false; - } - - @Override - public Optional showFileOpenFromArchiveDialog(Path archivePath) throws IOException { - return Optional.empty(); - } - - @Override - public void notify(String message) { + boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); - } + assertFalse(result, "Expected isActionNecessary to return false for a non-Git repository."); } - class FakeCliPreferences implements CliPreferences { - @Override - public void clear() throws BackingStoreException { - - } - - @Override - public void deleteKey(String key) throws IllegalArgumentException { - - } - - @Override - public void flush() { - - } - - @Override - public void exportPreferences(Path file) throws JabRefException { - - } - - @Override - public void importPreferences(Path file) throws JabRefException { - - } - - @Override - public InternalPreferences getInternalPreferences() { - return null; - } - - @Override - public BibEntryPreferences getBibEntryPreferences() { - return null; - } - - @Override - public JournalAbbreviationPreferences getJournalAbbreviationPreferences() { - return null; - } - - @Override - public FilePreferences getFilePreferences() { - return null; - } - - @Override - public FieldPreferences getFieldPreferences() { - return null; - } - - @Override - public OpenOfficePreferences getOpenOfficePreferences() { - return null; - } - - @Override - public Map getPreferences() { - return Map.of(); - } - - @Override - public Map getDefaults() { - return Map.of(); - } - - @Override - public LayoutFormatterPreferences getLayoutFormatterPreferences() { - return null; - } - - @Override - public ImportFormatPreferences getImportFormatPreferences() { - return null; - } - - @Override - public SelfContainedSaveConfiguration getSelfContainedExportConfiguration() { - return null; - } - - @Override - public BibEntryTypesManager getCustomEntryTypesRepository() { - return null; - } - - @Override - public void storeCustomEntryTypesRepository(BibEntryTypesManager entryTypesManager) { - - } - - @Override - public CleanupPreferences getCleanupPreferences() { - return null; - } - - @Override - public CleanupPreferences getDefaultCleanupPreset() { - return null; - } + @Test + void isActionNecessary_WhenDatabasePathExistsAndIsAGitRepo_ShouldReturnTrue() { + Path mockPath = Path.of("test-repo"); + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); - @Override - public LibraryPreferences getLibraryPreferences() { - return null; - } + GitHandler gitHandlerMock = mock(GitHandler.class); + when(gitHandlerMock.isGitRepository()).thenReturn(true); - @Override - public DOIPreferences getDOIPreferences() { - return null; - } - - @Override - public OwnerPreferences getOwnerPreferences() { - return null; - } - - @Override - public TimestampPreferences getTimestampPreferences() { - return null; - } - - @Override - public RemotePreferences getRemotePreferences() { - return null; - } - - @Override - public ProxyPreferences getProxyPreferences() { - return null; - } - - @Override - public SSLPreferences getSSLPreferences() { - return null; - } - - @Override - public CitationKeyPatternPreferences getCitationKeyPatternPreferences() { - return null; - } - - @Override - public AutoLinkPreferences getAutoLinkPreferences() { - return null; - } - - @Override - public ExportPreferences getExportPreferences() { - return null; - } - - @Override - public ImporterPreferences getImporterPreferences() { - return null; - } - - @Override - public GrobidPreferences getGrobidPreferences() { - return null; - } - - @Override - public XmpPreferences getXmpPreferences() { - return null; - } - - @Override - public NameFormatterPreferences getNameFormatterPreferences() { - return null; - } - - @Override - public SearchPreferences getSearchPreferences() { - return null; - } - - @Override - public MrDlibPreferences getMrDlibPreferences() { - return null; - } - - @Override - public ProtectedTermsPreferences getProtectedTermsPreferences() { - return null; - } - - @Override - public AiPreferences getAiPreferences() { - return null; - } - - @Override - public LastFilesOpenedPreferences getLastFilesOpenedPreferences() { - return null; - } - - @Override - public boolean shouldAutoPull() { - return false; - } + boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); - @Override - public Object isGitAutoPullEnabled() { - return null; - } + assertTrue(result, "Expected isActionNecessary to return true for a valid Git repository."); } - class FakeBibDatabaseContext extends BibDatabaseContext { - private Optional databasePath = Optional.empty(); + @Test + void performAction_WhenGitPullSucceeds_ShouldNotThrowException() throws IOException { + Path mockPath = Path.of("test-repo"); + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); + when(cliPreferences.shouldAutoPull()).thenReturn(true); - public void setDatabasePath(Path path) { - this.databasePath = Optional.ofNullable(path); - } + GitHandler gitHandlerMock = mock(GitHandler.class); + doNothing().when(gitHandlerMock).pullOnCurrentBranch(); - @Override - public Optional getDatabasePath() { - return databasePath; - } + assertDoesNotThrow(() -> action.performAction(parserResult, dialogService, cliPreferences), + "Expected performAction to complete without throwing exceptions."); } - class FakeGitHandler extends GitHandler { - private boolean isGitRepo = false; - private boolean throwException = false; - - public FakeGitHandler() { - super(Path.of("default-repo")); // Provide a default repository path - } - + @Test + void performAction_WhenGitPullFails_ShouldLogError() throws IOException { + Path mockPath = Path.of("test-repo"); + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); + when(cliPreferences.shouldAutoPull()).thenReturn(true); - public void setGitRepository(boolean isGitRepo) { - this.isGitRepo = isGitRepo; - } + GitHandler gitHandlerMock = mock(GitHandler.class); + doThrow(new IOException("Git pull failed")).when(gitHandlerMock).pullOnCurrentBranch(); - public void setThrowException(boolean throwException) { - this.throwException = throwException; - } + Exception exception = assertThrows(RuntimeException.class, () -> + action.performAction(parserResult, dialogService, cliPreferences)); - @Override - public boolean isGitRepository() { - return isGitRepo; - } - - @Override - public void pullOnCurrentBranch() throws IOException { - if (throwException) { - throw new IOException("Git pull failed"); - } - } + assertTrue(exception.getMessage().contains("Git pull failed"), + "Expected RuntimeException when Git pull fails."); } } - - -// -//package org.jabref.gui.importer.actions; -// -//import java.io.IOException; -//import java.nio.file.Path; -//import java.util.Optional; -// -//import org.jabref.gui.DialogService; -//import org.jabref.logic.git.GitHandler; -//import org.jabref.logic.importer.ParserResult; -//import org.jabref.logic.preferences.CliPreferences; -//import org.jabref.model.database.BibDatabaseContext; -// -//import org.junit.jupiter.api.BeforeEach; -//import org.junit.jupiter.api.Test; -//import org.mockito.Mockito; -// -//import static org.junit.jupiter.api.Assertions.*; -// import static org.mockito.Mockito.*; -// -//class CheckForVersionControlActionTest { -// -// private CheckForVersionControlAction action; -// private ParserResult parserResult; -// private DialogService dialogService; -// private CliPreferences cliPreferences; -// private BibDatabaseContext databaseContext; -// private GitHandler gitHandler; // Now mocked properly -// -// @BeforeEach -// void setUp() { -// action = new CheckForVersionControlAction(); -// parserResult = new ParserResult(); -// dialogService = mock(DialogService.class); // Mocked -// cliPreferences = mock(CliPreferences.class); // Mocked -// databaseContext = mock(BibDatabaseContext.class); // Mocked -// gitHandler = mock(GitHandler.class); // Mocked -// } -// -// @Test -// void isActionNecessary_WhenDatabasePathIsEmpty_ShouldReturnFalse() { -// when(databaseContext.getDatabasePath()).thenReturn(Optional.empty()); -// -// boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); -// -// assertFalse(result, "Expected isActionNecessary to return false when no database path exists."); -// } -// -// @Test -// void isActionNecessary_WhenDatabasePathExistsButNotAGitRepo_ShouldReturnFalse() { -// Path mockPath = Path.of("test-repo"); // Test directory instead of system path -// when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); -// -// GitHandler gitHandlerMock = mock(GitHandler.class); -// when(gitHandlerMock.isGitRepository()).thenReturn(false); -// -// boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); -// -// assertFalse(result, "Expected isActionNecessary to return false for a non-Git repository."); -// } -// -// @Test -// void isActionNecessary_WhenDatabasePathExistsAndIsAGitRepo_ShouldReturnTrue() { -// Path mockPath = Path.of("test-repo"); -// when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); -// -// GitHandler gitHandlerMock = mock(GitHandler.class); -// when(gitHandlerMock.isGitRepository()).thenReturn(true); -// -// boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); -// -// assertTrue(result, "Expected isActionNecessary to return true for a valid Git repository."); -// } -// -// @Test -// void performAction_WhenGitPullSucceeds_ShouldNotThrowException() throws IOException { -// Path mockPath = Path.of("test-repo"); -// when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); -// -// GitHandler gitHandlerMock = mock(GitHandler.class); -// doNothing().when(gitHandlerMock).pullOnCurrentBranch(); -// -// assertDoesNotThrow(() -> action.performAction(parserResult, dialogService, cliPreferences), -// "Expected performAction to complete without throwing exceptions."); -// } -// -// @Test -// void performAction_WhenGitPullFails_ShouldThrowRuntimeException() throws IOException { -// Path mockPath = Path.of("test-repo"); -// when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); -// -// GitHandler gitHandlerMock = mock(GitHandler.class); -// doThrow(new IOException("Git pull failed")).when(gitHandlerMock).pullOnCurrentBranch(); -// -// Exception exception = assertThrows(RuntimeException.class, () -> -// action.performAction(parserResult, dialogService, cliPreferences)); -// -// assertTrue(exception.getMessage().contains("Git pull failed"), -// "Expected RuntimeException when Git pull fails."); -// } -//} - - - - From 8db799cea15f88f3f39bb7edbe9a29e7d4c475f4 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Mon, 3 Mar 2025 14:20:14 +0000 Subject: [PATCH 14/72] Remove preference in CheckForVersionControlAction --- .../importer/actions/CheckForVersionControlAction.java | 10 ++++------ .../org/jabref/logic/preferences/CliPreferences.java | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java index 025ed4ac723..2db725f1516 100644 --- a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java @@ -36,12 +36,10 @@ public boolean isActionNecessary(ParserResult parserResult, DialogService dialog public void performAction(ParserResult parserResult, DialogService dialogService, CliPreferences preferencesService) { parserResult.getDatabaseContext().setVersioned(true); // tags as versioned - if (preferencesService.shouldAutoPull()) { // pulls only if preference allows - try { - this.gitHandler.pullOnCurrentBranch(); - } catch (IOException e) { - LOGGER.error("Failed to pull.", e); - } + try { + this.gitHandler.pullOnCurrentBranch(); + } catch (IOException e) { + LOGGER.error("Failed to pull.", e); } } } diff --git a/src/main/java/org/jabref/logic/preferences/CliPreferences.java b/src/main/java/org/jabref/logic/preferences/CliPreferences.java index 74bb94440c6..9fa68ca9adf 100644 --- a/src/main/java/org/jabref/logic/preferences/CliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/CliPreferences.java @@ -118,5 +118,5 @@ public interface CliPreferences { LastFilesOpenedPreferences getLastFilesOpenedPreferences(); - Object shouldAutoPull(); + boolean shouldAutoPull(); } From af0c3c8ebf4a51a0301520882b2919d6489f85b2 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Mon, 3 Mar 2025 16:58:36 +0000 Subject: [PATCH 15/72] Add git preferences --- .../org/jabref/logic/git/GitPreferences.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/org/jabref/logic/git/GitPreferences.java diff --git a/src/main/java/org/jabref/logic/git/GitPreferences.java b/src/main/java/org/jabref/logic/git/GitPreferences.java new file mode 100644 index 00000000000..01e2da07aef --- /dev/null +++ b/src/main/java/org/jabref/logic/git/GitPreferences.java @@ -0,0 +1,25 @@ +package org.jabref.logic.git; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GitPreferences { + private static final Logger LOGGER = LoggerFactory.getLogger(GitPreferences.class); + + private final BooleanProperty autoPushEnabled; + + public GitPreferences(boolean autoPushEnabled) { + this.autoPushEnabled = new SimpleBooleanProperty(autoPushEnabled); + } + + public boolean getAutoPushEnabled() { + return autoPushEnabled.get(); + } + + public BooleanProperty getAutoPushEnabledProperty() { + return autoPushEnabled; + } +} From 1f2de0af800ba27eb613644122dac1768f4ebd80 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Mon, 3 Mar 2025 17:05:30 +0000 Subject: [PATCH 16/72] Add GitPreferences to CliPreferences --- src/main/java/org/jabref/logic/preferences/CliPreferences.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/jabref/logic/preferences/CliPreferences.java b/src/main/java/org/jabref/logic/preferences/CliPreferences.java index 0d39cdf55a1..36b50bcd855 100644 --- a/src/main/java/org/jabref/logic/preferences/CliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/CliPreferences.java @@ -14,6 +14,7 @@ import org.jabref.logic.cleanup.CleanupPreferences; import org.jabref.logic.exporter.ExportPreferences; import org.jabref.logic.exporter.SelfContainedSaveConfiguration; +import org.jabref.logic.git.GitPreferences; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.ImporterPreferences; import org.jabref.logic.importer.fetcher.MrDlibPreferences; @@ -116,4 +117,6 @@ public interface CliPreferences { AiPreferences getAiPreferences(); LastFilesOpenedPreferences getLastFilesOpenedPreferences(); + + GitPreferences getGitPreferences(); } From cfd46db3282efca99bef6aa832879ddb32463b26 Mon Sep 17 00:00:00 2001 From: RapidShotzz Date: Mon, 3 Mar 2025 17:17:05 +0000 Subject: [PATCH 17/72] added autoPushEnabled attributes and set methods --- src/main/java/org/jabref/logic/git/GitPreferences.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/org/jabref/logic/git/GitPreferences.java b/src/main/java/org/jabref/logic/git/GitPreferences.java index 01e2da07aef..0171d5529f9 100644 --- a/src/main/java/org/jabref/logic/git/GitPreferences.java +++ b/src/main/java/org/jabref/logic/git/GitPreferences.java @@ -22,4 +22,12 @@ public boolean getAutoPushEnabled() { public BooleanProperty getAutoPushEnabledProperty() { return autoPushEnabled; } + + public void setAutoPushEnabled(boolean enabled) { + autoPushEnabled.set(enabled); + } + + public GitPreferences withAutoPushEnabled(boolean enabled) { + return new GitPreferences(enabled); + } } From 6ecf1a844103dd9d185bbc51e735a44b242f6d00 Mon Sep 17 00:00:00 2001 From: RapidShotzz Date: Mon, 3 Mar 2025 17:19:19 +0000 Subject: [PATCH 18/72] modified tab view model to handle auto push --- .../jabref/gui/preferences/general/GeneralTabViewModel.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java index 460d1aae3c7..87f1810792a 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java @@ -104,6 +104,8 @@ public class GeneralTabViewModel implements PreferenceTabViewModel { private final BibEntryTypesManager entryTypesManager; private final TrustStoreManager trustStoreManager; + private final BooleanProperty autoPushEnabled = new SimpleBooleanProperty(); + public GeneralTabViewModel(DialogService dialogService, GuiPreferences preferences, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager) { this.dialogService = dialogService; this.preferences = preferences; @@ -426,4 +428,8 @@ private Optional getPortAsInt(String value) { return Optional.empty(); } } + + public BooleanProperty autoPushEnabledProperty() { + return autoPushEnabled; + } } From a0e2dc75e629e9624fa06c6afb709e021a566575 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Mon, 3 Mar 2025 17:23:02 +0000 Subject: [PATCH 19/72] Add getGitPreferences to JabRefCliPreferences --- .../logic/preferences/JabRefCliPreferences.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java index 095febc0b7f..ad4327a1d0d 100644 --- a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java @@ -51,6 +51,7 @@ import org.jabref.logic.exporter.MetaDataSerializer; import org.jabref.logic.exporter.SelfContainedSaveConfiguration; import org.jabref.logic.exporter.TemplateExporter; +import org.jabref.logic.git.GitPreferences; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.ImporterPreferences; import org.jabref.logic.importer.fetcher.ACMPortalFetcher; @@ -421,6 +422,7 @@ public class JabRefCliPreferences implements CliPreferences { private FieldPreferences fieldPreferences; private AiPreferences aiPreferences; private LastFilesOpenedPreferences lastFilesOpenedPreferences; + private GitPreferences gitPreferences; /** * @implNote The constructor is made protected to enforce this as a singleton class: @@ -1819,6 +1821,17 @@ public LastFilesOpenedPreferences getLastFilesOpenedPreferences() { return lastFilesOpenedPreferences; } + @Override + public GitPreferences getGitPreferences() { + if (gitPreferences != null) { + return gitPreferences; + } + + // TODO: Construct git preferences + + return gitPreferences; + } + private FileHistory getFileHistory() { return FileHistory.of(getStringList(RECENT_DATABASES).stream() .map(Path::of) From 2bf349d03094d4a985fcc0cdcd556da404e0addc Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Mon, 3 Mar 2025 17:38:28 +0000 Subject: [PATCH 20/72] Remove redundant shouldAutoPull from CliPreferences --- .../logic/preferences/CliPreferences.java | 2 -- .../CheckForVersionControlActionTest.java | 17 +++++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/jabref/logic/preferences/CliPreferences.java b/src/main/java/org/jabref/logic/preferences/CliPreferences.java index 9fa68ca9adf..578118a8a48 100644 --- a/src/main/java/org/jabref/logic/preferences/CliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/CliPreferences.java @@ -117,6 +117,4 @@ public interface CliPreferences { AiPreferences getAiPreferences(); LastFilesOpenedPreferences getLastFilesOpenedPreferences(); - - boolean shouldAutoPull(); } diff --git a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java index 8ff5666b371..bfe1e36d2fe 100644 --- a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java +++ b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java @@ -12,10 +12,15 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; class CheckForVersionControlActionTest { private CheckForVersionControlAction action; @@ -62,7 +67,7 @@ void isActionNecessary_WhenDatabasePathExistsButNotAGitRepo_ShouldReturnFalse() @Test void isActionNecessary_WhenDatabasePathExistsAndIsAGitRepo_ShouldReturnTrue() { Path mockPath = Path.of("test-repo"); - when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); + //when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); GitHandler gitHandlerMock = mock(GitHandler.class); when(gitHandlerMock.isGitRepository()).thenReturn(true); @@ -76,7 +81,7 @@ void isActionNecessary_WhenDatabasePathExistsAndIsAGitRepo_ShouldReturnTrue() { void performAction_WhenGitPullSucceeds_ShouldNotThrowException() throws IOException { Path mockPath = Path.of("test-repo"); when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); - when(cliPreferences.shouldAutoPull()).thenReturn(true); + //when(cliPreferences.shouldAutoPull()).thenReturn(true); GitHandler gitHandlerMock = mock(GitHandler.class); doNothing().when(gitHandlerMock).pullOnCurrentBranch(); @@ -89,7 +94,7 @@ void performAction_WhenGitPullSucceeds_ShouldNotThrowException() throws IOExcept void performAction_WhenGitPullFails_ShouldLogError() throws IOException { Path mockPath = Path.of("test-repo"); when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); - when(cliPreferences.shouldAutoPull()).thenReturn(true); + //when(cliPreferences.shouldAutoPull()).thenReturn(true); GitHandler gitHandlerMock = mock(GitHandler.class); doThrow(new IOException("Git pull failed")).when(gitHandlerMock).pullOnCurrentBranch(); From bff985785ac5b70affaa37aa1066ffa542c421de Mon Sep 17 00:00:00 2001 From: SihasA Date: Mon, 3 Mar 2025 17:38:52 +0000 Subject: [PATCH 21/72] Added a rudimentary first draft preference selector under Saving in general for autopush - to be cleaned up --- .../org/jabref/gui/WorkspacePreferences.java | 33 ++++++++++++++++++- .../gui/preferences/JabRefGuiPreferences.java | 25 +++++++++++++- .../gui/preferences/general/GeneralTab.fxml | 4 +++ .../gui/preferences/general/GeneralTab.java | 14 ++++++++ .../general/GeneralTabViewModel.java | 15 ++++++--- .../logic/preferences/AutoPushMode.java | 25 ++++++++++++++ 6 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/jabref/logic/preferences/AutoPushMode.java diff --git a/src/main/java/org/jabref/gui/WorkspacePreferences.java b/src/main/java/org/jabref/gui/WorkspacePreferences.java index 2948be7582e..68b55083db0 100644 --- a/src/main/java/org/jabref/gui/WorkspacePreferences.java +++ b/src/main/java/org/jabref/gui/WorkspacePreferences.java @@ -13,6 +13,7 @@ import org.jabref.gui.theme.Theme; import org.jabref.logic.l10n.Language; +import org.jabref.logic.preferences.AutoPushMode; public class WorkspacePreferences { private final ObjectProperty language; @@ -26,6 +27,8 @@ public class WorkspacePreferences { private final BooleanProperty warnAboutDuplicatesInInspection; private final BooleanProperty confirmDelete; private final ObservableList selectedSlrCatalogs; + private final BooleanProperty autoPushEnabled; + private final ObjectProperty autoPushMode; public WorkspacePreferences(Language language, boolean shouldOverrideDefaultFontSize, @@ -37,7 +40,9 @@ public WorkspacePreferences(Language language, boolean showAdvancedHints, boolean warnAboutDuplicatesInInspection, boolean confirmDelete, - List selectedSlrCatalogs) { + List selectedSlrCatalogs, + boolean autoPushEnabled, + AutoPushMode autoPushMode) { this.language = new SimpleObjectProperty<>(language); this.shouldOverrideDefaultFontSize = new SimpleBooleanProperty(shouldOverrideDefaultFontSize); this.mainFontSize = new SimpleIntegerProperty(mainFontSize); @@ -49,6 +54,8 @@ public WorkspacePreferences(Language language, this.warnAboutDuplicatesInInspection = new SimpleBooleanProperty(warnAboutDuplicatesInInspection); this.confirmDelete = new SimpleBooleanProperty(confirmDelete); this.selectedSlrCatalogs = FXCollections.observableArrayList(selectedSlrCatalogs); + this.autoPushEnabled = new SimpleBooleanProperty(autoPushEnabled); + this.autoPushMode = new SimpleObjectProperty<>(autoPushMode); } public Language getLanguage() { @@ -170,4 +177,28 @@ public ObservableList getSelectedSlrCatalogs() { public void setSelectedSlrCatalogs(List catalogs) { selectedSlrCatalogs.setAll(catalogs); } + + public boolean isAutoPushEnabled() { + return autoPushEnabled.get(); + } + + public void setAutoPushEnabled(boolean enabled) { + this.autoPushEnabled.set(enabled); + } + + public BooleanProperty autoPushEnabledProperty() { + return autoPushEnabled; + } + + public AutoPushMode getAutoPushMode() { + return autoPushMode.get(); + } + + public void setAutoPushMode(AutoPushMode mode) { + this.autoPushMode.set(mode); + } + + public ObjectProperty autoPushModeProperty() { + return autoPushMode; + } } diff --git a/src/main/java/org/jabref/gui/preferences/JabRefGuiPreferences.java b/src/main/java/org/jabref/gui/preferences/JabRefGuiPreferences.java index ee0b2219e7b..e0908eb99ca 100644 --- a/src/main/java/org/jabref/gui/preferences/JabRefGuiPreferences.java +++ b/src/main/java/org/jabref/gui/preferences/JabRefGuiPreferences.java @@ -59,6 +59,7 @@ import org.jabref.logic.layout.TextBasedPreviewLayout; import org.jabref.logic.os.OS; import org.jabref.logic.preferences.AutoCompleteFirstNameMode; +import org.jabref.logic.preferences.AutoPushMode; import org.jabref.logic.preferences.JabRefCliPreferences; import org.jabref.logic.preview.PreviewLayout; import org.jabref.logic.push.CitationCommandString; @@ -170,6 +171,8 @@ public class JabRefGuiPreferences extends JabRefCliPreferences implements GuiPre private static final String OVERRIDE_DEFAULT_FONT_SIZE = "overrideDefaultFontSize"; private static final String SHOW_ADVANCED_HINTS = "showAdvancedHints"; private static final String CONFIRM_DELETE = "confirmDelete"; + private static final String AUTO_PUSH_ENABLED = "autoPushEnabled"; + private static final String AUTO_PUSH_MODE = "autoPushMode"; // endregion private static final String ENTRY_EDITOR_HEIGHT = "entryEditorHeightFX"; @@ -272,6 +275,8 @@ private JabRefGuiPreferences() { defaults.put(THEME_SYNC_OS, Boolean.FALSE); defaults.put(CONFIRM_DELETE, Boolean.TRUE); defaults.put(SHOW_ADVANCED_HINTS, Boolean.TRUE); + defaults.put(AUTO_PUSH_ENABLED, Boolean.FALSE); + defaults.put(AUTO_PUSH_MODE, "manual"); // endregion // region unlinkedFilesDialogPreferences @@ -652,7 +657,9 @@ public WorkspacePreferences getWorkspacePreferences() { getBoolean(SHOW_ADVANCED_HINTS), getBoolean(WARN_ABOUT_DUPLICATES_IN_INSPECTION), getBoolean(CONFIRM_DELETE), - getStringList(SELECTED_SLR_CATALOGS)); + getStringList(SELECTED_SLR_CATALOGS), + getBoolean(AUTO_PUSH_ENABLED), // <-- New parameter + AutoPushMode.fromString(get(AUTO_PUSH_MODE))); EasyBind.listen(workspacePreferences.languageProperty(), (obs, oldValue, newValue) -> { put(LANGUAGE, newValue.getId()); @@ -1236,4 +1243,20 @@ protected Path getDefaultPath() { protected boolean moveToTrashSupported() { return NativeDesktop.get().moveToTrashSupported(); } + + public boolean isAutoPushEnabled() { + return getBoolean(AUTO_PUSH_ENABLED); + } + + public void setAutoPushEnabled(boolean enabled) { + putBoolean(AUTO_PUSH_ENABLED, enabled); + } + + public String getAutoPushMode() { + return get(AUTO_PUSH_MODE); + } + + public void setAutoPushMode(String mode) { + put(AUTO_PUSH_MODE, mode); + } } diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml index b7f6c599498..8061a664588 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml @@ -100,6 +100,10 @@ + + + + diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java index e178b10a6e7..a25271c85c0 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java @@ -3,6 +3,7 @@ import java.util.regex.Pattern; import javafx.application.Platform; +import javafx.collections.FXCollections; import javafx.fxml.FXML; import javafx.geometry.Pos; import javafx.scene.control.Button; @@ -24,6 +25,7 @@ import org.jabref.logic.help.HelpFile; import org.jabref.logic.l10n.Language; import org.jabref.logic.l10n.Localization; +import org.jabref.logic.preferences.AutoPushMode; import org.jabref.model.database.BibDatabaseMode; import org.jabref.model.entry.BibEntryTypesManager; import org.jabref.model.util.FileUpdateMonitor; @@ -51,6 +53,8 @@ public class GeneralTab extends AbstractPreferenceTabView i @FXML private CheckBox alwaysReformatBib; @FXML private CheckBox autosaveLocalLibraries; @FXML private Button autosaveLocalLibrariesHelp; + @FXML private CheckBox autoPushCheckbox; + @FXML private ComboBox autoPushModeComboBox; @FXML private CheckBox createBackup; @FXML private TextField backupDirectory; @FXML private CheckBox remoteServer; @@ -128,6 +132,16 @@ public void initialize() { alwaysReformatBib.selectedProperty().bindBidirectional(viewModel.alwaysReformatBibProperty()); autosaveLocalLibraries.selectedProperty().bindBidirectional(viewModel.autosaveLocalLibrariesProperty()); + + autoPushCheckbox.selectedProperty().bindBidirectional(viewModel.autoPushEnabledProperty()); + + new ViewModelListCellFactory() + .withText(AutoPushMode::toString) + .install(autoPushModeComboBox); + + autoPushModeComboBox.setItems(FXCollections.observableArrayList(AutoPushMode.values())); + autoPushModeComboBox.valueProperty().bindBidirectional(viewModel.autoPushModeProperty()); + ActionFactory actionFactory = new ActionFactory(); actionFactory.configureIconButton(StandardActions.HELP, new HelpAction(HelpFile.AUTOSAVE, dialogService, preferences.getExternalApplicationsPreferences()), autosaveLocalLibrariesHelp); actionFactory.configureIconButton(StandardActions.HELP, new HelpAction(HelpFile.REMOTE, dialogService, preferences.getExternalApplicationsPreferences()), remoteHelp); diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java index 87f1810792a..fd8912e81dc 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java @@ -35,6 +35,7 @@ import org.jabref.logic.l10n.Language; import org.jabref.logic.l10n.Localization; import org.jabref.logic.net.ssl.TrustStoreManager; +import org.jabref.logic.preferences.AutoPushMode; import org.jabref.logic.remote.RemotePreferences; import org.jabref.logic.remote.RemoteUtil; import org.jabref.logic.remote.server.RemoteListenerServerManager; @@ -82,6 +83,8 @@ public class GeneralTabViewModel implements PreferenceTabViewModel { private final BooleanProperty alwaysReformatBibProperty = new SimpleBooleanProperty(); private final BooleanProperty autosaveLocalLibraries = new SimpleBooleanProperty(); + private final BooleanProperty autoPushEnabled = new SimpleBooleanProperty(); + private final ObjectProperty autoPushMode = new SimpleObjectProperty<>(AutoPushMode.MANUALLY); private final BooleanProperty createBackupProperty = new SimpleBooleanProperty(); private final StringProperty backupDirectoryProperty = new SimpleStringProperty(""); @@ -389,6 +392,14 @@ public BooleanProperty autosaveLocalLibrariesProperty() { return autosaveLocalLibraries; } + public BooleanProperty autoPushEnabledProperty() { + return autoPushEnabled; + } + + public ObjectProperty autoPushModeProperty() { + return autoPushMode; + } + public BooleanProperty createBackupProperty() { return this.createBackupProperty; } @@ -428,8 +439,4 @@ private Optional getPortAsInt(String value) { return Optional.empty(); } } - - public BooleanProperty autoPushEnabledProperty() { - return autoPushEnabled; - } } diff --git a/src/main/java/org/jabref/logic/preferences/AutoPushMode.java b/src/main/java/org/jabref/logic/preferences/AutoPushMode.java new file mode 100644 index 00000000000..0640903dbe2 --- /dev/null +++ b/src/main/java/org/jabref/logic/preferences/AutoPushMode.java @@ -0,0 +1,25 @@ +package org.jabref.logic.preferences; + +public enum AutoPushMode { + MANUALLY("Manually"), + AUTOMATICALLY("Automatically"); + + private final String mode; + + AutoPushMode(String mode) { + this.mode = mode; + } + + public String getMode() { + return mode; + } + + public static AutoPushMode fromString(String text) { + for (AutoPushMode mode : AutoPushMode.values()) { + if (mode.mode.equalsIgnoreCase(text)) { + return mode; + } + } + return MANUALLY; // Default mode + } +} From f7c21c4927580fd76dd18b16856ae91194bd6707 Mon Sep 17 00:00:00 2001 From: RapidShotzz Date: Tue, 4 Mar 2025 14:46:38 +0000 Subject: [PATCH 22/72] removed duplicate boolean --- .../org/jabref/gui/preferences/general/GeneralTabViewModel.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java index fd8912e81dc..fe7dd49cd0d 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java @@ -107,8 +107,6 @@ public class GeneralTabViewModel implements PreferenceTabViewModel { private final BibEntryTypesManager entryTypesManager; private final TrustStoreManager trustStoreManager; - private final BooleanProperty autoPushEnabled = new SimpleBooleanProperty(); - public GeneralTabViewModel(DialogService dialogService, GuiPreferences preferences, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager) { this.dialogService = dialogService; this.preferences = preferences; From 980c748d0fd278a61da63e7413a6a968ef7ecff3 Mon Sep 17 00:00:00 2001 From: SihasA Date: Wed, 5 Mar 2025 09:16:10 +0300 Subject: [PATCH 23/72] Cleaned up UI - "Auto push" Combo Box no longer is in all Caps --- .../gui/preferences/general/GeneralTab.fxml | 2 +- .../gui/preferences/general/GeneralTab.java | 16 +++++++++++++++- .../jabref/logic/preferences/AutoPushMode.java | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml index 8061a664588..d4c1be4ac67 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml @@ -101,7 +101,7 @@ - + diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java index a25271c85c0..07ead31e4d1 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java @@ -12,6 +12,7 @@ import javafx.scene.control.Spinner; import javafx.scene.control.TextField; import javafx.scene.control.TextFormatter; +import javafx.util.StringConverter; import javafx.util.converter.IntegerStringConverter; import org.jabref.gui.actions.ActionFactory; @@ -136,10 +137,23 @@ public void initialize() { autoPushCheckbox.selectedProperty().bindBidirectional(viewModel.autoPushEnabledProperty()); new ViewModelListCellFactory() - .withText(AutoPushMode::toString) + .withText(AutoPushMode::getMode) // Use getDisplayName() instead of toString() .install(autoPushModeComboBox); autoPushModeComboBox.setItems(FXCollections.observableArrayList(AutoPushMode.values())); + + autoPushModeComboBox.setConverter(new StringConverter<>() { + @Override + public String toString(AutoPushMode mode) { + return (mode != null) ? mode.getMode() : ""; + } + + @Override + public AutoPushMode fromString(String text) { + return AutoPushMode.fromString(text); + } + }); + autoPushModeComboBox.valueProperty().bindBidirectional(viewModel.autoPushModeProperty()); ActionFactory actionFactory = new ActionFactory(); diff --git a/src/main/java/org/jabref/logic/preferences/AutoPushMode.java b/src/main/java/org/jabref/logic/preferences/AutoPushMode.java index 0640903dbe2..42dd69d6672 100644 --- a/src/main/java/org/jabref/logic/preferences/AutoPushMode.java +++ b/src/main/java/org/jabref/logic/preferences/AutoPushMode.java @@ -2,7 +2,7 @@ public enum AutoPushMode { MANUALLY("Manually"), - AUTOMATICALLY("Automatically"); + ON_SAVE("On Save"); private final String mode; From caf405bbf93dae179875cbf96a169cc1f2322b99 Mon Sep 17 00:00:00 2001 From: "Aryaman Amit Mehta (k23043160)" Date: Thu, 6 Mar 2025 17:25:07 +0000 Subject: [PATCH 24/72] Added "Git" submenu with "Git Pull" and "Git Push" options --- build.gradle | 3 ++ src/main/java/module-info.java | 4 +- .../java/org/jabref/gui/frame/MainMenu.java | 50 +++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index fbafcd7bde5..a30d7ade880 100644 --- a/build.gradle +++ b/build.gradle @@ -137,6 +137,7 @@ repositories { // Required for one.jpro.jproutils:tree-showing maven { url 'https://sandec.jfrog.io/artifactory/repo' } + mavenCentral() } configurations { @@ -160,6 +161,8 @@ dependencies { // Include all jar-files in the 'lib' folder as dependencies implementation fileTree(dir: 'lib', includes: ['*.jar']) + implementation 'de.jensd:fontawesomefx-fontawesome:4.7.0-9.1.2' + def pdfbox = "3.0.4" implementation ("org.apache.pdfbox:pdfbox:$pdfbox") { exclude group: 'commons-logging' diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index ccb2f386829..f9d4ff4cbbe 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -7,9 +7,6 @@ requires java.sql.rowset; // region JavaFX - requires javafx.base; - requires javafx.graphics; - requires javafx.controls; requires javafx.web; requires javafx.fxml; @@ -193,5 +190,6 @@ requires mslinks; requires org.antlr.antlr4.runtime; requires org.libreoffice.uno; + requires de.jensd.fx.glyphs.fontawesome; // endregion } diff --git a/src/main/java/org/jabref/gui/frame/MainMenu.java b/src/main/java/org/jabref/gui/frame/MainMenu.java index 4a90a556172..f7ea4ea2f91 100644 --- a/src/main/java/org/jabref/gui/frame/MainMenu.java +++ b/src/main/java/org/jabref/gui/frame/MainMenu.java @@ -3,6 +3,7 @@ import java.util.function.Supplier; import javafx.event.ActionEvent; +import javafx.scene.control.Alert; import javafx.scene.control.Menu; import javafx.scene.control.MenuBar; import javafx.scene.control.MenuItem; @@ -157,6 +158,10 @@ private void createMenu() { new SeparatorMenuItem(), + createGitUIMenuItem(), + + new SeparatorMenuItem(), + factory.createSubMenu(StandardActions.IMPORT, factory.createMenuItem(StandardActions.IMPORT_INTO_CURRENT_LIBRARY, new ImportCommand(frame, ImportCommand.ImportMethod.TO_EXISTING, preferences, stateManager, fileUpdateMonitor, taskExecutor, dialogService)), factory.createMenuItem(StandardActions.IMPORT_INTO_NEW_LIBRARY, new ImportCommand(frame, ImportCommand.ImportMethod.AS_NEW, preferences, stateManager, fileUpdateMonitor, taskExecutor, dialogService))), @@ -386,4 +391,49 @@ private Menu createSendSubMenu(ActionFactory factory, return sendMenu; } + +// private MenuItem createGitUIMenuItem() { +// MenuItem gitUIItem = new MenuItem("Git"); +// +// // Define what happens when Git UI is clicked +// gitUIItem.setOnAction(event -> { +// Alert alert = new Alert(Alert.AlertType.INFORMATION); +// alert.setTitle("Git"); +// alert.setHeaderText(null); +// alert.setContentText("Git UI will be implemented here! ---TEST"); +// alert.showAndWait(); +// }); +// +// return gitUIItem; +// } + private Menu createGitUIMenuItem() { + Menu gitUIMenu = new Menu("Git"); + + // Create "Git Pull" menu item + MenuItem gitPullItem = new MenuItem("Git Pull"); + gitPullItem.setOnAction(event -> { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Git Pull"); + alert.setHeaderText(null); + alert.setContentText("Git Pull action will be implemented here!"); + alert.showAndWait(); + }); + + // Create "Git Push" menu item + MenuItem gitPushItem = new MenuItem("Git Push"); + gitPushItem.setOnAction(event -> { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Git Push"); + alert.setHeaderText(null); + alert.setContentText("Git Push action will be implemented here!"); + alert.showAndWait(); + }); + + // Add subitems to Git UI Menu + gitUIMenu.getItems().addAll(gitPullItem, gitPushItem); + + return gitUIMenu; + } } + + From 4ed64cdfe0688f316ec128e397c8ce600279c61d Mon Sep 17 00:00:00 2001 From: RapidShotzz Date: Sun, 9 Mar 2025 21:21:05 +0000 Subject: [PATCH 25/72] constructed get git preferences --- .../jabref/logic/preferences/JabRefCliPreferences.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java index ad4327a1d0d..02209640cef 100644 --- a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java @@ -1827,7 +1827,13 @@ public GitPreferences getGitPreferences() { return gitPreferences; } - // TODO: Construct git preferences + boolean autoPushEnabled = getBoolean("gitAutoPushEnabled", false); // Loads stored preference, initially false + + gitPreferences = new GitPreferences(autoPushEnabled); + + EasyBind.listen(gitPreferences.getAutoPushEnabledProperty(), (obs, oldValue, newValue) -> { + putBoolean("gitAutoPushEnabled", newValue); + }); // listener automatically saves changes return gitPreferences; } From 3ff8bc3c232b4bc09ae22b1eabf12eac7ccefa86 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Mon, 10 Mar 2025 00:00:00 +0000 Subject: [PATCH 26/72] Add autoPushMode to GitPreferences --- .../org/jabref/logic/git/GitPreferences.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/git/GitPreferences.java b/src/main/java/org/jabref/logic/git/GitPreferences.java index 0171d5529f9..4103bd55416 100644 --- a/src/main/java/org/jabref/logic/git/GitPreferences.java +++ b/src/main/java/org/jabref/logic/git/GitPreferences.java @@ -1,7 +1,11 @@ package org.jabref.logic.git; import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleObjectProperty; + +import org.jabref.logic.preferences.AutoPushMode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,9 +14,11 @@ public class GitPreferences { private static final Logger LOGGER = LoggerFactory.getLogger(GitPreferences.class); private final BooleanProperty autoPushEnabled; + private final ObjectProperty autoPushMode; - public GitPreferences(boolean autoPushEnabled) { + public GitPreferences(boolean autoPushEnabled, AutoPushMode autoPushMode) { this.autoPushEnabled = new SimpleBooleanProperty(autoPushEnabled); + this.autoPushMode = new SimpleObjectProperty<>(autoPushMode); } public boolean getAutoPushEnabled() { @@ -30,4 +36,12 @@ public void setAutoPushEnabled(boolean enabled) { public GitPreferences withAutoPushEnabled(boolean enabled) { return new GitPreferences(enabled); } + + public AutoPushMode getAutoPushMode() { + return autoPushMode.get(); + } + + public ObjectProperty getAutoPushModeProperty() { + return autoPushMode; + } } From 63d86f11759cdfb9da3d550c01c1544399d231b4 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Mon, 10 Mar 2025 00:37:42 +0000 Subject: [PATCH 27/72] Add git functionality on database save to GitHandler and SaveDatabaseAction --- .../org/jabref/gui/exporter/SaveDatabaseAction.java | 12 ++++++++++++ src/main/java/org/jabref/logic/git/GitHandler.java | 9 +++++++++ 2 files changed, 21 insertions(+) diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index 10487ead6ad..11573138ad8 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -32,8 +32,10 @@ import org.jabref.logic.exporter.BibtexDatabaseWriter; import org.jabref.logic.exporter.SaveException; import org.jabref.logic.exporter.SelfContainedSaveConfiguration; +import org.jabref.logic.git.GitHandler; import org.jabref.logic.l10n.Encodings; import org.jabref.logic.l10n.Localization; +import org.jabref.logic.preferences.AutoPushMode; import org.jabref.logic.shared.DatabaseLocation; import org.jabref.logic.shared.prefs.SharedDatabasePreferences; import org.jabref.logic.util.BackgroundTask; @@ -237,6 +239,16 @@ private boolean save(Path targetPath, SaveDatabaseMode mode) { if (success) { libraryTab.getUndoManager().markUnchanged(); libraryTab.resetChangedProperties(); + // Push if path is a repository + if ( + preferences.getGitPreferences().getAutoPushMode() == AutoPushMode.ON_SAVE && + preferences.getGitPreferences().getAutoPushEnabled() + ) { + GitHandler gitHandler = new GitHandler(targetPath, false); + if (gitHandler.isGitRepository()) { + gitHandler.postSaveDatabaseAction(); + } + } } dialogService.notify(Localization.lang("Library saved")); return success; diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 9b2ebbd6f31..322963b0065 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -214,4 +214,13 @@ public String getCurrentlyCheckedOutBranch() throws IOException { return git.getRepository().getBranch(); } } + + public void postSaveDatabaseAction() { + try { + this.createCommitOnCurrentBranch("Automatic update via JabRef", false); + this.pushCommitsToRemoteRepository(); + } catch (Exception e) { + LOGGER.info("Failed to push"); + } + } } From 837311ffe1ee145838f24389b1fb7603642d0aef Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Mon, 10 Mar 2025 12:51:58 +0000 Subject: [PATCH 28/72] Create GitPullAction for git pull menu item Remove autoPushMode from GitPreferences (re-add later) Modify git pull menu item to a factory construction --- .../jabref/gui/actions/StandardActions.java | 3 + .../java/org/jabref/gui/frame/MainMenu.java | 14 ++--- .../org/jabref/gui/shared/GitPullAction.java | 55 +++++++++++++++++++ .../org/jabref/logic/git/GitPreferences.java | 4 -- .../preferences/JabRefCliPreferences.java | 2 +- 5 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 src/main/java/org/jabref/gui/shared/GitPullAction.java diff --git a/src/main/java/org/jabref/gui/actions/StandardActions.java b/src/main/java/org/jabref/gui/actions/StandardActions.java index 8ef696aa10c..105afb6a662 100644 --- a/src/main/java/org/jabref/gui/actions/StandardActions.java +++ b/src/main/java/org/jabref/gui/actions/StandardActions.java @@ -205,6 +205,9 @@ public enum StandardActions implements Action { GROUP_ENTRIES_ADD(Localization.lang("Add selected entries to this group")), GROUP_ENTRIES_REMOVE(Localization.lang("Remove selected entries from this group")), + GIT_PULL(Localization.lang("Git pull")), + GIT_PUSH(Localization.lang("Git Push")), + CLEAR_EMBEDDINGS_CACHE(Localization.lang("Clear embeddings cache")); private String text; diff --git a/src/main/java/org/jabref/gui/frame/MainMenu.java b/src/main/java/org/jabref/gui/frame/MainMenu.java index f7ea4ea2f91..867cedcf3a0 100644 --- a/src/main/java/org/jabref/gui/frame/MainMenu.java +++ b/src/main/java/org/jabref/gui/frame/MainMenu.java @@ -60,6 +60,7 @@ import org.jabref.gui.push.PushToApplicationCommand; import org.jabref.gui.search.RebuildFulltextSearchIndexAction; import org.jabref.gui.shared.ConnectToSharedDatabaseCommand; +import org.jabref.gui.shared.GitPullAction; import org.jabref.gui.shared.PullChangesFromSharedAction; import org.jabref.gui.sidepane.SidePane; import org.jabref.gui.sidepane.SidePaneType; @@ -158,7 +159,7 @@ private void createMenu() { new SeparatorMenuItem(), - createGitUIMenuItem(), + createGitUIMenuItem(factory), new SeparatorMenuItem(), @@ -406,18 +407,11 @@ private Menu createSendSubMenu(ActionFactory factory, // // return gitUIItem; // } - private Menu createGitUIMenuItem() { + private Menu createGitUIMenuItem(ActionFactory factory) { Menu gitUIMenu = new Menu("Git"); // Create "Git Pull" menu item - MenuItem gitPullItem = new MenuItem("Git Pull"); - gitPullItem.setOnAction(event -> { - Alert alert = new Alert(Alert.AlertType.INFORMATION); - alert.setTitle("Git Pull"); - alert.setHeaderText(null); - alert.setContentText("Git Pull action will be implemented here!"); - alert.showAndWait(); - }); + MenuItem gitPullItem = factory.createMenuItem(StandardActions.GIT_PULL, new GitPullAction(preferences, dialogService, stateManager)); // Create "Git Push" menu item MenuItem gitPushItem = new MenuItem("Git Push"); diff --git a/src/main/java/org/jabref/gui/shared/GitPullAction.java b/src/main/java/org/jabref/gui/shared/GitPullAction.java new file mode 100644 index 00000000000..a5c28697e53 --- /dev/null +++ b/src/main/java/org/jabref/gui/shared/GitPullAction.java @@ -0,0 +1,55 @@ +package org.jabref.gui.shared; + +import java.nio.file.Path; +import java.util.Optional; + +import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.logic.git.GitHandler; +import org.jabref.model.database.BibDatabaseContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GitPullAction extends SimpleCommand { + private static final Logger LOGGER = LoggerFactory.getLogger(GitPullAction.class); + + private final GuiPreferences preferences; + private final DialogService dialogService; + private final StateManager stateManager; + + public GitPullAction( + GuiPreferences preferences, + DialogService dialogService, + StateManager stateManager) { + this.preferences = preferences; + this.dialogService = dialogService; + this.stateManager = stateManager; + } + + @Override + public void execute() { + BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); + if (stateManager.getActiveDatabase().isEmpty()) { + return; + } + + Optional path = databaseContext.getDatabasePath(); + if (path.isEmpty()) { + return; + } + + GitHandler gitHandler = new GitHandler(path.get(), false); + if (gitHandler.isGitRepository()) { + try { + gitHandler.pullOnCurrentBranch(); + } catch (Exception e) { + dialogService.showErrorDialogAndWait(e); + } + } else { + LOGGER.info("Not a git repository"); + } + } +} diff --git a/src/main/java/org/jabref/logic/git/GitPreferences.java b/src/main/java/org/jabref/logic/git/GitPreferences.java index 4103bd55416..316e36f8c9e 100644 --- a/src/main/java/org/jabref/logic/git/GitPreferences.java +++ b/src/main/java/org/jabref/logic/git/GitPreferences.java @@ -33,10 +33,6 @@ public void setAutoPushEnabled(boolean enabled) { autoPushEnabled.set(enabled); } - public GitPreferences withAutoPushEnabled(boolean enabled) { - return new GitPreferences(enabled); - } - public AutoPushMode getAutoPushMode() { return autoPushMode.get(); } diff --git a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java index d2fb652dff6..dc7e8442b36 100644 --- a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java @@ -1831,7 +1831,7 @@ public GitPreferences getGitPreferences() { boolean autoPushEnabled = getBoolean("gitAutoPushEnabled", false); // Loads stored preference, initially false - gitPreferences = new GitPreferences(autoPushEnabled); + gitPreferences = new GitPreferences(autoPushEnabled, AutoPushMode.MANUALLY); EasyBind.listen(gitPreferences.getAutoPushEnabledProperty(), (obs, oldValue, newValue) -> { putBoolean("gitAutoPushEnabled", newValue); From 53286d49cc7ba9d2e735f883649826c8ebe59a81 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Wed, 12 Mar 2025 10:07:22 +0000 Subject: [PATCH 29/72] Fix: Rename GitPullAction and correct GitHandler repository path in constructor calls --- .../jabref/gui/exporter/SaveDatabaseAction.java | 2 +- src/main/java/org/jabref/gui/frame/MainMenu.java | 16 ++++++++-------- .../{GitPullAction.java => GitPushAction.java} | 11 ++++++----- .../java/org/jabref/logic/git/GitHandler.java | 1 + 4 files changed, 16 insertions(+), 14 deletions(-) rename src/main/java/org/jabref/gui/shared/{GitPullAction.java => GitPushAction.java} (83%) diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index 11573138ad8..28355c055fb 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -244,7 +244,7 @@ private boolean save(Path targetPath, SaveDatabaseMode mode) { preferences.getGitPreferences().getAutoPushMode() == AutoPushMode.ON_SAVE && preferences.getGitPreferences().getAutoPushEnabled() ) { - GitHandler gitHandler = new GitHandler(targetPath, false); + GitHandler gitHandler = new GitHandler(targetPath.getParent(), false); if (gitHandler.isGitRepository()) { gitHandler.postSaveDatabaseAction(); } diff --git a/src/main/java/org/jabref/gui/frame/MainMenu.java b/src/main/java/org/jabref/gui/frame/MainMenu.java index 867cedcf3a0..5edaafc4210 100644 --- a/src/main/java/org/jabref/gui/frame/MainMenu.java +++ b/src/main/java/org/jabref/gui/frame/MainMenu.java @@ -60,7 +60,7 @@ import org.jabref.gui.push.PushToApplicationCommand; import org.jabref.gui.search.RebuildFulltextSearchIndexAction; import org.jabref.gui.shared.ConnectToSharedDatabaseCommand; -import org.jabref.gui.shared.GitPullAction; +import org.jabref.gui.shared.GitPushAction; import org.jabref.gui.shared.PullChangesFromSharedAction; import org.jabref.gui.sidepane.SidePane; import org.jabref.gui.sidepane.SidePaneType; @@ -411,18 +411,18 @@ private Menu createGitUIMenuItem(ActionFactory factory) { Menu gitUIMenu = new Menu("Git"); // Create "Git Pull" menu item - MenuItem gitPullItem = factory.createMenuItem(StandardActions.GIT_PULL, new GitPullAction(preferences, dialogService, stateManager)); - - // Create "Git Push" menu item - MenuItem gitPushItem = new MenuItem("Git Push"); - gitPushItem.setOnAction(event -> { + MenuItem gitPullItem = new MenuItem("Git Pull"); + gitPullItem.setOnAction(event -> { Alert alert = new Alert(Alert.AlertType.INFORMATION); - alert.setTitle("Git Push"); + alert.setTitle("Git Pull"); alert.setHeaderText(null); - alert.setContentText("Git Push action will be implemented here!"); + alert.setContentText("Git Pull action will be implemented here!"); alert.showAndWait(); }); + // Create "Git Push" menu item + MenuItem gitPushItem = factory.createMenuItem(StandardActions.GIT_PUSH, new GitPushAction(preferences, dialogService, stateManager)); + // Add subitems to Git UI Menu gitUIMenu.getItems().addAll(gitPullItem, gitPushItem); diff --git a/src/main/java/org/jabref/gui/shared/GitPullAction.java b/src/main/java/org/jabref/gui/shared/GitPushAction.java similarity index 83% rename from src/main/java/org/jabref/gui/shared/GitPullAction.java rename to src/main/java/org/jabref/gui/shared/GitPushAction.java index a5c28697e53..8566f5063ab 100644 --- a/src/main/java/org/jabref/gui/shared/GitPullAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPushAction.java @@ -13,14 +13,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class GitPullAction extends SimpleCommand { - private static final Logger LOGGER = LoggerFactory.getLogger(GitPullAction.class); +public class GitPushAction extends SimpleCommand { + private static final Logger LOGGER = LoggerFactory.getLogger(GitPushAction.class); private final GuiPreferences preferences; private final DialogService dialogService; private final StateManager stateManager; - public GitPullAction( + public GitPushAction( GuiPreferences preferences, DialogService dialogService, StateManager stateManager) { @@ -41,14 +41,15 @@ public void execute() { return; } - GitHandler gitHandler = new GitHandler(path.get(), false); + GitHandler gitHandler = new GitHandler(path.get().getParent(), false); if (gitHandler.isGitRepository()) { try { - gitHandler.pullOnCurrentBranch(); + gitHandler.pushCommitsToRemoteRepository(); } catch (Exception e) { dialogService.showErrorDialogAndWait(e); } } else { + LOGGER.info(String.valueOf(path.get())); LOGGER.info("Not a git repository"); } } diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 322963b0065..f29a082a902 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -193,6 +193,7 @@ public void pushCommitsToRemoteRepository() throws IOException { .call(); } catch (GitAPIException e) { LOGGER.info("Failed to push"); + LOGGER.info(e.toString()); } } } From cd6ff23c0f3687ffecf84c7cb4e2045f8e3e2371 Mon Sep 17 00:00:00 2001 From: RapidShotzz Date: Wed, 12 Mar 2025 10:09:24 +0000 Subject: [PATCH 30/72] modified getGitPreferences to account for getAutoPushModeProperty() method in gitpreferences --- .../preferences/general/GeneralTabViewModel.java | 3 ++- .../logic/preferences/JabRefCliPreferences.java | 14 +++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java index fe7dd49cd0d..ab9c1014bbe 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java @@ -32,6 +32,7 @@ import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.FilePreferences; import org.jabref.logic.LibraryPreferences; +import org.jabref.logic.git.GitPreferences; import org.jabref.logic.l10n.Language; import org.jabref.logic.l10n.Localization; import org.jabref.logic.net.ssl.TrustStoreManager; @@ -107,7 +108,7 @@ public class GeneralTabViewModel implements PreferenceTabViewModel { private final BibEntryTypesManager entryTypesManager; private final TrustStoreManager trustStoreManager; - public GeneralTabViewModel(DialogService dialogService, GuiPreferences preferences, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager) { + public GeneralTabViewModel(DialogService dialogService, GuiPreferences preferences, GitPreferences gitPreferences, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager) { this.dialogService = dialogService; this.preferences = preferences; this.workspacePreferences = preferences.getWorkspacePreferences(); diff --git a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java index dc7e8442b36..cd9ca7fb56e 100644 --- a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java @@ -121,6 +121,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.apache.commons.compress.harmony.archive.internal.nls.Messages.getString; + /** * The {@code JabRefPreferences} class provides the preferences and their defaults using the JDK {@code java.util.prefs} * class. @@ -1830,16 +1832,26 @@ public GitPreferences getGitPreferences() { } boolean autoPushEnabled = getBoolean("gitAutoPushEnabled", false); // Loads stored preference, initially false + String storedMode = getString("gitAutoPushMode", AutoPushMode.MANUALLY.name()); + AutoPushMode autoPushMode = AutoPushMode.valueOf(storedMode); - gitPreferences = new GitPreferences(autoPushEnabled, AutoPushMode.MANUALLY); + gitPreferences = new GitPreferences(autoPushEnabled, autoPushMode); EasyBind.listen(gitPreferences.getAutoPushEnabledProperty(), (obs, oldValue, newValue) -> { putBoolean("gitAutoPushEnabled", newValue); }); // listener automatically saves changes + EasyBind.listen(gitPreferences.getAutoPushModeProperty(), (obs, oldValue, newValue) -> { + putString("gitAutoPushMode", newValue.name()); + }); + return gitPreferences; } + private void putString(String key, String value) { + prefs.put(key, value); + } + private FileHistory getFileHistory() { return FileHistory.of(getStringList(RECENT_DATABASES).stream() .map(Path::of) From f2fae4b072cd653cf5ef3fe6eb41834d5311bd6c Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Wed, 12 Mar 2025 10:26:37 +0000 Subject: [PATCH 31/72] Remove redundant parameter from GeneralTabViewModel --- .../jabref/gui/preferences/general/GeneralTabViewModel.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java index ab9c1014bbe..fe7dd49cd0d 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java @@ -32,7 +32,6 @@ import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.FilePreferences; import org.jabref.logic.LibraryPreferences; -import org.jabref.logic.git.GitPreferences; import org.jabref.logic.l10n.Language; import org.jabref.logic.l10n.Localization; import org.jabref.logic.net.ssl.TrustStoreManager; @@ -108,7 +107,7 @@ public class GeneralTabViewModel implements PreferenceTabViewModel { private final BibEntryTypesManager entryTypesManager; private final TrustStoreManager trustStoreManager; - public GeneralTabViewModel(DialogService dialogService, GuiPreferences preferences, GitPreferences gitPreferences, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager) { + public GeneralTabViewModel(DialogService dialogService, GuiPreferences preferences, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager) { this.dialogService = dialogService; this.preferences = preferences; this.workspacePreferences = preferences.getWorkspacePreferences(); From 7b0e930faef56914a1110113ed82bb8aa641da89 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Wed, 12 Mar 2025 10:45:27 +0000 Subject: [PATCH 32/72] Clean 'Failed to push' logger message --- src/main/java/org/jabref/logic/git/GitHandler.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index f29a082a902..73269c7ae29 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -192,8 +192,7 @@ public void pushCommitsToRemoteRepository() throws IOException { .setCredentialsProvider(credentialsProvider) .call(); } catch (GitAPIException e) { - LOGGER.info("Failed to push"); - LOGGER.info(e.toString()); + LOGGER.info("Failed to push: ".concat(e.toString())); } } } From c28b84fc04ec1705f6f755b94ff0f2d63c21083f Mon Sep 17 00:00:00 2001 From: RapidShotzz Date: Wed, 12 Mar 2025 13:32:58 +0000 Subject: [PATCH 33/72] removed comments --- .../org/jabref/logic/preferences/JabRefCliPreferences.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java index cd9ca7fb56e..70b622cd8b6 100644 --- a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java @@ -1831,7 +1831,7 @@ public GitPreferences getGitPreferences() { return gitPreferences; } - boolean autoPushEnabled = getBoolean("gitAutoPushEnabled", false); // Loads stored preference, initially false + boolean autoPushEnabled = getBoolean("gitAutoPushEnabled", false); String storedMode = getString("gitAutoPushMode", AutoPushMode.MANUALLY.name()); AutoPushMode autoPushMode = AutoPushMode.valueOf(storedMode); @@ -1839,7 +1839,7 @@ public GitPreferences getGitPreferences() { EasyBind.listen(gitPreferences.getAutoPushEnabledProperty(), (obs, oldValue, newValue) -> { putBoolean("gitAutoPushEnabled", newValue); - }); // listener automatically saves changes + }); EasyBind.listen(gitPreferences.getAutoPushModeProperty(), (obs, oldValue, newValue) -> { putString("gitAutoPushMode", newValue.name()); From 0e0ddbaa4631228c7497bc3db0768ba2680aa1fd Mon Sep 17 00:00:00 2001 From: SihasA Date: Thu, 13 Mar 2025 11:57:51 +0000 Subject: [PATCH 34/72] Fixed error regarding preferences not saving correctly --- .../org/jabref/gui/WorkspacePreferences.java | 33 +------------------ .../gui/preferences/JabRefGuiPreferences.java | 25 +------------- .../gui/preferences/general/GeneralTab.java | 19 ----------- .../general/GeneralTabViewModel.java | 27 +++++++++------ .../preferences/JabRefCliPreferences.java | 15 ++++----- 5 files changed, 26 insertions(+), 93 deletions(-) diff --git a/src/main/java/org/jabref/gui/WorkspacePreferences.java b/src/main/java/org/jabref/gui/WorkspacePreferences.java index 68b55083db0..2948be7582e 100644 --- a/src/main/java/org/jabref/gui/WorkspacePreferences.java +++ b/src/main/java/org/jabref/gui/WorkspacePreferences.java @@ -13,7 +13,6 @@ import org.jabref.gui.theme.Theme; import org.jabref.logic.l10n.Language; -import org.jabref.logic.preferences.AutoPushMode; public class WorkspacePreferences { private final ObjectProperty language; @@ -27,8 +26,6 @@ public class WorkspacePreferences { private final BooleanProperty warnAboutDuplicatesInInspection; private final BooleanProperty confirmDelete; private final ObservableList selectedSlrCatalogs; - private final BooleanProperty autoPushEnabled; - private final ObjectProperty autoPushMode; public WorkspacePreferences(Language language, boolean shouldOverrideDefaultFontSize, @@ -40,9 +37,7 @@ public WorkspacePreferences(Language language, boolean showAdvancedHints, boolean warnAboutDuplicatesInInspection, boolean confirmDelete, - List selectedSlrCatalogs, - boolean autoPushEnabled, - AutoPushMode autoPushMode) { + List selectedSlrCatalogs) { this.language = new SimpleObjectProperty<>(language); this.shouldOverrideDefaultFontSize = new SimpleBooleanProperty(shouldOverrideDefaultFontSize); this.mainFontSize = new SimpleIntegerProperty(mainFontSize); @@ -54,8 +49,6 @@ public WorkspacePreferences(Language language, this.warnAboutDuplicatesInInspection = new SimpleBooleanProperty(warnAboutDuplicatesInInspection); this.confirmDelete = new SimpleBooleanProperty(confirmDelete); this.selectedSlrCatalogs = FXCollections.observableArrayList(selectedSlrCatalogs); - this.autoPushEnabled = new SimpleBooleanProperty(autoPushEnabled); - this.autoPushMode = new SimpleObjectProperty<>(autoPushMode); } public Language getLanguage() { @@ -177,28 +170,4 @@ public ObservableList getSelectedSlrCatalogs() { public void setSelectedSlrCatalogs(List catalogs) { selectedSlrCatalogs.setAll(catalogs); } - - public boolean isAutoPushEnabled() { - return autoPushEnabled.get(); - } - - public void setAutoPushEnabled(boolean enabled) { - this.autoPushEnabled.set(enabled); - } - - public BooleanProperty autoPushEnabledProperty() { - return autoPushEnabled; - } - - public AutoPushMode getAutoPushMode() { - return autoPushMode.get(); - } - - public void setAutoPushMode(AutoPushMode mode) { - this.autoPushMode.set(mode); - } - - public ObjectProperty autoPushModeProperty() { - return autoPushMode; - } } diff --git a/src/main/java/org/jabref/gui/preferences/JabRefGuiPreferences.java b/src/main/java/org/jabref/gui/preferences/JabRefGuiPreferences.java index e0908eb99ca..ee0b2219e7b 100644 --- a/src/main/java/org/jabref/gui/preferences/JabRefGuiPreferences.java +++ b/src/main/java/org/jabref/gui/preferences/JabRefGuiPreferences.java @@ -59,7 +59,6 @@ import org.jabref.logic.layout.TextBasedPreviewLayout; import org.jabref.logic.os.OS; import org.jabref.logic.preferences.AutoCompleteFirstNameMode; -import org.jabref.logic.preferences.AutoPushMode; import org.jabref.logic.preferences.JabRefCliPreferences; import org.jabref.logic.preview.PreviewLayout; import org.jabref.logic.push.CitationCommandString; @@ -171,8 +170,6 @@ public class JabRefGuiPreferences extends JabRefCliPreferences implements GuiPre private static final String OVERRIDE_DEFAULT_FONT_SIZE = "overrideDefaultFontSize"; private static final String SHOW_ADVANCED_HINTS = "showAdvancedHints"; private static final String CONFIRM_DELETE = "confirmDelete"; - private static final String AUTO_PUSH_ENABLED = "autoPushEnabled"; - private static final String AUTO_PUSH_MODE = "autoPushMode"; // endregion private static final String ENTRY_EDITOR_HEIGHT = "entryEditorHeightFX"; @@ -275,8 +272,6 @@ private JabRefGuiPreferences() { defaults.put(THEME_SYNC_OS, Boolean.FALSE); defaults.put(CONFIRM_DELETE, Boolean.TRUE); defaults.put(SHOW_ADVANCED_HINTS, Boolean.TRUE); - defaults.put(AUTO_PUSH_ENABLED, Boolean.FALSE); - defaults.put(AUTO_PUSH_MODE, "manual"); // endregion // region unlinkedFilesDialogPreferences @@ -657,9 +652,7 @@ public WorkspacePreferences getWorkspacePreferences() { getBoolean(SHOW_ADVANCED_HINTS), getBoolean(WARN_ABOUT_DUPLICATES_IN_INSPECTION), getBoolean(CONFIRM_DELETE), - getStringList(SELECTED_SLR_CATALOGS), - getBoolean(AUTO_PUSH_ENABLED), // <-- New parameter - AutoPushMode.fromString(get(AUTO_PUSH_MODE))); + getStringList(SELECTED_SLR_CATALOGS)); EasyBind.listen(workspacePreferences.languageProperty(), (obs, oldValue, newValue) -> { put(LANGUAGE, newValue.getId()); @@ -1243,20 +1236,4 @@ protected Path getDefaultPath() { protected boolean moveToTrashSupported() { return NativeDesktop.get().moveToTrashSupported(); } - - public boolean isAutoPushEnabled() { - return getBoolean(AUTO_PUSH_ENABLED); - } - - public void setAutoPushEnabled(boolean enabled) { - putBoolean(AUTO_PUSH_ENABLED, enabled); - } - - public String getAutoPushMode() { - return get(AUTO_PUSH_MODE); - } - - public void setAutoPushMode(String mode) { - put(AUTO_PUSH_MODE, mode); - } } diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java index 07ead31e4d1..6f6339e6d29 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java @@ -12,7 +12,6 @@ import javafx.scene.control.Spinner; import javafx.scene.control.TextField; import javafx.scene.control.TextFormatter; -import javafx.util.StringConverter; import javafx.util.converter.IntegerStringConverter; import org.jabref.gui.actions.ActionFactory; @@ -135,25 +134,7 @@ public void initialize() { autosaveLocalLibraries.selectedProperty().bindBidirectional(viewModel.autosaveLocalLibrariesProperty()); autoPushCheckbox.selectedProperty().bindBidirectional(viewModel.autoPushEnabledProperty()); - - new ViewModelListCellFactory() - .withText(AutoPushMode::getMode) // Use getDisplayName() instead of toString() - .install(autoPushModeComboBox); - autoPushModeComboBox.setItems(FXCollections.observableArrayList(AutoPushMode.values())); - - autoPushModeComboBox.setConverter(new StringConverter<>() { - @Override - public String toString(AutoPushMode mode) { - return (mode != null) ? mode.getMode() : ""; - } - - @Override - public AutoPushMode fromString(String text) { - return AutoPushMode.fromString(text); - } - }); - autoPushModeComboBox.valueProperty().bindBidirectional(viewModel.autoPushModeProperty()); ActionFactory actionFactory = new ActionFactory(); diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java index fe7dd49cd0d..39eba7fb456 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java @@ -32,6 +32,7 @@ import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.FilePreferences; import org.jabref.logic.LibraryPreferences; +import org.jabref.logic.git.GitPreferences; import org.jabref.logic.l10n.Language; import org.jabref.logic.l10n.Localization; import org.jabref.logic.net.ssl.TrustStoreManager; @@ -83,8 +84,6 @@ public class GeneralTabViewModel implements PreferenceTabViewModel { private final BooleanProperty alwaysReformatBibProperty = new SimpleBooleanProperty(); private final BooleanProperty autosaveLocalLibraries = new SimpleBooleanProperty(); - private final BooleanProperty autoPushEnabled = new SimpleBooleanProperty(); - private final ObjectProperty autoPushMode = new SimpleObjectProperty<>(AutoPushMode.MANUALLY); private final BooleanProperty createBackupProperty = new SimpleBooleanProperty(); private final StringProperty backupDirectoryProperty = new SimpleStringProperty(""); @@ -95,6 +94,7 @@ public class GeneralTabViewModel implements PreferenceTabViewModel { private final LibraryPreferences libraryPreferences; private final FilePreferences filePreferences; private final RemotePreferences remotePreferences; + private final GitPreferences gitPreferences; private final Validator fontSizeValidator; private final Validator customPathToThemeValidator; @@ -113,6 +113,7 @@ public GeneralTabViewModel(DialogService dialogService, GuiPreferences preferenc this.workspacePreferences = preferences.getWorkspacePreferences(); this.libraryPreferences = preferences.getLibraryPreferences(); this.filePreferences = preferences.getFilePreferences(); + this.gitPreferences = preferences.getGitPreferences(); this.remotePreferences = preferences.getRemotePreferences(); this.fileUpdateMonitor = fileUpdateMonitor; this.entryTypesManager = entryTypesManager; @@ -194,6 +195,9 @@ public void setValues() { alwaysReformatBibProperty.setValue(libraryPreferences.shouldAlwaysReformatOnSave()); autosaveLocalLibraries.setValue(libraryPreferences.shouldAutoSave()); + autoPushEnabledProperty().setValue(gitPreferences.getAutoPushEnabled()); + autoPushModeProperty().setValue(gitPreferences.getAutoPushMode()); + createBackupProperty.setValue(filePreferences.shouldCreateBackup()); backupDirectoryProperty.setValue(filePreferences.getBackupDirectory().toString()); @@ -234,6 +238,9 @@ public void storeSettings() { libraryPreferences.setAlwaysReformatOnSave(alwaysReformatBibProperty.getValue()); libraryPreferences.setAutoSave(autosaveLocalLibraries.getValue()); + gitPreferences.setAutoPushEnabled(autoPushEnabledProperty().get()); + gitPreferences.getAutoPushModeProperty().set(autoPushModeProperty().get()); + filePreferences.createBackupProperty().setValue(createBackupProperty.getValue()); filePreferences.backupDirectoryProperty().setValue(Path.of(backupDirectoryProperty.getValue())); @@ -390,14 +397,6 @@ public BooleanProperty autosaveLocalLibrariesProperty() { return autosaveLocalLibraries; } - public BooleanProperty autoPushEnabledProperty() { - return autoPushEnabled; - } - - public ObjectProperty autoPushModeProperty() { - return autoPushMode; - } - public BooleanProperty createBackupProperty() { return this.createBackupProperty; } @@ -437,4 +436,12 @@ private Optional getPortAsInt(String value) { return Optional.empty(); } } + + public BooleanProperty autoPushEnabledProperty() { + return gitPreferences.getAutoPushEnabledProperty(); + } + + public ObjectProperty autoPushModeProperty() { + return gitPreferences.getAutoPushModeProperty(); + } } diff --git a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java index cd9ca7fb56e..8f30f3e8dfe 100644 --- a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java @@ -1831,19 +1831,18 @@ public GitPreferences getGitPreferences() { return gitPreferences; } - boolean autoPushEnabled = getBoolean("gitAutoPushEnabled", false); // Loads stored preference, initially false + boolean autoPushEnabled = getBoolean("gitAutoPushEnabled", false); String storedMode = getString("gitAutoPushMode", AutoPushMode.MANUALLY.name()); - AutoPushMode autoPushMode = AutoPushMode.valueOf(storedMode); + AutoPushMode autoPushMode = AutoPushMode.fromString(storedMode); gitPreferences = new GitPreferences(autoPushEnabled, autoPushMode); - EasyBind.listen(gitPreferences.getAutoPushEnabledProperty(), (obs, oldValue, newValue) -> { - putBoolean("gitAutoPushEnabled", newValue); - }); // listener automatically saves changes + // Automatically save changes when properties are updated + EasyBind.listen(gitPreferences.getAutoPushEnabledProperty(), + (obs, oldValue, newValue) -> putBoolean("gitAutoPushEnabled", newValue)); - EasyBind.listen(gitPreferences.getAutoPushModeProperty(), (obs, oldValue, newValue) -> { - putString("gitAutoPushMode", newValue.name()); - }); + EasyBind.listen(gitPreferences.getAutoPushModeProperty(), + (obs, oldValue, newValue) -> putString("gitAutoPushMode", newValue.name())); return gitPreferences; } From e71d3ad392412d47c9cc9f806366de7ee54a2786 Mon Sep 17 00:00:00 2001 From: SihasA Date: Thu, 13 Mar 2025 12:07:51 +0000 Subject: [PATCH 35/72] Fixed error regarding preferences not saving correctly --- .../logic/preferences/JabRefCliPreferences.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java index cd9ca7fb56e..ea1c89cb9f7 100644 --- a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java @@ -1833,17 +1833,16 @@ public GitPreferences getGitPreferences() { boolean autoPushEnabled = getBoolean("gitAutoPushEnabled", false); // Loads stored preference, initially false String storedMode = getString("gitAutoPushMode", AutoPushMode.MANUALLY.name()); - AutoPushMode autoPushMode = AutoPushMode.valueOf(storedMode); + AutoPushMode autoPushMode = AutoPushMode.fromString(storedMode); // Safely parse gitPreferences = new GitPreferences(autoPushEnabled, autoPushMode); - EasyBind.listen(gitPreferences.getAutoPushEnabledProperty(), (obs, oldValue, newValue) -> { - putBoolean("gitAutoPushEnabled", newValue); - }); // listener automatically saves changes + // Automatically save changes when properties are updated + EasyBind.listen(gitPreferences.getAutoPushEnabledProperty(), + (obs, oldValue, newValue) -> putBoolean("gitAutoPushEnabled", newValue)); - EasyBind.listen(gitPreferences.getAutoPushModeProperty(), (obs, oldValue, newValue) -> { - putString("gitAutoPushMode", newValue.name()); - }); + EasyBind.listen(gitPreferences.getAutoPushModeProperty(), + (obs, oldValue, newValue) -> putString("gitAutoPushMode", newValue.name())); return gitPreferences; } From 6a7e013531f1f45d2cace6de7eb400e576d1da8c Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Thu, 13 Mar 2025 13:22:33 +0000 Subject: [PATCH 36/72] Update GitHandler with staging methods and add GitPullAction --- .../jabref/gui/actions/StandardActions.java | 1 + .../java/org/jabref/gui/frame/MainMenu.java | 42 ++----------- .../actions/CheckForVersionControlAction.java | 7 +-- .../org/jabref/gui/shared/GitPullAction.java | 56 ++++++++++++++++++ .../org/jabref/gui/shared/GitPushAction.java | 2 + .../java/org/jabref/logic/git/GitHandler.java | 59 ++++++++++++++++++- 6 files changed, 122 insertions(+), 45 deletions(-) create mode 100644 src/main/java/org/jabref/gui/shared/GitPullAction.java diff --git a/src/main/java/org/jabref/gui/actions/StandardActions.java b/src/main/java/org/jabref/gui/actions/StandardActions.java index 105afb6a662..7698df521c5 100644 --- a/src/main/java/org/jabref/gui/actions/StandardActions.java +++ b/src/main/java/org/jabref/gui/actions/StandardActions.java @@ -205,6 +205,7 @@ public enum StandardActions implements Action { GROUP_ENTRIES_ADD(Localization.lang("Add selected entries to this group")), GROUP_ENTRIES_REMOVE(Localization.lang("Remove selected entries from this group")), + GIT(Localization.lang("Git")), GIT_PULL(Localization.lang("Git pull")), GIT_PUSH(Localization.lang("Git Push")), diff --git a/src/main/java/org/jabref/gui/frame/MainMenu.java b/src/main/java/org/jabref/gui/frame/MainMenu.java index 5edaafc4210..5a26ecc9b4b 100644 --- a/src/main/java/org/jabref/gui/frame/MainMenu.java +++ b/src/main/java/org/jabref/gui/frame/MainMenu.java @@ -3,7 +3,6 @@ import java.util.function.Supplier; import javafx.event.ActionEvent; -import javafx.scene.control.Alert; import javafx.scene.control.Menu; import javafx.scene.control.MenuBar; import javafx.scene.control.MenuItem; @@ -60,6 +59,7 @@ import org.jabref.gui.push.PushToApplicationCommand; import org.jabref.gui.search.RebuildFulltextSearchIndexAction; import org.jabref.gui.shared.ConnectToSharedDatabaseCommand; +import org.jabref.gui.shared.GitPullAction; import org.jabref.gui.shared.GitPushAction; import org.jabref.gui.shared.PullChangesFromSharedAction; import org.jabref.gui.sidepane.SidePane; @@ -159,7 +159,9 @@ private void createMenu() { new SeparatorMenuItem(), - createGitUIMenuItem(factory), + factory.createSubMenu(StandardActions.GIT, + factory.createMenuItem(StandardActions.GIT_PUSH, new GitPushAction(preferences, dialogService, stateManager)), + factory.createMenuItem(StandardActions.GIT_PULL, new GitPullAction(preferences, dialogService, stateManager))), new SeparatorMenuItem(), @@ -392,42 +394,6 @@ private Menu createSendSubMenu(ActionFactory factory, return sendMenu; } - -// private MenuItem createGitUIMenuItem() { -// MenuItem gitUIItem = new MenuItem("Git"); -// -// // Define what happens when Git UI is clicked -// gitUIItem.setOnAction(event -> { -// Alert alert = new Alert(Alert.AlertType.INFORMATION); -// alert.setTitle("Git"); -// alert.setHeaderText(null); -// alert.setContentText("Git UI will be implemented here! ---TEST"); -// alert.showAndWait(); -// }); -// -// return gitUIItem; -// } - private Menu createGitUIMenuItem(ActionFactory factory) { - Menu gitUIMenu = new Menu("Git"); - - // Create "Git Pull" menu item - MenuItem gitPullItem = new MenuItem("Git Pull"); - gitPullItem.setOnAction(event -> { - Alert alert = new Alert(Alert.AlertType.INFORMATION); - alert.setTitle("Git Pull"); - alert.setHeaderText(null); - alert.setContentText("Git Pull action will be implemented here!"); - alert.showAndWait(); - }); - - // Create "Git Push" menu item - MenuItem gitPushItem = factory.createMenuItem(StandardActions.GIT_PUSH, new GitPushAction(preferences, dialogService, stateManager)); - - // Add subitems to Git UI Menu - gitUIMenu.getItems().addAll(gitPullItem, gitPushItem); - - return gitUIMenu; - } } diff --git a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java index 2db725f1516..bd25313b2a9 100644 --- a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java @@ -26,15 +26,14 @@ public boolean isActionNecessary(ParserResult parserResult, DialogService dialog Optional path = parserResult.getDatabaseContext().getDatabasePath(); if (path.isEmpty()) { return false; - } else { - this.gitHandler = new GitHandler(path.get()); - return gitHandler.isGitRepository(); } + this.gitHandler = new GitHandler(path.get()); + return gitHandler.isGitRepository(); } @Override public void performAction(ParserResult parserResult, DialogService dialogService, CliPreferences preferencesService) { - parserResult.getDatabaseContext().setVersioned(true); // tags as versioned + parserResult.getDatabaseContext().setVersioned(true); try { this.gitHandler.pullOnCurrentBranch(); diff --git a/src/main/java/org/jabref/gui/shared/GitPullAction.java b/src/main/java/org/jabref/gui/shared/GitPullAction.java new file mode 100644 index 00000000000..4c4537f4ff9 --- /dev/null +++ b/src/main/java/org/jabref/gui/shared/GitPullAction.java @@ -0,0 +1,56 @@ +package org.jabref.gui.shared; + +import java.nio.file.Path; +import java.util.Optional; + +import org.jabref.gui.DialogService; +import org.jabref.gui.StateManager; +import org.jabref.gui.actions.SimpleCommand; +import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.logic.git.GitHandler; +import org.jabref.model.database.BibDatabaseContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GitPullAction extends SimpleCommand { + private static final Logger LOGGER = LoggerFactory.getLogger(GitPullAction.class); + + private final GuiPreferences preferences; + private final DialogService dialogService; + private final StateManager stateManager; + + public GitPullAction( + GuiPreferences preferences, + DialogService dialogService, + StateManager stateManager) { + this.preferences = preferences; + this.dialogService = dialogService; + this.stateManager = stateManager; + } + + @Override + public void execute() { + BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); + if (stateManager.getActiveDatabase().isEmpty()) { + return; + } + + Optional path = databaseContext.getDatabasePath(); + if (path.isEmpty()) { + return; + } + + GitHandler gitHandler = new GitHandler(path.get().getParent(), false); + if (gitHandler.isGitRepository()) { + try { + gitHandler.pullOnCurrentBranch(); + } catch (Exception e) { + dialogService.showErrorDialogAndWait(e); + } + } else { + LOGGER.info(String.valueOf(path.get())); + LOGGER.info("Not a git repository"); + } + } +} diff --git a/src/main/java/org/jabref/gui/shared/GitPushAction.java b/src/main/java/org/jabref/gui/shared/GitPushAction.java index 8566f5063ab..458f04ba9c9 100644 --- a/src/main/java/org/jabref/gui/shared/GitPushAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPushAction.java @@ -44,6 +44,8 @@ public void execute() { GitHandler gitHandler = new GitHandler(path.get().getParent(), false); if (gitHandler.isGitRepository()) { try { + gitHandler.stageAllFiles(); + gitHandler.createCommitOnCurrentBranch("Automatic update via JabRef)", false); gitHandler.pushCommitsToRemoteRepository(); } catch (Exception e) { dialogService.showErrorDialogAndWait(e); diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 73269c7ae29..ee7aa25cc29 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -5,7 +5,10 @@ import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import java.util.Set; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.RmCommand; @@ -24,7 +27,7 @@ */ public class GitHandler { static final Logger LOGGER = LoggerFactory.getLogger(GitHandler.class); - protected final Path repositoryPath; + final Path repositoryPath; final File repositoryPathAsFile; String gitUsername = Optional.ofNullable(System.getenv("GIT_EMAIL")).orElse(""); String gitPassword = Optional.ofNullable(System.getenv("GIT_PW")).orElse(""); @@ -204,7 +207,7 @@ public void pullOnCurrentBranch() throws IOException { .setCredentialsProvider(credentialsProvider) .call(); } catch (GitAPIException e) { - LOGGER.info("Failed to push"); + LOGGER.info("Failed to pull".concat(e.toString())); } } } @@ -215,12 +218,62 @@ public String getCurrentlyCheckedOutBranch() throws IOException { } } + /** + * Returns a list of unstaged (modified or untracked) files in the repository. + * + * @return List of unstaged file paths + * @throws GitAPIException If an error occurs while fetching the status + * @throws IOException If an error occurs while accessing the repository + */ + public List getUnstagedFiles() throws GitAPIException, IOException { + try (Git git = Git.open(repositoryPathAsFile)) { + Status status = git.status().call(); + Set modifiedFiles = status.getModified(); + Set untrackedFiles = status.getUntracked(); + + List unstagedFiles = new ArrayList<>(); + unstagedFiles.addAll(modifiedFiles); + unstagedFiles.addAll(untrackedFiles); + + return unstagedFiles; + } + } + + /** + * Stages a specific file. + * + * @param filePath The relative path of the file to stage + * @throws GitAPIException If an error occurs while staging the file + * @throws IOException If an error occurs while accessing the repository + */ + public void stageFile(String filePath) throws GitAPIException, IOException { + try (Git git = Git.open(repositoryPathAsFile)) { + git.add().addFilepattern(filePath).call(); + } catch (GitAPIException | IOException e) { + LOGGER.info("Failed to stage file: ".concat(e.toString())); + } + } + + /** + * Stages all unstaged files in the repository. + * + * @throws GitAPIException If an error occurs while staging files + * @throws IOException If an error occurs while accessing the repository + */ + public void stageAllFiles() throws GitAPIException, IOException { + try (Git git = Git.open(repositoryPathAsFile)) { + git.add().addFilepattern(".").call(); + } catch (GitAPIException | IOException e) { + LOGGER.info("Failed to stage all files: ".concat(e.toString())); + } + } + public void postSaveDatabaseAction() { try { this.createCommitOnCurrentBranch("Automatic update via JabRef", false); this.pushCommitsToRemoteRepository(); } catch (Exception e) { - LOGGER.info("Failed to push"); + LOGGER.info("Failed to push".concat(e.toString())); } } } From e3885b7f928594cfb590753756dd736a94f7d228 Mon Sep 17 00:00:00 2001 From: SihasA Date: Thu, 13 Mar 2025 13:24:59 +0000 Subject: [PATCH 37/72] Cleaned up UI Preferences --- .../logic/preferences/AutoPushMode.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/jabref/logic/preferences/AutoPushMode.java b/src/main/java/org/jabref/logic/preferences/AutoPushMode.java index 42dd69d6672..6f1ad904f2d 100644 --- a/src/main/java/org/jabref/logic/preferences/AutoPushMode.java +++ b/src/main/java/org/jabref/logic/preferences/AutoPushMode.java @@ -4,22 +4,27 @@ public enum AutoPushMode { MANUALLY("Manually"), ON_SAVE("On Save"); - private final String mode; + private final String displayName; - AutoPushMode(String mode) { - this.mode = mode; + AutoPushMode(String displayName) { + this.displayName = displayName; } - public String getMode() { - return mode; + public String getDisplayName() { + return displayName; + } + + @Override + public String toString() { + return displayName; } public static AutoPushMode fromString(String text) { for (AutoPushMode mode : AutoPushMode.values()) { - if (mode.mode.equalsIgnoreCase(text)) { + if (mode.displayName.equalsIgnoreCase(text)) { return mode; } } - return MANUALLY; // Default mode + return MANUALLY; } } From b1458b2ee6f977d1b0288902e76f8b0ad716f842 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Thu, 13 Mar 2025 13:29:10 +0000 Subject: [PATCH 38/72] Capitalization --- src/main/java/org/jabref/gui/actions/StandardActions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/gui/actions/StandardActions.java b/src/main/java/org/jabref/gui/actions/StandardActions.java index 7698df521c5..8a2d67cc2f2 100644 --- a/src/main/java/org/jabref/gui/actions/StandardActions.java +++ b/src/main/java/org/jabref/gui/actions/StandardActions.java @@ -206,7 +206,7 @@ public enum StandardActions implements Action { GROUP_ENTRIES_REMOVE(Localization.lang("Remove selected entries from this group")), GIT(Localization.lang("Git")), - GIT_PULL(Localization.lang("Git pull")), + GIT_PULL(Localization.lang("Git Pull")), GIT_PUSH(Localization.lang("Git Push")), CLEAR_EMBEDDINGS_CACHE(Localization.lang("Clear embeddings cache")); From 98ec8a89bd3625565b3b6f3fec808656d024be60 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Thu, 13 Mar 2025 14:38:46 +0000 Subject: [PATCH 39/72] Remove redundant methods from GitHandler --- .../org/jabref/gui/shared/GitPushAction.java | 1 - .../java/org/jabref/logic/git/GitHandler.java | 53 ------------------- 2 files changed, 54 deletions(-) diff --git a/src/main/java/org/jabref/gui/shared/GitPushAction.java b/src/main/java/org/jabref/gui/shared/GitPushAction.java index 458f04ba9c9..df178079ee2 100644 --- a/src/main/java/org/jabref/gui/shared/GitPushAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPushAction.java @@ -44,7 +44,6 @@ public void execute() { GitHandler gitHandler = new GitHandler(path.get().getParent(), false); if (gitHandler.isGitRepository()) { try { - gitHandler.stageAllFiles(); gitHandler.createCommitOnCurrentBranch("Automatic update via JabRef)", false); gitHandler.pushCommitsToRemoteRepository(); } catch (Exception e) { diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index ee7aa25cc29..b2c86171138 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -5,10 +5,7 @@ import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; import java.util.Optional; -import java.util.Set; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.RmCommand; @@ -218,56 +215,6 @@ public String getCurrentlyCheckedOutBranch() throws IOException { } } - /** - * Returns a list of unstaged (modified or untracked) files in the repository. - * - * @return List of unstaged file paths - * @throws GitAPIException If an error occurs while fetching the status - * @throws IOException If an error occurs while accessing the repository - */ - public List getUnstagedFiles() throws GitAPIException, IOException { - try (Git git = Git.open(repositoryPathAsFile)) { - Status status = git.status().call(); - Set modifiedFiles = status.getModified(); - Set untrackedFiles = status.getUntracked(); - - List unstagedFiles = new ArrayList<>(); - unstagedFiles.addAll(modifiedFiles); - unstagedFiles.addAll(untrackedFiles); - - return unstagedFiles; - } - } - - /** - * Stages a specific file. - * - * @param filePath The relative path of the file to stage - * @throws GitAPIException If an error occurs while staging the file - * @throws IOException If an error occurs while accessing the repository - */ - public void stageFile(String filePath) throws GitAPIException, IOException { - try (Git git = Git.open(repositoryPathAsFile)) { - git.add().addFilepattern(filePath).call(); - } catch (GitAPIException | IOException e) { - LOGGER.info("Failed to stage file: ".concat(e.toString())); - } - } - - /** - * Stages all unstaged files in the repository. - * - * @throws GitAPIException If an error occurs while staging files - * @throws IOException If an error occurs while accessing the repository - */ - public void stageAllFiles() throws GitAPIException, IOException { - try (Git git = Git.open(repositoryPathAsFile)) { - git.add().addFilepattern(".").call(); - } catch (GitAPIException | IOException e) { - LOGGER.info("Failed to stage all files: ".concat(e.toString())); - } - } - public void postSaveDatabaseAction() { try { this.createCommitOnCurrentBranch("Automatic update via JabRef", false); From d9162bc613115c328800a264fe221126d735ebbd Mon Sep 17 00:00:00 2001 From: RapidShotzz Date: Thu, 13 Mar 2025 19:33:53 +0000 Subject: [PATCH 40/72] added tests for git preferences to ensure that auto push functionality works and that boolean properties are updated. --- .../logic/preferences/GitPreferencesTest.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/test/java/org/jabref/logic/preferences/GitPreferencesTest.java diff --git a/src/test/java/org/jabref/logic/preferences/GitPreferencesTest.java b/src/test/java/org/jabref/logic/preferences/GitPreferencesTest.java new file mode 100644 index 00000000000..f2d18cd5b4f --- /dev/null +++ b/src/test/java/org/jabref/logic/preferences/GitPreferencesTest.java @@ -0,0 +1,60 @@ +package org.jabref.logic.preferences; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ObjectProperty; + +import org.jabref.logic.git.GitPreferences; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class GitPreferencesTest { + + private GitPreferences gitPreferences; + + @BeforeEach + void setUp() { + gitPreferences = new GitPreferences(true, AutoPushMode.ON_SAVE); + } + + @Test + void testConstructorInitialisesValues() { + assertThat(gitPreferences.getAutoPushEnabled()).isTrue(); + assertThat(gitPreferences.getAutoPushMode()).isEqualTo(AutoPushMode.ON_SAVE); + } + + @Test + void testGettersReturnCorrectValues() { + assertThat(gitPreferences.getAutoPushEnabled()).isTrue(); + assertThat(gitPreferences.getAutoPushMode()).isEqualTo(AutoPushMode.ON_SAVE); + } + + @Test + void testSetAutoPushEnabledUpdatesValue() { + gitPreferences.setAutoPushEnabled(false); + assertThat(gitPreferences.getAutoPushEnabled()).isFalse(); + } + + @Test + void testJavaFXBooleanPropertyUpdates() { + BooleanProperty autoPushProperty = gitPreferences.getAutoPushEnabledProperty(); + autoPushProperty.set(false); + assertThat(gitPreferences.getAutoPushEnabled()).isFalse(); + } + + @Test + void testAutoPushModeUpdates() { + ObjectProperty autoPushModeProperty = gitPreferences.getAutoPushModeProperty(); + autoPushModeProperty.set(AutoPushMode.MANUALLY); + assertThat(gitPreferences.getAutoPushMode()).isEqualTo(AutoPushMode.MANUALLY); + } + + @Test + void testAutoPushModeFromString() { + assertThat(AutoPushMode.fromString("On Save")).isEqualTo(AutoPushMode.ON_SAVE); + assertThat(AutoPushMode.fromString("Manually")).isEqualTo(AutoPushMode.MANUALLY); + assertThat(AutoPushMode.fromString("invalid")).isEqualTo(AutoPushMode.MANUALLY); + } +} From e800a28e5baed7800547fcc5fcdee00ca8d66038 Mon Sep 17 00:00:00 2001 From: RapidShotzz Date: Thu, 13 Mar 2025 19:41:49 +0000 Subject: [PATCH 41/72] moved location of gitpreferences test --- .../jabref/logic/{preferences => git}/GitPreferencesTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename src/test/java/org/jabref/logic/{preferences => git}/GitPreferencesTest.java (95%) diff --git a/src/test/java/org/jabref/logic/preferences/GitPreferencesTest.java b/src/test/java/org/jabref/logic/git/GitPreferencesTest.java similarity index 95% rename from src/test/java/org/jabref/logic/preferences/GitPreferencesTest.java rename to src/test/java/org/jabref/logic/git/GitPreferencesTest.java index f2d18cd5b4f..38a8a6b78a3 100644 --- a/src/test/java/org/jabref/logic/preferences/GitPreferencesTest.java +++ b/src/test/java/org/jabref/logic/git/GitPreferencesTest.java @@ -1,9 +1,9 @@ -package org.jabref.logic.preferences; +package org.jabref.logic.git; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; -import org.jabref.logic.git.GitPreferences; +import org.jabref.logic.preferences.AutoPushMode; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; From 0c51c0ea86c427f7fce24850d81ca443e039f517 Mon Sep 17 00:00:00 2001 From: "Aryaman Amit Mehta (k23043160)" Date: Mon, 17 Mar 2025 01:43:17 +0000 Subject: [PATCH 42/72] Add unit tests for AutoPushMode - covering getDisplayName(), toString() and fromString() --- src/main/java/module-info.java | 1 + .../logic/preferences/AutoPushModeTest.java | 46 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/main/java/org/jabref/logic/preferences/AutoPushModeTest.java diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index f9d4ff4cbbe..e36ac66cafb 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -191,5 +191,6 @@ requires org.antlr.antlr4.runtime; requires org.libreoffice.uno; requires de.jensd.fx.glyphs.fontawesome; + requires org.junit.jupiter.api; // endregion } diff --git a/src/main/java/org/jabref/logic/preferences/AutoPushModeTest.java b/src/main/java/org/jabref/logic/preferences/AutoPushModeTest.java new file mode 100644 index 00000000000..881a87cc3f8 --- /dev/null +++ b/src/main/java/org/jabref/logic/preferences/AutoPushModeTest.java @@ -0,0 +1,46 @@ +package org.jabref.logic.preferences; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class AutoPushModeTest { + + @Test + void allEnumValuesExist() { + assertNotNull(AutoPushMode.MANUALLY); + assertNotNull(AutoPushMode.ON_SAVE); + } + + @Test + void getDisplayNameReturnsCorrectValue() { + assertEquals("Manually", AutoPushMode.MANUALLY.getDisplayName()); + assertEquals("On Save", AutoPushMode.ON_SAVE.getDisplayName()); + } + + @Test + void toStringReturnsDisplayName() { + assertEquals("Manually", AutoPushMode.MANUALLY.toString()); + assertEquals("On Save", AutoPushMode.ON_SAVE.toString()); + } + + @Test + void fromStringReturnsCorrectEnum() { + assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString("Manually")); + assertEquals(AutoPushMode.ON_SAVE, AutoPushMode.fromString("On Save")); + } + + @Test + void fromStringIsCaseInsensitive() { + assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString("manually")); + assertEquals(AutoPushMode.ON_SAVE, AutoPushMode.fromString("on save")); + } + + @Test + void fromStringInvalidReturnsManually() { + assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString("invalid")); + assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString("")); + assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString(null)); + } +} From 5e0015c6cc860f1b0d49306d93885df8fe389be3 Mon Sep 17 00:00:00 2001 From: SihasA Date: Mon, 17 Mar 2025 12:04:43 +0000 Subject: [PATCH 43/72] Added Git Username and Passkey fields to preferences --- src/main/java/module-info.java | 1 - .../gui/preferences/general/GeneralTab.fxml | 10 ++++ .../gui/preferences/general/GeneralTab.java | 5 ++ .../general/GeneralTabViewModel.java | 14 +++++- .../java/org/jabref/logic/git/GitHandler.java | 6 ++- .../org/jabref/logic/git/GitPreferences.java | 36 ++++++++++++++- .../logic/preferences/AutoPushModeTest.java | 46 ------------------- .../preferences/JabRefCliPreferences.java | 28 +++++++---- 8 files changed, 87 insertions(+), 59 deletions(-) delete mode 100644 src/main/java/org/jabref/logic/preferences/AutoPushModeTest.java diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index e36ac66cafb..f9d4ff4cbbe 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -191,6 +191,5 @@ requires org.antlr.antlr4.runtime; requires org.libreoffice.uno; requires de.jensd.fx.glyphs.fontawesome; - requires org.junit.jupiter.api; // endregion } diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml index d4c1be4ac67..73d78e83b2d 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml @@ -100,6 +100,16 @@ + + + + + + diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java index 6f6339e6d29..f25d93aff5a 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java @@ -53,6 +53,8 @@ public class GeneralTab extends AbstractPreferenceTabView i @FXML private CheckBox alwaysReformatBib; @FXML private CheckBox autosaveLocalLibraries; @FXML private Button autosaveLocalLibrariesHelp; + @FXML private TextField gitHubUsernameField; + @FXML private TextField gitHubPasskeyField; @FXML private CheckBox autoPushCheckbox; @FXML private ComboBox autoPushModeComboBox; @FXML private CheckBox createBackup; @@ -133,6 +135,9 @@ public void initialize() { alwaysReformatBib.selectedProperty().bindBidirectional(viewModel.alwaysReformatBibProperty()); autosaveLocalLibraries.selectedProperty().bindBidirectional(viewModel.autosaveLocalLibrariesProperty()); + gitHubUsernameField.textProperty().bindBidirectional(viewModel.gitHubUsernameProperty()); + gitHubPasskeyField.textProperty().bindBidirectional(viewModel.gitHubPasskeyProperty()); + autoPushCheckbox.selectedProperty().bindBidirectional(viewModel.autoPushEnabledProperty()); autoPushModeComboBox.setItems(FXCollections.observableArrayList(AutoPushMode.values())); autoPushModeComboBox.valueProperty().bindBidirectional(viewModel.autoPushModeProperty()); diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java index 39eba7fb456..d925c19b699 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java @@ -197,6 +197,8 @@ public void setValues() { autoPushEnabledProperty().setValue(gitPreferences.getAutoPushEnabled()); autoPushModeProperty().setValue(gitPreferences.getAutoPushMode()); + gitHubUsernameProperty().setValue(gitPreferences.getGitHubUsername()); + gitHubPasskeyProperty().setValue(gitPreferences.getGitHubPasskey()); createBackupProperty.setValue(filePreferences.shouldCreateBackup()); backupDirectoryProperty.setValue(filePreferences.getBackupDirectory().toString()); @@ -239,7 +241,9 @@ public void storeSettings() { libraryPreferences.setAutoSave(autosaveLocalLibraries.getValue()); gitPreferences.setAutoPushEnabled(autoPushEnabledProperty().get()); - gitPreferences.getAutoPushModeProperty().set(autoPushModeProperty().get()); + gitPreferences.setAutoPushMode(autoPushModeProperty().get()); + gitPreferences.setGitHubUsername(gitHubUsernameProperty().get()); + gitPreferences.setGitHubPasskey(gitHubPasskeyProperty().get()); filePreferences.createBackupProperty().setValue(createBackupProperty.getValue()); filePreferences.backupDirectoryProperty().setValue(Path.of(backupDirectoryProperty.getValue())); @@ -444,4 +448,12 @@ public BooleanProperty autoPushEnabledProperty() { public ObjectProperty autoPushModeProperty() { return gitPreferences.getAutoPushModeProperty(); } + + public StringProperty gitHubUsernameProperty() { + return gitPreferences.gitHubUsernameProperty(); + } + + public StringProperty gitHubPasskeyProperty() { + return gitPreferences.gitHubPasskeyProperty(); + } } diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index b2c86171138..77f2ec3873c 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -26,8 +26,10 @@ public class GitHandler { static final Logger LOGGER = LoggerFactory.getLogger(GitHandler.class); final Path repositoryPath; final File repositoryPathAsFile; - String gitUsername = Optional.ofNullable(System.getenv("GIT_EMAIL")).orElse(""); - String gitPassword = Optional.ofNullable(System.getenv("GIT_PW")).orElse(""); +// String gitUsername = Optional.ofNullable(System.getenv("GIT_EMAIL")).orElse(""); +// String gitPassword = Optional.ofNullable(System.getenv("GIT_PW")).orElse(""); + String gitUsername = "SihasA"; + String gitPassword = "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"; final CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider(gitUsername, gitPassword); /** diff --git a/src/main/java/org/jabref/logic/git/GitPreferences.java b/src/main/java/org/jabref/logic/git/GitPreferences.java index 316e36f8c9e..cd51907c8b2 100644 --- a/src/main/java/org/jabref/logic/git/GitPreferences.java +++ b/src/main/java/org/jabref/logic/git/GitPreferences.java @@ -4,6 +4,8 @@ import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; import org.jabref.logic.preferences.AutoPushMode; @@ -15,10 +17,14 @@ public class GitPreferences { private final BooleanProperty autoPushEnabled; private final ObjectProperty autoPushMode; + private final StringProperty gitHubUsername; + private final StringProperty gitHubPasskey; - public GitPreferences(boolean autoPushEnabled, AutoPushMode autoPushMode) { + public GitPreferences(boolean autoPushEnabled, AutoPushMode autoPushMode, String gitHubUsername, String gitHubPasskey) { this.autoPushEnabled = new SimpleBooleanProperty(autoPushEnabled); this.autoPushMode = new SimpleObjectProperty<>(autoPushMode); + this.gitHubUsername = new SimpleStringProperty(gitHubUsername); + this.gitHubPasskey = new SimpleStringProperty(gitHubPasskey); } public boolean getAutoPushEnabled() { @@ -40,4 +46,32 @@ public AutoPushMode getAutoPushMode() { public ObjectProperty getAutoPushModeProperty() { return autoPushMode; } + + public void setAutoPushMode(AutoPushMode mode) { + autoPushMode.set(mode); + } + + public String getGitHubUsername() { + return gitHubUsername.get(); + } + + public void setGitHubUsername(String username) { + gitHubUsername.set(username); + } + + public StringProperty gitHubUsernameProperty() { + return gitHubUsername; + } + + public String getGitHubPasskey() { + return gitHubPasskey.get(); + } + + public void setGitHubPasskey(String passkey) { + gitHubPasskey.set(passkey); + } + + public StringProperty gitHubPasskeyProperty() { + return gitHubPasskey; + } } diff --git a/src/main/java/org/jabref/logic/preferences/AutoPushModeTest.java b/src/main/java/org/jabref/logic/preferences/AutoPushModeTest.java deleted file mode 100644 index 881a87cc3f8..00000000000 --- a/src/main/java/org/jabref/logic/preferences/AutoPushModeTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.jabref.logic.preferences; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -public class AutoPushModeTest { - - @Test - void allEnumValuesExist() { - assertNotNull(AutoPushMode.MANUALLY); - assertNotNull(AutoPushMode.ON_SAVE); - } - - @Test - void getDisplayNameReturnsCorrectValue() { - assertEquals("Manually", AutoPushMode.MANUALLY.getDisplayName()); - assertEquals("On Save", AutoPushMode.ON_SAVE.getDisplayName()); - } - - @Test - void toStringReturnsDisplayName() { - assertEquals("Manually", AutoPushMode.MANUALLY.toString()); - assertEquals("On Save", AutoPushMode.ON_SAVE.toString()); - } - - @Test - void fromStringReturnsCorrectEnum() { - assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString("Manually")); - assertEquals(AutoPushMode.ON_SAVE, AutoPushMode.fromString("On Save")); - } - - @Test - void fromStringIsCaseInsensitive() { - assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString("manually")); - assertEquals(AutoPushMode.ON_SAVE, AutoPushMode.fromString("on save")); - } - - @Test - void fromStringInvalidReturnsManually() { - assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString("invalid")); - assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString("")); - assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString(null)); - } -} diff --git a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java index ea1c89cb9f7..bedee7a13ed 100644 --- a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java @@ -1831,18 +1831,30 @@ public GitPreferences getGitPreferences() { return gitPreferences; } - boolean autoPushEnabled = getBoolean("gitAutoPushEnabled", false); // Loads stored preference, initially false + boolean autoPushEnabled = getBoolean("gitAutoPushEnabled", false); String storedMode = getString("gitAutoPushMode", AutoPushMode.MANUALLY.name()); - AutoPushMode autoPushMode = AutoPushMode.fromString(storedMode); // Safely parse + AutoPushMode autoPushMode = AutoPushMode.fromString(storedMode); - gitPreferences = new GitPreferences(autoPushEnabled, autoPushMode); + String gitHubUsername = getString("gitHubUsername", ""); + String gitHubPasskey = getString("gitHubPasskey", ""); - // Automatically save changes when properties are updated - EasyBind.listen(gitPreferences.getAutoPushEnabledProperty(), - (obs, oldValue, newValue) -> putBoolean("gitAutoPushEnabled", newValue)); + gitPreferences = new GitPreferences(autoPushEnabled, autoPushMode, gitHubUsername, gitHubPasskey); - EasyBind.listen(gitPreferences.getAutoPushModeProperty(), - (obs, oldValue, newValue) -> putString("gitAutoPushMode", newValue.name())); + EasyBind.listen(gitPreferences.getAutoPushEnabledProperty(), (obs, oldValue, newValue) -> + putBoolean("gitAutoPushEnabled", newValue) + ); + + EasyBind.listen(gitPreferences.getAutoPushModeProperty(), (obs, oldValue, newValue) -> + putString("gitAutoPushMode", newValue.name()) + ); + + EasyBind.listen(gitPreferences.gitHubUsernameProperty(), (obs, oldValue, newValue) -> + putString("gitHubUsername", newValue) + ); + + EasyBind.listen(gitPreferences.gitHubPasskeyProperty(), (obs, oldValue, newValue) -> + putString("gitHubPasskey", newValue) + ); return gitPreferences; } From d5b72bbbe22a1d3654b45f2f9a48a33f55083548 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Mon, 17 Mar 2025 12:01:47 +0000 Subject: [PATCH 44/72] Add git credentials logic --- .../java/org/jabref/logic/git/GitHandler.java | 21 +++++++-- .../org/jabref/logic/git/GitPreferences.java | 43 ++++++++++++++++++- .../preferences/JabRefCliPreferences.java | 13 +++++- 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index b2c86171138..6f7e3567658 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -7,6 +7,8 @@ import java.nio.file.Path; import java.util.Optional; +import org.jabref.logic.preferences.CliPreferences; + import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.RmCommand; import org.eclipse.jgit.api.Status; @@ -24,11 +26,13 @@ */ public class GitHandler { static final Logger LOGGER = LoggerFactory.getLogger(GitHandler.class); + CliPreferences preferences; + GitPreferences gitPreferences; final Path repositoryPath; final File repositoryPathAsFile; - String gitUsername = Optional.ofNullable(System.getenv("GIT_EMAIL")).orElse(""); - String gitPassword = Optional.ofNullable(System.getenv("GIT_PW")).orElse(""); - final CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider(gitUsername, gitPassword); + String gitUsername = Optional.ofNullable(System.getenv("GIT_USERNAME")).orElse(""); + String gitPassword = Optional.ofNullable(System.getenv("GIT_PASSWORD")).orElse(""); + CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider(gitUsername, gitPassword); /** * Initialize the handler for the given repository @@ -46,6 +50,8 @@ public GitHandler(Path repositoryPath) { * @param createRepo If true, initializes a repository if the file path does not contain a repository */ public GitHandler(Path repositoryPath, boolean createRepo) { + this.gitPreferences = preferences.getGitPreferences(); + this.repositoryPath = repositoryPath; this.repositoryPathAsFile = this.repositoryPath.toFile(); if (!isGitRepository()) { @@ -186,6 +192,7 @@ public void mergeBranches(String targetBranch, String sourceBranch, MergeStrateg * If pushing to remote fails, it fails silently. */ public void pushCommitsToRemoteRepository() throws IOException { + updateCredentials(); try (Git git = Git.open(this.repositoryPathAsFile)) { try { git.push() @@ -198,6 +205,7 @@ public void pushCommitsToRemoteRepository() throws IOException { } public void pullOnCurrentBranch() throws IOException { + updateCredentials(); try (Git git = Git.open(this.repositoryPathAsFile)) { try { git.pull() @@ -223,4 +231,11 @@ public void postSaveDatabaseAction() { LOGGER.info("Failed to push".concat(e.toString())); } } + + public void updateCredentials() { + this.credentialsProvider = new UsernamePasswordCredentialsProvider( + this.gitPreferences.getUsername(), + this.gitPreferences.getPassword() + ); + } } diff --git a/src/main/java/org/jabref/logic/git/GitPreferences.java b/src/main/java/org/jabref/logic/git/GitPreferences.java index 316e36f8c9e..72df191d05c 100644 --- a/src/main/java/org/jabref/logic/git/GitPreferences.java +++ b/src/main/java/org/jabref/logic/git/GitPreferences.java @@ -4,6 +4,8 @@ import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; import org.jabref.logic.preferences.AutoPushMode; @@ -13,14 +15,53 @@ public class GitPreferences { private static final Logger LOGGER = LoggerFactory.getLogger(GitPreferences.class); + private StringProperty username; + private StringProperty password; private final BooleanProperty autoPushEnabled; private final ObjectProperty autoPushMode; - public GitPreferences(boolean autoPushEnabled, AutoPushMode autoPushMode) { + public GitPreferences(String username, + String password, + boolean autoPushEnabled, + AutoPushMode autoPushMode) { + this.username = new SimpleStringProperty(username); + this.password = new SimpleStringProperty(password); this.autoPushEnabled = new SimpleBooleanProperty(autoPushEnabled); this.autoPushMode = new SimpleObjectProperty<>(autoPushMode); } + public StringProperty getUsernameProperty() { + return this.username; + } + + public String getUsername() { + return this.username.get(); + } + + public StringProperty getPasswordProperty() { + return this.password; + } + + public String getPassword() { + return this.password.get(); + } + + public void setPassword(StringProperty password) { + this.password = password; + } + + public void setPassword(String password) { + this.password = new SimpleStringProperty(password); + } + + public void setUsername(StringProperty username) { + this.username = username; + } + + public void setUsername(String username) { + this.username = new SimpleStringProperty(username); + } + public boolean getAutoPushEnabled() { return autoPushEnabled.get(); } diff --git a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java index ea1c89cb9f7..be5baf0ab87 100644 --- a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java @@ -1835,15 +1835,24 @@ public GitPreferences getGitPreferences() { String storedMode = getString("gitAutoPushMode", AutoPushMode.MANUALLY.name()); AutoPushMode autoPushMode = AutoPushMode.fromString(storedMode); // Safely parse - gitPreferences = new GitPreferences(autoPushEnabled, autoPushMode); + gitPreferences = new GitPreferences( + "", + "", + autoPushEnabled, + autoPushMode); - // Automatically save changes when properties are updated EasyBind.listen(gitPreferences.getAutoPushEnabledProperty(), (obs, oldValue, newValue) -> putBoolean("gitAutoPushEnabled", newValue)); EasyBind.listen(gitPreferences.getAutoPushModeProperty(), (obs, oldValue, newValue) -> putString("gitAutoPushMode", newValue.name())); + EasyBind.listen(gitPreferences.getUsernameProperty(), + (obs, oldValue, newValue) -> putString("username", newValue)); + + EasyBind.listen(gitPreferences.getPasswordProperty(), + (obs, oldValue, newValue) -> putString("password", newValue)); + return gitPreferences; } From bed8cc7aaecef4d3979dc7b115c9adac4b7d0e69 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Mon, 17 Mar 2025 12:30:32 +0000 Subject: [PATCH 45/72] Fix preferences in GitHandler --- src/main/java/org/jabref/gui/shared/GitPullAction.java | 1 + src/main/java/org/jabref/gui/shared/GitPushAction.java | 1 + src/main/java/org/jabref/logic/git/GitHandler.java | 9 ++++----- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/jabref/gui/shared/GitPullAction.java b/src/main/java/org/jabref/gui/shared/GitPullAction.java index 4c4537f4ff9..a2eaf9f3dc5 100644 --- a/src/main/java/org/jabref/gui/shared/GitPullAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPullAction.java @@ -44,6 +44,7 @@ public void execute() { GitHandler gitHandler = new GitHandler(path.get().getParent(), false); if (gitHandler.isGitRepository()) { try { + gitHandler.updateCredentials(preferences); gitHandler.pullOnCurrentBranch(); } catch (Exception e) { dialogService.showErrorDialogAndWait(e); diff --git a/src/main/java/org/jabref/gui/shared/GitPushAction.java b/src/main/java/org/jabref/gui/shared/GitPushAction.java index df178079ee2..476984f2e43 100644 --- a/src/main/java/org/jabref/gui/shared/GitPushAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPushAction.java @@ -45,6 +45,7 @@ public void execute() { if (gitHandler.isGitRepository()) { try { gitHandler.createCommitOnCurrentBranch("Automatic update via JabRef)", false); + gitHandler.updateCredentials(preferences); gitHandler.pushCommitsToRemoteRepository(); } catch (Exception e) { dialogService.showErrorDialogAndWait(e); diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 6f7e3567658..22c3419b65f 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -7,6 +7,7 @@ import java.nio.file.Path; import java.util.Optional; +import org.jabref.gui.preferences.GuiPreferences; import org.jabref.logic.preferences.CliPreferences; import org.eclipse.jgit.api.Git; @@ -192,7 +193,6 @@ public void mergeBranches(String targetBranch, String sourceBranch, MergeStrateg * If pushing to remote fails, it fails silently. */ public void pushCommitsToRemoteRepository() throws IOException { - updateCredentials(); try (Git git = Git.open(this.repositoryPathAsFile)) { try { git.push() @@ -205,7 +205,6 @@ public void pushCommitsToRemoteRepository() throws IOException { } public void pullOnCurrentBranch() throws IOException { - updateCredentials(); try (Git git = Git.open(this.repositoryPathAsFile)) { try { git.pull() @@ -232,10 +231,10 @@ public void postSaveDatabaseAction() { } } - public void updateCredentials() { + public void updateCredentials(GuiPreferences preferences) { this.credentialsProvider = new UsernamePasswordCredentialsProvider( - this.gitPreferences.getUsername(), - this.gitPreferences.getPassword() + preferences.getGitPreferences().getUsername(), + preferences.getGitPreferences().getPassword() ); } } From 4b71771c1fce80f30449084de696d18e812d752d Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Mon, 17 Mar 2025 12:56:19 +0000 Subject: [PATCH 46/72] demo --- src/main/java/module-info.java | 1 - .../java/org/jabref/logic/git/GitHandler.java | 5 -- .../logic/preferences/AutoPushModeTest.java | 46 ------------------- 3 files changed, 52 deletions(-) delete mode 100644 src/main/java/org/jabref/logic/preferences/AutoPushModeTest.java diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index e36ac66cafb..f9d4ff4cbbe 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -191,6 +191,5 @@ requires org.antlr.antlr4.runtime; requires org.libreoffice.uno; requires de.jensd.fx.glyphs.fontawesome; - requires org.junit.jupiter.api; // endregion } diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 22c3419b65f..20f0f930b98 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -8,7 +8,6 @@ import java.util.Optional; import org.jabref.gui.preferences.GuiPreferences; -import org.jabref.logic.preferences.CliPreferences; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.RmCommand; @@ -27,8 +26,6 @@ */ public class GitHandler { static final Logger LOGGER = LoggerFactory.getLogger(GitHandler.class); - CliPreferences preferences; - GitPreferences gitPreferences; final Path repositoryPath; final File repositoryPathAsFile; String gitUsername = Optional.ofNullable(System.getenv("GIT_USERNAME")).orElse(""); @@ -51,8 +48,6 @@ public GitHandler(Path repositoryPath) { * @param createRepo If true, initializes a repository if the file path does not contain a repository */ public GitHandler(Path repositoryPath, boolean createRepo) { - this.gitPreferences = preferences.getGitPreferences(); - this.repositoryPath = repositoryPath; this.repositoryPathAsFile = this.repositoryPath.toFile(); if (!isGitRepository()) { diff --git a/src/main/java/org/jabref/logic/preferences/AutoPushModeTest.java b/src/main/java/org/jabref/logic/preferences/AutoPushModeTest.java deleted file mode 100644 index 881a87cc3f8..00000000000 --- a/src/main/java/org/jabref/logic/preferences/AutoPushModeTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.jabref.logic.preferences; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -public class AutoPushModeTest { - - @Test - void allEnumValuesExist() { - assertNotNull(AutoPushMode.MANUALLY); - assertNotNull(AutoPushMode.ON_SAVE); - } - - @Test - void getDisplayNameReturnsCorrectValue() { - assertEquals("Manually", AutoPushMode.MANUALLY.getDisplayName()); - assertEquals("On Save", AutoPushMode.ON_SAVE.getDisplayName()); - } - - @Test - void toStringReturnsDisplayName() { - assertEquals("Manually", AutoPushMode.MANUALLY.toString()); - assertEquals("On Save", AutoPushMode.ON_SAVE.toString()); - } - - @Test - void fromStringReturnsCorrectEnum() { - assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString("Manually")); - assertEquals(AutoPushMode.ON_SAVE, AutoPushMode.fromString("On Save")); - } - - @Test - void fromStringIsCaseInsensitive() { - assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString("manually")); - assertEquals(AutoPushMode.ON_SAVE, AutoPushMode.fromString("on save")); - } - - @Test - void fromStringInvalidReturnsManually() { - assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString("invalid")); - assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString("")); - assertEquals(AutoPushMode.MANUALLY, AutoPushMode.fromString(null)); - } -} From f232305d34fb4e41a876e1f5b8a98d71c3569816 Mon Sep 17 00:00:00 2001 From: SihasA Date: Mon, 17 Mar 2025 14:32:27 +0000 Subject: [PATCH 47/72] Fixed merge conflicts and added github passkey and username to preferences --- src/main/java/org/jabref/logic/git/GitPreferences.java | 2 ++ src/test/java/org/jabref/logic/git/GitPreferencesTest.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/git/GitPreferences.java b/src/main/java/org/jabref/logic/git/GitPreferences.java index 798570c41c2..a44cad5fdcd 100644 --- a/src/main/java/org/jabref/logic/git/GitPreferences.java +++ b/src/main/java/org/jabref/logic/git/GitPreferences.java @@ -4,6 +4,8 @@ import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.StringProperty; +import javafx.beans.property.SimpleStringProperty; import org.jabref.logic.preferences.AutoPushMode; diff --git a/src/test/java/org/jabref/logic/git/GitPreferencesTest.java b/src/test/java/org/jabref/logic/git/GitPreferencesTest.java index 38a8a6b78a3..16d309d5b62 100644 --- a/src/test/java/org/jabref/logic/git/GitPreferencesTest.java +++ b/src/test/java/org/jabref/logic/git/GitPreferencesTest.java @@ -16,7 +16,7 @@ class GitPreferencesTest { @BeforeEach void setUp() { - gitPreferences = new GitPreferences(true, AutoPushMode.ON_SAVE); + gitPreferences = new GitPreferences(true, AutoPushMode.ON_SAVE, "", ""); } @Test From 4d9198551cceb08eacdcc015aa823fc76f26f9b9 Mon Sep 17 00:00:00 2001 From: SihasA Date: Mon, 17 Mar 2025 14:50:05 +0000 Subject: [PATCH 48/72] Revert "Added Git Username and Passkey fields to preferences" This reverts commit 5e0015c6 --- src/main/java/module-info.java | 1 + src/main/java/org/jabref/logic/git/GitHandler.java | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index f9d4ff4cbbe..e36ac66cafb 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -191,5 +191,6 @@ requires org.antlr.antlr4.runtime; requires org.libreoffice.uno; requires de.jensd.fx.glyphs.fontawesome; + requires org.junit.jupiter.api; // endregion } diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 61d02b55eed..62240fbffd8 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -26,9 +26,9 @@ public class GitHandler { static final Logger LOGGER = LoggerFactory.getLogger(GitHandler.class); final Path repositoryPath; final File repositoryPathAsFile; - String gitUsername = Optional.ofNullable(System.getenv("GIT_USERNAME")).orElse(""); - String gitPassword = Optional.ofNullable(System.getenv("GIT_PASSWORD")).orElse(""); - CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider(gitUsername, gitPassword); + String gitUsername = Optional.ofNullable(System.getenv("GIT_EMAIL")).orElse(""); + String gitPassword = Optional.ofNullable(System.getenv("GIT_PW")).orElse(""); + final CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider(gitUsername, gitPassword); /** * Initialize the handler for the given repository From 2ea0d729962ceea45df25bc1610b7e03c1895618 Mon Sep 17 00:00:00 2001 From: SihasA Date: Mon, 17 Mar 2025 16:41:55 +0000 Subject: [PATCH 49/72] Fixed Preferences and finished GitFunctionality for basic pull and push --- src/main/java/module-info.java | 1 - src/main/java/org/jabref/logic/git/GitHandler.java | 8 +++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index e36ac66cafb..f9d4ff4cbbe 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -191,6 +191,5 @@ requires org.antlr.antlr4.runtime; requires org.libreoffice.uno; requires de.jensd.fx.glyphs.fontawesome; - requires org.junit.jupiter.api; // endregion } diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 62240fbffd8..00cee0d74b7 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -7,6 +7,8 @@ import java.nio.file.Path; import java.util.Optional; +import org.jabref.gui.preferences.GuiPreferences; + import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.RmCommand; import org.eclipse.jgit.api.Status; @@ -28,7 +30,7 @@ public class GitHandler { final File repositoryPathAsFile; String gitUsername = Optional.ofNullable(System.getenv("GIT_EMAIL")).orElse(""); String gitPassword = Optional.ofNullable(System.getenv("GIT_PW")).orElse(""); - final CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider(gitUsername, gitPassword); + CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider(gitUsername, gitPassword); /** * Initialize the handler for the given repository @@ -226,8 +228,8 @@ public void postSaveDatabaseAction() { public void updateCredentials(GuiPreferences preferences) { this.credentialsProvider = new UsernamePasswordCredentialsProvider( - preferences.getGitPreferences().getUsername(), - preferences.getGitPreferences().getPassword() + preferences.getGitPreferences().getGitHubUsername(), + preferences.getGitPreferences().getGitHubPasskey() ); } } From 2fe10666ea7baa06fc3c8677e7f0d96f6cb027e3 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Mon, 17 Mar 2025 18:35:54 +0000 Subject: [PATCH 50/72] Implement auto push on database save --- .../gui/exporter/SaveDatabaseAction.java | 12 +-------- .../org/jabref/gui/shared/GitPullAction.java | 2 +- .../org/jabref/gui/shared/GitPushAction.java | 4 +-- .../java/org/jabref/logic/git/GitHandler.java | 26 ++++++++++++------- 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index 28355c055fb..49b26d37cb6 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -35,7 +35,6 @@ import org.jabref.logic.git.GitHandler; import org.jabref.logic.l10n.Encodings; import org.jabref.logic.l10n.Localization; -import org.jabref.logic.preferences.AutoPushMode; import org.jabref.logic.shared.DatabaseLocation; import org.jabref.logic.shared.prefs.SharedDatabasePreferences; import org.jabref.logic.util.BackgroundTask; @@ -239,16 +238,7 @@ private boolean save(Path targetPath, SaveDatabaseMode mode) { if (success) { libraryTab.getUndoManager().markUnchanged(); libraryTab.resetChangedProperties(); - // Push if path is a repository - if ( - preferences.getGitPreferences().getAutoPushMode() == AutoPushMode.ON_SAVE && - preferences.getGitPreferences().getAutoPushEnabled() - ) { - GitHandler gitHandler = new GitHandler(targetPath.getParent(), false); - if (gitHandler.isGitRepository()) { - gitHandler.postSaveDatabaseAction(); - } - } + new GitHandler(targetPath.getParent(), false).postSaveDatabaseAction(preferences.getGitPreferences()); } dialogService.notify(Localization.lang("Library saved")); return success; diff --git a/src/main/java/org/jabref/gui/shared/GitPullAction.java b/src/main/java/org/jabref/gui/shared/GitPullAction.java index a2eaf9f3dc5..98f348e385b 100644 --- a/src/main/java/org/jabref/gui/shared/GitPullAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPullAction.java @@ -44,7 +44,7 @@ public void execute() { GitHandler gitHandler = new GitHandler(path.get().getParent(), false); if (gitHandler.isGitRepository()) { try { - gitHandler.updateCredentials(preferences); + gitHandler.updateCredentials(preferences.getGitPreferences()); gitHandler.pullOnCurrentBranch(); } catch (Exception e) { dialogService.showErrorDialogAndWait(e); diff --git a/src/main/java/org/jabref/gui/shared/GitPushAction.java b/src/main/java/org/jabref/gui/shared/GitPushAction.java index 476984f2e43..504c4bfff30 100644 --- a/src/main/java/org/jabref/gui/shared/GitPushAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPushAction.java @@ -44,8 +44,8 @@ public void execute() { GitHandler gitHandler = new GitHandler(path.get().getParent(), false); if (gitHandler.isGitRepository()) { try { - gitHandler.createCommitOnCurrentBranch("Automatic update via JabRef)", false); - gitHandler.updateCredentials(preferences); + gitHandler.createCommitOnCurrentBranch("Automatic update via JabRef", false); + gitHandler.updateCredentials(preferences.getGitPreferences()); gitHandler.pushCommitsToRemoteRepository(); } catch (Exception e) { dialogService.showErrorDialogAndWait(e); diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 00cee0d74b7..2e41a3b8371 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -7,7 +7,7 @@ import java.nio.file.Path; import java.util.Optional; -import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.logic.preferences.AutoPushMode; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.RmCommand; @@ -24,6 +24,7 @@ * This class handles the updating of the local and remote git repository that is located at the repository path * This provides an easy-to-use interface to manage a git repository */ +@SuppressWarnings("checkstyle:RegexpMultiline") public class GitHandler { static final Logger LOGGER = LoggerFactory.getLogger(GitHandler.class); final Path repositoryPath; @@ -217,19 +218,24 @@ public String getCurrentlyCheckedOutBranch() throws IOException { } } - public void postSaveDatabaseAction() { - try { - this.createCommitOnCurrentBranch("Automatic update via JabRef", false); - this.pushCommitsToRemoteRepository(); - } catch (Exception e) { - LOGGER.info("Failed to push".concat(e.toString())); + public void postSaveDatabaseAction(GitPreferences preferences) { + if (this.isGitRepository() && + preferences.getAutoPushMode() == AutoPushMode.ON_SAVE && + preferences.getAutoPushEnabled()) { + this.updateCredentials(preferences); + try { + this.createCommitOnCurrentBranch("Automatic update via JabRef", false); + this.pushCommitsToRemoteRepository(); + } catch (Exception e) { + LOGGER.info("Failed to push".concat(e.toString())); + } } } - public void updateCredentials(GuiPreferences preferences) { + public void updateCredentials(GitPreferences preferences) { this.credentialsProvider = new UsernamePasswordCredentialsProvider( - preferences.getGitPreferences().getGitHubUsername(), - preferences.getGitPreferences().getGitHubPasskey() + preferences.getGitHubUsername(), + preferences.getGitHubPasskey() ); } } From 8f683f05ea29b71f5255015db724d2bbdc9d6406 Mon Sep 17 00:00:00 2001 From: SihasA Date: Mon, 17 Mar 2025 18:39:13 +0000 Subject: [PATCH 51/72] Removed Manually option from combobox, will remove combobox in future. --- src/main/java/org/jabref/logic/preferences/AutoPushMode.java | 3 +-- .../org/jabref/logic/preferences/JabRefCliPreferences.java | 2 +- src/test/java/org/jabref/logic/git/GitPreferencesTest.java | 4 ---- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/jabref/logic/preferences/AutoPushMode.java b/src/main/java/org/jabref/logic/preferences/AutoPushMode.java index 6f1ad904f2d..ddf9f47f62e 100644 --- a/src/main/java/org/jabref/logic/preferences/AutoPushMode.java +++ b/src/main/java/org/jabref/logic/preferences/AutoPushMode.java @@ -1,7 +1,6 @@ package org.jabref.logic.preferences; public enum AutoPushMode { - MANUALLY("Manually"), ON_SAVE("On Save"); private final String displayName; @@ -25,6 +24,6 @@ public static AutoPushMode fromString(String text) { return mode; } } - return MANUALLY; + return ON_SAVE; } } diff --git a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java index bedee7a13ed..8f79a7f9ec1 100644 --- a/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java +++ b/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java @@ -1832,7 +1832,7 @@ public GitPreferences getGitPreferences() { } boolean autoPushEnabled = getBoolean("gitAutoPushEnabled", false); - String storedMode = getString("gitAutoPushMode", AutoPushMode.MANUALLY.name()); + String storedMode = getString("gitAutoPushMode", AutoPushMode.ON_SAVE.name()); AutoPushMode autoPushMode = AutoPushMode.fromString(storedMode); String gitHubUsername = getString("gitHubUsername", ""); diff --git a/src/test/java/org/jabref/logic/git/GitPreferencesTest.java b/src/test/java/org/jabref/logic/git/GitPreferencesTest.java index 16d309d5b62..47eea31b053 100644 --- a/src/test/java/org/jabref/logic/git/GitPreferencesTest.java +++ b/src/test/java/org/jabref/logic/git/GitPreferencesTest.java @@ -47,14 +47,10 @@ void testJavaFXBooleanPropertyUpdates() { @Test void testAutoPushModeUpdates() { ObjectProperty autoPushModeProperty = gitPreferences.getAutoPushModeProperty(); - autoPushModeProperty.set(AutoPushMode.MANUALLY); - assertThat(gitPreferences.getAutoPushMode()).isEqualTo(AutoPushMode.MANUALLY); } @Test void testAutoPushModeFromString() { assertThat(AutoPushMode.fromString("On Save")).isEqualTo(AutoPushMode.ON_SAVE); - assertThat(AutoPushMode.fromString("Manually")).isEqualTo(AutoPushMode.MANUALLY); - assertThat(AutoPushMode.fromString("invalid")).isEqualTo(AutoPushMode.MANUALLY); } } From 1884dd72549cfc1b743aaf35830e1d7b50bb5f94 Mon Sep 17 00:00:00 2001 From: SihasA Date: Mon, 17 Mar 2025 18:44:50 +0000 Subject: [PATCH 52/72] Revert "Implement auto push on database save" This reverts commit 2fe10666ea7baa06fc3c8677e7f0d96f6cb027e3. --- .../gui/exporter/SaveDatabaseAction.java | 12 ++++++++- .../org/jabref/gui/shared/GitPullAction.java | 2 +- .../org/jabref/gui/shared/GitPushAction.java | 4 +-- .../java/org/jabref/logic/git/GitHandler.java | 26 +++++++------------ 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index 49b26d37cb6..28355c055fb 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -35,6 +35,7 @@ import org.jabref.logic.git.GitHandler; import org.jabref.logic.l10n.Encodings; import org.jabref.logic.l10n.Localization; +import org.jabref.logic.preferences.AutoPushMode; import org.jabref.logic.shared.DatabaseLocation; import org.jabref.logic.shared.prefs.SharedDatabasePreferences; import org.jabref.logic.util.BackgroundTask; @@ -238,7 +239,16 @@ private boolean save(Path targetPath, SaveDatabaseMode mode) { if (success) { libraryTab.getUndoManager().markUnchanged(); libraryTab.resetChangedProperties(); - new GitHandler(targetPath.getParent(), false).postSaveDatabaseAction(preferences.getGitPreferences()); + // Push if path is a repository + if ( + preferences.getGitPreferences().getAutoPushMode() == AutoPushMode.ON_SAVE && + preferences.getGitPreferences().getAutoPushEnabled() + ) { + GitHandler gitHandler = new GitHandler(targetPath.getParent(), false); + if (gitHandler.isGitRepository()) { + gitHandler.postSaveDatabaseAction(); + } + } } dialogService.notify(Localization.lang("Library saved")); return success; diff --git a/src/main/java/org/jabref/gui/shared/GitPullAction.java b/src/main/java/org/jabref/gui/shared/GitPullAction.java index 98f348e385b..a2eaf9f3dc5 100644 --- a/src/main/java/org/jabref/gui/shared/GitPullAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPullAction.java @@ -44,7 +44,7 @@ public void execute() { GitHandler gitHandler = new GitHandler(path.get().getParent(), false); if (gitHandler.isGitRepository()) { try { - gitHandler.updateCredentials(preferences.getGitPreferences()); + gitHandler.updateCredentials(preferences); gitHandler.pullOnCurrentBranch(); } catch (Exception e) { dialogService.showErrorDialogAndWait(e); diff --git a/src/main/java/org/jabref/gui/shared/GitPushAction.java b/src/main/java/org/jabref/gui/shared/GitPushAction.java index 504c4bfff30..476984f2e43 100644 --- a/src/main/java/org/jabref/gui/shared/GitPushAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPushAction.java @@ -44,8 +44,8 @@ public void execute() { GitHandler gitHandler = new GitHandler(path.get().getParent(), false); if (gitHandler.isGitRepository()) { try { - gitHandler.createCommitOnCurrentBranch("Automatic update via JabRef", false); - gitHandler.updateCredentials(preferences.getGitPreferences()); + gitHandler.createCommitOnCurrentBranch("Automatic update via JabRef)", false); + gitHandler.updateCredentials(preferences); gitHandler.pushCommitsToRemoteRepository(); } catch (Exception e) { dialogService.showErrorDialogAndWait(e); diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 2e41a3b8371..00cee0d74b7 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -7,7 +7,7 @@ import java.nio.file.Path; import java.util.Optional; -import org.jabref.logic.preferences.AutoPushMode; +import org.jabref.gui.preferences.GuiPreferences; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.RmCommand; @@ -24,7 +24,6 @@ * This class handles the updating of the local and remote git repository that is located at the repository path * This provides an easy-to-use interface to manage a git repository */ -@SuppressWarnings("checkstyle:RegexpMultiline") public class GitHandler { static final Logger LOGGER = LoggerFactory.getLogger(GitHandler.class); final Path repositoryPath; @@ -218,24 +217,19 @@ public String getCurrentlyCheckedOutBranch() throws IOException { } } - public void postSaveDatabaseAction(GitPreferences preferences) { - if (this.isGitRepository() && - preferences.getAutoPushMode() == AutoPushMode.ON_SAVE && - preferences.getAutoPushEnabled()) { - this.updateCredentials(preferences); - try { - this.createCommitOnCurrentBranch("Automatic update via JabRef", false); - this.pushCommitsToRemoteRepository(); - } catch (Exception e) { - LOGGER.info("Failed to push".concat(e.toString())); - } + public void postSaveDatabaseAction() { + try { + this.createCommitOnCurrentBranch("Automatic update via JabRef", false); + this.pushCommitsToRemoteRepository(); + } catch (Exception e) { + LOGGER.info("Failed to push".concat(e.toString())); } } - public void updateCredentials(GitPreferences preferences) { + public void updateCredentials(GuiPreferences preferences) { this.credentialsProvider = new UsernamePasswordCredentialsProvider( - preferences.getGitHubUsername(), - preferences.getGitHubPasskey() + preferences.getGitPreferences().getGitHubUsername(), + preferences.getGitPreferences().getGitHubPasskey() ); } } From bde293a835bfbff2ba6e1c253db7e83d6d5e929f Mon Sep 17 00:00:00 2001 From: SihasA Date: Mon, 17 Mar 2025 18:47:01 +0000 Subject: [PATCH 53/72] Revert "Revert "Implement auto push on database save"" This reverts commit 1884dd72549cfc1b743aaf35830e1d7b50bb5f94. --- .../gui/exporter/SaveDatabaseAction.java | 12 +-------- .../org/jabref/gui/shared/GitPullAction.java | 2 +- .../org/jabref/gui/shared/GitPushAction.java | 4 +-- .../java/org/jabref/logic/git/GitHandler.java | 26 ++++++++++++------- 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index 28355c055fb..49b26d37cb6 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -35,7 +35,6 @@ import org.jabref.logic.git.GitHandler; import org.jabref.logic.l10n.Encodings; import org.jabref.logic.l10n.Localization; -import org.jabref.logic.preferences.AutoPushMode; import org.jabref.logic.shared.DatabaseLocation; import org.jabref.logic.shared.prefs.SharedDatabasePreferences; import org.jabref.logic.util.BackgroundTask; @@ -239,16 +238,7 @@ private boolean save(Path targetPath, SaveDatabaseMode mode) { if (success) { libraryTab.getUndoManager().markUnchanged(); libraryTab.resetChangedProperties(); - // Push if path is a repository - if ( - preferences.getGitPreferences().getAutoPushMode() == AutoPushMode.ON_SAVE && - preferences.getGitPreferences().getAutoPushEnabled() - ) { - GitHandler gitHandler = new GitHandler(targetPath.getParent(), false); - if (gitHandler.isGitRepository()) { - gitHandler.postSaveDatabaseAction(); - } - } + new GitHandler(targetPath.getParent(), false).postSaveDatabaseAction(preferences.getGitPreferences()); } dialogService.notify(Localization.lang("Library saved")); return success; diff --git a/src/main/java/org/jabref/gui/shared/GitPullAction.java b/src/main/java/org/jabref/gui/shared/GitPullAction.java index a2eaf9f3dc5..98f348e385b 100644 --- a/src/main/java/org/jabref/gui/shared/GitPullAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPullAction.java @@ -44,7 +44,7 @@ public void execute() { GitHandler gitHandler = new GitHandler(path.get().getParent(), false); if (gitHandler.isGitRepository()) { try { - gitHandler.updateCredentials(preferences); + gitHandler.updateCredentials(preferences.getGitPreferences()); gitHandler.pullOnCurrentBranch(); } catch (Exception e) { dialogService.showErrorDialogAndWait(e); diff --git a/src/main/java/org/jabref/gui/shared/GitPushAction.java b/src/main/java/org/jabref/gui/shared/GitPushAction.java index 476984f2e43..504c4bfff30 100644 --- a/src/main/java/org/jabref/gui/shared/GitPushAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPushAction.java @@ -44,8 +44,8 @@ public void execute() { GitHandler gitHandler = new GitHandler(path.get().getParent(), false); if (gitHandler.isGitRepository()) { try { - gitHandler.createCommitOnCurrentBranch("Automatic update via JabRef)", false); - gitHandler.updateCredentials(preferences); + gitHandler.createCommitOnCurrentBranch("Automatic update via JabRef", false); + gitHandler.updateCredentials(preferences.getGitPreferences()); gitHandler.pushCommitsToRemoteRepository(); } catch (Exception e) { dialogService.showErrorDialogAndWait(e); diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 00cee0d74b7..2e41a3b8371 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -7,7 +7,7 @@ import java.nio.file.Path; import java.util.Optional; -import org.jabref.gui.preferences.GuiPreferences; +import org.jabref.logic.preferences.AutoPushMode; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.RmCommand; @@ -24,6 +24,7 @@ * This class handles the updating of the local and remote git repository that is located at the repository path * This provides an easy-to-use interface to manage a git repository */ +@SuppressWarnings("checkstyle:RegexpMultiline") public class GitHandler { static final Logger LOGGER = LoggerFactory.getLogger(GitHandler.class); final Path repositoryPath; @@ -217,19 +218,24 @@ public String getCurrentlyCheckedOutBranch() throws IOException { } } - public void postSaveDatabaseAction() { - try { - this.createCommitOnCurrentBranch("Automatic update via JabRef", false); - this.pushCommitsToRemoteRepository(); - } catch (Exception e) { - LOGGER.info("Failed to push".concat(e.toString())); + public void postSaveDatabaseAction(GitPreferences preferences) { + if (this.isGitRepository() && + preferences.getAutoPushMode() == AutoPushMode.ON_SAVE && + preferences.getAutoPushEnabled()) { + this.updateCredentials(preferences); + try { + this.createCommitOnCurrentBranch("Automatic update via JabRef", false); + this.pushCommitsToRemoteRepository(); + } catch (Exception e) { + LOGGER.info("Failed to push".concat(e.toString())); + } } } - public void updateCredentials(GuiPreferences preferences) { + public void updateCredentials(GitPreferences preferences) { this.credentialsProvider = new UsernamePasswordCredentialsProvider( - preferences.getGitPreferences().getGitHubUsername(), - preferences.getGitPreferences().getGitHubPasskey() + preferences.getGitHubUsername(), + preferences.getGitHubPasskey() ); } } From 37e0b92ff26dc43052f1eb3d1498350521043b56 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Tue, 18 Mar 2025 15:16:32 +0000 Subject: [PATCH 54/72] Fix various issues Move item list autoPushModeComboBox to GeneralTabViewModel Catch specific exceptions in GitHandler postSaveDatabaseAction Add JavaDoc to postSaveDatabaseAction Add Localization to AutoPushMode modes --- .../org/jabref/gui/preferences/general/GeneralTab.java | 3 +-- .../gui/preferences/general/GeneralTabViewModel.java | 10 +++++++++- src/main/java/org/jabref/gui/shared/GitPushAction.java | 2 +- src/main/java/org/jabref/logic/git/GitHandler.java | 7 ++++++- .../org/jabref/logic/preferences/AutoPushMode.java | 4 +++- src/main/resources/l10n/JabRef_en.properties | 3 ++- 6 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java index f25d93aff5a..06ad90d854e 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java @@ -3,7 +3,6 @@ import java.util.regex.Pattern; import javafx.application.Platform; -import javafx.collections.FXCollections; import javafx.fxml.FXML; import javafx.geometry.Pos; import javafx.scene.control.Button; @@ -139,7 +138,7 @@ public void initialize() { gitHubPasskeyField.textProperty().bindBidirectional(viewModel.gitHubPasskeyProperty()); autoPushCheckbox.selectedProperty().bindBidirectional(viewModel.autoPushEnabledProperty()); - autoPushModeComboBox.setItems(FXCollections.observableArrayList(AutoPushMode.values())); + autoPushModeComboBox.setItems(viewModel.autoPushModeListProperty()); autoPushModeComboBox.valueProperty().bindBidirectional(viewModel.autoPushModeProperty()); ActionFactory actionFactory = new ActionFactory(); diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java index d925c19b699..e5a582e979d 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java @@ -66,6 +66,10 @@ public class GeneralTabViewModel implements PreferenceTabViewModel { new ReadOnlyListWrapper<>(FXCollections.observableArrayList(ThemeTypes.values())); private final ObjectProperty selectedThemeProperty = new SimpleObjectProperty<>(); + private final ReadOnlyListProperty autoPushModeListProperty = + new ReadOnlyListWrapper<>(FXCollections.observableArrayList(AutoPushMode.values())); + private final ObjectProperty autoPushModeProperty = new SimpleObjectProperty<>(); + private final BooleanProperty themeSyncOsProperty = new SimpleBooleanProperty(); // init with empty string to avoid npe in accessing @@ -445,8 +449,12 @@ public BooleanProperty autoPushEnabledProperty() { return gitPreferences.getAutoPushEnabledProperty(); } + public ReadOnlyListProperty autoPushModeListProperty() { + return this.autoPushModeListProperty; + } + public ObjectProperty autoPushModeProperty() { - return gitPreferences.getAutoPushModeProperty(); + return this.autoPushModeProperty; } public StringProperty gitHubUsernameProperty() { diff --git a/src/main/java/org/jabref/gui/shared/GitPushAction.java b/src/main/java/org/jabref/gui/shared/GitPushAction.java index 504c4bfff30..daa2a273703 100644 --- a/src/main/java/org/jabref/gui/shared/GitPushAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPushAction.java @@ -31,10 +31,10 @@ public GitPushAction( @Override public void execute() { - BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); if (stateManager.getActiveDatabase().isEmpty()) { return; } + BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); Optional path = databaseContext.getDatabasePath(); if (path.isEmpty()) { diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 2e41a3b8371..dd40476f2c3 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -218,6 +218,11 @@ public String getCurrentlyCheckedOutBranch() throws IOException { } } + /** + * Contains logic for commiting and pushing after a database is saved locally, + * if the relevant preferences are present. + * @param preferences preferences for git + */ public void postSaveDatabaseAction(GitPreferences preferences) { if (this.isGitRepository() && preferences.getAutoPushMode() == AutoPushMode.ON_SAVE && @@ -226,7 +231,7 @@ public void postSaveDatabaseAction(GitPreferences preferences) { try { this.createCommitOnCurrentBranch("Automatic update via JabRef", false); this.pushCommitsToRemoteRepository(); - } catch (Exception e) { + } catch (GitAPIException | IOException e) { LOGGER.info("Failed to push".concat(e.toString())); } } diff --git a/src/main/java/org/jabref/logic/preferences/AutoPushMode.java b/src/main/java/org/jabref/logic/preferences/AutoPushMode.java index ddf9f47f62e..c236af2fc25 100644 --- a/src/main/java/org/jabref/logic/preferences/AutoPushMode.java +++ b/src/main/java/org/jabref/logic/preferences/AutoPushMode.java @@ -1,7 +1,9 @@ package org.jabref.logic.preferences; +import org.jabref.logic.l10n.Localization; + public enum AutoPushMode { - ON_SAVE("On Save"); + ON_SAVE(Localization.lang("On save")); private final String displayName; diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index c41f97a712a..3f07ba3e7e5 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -799,7 +799,8 @@ Could\ not\ save,\ file\ locked\ by\ another\ JabRef\ instance.=Could not save, Saved\ selected\ to\ '%0'.=Saved selected to '%0'. Autosave\ local\ libraries=Autosave local libraries Automatically\ save\ the\ library\ to=Automatically save the library to -Please\ enter\ a\ valid\ file\ path.=Please enter a valid file path. +On\ save=On save +Please\ enter\ a\ valid\ file\ path.=Please enter a valid file path Overwrite\ file=Overwrite file Unable\ to\ write\ to\ %0.=Unable to write to %0. From f87ab7a8089cd9d6ced3066950dde6218ac60915 Mon Sep 17 00:00:00 2001 From: SihasA Date: Tue, 18 Mar 2025 15:18:52 +0000 Subject: [PATCH 55/72] Fixed/ Looked into Bot Comments - Fixed "Calling get() before checking isEmpty() can throw NoSuchElementException." in GitPushAction.java - Removed messages in assertion statements for CheckForVersionControlActionTest.java --- .../org/jabref/gui/shared/GitPushAction.java | 2 +- .../CheckForVersionControlActionTest.java | 23 +++++-------------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/jabref/gui/shared/GitPushAction.java b/src/main/java/org/jabref/gui/shared/GitPushAction.java index 504c4bfff30..daa2a273703 100644 --- a/src/main/java/org/jabref/gui/shared/GitPushAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPushAction.java @@ -31,10 +31,10 @@ public GitPushAction( @Override public void execute() { - BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); if (stateManager.getActiveDatabase().isEmpty()) { return; } + BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); Optional path = databaseContext.getDatabasePath(); if (path.isEmpty()) { diff --git a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java index bfe1e36d2fe..747dd859a7d 100644 --- a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java +++ b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java @@ -28,7 +28,6 @@ class CheckForVersionControlActionTest { private DialogService dialogService; private CliPreferences cliPreferences; private BibDatabaseContext databaseContext; - private GitHandler gitHandler; @BeforeEach void setUp() { @@ -37,7 +36,6 @@ void setUp() { dialogService = mock(DialogService.class); cliPreferences = mock(CliPreferences.class); databaseContext = mock(BibDatabaseContext.class); - gitHandler = mock(GitHandler.class); when(parserResult.getDatabaseContext()).thenReturn(databaseContext); } @@ -48,7 +46,7 @@ void isActionNecessary_WhenDatabasePathIsEmpty_ShouldReturnFalse() { boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); - assertFalse(result, "Expected isActionNecessary to return false when no database path exists."); + assertFalse(result); } @Test @@ -61,48 +59,39 @@ void isActionNecessary_WhenDatabasePathExistsButNotAGitRepo_ShouldReturnFalse() boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); - assertFalse(result, "Expected isActionNecessary to return false for a non-Git repository."); + assertFalse(result); } @Test void isActionNecessary_WhenDatabasePathExistsAndIsAGitRepo_ShouldReturnTrue() { - Path mockPath = Path.of("test-repo"); - //when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); - GitHandler gitHandlerMock = mock(GitHandler.class); when(gitHandlerMock.isGitRepository()).thenReturn(true); boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); - assertTrue(result, "Expected isActionNecessary to return true for a valid Git repository."); + assertTrue(result); } @Test void performAction_WhenGitPullSucceeds_ShouldNotThrowException() throws IOException { Path mockPath = Path.of("test-repo"); when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); - //when(cliPreferences.shouldAutoPull()).thenReturn(true); GitHandler gitHandlerMock = mock(GitHandler.class); doNothing().when(gitHandlerMock).pullOnCurrentBranch(); - assertDoesNotThrow(() -> action.performAction(parserResult, dialogService, cliPreferences), - "Expected performAction to complete without throwing exceptions."); + assertDoesNotThrow(() -> action.performAction(parserResult, dialogService, cliPreferences)); } @Test - void performAction_WhenGitPullFails_ShouldLogError() throws IOException { + void performAction_WhenGitPullFails_ShouldHandleIOException() throws IOException { Path mockPath = Path.of("test-repo"); when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); - //when(cliPreferences.shouldAutoPull()).thenReturn(true); GitHandler gitHandlerMock = mock(GitHandler.class); doThrow(new IOException("Git pull failed")).when(gitHandlerMock).pullOnCurrentBranch(); - Exception exception = assertThrows(RuntimeException.class, () -> + assertThrows(IOException.class, () -> action.performAction(parserResult, dialogService, cliPreferences)); - - assertTrue(exception.getMessage().contains("Git pull failed"), - "Expected RuntimeException when Git pull fails."); } } From b11f155b67fd1ed5b90a1da7cb3ea8ad26970cb5 Mon Sep 17 00:00:00 2001 From: SihasA Date: Tue, 18 Mar 2025 15:43:33 +0000 Subject: [PATCH 56/72] Fixed CheckStyleIssues and Bot Issue - Checkstyle issue in GitPreferences.java fixed. (Incorrect import order) - Broad catch blocks in GitPullAction and GitPushAction fixed - Also fixed incorrect logger usage. --- src/main/java/org/jabref/gui/shared/GitPullAction.java | 6 +++--- src/main/java/org/jabref/gui/shared/GitPushAction.java | 7 ++++--- src/main/java/org/jabref/logic/git/GitPreferences.java | 7 +------ 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/jabref/gui/shared/GitPullAction.java b/src/main/java/org/jabref/gui/shared/GitPullAction.java index 98f348e385b..5ab3d514c8b 100644 --- a/src/main/java/org/jabref/gui/shared/GitPullAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPullAction.java @@ -1,5 +1,6 @@ package org.jabref.gui.shared; +import java.io.IOException; import java.nio.file.Path; import java.util.Optional; @@ -46,12 +47,11 @@ public void execute() { try { gitHandler.updateCredentials(preferences.getGitPreferences()); gitHandler.pullOnCurrentBranch(); - } catch (Exception e) { + } catch (IOException e) { dialogService.showErrorDialogAndWait(e); } } else { - LOGGER.info(String.valueOf(path.get())); - LOGGER.info("Not a git repository"); + LOGGER.info("Not a git repository at path: {}", path.get()); } } } diff --git a/src/main/java/org/jabref/gui/shared/GitPushAction.java b/src/main/java/org/jabref/gui/shared/GitPushAction.java index daa2a273703..601531dbbef 100644 --- a/src/main/java/org/jabref/gui/shared/GitPushAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPushAction.java @@ -1,5 +1,6 @@ package org.jabref.gui.shared; +import java.io.IOException; import java.nio.file.Path; import java.util.Optional; @@ -10,6 +11,7 @@ import org.jabref.logic.git.GitHandler; import org.jabref.model.database.BibDatabaseContext; +import org.eclipse.jgit.api.errors.GitAPIException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,12 +49,11 @@ public void execute() { gitHandler.createCommitOnCurrentBranch("Automatic update via JabRef", false); gitHandler.updateCredentials(preferences.getGitPreferences()); gitHandler.pushCommitsToRemoteRepository(); - } catch (Exception e) { + } catch (IOException | GitAPIException e) { dialogService.showErrorDialogAndWait(e); } } else { - LOGGER.info(String.valueOf(path.get())); - LOGGER.info("Not a git repository"); + LOGGER.info("Not a git repository at path: {}", path.get()); } } } diff --git a/src/main/java/org/jabref/logic/git/GitPreferences.java b/src/main/java/org/jabref/logic/git/GitPreferences.java index a44cad5fdcd..5ec95289cd6 100644 --- a/src/main/java/org/jabref/logic/git/GitPreferences.java +++ b/src/main/java/org/jabref/logic/git/GitPreferences.java @@ -4,17 +4,12 @@ import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.property.StringProperty; import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; import org.jabref.logic.preferences.AutoPushMode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class GitPreferences { - private static final Logger LOGGER = LoggerFactory.getLogger(GitPreferences.class); - private final BooleanProperty autoPushEnabled; private final ObjectProperty autoPushMode; private final StringProperty gitHubUsername; From 854af5ced808c51754476f21c94d926676a8fc70 Mon Sep 17 00:00:00 2001 From: SihasA Date: Tue, 18 Mar 2025 16:20:42 +0000 Subject: [PATCH 57/72] Fixing Bot Comments - fixed incorrect order of statements for GitPullAction - removed .get() for path in LOGGER statements - checkstyle error fixed - fixed used of a hardcoded path instead of leveraging JUnit's @tempdir annotation. --- .../org/jabref/gui/shared/GitPullAction.java | 4 ++-- .../org/jabref/gui/shared/GitPushAction.java | 2 +- .../java/org/jabref/logic/git/GitHandler.java | 1 + .../CheckForVersionControlActionTest.java | 16 ++++++++++------ 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/jabref/gui/shared/GitPullAction.java b/src/main/java/org/jabref/gui/shared/GitPullAction.java index 5ab3d514c8b..b3865644242 100644 --- a/src/main/java/org/jabref/gui/shared/GitPullAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPullAction.java @@ -32,10 +32,10 @@ public GitPullAction( @Override public void execute() { - BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); if (stateManager.getActiveDatabase().isEmpty()) { return; } + BibDatabaseContext databaseContext = stateManager.getActiveDatabase().get(); Optional path = databaseContext.getDatabasePath(); if (path.isEmpty()) { @@ -51,7 +51,7 @@ public void execute() { dialogService.showErrorDialogAndWait(e); } } else { - LOGGER.info("Not a git repository at path: {}", path.get()); + LOGGER.info("Not a git repository at path: {}", path); } } } diff --git a/src/main/java/org/jabref/gui/shared/GitPushAction.java b/src/main/java/org/jabref/gui/shared/GitPushAction.java index 601531dbbef..d8c98e8acf6 100644 --- a/src/main/java/org/jabref/gui/shared/GitPushAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPushAction.java @@ -53,7 +53,7 @@ public void execute() { dialogService.showErrorDialogAndWait(e); } } else { - LOGGER.info("Not a git repository at path: {}", path.get()); + LOGGER.info("Not a git repository at path: {}", path); } } } diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index dd40476f2c3..ee5f298f43c 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -221,6 +221,7 @@ public String getCurrentlyCheckedOutBranch() throws IOException { /** * Contains logic for commiting and pushing after a database is saved locally, * if the relevant preferences are present. + * * @param preferences preferences for git */ public void postSaveDatabaseAction(GitPreferences preferences) { diff --git a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java index 747dd859a7d..d11680d829f 100644 --- a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java +++ b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java @@ -12,6 +12,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -23,6 +24,9 @@ import static org.mockito.Mockito.when; class CheckForVersionControlActionTest { + @TempDir + Path tempDir; + private CheckForVersionControlAction action; private ParserResult parserResult; private DialogService dialogService; @@ -51,8 +55,8 @@ void isActionNecessary_WhenDatabasePathIsEmpty_ShouldReturnFalse() { @Test void isActionNecessary_WhenDatabasePathExistsButNotAGitRepo_ShouldReturnFalse() { - Path mockPath = Path.of("test-repo"); - when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); + Path testRepo = tempDir.resolve("test-repo"); + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(testRepo)); GitHandler gitHandlerMock = mock(GitHandler.class); when(gitHandlerMock.isGitRepository()).thenReturn(false); @@ -74,8 +78,8 @@ void isActionNecessary_WhenDatabasePathExistsAndIsAGitRepo_ShouldReturnTrue() { @Test void performAction_WhenGitPullSucceeds_ShouldNotThrowException() throws IOException { - Path mockPath = Path.of("test-repo"); - when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); + Path testRepo = tempDir.resolve("test-repo"); + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(testRepo)); GitHandler gitHandlerMock = mock(GitHandler.class); doNothing().when(gitHandlerMock).pullOnCurrentBranch(); @@ -85,8 +89,8 @@ void performAction_WhenGitPullSucceeds_ShouldNotThrowException() throws IOExcept @Test void performAction_WhenGitPullFails_ShouldHandleIOException() throws IOException { - Path mockPath = Path.of("test-repo"); - when(databaseContext.getDatabasePath()).thenReturn(Optional.of(mockPath)); + Path testRepo = tempDir.resolve("test-repo"); + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(testRepo)); GitHandler gitHandlerMock = mock(GitHandler.class); doThrow(new IOException("Git pull failed")).when(gitHandlerMock).pullOnCurrentBranch(); From 95197c2d67bf490f1d0f33646e75bf0fd52b2c8c Mon Sep 17 00:00:00 2001 From: SihasA Date: Wed, 19 Mar 2025 12:49:31 +0000 Subject: [PATCH 58/72] Reverted changes to module-info.java and build.gradle. --- build.gradle | 2 -- src/main/java/module-info.java | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index a30d7ade880..ca626ef4818 100644 --- a/build.gradle +++ b/build.gradle @@ -137,7 +137,6 @@ repositories { // Required for one.jpro.jproutils:tree-showing maven { url 'https://sandec.jfrog.io/artifactory/repo' } - mavenCentral() } configurations { @@ -161,7 +160,6 @@ dependencies { // Include all jar-files in the 'lib' folder as dependencies implementation fileTree(dir: 'lib', includes: ['*.jar']) - implementation 'de.jensd:fontawesomefx-fontawesome:4.7.0-9.1.2' def pdfbox = "3.0.4" implementation ("org.apache.pdfbox:pdfbox:$pdfbox") { diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index f9d4ff4cbbe..ccb2f386829 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -7,6 +7,9 @@ requires java.sql.rowset; // region JavaFX + requires javafx.base; + requires javafx.graphics; + requires javafx.controls; requires javafx.web; requires javafx.fxml; @@ -190,6 +193,5 @@ requires mslinks; requires org.antlr.antlr4.runtime; requires org.libreoffice.uno; - requires de.jensd.fx.glyphs.fontawesome; // endregion } From 51e6fd6fcc2381526e7358a5a0f068f0dfc68ba5 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Wed, 19 Mar 2025 12:54:18 +0000 Subject: [PATCH 59/72] Refactor git client functionality into GitClientHandler --- .../gui/exporter/SaveDatabaseAction.java | 4 +- .../actions/CheckForVersionControlAction.java | 10 ++--- .../org/jabref/gui/shared/GitPullAction.java | 10 ++--- .../org/jabref/gui/shared/GitPushAction.java | 12 +++--- .../jabref/logic/git/GitClientHandler.java | 43 +++++++++++++++++++ .../java/org/jabref/logic/git/GitHandler.java | 34 +-------------- 6 files changed, 63 insertions(+), 50 deletions(-) create mode 100644 src/main/java/org/jabref/logic/git/GitClientHandler.java diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index 49b26d37cb6..9a47eb07ca6 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -32,7 +32,7 @@ import org.jabref.logic.exporter.BibtexDatabaseWriter; import org.jabref.logic.exporter.SaveException; import org.jabref.logic.exporter.SelfContainedSaveConfiguration; -import org.jabref.logic.git.GitHandler; +import org.jabref.logic.git.GitClientHandler; import org.jabref.logic.l10n.Encodings; import org.jabref.logic.l10n.Localization; import org.jabref.logic.shared.DatabaseLocation; @@ -238,7 +238,7 @@ private boolean save(Path targetPath, SaveDatabaseMode mode) { if (success) { libraryTab.getUndoManager().markUnchanged(); libraryTab.resetChangedProperties(); - new GitHandler(targetPath.getParent(), false).postSaveDatabaseAction(preferences.getGitPreferences()); + new GitClientHandler(targetPath.getParent()).postSaveDatabaseAction(preferences.getGitPreferences()); } dialogService.notify(Localization.lang("Library saved")); return success; diff --git a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java index bd25313b2a9..90ea34bca31 100644 --- a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java @@ -5,7 +5,7 @@ import java.util.Optional; import org.jabref.gui.DialogService; -import org.jabref.logic.git.GitHandler; +import org.jabref.logic.git.GitClientHandler; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.preferences.CliPreferences; @@ -19,7 +19,7 @@ */ public class CheckForVersionControlAction implements GUIPostOpenAction { private static final Logger LOGGER = LoggerFactory.getLogger(CheckForVersionControlAction.class); - private GitHandler gitHandler; + private GitClientHandler gitClientHandler; @Override public boolean isActionNecessary(ParserResult parserResult, DialogService dialogService, CliPreferences preferences) { @@ -27,8 +27,8 @@ public boolean isActionNecessary(ParserResult parserResult, DialogService dialog if (path.isEmpty()) { return false; } - this.gitHandler = new GitHandler(path.get()); - return gitHandler.isGitRepository(); + this.gitClientHandler = new GitClientHandler(path.get()); + return gitClientHandler.isGitRepository(); } @Override @@ -36,7 +36,7 @@ public void performAction(ParserResult parserResult, DialogService dialogService parserResult.getDatabaseContext().setVersioned(true); try { - this.gitHandler.pullOnCurrentBranch(); + this.gitClientHandler.pullOnCurrentBranch(); } catch (IOException e) { LOGGER.error("Failed to pull.", e); } diff --git a/src/main/java/org/jabref/gui/shared/GitPullAction.java b/src/main/java/org/jabref/gui/shared/GitPullAction.java index b3865644242..c48487989f4 100644 --- a/src/main/java/org/jabref/gui/shared/GitPullAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPullAction.java @@ -8,7 +8,7 @@ import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.preferences.GuiPreferences; -import org.jabref.logic.git.GitHandler; +import org.jabref.logic.git.GitClientHandler; import org.jabref.model.database.BibDatabaseContext; import org.slf4j.Logger; @@ -42,11 +42,11 @@ public void execute() { return; } - GitHandler gitHandler = new GitHandler(path.get().getParent(), false); - if (gitHandler.isGitRepository()) { + GitClientHandler gitClientHandler = new GitClientHandler(path.get().getParent()); + if (gitClientHandler.isGitRepository()) { try { - gitHandler.updateCredentials(preferences.getGitPreferences()); - gitHandler.pullOnCurrentBranch(); + gitClientHandler.updateCredentials(preferences.getGitPreferences()); + gitClientHandler.pullOnCurrentBranch(); } catch (IOException e) { dialogService.showErrorDialogAndWait(e); } diff --git a/src/main/java/org/jabref/gui/shared/GitPushAction.java b/src/main/java/org/jabref/gui/shared/GitPushAction.java index d8c98e8acf6..96348bd20c5 100644 --- a/src/main/java/org/jabref/gui/shared/GitPushAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPushAction.java @@ -8,7 +8,7 @@ import org.jabref.gui.StateManager; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.preferences.GuiPreferences; -import org.jabref.logic.git.GitHandler; +import org.jabref.logic.git.GitClientHandler; import org.jabref.model.database.BibDatabaseContext; import org.eclipse.jgit.api.errors.GitAPIException; @@ -43,12 +43,12 @@ public void execute() { return; } - GitHandler gitHandler = new GitHandler(path.get().getParent(), false); - if (gitHandler.isGitRepository()) { + GitClientHandler gitClientHandler = new GitClientHandler(path.get().getParent()); + if (gitClientHandler.isGitRepository()) { try { - gitHandler.createCommitOnCurrentBranch("Automatic update via JabRef", false); - gitHandler.updateCredentials(preferences.getGitPreferences()); - gitHandler.pushCommitsToRemoteRepository(); + gitClientHandler.createCommitOnCurrentBranch("Automatic update via JabRef", false); + gitClientHandler.updateCredentials(preferences.getGitPreferences()); + gitClientHandler.pushCommitsToRemoteRepository(); } catch (IOException | GitAPIException e) { dialogService.showErrorDialogAndWait(e); } diff --git a/src/main/java/org/jabref/logic/git/GitClientHandler.java b/src/main/java/org/jabref/logic/git/GitClientHandler.java new file mode 100644 index 00000000000..730a5393d6d --- /dev/null +++ b/src/main/java/org/jabref/logic/git/GitClientHandler.java @@ -0,0 +1,43 @@ +package org.jabref.logic.git; + +import java.io.IOException; +import java.nio.file.Path; + +import org.jabref.logic.preferences.AutoPushMode; + +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; + +public class GitClientHandler extends GitHandler { + + public GitClientHandler(Path repositoryPath) { + super(repositoryPath, false); + } + + /** + * Contains logic for commiting and pushing after a database is saved locally, + * if the relevant preferences are present. + * + * @param preferences preferences for git + */ + public void postSaveDatabaseAction(GitPreferences preferences) { + if (this.isGitRepository() && + preferences.getAutoPushMode() == AutoPushMode.ON_SAVE && + preferences.getAutoPushEnabled()) { + this.updateCredentials(preferences); + try { + this.createCommitOnCurrentBranch("Automatic update via JabRef", false); + this.pushCommitsToRemoteRepository(); + } catch (GitAPIException | IOException e) { + LOGGER.info("Failed to push".concat(e.toString())); + } + } + } + + public void updateCredentials(GitPreferences preferences) { + this.credentialsProvider = new UsernamePasswordCredentialsProvider( + preferences.getGitHubUsername(), + preferences.getGitHubPasskey() + ); + } +} diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index ee5f298f43c..871e9e6773d 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -7,8 +7,6 @@ import java.nio.file.Path; import java.util.Optional; -import org.jabref.logic.preferences.AutoPushMode; - import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.RmCommand; import org.eclipse.jgit.api.Status; @@ -24,7 +22,6 @@ * This class handles the updating of the local and remote git repository that is located at the repository path * This provides an easy-to-use interface to manage a git repository */ -@SuppressWarnings("checkstyle:RegexpMultiline") public class GitHandler { static final Logger LOGGER = LoggerFactory.getLogger(GitHandler.class); final Path repositoryPath; @@ -195,7 +192,7 @@ public void pushCommitsToRemoteRepository() throws IOException { .setCredentialsProvider(credentialsProvider) .call(); } catch (GitAPIException e) { - LOGGER.info("Failed to push: ".concat(e.toString())); + LOGGER.info("Failed to push: "); } } } @@ -207,7 +204,7 @@ public void pullOnCurrentBranch() throws IOException { .setCredentialsProvider(credentialsProvider) .call(); } catch (GitAPIException e) { - LOGGER.info("Failed to pull".concat(e.toString())); + LOGGER.info("Failed to pull"); } } } @@ -217,31 +214,4 @@ public String getCurrentlyCheckedOutBranch() throws IOException { return git.getRepository().getBranch(); } } - - /** - * Contains logic for commiting and pushing after a database is saved locally, - * if the relevant preferences are present. - * - * @param preferences preferences for git - */ - public void postSaveDatabaseAction(GitPreferences preferences) { - if (this.isGitRepository() && - preferences.getAutoPushMode() == AutoPushMode.ON_SAVE && - preferences.getAutoPushEnabled()) { - this.updateCredentials(preferences); - try { - this.createCommitOnCurrentBranch("Automatic update via JabRef", false); - this.pushCommitsToRemoteRepository(); - } catch (GitAPIException | IOException e) { - LOGGER.info("Failed to push".concat(e.toString())); - } - } - } - - public void updateCredentials(GitPreferences preferences) { - this.credentialsProvider = new UsernamePasswordCredentialsProvider( - preferences.getGitHubUsername(), - preferences.getGitHubPasskey() - ); - } } From e3fc84e28073fb96bad1e23fee92bbe0be4af9ef Mon Sep 17 00:00:00 2001 From: "Aryaman Amit Mehta (k23043160)" Date: Wed, 19 Mar 2025 13:09:35 +0000 Subject: [PATCH 60/72] Corrected issue - "Method violates fail-fast principle by nesting all logic inside a complex if condition. Should check conditions individually and return early if any fails." --- .../java/org/jabref/logic/git/GitHandler.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 871e9e6773d..3c920c3a401 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -7,6 +7,8 @@ import java.nio.file.Path; import java.util.Optional; +import org.jabref.logic.preferences.AutoPushMode; + import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.RmCommand; import org.eclipse.jgit.api.Status; @@ -214,4 +216,40 @@ public String getCurrentlyCheckedOutBranch() throws IOException { return git.getRepository().getBranch(); } } + + /** + * Contains logic for commiting and pushing after a database is saved locally, + * if the relevant preferences are present. + * + * @param preferences preferences for git + */ + public void postSaveDatabaseAction(GitPreferences preferences) { + if (!isGitRepository()) { + return; + } + + if (preferences.getAutoPushMode() != AutoPushMode.ON_SAVE) { + return; + } + + if (!preferences.getAutoPushEnabled()) { + return; + } + + updateCredentials(preferences); + + try { + createCommitOnCurrentBranch("Automatic update via JabRef", false); + pushCommitsToRemoteRepository(); + } catch (GitAPIException | IOException e) { + LOGGER.info("Failed to push: {}", e.toString()); + } + } + + public void updateCredentials(GitPreferences preferences) { + this.credentialsProvider = new UsernamePasswordCredentialsProvider( + preferences.getGitHubUsername(), + preferences.getGitHubPasskey() + ); + } } From 307008786ebe7fa6df22a39c5c07827e93876a33 Mon Sep 17 00:00:00 2001 From: "Aryaman Amit Mehta (k23043160)" Date: Wed, 19 Mar 2025 13:14:36 +0000 Subject: [PATCH 61/72] Corrected issue - "Method violates fail-fast principle by nesting all logic inside a complex if condition. Should check conditions individually and return early if any fails." --- .../jabref/logic/git/GitClientHandler.java | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/jabref/logic/git/GitClientHandler.java b/src/main/java/org/jabref/logic/git/GitClientHandler.java index 730a5393d6d..4a2a5e1b09d 100644 --- a/src/main/java/org/jabref/logic/git/GitClientHandler.java +++ b/src/main/java/org/jabref/logic/git/GitClientHandler.java @@ -21,16 +21,25 @@ public GitClientHandler(Path repositoryPath) { * @param preferences preferences for git */ public void postSaveDatabaseAction(GitPreferences preferences) { - if (this.isGitRepository() && - preferences.getAutoPushMode() == AutoPushMode.ON_SAVE && - preferences.getAutoPushEnabled()) { - this.updateCredentials(preferences); - try { - this.createCommitOnCurrentBranch("Automatic update via JabRef", false); - this.pushCommitsToRemoteRepository(); - } catch (GitAPIException | IOException e) { - LOGGER.info("Failed to push".concat(e.toString())); - } + if (!isGitRepository()) { + return; + } + + if (preferences.getAutoPushMode() != AutoPushMode.ON_SAVE) { + return; + } + + if (!preferences.getAutoPushEnabled()) { + return; + } + + updateCredentials(preferences); + + try { + createCommitOnCurrentBranch("Automatic update via JabRef", false); + pushCommitsToRemoteRepository(); + } catch (GitAPIException | IOException e) { + LOGGER.info("Failed to push: {}", e.toString()); } } From 4e1c577209be7001873fe06a33c2973185148716 Mon Sep 17 00:00:00 2001 From: "Aryaman Amit Mehta (k23043160)" Date: Wed, 19 Mar 2025 13:17:09 +0000 Subject: [PATCH 62/72] Corrected issue - "Method violates fail-fast principle by nesting all logic inside a complex if condition. Should check conditions individually and return early if any fails." --- .../jabref/logic/git/GitClientHandler.java | 29 +++++++------------ .../java/org/jabref/logic/git/GitHandler.java | 2 +- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/jabref/logic/git/GitClientHandler.java b/src/main/java/org/jabref/logic/git/GitClientHandler.java index 4a2a5e1b09d..730a5393d6d 100644 --- a/src/main/java/org/jabref/logic/git/GitClientHandler.java +++ b/src/main/java/org/jabref/logic/git/GitClientHandler.java @@ -21,25 +21,16 @@ public GitClientHandler(Path repositoryPath) { * @param preferences preferences for git */ public void postSaveDatabaseAction(GitPreferences preferences) { - if (!isGitRepository()) { - return; - } - - if (preferences.getAutoPushMode() != AutoPushMode.ON_SAVE) { - return; - } - - if (!preferences.getAutoPushEnabled()) { - return; - } - - updateCredentials(preferences); - - try { - createCommitOnCurrentBranch("Automatic update via JabRef", false); - pushCommitsToRemoteRepository(); - } catch (GitAPIException | IOException e) { - LOGGER.info("Failed to push: {}", e.toString()); + if (this.isGitRepository() && + preferences.getAutoPushMode() == AutoPushMode.ON_SAVE && + preferences.getAutoPushEnabled()) { + this.updateCredentials(preferences); + try { + this.createCommitOnCurrentBranch("Automatic update via JabRef", false); + this.pushCommitsToRemoteRepository(); + } catch (GitAPIException | IOException e) { + LOGGER.info("Failed to push".concat(e.toString())); + } } } diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index 3c920c3a401..fa0e83729f9 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -242,7 +242,7 @@ public void postSaveDatabaseAction(GitPreferences preferences) { createCommitOnCurrentBranch("Automatic update via JabRef", false); pushCommitsToRemoteRepository(); } catch (GitAPIException | IOException e) { - LOGGER.info("Failed to push: {}", e.toString()); + LOGGER.error("Failed to push", e); } } From 5b278aa643fc78d87995c2d162693d9a6b1ef5eb Mon Sep 17 00:00:00 2001 From: SihasA Date: Wed, 19 Mar 2025 13:30:00 +0000 Subject: [PATCH 63/72] Ran rewriteRun and fixed bot comments --- .../org/jabref/gui/shared/GitPullAction.java | 2 +- .../java/org/jabref/logic/git/GitHandler.java | 6 +++--- .../org/jabref/logic/git/GitPreferencesTest.java | 16 +++++----------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/jabref/gui/shared/GitPullAction.java b/src/main/java/org/jabref/gui/shared/GitPullAction.java index c48487989f4..6ad3c4619ae 100644 --- a/src/main/java/org/jabref/gui/shared/GitPullAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPullAction.java @@ -44,8 +44,8 @@ public void execute() { GitClientHandler gitClientHandler = new GitClientHandler(path.get().getParent()); if (gitClientHandler.isGitRepository()) { + gitClientHandler.updateCredentials(preferences.getGitPreferences()); try { - gitClientHandler.updateCredentials(preferences.getGitPreferences()); gitClientHandler.pullOnCurrentBranch(); } catch (IOException e) { dialogService.showErrorDialogAndWait(e); diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index fa0e83729f9..b5823186d93 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -70,7 +70,7 @@ public GitHandler(Path repositoryPath, boolean createRepo) { } } } catch (GitAPIException | IOException e) { - LOGGER.error("Initialization failed"); + LOGGER.error("Initialization failed.", e); } } } @@ -194,7 +194,7 @@ public void pushCommitsToRemoteRepository() throws IOException { .setCredentialsProvider(credentialsProvider) .call(); } catch (GitAPIException e) { - LOGGER.info("Failed to push: "); + LOGGER.error("Git push failed", e); } } } @@ -206,7 +206,7 @@ public void pullOnCurrentBranch() throws IOException { .setCredentialsProvider(credentialsProvider) .call(); } catch (GitAPIException e) { - LOGGER.info("Failed to pull"); + LOGGER.error("Git pull failed", e); } } } diff --git a/src/test/java/org/jabref/logic/git/GitPreferencesTest.java b/src/test/java/org/jabref/logic/git/GitPreferencesTest.java index 47eea31b053..0b9c9d41768 100644 --- a/src/test/java/org/jabref/logic/git/GitPreferencesTest.java +++ b/src/test/java/org/jabref/logic/git/GitPreferencesTest.java @@ -1,7 +1,6 @@ package org.jabref.logic.git; import javafx.beans.property.BooleanProperty; -import javafx.beans.property.ObjectProperty; import org.jabref.logic.preferences.AutoPushMode; @@ -20,37 +19,32 @@ void setUp() { } @Test - void testConstructorInitialisesValues() { + void constructorInitialisesValues() { assertThat(gitPreferences.getAutoPushEnabled()).isTrue(); assertThat(gitPreferences.getAutoPushMode()).isEqualTo(AutoPushMode.ON_SAVE); } @Test - void testGettersReturnCorrectValues() { + void gettersReturnCorrectValues() { assertThat(gitPreferences.getAutoPushEnabled()).isTrue(); assertThat(gitPreferences.getAutoPushMode()).isEqualTo(AutoPushMode.ON_SAVE); } @Test - void testSetAutoPushEnabledUpdatesValue() { + void setAutoPushEnabledUpdatesValue() { gitPreferences.setAutoPushEnabled(false); assertThat(gitPreferences.getAutoPushEnabled()).isFalse(); } @Test - void testJavaFXBooleanPropertyUpdates() { + void javaFXBooleanPropertyUpdates() { BooleanProperty autoPushProperty = gitPreferences.getAutoPushEnabledProperty(); autoPushProperty.set(false); assertThat(gitPreferences.getAutoPushEnabled()).isFalse(); } @Test - void testAutoPushModeUpdates() { - ObjectProperty autoPushModeProperty = gitPreferences.getAutoPushModeProperty(); - } - - @Test - void testAutoPushModeFromString() { + void autoPushModeFromString() { assertThat(AutoPushMode.fromString("On Save")).isEqualTo(AutoPushMode.ON_SAVE); } } From c305e531699fd4d6fddc5066a60e9eb87efaf215 Mon Sep 17 00:00:00 2001 From: SihasA Date: Wed, 19 Mar 2025 14:32:10 +0000 Subject: [PATCH 64/72] Added localisation and fixed logger issues. - Localisation tests were failing. Added keys yo JabRef_en.properties. - Bot mentioned issues with logger, these have been resolved. --- src/main/java/org/jabref/gui/shared/GitPullAction.java | 2 +- src/main/java/org/jabref/logic/git/GitClientHandler.java | 2 +- src/main/resources/l10n/JabRef_en.properties | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/gui/shared/GitPullAction.java b/src/main/java/org/jabref/gui/shared/GitPullAction.java index 6ad3c4619ae..137d6648211 100644 --- a/src/main/java/org/jabref/gui/shared/GitPullAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPullAction.java @@ -48,7 +48,7 @@ public void execute() { try { gitClientHandler.pullOnCurrentBranch(); } catch (IOException e) { - dialogService.showErrorDialogAndWait(e); + LOGGER.error("Failed to Pull", e); } } else { LOGGER.info("Not a git repository at path: {}", path); diff --git a/src/main/java/org/jabref/logic/git/GitClientHandler.java b/src/main/java/org/jabref/logic/git/GitClientHandler.java index 730a5393d6d..6cc29b75bc5 100644 --- a/src/main/java/org/jabref/logic/git/GitClientHandler.java +++ b/src/main/java/org/jabref/logic/git/GitClientHandler.java @@ -29,7 +29,7 @@ public void postSaveDatabaseAction(GitPreferences preferences) { this.createCommitOnCurrentBranch("Automatic update via JabRef", false); this.pushCommitsToRemoteRepository(); } catch (GitAPIException | IOException e) { - LOGGER.info("Failed to push".concat(e.toString())); + LOGGER.error("Failed to push", e); } } } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 3f07ba3e7e5..cecacb64f94 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -1405,6 +1405,9 @@ Focus\ entry\ table=Focus entry table Focus\ group\ list=Focus group list Import\ into\ current\ library=Import into current library Import\ into\ new\ library=Import into new library +Git=Git +Git\ Pull=Git Pull +Git\ Push=Git Push New\ article=New article New\ book=New book New\ entry=New entry From 9b0bf8f2ed366384c22f7ecf9c3fe5807892784d Mon Sep 17 00:00:00 2001 From: SihasA Date: Wed, 19 Mar 2025 15:45:28 +0000 Subject: [PATCH 65/72] Fixed one failing test case and removed problematic test + Bot comment fix. - Removed CheckForVersionControlActionTest.java and working on a replacement. - fixed properties file issue --- .../org/jabref/gui/shared/GitPullAction.java | 2 +- src/main/resources/l10n/JabRef_en.properties | 2 +- .../CheckForVersionControlActionTest.java | 101 ------------------ 3 files changed, 2 insertions(+), 103 deletions(-) delete mode 100644 src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java diff --git a/src/main/java/org/jabref/gui/shared/GitPullAction.java b/src/main/java/org/jabref/gui/shared/GitPullAction.java index 137d6648211..6496f342ff8 100644 --- a/src/main/java/org/jabref/gui/shared/GitPullAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPullAction.java @@ -51,7 +51,7 @@ public void execute() { LOGGER.error("Failed to Pull", e); } } else { - LOGGER.info("Not a git repository at path: {}", path); + LOGGER.info("Not a git repository at path: {}", path.get()); } } } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index cecacb64f94..a3680be52c3 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -800,7 +800,7 @@ Saved\ selected\ to\ '%0'.=Saved selected to '%0'. Autosave\ local\ libraries=Autosave local libraries Automatically\ save\ the\ library\ to=Automatically save the library to On\ save=On save -Please\ enter\ a\ valid\ file\ path.=Please enter a valid file path +Please\ enter\ a\ valid\ file\ path.=Please enter a valid file path. Overwrite\ file=Overwrite file Unable\ to\ write\ to\ %0.=Unable to write to %0. diff --git a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java deleted file mode 100644 index d11680d829f..00000000000 --- a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package org.jabref.gui.importer.actions; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.Optional; - -import org.jabref.gui.DialogService; -import org.jabref.logic.git.GitHandler; -import org.jabref.logic.importer.ParserResult; -import org.jabref.logic.preferences.CliPreferences; -import org.jabref.model.database.BibDatabaseContext; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; - -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class CheckForVersionControlActionTest { - @TempDir - Path tempDir; - - private CheckForVersionControlAction action; - private ParserResult parserResult; - private DialogService dialogService; - private CliPreferences cliPreferences; - private BibDatabaseContext databaseContext; - - @BeforeEach - void setUp() { - action = new CheckForVersionControlAction(); - parserResult = mock(ParserResult.class); - dialogService = mock(DialogService.class); - cliPreferences = mock(CliPreferences.class); - databaseContext = mock(BibDatabaseContext.class); - - when(parserResult.getDatabaseContext()).thenReturn(databaseContext); - } - - @Test - void isActionNecessary_WhenDatabasePathIsEmpty_ShouldReturnFalse() { - when(databaseContext.getDatabasePath()).thenReturn(Optional.empty()); - - boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); - - assertFalse(result); - } - - @Test - void isActionNecessary_WhenDatabasePathExistsButNotAGitRepo_ShouldReturnFalse() { - Path testRepo = tempDir.resolve("test-repo"); - when(databaseContext.getDatabasePath()).thenReturn(Optional.of(testRepo)); - - GitHandler gitHandlerMock = mock(GitHandler.class); - when(gitHandlerMock.isGitRepository()).thenReturn(false); - - boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); - - assertFalse(result); - } - - @Test - void isActionNecessary_WhenDatabasePathExistsAndIsAGitRepo_ShouldReturnTrue() { - GitHandler gitHandlerMock = mock(GitHandler.class); - when(gitHandlerMock.isGitRepository()).thenReturn(true); - - boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); - - assertTrue(result); - } - - @Test - void performAction_WhenGitPullSucceeds_ShouldNotThrowException() throws IOException { - Path testRepo = tempDir.resolve("test-repo"); - when(databaseContext.getDatabasePath()).thenReturn(Optional.of(testRepo)); - - GitHandler gitHandlerMock = mock(GitHandler.class); - doNothing().when(gitHandlerMock).pullOnCurrentBranch(); - - assertDoesNotThrow(() -> action.performAction(parserResult, dialogService, cliPreferences)); - } - - @Test - void performAction_WhenGitPullFails_ShouldHandleIOException() throws IOException { - Path testRepo = tempDir.resolve("test-repo"); - when(databaseContext.getDatabasePath()).thenReturn(Optional.of(testRepo)); - - GitHandler gitHandlerMock = mock(GitHandler.class); - doThrow(new IOException("Git pull failed")).when(gitHandlerMock).pullOnCurrentBranch(); - - assertThrows(IOException.class, () -> - action.performAction(parserResult, dialogService, cliPreferences)); - } -} From 493775b51f9d249981350711c09f4fbb16c962eb Mon Sep 17 00:00:00 2001 From: arp-23 Date: Wed, 19 Mar 2025 15:48:11 +0000 Subject: [PATCH 66/72] Add test cases for Git repository detection --- ...ckForVersionControlActionEndToEndTest.java | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionEndToEndTest.java diff --git a/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionEndToEndTest.java b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionEndToEndTest.java new file mode 100644 index 00000000000..f3d42b2819e --- /dev/null +++ b/src/test/java/org/jabref/gui/importer/actions/CheckForVersionControlActionEndToEndTest.java @@ -0,0 +1,93 @@ +package org.jabref.gui.importer.actions; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Optional; + +import org.jabref.gui.DialogService; +import org.jabref.logic.importer.ParserResult; +import org.jabref.logic.preferences.CliPreferences; +import org.jabref.model.database.BibDatabaseContext; + +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class CheckForVersionControlActionEndToEndTest { + @TempDir + Path tempDir; + + private CheckForVersionControlAction action; + private ParserResult parserResult; + private DialogService dialogService; + private CliPreferences cliPreferences; + private BibDatabaseContext databaseContext; + private Path gitRepo; + + @BeforeEach + void setUp() throws IOException, GitAPIException { + gitRepo = tempDir.resolve("git-test-repo"); + Files.createDirectories(gitRepo); + + Git.init() + .setDirectory(gitRepo.toFile()) + .call() + .close(); + + Path testFile = gitRepo.resolve("test.bib"); + Files.writeString(testFile, "@article{test, author={Test Author}, title={Test Title}}"); + + action = new CheckForVersionControlAction(); + parserResult = mock(ParserResult.class); + dialogService = mock(DialogService.class); + cliPreferences = mock(CliPreferences.class); + databaseContext = mock(BibDatabaseContext.class); + + when(parserResult.getDatabaseContext()).thenReturn(databaseContext); + } + + @Test + void isActionNecessary_WhenDatabasePathExistsAndIsAGitRepo_ShouldReturnTrue() { + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(gitRepo.resolve("test.bib"))); + + boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); + + assertTrue(result); + } + + @Test + void isActionNecessary_WhenDatabasePathExistsButNotAGitRepo_ShouldReturnFalse() { + Path nonGitDir = tempDir.resolve("non-git-dir"); + try { + Files.createDirectories(nonGitDir); + Path nonGitFile = nonGitDir.resolve("test.bib"); + Files.writeString(nonGitFile, "@article{test, author={Test Author}, title={Test Title}}"); + + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(nonGitFile)); + + boolean result = action.isActionNecessary(parserResult, dialogService, cliPreferences); + + assertFalse(result); + } catch (IOException e) { + throw new AssertionError("Failed to set up test directory", e); + } + } + + @Test + void performAction_WhenGitPullSucceeds_ShouldNotThrowException() { + when(databaseContext.getDatabasePath()).thenReturn(Optional.of(gitRepo.resolve("test.bib"))); + + action.isActionNecessary(parserResult, dialogService, cliPreferences); + + assertDoesNotThrow(() -> action.performAction(parserResult, dialogService, cliPreferences)); + } +} From 0c0a094dc9ac0b0d54455e1ab243227fdc63acc3 Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Wed, 19 Mar 2025 16:23:17 +0000 Subject: [PATCH 67/72] Refactor postSaveDatabaseAction and GitClientHandler --- .../gui/exporter/SaveDatabaseAction.java | 5 +- .../actions/CheckForVersionControlAction.java | 4 +- .../org/jabref/gui/shared/GitPullAction.java | 5 +- .../org/jabref/gui/shared/GitPushAction.java | 5 +- .../jabref/logic/git/GitClientHandler.java | 102 +++++++++++++++--- .../java/org/jabref/logic/git/GitHandler.java | 38 ------- 6 files changed, 102 insertions(+), 57 deletions(-) diff --git a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java index 9a47eb07ca6..b29838b5c13 100644 --- a/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java +++ b/src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java @@ -238,7 +238,10 @@ private boolean save(Path targetPath, SaveDatabaseMode mode) { if (success) { libraryTab.getUndoManager().markUnchanged(); libraryTab.resetChangedProperties(); - new GitClientHandler(targetPath.getParent()).postSaveDatabaseAction(preferences.getGitPreferences()); + new GitClientHandler(targetPath.getParent(), + dialogService, + preferences.getGitPreferences()) + .postSaveDatabaseAction(); } dialogService.notify(Localization.lang("Library saved")); return success; diff --git a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java index 90ea34bca31..fb80aae56a6 100644 --- a/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/CheckForVersionControlAction.java @@ -27,7 +27,9 @@ public boolean isActionNecessary(ParserResult parserResult, DialogService dialog if (path.isEmpty()) { return false; } - this.gitClientHandler = new GitClientHandler(path.get()); + this.gitClientHandler = new GitClientHandler(path.get(), + dialogService, + preferences.getGitPreferences()); return gitClientHandler.isGitRepository(); } diff --git a/src/main/java/org/jabref/gui/shared/GitPullAction.java b/src/main/java/org/jabref/gui/shared/GitPullAction.java index 137d6648211..387b1484a19 100644 --- a/src/main/java/org/jabref/gui/shared/GitPullAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPullAction.java @@ -42,9 +42,10 @@ public void execute() { return; } - GitClientHandler gitClientHandler = new GitClientHandler(path.get().getParent()); + GitClientHandler gitClientHandler = new GitClientHandler(path.get().getParent(), + dialogService, + preferences.getGitPreferences()); if (gitClientHandler.isGitRepository()) { - gitClientHandler.updateCredentials(preferences.getGitPreferences()); try { gitClientHandler.pullOnCurrentBranch(); } catch (IOException e) { diff --git a/src/main/java/org/jabref/gui/shared/GitPushAction.java b/src/main/java/org/jabref/gui/shared/GitPushAction.java index 96348bd20c5..7bbeebe3399 100644 --- a/src/main/java/org/jabref/gui/shared/GitPushAction.java +++ b/src/main/java/org/jabref/gui/shared/GitPushAction.java @@ -43,11 +43,12 @@ public void execute() { return; } - GitClientHandler gitClientHandler = new GitClientHandler(path.get().getParent()); + GitClientHandler gitClientHandler = new GitClientHandler(path.get().getParent(), + dialogService, + preferences.getGitPreferences()); if (gitClientHandler.isGitRepository()) { try { gitClientHandler.createCommitOnCurrentBranch("Automatic update via JabRef", false); - gitClientHandler.updateCredentials(preferences.getGitPreferences()); gitClientHandler.pushCommitsToRemoteRepository(); } catch (IOException | GitAPIException e) { dialogService.showErrorDialogAndWait(e); diff --git a/src/main/java/org/jabref/logic/git/GitClientHandler.java b/src/main/java/org/jabref/logic/git/GitClientHandler.java index 6cc29b75bc5..10c339da5fd 100644 --- a/src/main/java/org/jabref/logic/git/GitClientHandler.java +++ b/src/main/java/org/jabref/logic/git/GitClientHandler.java @@ -2,42 +2,118 @@ import java.io.IOException; import java.nio.file.Path; +import java.util.Optional; +import org.jabref.gui.DialogService; +import org.jabref.logic.l10n.Localization; import org.jabref.logic.preferences.AutoPushMode; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.ResetCommand; import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; public class GitClientHandler extends GitHandler { + private final DialogService dialogService; + private final GitPreferences gitPreferences; - public GitClientHandler(Path repositoryPath) { + public GitClientHandler(Path repositoryPath, + DialogService dialogService, + GitPreferences gitPreferences) { super(repositoryPath, false); + this.dialogService = dialogService; + this.gitPreferences = gitPreferences; + + this.credentialsProvider = new UsernamePasswordCredentialsProvider( + gitPreferences.getGitHubUsername(), + gitPreferences.getGitHubPasskey() + ); } /** * Contains logic for commiting and pushing after a database is saved locally, * if the relevant preferences are present. * - * @param preferences preferences for git */ - public void postSaveDatabaseAction(GitPreferences preferences) { + public void postSaveDatabaseAction() { if (this.isGitRepository() && - preferences.getAutoPushMode() == AutoPushMode.ON_SAVE && - preferences.getAutoPushEnabled()) { - this.updateCredentials(preferences); + gitPreferences.getAutoPushMode() == AutoPushMode.ON_SAVE && + gitPreferences.getAutoPushEnabled()) { try { this.createCommitOnCurrentBranch("Automatic update via JabRef", false); - this.pushCommitsToRemoteRepository(); } catch (GitAPIException | IOException e) { - LOGGER.error("Failed to push", e); + return; + } + + try { + this.pullAndRebaseOnCurrentBranch(); + dialogService.notify(Localization.lang("Successfully pulled")); + } catch (IOException e) { + // In the case that rebase fails, try revert to previous commit + // and execute regular pull + Optional headRef = Optional.empty(); + try { + headRef = this.getHeadRef(); + } catch (IOException | GitAPIException ex) { + LOGGER.error("Cannot find HEAD on current branch"); + } + if (headRef.isEmpty()) { + return; + } + + try { + this.revertToCommit(headRef.get()); + } catch (IOException ex) { + LOGGER.error("Failed to revert to commit"); + } + + try { + this.pullOnCurrentBranch(); + } catch (IOException ex) { + LOGGER.error("Failed to pull"); + dialogService.notify(Localization.lang("Failed to update repository")); + // TODO: Detect if a merge conflict occurs at this point and resolve + return; + } + } + + try { + this.pushCommitsToRemoteRepository(); + dialogService.notify(Localization.lang("Succesfully pushed")); + } catch (IOException e) { + dialogService.notify(Localization.lang("Failed to push")); } } } - public void updateCredentials(GitPreferences preferences) { - this.credentialsProvider = new UsernamePasswordCredentialsProvider( - preferences.getGitHubUsername(), - preferences.getGitHubPasskey() - ); + private Optional getHeadRef() throws IOException, GitAPIException { + return this.getRefForBranch(this.getCurrentlyCheckedOutBranch()); + } + + private void revertToCommit(Ref commit) throws IOException { + try (Git git = Git.open(this.repositoryPathAsFile)) { + try { + git.reset() + .setMode(ResetCommand.ResetType.SOFT) + .setRef(commit.toString()) + .call(); + } catch (GitAPIException e) { + LOGGER.error("Failed to rever to commit"); + } + } + } + + private void pullAndRebaseOnCurrentBranch() throws IOException { + try (Git git = Git.open(this.repositoryPathAsFile)) { + try { + git.pull() + .setCredentialsProvider(credentialsProvider) + .setRebase(true) + .call(); + } catch (GitAPIException e) { + LOGGER.error("Failed to pull and rebase"); + } + } } } diff --git a/src/main/java/org/jabref/logic/git/GitHandler.java b/src/main/java/org/jabref/logic/git/GitHandler.java index b5823186d93..4ea36205fad 100644 --- a/src/main/java/org/jabref/logic/git/GitHandler.java +++ b/src/main/java/org/jabref/logic/git/GitHandler.java @@ -7,8 +7,6 @@ import java.nio.file.Path; import java.util.Optional; -import org.jabref.logic.preferences.AutoPushMode; - import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.RmCommand; import org.eclipse.jgit.api.Status; @@ -216,40 +214,4 @@ public String getCurrentlyCheckedOutBranch() throws IOException { return git.getRepository().getBranch(); } } - - /** - * Contains logic for commiting and pushing after a database is saved locally, - * if the relevant preferences are present. - * - * @param preferences preferences for git - */ - public void postSaveDatabaseAction(GitPreferences preferences) { - if (!isGitRepository()) { - return; - } - - if (preferences.getAutoPushMode() != AutoPushMode.ON_SAVE) { - return; - } - - if (!preferences.getAutoPushEnabled()) { - return; - } - - updateCredentials(preferences); - - try { - createCommitOnCurrentBranch("Automatic update via JabRef", false); - pushCommitsToRemoteRepository(); - } catch (GitAPIException | IOException e) { - LOGGER.error("Failed to push", e); - } - } - - public void updateCredentials(GitPreferences preferences) { - this.credentialsProvider = new UsernamePasswordCredentialsProvider( - preferences.getGitHubUsername(), - preferences.getGitHubPasskey() - ); - } } From 355ff897467d4e381fd5d70787f4e43a252f3f9e Mon Sep 17 00:00:00 2001 From: Raphael Ahiable Date: Wed, 19 Mar 2025 16:26:38 +0000 Subject: [PATCH 68/72] Update postSaveDatabaseAction JavaDoc --- src/main/java/org/jabref/logic/git/GitClientHandler.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/logic/git/GitClientHandler.java b/src/main/java/org/jabref/logic/git/GitClientHandler.java index 10c339da5fd..6a74b983fd0 100644 --- a/src/main/java/org/jabref/logic/git/GitClientHandler.java +++ b/src/main/java/org/jabref/logic/git/GitClientHandler.java @@ -33,8 +33,9 @@ public GitClientHandler(Path repositoryPath, /** * Contains logic for commiting and pushing after a database is saved locally, - * if the relevant preferences are present. - * + * if the relevant preferences are present.

+ * A git commit is created and a 'git pull --rebase' is executed. In the case of + * an error, the repository is reverted to the commit and a regular pull is executed. */ public void postSaveDatabaseAction() { if (this.isGitRepository() && From 86edd20162dbbec150c53af11db7f7fb70bf7c94 Mon Sep 17 00:00:00 2001 From: SihasA Date: Thu, 20 Mar 2025 13:28:17 +0000 Subject: [PATCH 69/72] Removed line in build.gradle --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index ca626ef4818..fbafcd7bde5 100644 --- a/build.gradle +++ b/build.gradle @@ -160,7 +160,6 @@ dependencies { // Include all jar-files in the 'lib' folder as dependencies implementation fileTree(dir: 'lib', includes: ['*.jar']) - def pdfbox = "3.0.4" implementation ("org.apache.pdfbox:pdfbox:$pdfbox") { exclude group: 'commons-logging' From 14e6d52380d86f61afe200e992ae7962cd61009c Mon Sep 17 00:00:00 2001 From: SihasA Date: Thu, 20 Mar 2025 14:27:25 +0000 Subject: [PATCH 70/72] Added a new heading under saving for git related preferences in general preferences --- .../gui/preferences/general/GeneralTab.fxml | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml index 73d78e83b2d..629c8cc2230 100644 --- a/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml +++ b/src/main/java/org/jabref/gui/preferences/general/GeneralTab.fxml @@ -101,20 +101,6 @@ - - - - - - - - - - @@ -132,4 +118,19 @@ + +