react-native-update 10.39.0 → 10.40.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +0 -6
- package/android/jni/Application.mk +1 -1
- package/android/lib/arm64-v8a/librnupdate.so +0 -0
- package/android/lib/armeabi-v7a/librnupdate.so +0 -0
- package/android/lib/x86/librnupdate.so +0 -0
- package/android/lib/x86_64/librnupdate.so +0 -0
- package/android/src/main/java/cn/reactnative/modules/update/BundledResourceCopier.java +314 -0
- package/android/src/main/java/cn/reactnative/modules/update/DownloadTask.java +253 -586
- package/android/src/main/java/cn/reactnative/modules/update/NativeUpdateCore.java +1 -9
- package/android/src/main/java/cn/reactnative/modules/update/ReactReloadManager.java +220 -0
- package/android/src/main/java/cn/reactnative/modules/update/SafeZipFile.java +9 -3
- package/android/src/main/java/cn/reactnative/modules/update/UiThreadRunner.java +36 -0
- package/android/src/main/java/cn/reactnative/modules/update/UpdateContext.java +36 -26
- package/android/src/main/java/cn/reactnative/modules/update/UpdateEventEmitter.java +39 -0
- package/android/src/main/java/cn/reactnative/modules/update/UpdateFileUtils.java +74 -0
- package/android/src/main/java/cn/reactnative/modules/update/UpdateModuleImpl.java +143 -260
- package/android/src/main/java/cn/reactnative/modules/update/UpdateModuleSupport.java +63 -0
- package/android/src/main/java/cn/reactnative/modules/update/UpdatePackage.java +1 -5
- package/android/src/newarch/cn/reactnative/modules/update/UpdateModule.java +26 -73
- package/android/src/oldarch/cn/reactnative/modules/update/UpdateModule.java +28 -242
- package/harmony/pushy/src/main/cpp/PushyTurboModule.cpp +89 -135
- package/harmony/pushy/src/main/cpp/PushyTurboModule.h +5 -5
- package/harmony/pushy/src/main/ets/DownloadTaskParams.ts +7 -7
- package/harmony/pushy/src/main/ets/PushyPackage.ets +3 -9
- package/harmony/pushy/src/main/ets/PushyPackageCompat.ts +3 -9
- package/harmony/pushy/src/main/ets/PushyPackageFactory.ts +14 -0
- package/harmony/pushy/src/main/ets/PushyTurboModule.ts +124 -24
- package/harmony/pushy/src/main/ets/UpdateContext.ts +92 -70
- package/harmony/pushy.har +0 -0
- package/ios/Expo/ExpoPushyReactDelegateHandler.swift +6 -26
- package/ios/RCTPushy/RCTPushy.mm +315 -259
- package/ios/RCTPushy/RCTPushyDownloader.mm +52 -29
- package/package.json +2 -2
- package/react-native-update.podspec +3 -3
- package/harmony/pushy/src/main/ets/UpdateModuleImpl.ts +0 -123
- package/ios/ImportReact.h +0 -2
- package/ios/RCTPushy/HDiffPatch/HDiffPatch.h +0 -16
- package/ios/RCTPushy/HDiffPatch/HDiffPatch.mm +0 -35
- package/ios/RCTPushy/RCTPushyManager.h +0 -27
- package/ios/RCTPushy/RCTPushyManager.mm +0 -181
- package/ios/RCTPushy.xcodeproj/project.pbxproj +0 -479
- package/package/harmony/pushy.har +0 -0
- package/react-native-update-10.39.0-beta.3.tgz +0 -0
- package/scripts/prune-host-stl.sh +0 -6
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
#import "RCTPushyDownloader.h"
|
|
2
2
|
|
|
3
|
-
@
|
|
3
|
+
static NSString *const RCTPushyDownloaderErrorDomain = @"cn.reactnative.pushy";
|
|
4
4
|
|
|
5
|
+
@interface RCTPushyDownloader()<NSURLSessionDownloadDelegate>
|
|
6
|
+
|
|
7
|
+
@property (nonatomic, strong) NSURLSession *session;
|
|
5
8
|
@property (copy) void (^progressHandler)(long long, long long);
|
|
6
9
|
@property (copy) void (^completionHandler)(NSString*, NSError*);
|
|
7
10
|
@property (copy) NSString *savePath;
|
|
11
|
+
@property (nonatomic, strong) NSError *fileError;
|
|
12
|
+
@property (nonatomic, assign) BOOL finished;
|
|
8
13
|
@end
|
|
9
14
|
|
|
10
15
|
@implementation RCTPushyDownloader
|
|
@@ -21,27 +26,50 @@ completionHandler:(void (^)(NSString *path, NSError *error))completionHandler
|
|
|
21
26
|
downloader.completionHandler = completionHandler;
|
|
22
27
|
downloader.savePath = savePath;
|
|
23
28
|
|
|
24
|
-
[downloader
|
|
29
|
+
[downloader startDownload:downloadPath];
|
|
25
30
|
}
|
|
26
31
|
|
|
27
|
-
- (void)
|
|
28
|
-
{
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
- (void)download:(NSString *)path
|
|
32
|
+
- (void)startDownload:(NSString *)path
|
|
32
33
|
{
|
|
33
34
|
NSURL *url = [NSURL URLWithString:path];
|
|
34
|
-
|
|
35
|
+
if (url == nil) {
|
|
36
|
+
[self completeWithError:[NSError errorWithDomain:RCTPushyDownloaderErrorDomain
|
|
37
|
+
code:-1
|
|
38
|
+
userInfo:@{
|
|
39
|
+
NSLocalizedDescriptionKey: @"invalid download url",
|
|
40
|
+
}]];
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
35
44
|
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url];
|
|
41
|
-
[session downloadTaskWithURL:url];
|
|
45
|
+
self.session = [NSURLSession sessionWithConfiguration:sessionConfig
|
|
46
|
+
delegate:self
|
|
47
|
+
delegateQueue:nil];
|
|
48
|
+
|
|
49
|
+
NSURLSessionDownloadTask *task = [self.session downloadTaskWithURL:url];
|
|
42
50
|
[task resume];
|
|
43
51
|
}
|
|
44
52
|
|
|
53
|
+
- (void)completeWithError:(NSError *)error
|
|
54
|
+
{
|
|
55
|
+
if (self.finished) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
self.finished = YES;
|
|
59
|
+
|
|
60
|
+
void (^completionHandler)(NSString *, NSError *) = self.completionHandler;
|
|
61
|
+
self.progressHandler = nil;
|
|
62
|
+
self.completionHandler = nil;
|
|
63
|
+
self.fileError = nil;
|
|
64
|
+
|
|
65
|
+
[self.session finishTasksAndInvalidate];
|
|
66
|
+
self.session = nil;
|
|
67
|
+
|
|
68
|
+
if (completionHandler) {
|
|
69
|
+
completionHandler(error == nil ? self.savePath : nil, error);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
45
73
|
#pragma mark - session delegate
|
|
46
74
|
|
|
47
75
|
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
|
|
@@ -49,10 +77,6 @@ completionHandler:(void (^)(NSString *path, NSError *error))completionHandler
|
|
|
49
77
|
totalBytesWritten:(int64_t)totalBytesWritten
|
|
50
78
|
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
|
|
51
79
|
{
|
|
52
|
-
#ifdef DEBUG
|
|
53
|
-
NSLog(@"download progress, %lld, %lld, %lld", bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
|
|
54
|
-
#endif
|
|
55
|
-
|
|
56
80
|
if (self.progressHandler) {
|
|
57
81
|
self.progressHandler(totalBytesWritten ,totalBytesExpectedToWrite);
|
|
58
82
|
}
|
|
@@ -61,23 +85,22 @@ totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
|
|
|
61
85
|
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
|
|
62
86
|
didFinishDownloadingToURL:(NSURL *)location
|
|
63
87
|
{
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
88
|
+
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
89
|
+
[fileManager removeItemAtPath:self.savePath error:nil];
|
|
90
|
+
|
|
91
|
+
NSError *fileError = nil;
|
|
92
|
+
[fileManager moveItemAtURL:location
|
|
93
|
+
toURL:[NSURL fileURLWithPath:self.savePath]
|
|
94
|
+
error:&fileError];
|
|
95
|
+
if (fileError != nil) {
|
|
96
|
+
self.fileError = fileError;
|
|
72
97
|
}
|
|
73
98
|
}
|
|
74
99
|
|
|
75
100
|
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
|
|
76
101
|
didCompleteWithError:(NSError *)error
|
|
77
102
|
{
|
|
78
|
-
|
|
79
|
-
self.completionHandler(self.savePath, error);
|
|
80
|
-
}
|
|
103
|
+
[self completeWithError:error ?: self.fileError];
|
|
81
104
|
}
|
|
82
105
|
|
|
83
106
|
@end
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-update",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.40.0-beta.0",
|
|
4
4
|
"description": "react-native hot update",
|
|
5
5
|
"main": "src/index",
|
|
6
6
|
"scripts": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"test": "bun test src/__tests__",
|
|
14
14
|
"test:patch-core": "./scripts/test-patch-core.sh",
|
|
15
15
|
"build:harmony-har": "node scripts/build-harmony-har.js",
|
|
16
|
-
"build:so": "bun submodule && $ANDROID_HOME/ndk/28.2.13676358/ndk-build NDK_PROJECT_PATH=android APP_BUILD_SCRIPT=android/jni/Android.mk NDK_APPLICATION_MK=android/jni/Application.mk NDK_LIBS_OUT=android/lib
|
|
16
|
+
"build:so": "bun submodule && $ANDROID_HOME/ndk/28.2.13676358/ndk-build NDK_PROJECT_PATH=android APP_BUILD_SCRIPT=android/jni/Android.mk NDK_APPLICATION_MK=android/jni/Application.mk NDK_LIBS_OUT=android/lib",
|
|
17
17
|
"build:ios-debug": "cd Example/testHotUpdate && bun && detox build --configuration ios.sim.debug",
|
|
18
18
|
"build:ios-release": "cd Example/testHotUpdate && bun && detox build --configuration ios.sim.release",
|
|
19
19
|
"test:ios-debug": "cd Example/testHotUpdate && E2E_PLATFORM=ios detox test --configuration ios.sim.debug",
|
|
@@ -88,7 +88,7 @@ Pod::Spec.new do |s|
|
|
|
88
88
|
|
|
89
89
|
s.cocoapods_version = '>= 1.6.0'
|
|
90
90
|
|
|
91
|
-
s.source = { :git => 'https://github.com/reactnativecn/react-native-update.git', :tag =>
|
|
91
|
+
s.source = { :git => 'https://github.com/reactnativecn/react-native-update.git', :tag => "#{s.version}" }
|
|
92
92
|
|
|
93
93
|
s.libraries = 'bz2', 'z'
|
|
94
94
|
s.pod_target_xcconfig = {
|
|
@@ -108,7 +108,7 @@ Pod::Spec.new do |s|
|
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
s.subspec 'RCTPushy' do |ss|
|
|
111
|
-
ss.source_files = ['ios
|
|
111
|
+
ss.source_files = ['ios/RCTPushy/*.{h,m,mm}',
|
|
112
112
|
'cpp/patch_core/archive_patch_core.{h,cpp}',
|
|
113
113
|
'cpp/patch_core/patch_core.{h,cpp}',
|
|
114
114
|
'cpp/patch_core/state_core.{h,cpp}',
|
|
@@ -117,7 +117,7 @@ Pod::Spec.new do |s|
|
|
|
117
117
|
'android/jni/HDiffPatch/file_for_patch.{h,c}',
|
|
118
118
|
'android/jni/lzma/C/LzmaDec.{h,c}',
|
|
119
119
|
'android/jni/lzma/C/Lzma2Dec.{h,c}']
|
|
120
|
-
ss.public_header_files = ['ios
|
|
120
|
+
ss.public_header_files = ['ios/RCTPushy/*.h']
|
|
121
121
|
end
|
|
122
122
|
|
|
123
123
|
# Conditionally add Expo subspec and check ExpoModulesCore version
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import { bundleManager } from '@kit.AbilityKit';
|
|
2
|
-
import common from '@ohos.app.ability.common';
|
|
3
|
-
import { UpdateContext } from './UpdateContext';
|
|
4
|
-
import logger from './Logger';
|
|
5
|
-
|
|
6
|
-
const TAG = 'UpdateModuleImpl';
|
|
7
|
-
|
|
8
|
-
export class UpdateModuleImpl {
|
|
9
|
-
static readonly NAME = 'Pushy';
|
|
10
|
-
|
|
11
|
-
static async downloadFullUpdate(
|
|
12
|
-
updateContext: UpdateContext,
|
|
13
|
-
options: { updateUrl: string; hash: string },
|
|
14
|
-
): Promise<void> {
|
|
15
|
-
return updateContext.downloadFullUpdate(options.updateUrl, options.hash);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
static async downloadPatchFromPackage(
|
|
19
|
-
updateContext: UpdateContext,
|
|
20
|
-
options: { updateUrl: string; hash: string },
|
|
21
|
-
): Promise<void> {
|
|
22
|
-
return updateContext.downloadPatchFromPackage(
|
|
23
|
-
options.updateUrl,
|
|
24
|
-
options.hash,
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
static async downloadPatchFromPpk(
|
|
29
|
-
updateContext: UpdateContext,
|
|
30
|
-
options: { updateUrl: string; hash: string; originHash: string },
|
|
31
|
-
): Promise<void> {
|
|
32
|
-
return updateContext.downloadPatchFromPpk(
|
|
33
|
-
options.updateUrl,
|
|
34
|
-
options.hash,
|
|
35
|
-
options.originHash,
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
static async reloadUpdate(
|
|
40
|
-
updateContext: UpdateContext,
|
|
41
|
-
context: common.UIAbilityContext,
|
|
42
|
-
options: { hash: string },
|
|
43
|
-
): Promise<void> {
|
|
44
|
-
const hash = options.hash;
|
|
45
|
-
if (!hash) {
|
|
46
|
-
throw Error('hash不能为空');
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
try {
|
|
50
|
-
await updateContext.switchVersion(hash);
|
|
51
|
-
const bundleInfo = await bundleManager.getBundleInfoForSelf(
|
|
52
|
-
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION,
|
|
53
|
-
);
|
|
54
|
-
await context.terminateSelf();
|
|
55
|
-
const want = {
|
|
56
|
-
bundleName: bundleInfo.name,
|
|
57
|
-
abilityName: context.abilityInfo?.name,
|
|
58
|
-
};
|
|
59
|
-
await context.startAbility(want);
|
|
60
|
-
} catch (error) {
|
|
61
|
-
logger.error(TAG, `reloadUpdate failed: ${error}`);
|
|
62
|
-
throw Error(`switchVersion failed ${error.message}`);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
static async setNeedUpdate(
|
|
67
|
-
updateContext: UpdateContext,
|
|
68
|
-
options: { hash: string },
|
|
69
|
-
): Promise<boolean> {
|
|
70
|
-
const hash = options.hash;
|
|
71
|
-
if (!hash) {
|
|
72
|
-
throw Error('empty hash');
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
await updateContext.switchVersion(hash);
|
|
77
|
-
return true;
|
|
78
|
-
} catch (error) {
|
|
79
|
-
logger.error(TAG, `setNeedUpdate failed: ${error}`);
|
|
80
|
-
throw Error(`switchVersionLater failed: ${error.message}`);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
static async markSuccess(updateContext: UpdateContext): Promise<boolean> {
|
|
85
|
-
try {
|
|
86
|
-
await updateContext.markSuccess();
|
|
87
|
-
return true;
|
|
88
|
-
} catch (error) {
|
|
89
|
-
logger.error(TAG, `markSuccess failed: ${error}`);
|
|
90
|
-
throw error;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
static async setUuid(
|
|
95
|
-
updateContext: UpdateContext,
|
|
96
|
-
uuid: string,
|
|
97
|
-
): Promise<void> {
|
|
98
|
-
return updateContext.setKv('uuid', uuid);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
static checkJson(json: string): boolean {
|
|
102
|
-
try {
|
|
103
|
-
JSON.parse(json);
|
|
104
|
-
return true;
|
|
105
|
-
} catch {
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
static setLocalHashInfo(
|
|
111
|
-
updateContext: UpdateContext,
|
|
112
|
-
hash: string,
|
|
113
|
-
info: string,
|
|
114
|
-
): boolean {
|
|
115
|
-
updateContext.setKv(`hash_${hash}`, info);
|
|
116
|
-
return true;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
static getLocalHashInfo(updateContext: UpdateContext, hash: string): string {
|
|
120
|
-
const value = updateContext.getKv(`hash_${hash}`);
|
|
121
|
-
return value;
|
|
122
|
-
}
|
|
123
|
-
}
|
package/ios/ImportReact.h
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// HDiffPatch.h
|
|
3
|
-
// RCTPushy
|
|
4
|
-
//
|
|
5
|
-
// Created by HouSisong, All rights reserved.
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
#import <Foundation/Foundation.h>
|
|
9
|
-
|
|
10
|
-
@interface HDiffPatch : NSObject
|
|
11
|
-
|
|
12
|
-
+ (BOOL)hdiffPatch:(NSString *)path
|
|
13
|
-
origin:(NSString *)origin
|
|
14
|
-
toDestination:(NSString *)destination;
|
|
15
|
-
|
|
16
|
-
@end
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// HDiffPatch.m
|
|
3
|
-
// RCTPushy
|
|
4
|
-
//
|
|
5
|
-
// Created by HouSisong, All rights reserved.
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
#import "HDiffPatch.h"
|
|
9
|
-
#include "../../../android/jni/hpatch.h"
|
|
10
|
-
|
|
11
|
-
@implementation HDiffPatch
|
|
12
|
-
|
|
13
|
-
+ (BOOL)hdiffPatch:(NSString *)patch
|
|
14
|
-
origin:(NSString *)origin
|
|
15
|
-
toDestination:(NSString *)destination
|
|
16
|
-
{
|
|
17
|
-
if (![[NSFileManager defaultManager] fileExistsAtPath:patch]) {
|
|
18
|
-
return NO;
|
|
19
|
-
}
|
|
20
|
-
if (![[NSFileManager defaultManager] fileExistsAtPath:origin]) {
|
|
21
|
-
return NO;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if ([[NSFileManager defaultManager] fileExistsAtPath:destination]) {
|
|
25
|
-
[[NSFileManager defaultManager] removeItemAtPath:destination error:nil];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
int err = hpatch_by_file([origin UTF8String], [destination UTF8String], [patch UTF8String]);
|
|
29
|
-
if (err) {
|
|
30
|
-
return NO;
|
|
31
|
-
}
|
|
32
|
-
return YES;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
@end
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
#import <Foundation/Foundation.h>
|
|
2
|
-
|
|
3
|
-
@interface RCTPushyManager : NSObject
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
- (BOOL)createDir:(NSString *)dir;
|
|
7
|
-
|
|
8
|
-
- (void)unzipFileAtPath:(NSString *)path
|
|
9
|
-
toDestination:(NSString *)destination
|
|
10
|
-
progressHandler:(void (^)(NSString *entry, long entryNumber, long total))progressHandler
|
|
11
|
-
completionHandler:(void (^)(NSString *path, BOOL succeeded, NSError *error))completionHandler;
|
|
12
|
-
|
|
13
|
-
- (void)hdiffFileAtPath:(NSString *)path
|
|
14
|
-
fromOrigin:(NSString *)origin
|
|
15
|
-
toDestination:(NSString *)destination
|
|
16
|
-
completionHandler:(void (^)(BOOL success))completionHandler;
|
|
17
|
-
|
|
18
|
-
- (void)copyFiles:(NSDictionary *)filesDic
|
|
19
|
-
fromDir:(NSString *)fromDir
|
|
20
|
-
toDir:(NSString *)toDir
|
|
21
|
-
deletes:(NSDictionary *)deletes
|
|
22
|
-
completionHandler:(void (^)(NSError *error))completionHandler;
|
|
23
|
-
|
|
24
|
-
- (void)removeFile:(NSString *)filePath
|
|
25
|
-
completionHandler:(void (^)(NSError *error))completionHandler;
|
|
26
|
-
|
|
27
|
-
@end
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
#import "RCTPushyManager.h"
|
|
2
|
-
#import "ZipArchive.h"
|
|
3
|
-
#import "HDiffPatch.h"
|
|
4
|
-
|
|
5
|
-
@implementation RCTPushyManager {
|
|
6
|
-
dispatch_queue_t _opQueue;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
- (instancetype)init
|
|
10
|
-
{
|
|
11
|
-
self = [super init];
|
|
12
|
-
if (self) {
|
|
13
|
-
_opQueue = dispatch_queue_create("cn.reactnative.pushy", DISPATCH_QUEUE_SERIAL);
|
|
14
|
-
}
|
|
15
|
-
return self;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
- (BOOL)createDir:(NSString *)dir
|
|
19
|
-
{
|
|
20
|
-
__block BOOL success = false;
|
|
21
|
-
|
|
22
|
-
dispatch_sync(_opQueue, ^{
|
|
23
|
-
BOOL isDir;
|
|
24
|
-
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
25
|
-
if ([fileManager fileExistsAtPath:dir isDirectory:&isDir]) {
|
|
26
|
-
if (isDir) {
|
|
27
|
-
success = true;
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
NSError *error;
|
|
33
|
-
[fileManager createDirectoryAtPath:dir
|
|
34
|
-
withIntermediateDirectories:YES
|
|
35
|
-
attributes:nil
|
|
36
|
-
error:&error];
|
|
37
|
-
if (!error) {
|
|
38
|
-
success = true;
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
return success;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
- (void)unzipFileAtPath:(NSString *)path
|
|
47
|
-
toDestination:(NSString *)destination
|
|
48
|
-
progressHandler:(void (^)(NSString *entry, long entryNumber, long total))progressHandler
|
|
49
|
-
completionHandler:(void (^)(NSString *path, BOOL succeeded, NSError *error))completionHandler
|
|
50
|
-
{
|
|
51
|
-
dispatch_async(_opQueue, ^{
|
|
52
|
-
|
|
53
|
-
if ([[NSFileManager defaultManager] fileExistsAtPath:destination]) {
|
|
54
|
-
[[NSFileManager defaultManager] removeItemAtPath:destination error:nil];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
[SSZipArchive unzipFileAtPath:path toDestination:destination progressHandler:^(NSString *entry, unz_file_info zipInfo, long entryNumber, long total) {
|
|
58
|
-
progressHandler(entry, entryNumber, total);
|
|
59
|
-
} completionHandler:^(NSString *path, BOOL succeeded, NSError *error) {
|
|
60
|
-
// 解压完,移除zip文件
|
|
61
|
-
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
|
|
62
|
-
if (completionHandler) {
|
|
63
|
-
completionHandler(path, succeeded, error);
|
|
64
|
-
}
|
|
65
|
-
}];
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
- (void)hdiffFileAtPath:(NSString *)path
|
|
70
|
-
fromOrigin:(NSString *)origin
|
|
71
|
-
toDestination:(NSString *)destination
|
|
72
|
-
completionHandler:(void (^)(BOOL success))completionHandler
|
|
73
|
-
{
|
|
74
|
-
dispatch_async(_opQueue, ^{
|
|
75
|
-
BOOL success = [HDiffPatch hdiffPatch:path origin:origin toDestination:destination];
|
|
76
|
-
if (completionHandler) {
|
|
77
|
-
completionHandler(success);
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
- (void)copyFiles:(NSDictionary *)filesDic
|
|
83
|
-
fromDir:(NSString *)fromDir
|
|
84
|
-
toDir:(NSString *)toDir
|
|
85
|
-
deletes:(NSDictionary *)deletes
|
|
86
|
-
completionHandler:(void (^)(NSError *error))completionHandler
|
|
87
|
-
{
|
|
88
|
-
dispatch_async(_opQueue, ^{
|
|
89
|
-
NSFileManager *fm = [NSFileManager defaultManager];
|
|
90
|
-
|
|
91
|
-
// merge old files
|
|
92
|
-
if (deletes!= nil) {
|
|
93
|
-
NSString *srcDir = [fromDir stringByAppendingPathComponent:@"assets"];
|
|
94
|
-
NSString *desDir = [toDir stringByAppendingPathComponent:@"assets"];
|
|
95
|
-
[self _mergeContentsOfPath:srcDir intoPath:desDir deletes:deletes];
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// copy files
|
|
99
|
-
for (NSString *to in filesDic.allKeys) {
|
|
100
|
-
NSString *from = filesDic[to];
|
|
101
|
-
if (from.length <=0) {
|
|
102
|
-
from = to;
|
|
103
|
-
}
|
|
104
|
-
NSString *fromPath = [fromDir stringByAppendingPathComponent:from];
|
|
105
|
-
NSString *toPath = [toDir stringByAppendingPathComponent:to];
|
|
106
|
-
|
|
107
|
-
if ([fm fileExistsAtPath:toPath]) {
|
|
108
|
-
[fm removeItemAtPath:toPath error:nil];
|
|
109
|
-
}
|
|
110
|
-
NSError *error = nil;
|
|
111
|
-
[fm copyItemAtPath:fromPath toPath:toPath error:&error];
|
|
112
|
-
if (error) {
|
|
113
|
-
NSLog(@"Pushy copy error: %@", error.localizedDescription);
|
|
114
|
-
// if (completionHandler) {
|
|
115
|
-
// completionHandler(error);
|
|
116
|
-
// }
|
|
117
|
-
// return;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
if (completionHandler) {
|
|
121
|
-
completionHandler(nil);
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
- (void)removeFile:(NSString *)filePath
|
|
127
|
-
completionHandler:(void (^)(NSError *error))completionHandler
|
|
128
|
-
{
|
|
129
|
-
dispatch_async(_opQueue, ^{
|
|
130
|
-
NSError *error = nil;
|
|
131
|
-
[[NSFileManager defaultManager] removeItemAtPath:filePath error:&error];
|
|
132
|
-
if (completionHandler) {
|
|
133
|
-
completionHandler(error);
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
- (void)_mergeContentsOfPath:(NSString *)srcDir intoPath:(NSString *)dstDir deletes:(NSDictionary *)deletes
|
|
139
|
-
{
|
|
140
|
-
NSFileManager *fm = [NSFileManager defaultManager];
|
|
141
|
-
NSDirectoryEnumerator *srcDirEnum = [fm enumeratorAtPath:srcDir];
|
|
142
|
-
NSString *subPath;
|
|
143
|
-
while ((subPath = [srcDirEnum nextObject])) {
|
|
144
|
-
|
|
145
|
-
NSString *srcFullPath = [srcDir stringByAppendingPathComponent:subPath];
|
|
146
|
-
NSString *potentialDstPath = [dstDir stringByAppendingPathComponent:subPath];
|
|
147
|
-
|
|
148
|
-
NSError *error = nil;
|
|
149
|
-
|
|
150
|
-
BOOL inDeletes = NO;
|
|
151
|
-
if (deletes) {
|
|
152
|
-
NSString *path = [@"assets" stringByAppendingPathComponent:subPath];
|
|
153
|
-
if (deletes[path]) {
|
|
154
|
-
inDeletes = YES;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
if (!inDeletes) {
|
|
158
|
-
BOOL isDirectory = ([fm fileExistsAtPath:srcFullPath isDirectory:&isDirectory] && isDirectory);
|
|
159
|
-
if (isDirectory) {
|
|
160
|
-
if (![fm fileExistsAtPath:potentialDstPath isDirectory:nil]) {
|
|
161
|
-
[fm createDirectoryAtPath:potentialDstPath withIntermediateDirectories:YES attributes:nil error:&error];
|
|
162
|
-
if (error) {
|
|
163
|
-
NSLog(@"Pushy merge error: %@", error.localizedDescription);
|
|
164
|
-
// return;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
if (![fm fileExistsAtPath:potentialDstPath]) {
|
|
170
|
-
[fm copyItemAtPath:srcFullPath toPath:potentialDstPath error:&error];
|
|
171
|
-
if (error) {
|
|
172
|
-
NSLog(@"Pushy merge error: %@", error.localizedDescription);
|
|
173
|
-
// return;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
@end
|