Skip to content
This repository was archived by the owner on May 20, 2025. It is now read-only.

Commit f890664

Browse files
author
Will Anderson
committed
Start refactoring package management into a distinct class
1 parent 777b9b6 commit f890664

File tree

6 files changed

+187
-71
lines changed

6 files changed

+187
-71
lines changed

CodePush.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,17 @@
2525

2626
+ (NSDictionary *)getConfiguration;
2727

28+
@end
29+
30+
@interface CodePushPackage : NSObject
31+
32+
+ (NSString *)getCurrentPackageFolderPath:(NSError **)error;
33+
34+
+ (NSString *)getPackageFolderPath:(NSString *)packageHash;
35+
36+
+ (void)downloadPackage:(NSDictionary *)updatePackage
37+
error:(NSError **)error;
38+
39+
+ (void)applyPackage:(NSString *)packageHash;
40+
2841
@end

CodePush.ios.js

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55

66
'use strict';
77

8+
var extend = require("extend");
89
var NativeCodePush = require('react-native').NativeModules.CodePush;
910
var requestFetchAdapter = require("./request-fetch-adapter.js");
1011
var Sdk = require("code-push/script/acquisition-sdk").AcquisitionManager;
12+
var packageMixins = require("./package-mixins")(NativeCodePush);
1113

1214
// This function is only used for tests. Replaces the default SDK, configuration and native bridge
1315
function setUpTestDependencies(testSdk, testConfiguration, testNativeBridge){
@@ -67,18 +69,12 @@ function checkForUpdate() {
6769
return new Promise((resolve, reject) => {
6870
sdk.queryUpdateWithCurrentPackage(queryPackage, (err, update) => {
6971
if (err) return reject(err);
70-
resolve(update);
72+
resolve(extend({}, update, packageMixins.remote));
7173
});
7274
});
7375
});
7476
}
7577

76-
function download(updatePackage) {
77-
// Use the downloaded package info. Native code will save the package info
78-
// so that the client knows what the current package version is.
79-
return NativeCodePush.downloadUpdate(updatePackage);
80-
}
81-
8278
function apply(updatePackage) {
8379
return NativeCodePush.applyUpdate(updatePackage);
8480
}
@@ -94,7 +90,6 @@ function notifyApplicationReady() {
9490
var CodePush = {
9591
getConfiguration: getConfiguration,
9692
checkForUpdate: checkForUpdate,
97-
download: download,
9893
apply: apply,
9994
getCurrentPackage: getCurrentPackage,
10095
notifyApplicationReady: notifyApplicationReady,

CodePush.m

Lines changed: 33 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,39 @@ @implementation CodePush
1414

1515
@synthesize bridge = _bridge;
1616

17-
+ (NSString *) getBundleFolderPath
18-
{
19-
NSString* home = NSHomeDirectory();
20-
NSString* pathExtension = [[@"CodePush/" stringByAppendingString: (usingTestFolder ? @"test/" : @"")] stringByAppendingString: @"bundle"];
21-
NSString* bundleFolder = [home stringByAppendingPathComponent:pathExtension];
22-
return bundleFolder;
23-
}
24-
2517
+ (NSString *) getBundlePath
2618
{
27-
NSString * bundleFolderPath = [self getBundleFolderPath];
19+
NSString * bundleFolderPath = [self getPackageFolderPath];
2820
NSString* appBundleName = @"main.jsbundle";
2921
return [bundleFolderPath stringByAppendingPathComponent:appBundleName];
3022
}
3123

3224
+ (NSString *) getPackageFolderPath
3325
{
3426
NSString* home = NSHomeDirectory();
35-
NSString* pathExtension = [[@"CodePush/" stringByAppendingString: (usingTestFolder ? @"test/" : @"")] stringByAppendingString: @"package"];
27+
NSString* pathExtension = [[@"CodePush/" stringByAppendingString: (usingTestFolder ? @"test/" : @"")] stringByAppendingString: @"currentPackage"];
28+
NSString* packageFolder = [home stringByAppendingPathComponent:pathExtension];
29+
return packageFolder;
30+
}
31+
32+
+ (NSString *) getPreviousPackageFolderPath
33+
{
34+
NSString* home = NSHomeDirectory();
35+
NSString* pathExtension = [[@"CodePush/" stringByAppendingString: (usingTestFolder ? @"test/" : @"")] stringByAppendingString: @"previous"];
3636
NSString* packageFolder = [home stringByAppendingPathComponent:pathExtension];
3737
return packageFolder;
3838
}
3939

4040
+ (NSString *) getPackagePath
4141
{
42-
NSString * packageFolderPath = [self getPackageFolderPath];
42+
NSString *packageFolderPath = [self getPackageFolderPath];
43+
NSString* appPackageName = @"localpackage.json";
44+
return [packageFolderPath stringByAppendingPathComponent:appPackageName];
45+
}
46+
47+
+ (NSString *) getPreviousPackagePath
48+
{
49+
NSString * packageFolderPath = [self getPreviousPackageFolderPath];
4350
NSString* appPackageName = @"localpackage.json";
4451
return [packageFolderPath stringByAppendingPathComponent:appPackageName];
4552
}
@@ -86,67 +93,31 @@ + (void) loadBundle:(NSString*)rootComponent
8693
resolve([CodePushConfig getConfiguration]);
8794
}
8895

89-
RCT_EXPORT_METHOD(installUpdate:(NSDictionary*)updatePackage
96+
RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage
9097
resolver:(RCTPromiseResolveBlock)resolve
9198
rejecter:(RCTPromiseRejectBlock)reject)
9299
{
93100
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
94-
NSURL* url = [NSURL URLWithString:updatePackage[@"downloadUrl"]];
95101
NSError *err;
96-
97-
NSString *updateContents = [[NSString alloc] initWithContentsOfURL:url
98-
encoding:NSUTF8StringEncoding
99-
error:&err];
100-
if (err) {
101-
// TODO send download url
102-
return reject(err);
103-
}
102+
[CodePushPackage downloadPackage:updatePackage
103+
error:&err];
104104

105-
dispatch_async(dispatch_get_main_queue(), ^{
106-
NSError *saveError;
107-
NSString *bundleFolderPath = [CodePush getBundleFolderPath];
108-
if (![[NSFileManager defaultManager] fileExistsAtPath:bundleFolderPath]) {
109-
[[NSFileManager defaultManager] createDirectoryAtPath:bundleFolderPath withIntermediateDirectories:YES attributes:nil error:&saveError];
110-
}
111-
112-
[updateContents writeToFile:[CodePush getBundlePath]
113-
atomically:YES
114-
encoding:NSUTF8StringEncoding
115-
error:&saveError];
116-
if (saveError) {
117-
// TODO send file path
118-
return reject(saveError);
119-
}
120-
121-
// Save the package info too.
122-
NSString *packageFolderPath = [CodePush getPackageFolderPath];
123-
if (![[NSFileManager defaultManager] fileExistsAtPath:packageFolderPath]) {
124-
[[NSFileManager defaultManager] createDirectoryAtPath:packageFolderPath withIntermediateDirectories:YES attributes:nil error:&saveError];
125-
}
126-
127-
NSError *updateSerializeError;
128-
NSData *updateSerializedData = [NSJSONSerialization dataWithJSONObject:updatePackage options:0 error:&updateSerializeError];
129-
130-
if (updateSerializeError) {
131-
return reject(updateSerializeError);
132-
}
133-
134-
NSString *packageJsonString = [[NSString alloc] initWithData:updateSerializedData encoding:NSUTF8StringEncoding];
135-
[packageJsonString writeToFile:[CodePush getPackagePath]
136-
atomically:YES
137-
encoding:NSUTF8StringEncoding
138-
error:&saveError];
139-
140-
if (saveError) {
141-
return reject(saveError);
142-
}
143-
144-
[CodePush loadBundle:[CodePushConfig getRootComponent]];
105+
if (err) {
106+
reject(err);
107+
} else {
145108
resolve([NSNull null]);
146-
});
109+
}
147110
});
148111
}
149112

113+
RCT_EXPORT_METHOD(applyUpdate:(NSDictionary*)updatePackage
114+
resolver:(RCTPromiseResolveBlock)resolve
115+
rejecter:(RCTPromiseRejectBlock)reject)
116+
{
117+
[CodePush loadBundle:[CodePushConfig getRootComponent]];
118+
resolve([NSNull null]);
119+
}
120+
150121
RCT_EXPORT_METHOD(writeToLocalPackage:(NSString*)packageJsonString
151122
callback:(RCTResponseSenderBlock)callback)
152123
{

CodePush.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
13BE3DEE1AC21097009241FE /* CodePush.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* CodePush.m */; };
11+
810D4E6D1B96935000B397E9 /* CodePushPackage.m in Sources */ = {isa = PBXBuildFile; fileRef = 810D4E6C1B96935000B397E9 /* CodePushPackage.m */; };
1112
81D51F3A1B6181C2000DA084 /* CodePushConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 81D51F391B6181C2000DA084 /* CodePushConfig.m */; };
1213
/* End PBXBuildFile section */
1314

@@ -27,6 +28,7 @@
2728
134814201AA4EA6300B7C361 /* libCodePush.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCodePush.a; sourceTree = BUILT_PRODUCTS_DIR; };
2829
13BE3DEC1AC21097009241FE /* CodePush.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodePush.h; sourceTree = "<group>"; };
2930
13BE3DED1AC21097009241FE /* CodePush.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePush.m; sourceTree = "<group>"; };
31+
810D4E6C1B96935000B397E9 /* CodePushPackage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePushPackage.m; sourceTree = "<group>"; };
3032
81D51F391B6181C2000DA084 /* CodePushConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePushConfig.m; sourceTree = "<group>"; };
3133
/* End PBXFileReference section */
3234

@@ -52,6 +54,7 @@
5254
58B511D21A9E6C8500147676 = {
5355
isa = PBXGroup;
5456
children = (
57+
810D4E6C1B96935000B397E9 /* CodePushPackage.m */,
5558
81D51F391B6181C2000DA084 /* CodePushConfig.m */,
5659
13BE3DEC1AC21097009241FE /* CodePush.h */,
5760
13BE3DED1AC21097009241FE /* CodePush.m */,
@@ -117,6 +120,7 @@
117120
files = (
118121
81D51F3A1B6181C2000DA084 /* CodePushConfig.m in Sources */,
119122
13BE3DEE1AC21097009241FE /* CodePush.m in Sources */,
123+
810D4E6D1B96935000B397E9 /* CodePushPackage.m in Sources */,
120124
);
121125
runOnlyForDeploymentPostprocessing = 0;
122126
};

CodePushPackage.m

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#import "CodePush.h"
2+
3+
@implementation CodePushPackage
4+
5+
NSString * const PackageInfoFile = @"packages.json";
6+
7+
+ (NSString *)getCodePushPath
8+
{
9+
return [NSHomeDirectory() stringByAppendingPathComponent:@"CodePush"];
10+
}
11+
12+
+ (NSString *)getCurrentPackageInfoPath
13+
{
14+
return [[self getCodePushPath] stringByAppendingPathComponent:PackageInfoFile];
15+
}
16+
17+
+ (NSDictionary *)getCurrentPackageInfo:(NSError **)error
18+
{
19+
NSString *content = [NSString stringWithContentsOfFile:[self getCurrentPackageInfoPath]
20+
encoding:NSUTF8StringEncoding
21+
error:error];
22+
if (*error) {
23+
return NULL;
24+
}
25+
26+
NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
27+
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data
28+
options:kNilOptions
29+
error:error];
30+
if (*error) {
31+
return NULL;
32+
}
33+
34+
return json;
35+
}
36+
37+
+ (void)updateCurrentPackageInfo:(NSDictionary *)packageInfo
38+
error:(NSError **)error
39+
{
40+
41+
NSData *packageInfoData = [NSJSONSerialization dataWithJSONObject:packageInfo
42+
options:0
43+
error:error];
44+
45+
NSString *packageInfoString = [[NSString alloc] initWithData:packageInfoData
46+
encoding:NSUTF8StringEncoding];
47+
[packageInfoString writeToFile:[self getCurrentPackageInfoPath]
48+
atomically:YES
49+
encoding:NSUTF8StringEncoding
50+
error:error];
51+
}
52+
53+
+ (NSString *)getCurrentPackageFolderPath:(NSError **)error
54+
{
55+
NSDictionary *info = [self getCurrentPackageInfo:error];
56+
57+
if (*error) {
58+
return NULL;
59+
}
60+
61+
return [self getPackageFolderPath:info[@"currentPackage"]];
62+
}
63+
64+
+ (NSString *)getPackageFolderPath:(NSString *)packageHash
65+
{
66+
return [[self getCodePushPath] stringByAppendingPathComponent:packageHash];
67+
}
68+
69+
+ (void)downloadPackage:(NSDictionary *)updatePackage
70+
error:(NSError **)error
71+
{
72+
NSString *packageFolderPath = [self getPackageFolderPath:updatePackage[@"packageHash"]];
73+
74+
if (![[NSFileManager defaultManager] fileExistsAtPath:packageFolderPath]) {
75+
[[NSFileManager defaultManager] createDirectoryAtPath:packageFolderPath
76+
withIntermediateDirectories:YES
77+
attributes:nil
78+
error:error];
79+
}
80+
81+
if (error) {
82+
return;
83+
}
84+
85+
NSURL *url = [[NSURL alloc] initWithString:updatePackage[@"downloadUrl"]];
86+
NSString *updateContents = [[NSString alloc] initWithContentsOfURL:url
87+
encoding:NSUTF8StringEncoding
88+
error:error];
89+
if (error) {
90+
return;
91+
}
92+
93+
[updateContents writeToFile:[packageFolderPath stringByAppendingPathComponent:@"app.jsbundle"]
94+
atomically:YES
95+
encoding:NSUTF8StringEncoding
96+
error:error];
97+
if (error) {
98+
return;
99+
}
100+
101+
NSData *updateSerializedData = [NSJSONSerialization dataWithJSONObject:updatePackage
102+
options:0
103+
error:error];
104+
105+
if (error) {
106+
return;
107+
}
108+
109+
NSString *packageJsonString = [[NSString alloc] initWithData:updateSerializedData encoding:NSUTF8StringEncoding];
110+
[packageJsonString writeToFile:[packageFolderPath stringByAppendingPathComponent:@"app.json"]
111+
atomically:YES
112+
encoding:NSUTF8StringEncoding
113+
error:error];
114+
}
115+
116+
+ (void)applyPackage:(NSString *)packageHash
117+
error:(NSError **)error
118+
{
119+
NSDictionary *info = [self getCurrentPackageInfo:error];
120+
121+
if (error) {
122+
return;
123+
}
124+
125+
[info setValue:packageHash forKey:@"currentPackage"];
126+
127+
[self updateCurrentPackageInfo:info
128+
error:error];
129+
}
130+
131+
@end

Examples/CodePushDemoApp/index.ios.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ var CodePushDemoApp = React.createClass({
3030
return { update: false };
3131
},
3232
handlePress: function() {
33-
CodePush.installUpdate(this.state.update).done();
33+
this.state.update.download((localPackage) => {
34+
localPackage.apply().done();
35+
});
3436
},
3537
render: function() {
3638
var updateView;

0 commit comments

Comments
 (0)