Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refine BackupManager #9054

Merged
merged 29 commits into from
Aug 15, 2022
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
8051bfd
Refine BackupManager
koppor Aug 13, 2022
83938bf
Fix BackupManager
koppor Aug 13, 2022
b607fff
Exchange "bak" and "sav"
koppor Aug 13, 2022
266f997
Refine backup message to show backup path
koppor Aug 13, 2022
dc5710a
Merge remote-tracking branch 'origin/main' into ten-saves-for-backup-…
koppor Aug 14, 2022
78065e2
Introduce BackupFileUtil
koppor Aug 14, 2022
3592ad4
Use AtomicFileWriter
koppor Aug 14, 2022
7c6fd38
Update src/main/java/org/jabref/logic/util/io/BackupFileUtil.java
koppor Aug 14, 2022
e7660e3
More comments
koppor Aug 14, 2022
b2da978
Align JabRefGUI#openLastEditedDatabases() with OpenDatabaseAction#loa…
koppor Aug 14, 2022
d26e218
Remove unused parameter "raisePanel"
koppor Aug 14, 2022
d8b48dd
WIP: Fix opening of databases i) on startup, ii) using File > Open
koppor Aug 14, 2022
9c5cac5
Experiment with needsBackup
koppor Aug 14, 2022
457c4a5
Fix variable name
koppor Aug 15, 2022
3f1ffc6
Remove obsolete method
koppor Aug 15, 2022
e171c04
Remove duplicate code
koppor Aug 15, 2022
b580577
Switch from DelayTaskThrottler to Java's ScheduledThreadPoolExecutor
koppor Aug 15, 2022
7aa1b76
Group together code cloned methods
koppor Aug 15, 2022
7f04fa3
Enable "needsBackup" strategy
koppor Aug 15, 2022
bf18715
Ensure that backup is a recent one
koppor Aug 15, 2022
dacd300
Fix checkstyle
koppor Aug 15, 2022
2f8a75e
Removed JabRefGUI import
calixtus Aug 15, 2022
2db1fab
Introdce OS.APP_DIR_APP_*
koppor Aug 15, 2022
1c45014
Fix checkstyle
koppor Aug 15, 2022
e722e3d
Merge remote-tracking branch 'origin/main' into ten-saves-for-backup-…
koppor Aug 15, 2022
c317aea
Try to fix tests
koppor Aug 15, 2022
122a236
Remove check for concrete hash code
koppor Aug 15, 2022
1e2c2fa
Fix checkstyle
koppor Aug 15, 2022
80797de
Refine comment on expected behavior
koppor Aug 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve

### Added

- In case a backup is found, the filename of the backup is shown.
- On startup, JabRef notifies the user if there were parsing errors during opening.
- We integrated a new three-way merge UI for merging entries in the Entries Merger Dialog, the Duplicate Resolver Dialog, the Entry Importer Dialog, and the External Changes Resolver Dialog. [#8945](https://github.com/JabRef/jabref/pull/8945)
- We added the ability to merge groups, keywords, comments and files when merging entries. [#9022](https://github.com/JabRef/jabref/pull/9022)

### Changed

- We improved the Citavi Importer to also import so called Knowledge-items into the field `comment` of the corresponding entry [#9025](https://github.com/JabRef/jabref/issues/9025)
- We removed wrapping of string constants when writing to a `.bib` file.
- We call backup files `.bak` and temporary writing files now `.sav`.
- JabRef keeps 10 older versions of a `.bib` file in the [user data dir](https://github.com/harawata/appdirs#supported-directories) (instead of a single `.sav` (now: `.bak`) file in the directory of the `.bib` file)
- We changed the button label from "Return to JabRef" to "Return to library" to better indicate the purpose of the action.

### Fixed
Expand Down
25 changes: 9 additions & 16 deletions src/main/java/org/jabref/gui/JabRefFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ private void initDragAndDrop() {
tabbedPane.getTabs().remove(dndIndicator);
List<Path> bibFiles = DragAndDropHelper.getBibFiles(tabDragEvent.getDragboard());
OpenDatabaseAction openDatabaseAction = this.getOpenDatabaseAction();
openDatabaseAction.openFiles(bibFiles, true);
openDatabaseAction.openFiles(bibFiles);
tabDragEvent.setDropCompleted(true);
tabDragEvent.consume();
} else {
Expand All @@ -280,7 +280,7 @@ private void initDragAndDrop() {
tabbedPane.getTabs().remove(dndIndicator);
List<Path> bibFiles = DragAndDropHelper.getBibFiles(event.getDragboard());
OpenDatabaseAction openDatabaseAction = this.getOpenDatabaseAction();
openDatabaseAction.openFiles(bibFiles, true);
openDatabaseAction.openFiles(bibFiles);
event.setDropCompleted(true);
event.consume();
});
Expand Down Expand Up @@ -380,8 +380,7 @@ private void showTrackingNotification() {
*/
public void openAction(String filePath) {
Path file = Path.of(filePath);
// all the logic is done in openIt. Even raising an existing panel
getOpenDatabaseAction().openFile(file, true);
getOpenDatabaseAction().openFile(file);
}

/**
Expand Down Expand Up @@ -1048,6 +1047,11 @@ hide it and clip it to a square of (width x width) each time width is updated.
return new Group(indicator);
}

/**
* Might be called when a user asks JabRef at the command line
* i) to import a file or
* ii) to open a .bib file
*/
public void addParserResult(ParserResult parserResult, boolean focusPanel) {
if (parserResult.toOpenTab()) {
// Add the entries to the open tab.
Expand All @@ -1059,7 +1063,7 @@ public void addParserResult(ParserResult parserResult, boolean focusPanel) {
addImportedEntries(libraryTab, parserResult);
}
} else {
// only add tab if DB is not already open
// only add tab if library is not already open
Optional<LibraryTab> libraryTab = getLibraryTabs().stream()
.filter(p -> p.getBibDatabaseContext()
.getDatabasePath()
Expand Down Expand Up @@ -1119,17 +1123,6 @@ public void addTab(LibraryTab libraryTab, boolean raisePanel) {
}

libraryTab.getUndoManager().registerListener(new UndoRedoEventManager());

BibDatabaseContext context = libraryTab.getBibDatabaseContext();

if (readyForAutosave(context)) {
AutosaveManager autosaver = AutosaveManager.start(context);
autosaver.registerListener(new AutosaveUiManager(libraryTab));
}

BackupManager.start(context, Globals.entryTypesManager, prefs);

trackOpenNewDatabase(libraryTab);
}

private void trackOpenNewDatabase(LibraryTab libraryTab) {
Expand Down
37 changes: 7 additions & 30 deletions src/main/java/org/jabref/gui/JabRefGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.jabref.gui.importer.actions.OpenDatabaseAction;
import org.jabref.gui.keyboard.TextInputKeyBindings;
import org.jabref.gui.shared.SharedDatabaseUIManager;
import org.jabref.gui.util.DefaultTaskExecutor;
koppor marked this conversation as resolved.
Show resolved Hide resolved
import org.jabref.logic.autosaveandbackup.BackupManager;
import org.jabref.logic.importer.OpenDatabase;
import org.jabref.logic.importer.ParserResult;
Expand Down Expand Up @@ -77,8 +78,8 @@ private void openWindow(Stage mainStage) {
if (guiPreferences.isWindowMaximised()) {
mainStage.setMaximized(true);
} else if ((Screen.getScreens().size() == 1) && isWindowPositionOutOfBounds()) {
// corrects the Window, if its outside of the mainscreen
LOGGER.debug("The Jabref Window is outside the Main Monitor\n");
// corrects the Window, if it is outside the mainscreen
LOGGER.debug("The Jabref window is outside the main screen\n");
mainStage.setX(0);
mainStage.setY(0);
mainStage.setWidth(1024);
Expand Down Expand Up @@ -135,6 +136,8 @@ private void openDatabases() {
openLastEditedDatabases();
}

// From here on, the libraries provided by command line arguments are treated

// Remove invalid databases
List<ParserResult> invalidDatabases = bibDatabases.stream()
.filter(ParserResult::isInvalid)
Expand Down Expand Up @@ -266,34 +269,8 @@ private void openLastEditedDatabases() {
return;
}

for (String fileName : lastFiles) {
Path dbFile = Path.of(fileName);

// Already parsed via command line parameter, e.g., "jabref.jar somefile.bib"
if (isLoaded(dbFile) || !Files.exists(dbFile)) {
continue;
}

if (BackupManager.backupFileDiffers(dbFile)) {
BackupUIManager.showRestoreBackupDialog(mainFrame.getDialogService(), dbFile);
}

ParserResult parsedDatabase;
try {
parsedDatabase = OpenDatabase.loadDatabase(
dbFile,
preferencesService.getImportFormatPreferences(),
Globals.getFileUpdateMonitor());
} catch (IOException ex) {
LOGGER.error("Error opening file '{}'", dbFile, ex);
parsedDatabase = ParserResult.fromError(ex);
}
bibDatabases.add(parsedDatabase);
}
}

private boolean isLoaded(Path fileToOpen) {
return bibDatabases.stream().anyMatch(pr -> pr.getPath().isPresent() && pr.getPath().get().equals(fileToOpen));
List<Path> filesToOpen = lastFiles.stream().map(file -> Path.of(file)).collect(Collectors.toList());
getMainFrame().getOpenDatabaseAction().openFiles(filesToOpen);
}

public static JabRefFrame getMainFrame() {
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/jabref/gui/LibraryTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ public void onDatabaseLoadingSucceed(ParserResult result) {
OpenDatabaseAction.performPostOpenActions(this, result);

feedData(context);

// a temporary workaround to update groups pane
stateManager.activeDatabaseProperty().bind(
EasyBind.map(frame.getTabbedPane().getSelectionModel().selectedItemProperty(),
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/org/jabref/gui/dialogs/BackupUIManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import org.jabref.gui.util.DefaultTaskExecutor;
import org.jabref.logic.autosaveandbackup.BackupManager;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.util.BackupFileType;
import org.jabref.logic.util.io.BackupFileUtil;

/**
* Stores all user dialogs related to {@link BackupManager}.
Expand All @@ -17,7 +19,10 @@ private BackupUIManager() {

public static void showRestoreBackupDialog(DialogService dialogService, Path originalPath) {
String content = new StringBuilder()
.append(Localization.lang("A backup file for '%0' was found.", originalPath.getFileName().toString()))
.append(Localization.lang("A backup file for '%0' was found at '%1'.",
originalPath.getFileName().toString(),
// We need to determine the path "manually" as the path does not get passed through when a diff is detected.
BackupFileUtil.getPathOfLatestExisingBackupFile(originalPath, BackupFileType.BACKUP).map(Path::toString).orElse(Localization.lang("File not found"))))
.append("\n")
.append(Localization.lang("This could indicate that JabRef did not shut down cleanly last time the file was used."))
.append("\n\n")
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public void saveSelectedAsPlain() {
}

/**
* @param file the new file name to save the data base to. This is stored in the database context of the panel upon
* @param file the new file name to save the database to. This is stored in the database context of the panel upon
* successful save.
* @return true on successful save
*/
Expand All @@ -131,7 +131,7 @@ boolean saveAs(Path file, SaveDatabaseMode mode) {

if (saveResult) {
// we managed to successfully save the file
// thus, we can store the store the path into the context
// thus, we can store the path into the context
context.setDatabasePath(file);
libraryTab.updateTabTitle(false);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class FileExtensionViewModel {

FileExtensionViewModel(FileType fileType, FilePreferences filePreferences) {
this.description = Localization.lang("%0 file", fileType.getName());
this.extensions = fileType.getExtensionsWithDot();
this.extensions = fileType.getExtensionsWithAsteriskAndDot();
this.filePreferences = filePreferences;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
import org.jabref.gui.DialogService;
import org.jabref.gui.Globals;
import org.jabref.gui.JabRefFrame;
import org.jabref.gui.JabRefGUI;
import org.jabref.gui.LibraryTab;
import org.jabref.gui.StateManager;
import org.jabref.gui.actions.SimpleCommand;
import org.jabref.gui.dialogs.BackupUIManager;
import org.jabref.gui.menus.FileHistoryMenu;
import org.jabref.gui.shared.SharedDatabaseUIManager;
import org.jabref.gui.theme.ThemeManager;
import org.jabref.gui.util.BackgroundTask;
Expand All @@ -46,7 +48,7 @@ public class OpenDatabaseAction extends SimpleCommand {

// List of actions that may need to be called after opening the file. Such as
// upgrade actions etc. that may depend on the JabRef version that wrote the file:
private static final List<GUIPostOpenAction> POST_OPEN_ACTIONS = Arrays.asList(
private static final List<GUIPostOpenAction> POST_OPEN_ACTIONS = List.of(
// Migrations:
// Warning for migrating the Review into the Comment field
new MergeReviewIntoCommentAction(),
Expand Down Expand Up @@ -95,7 +97,7 @@ public void execute() {
.build();

List<Path> filesToOpen = dialogService.showFileOpenDialogAndGetMultipleFiles(fileDialogConfiguration);
openFiles(filesToOpen, true);
openFiles(filesToOpen);
}

/**
Expand All @@ -111,20 +113,22 @@ private Path getInitialDirectory() {
}

/**
* Opens the given file. If null or 404, nothing happens
* Opens the given file. If null or 404, nothing happens.
* In case the file is already opened, that panel is raised.
*
* @param file the file, may be null or not existing
*/
public void openFile(Path file, boolean raisePanel) {
openFiles(new ArrayList<>(List.of(file)), raisePanel);
public void openFile(Path file) {
openFiles(new ArrayList<>(List.of(file)));
}

/**
* Opens the given files. If one of it is null or 404, nothing happens
* Opens the given files. If one of it is null or 404, nothing happens.
* In case the file is already opened, that panel is raised.
*
* @param filesToOpen the filesToOpen, may be null or not existing
*/
public void openFiles(List<Path> filesToOpen, boolean raisePanel) {
public void openFiles(List<Path> filesToOpen) {
LibraryTab toRaise = null;
int initialCount = filesToOpen.size();
int removed = 0;
Expand Down Expand Up @@ -152,16 +156,12 @@ public void openFiles(List<Path> filesToOpen, boolean raisePanel) {
// Run the actual open in a thread to prevent the program
// locking until the file is loaded.
if (!filesToOpen.isEmpty()) {
final List<Path> theFiles = Collections.unmodifiableList(filesToOpen);

for (Path theFile : theFiles) {
FileHistoryMenu fileHistory = frame.getFileHistory();
filesToOpen.forEach(theFile -> {
// This method will execute the concrete file opening and loading in a background thread
openTheFile(theFile, raisePanel);
}

for (Path theFile : theFiles) {
frame.getFileHistory().newFile(theFile);
}
openTheFile(theFile);
fileHistory.newFile(theFile);
});
} else if (toRaise != null) {
// If no files are remaining to open, this could mean that a file was
// already open. If so, we may have to raise the correct tab:
Expand All @@ -170,9 +170,11 @@ public void openFiles(List<Path> filesToOpen, boolean raisePanel) {
}

/**
* @param file the file, may be null or not existing
* This is the real file opening. Should be called via {@link #openFile(Path)}
*
* @param file the file, may be NOT null, but may not be existing
*/
private void openTheFile(Path file, boolean raisePanel) {
private void openTheFile(Path file) {
Objects.requireNonNull(file);
if (!Files.exists(file)) {
return;
Expand All @@ -185,6 +187,10 @@ private void openTheFile(Path file, boolean raisePanel) {
backgroundTask.onFinished(() -> trackOpenNewDatabase(newTab));
}

/**
* This method is similar to {@link JabRefGUI#openLastEditedDatabases()}.
* This method also has the capability to open remote shared databases
*/
private ParserResult loadDatabase(Path file) throws Exception {
Path fileToLoad = file.toAbsolutePath();

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jabref/gui/menus/FileHistoryMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,6 @@ public void openFile(Path file) {
setItems();
return;
}
openDatabaseAction.openFile(file, true);
openDatabaseAction.openFile(file);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public void crawl() {
dialogService.showErrorDialogAndWait(Localization.lang("Error during persistence of crawling results."), e);
})
.onSuccess(unused -> {
new OpenDatabaseAction(frame, preferencesService, dialogService, stateManager, themeManager).openFile(Path.of(studyDirectory.toString(), "studyResult.bib"), true);
new OpenDatabaseAction(frame, preferencesService, dialogService, stateManager, themeManager).openFile(Path.of(studyDirectory.toString(), "studyResult.bib"));
// If finished reset command object for next use
studyDirectory = null;
})
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/org/jabref/gui/util/FileFilterConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ private FileFilterConverter() {

public static FileChooser.ExtensionFilter toExtensionFilter(FileType fileType) {
String description = Localization.lang("%0 file", fileType.toString());
return new FileChooser.ExtensionFilter(description, fileType.getExtensionsWithDot());
return new FileChooser.ExtensionFilter(description, fileType.getExtensionsWithAsteriskAndDot());
}

public static FileChooser.ExtensionFilter toExtensionFilter(String description, FileType fileType) {
return new FileChooser.ExtensionFilter(description, fileType.getExtensionsWithDot());
return new FileChooser.ExtensionFilter(description, fileType.getExtensionsWithAsteriskAndDot());
}

public static Optional<Importer> getImporter(FileChooser.ExtensionFilter extensionFilter, Collection<Importer> importers) {
Expand All @@ -46,7 +46,7 @@ public static Optional<Exporter> getExporter(FileChooser.ExtensionFilter extensi
public static FileChooser.ExtensionFilter forAllImporters(SortedSet<Importer> importers) {
List<FileType> fileTypes = importers.stream().map(Importer::getFileType).collect(Collectors.toList());
List<String> flatExtensions = fileTypes.stream()
.flatMap(type -> type.getExtensionsWithDot().stream())
.flatMap(type -> type.getExtensionsWithAsteriskAndDot().stream())
.collect(Collectors.toList());

return new FileChooser.ExtensionFilter(Localization.lang("Available import formats"), flatExtensions);
Expand Down
Loading