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

Commit 41a24cb

Browse files
committed
Merge pull request #125 from Microsoft/clear-updates-on-new-binary
Clear updates on new binary
2 parents 35945e9 + 86a4ed3 commit 41a24cb

File tree

9 files changed

+72
-37
lines changed

9 files changed

+72
-37
lines changed

CodePush.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
// The below methods are only used during tests.
2626
+ (BOOL)isUsingTestConfiguration;
2727
+ (void)setUsingTestConfiguration:(BOOL)shouldUseTestConfiguration;
28-
+ (void)clearTestUpdates;
28+
+ (void)clearUpdates;
2929

3030
@end
3131

@@ -84,7 +84,7 @@ failCallback:(void (^)(NSError *err))failCallback;
8484

8585
// The below methods are only used during tests.
8686
+ (void)downloadAndReplaceCurrentBundle:(NSString *)remoteBundleUrl;
87-
+ (void)clearTestUpdates;
87+
+ (void)clearUpdates;
8888

8989
@end
9090

CodePush.m

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,22 @@ + (NSURL *)bundleURLForResource:(NSString *)resourceName
6161
NSDictionary *appFileAttribs = [[NSFileManager defaultManager] attributesOfItemAtPath:packageFile error:nil];
6262
NSDate *binaryDate = [binaryFileAttributes objectForKey:NSFileModificationDate];
6363
NSDate *packageDate = [appFileAttribs objectForKey:NSFileModificationDate];
64+
NSString *binaryAppVersion = [[CodePushConfig current] appVersion];
65+
NSDictionary *currentPackageMetadata = [CodePushPackage getCurrentPackage:&error];
66+
if (error || !currentPackageMetadata) {
67+
NSLog(logMessageFormat, binaryJsBundleUrl);
68+
return binaryJsBundleUrl;
69+
}
70+
71+
NSString *packageAppVersion = [currentPackageMetadata objectForKey:@"appVersion"];
6472

65-
if ([binaryDate compare:packageDate] == NSOrderedAscending) {
73+
if ([binaryDate compare:packageDate] == NSOrderedAscending && [binaryAppVersion isEqualToString:packageAppVersion]) {
6674
// Return package file because it is newer than the app store binary's JS bundle
6775
NSURL *packageUrl = [[NSURL alloc] initFileURLWithPath:packageFile];
6876
NSLog(logMessageFormat, packageUrl);
6977
return packageUrl;
7078
} else {
79+
[CodePush clearUpdates];
7180
NSLog(logMessageFormat, binaryJsBundleUrl);
7281
return binaryJsBundleUrl;
7382
}
@@ -100,16 +109,13 @@ + (void)setUsingTestConfiguration:(BOOL)shouldUseTestConfiguration
100109
}
101110

102111
/*
103-
* This is used to clean up all test updates. It can only be used
104-
* when the testConfigurationFlag is set to YES, otherwise it will
105-
* simply no-op.
112+
* WARNING: This cleans up all downloaded and pending updates.
106113
*/
107-
+ (void)clearTestUpdates
114+
+ (void)clearUpdates
108115
{
109-
if ([CodePush isUsingTestConfiguration]) {
110-
[CodePushPackage clearTestUpdates];
111-
[self removePendingUpdate];
112-
}
116+
[CodePushPackage clearUpdates];
117+
[self removePendingUpdate];
118+
[self removeFailedUpdates];
113119
}
114120

115121

@@ -271,6 +277,17 @@ - (void)saveFailedUpdate:(NSString *)packageHash
271277
[preferences synchronize];
272278
}
273279

280+
/*
281+
* This method is used to clear away failed updates in the event that
282+
* a new app store binary is installed.
283+
*/
284+
+ (void)removeFailedUpdates
285+
{
286+
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
287+
[preferences removeObjectForKey:FailedUpdatesKey];
288+
[preferences synchronize];
289+
}
290+
274291
/*
275292
* This method is used to register the fact that a pending
276293
* update succeeded and therefore can be removed.

CodePushPackage.m

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -505,12 +505,10 @@ + (void)downloadAndReplaceCurrentBundle:(NSString *)remoteBundleUrl
505505
}
506506
}
507507

508-
+ (void)clearTestUpdates
508+
+ (void)clearUpdates
509509
{
510-
if ([CodePush isUsingTestConfiguration]) {
511-
[[NSFileManager defaultManager] removeItemAtPath:[self getCodePushPath] error:nil];
512-
[[NSFileManager defaultManager] removeItemAtPath:[self getStatusFilePath] error:nil];
513-
}
510+
[[NSFileManager defaultManager] removeItemAtPath:[self getCodePushPath] error:nil];
511+
[[NSFileManager defaultManager] removeItemAtPath:[self getStatusFilePath] error:nil];
514512
}
515513

516514
@end

Examples/CodePushDemoApp/CodePushDemoAppTests/CheckForUpdateTests.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ - (void)setUp
2525
NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];
2626
RCTAssert(version.majorVersion == 8 || version.minorVersion == 3, @"Tests should be run on iOS 8.3, found %zd.%zd.%zd", version.majorVersion, version.minorVersion, version.patchVersion);
2727
[CodePush setUsingTestConfiguration:YES];
28-
[CodePush clearTestUpdates];
28+
[CodePush clearUpdates];
2929
_runner = RCTInitRunnerForApp(@"CodePushDemoAppTests/CheckForUpdateTests/CheckForUpdateTestApp", nil);
3030
}
3131

Examples/CodePushDemoApp/CodePushDemoAppTests/DownloadProgressTests.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ - (void)setUp
2525
NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];
2626
RCTAssert(version.majorVersion == 8 || version.minorVersion == 3, @"Tests should be run on iOS 8.3, found %zd.%zd.%zd", version.majorVersion, version.minorVersion, version.patchVersion);
2727
[CodePush setUsingTestConfiguration:YES];
28-
[CodePush clearTestUpdates];
28+
[CodePush clearUpdates];
2929
_runner = RCTInitRunnerForApp(@"CodePushDemoAppTests/DownloadProgressTests/DownloadProgressTestApp", nil);
3030
}
3131

Examples/CodePushDemoApp/CodePushDemoAppTests/InstallUpdateTests.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ - (void)testIsPending
7272

7373
- (void)runTest:(NSString *)testName
7474
{
75-
[CodePush clearTestUpdates];
75+
[CodePush clearUpdates];
7676
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:8081/CodePushDemoAppTests/InstallUpdateTests/testcases/%@.bundle?platform=ios&dev=true", testName]]
7777
moduleName:testName
7878
initialProperties:nil

Examples/CodePushDemoApp/android/app/src/main/java/com/microsoft/codepushdemoapp/MainActivity.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
public class MainActivity extends FragmentActivity implements DefaultHardwareBackBtnHandler {
1616

17-
private final String TEST_FOLDER_PREFIX = "CodePushDemoAppTests/";
1817
private ReactInstanceManager mReactInstanceManager;
1918
private ReactRootView mReactRootView;
2019

@@ -25,7 +24,7 @@ protected void onCreate(Bundle savedInstanceState) {
2524
super.onCreate(savedInstanceState);
2625
mReactRootView = new ReactRootView(this);
2726

28-
codePush = new CodePush("DEPLOYMENT_KEY_HERE", this);
27+
codePush = new CodePush("DEPLOYMENT_KEY_HERE", this, BuildConfig.DEBUG);
2928

3029
ReactInstanceManager.Builder builder = ReactInstanceManager.builder()
3130
.setApplication(getApplication())

android/app/src/main/java/com/microsoft/codepush/react/CodePush.java

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,20 @@ public class CodePush {
6767

6868
private Activity mainActivity;
6969
private Context applicationContext;
70+
private final boolean isDebugMode;
7071

7172
public CodePush(String deploymentKey, Activity mainActivity) {
73+
this(deploymentKey, mainActivity, false);
74+
}
75+
76+
public CodePush(String deploymentKey, Activity mainActivity, boolean isDebugMode) {
7277
SoLoader.init(mainActivity, false);
7378
this.deploymentKey = deploymentKey;
7479
this.codePushPackage = new CodePushPackage(mainActivity.getFilesDir().getAbsolutePath());
7580
this.mainActivity = mainActivity;
7681
this.applicationContext = mainActivity.getApplicationContext();
7782
this.deploymentKey = deploymentKey;
83+
this.isDebugMode = isDebugMode;
7884

7985
PackageInfo pInfo = null;
8086
try {
@@ -130,13 +136,25 @@ public String getBundleUrl(String assetsBundleFileName) {
130136
}
131137

132138
ReadableMap packageMetadata = codePushPackage.getCurrentPackage();
133-
// May throw NumberFormatException.
134-
Long binaryModifiedDateDuringPackageInstall = Long.parseLong(CodePushUtils.tryGetString(packageMetadata, BINARY_MODIFIED_TIME_KEY));
135-
if (binaryModifiedDateDuringPackageInstall == binaryResourcesModifiedTime) {
139+
Long binaryModifiedDateDuringPackageInstall = null;
140+
String binaryModifiedDateDuringPackageInstallString = CodePushUtils.tryGetString(packageMetadata, BINARY_MODIFIED_TIME_KEY);
141+
if (binaryModifiedDateDuringPackageInstallString != null) {
142+
binaryModifiedDateDuringPackageInstall = Long.parseLong(binaryModifiedDateDuringPackageInstallString);
143+
}
144+
145+
String pacakgeAppVersion = CodePushUtils.tryGetString(packageMetadata, "appVersion");
146+
if (binaryModifiedDateDuringPackageInstall != null &&
147+
binaryModifiedDateDuringPackageInstall == binaryResourcesModifiedTime &&
148+
this.appVersion.equals(pacakgeAppVersion)) {
136149
CodePushUtils.logBundleUrl(packageFilePath);
137150
return packageFilePath;
138151
} else {
139152
// The binary version is newer.
153+
didUpdate = false;
154+
if (!this.isDebugMode) {
155+
this.clearUpdates();
156+
}
157+
140158
CodePushUtils.logBundleUrl(binaryJsBundleUrl);
141159
return binaryJsBundleUrl;
142160
}
@@ -185,7 +203,9 @@ private void initializeUpdateAfterRestart() {
185203
rollbackPackage();
186204
} else {
187205
// Clear the React dev bundle cache so that new updates can be loaded.
188-
clearReactDevBundleCache();
206+
if (this.isDebugMode) {
207+
clearReactDevBundleCache();
208+
}
189209
// Mark that we tried to initialize the new update, so that if it crashes,
190210
// we will know that we need to rollback when the app next starts.
191211
savePendingUpdate(pendingUpdate.getString(PENDING_UPDATE_HASH_KEY),
@@ -222,14 +242,18 @@ private boolean isPendingUpdate(String packageHash) {
222242
boolean updateIsPending = pendingUpdate != null &&
223243
pendingUpdate.getBoolean(PENDING_UPDATE_IS_LOADING_KEY) == false &&
224244
pendingUpdate.getString(PENDING_UPDATE_HASH_KEY).equals(packageHash);
225-
226245
return updateIsPending;
227246
}
228247
catch (JSONException e) {
229248
throw new CodePushUnknownException("Unable to read pending update metadata in isPendingUpdate.", e);
230249
}
231250
}
232251

252+
private void removeFailedUpdates() {
253+
SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0);
254+
settings.edit().remove(FAILED_UPDATES_KEY).commit();
255+
}
256+
233257
private void removePendingUpdate() {
234258
SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0);
235259
settings.edit().remove(PENDING_UPDATE_KEY).commit();
@@ -299,11 +323,10 @@ public static void setUsingTestConfiguration(boolean shouldUseTestConfiguration)
299323
testConfigurationFlag = shouldUseTestConfiguration;
300324
}
301325

302-
public void clearTestUpdates() {
303-
if (isUsingTestConfiguration()) {
304-
codePushPackage.clearTestUpdates();
305-
removePendingUpdate();
306-
}
326+
public void clearUpdates() {
327+
codePushPackage.clearUpdates();
328+
removePendingUpdate();
329+
removeFailedUpdates();
307330
}
308331

309332
private class CodePushNativeModule extends ReactContextBaseJavaModule {

android/app/src/main/java/com/microsoft/codepush/react/CodePushPackage.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,9 @@ public void downloadAndReplaceCurrentBundle(String remoteBundleUrl) throws IOExc
225225
}
226226
}
227227

228-
public void clearTestUpdates() {
229-
if (CodePush.isUsingTestConfiguration()) {
230-
File statusFile = new File(getStatusFilePath());
231-
statusFile.delete();
232-
CodePushUtils.deleteDirectoryAtPath(getCodePushPath());
233-
}
228+
public void clearUpdates() {
229+
File statusFile = new File(getStatusFilePath());
230+
statusFile.delete();
231+
CodePushUtils.deleteDirectoryAtPath(getCodePushPath());
234232
}
235233
}

0 commit comments

Comments
 (0)