Skip to content

Commit a974075

Browse files
committed
updated sync
1 parent ff891db commit a974075

20 files changed

+266
-156
lines changed

CodePush.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ failCallback:(void (^)(NSError *err))failCallback;
4949

5050
@interface CodePushPackage : NSObject
5151

52-
+ (void)applyPackage:(NSDictionary *)updatePackage
52+
+ (void)installPackage:(NSDictionary *)updatePackage
5353
error:(NSError **)error;
5454

5555
+ (NSDictionary *)getCurrentPackage:(NSError **)error;
@@ -72,8 +72,8 @@ failCallback:(void (^)(NSError *err))failCallback;
7272

7373
@end
7474

75-
typedef NS_ENUM(NSInteger, CodePushRestartMode) {
76-
CodePushRestartModeNone,
77-
CodePushRestartModeImmediate,
78-
CodePushRestartModeOnNextResume
75+
typedef NS_ENUM(NSInteger, CodePushInstallMode) {
76+
CodePushInstallModeImmediate,
77+
CodePushInstallModeOnNextRestart,
78+
CodePushInstallModeOnNextResume
7979
};

CodePush.ios.js

+91-40
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ function getCurrentPackage() {
6060
return NativeCodePush.isFailedUpdate(currentPackage.packageHash);
6161
})
6262
.then((failedUpdate) => {
63-
localPackage.failedApply = failedUpdate;
63+
localPackage.failedInstall = failedUpdate;
6464
return NativeCodePush.isFirstRun(localPackage.packageHash);
6565
})
6666
.then((isFirstRun) => {
@@ -98,7 +98,7 @@ function checkForUpdate() {
9898
}
9999

100100
// Ignore updates that require a newer app version,
101-
// since the end-user couldn't reliably apply it
101+
// since the end-user couldn't reliably install it
102102
if (!update || update.updateAppVersion) {
103103
return resolve(null);
104104
}
@@ -107,7 +107,7 @@ function checkForUpdate() {
107107

108108
NativeCodePush.isFailedUpdate(update.packageHash)
109109
.then((isFailedHash) => {
110-
update.failedApply = isFailedHash;
110+
update.failedInstall = isFailedHash;
111111
resolve(update);
112112
})
113113
.catch(reject)
@@ -126,72 +126,106 @@ function checkForUpdate() {
126126
* releases, and displaying a standard confirmation UI to the end-user
127127
* when an update is available.
128128
*/
129-
function sync(options = {}) {
129+
function sync(options = {}, onSyncStatusChange, onDownloadProgress) {
130130
var syncOptions = {
131-
descriptionPrefix: " Description: ",
132-
appendReleaseDescription: false,
133131

134132
ignoreFailedUpdates: true,
135-
136-
mandatoryContinueButtonLabel: "Continue",
137-
mandatoryUpdateMessage: "An update is available that must be installed.",
138-
139-
optionalIgnoreButtonLabel: "Ignore",
140-
optionalInstallButtonLabel: "Install",
141-
optionalUpdateMessage: "An update is available. Would you like to install it?",
142-
133+
installMode: CodePush.InstallMode.ON_NEXT_RESTART,
143134
rollbackTimeout: 0,
144-
145-
updateTitle: "Update available",
135+
updateDialog: null,
146136

147137
...options
148138
};
149-
139+
140+
onSyncStatusChange = typeof onSyncStatusChange == "function"
141+
? onSyncStatusChange
142+
: function(syncStatus) {
143+
switch(syncStatus) {
144+
case CodePush.SyncStatus.CHECKING_FOR_UPDATE:
145+
console.log("Checking for update.");
146+
break;
147+
case CodePush.SyncStatus.DOWNLOADING_PACKAGE:
148+
console.log("Downloading package.");
149+
break;
150+
case CodePush.SyncStatus.AWAITING_USER_ACTION:
151+
console.log("Awaiting user action.");
152+
break;
153+
case CodePush.SyncStatus.INSTALLING_UPDATE:
154+
console.log("Installing update.");
155+
break;
156+
case CodePush.SyncStatus.IDLE:
157+
console.log("Sync is idle.");
158+
break;
159+
}
160+
};
161+
162+
onDownloadProgress = typeof onDownloadProgress == "function"
163+
? onDownloadProgress
164+
: function(downloadProgress) {
165+
console.log(`Expecting ${downloadProgress.totalBytes} bytes, received ${downloadProgress.receivedBytes} bytes.`);
166+
};
167+
150168
return new Promise((resolve, reject) => {
169+
onSyncStatusChange(CodePush.SyncStatus.CHECKING_FOR_UPDATE);
151170
checkForUpdate()
152171
.then((remotePackage) => {
153-
if (!remotePackage || (remotePackage.failedApply && syncOptions.ignoreFailedUpdates)) {
154-
resolve(CodePush.SyncStatus.UP_TO_DATE);
172+
var doDownloadAndInstall = () => {
173+
onSyncStatusChange(CodePush.SyncStatus.DOWNLOADING_PACKAGE);
174+
remotePackage.download(onDownloadProgress)
175+
.then((localPackage) => {
176+
onSyncStatusChange(CodePush.SyncStatus.INSTALLING_UPDATE);
177+
return localPackage.install(syncOptions.rollbackTimeout, syncOptions.installMode)
178+
})
179+
.then(() => {
180+
onSyncStatusChange(CodePush.SyncStatus.IDLE);
181+
resolve(CodePush.SyncResult.UPDATE_INSTALLED)
182+
})
183+
.catch(reject)
184+
.done();
155185
}
156-
else {
186+
187+
if (!remotePackage || (remotePackage.failedInstall && syncOptions.ignoreFailedUpdates)) {
188+
onSyncStatusChange(CodePush.SyncStatus.IDLE);
189+
resolve(CodePush.SyncResult.UP_TO_DATE);
190+
}
191+
else if (syncOptions.updateNotification) {
192+
syncOptions.updateNotification = Object.assign(CodePush.DEFAULT_UPDATE_DIALOG, syncOptions.updateNotification);
193+
157194
var message = null;
158195
var dialogButtons = [
159196
{
160197
text: null,
161198
onPress: () => {
162-
remotePackage.download()
163-
.then((localPackage) => {
164-
resolve(CodePush.SyncStatus.UPDATE_APPLIED)
165-
return localPackage.apply(syncOptions.rollbackTimeout);
166-
})
167-
.catch(reject)
168-
.done();
199+
doDownloadAndInstall();
169200
}
170201
}
171202
];
172203

173204
if (remotePackage.isMandatory) {
174-
message = syncOptions.mandatoryUpdateMessage;
205+
message = syncOptions.updateNotification.mandatoryUpdateMessage;
175206
dialogButtons[0].text = syncOptions.mandatoryContinueButtonLabel;
176207
} else {
177-
message = syncOptions.optionalUpdateMessage;
178-
dialogButtons[0].text = syncOptions.optionalInstallButtonLabel;
208+
message = syncOptions.updateNotification.optionalUpdateMessage;
209+
dialogButtons[0].text = syncOptions.updateNotification.optionalInstallButtonLabel;
179210

180211
// Since this is an optional update, add another button
181212
// to allow the end-user to ignore it
182213
dialogButtons.push({
183-
text: syncOptions.optionalIgnoreButtonLabel,
184-
onPress: () => resolve(CodePush.SyncStatus.UPDATE_IGNORED)
214+
text: syncOptions.updateNotification.optionalIgnoreButtonLabel,
215+
onPress: () => resolve(CodePush.SyncResult.UPDATE_IGNORED)
185216
});
186217
}
187218

188219
// If the update has a description, and the developer
189220
// explicitly chose to display it, then set that as the message
190-
if (syncOptions.appendReleaseDescription && remotePackage.description) {
191-
message += `${syncOptions.descriptionPrefix} ${remotePackage.description}`;
221+
if (syncOptions.updateNotification.appendReleaseDescription && remotePackage.description) {
222+
message += `${syncOptions.updateNotification.descriptionPrefix} ${remotePackage.description}`;
192223
}
193224

225+
onSyncStatusChange(CodePush.SyncStatus.AWAITING_USER_ACTION);
194226
AlertIOS.alert(syncOptions.updateTitle, message, dialogButtons);
227+
} else {
228+
doDownloadAndInstall();
195229
}
196230
})
197231
.catch(reject)
@@ -206,15 +240,32 @@ var CodePush = {
206240
notifyApplicationReady: NativeCodePush.notifyApplicationReady,
207241
setUpTestDependencies: setUpTestDependencies,
208242
sync: sync,
209-
RestartMode: {
210-
NONE: NativeCodePush.codePushRestartModeNone, // Don't artificially restart the app. Allow the update to be "picked up" on the next app restart
211-
IMMEDIATE: NativeCodePush.codePushRestartModeImmediate, // Restart the app immediately
212-
ON_NEXT_RESUME: NativeCodePush.codePushRestartModeOnNextResume // Restart the app the next time it is resumed from the background
243+
InstallMode: {
244+
IMMEDIATE: NativeCodePush.codePushInstallModeImmediate, // Restart the app immediately
245+
ON_NEXT_RESTART: NativeCodePush.codePushInstallModeOnNextRestart, // Don't artificially restart the app. Allow the update to be "picked up" on the next app restart
246+
ON_NEXT_RESUME: NativeCodePush.codePushInstallModeOnNextResume // Restart the app the next time it is resumed from the background
213247
},
214-
SyncStatus: {
248+
SyncResult: {
215249
UP_TO_DATE: 0, // The running app is up-to-date
216250
UPDATE_IGNORED: 1, // The app had an optional update and the end-user chose to ignore it
217-
UPDATE_APPLIED: 2 // The app had an optional/mandatory update that was successfully downloaded and is about to be applied
251+
UPDATE_INSTALLED: 2 // The app had an optional/mandatory update that was successfully downloaded and is about to be installed.
252+
},
253+
SyncStatus: {
254+
CHECKING_FOR_UPDATE: 1,
255+
AWAITING_USER_ACTION: 2,
256+
DOWNLOADING_PACKAGE: 3,
257+
INSTALLING_UPDATE: 4,
258+
IDLE: 5
259+
},
260+
DEFAULT_UPDATE_DIALOG: {
261+
appendReleaseDescription: false,
262+
descriptionPrefix: " Description: ",
263+
mandatoryContinueButtonLabel: "Continue",
264+
mandatoryUpdateMessage: "An update is available that must be installed.",
265+
optionalIgnoreButtonLabel: "Ignore",
266+
optionalInstallButtonLabel: "Install",
267+
optionalUpdateMessage: "An update is available. Would you like to install it?",
268+
updateTitle: "Update available",
218269
}
219270
};
220271

CodePush.m

+13-11
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,11 @@ - (void)checkForPendingUpdateDuringResume
102102

103103
- (NSDictionary *)constantsToExport
104104
{
105-
// Export the values of the CodePushRestartMode enum
105+
// Export the values of the CodePushInstallMode enum
106106
// so that the script-side can easily stay in sync
107-
return @{ @"codePushRestartModeNone": @(CodePushRestartModeNone),
108-
@"codePushRestartModeImmediate": @(CodePushRestartModeImmediate),
109-
@"codePushRestartModeOnNextResume": @(CodePushRestartModeOnNextResume)
107+
return @{ @"codePushInstallModeOnNextRestart": @(CodePushInstallModeOnNextRestart),
108+
@"codePushInstallModeImmediate": @(CodePushInstallModeImmediate),
109+
@"codePushInstallModeOnNextResume": @(CodePushInstallModeOnNextResume)
110110
};
111111
};
112112

@@ -124,7 +124,7 @@ - (CodePush *)init
124124
if (self) {
125125
// Do an async check to see whether
126126
// we need to start the rollback timer
127-
// due to a pending update being applied at start
127+
// due to a pending update being installed at start
128128
[self checkForPendingUpdate:NO];
129129

130130
// Register for app resume notifications so that we
@@ -204,7 +204,7 @@ - (void)savePendingUpdate:(NSString *)packageHash
204204
rollbackTimeout:(int)rollbackTimeout
205205
{
206206
// Since we're not restarting, we need to store the fact that the update
207-
// was applied, but hasn't yet become "active".
207+
// was installed, but hasn't yet become "active".
208208
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
209209
NSDictionary *pendingUpdate = [[NSDictionary alloc] initWithObjectsAndKeys:
210210
packageHash,PendingUpdateHashKey,
@@ -225,26 +225,28 @@ - (void)startRollbackTimer:(int)rollbackTimeout
225225
}
226226

227227
// JavaScript-exported module methods
228-
RCT_EXPORT_METHOD(applyUpdate:(NSDictionary*)updatePackage
228+
RCT_EXPORT_METHOD(installUpdate:(NSDictionary*)updatePackage
229229
rollbackTimeout:(int)rollbackTimeout
230-
restartMode:(CodePushRestartMode)restartMode
230+
installMode:(CodePushInstallMode)installMode
231231
resolver:(RCTPromiseResolveBlock)resolve
232232
rejecter:(RCTPromiseRejectBlock)reject)
233233
{
234234
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
235235
NSError *error;
236-
[CodePushPackage applyPackage:updatePackage
236+
[CodePushPackage installPackage:updatePackage
237237
error:&error];
238238

239239
if (error) {
240240
reject(error);
241241
} else {
242-
if (restartMode == CodePushRestartModeImmediate) {
242+
if (installMode == CodePushInstallModeImmediate) {
243243
[self initializeUpdateWithRollbackTimeout:rollbackTimeout needsRestart:YES];
244244
} else {
245-
_resumablePendingUpdateAvailable = (restartMode == CodePushRestartModeOnNextResume);
245+
_resumablePendingUpdateAvailable = (installMode == CodePushInstallModeOnNextResume);
246246
[self savePendingUpdate:updatePackage[@"packageHash"]
247247
rollbackTimeout:rollbackTimeout];
248+
// Signal to JS that the update has been applied.
249+
resolve(nil);
248250
}
249251
}
250252
});

CodePush.xcodeproj/project.pbxproj

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
13BE3DEE1AC21097009241FE /* CodePush.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* CodePush.m */; };
11-
1B23B9141BF9267B000BB2F0 /* RCTConvert+CodePushRestartMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushRestartMode.m */; };
11+
1B23B9141BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */; };
1212
54FFEDE01BF550630061DD23 /* CodePushDownloadHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */; };
1313
810D4E6D1B96935000B397E9 /* CodePushPackage.m in Sources */ = {isa = PBXBuildFile; fileRef = 810D4E6C1B96935000B397E9 /* CodePushPackage.m */; };
1414
81D51F3A1B6181C2000DA084 /* CodePushConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 81D51F391B6181C2000DA084 /* CodePushConfig.m */; };
@@ -30,7 +30,7 @@
3030
134814201AA4EA6300B7C361 /* libCodePush.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCodePush.a; sourceTree = BUILT_PRODUCTS_DIR; };
3131
13BE3DEC1AC21097009241FE /* CodePush.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodePush.h; sourceTree = "<group>"; };
3232
13BE3DED1AC21097009241FE /* CodePush.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePush.m; sourceTree = "<group>"; };
33-
1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushRestartMode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+CodePushRestartMode.m"; sourceTree = "<group>"; };
33+
1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+CodePushInstallMode.m"; sourceTree = "<group>"; };
3434
54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePushDownloadHandler.m; sourceTree = "<group>"; };
3535
810D4E6C1B96935000B397E9 /* CodePushPackage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePushPackage.m; sourceTree = "<group>"; };
3636
81D51F391B6181C2000DA084 /* CodePushConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePushConfig.m; sourceTree = "<group>"; };
@@ -58,7 +58,7 @@
5858
58B511D21A9E6C8500147676 = {
5959
isa = PBXGroup;
6060
children = (
61-
1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushRestartMode.m */,
61+
1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */,
6262
54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */,
6363
810D4E6C1B96935000B397E9 /* CodePushPackage.m */,
6464
81D51F391B6181C2000DA084 /* CodePushConfig.m */,
@@ -124,7 +124,7 @@
124124
isa = PBXSourcesBuildPhase;
125125
buildActionMask = 2147483647;
126126
files = (
127-
1B23B9141BF9267B000BB2F0 /* RCTConvert+CodePushRestartMode.m in Sources */,
127+
1B23B9141BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m in Sources */,
128128
81D51F3A1B6181C2000DA084 /* CodePushConfig.m in Sources */,
129129
54FFEDE01BF550630061DD23 /* CodePushDownloadHandler.m in Sources */,
130130
13BE3DEE1AC21097009241FE /* CodePush.m in Sources */,

CodePushPackage.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ + (void)downloadPackage:(NSDictionary *)updatePackage
208208
[downloadHandler download:updatePackage[@"downloadUrl"]];
209209
}
210210

211-
+ (void)applyPackage:(NSDictionary *)updatePackage
211+
+ (void)installPackage:(NSDictionary *)updatePackage
212212
error:(NSError **)error
213213
{
214214
NSString *packageHash = updatePackage[@"packageHash" ];

Examples/CodePushDemoApp/CodePushDemoApp.xcodeproj/project.pbxproj

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
544161591B8BCA81000D9E25 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
2525
5451ACBA1B86A5B600E2A7DF /* QueryUpdateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5451ACB81B86A5B600E2A7DF /* QueryUpdateTests.m */; };
2626
5451ACEC1B86E40A00E2A7DF /* libRCTTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5451ACEB1B86E34300E2A7DF /* libRCTTest.a */; };
27-
54D774BA1B87DAF800F2ABF8 /* ApplyUpdateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 54D774B91B87DAF800F2ABF8 /* ApplyUpdateTests.m */; };
27+
54D774BA1B87DAF800F2ABF8 /* InstallUpdateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 54D774B91B87DAF800F2ABF8 /* InstallUpdateTests.m */; };
2828
54F5F2B41BF6B45D007C3CEA /* DownloadProgressTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 54F5F2B31BF6B45D007C3CEA /* DownloadProgressTests.m */; settings = {ASSET_TAGS = (); }; };
2929
81551E1B1B3B428000F5B9F1 /* libCodePush.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 81551E0F1B3B427200F5B9F1 /* libCodePush.a */; };
3030
/* End PBXBuildFile section */
@@ -151,7 +151,7 @@
151151
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
152152
5451ACB81B86A5B600E2A7DF /* QueryUpdateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QueryUpdateTests.m; sourceTree = "<group>"; };
153153
5451ACE61B86E34300E2A7DF /* RCTTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTest.xcodeproj; path = "node_modules/react-native/Libraries/RCTTest/RCTTest.xcodeproj"; sourceTree = "<group>"; };
154-
54D774B91B87DAF800F2ABF8 /* ApplyUpdateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ApplyUpdateTests.m; sourceTree = "<group>"; };
154+
54D774B91B87DAF800F2ABF8 /* InstallUpdateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InstallUpdateTests.m; sourceTree = "<group>"; };
155155
54F5F2B31BF6B45D007C3CEA /* DownloadProgressTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DownloadProgressTests.m; sourceTree = "<group>"; };
156156
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
157157
81551E0A1B3B427200F5B9F1 /* CodePush.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CodePush.xcodeproj; path = ../../CodePush.xcodeproj; sourceTree = "<group>"; };
@@ -242,7 +242,7 @@
242242
children = (
243243
54F5F2B31BF6B45D007C3CEA /* DownloadProgressTests.m */,
244244
5451ACB81B86A5B600E2A7DF /* QueryUpdateTests.m */,
245-
54D774B91B87DAF800F2ABF8 /* ApplyUpdateTests.m */,
245+
54D774B91B87DAF800F2ABF8 /* InstallUpdateTests.m */,
246246
00E356F01AD99517003FC87E /* Supporting Files */,
247247
);
248248
path = CodePushDemoAppTests;
@@ -612,7 +612,7 @@
612612
files = (
613613
5451ACBA1B86A5B600E2A7DF /* QueryUpdateTests.m in Sources */,
614614
54F5F2B41BF6B45D007C3CEA /* DownloadProgressTests.m in Sources */,
615-
54D774BA1B87DAF800F2ABF8 /* ApplyUpdateTests.m in Sources */,
615+
54D774BA1B87DAF800F2ABF8 /* InstallUpdateTests.m in Sources */,
616616
);
617617
runOnlyForDeploymentPostprocessing = 0;
618618
};

0 commit comments

Comments
 (0)