Skip to content

Commit 316a439

Browse files
committed
iOS: apply bsdiff patches during package install
1 parent 35dfdb1 commit 316a439

14 files changed

Lines changed: 952 additions & 8 deletions

docs/setup-ios.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,19 @@ MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANkWYydPuyOumR/sn2agNBVDnzyRpM16NAUpYPGxNgjSEp0e
136136
</plist>
137137
```
138138

139+
### Enable Delta Updates
140+
141+
Switch for applying binary diff (bsdiff) patches during a diff update, off by default (at the moment). When disabled, only file-by-file diffing is applied (for example, skipping assets if only the main JS bundle changed, but that whole file is downloaded byte for byte). Add a `CodePushEnableDeltaUpdates` boolean record to `Info.plist` to turn it on:
142+
143+
```xml
144+
<plist version="1.0">
145+
<dict>
146+
<!-- ...other configs... -->
147+
148+
<key>CodePushEnableDeltaUpdates</key>
149+
<true/>
150+
151+
<!-- ...other configs... -->
152+
</dict>
153+
</plist>
154+
```

ios/CodePush.xcodeproj/project.pbxproj

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,24 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
46BD3246E1289AF018ED4FEB /* CodePushSha256Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C09E6C954EFE879F5C40F34A /* CodePushSha256Tests.swift */; };
11+
BBC7F97A68E454FB38953FC4 /* CodePushDiffManifestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9645879798B46D35D8D824F8 /* CodePushDiffManifestTests.swift */; };
12+
3643F3729205426163367671 /* CodePushBinaryDiffPatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42FA68BF21AED765F55E71A /* CodePushBinaryDiffPatcherTests.swift */; };
13+
B75F8EB77C01BA01704CAD97 /* CodePushSha256.m in Sources */ = {isa = PBXBuildFile; fileRef = 62708BC475E46556136816C9 /* CodePushSha256.m */; };
14+
A2206CF91ED7FE901C630AB4 /* CodePushSha256.m in Sources */ = {isa = PBXBuildFile; fileRef = 62708BC475E46556136816C9 /* CodePushSha256.m */; };
15+
6663AFF6236CD01E20CBDD80 /* CodePushSha256.m in Sources */ = {isa = PBXBuildFile; fileRef = 62708BC475E46556136816C9 /* CodePushSha256.m */; };
16+
6A57E1B401615DA251D0F91F /* CodePushSha256.h in Headers */ = {isa = PBXBuildFile; fileRef = B7CE82B73092943E0F67E825 /* CodePushSha256.h */; };
17+
B0E0E947B133B742F6B41FBF /* CodePushSha256.h in Headers */ = {isa = PBXBuildFile; fileRef = B7CE82B73092943E0F67E825 /* CodePushSha256.h */; };
18+
CED0A6936F6F8C354302F246 /* CodePushDiffManifest.m in Sources */ = {isa = PBXBuildFile; fileRef = 49166671F067D5F6429B262B /* CodePushDiffManifest.m */; };
19+
CD32522E04D0F0E86DCC7BBE /* CodePushDiffManifest.m in Sources */ = {isa = PBXBuildFile; fileRef = 49166671F067D5F6429B262B /* CodePushDiffManifest.m */; };
20+
0E9314F338AC505D2E33C1A3 /* CodePushDiffManifest.m in Sources */ = {isa = PBXBuildFile; fileRef = 49166671F067D5F6429B262B /* CodePushDiffManifest.m */; };
21+
C11A2DB29D3D814B1A7891DF /* CodePushDiffManifest.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A092598DCE51279CA317823 /* CodePushDiffManifest.h */; };
22+
4693408DCB9ACB8E02BF69B1 /* CodePushDiffManifest.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A092598DCE51279CA317823 /* CodePushDiffManifest.h */; };
23+
1993F82DF6330426AC5CBC2E /* CodePushBinaryDiffPatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 9414C770C70E1B1319F24B12 /* CodePushBinaryDiffPatcher.m */; };
24+
F41E2EFAD0D322F7D14D7125 /* CodePushBinaryDiffPatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 9414C770C70E1B1319F24B12 /* CodePushBinaryDiffPatcher.m */; };
25+
D5BC8B1BF7D2DA03BB888FCC /* CodePushBinaryDiffPatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 9414C770C70E1B1319F24B12 /* CodePushBinaryDiffPatcher.m */; };
26+
E5C712D353D9164F04A2F456 /* CodePushBinaryDiffPatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F588BE40F9B3092085C5B63 /* CodePushBinaryDiffPatcher.h */; };
27+
469472C57F1D5FF7C0274268 /* CodePushBinaryDiffPatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F588BE40F9B3092085C5B63 /* CodePushBinaryDiffPatcher.h */; };
1028
0ABCB5DEFE01A7A15552A498 /* file_for_patch.c in Sources */ = {isa = PBXBuildFile; fileRef = 70779807AB59EA4711737F4E /* file_for_patch.c */; };
1129
08B8B3B8260E70B7ECA85451 /* bspatch_bridge.c in Sources */ = {isa = PBXBuildFile; fileRef = A430CBE260F09A3233110E28 /* bspatch_bridge.c */; };
1230
A75C1A7A555663186E25AA3D /* libHDiffPatch/HPatch/patch.c in Sources */ = {isa = PBXBuildFile; fileRef = 827016DF6E52E356F4B89D18 /* libHDiffPatch/HPatch/patch.c */; };
@@ -181,6 +199,15 @@
181199
/* End PBXCopyFilesBuildPhase section */
182200

183201
/* Begin PBXFileReference section */
202+
C09E6C954EFE879F5C40F34A /* CodePushSha256Tests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CodePushSha256Tests.swift; sourceTree = "<group>"; };
203+
9645879798B46D35D8D824F8 /* CodePushDiffManifestTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CodePushDiffManifestTests.swift; sourceTree = "<group>"; };
204+
F42FA68BF21AED765F55E71A /* CodePushBinaryDiffPatcherTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CodePushBinaryDiffPatcherTests.swift; sourceTree = "<group>"; };
205+
B7CE82B73092943E0F67E825 /* CodePushSha256.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CodePushSha256.h; path = CodePush/CodePushSha256.h; sourceTree = "<group>"; };
206+
62708BC475E46556136816C9 /* CodePushSha256.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CodePushSha256.m; path = CodePush/CodePushSha256.m; sourceTree = "<group>"; };
207+
2A092598DCE51279CA317823 /* CodePushDiffManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CodePushDiffManifest.h; path = CodePush/CodePushDiffManifest.h; sourceTree = "<group>"; };
208+
49166671F067D5F6429B262B /* CodePushDiffManifest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CodePushDiffManifest.m; path = CodePush/CodePushDiffManifest.m; sourceTree = "<group>"; };
209+
0F588BE40F9B3092085C5B63 /* CodePushBinaryDiffPatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CodePushBinaryDiffPatcher.h; path = CodePush/CodePushBinaryDiffPatcher.h; sourceTree = "<group>"; };
210+
9414C770C70E1B1319F24B12 /* CodePushBinaryDiffPatcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CodePushBinaryDiffPatcher.m; path = CodePush/CodePushBinaryDiffPatcher.m; sourceTree = "<group>"; };
184211
0BF68F85125CF81D7EB65ABB /* bspatch_bridge.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = bspatch_bridge.h; sourceTree = "<group>"; };
185212
0DC7989C75C72A774EF3685F /* bsdiff_wrapper/bspatch_wrapper.c */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.c; path = bsdiff_wrapper/bspatch_wrapper.c; sourceTree = "<group>"; };
186213
134814201AA4EA6300B7C361 /* libCodePush.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCodePush.a; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -430,6 +457,12 @@
430457
54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */,
431458
1B762E8F1C9A5E9A006EF800 /* CodePushErrorUtils.m */,
432459
810D4E6C1B96935000B397E9 /* CodePushPackage.m */,
460+
B7CE82B73092943E0F67E825 /* CodePushSha256.h */,
461+
62708BC475E46556136816C9 /* CodePushSha256.m */,
462+
2A092598DCE51279CA317823 /* CodePushDiffManifest.h */,
463+
49166671F067D5F6429B262B /* CodePushDiffManifest.m */,
464+
0F588BE40F9B3092085C5B63 /* CodePushBinaryDiffPatcher.h */,
465+
9414C770C70E1B1319F24B12 /* CodePushBinaryDiffPatcher.m */,
433466
5421FE301C58AD5A00986A55 /* CodePushTelemetryManager.m */,
434467
540D20111C7684FE00D6EF41 /* CodePushUpdateUtils.m */,
435468
1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */,
@@ -459,6 +492,9 @@
459492
isa = PBXGroup;
460493
children = (
461494
95D6DD0EACAC8D095880DFD0 /* BSPatchTests.swift */,
495+
C09E6C954EFE879F5C40F34A /* CodePushSha256Tests.swift */,
496+
9645879798B46D35D8D824F8 /* CodePushDiffManifestTests.swift */,
497+
F42FA68BF21AED765F55E71A /* CodePushBinaryDiffPatcherTests.swift */,
462498
E9FA144425AE78B97AD6C870 /* CodePushTests-Bridging-Header.h */,
463499
E74D80ECD8DD03C4C0772B7B /* Fixtures */,
464500
);
@@ -656,6 +692,9 @@
656692
3221E4762C8ABE1300268379 /* mz_strm_pkcrypt.h in Headers */,
657693
3221E4642C8ABE1300268379 /* mz_strm_split.h in Headers */,
658694
6463C8471EBA0D290095B8CD /* CodePush.h in Headers */,
695+
B0E0E947B133B742F6B41FBF /* CodePushSha256.h in Headers */,
696+
4693408DCB9ACB8E02BF69B1 /* CodePushDiffManifest.h in Headers */,
697+
469472C57F1D5FF7C0274268 /* CodePushBinaryDiffPatcher.h in Headers */,
659698
3221E46A2C8ABE1300268379 /* mz_strm.h in Headers */,
660699
3221E4782C8ABE1300268379 /* mz_zip_rw.h in Headers */,
661700
3221E4802C8ABE1400268379 /* mz.h in Headers */,
@@ -716,6 +755,9 @@
716755
3221E4632C8ABE1300268379 /* mz_strm_split.h in Headers */,
717756
3221E4752C8ABE1300268379 /* mz_strm_pkcrypt.h in Headers */,
718757
8482F84E1E24C66300F793DB /* CodePush.h in Headers */,
758+
6A57E1B401615DA251D0F91F /* CodePushSha256.h in Headers */,
759+
C11A2DB29D3D814B1A7891DF /* CodePushDiffManifest.h in Headers */,
760+
E5C712D353D9164F04A2F456 /* CodePushBinaryDiffPatcher.h in Headers */,
719761
F88664711F4AD1EE0036D01B /* JWTCoding+VersionTwo.h in Headers */,
720762
F886646B1F4AD1EE0036D01B /* JWTCoding+ResultTypes.h in Headers */,
721763
3221E4652C8ABE1300268379 /* mz_strm_buf.h in Headers */,
@@ -884,6 +926,9 @@
884926
5498D8F61D21F14100B5EB43 /* CodePushUtils.m in Sources */,
885927
3221E4612C8ABE1300268379 /* mz_zip_rw.c in Sources */,
886928
810D4E6D1B96935000B397E9 /* CodePushPackage.m in Sources */,
929+
B75F8EB77C01BA01704CAD97 /* CodePushSha256.m in Sources */,
930+
CED0A6936F6F8C354302F246 /* CodePushDiffManifest.m in Sources */,
931+
1993F82DF6330426AC5CBC2E /* CodePushBinaryDiffPatcher.m in Sources */,
887932
3221E4552C8ABE1300268379 /* mz_strm_pkcrypt.c in Sources */,
888933
F88664531F4AD1EE0036D01B /* JWTAlgorithmESBase.m in Sources */,
889934
3221E4532C8ABE1300268379 /* mz_strm_os_posix.c in Sources */,
@@ -907,6 +952,9 @@
907952
6463C8311EBA0CFB0095B8CD /* CodePushErrorUtils.m in Sources */,
908953
3221E46E2C8ABE1300268379 /* mz_crypt.c in Sources */,
909954
6463C8321EBA0CFB0095B8CD /* CodePushPackage.m in Sources */,
955+
A2206CF91ED7FE901C630AB4 /* CodePushSha256.m in Sources */,
956+
CD32522E04D0F0E86DCC7BBE /* CodePushDiffManifest.m in Sources */,
957+
F41E2EFAD0D322F7D14D7125 /* CodePushBinaryDiffPatcher.m in Sources */,
910958
6463C8331EBA0CFB0095B8CD /* CodePushTelemetryManager.m in Sources */,
911959
6463C8341EBA0CFB0095B8CD /* CodePushUpdateUtils.m in Sources */,
912960
3221E45C2C8ABE1300268379 /* mz_strm_zlib.c in Sources */,
@@ -929,7 +977,13 @@
929977
buildActionMask = 2147483647;
930978
files = (
931979
B5B50F91FAAF80444988E284 /* BSPatchTests.swift in Sources */,
980+
46BD3246E1289AF018ED4FEB /* CodePushSha256Tests.swift in Sources */,
981+
BBC7F97A68E454FB38953FC4 /* CodePushDiffManifestTests.swift in Sources */,
982+
3643F3729205426163367671 /* CodePushBinaryDiffPatcherTests.swift in Sources */,
932983
47F66D5AF3C3185E1A3E3B15 /* bspatch_bridge.c in Sources */,
984+
6663AFF6236CD01E20CBDD80 /* CodePushSha256.m in Sources */,
985+
0E9314F338AC505D2E33C1A3 /* CodePushDiffManifest.m in Sources */,
986+
D5BC8B1BF7D2DA03BB888FCC /* CodePushBinaryDiffPatcher.m in Sources */,
933987
DC983F1C71E0E7131BB343C5 /* libHDiffPatch/HPatch/patch.c in Sources */,
934988
A88F11124A2120A8373A8B61 /* bsdiff_wrapper/bspatch_wrapper.c in Sources */,
935989
0ABCB5DEFE01A7A15552A498 /* file_for_patch.c in Sources */,

ios/CodePush/CodePush.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
@property (copy) NSString *deploymentKey;
104104
@property (copy) NSString *serverURL;
105105
@property (copy) NSString *publicKey;
106+
@property (readonly) BOOL enableDeltaUpdates;
106107

107108
+ (instancetype)current;
108109

@@ -141,6 +142,7 @@ failCallback:(void (^)(NSError *err))failCallback;
141142
+ (void)downloadPackage:(NSDictionary *)updatePackage
142143
expectedBundleFileName:(NSString *)expectedBundleFileName
143144
publicKey:(NSString *)publicKey
145+
enableDeltaUpdates:(BOOL)enableDeltaUpdates
144146
operationQueue:(dispatch_queue_t)operationQueue
145147
progressCallback:(void (^)(long long, long long))progressCallback
146148
doneCallback:(void (^)())doneCallback

ios/CodePush/CodePush.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,11 +875,13 @@ -(void)loadBundleOnTick:(NSTimer *)timer {
875875
}
876876

877877
NSString * publicKey = [[CodePushConfig current] publicKey];
878+
BOOL enableDeltaUpdates = [[CodePushConfig current] enableDeltaUpdates];
878879

879880
[CodePushPackage
880881
downloadPackage:mutableUpdatePackage
881882
expectedBundleFileName:[bundleResourceName stringByAppendingPathExtension:bundleResourceExtension]
882883
publicKey:publicKey
884+
enableDeltaUpdates:enableDeltaUpdates
883885
operationQueue:_methodQueue
884886
// The download is progressing forward
885887
progressCallback:^(long long expectedContentLength, long long receivedContentLength) {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#import <Foundation/Foundation.h>
2+
#import "CodePushDiffManifest.h"
3+
4+
NS_ASSUME_NONNULL_BEGIN
5+
6+
@interface CodePushBinaryDiffPatcher : NSObject
7+
8+
// Applies every entry in manifest.patchedFiles: verifies the pre-patch file
9+
// against baseHash, applies the patch into newUpdateFolder, then verifies
10+
// the result against targetHash.
11+
//
12+
// Returns NO and sets *error on the first failure (unsupported algo, hash
13+
// mismatch, or patch failure).
14+
+ (BOOL)applyBinaryDiffPatchesFromManifest:(CodePushDiffManifest *)manifest
15+
currentPackageFolder:(NSString *)currentPackageFolder
16+
unzippedFolder:(NSString *)unzippedFolder
17+
newUpdateFolder:(NSString *)newUpdateFolder
18+
error:(NSError **)error
19+
NS_SWIFT_NAME(applyBinaryDiffPatches(manifest:currentPackageFolder:unzippedFolder:newUpdateFolder:));
20+
21+
@end
22+
23+
NS_ASSUME_NONNULL_END
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#import "CodePushBinaryDiffPatcher.h"
2+
#import "CodePushSha256.h"
3+
#import "bspatch_bridge.h"
4+
5+
static NSString *const CodePushBinaryDiffPatcherErrorDomain = @"CodePushBinaryDiffPatcherError";
6+
7+
static NSError *patchApplyError(NSString *relativePath, NSString *reason)
8+
{
9+
return [NSError errorWithDomain:CodePushBinaryDiffPatcherErrorDomain
10+
code:1
11+
userInfo:@{ NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Failed to apply binary diff patch for \"%@\": %@", relativePath, reason] }];
12+
}
13+
14+
// Keep in sync with shared/diffpatch/bspatch_bridge.h.
15+
static NSString *describeBSPatchResult(CodePushBSPatchResult result)
16+
{
17+
switch (result) {
18+
case CODEPUSH_BSPATCH_OK: return @"OK";
19+
case CODEPUSH_BSPATCH_ERR_BAD_DIFF_HEADER: return @"BAD_DIFF_HEADER";
20+
case CODEPUSH_BSPATCH_ERR_OPEN_OLD: return @"OPEN_OLD_FAILED";
21+
case CODEPUSH_BSPATCH_ERR_OPEN_DIFF: return @"OPEN_DIFF_FAILED";
22+
case CODEPUSH_BSPATCH_ERR_OPEN_OUT: return @"OPEN_OUT_FAILED";
23+
case CODEPUSH_BSPATCH_ERR_OOM: return @"OUT_OF_MEMORY";
24+
case CODEPUSH_BSPATCH_ERR_PATCH_FAILED: return @"PATCH_FAILED";
25+
}
26+
return [NSString stringWithFormat:@"UNKNOWN (%ld)", (long)result];
27+
}
28+
29+
// Resolves `path` inside `base`, or returns nil and describes the rejection in
30+
// terms of the manifest entry it came from.
31+
static NSString *resolveWithin(NSString *base, NSString *path, NSString *manifestEntry, NSError **error)
32+
{
33+
NSString *resolved = [CodePushDiffManifest resolvePath:path withinFolder:base];
34+
if (resolved == nil) {
35+
if (error) *error = patchApplyError(manifestEntry, @"path escapes expected directory");
36+
}
37+
return resolved;
38+
}
39+
40+
@implementation CodePushBinaryDiffPatcher
41+
42+
+ (BOOL)applyBinaryDiffPatchesFromManifest:(CodePushDiffManifest *)manifest
43+
currentPackageFolder:(NSString *)currentPackageFolder
44+
unzippedFolder:(NSString *)unzippedFolder
45+
newUpdateFolder:(NSString *)newUpdateFolder
46+
error:(NSError **)error
47+
{
48+
NSDictionary<NSString *, CodePushPatchedFileEntry *> *patchedFiles = manifest.patchedFiles;
49+
50+
for (NSString *relativePath in patchedFiles) {
51+
CodePushPatchedFileEntry *entry = patchedFiles[relativePath];
52+
if (![entry.algo isEqualToString:@"bsdiff"]) {
53+
if (error) *error = patchApplyError(relativePath, [NSString stringWithFormat:@"unsupported patch algorithm: %@", entry.algo]);
54+
return NO;
55+
}
56+
}
57+
58+
NSFileManager *fileManager = [NSFileManager defaultManager];
59+
60+
for (NSString *relativePath in patchedFiles) {
61+
CodePushPatchedFileEntry *entry = patchedFiles[relativePath];
62+
63+
NSString *oldFile = resolveWithin(currentPackageFolder, relativePath, relativePath, error);
64+
if (!oldFile) return NO;
65+
66+
NSError *hashError = nil;
67+
NSString *oldFileHash = CodePushSha256HexForFile(oldFile, &hashError);
68+
if (!oldFileHash || ![oldFileHash isEqualToString:entry.baseHash]) {
69+
if (error) *error = patchApplyError(relativePath, [NSString stringWithFormat:@"baseHash mismatch: expected %@, got %@", entry.baseHash, oldFileHash]);
70+
return NO;
71+
}
72+
73+
NSString *diffFile = resolveWithin(unzippedFolder, entry.patch, relativePath, error);
74+
if (!diffFile) return NO;
75+
76+
NSString *newFile = resolveWithin(newUpdateFolder, relativePath, relativePath, error);
77+
if (!newFile) return NO;
78+
79+
NSError *createDirError = nil;
80+
[fileManager createDirectoryAtPath:[newFile stringByDeletingLastPathComponent]
81+
withIntermediateDirectories:YES
82+
attributes:nil
83+
error:&createDirError];
84+
if (createDirError) {
85+
if (error) *error = patchApplyError(relativePath, createDirError.localizedDescription);
86+
return NO;
87+
}
88+
89+
CodePushBSPatchResult result = codepush_bspatch_apply(oldFile.fileSystemRepresentation,
90+
diffFile.fileSystemRepresentation,
91+
newFile.fileSystemRepresentation);
92+
if (result != CODEPUSH_BSPATCH_OK) {
93+
if (error) *error = patchApplyError(relativePath, [NSString stringWithFormat:@"patch failed: %@", describeBSPatchResult(result)]);
94+
return NO;
95+
}
96+
97+
NSString *newFileHash = CodePushSha256HexForFile(newFile, &hashError);
98+
if (!newFileHash || ![newFileHash isEqualToString:entry.targetHash]) {
99+
if (error) *error = patchApplyError(relativePath, [NSString stringWithFormat:@"targetHash mismatch: expected %@, got %@", entry.targetHash, newFileHash]);
100+
return NO;
101+
}
102+
}
103+
104+
return YES;
105+
}
106+
107+
@end

ios/CodePush/CodePushConfig.m

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
@implementation CodePushConfig {
55
NSMutableDictionary *_configDictionary;
6+
BOOL _enableDeltaUpdates;
67
}
78

89
static CodePushConfig *_currentConfig;
@@ -36,7 +37,8 @@ - (instancetype)init
3637
NSString *deploymentKey = [infoDictionary objectForKey:@"CodePushDeploymentKey"];
3738
NSString *serverURL = [infoDictionary objectForKey:@"CodePushServerURL"];
3839
NSString *publicKey = [infoDictionary objectForKey:@"CodePushPublicKey"];
39-
40+
_enableDeltaUpdates = [[infoDictionary objectForKey:@"CodePushEnableDeltaUpdates"] boolValue];
41+
4042
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
4143
NSString *clientUniqueId = [userDefaults stringForKey:ClientUniqueIDConfigKey];
4244
if (clientUniqueId == nil) {
@@ -96,6 +98,11 @@ - (NSString *)publicKey
9698
return [_configDictionary objectForKey:PublicKeyKey];
9799
}
98100

101+
- (BOOL)enableDeltaUpdates
102+
{
103+
return _enableDeltaUpdates;
104+
}
105+
99106
- (void)setAppVersion:(NSString *)appVersion
100107
{
101108
[_configDictionary setValue:appVersion forKey:AppVersionConfigKey];

0 commit comments

Comments
 (0)