More robust against exceptions and a few other fixes.
This commit is contained in:
parent
bb97e8f3e8
commit
85dab50996
2
External/Pearl
vendored
2
External/Pearl
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 717bc5e5e7be3aedb997581260b67579eb651f8e
|
Subproject commit 3c7b13b3649c92f7d30e4b8bd0570c8c6b1798c6
|
@ -32,6 +32,13 @@ fi
|
|||||||
|
|
||||||
### DEPENDENCIES
|
### DEPENDENCIES
|
||||||
|
|
||||||
|
digest() {
|
||||||
|
if hash xxd 2>/dev/null; then
|
||||||
|
openssl sha1 -binary < "$1" | xxd -p
|
||||||
|
else
|
||||||
|
openssl sha1 < "$1" | sed 's/.* //'
|
||||||
|
fi
|
||||||
|
}
|
||||||
fetch() {
|
fetch() {
|
||||||
if hash wget 2>/dev/null; then
|
if hash wget 2>/dev/null; then
|
||||||
wget -O "${1##*/}" "$1"
|
wget -O "${1##*/}" "$1"
|
||||||
@ -54,7 +61,7 @@ unpack() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
printf 'Verifying package: %s, against digest: %s...' "$1" "$2"
|
printf 'Verifying package: %s, against digest: %s...' "$1" "$2"
|
||||||
[[ $(openssl sha < "$1") = $2 ]] || {
|
[[ $(digest "$1") = $2 ]] || {
|
||||||
printf ' mismatch!\n'
|
printf ' mismatch!\n'
|
||||||
echo 2>&1 "Downloaded package doesn't match digest."
|
echo 2>&1 "Downloaded package doesn't match digest."
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -56,7 +56,11 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
|||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
[mainManagedObjectContext performBlock:^{
|
[mainManagedObjectContext performBlock:^{
|
||||||
mocBlock( mainManagedObjectContext );
|
@try {
|
||||||
|
mocBlock( mainManagedObjectContext );
|
||||||
|
} @catch (NSException *exception) {
|
||||||
|
err( @"While performing managed block:\n%@", [exception fullDescription] );
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
@ -69,7 +73,12 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
|||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
[mainManagedObjectContext performBlockAndWait:^{
|
[mainManagedObjectContext performBlockAndWait:^{
|
||||||
mocBlock( mainManagedObjectContext );
|
@try {
|
||||||
|
mocBlock( mainManagedObjectContext );
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
err( @"While performing managed block:\n%@", [exception fullDescription] );
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
@ -84,7 +93,12 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
|||||||
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||||
moc.parentContext = privateManagedObjectContextIfReady;
|
moc.parentContext = privateManagedObjectContextIfReady;
|
||||||
[moc performBlock:^{
|
[moc performBlock:^{
|
||||||
mocBlock( moc );
|
@try {
|
||||||
|
mocBlock( moc );
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
err( @"While performing managed block:\n%@", [exception fullDescription] );
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
@ -99,7 +113,12 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
|||||||
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||||
moc.parentContext = privateManagedObjectContextIfReady;
|
moc.parentContext = privateManagedObjectContextIfReady;
|
||||||
[moc performBlockAndWait:^{
|
[moc performBlockAndWait:^{
|
||||||
mocBlock( moc );
|
@try {
|
||||||
|
mocBlock( moc );
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
err( @"While performing managed block:\n%@", [exception fullDescription] );
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
@ -195,7 +214,12 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
|
|||||||
^(NSNotification *note) {
|
^(NSNotification *note) {
|
||||||
// When privateManagedObjectContext is saved, import the changes into mainManagedObjectContext.
|
// When privateManagedObjectContext is saved, import the changes into mainManagedObjectContext.
|
||||||
[self.mainManagedObjectContext performBlock:^{
|
[self.mainManagedObjectContext performBlock:^{
|
||||||
[self.mainManagedObjectContext mergeChangesFromContextDidSaveNotification:note];
|
@try {
|
||||||
|
[self.mainManagedObjectContext mergeChangesFromContextDidSaveNotification:note];
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
err( @"While merging changes:\n%@", [exception fullDescription] );
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
}
|
}
|
||||||
@catch (NSException *exception) {
|
@catch (NSException *exception) {
|
||||||
success = NO;
|
success = NO;
|
||||||
err( @"While saving: %@", exception );
|
err( @"While saving: %@", [exception fullDescription] );
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
@ -128,10 +128,15 @@
|
|||||||
|
|
||||||
- (NSString *)debugDescription {
|
- (NSString *)debugDescription {
|
||||||
|
|
||||||
return strf( @"{%@: name=%@, user=%@, type=%lu, uses=%ld, lastUsed=%@, version=%ld, loginName=%@, requiresExplicitMigration=%d}",
|
@try {
|
||||||
NSStringFromClass( [self class] ), self.name, self.user.name, (long)self.type, (long)self.uses, self.lastUsed,
|
return strf( @"{%@: name=%@, user=%@, type=%lu, uses=%ld, lastUsed=%@, version=%ld, loginName=%@, requiresExplicitMigration=%d}",
|
||||||
(long)self.version,
|
NSStringFromClass( [self class] ), self.name, self.user.name, (long)self.type, (long)self.uses, self.lastUsed,
|
||||||
self.loginName, self.requiresExplicitMigration );
|
(long)self.version,
|
||||||
|
self.loginName, self.requiresExplicitMigration );
|
||||||
|
} @catch (NSException *exception) {
|
||||||
|
return strf( @"{%@: inaccessible: %@}",
|
||||||
|
NSStringFromClass( [self class] ), [exception fullDescription] );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)tryMigrateExplicitly:(BOOL)explicit {
|
- (BOOL)tryMigrateExplicitly:(BOOL)explicit {
|
||||||
|
@ -257,8 +257,11 @@
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||||
[context deleteObject:[self siteInContext:context]];
|
MPSiteEntity *site_ = [self siteInContext:context];
|
||||||
[context saveToStore];
|
if (site_) {
|
||||||
|
[context deleteObject:site_];
|
||||||
|
[context saveToStore];
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
} cancelTitle:@"Cancel" destructiveTitle:@"Delete Site" otherTitles:nil];
|
} cancelTitle:@"Cancel" destructiveTitle:@"Delete Site" otherTitles:nil];
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
|||||||
self.view.backgroundColor = [UIColor clearColor];
|
self.view.backgroundColor = [UIColor clearColor];
|
||||||
[self.passwordCollectionView automaticallyAdjustInsetsForKeyboard];
|
[self.passwordCollectionView automaticallyAdjustInsetsForKeyboard];
|
||||||
self.passwordsSearchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
|
self.passwordsSearchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
|
||||||
if ([self.passwordsSearchBar respondsToSelector:@selector(keyboardAppearance)])
|
if ([self.passwordsSearchBar respondsToSelector:@selector( keyboardAppearance )])
|
||||||
self.passwordsSearchBar.keyboardAppearance = UIKeyboardAppearanceDark;
|
self.passwordsSearchBar.keyboardAppearance = UIKeyboardAppearanceDark;
|
||||||
else
|
else
|
||||||
[self.passwordsSearchBar enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
[self.passwordsSearchBar enumerateViews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
||||||
@ -170,23 +170,29 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
|||||||
forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
|
forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
|
||||||
|
|
||||||
if (controller == _fetchedResultsController) {
|
if (controller == _fetchedResultsController) {
|
||||||
[self.passwordCollectionView performBatchUpdates:^{
|
@try {
|
||||||
[self fetchedItemsDidUpdate];
|
[self.passwordCollectionView performBatchUpdates:^{
|
||||||
switch (type) {
|
[self fetchedItemsDidUpdate];
|
||||||
case NSFetchedResultsChangeInsert:
|
switch (type) {
|
||||||
[self.passwordCollectionView insertItemsAtIndexPaths:@[ newIndexPath ]];
|
case NSFetchedResultsChangeInsert:
|
||||||
break;
|
[self.passwordCollectionView insertItemsAtIndexPaths:@[ newIndexPath ]];
|
||||||
case NSFetchedResultsChangeDelete:
|
break;
|
||||||
[self.passwordCollectionView deleteItemsAtIndexPaths:@[ indexPath ]];
|
case NSFetchedResultsChangeDelete:
|
||||||
break;
|
[self.passwordCollectionView deleteItemsAtIndexPaths:@[ indexPath ]];
|
||||||
case NSFetchedResultsChangeMove:
|
break;
|
||||||
[self.passwordCollectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath];
|
case NSFetchedResultsChangeMove:
|
||||||
break;
|
[self.passwordCollectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath];
|
||||||
case NSFetchedResultsChangeUpdate:
|
break;
|
||||||
[self.passwordCollectionView reloadItemsAtIndexPaths:@[ indexPath ]];
|
case NSFetchedResultsChangeUpdate:
|
||||||
break;
|
[self.passwordCollectionView reloadItemsAtIndexPaths:@[ indexPath ]];
|
||||||
}
|
break;
|
||||||
} completion:nil];
|
}
|
||||||
|
} completion:nil];
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
wrn( @"While updating password cells: %@", [exception fullDescription] );
|
||||||
|
[self.passwordCollectionView reloadData];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,7 +255,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
|||||||
if (searchBar == self.passwordsSearchBar) {
|
if (searchBar == self.passwordsSearchBar) {
|
||||||
if ([self.query length] && [[self.query stringByTrimmingCharactersInSet:_siteNameAcceptableCharactersSet] length])
|
if ([self.query length] && [[self.query stringByTrimmingCharactersInSet:_siteNameAcceptableCharactersSet] length])
|
||||||
[self showTips:MPPasswordsBadNameTip];
|
[self showTips:MPPasswordsBadNameTip];
|
||||||
|
|
||||||
[self updatePasswords];
|
[self updatePasswords];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,7 +267,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
|||||||
[UIView animateWithDuration:0.3f animations:^{
|
[UIView animateWithDuration:0.3f animations:^{
|
||||||
if (showTips & MPPasswordsBadNameTip)
|
if (showTips & MPPasswordsBadNameTip)
|
||||||
self.badNameTipContainer.alpha = 1;
|
self.badNameTipContainer.alpha = 1;
|
||||||
} completion:^(BOOL finished) {
|
} completion:^(BOOL finished) {
|
||||||
if (finished)
|
if (finished)
|
||||||
PearlMainQueueAfter( 5, ^{
|
PearlMainQueueAfter( 5, ^{
|
||||||
[UIView animateWithDuration:0.3f animations:^{
|
[UIView animateWithDuration:0.3f animations:^{
|
||||||
@ -375,28 +381,34 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
|
|||||||
if (![self.fetchedResultsController performFetch:&error])
|
if (![self.fetchedResultsController performFetch:&error])
|
||||||
err( @"Couldn't fetch sites: %@", [error fullDescription] );
|
err( @"Couldn't fetch sites: %@", [error fullDescription] );
|
||||||
|
|
||||||
[self.passwordCollectionView performBatchUpdates:^{
|
@try {
|
||||||
[self fetchedItemsDidUpdate];
|
[self.passwordCollectionView performBatchUpdates:^{
|
||||||
|
[self fetchedItemsDidUpdate];
|
||||||
|
|
||||||
NSInteger fromSections = self.passwordCollectionView.numberOfSections;
|
NSInteger fromSections = self.passwordCollectionView.numberOfSections;
|
||||||
NSInteger toSections = [self numberOfSectionsInCollectionView:self.passwordCollectionView];
|
NSInteger toSections = [self numberOfSectionsInCollectionView:self.passwordCollectionView];
|
||||||
for (NSInteger section = 0; section < MAX( toSections, fromSections ); ++section) {
|
for (NSInteger section = 0; section < MAX( toSections, fromSections ); ++section) {
|
||||||
if (section >= fromSections)
|
if (section >= fromSections)
|
||||||
[self.passwordCollectionView insertSections:[NSIndexSet indexSetWithIndex:section]];
|
[self.passwordCollectionView insertSections:[NSIndexSet indexSetWithIndex:section]];
|
||||||
else if (section >= toSections)
|
else if (section >= toSections)
|
||||||
[self.passwordCollectionView deleteSections:[NSIndexSet indexSetWithIndex:section]];
|
[self.passwordCollectionView deleteSections:[NSIndexSet indexSetWithIndex:section]];
|
||||||
else if (section < [oldSections count])
|
else if (section < [oldSections count])
|
||||||
[self.passwordCollectionView reloadItemsFromArray:oldSections[section]
|
[self.passwordCollectionView reloadItemsFromArray:oldSections[section]
|
||||||
toArray:[[self.fetchedResultsController sections][section] objects]
|
toArray:[[self.fetchedResultsController sections][section] objects]
|
||||||
inSection:section];
|
inSection:section];
|
||||||
else
|
else
|
||||||
[self.passwordCollectionView reloadSections:[NSIndexSet indexSetWithIndex:section]];
|
[self.passwordCollectionView reloadSections:[NSIndexSet indexSetWithIndex:section]];
|
||||||
}
|
}
|
||||||
} completion:^(BOOL finished) {
|
} completion:^(BOOL finished) {
|
||||||
if (finished)
|
if (finished)
|
||||||
[self.passwordCollectionView setContentOffset:CGPointMake( 0, -self.passwordCollectionView.contentInset.top )
|
[self.passwordCollectionView setContentOffset:CGPointMake( 0, -self.passwordCollectionView.contentInset.top )
|
||||||
animated:YES];
|
animated:YES];
|
||||||
}];
|
}];
|
||||||
|
}
|
||||||
|
@catch (NSException *exception) {
|
||||||
|
wrn( @"While updating password cells: %@", [exception fullDescription] );
|
||||||
|
[self.passwordCollectionView reloadData];
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user