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

Perform a sanity check on database at launch #1778

Merged
merged 1 commit into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 10 additions & 1 deletion Vienna/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -5912,6 +5912,9 @@
}
}
},
"Continue Anyway" : {
"comment" : "Button to continue running Vienna despite an unsuccessful check"
},
"Copy URL" : {
"comment" : "Copy URL",
"localizations" : {
Expand Down Expand Up @@ -16521,7 +16524,7 @@
}
},
"Quit Vienna" : {
"comment" : "Title of a button on an alert\nTitle of a menu item",
"comment" : "Button to quit Vienna after a database check\nTitle of a menu item",
"localizations" : {
"cs" : {
"stringUnit" : {
Expand Down Expand Up @@ -23078,6 +23081,9 @@
}
}
},
"Vienna may not work as expected if the database is corrupted. We recommend you quit Vienna and either restore the database (%@) from a backup or attempt a sqlite3 recovery." : {
"comment" : "Informative text of an alert"
},
"Vienna must upgrade its database to the latest version. This may take a minute or so. We apologize for the inconvenience." : {
"localizations" : {
"da" : {
Expand Down Expand Up @@ -23278,6 +23284,9 @@
}
}
},
"Vienna's database seems to be corrupted. Would you like to quit Vienna or continue anyway?" : {
"comment" : "Title of an alert"
},
"You are already subscribed to that feed" : {
"comment" : "You are already subscribed to that feed",
"localizations" : {
Expand Down
64 changes: 47 additions & 17 deletions Vienna/Sources/Database/Database.m
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,31 @@ + (instancetype)sharedManager {
* @return YES if the database is at the correct version and good to go
*/
- (BOOL)initialiseDatabase {
__block BOOL success;
[self.databaseQueue inDatabase:^(FMDatabase *db) {
success = [db executeStatements:@"PRAGMA quick_check;"];
}];
if (!success) {
NSAlert * alert = [NSAlert new];
alert.alertStyle = NSAlertStyleCritical;
alert.messageText = NSLocalizedString(@"Vienna's database seems to be corrupted. Would you like to quit Vienna or continue anyway?",
@"Title of an alert");
alert.informativeText =
[NSString stringWithFormat:NSLocalizedString(
@"Vienna may not work as expected if the database is corrupted. We recommend you quit Vienna and either restore the database (%@) from a backup or attempt a sqlite3 recovery.",
@"Informative text of an alert"),
self.databaseQueue.path.lastPathComponent];
[alert addButtonWithTitle:NSLocalizedString(@"Quit Vienna", @"Button to quit Vienna after a database check")];
[alert addButtonWithTitle:NSLocalizedString(@"Continue Anyway",
@"Button to continue running Vienna despite an unsuccessful check")];
NSInteger modalReturn = [alert runModal];
if (modalReturn == NSAlertFirstButtonReturn) {
return NO;
} else {
[self backupDatabase];
}
}

NSInteger databaseVersion = self.databaseVersion;
os_log_debug(VNA_LOG, "Database version: %ld", databaseVersion);

Expand All @@ -135,28 +160,13 @@ - (BOOL)initialiseDatabase {
[alert setMessageText:NSLocalizedString(@"Database Upgrade", nil)];
[alert setInformativeText:NSLocalizedString(@"Vienna must upgrade its database to the latest version. This may take a minute or so. We apologize for the inconvenience.", nil)];
[alert addButtonWithTitle:NSLocalizedString(@"Upgrade Database", @"Title of a button on an alert")];
[alert addButtonWithTitle:NSLocalizedString(@"Quit Vienna", @"Title of a button on an alert")];
[alert addButtonWithTitle:NSLocalizedString(@"Quit Vienna", @"Button to quit Vienna after a database check")];
NSInteger modalReturn = [alert runModal];
if (modalReturn == NSAlertSecondButtonReturn) {
return NO;
}

// Back up the database before any upgrade.
NSFileManager *fileManager = NSFileManager.defaultManager;
NSString *databaseBackupPath = [[Database databasePath] stringByAppendingPathExtension:@"bak"];
NSError *error = nil;
if ([fileManager fileExistsAtPath:databaseBackupPath]) {
[fileManager removeItemAtPath:databaseBackupPath
error:&error];
}
[fileManager copyItemAtPath:[Database databasePath]
toPath:databaseBackupPath
error:&error];

// Log the error if the backup creation failed, but continue regardless.
if (error) {
NSLog(@"Database backup could not created: %@", error.localizedDescription);
}
[self backupDatabase];

[self.databaseQueue inDatabase:^(FMDatabase *db) {
// Migrate the database to the newest version
Expand Down Expand Up @@ -187,6 +197,26 @@ - (BOOL)initialiseDatabase {
return NO;
}

-(void)backupDatabase {
// Back up the database (before any upgrade or if an anomaly has been detected).
NSFileManager *fileManager = NSFileManager.defaultManager;
NSString *databaseBackupPath = [[Database databasePath] stringByAppendingPathExtension:@"bak"];
NSError *error = nil;
if ([fileManager fileExistsAtPath:databaseBackupPath]) {
[fileManager removeItemAtPath:databaseBackupPath
error:&error];
}
[fileManager copyItemAtPath:[Database databasePath]
toPath:databaseBackupPath
error:&error];

// Log the error if the backup creation failed, but continue regardless.
if (error) {
NSLog(@"Database backup could not created: %@", error.localizedDescription);
}
}


/*!
* sets up an inital Vienna database at the given path
* TODO: put this into some Swift file to free VNACriteriaOperator enum from Objective-C legacy
Expand Down