Skip to content
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ _Note: Any product changes which touch native code (e.g. modifying your `AppDele

## Supported React Native platforms

- iOS (7+)
- iOS (15.5+)
- Android (4.1+) on TLS 1.2 compatible devices
- Windows (UWP) - Not actively tested

Expand Down
42 changes: 42 additions & 0 deletions ios/CodePush/CodePush.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#import "CodePush.h"

@interface CodePush () <RCTBridgeModule, RCTFrameUpdateObserver>
+ (BOOL)rollbackFailedPendingUpdate;
@end

@implementation CodePush {
Expand Down Expand Up @@ -183,6 +184,13 @@ + (NSURL *)bundleURLForResource:(NSString *)resourceName
NSString *packageAppVersion = [currentPackageMetadata objectForKey:AppVersionKey];

if ([[CodePushUpdateUtils modifiedDateStringOfFileAtURL:binaryBundleURL] isEqualToString:packageDate] && ([CodePush isUsingTestConfiguration] ||[binaryAppVersion isEqualToString:packageAppVersion])) {
if ([self rollbackFailedPendingUpdate]) {
return [self bundleURLForResource:resourceName
withExtension:resourceExtension
subdirectory:resourceSubdirectory
bundle:resourceBundle];
}

// Return package file because it is newer than the app store binary's JS bundle
NSURL *packageUrl = [[NSURL alloc] initFileURLWithPath:packageFile];
CPLog(logMessageFormat, packageUrl);
Expand Down Expand Up @@ -417,6 +425,40 @@ - (void)initializeUpdateAfterRestart
}
}

/*
* Rolls back a pending update that already failed a previous launch before returning
* its bundle URL to React Native.
*/
+ (BOOL)rollbackFailedPendingUpdate
{
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
NSDictionary *pendingUpdate = [preferences objectForKey:PendingUpdateKey];
if (!pendingUpdate || ![pendingUpdate[PendingUpdateIsLoadingKey] boolValue]) {
return NO;
}

CPLog(@"Update did not finish loading the last time, rolling back to a previous version.");
needToReportRollback = YES;

NSError *error;
NSDictionary *failedPackage = [CodePushPackage getCurrentPackage:&error];
if (!failedPackage) {
if (error) {
CPLog(@"Error getting current update metadata during rollback: %@", error);
} else {
CPLog(@"Attempted to perform a rollback when there is no current update");
}
} else if (![self isFailedHash:[failedPackage objectForKey:PackageHashKey]]) {
NSArray *failedUpdates = [preferences objectForKey:FailedUpdatesKey];
failedUpdates = failedUpdates ? [failedUpdates arrayByAddingObject:failedPackage] : @[failedPackage];
[preferences setObject:failedUpdates forKey:FailedUpdatesKey];
}

[CodePushPackage rollbackPackage];
[self removePendingUpdate];
return YES;
}

/*
* This method is used to get information about the latest rollback.
* This information will be used to decide whether the application
Expand Down
Loading
Loading