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.
Files changed (44) hide show
  1. package/android/build.gradle +0 -6
  2. package/android/jni/Application.mk +1 -1
  3. package/android/lib/arm64-v8a/librnupdate.so +0 -0
  4. package/android/lib/armeabi-v7a/librnupdate.so +0 -0
  5. package/android/lib/x86/librnupdate.so +0 -0
  6. package/android/lib/x86_64/librnupdate.so +0 -0
  7. package/android/src/main/java/cn/reactnative/modules/update/BundledResourceCopier.java +314 -0
  8. package/android/src/main/java/cn/reactnative/modules/update/DownloadTask.java +253 -586
  9. package/android/src/main/java/cn/reactnative/modules/update/NativeUpdateCore.java +1 -9
  10. package/android/src/main/java/cn/reactnative/modules/update/ReactReloadManager.java +220 -0
  11. package/android/src/main/java/cn/reactnative/modules/update/SafeZipFile.java +9 -3
  12. package/android/src/main/java/cn/reactnative/modules/update/UiThreadRunner.java +36 -0
  13. package/android/src/main/java/cn/reactnative/modules/update/UpdateContext.java +36 -26
  14. package/android/src/main/java/cn/reactnative/modules/update/UpdateEventEmitter.java +39 -0
  15. package/android/src/main/java/cn/reactnative/modules/update/UpdateFileUtils.java +74 -0
  16. package/android/src/main/java/cn/reactnative/modules/update/UpdateModuleImpl.java +143 -260
  17. package/android/src/main/java/cn/reactnative/modules/update/UpdateModuleSupport.java +63 -0
  18. package/android/src/main/java/cn/reactnative/modules/update/UpdatePackage.java +1 -5
  19. package/android/src/newarch/cn/reactnative/modules/update/UpdateModule.java +26 -73
  20. package/android/src/oldarch/cn/reactnative/modules/update/UpdateModule.java +28 -242
  21. package/harmony/pushy/src/main/cpp/PushyTurboModule.cpp +89 -135
  22. package/harmony/pushy/src/main/cpp/PushyTurboModule.h +5 -5
  23. package/harmony/pushy/src/main/ets/DownloadTaskParams.ts +7 -7
  24. package/harmony/pushy/src/main/ets/PushyPackage.ets +3 -9
  25. package/harmony/pushy/src/main/ets/PushyPackageCompat.ts +3 -9
  26. package/harmony/pushy/src/main/ets/PushyPackageFactory.ts +14 -0
  27. package/harmony/pushy/src/main/ets/PushyTurboModule.ts +124 -24
  28. package/harmony/pushy/src/main/ets/UpdateContext.ts +92 -70
  29. package/harmony/pushy.har +0 -0
  30. package/ios/Expo/ExpoPushyReactDelegateHandler.swift +6 -26
  31. package/ios/RCTPushy/RCTPushy.mm +315 -259
  32. package/ios/RCTPushy/RCTPushyDownloader.mm +52 -29
  33. package/package.json +2 -2
  34. package/react-native-update.podspec +3 -3
  35. package/harmony/pushy/src/main/ets/UpdateModuleImpl.ts +0 -123
  36. package/ios/ImportReact.h +0 -2
  37. package/ios/RCTPushy/HDiffPatch/HDiffPatch.h +0 -16
  38. package/ios/RCTPushy/HDiffPatch/HDiffPatch.mm +0 -35
  39. package/ios/RCTPushy/RCTPushyManager.h +0 -27
  40. package/ios/RCTPushy/RCTPushyManager.mm +0 -181
  41. package/ios/RCTPushy.xcodeproj/project.pbxproj +0 -479
  42. package/package/harmony/pushy.har +0 -0
  43. package/react-native-update-10.39.0-beta.3.tgz +0 -0
  44. package/scripts/prune-host-stl.sh +0 -6
@@ -1,10 +1,15 @@
1
1
  #import "RCTPushyDownloader.h"
2
2
 
3
- @interface RCTPushyDownloader()<NSURLSessionDelegate>
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 download:downloadPath];
29
+ [downloader startDownload:downloadPath];
25
30
  }
26
31
 
27
- - (void)dealloc
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
- NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig
37
- delegate:self
38
- delegateQueue:nil];
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
- NSData *data = [NSData dataWithContentsOfURL:location];
65
- NSError *error;
66
- [data writeToFile:self.savePath options:NSDataWritingAtomic error:&error];
67
- if (error) {
68
- if (self.completionHandler) {
69
- self.completionHandler(nil, error);
70
- self.completionHandler = nil;
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
- if (self.completionHandler) {
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.39.0",
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 && ./scripts/prune-host-stl.sh 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 => '#{s.version}' }
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/**/*.{h,m,mm,c}',
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/**/*.h']
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,2 +0,0 @@
1
- @import React;
2
-
@@ -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