iOS implementation of getUpdateMetadata

This commit is contained in:
Jonathan Carter
2016-04-15 15:24:22 -07:00
parent bd09373c37
commit 3086aeae08
6 changed files with 95 additions and 54 deletions

View File

@@ -100,12 +100,16 @@ const getConfiguration = (() => {
})();
async function getCurrentPackage() {
const localPackage = await NativeCodePush.getCurrentPackage();
if (localPackage) {
localPackage.failedInstall = await NativeCodePush.isFailedUpdate(localPackage.packageHash);
localPackage.isFirstRun = await NativeCodePush.isFirstRun(localPackage.packageHash);
return await getUpdateMetadata(CodePush.UpdateState.LATEST);
}
async function getUpdateMetadata(updateState) {
const updateMetadata = await NativeCodePush.getUpdateMetadata(updateState || CodePush.UpdateState.RUNNING);
if (updateMetadata) {
updateMetadata.failedInstall = await NativeCodePush.isFailedUpdate(updateMetadata.packageHash);
updateMetadata.isFirstRun = await NativeCodePush.isFirstRun(updateMetadata.packageHash);
}
return localPackage;
return updateMetadata;
}
function getPromisifiedSdk(requestFetchAdapter, config) {
@@ -388,9 +392,11 @@ if (NativeCodePush) {
checkForUpdate,
getConfiguration,
getCurrentPackage,
getUpdateMetadata,
log,
notifyApplicationReady,
restartApp,
restartApplication: restartApp,
setUpTestDependencies,
sync,
InstallMode: {
@@ -409,6 +415,11 @@ if (NativeCodePush) {
SYNC_IN_PROGRESS: 7, // There is an ongoing "sync" operation in progress.
UNKNOWN_ERROR: -1
},
UpdateState: {
RUNNING: NativeCodePush.codePushUpdateStateRunning,
PENDING: NativeCodePush.codePushUpdateStatePending,
LATEST: NativeCodePush.codePushUpdateStateLatest
},
DEFAULT_UPDATE_DIALOG: {
appendReleaseDescription: false,
descriptionPrefix: " Description: ",
@@ -424,4 +435,4 @@ if (NativeCodePush) {
log("The CodePush module doesn't appear to be properly installed. Please double-check that everything is setup correctly.");
}
module.exports = CodePush;
module.exports = CodePush;

View File

@@ -10,6 +10,7 @@
13BE3DEE1AC21097009241FE /* CodePush.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* CodePush.m */; };
1B23B9141BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */; };
1B762E901C9A5E9A006EF800 /* CodePushErrorUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B762E8F1C9A5E9A006EF800 /* CodePushErrorUtils.m */; };
1BCC09A71CC19EB700DDC0DD /* RCTConvert+CodePushUpdateState.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BCC09A61CC19EB700DDC0DD /* RCTConvert+CodePushUpdateState.m */; };
540D20121C7684FE00D6EF41 /* CodePushUpdateUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 540D20111C7684FE00D6EF41 /* CodePushUpdateUtils.m */; };
5421FE311C58AD5A00986A55 /* CodePushTelemetryManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5421FE301C58AD5A00986A55 /* CodePushTelemetryManager.m */; };
54A0026C1C0E2880004C3CEC /* aescrypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0024C1C0E2880004C3CEC /* aescrypt.c */; };
@@ -49,6 +50,7 @@
13BE3DED1AC21097009241FE /* CodePush.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CodePush.m; path = CodePush/CodePush.m; sourceTree = "<group>"; };
1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "RCTConvert+CodePushInstallMode.m"; path = "CodePush/RCTConvert+CodePushInstallMode.m"; sourceTree = "<group>"; };
1B762E8F1C9A5E9A006EF800 /* CodePushErrorUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CodePushErrorUtils.m; path = CodePush/CodePushErrorUtils.m; sourceTree = "<group>"; };
1BCC09A61CC19EB700DDC0DD /* RCTConvert+CodePushUpdateState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "RCTConvert+CodePushUpdateState.m"; path = "CodePush/RCTConvert+CodePushUpdateState.m"; sourceTree = "<group>"; };
540D20111C7684FE00D6EF41 /* CodePushUpdateUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CodePushUpdateUtils.m; path = CodePush/CodePushUpdateUtils.m; sourceTree = "<group>"; };
5421FE301C58AD5A00986A55 /* CodePushTelemetryManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CodePushTelemetryManager.m; path = CodePush/CodePushTelemetryManager.m; sourceTree = "<group>"; };
54A0024A1C0E2880004C3CEC /* aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes.h; sourceTree = "<group>"; };
@@ -168,16 +170,17 @@
58B511D21A9E6C8500147676 = {
isa = PBXGroup;
children = (
54A002481C0E2880004C3CEC /* SSZipArchive */,
1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */,
13BE3DEC1AC21097009241FE /* CodePush.h */,
13BE3DED1AC21097009241FE /* CodePush.m */,
81D51F391B6181C2000DA084 /* CodePushConfig.m */,
54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */,
1B762E8F1C9A5E9A006EF800 /* CodePushErrorUtils.m */,
810D4E6C1B96935000B397E9 /* CodePushPackage.m */,
5421FE301C58AD5A00986A55 /* CodePushTelemetryManager.m */,
540D20111C7684FE00D6EF41 /* CodePushUpdateUtils.m */,
13BE3DEC1AC21097009241FE /* CodePush.h */,
13BE3DED1AC21097009241FE /* CodePush.m */,
1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */,
1BCC09A61CC19EB700DDC0DD /* RCTConvert+CodePushUpdateState.m */,
54A002481C0E2880004C3CEC /* SSZipArchive */,
134814211AA4EA7D00B7C361 /* Products */,
);
sourceTree = "<group>";
@@ -242,6 +245,7 @@
540D20121C7684FE00D6EF41 /* CodePushUpdateUtils.m in Sources */,
54A0026E1C0E2880004C3CEC /* aestab.c in Sources */,
54A002761C0E2880004C3CEC /* mztools.c in Sources */,
1BCC09A71CC19EB700DDC0DD /* RCTConvert+CodePushUpdateState.m in Sources */,
54A002781C0E2880004C3CEC /* zip.c in Sources */,
54A002791C0E2880004C3CEC /* SSZipArchive.m in Sources */,
1B23B9141BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m in Sources */,

View File

@@ -84,6 +84,7 @@ failCallback:(void (^)(NSError *err))failCallback;
+ (NSString *)getBinaryAssetsPath;
+ (NSDictionary *)getCurrentPackage:(NSError **)error;
+ (NSDictionary *)getPreviousPackage:(NSError **)error;
+ (NSString *)getCurrentPackageFolderPath:(NSError **)error;
+ (NSString *)getCurrentPackageBundlePath:(NSError **)error;
+ (NSString *)getCurrentPackageHash:(NSError **)error;
@@ -140,4 +141,10 @@ typedef NS_ENUM(NSInteger, CodePushInstallMode) {
CodePushInstallModeImmediate,
CodePushInstallModeOnNextRestart,
CodePushInstallModeOnNextResume
};
typedef NS_ENUM(NSInteger, CodePushUpdateState) {
CodePushUpdateStateRunning,
CodePushUpdateStatePending,
CodePushUpdateStateLatest
};

View File

@@ -180,12 +180,16 @@ static NSString *bundleResourceName = @"main";
*/
- (NSDictionary *)constantsToExport
{
// Export the values of the CodePushInstallMode enum
// so that the script-side can easily stay in sync
// Export the values of the CodePushInstallMode and CodePushUpdateState
// enums so that the script-side can easily stay in sync
return @{
@"codePushInstallModeOnNextRestart":@(CodePushInstallModeOnNextRestart),
@"codePushInstallModeImmediate": @(CodePushInstallModeImmediate),
@"codePushInstallModeOnNextResume": @(CodePushInstallModeOnNextResume)
@"codePushInstallModeOnNextResume": @(CodePushInstallModeOnNextResume),
@"codePushUpdateStateRunning": @(CodePushUpdateStateRunning),
@"codePushUpdateStatePending": @(CodePushUpdateStatePending),
@"codePushUpdateStateLatest": @(CodePushUpdateStateLatest)
};
};
@@ -532,35 +536,49 @@ RCT_EXPORT_METHOD(getConfiguration:(RCTPromiseResolveBlock)resolve
}
/*
* This method is the native side of the CodePush.getCurrentPackage method.
* This method is the native side of the CodePush.getUpdateMetadata method.
*/
RCT_EXPORT_METHOD(getCurrentPackage:(RCTPromiseResolveBlock)resolve
RCT_EXPORT_METHOD(getUpdateMetadata:(CodePushUpdateState)updateState
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
NSError *error;
NSMutableDictionary *package = [[CodePushPackage getCurrentPackage:&error] mutableCopy];
if (error) {
reject([NSString stringWithFormat: @"%lu", (long)error.code], error.localizedDescription, error);
return;
return reject([NSString stringWithFormat: @"%lu", (long)error.code], error.localizedDescription, error);
} else if (package == nil) {
// The app hasn't downloaded any CodePush updates yet,
// so we simply return nil regardless if the user
// wanted to retrieve the pending or running update.
return resolve(nil);
}
// We have a CodePush update, so let's see if it's currently in a pending state.
BOOL currentUpdateIsPending = [self isPendingUpdate:[package objectForKey:PackageHashKey]];
if (updateState == CodePushUpdateStatePending && !currentUpdateIsPending) {
// The caller wanted a pending update
// but there isn't currently one.
resolve(nil);
return;
} else if (updateState == CodePushUpdateStateRunning && currentUpdateIsPending) {
// The caller wants the running update, but the current
// one is pending, so we need to grab the previous.
resolve([CodePushPackage getPreviousPackage:nil]);
} else {
// The current package satisfies the request:
// 1) Caller wanted a pending, and there is a pending update
// 2) Caller wanted the running update, and there isn't a pending
// 3) Calers wants the latest update, regardless if it's pending or not
if (isRunningBinaryVersion) {
// This only matters in Debug builds. Since we do not clear "outdated" updates,
// we need to indicate to the JS side that somehow we have a current update on
// disk that is not actually running.
[package setObject:@(YES) forKey:@"_isDebugOnly"];
}
resolve(package);
}
if (isRunningBinaryVersion) {
// This only matters in Debug builds. Since we do not clear "outdated" updates,
// we need to indicate to the JS side that somehow we have a current update on
// disk that is not actually running.
[package setObject:@(YES) forKey:@"_isDebugOnly"];
}
// Add the "isPending" virtual property to the package at this point, so that
// the script-side doesn't need to immediately call back into native to populate it.
BOOL isPendingUpdate = [self isPendingUpdate:[package objectForKey:PackageHashKey]];
[package setObject:@(isPendingUpdate) forKey:PackageIsPendingKey];
resolve(package);
}
/*

View File

@@ -17,7 +17,6 @@ static NSString *const UnzippedFolderName = @"unzipped";
+ (void)clearUpdates
{
[[NSFileManager defaultManager] removeItemAtPath:[self getCodePushPath] error:nil];
[[NSFileManager defaultManager] removeItemAtPath:[self getStatusFilePath] error:nil];
}
+ (void)downloadAndReplaceCurrentBundle:(NSString *)remoteBundleUrl
@@ -290,27 +289,8 @@ static NSString *const UnzippedFolderName = @"unzipped";
+ (NSDictionary *)getCurrentPackage:(NSError **)error
{
NSString *folderPath = [CodePushPackage getCurrentPackageFolderPath:error];
if (!*error) {
if (!folderPath) {
return nil;
}
NSString *packagePath = [folderPath stringByAppendingPathComponent:@"app.json"];
NSString *content = [NSString stringWithContentsOfFile:packagePath
encoding:NSUTF8StringEncoding
error:error];
if (!*error) {
NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary* jsonDict = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:error];
return jsonDict;
}
}
return nil;
NSString *packageHash = [CodePushPackage getCurrentPackageHash:error];
return [CodePushPackage getPackage:packageHash error:error];
}
+ (NSString *)getCurrentPackageBundlePath:(NSError **)error
@@ -423,6 +403,12 @@ static NSString *const UnzippedFolderName = @"unzipped";
return [[self getCodePushPath] stringByAppendingPathComponent:packageHash];
}
+ (NSDictionary *)getPreviousPackage:(NSError **)error
{
NSString *packageHash = [CodePushPackage getPreviousPackageHash:error];
return [CodePushPackage getPackage:packageHash error:error];
}
+ (NSString *)getPreviousPackageHash:(NSError **)error
{
NSDictionary *info = [self getCurrentPackageInfo:error];

View File

@@ -0,0 +1,15 @@
#import "CodePush.h"
#import "RCTConvert.h"
// Extending the RCTConvert class allows the React Native
// bridge to handle args of type "CodePushUpdateState"
@implementation RCTConvert (CodePushUpdateState)
RCT_ENUM_CONVERTER(CodePushUpdateState, (@{ @"codePushUpdateStateRunning": @(CodePushUpdateStateRunning),
@"codePushUpdateStatePending": @(CodePushUpdateStatePending),
@"codePushUpdateStateLatest": @(CodePushUpdateStateLatest)
}),
CodePushUpdateStateRunning, // Default enum value
integerValue)
@end