pbind 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pbind.rb +1 -88
- data/lib/pbind/command.rb +32 -2
- data/lib/pbind/command/mock.rb +109 -0
- data/lib/pbind/command/watch.rb +16 -21
- data/source/PBLiveLoader/PBDirectoryWatcher.h +38 -0
- data/source/PBLiveLoader/PBDirectoryWatcher.m +466 -0
- data/source/PBLiveLoader/PBLiveLoader.h +25 -0
- data/source/PBLiveLoader/PBLiveLoader.m +203 -0
- data/source/PBLocalhost/ignore.h +2 -2
- metadata +7 -6
- data/source/PBPlayground/PBPlayground.h +0 -19
- data/source/PBPlayground/PBPlayground.m +0 -237
- data/source/PBPlayground/SGDirWatchdog.h +0 -29
- data/source/PBPlayground/SGDirWatchdog.m +0 -163
@@ -0,0 +1,25 @@
|
|
1
|
+
//
|
2
|
+
// PBLiveLoader.h
|
3
|
+
// Pbind
|
4
|
+
//
|
5
|
+
// Created by Galen Lin on 2016/12/9.
|
6
|
+
//
|
7
|
+
|
8
|
+
#include <targetconditionals.h>
|
9
|
+
|
10
|
+
#if (DEBUG && TARGET_IPHONE_SIMULATOR)
|
11
|
+
|
12
|
+
#import <Foundation/Foundation.h>
|
13
|
+
|
14
|
+
/**
|
15
|
+
The live loader for Pbind.
|
16
|
+
|
17
|
+
@discussion while the application start, it will watch the project directories
|
18
|
+
to detect changes of all the *.plist files and all the *.json files under PBLocalhost
|
19
|
+
directory, by what we can instantly reload the related views.
|
20
|
+
*/
|
21
|
+
@interface PBLiveLoader : NSObject
|
22
|
+
|
23
|
+
@end
|
24
|
+
|
25
|
+
#endif
|
@@ -0,0 +1,203 @@
|
|
1
|
+
//
|
2
|
+
// PBLiveLoader.m
|
3
|
+
// Pbind
|
4
|
+
//
|
5
|
+
// Created by Galen Lin on 2016/12/9.
|
6
|
+
//
|
7
|
+
|
8
|
+
#import "PBLiveLoader.h"
|
9
|
+
|
10
|
+
#if (DEBUG && TARGET_IPHONE_SIMULATOR)
|
11
|
+
|
12
|
+
#import "PBDirectoryWatcher.h"
|
13
|
+
#import <Pbind/Pbind.h>
|
14
|
+
|
15
|
+
@implementation PBLiveLoader
|
16
|
+
|
17
|
+
static NSString *const PLIST_SUFFIX = @".plist";
|
18
|
+
static NSString *const JSON_SUFFIX = @".json";
|
19
|
+
static NSString *const IGNORES_SUFFIX = @"ignore.h";
|
20
|
+
|
21
|
+
static NSArray<NSString *> *kIgnoreAPIs;
|
22
|
+
static PBDirectoryWatcher *kResWatcher;
|
23
|
+
static PBDirectoryWatcher *kAPIWatcher;
|
24
|
+
|
25
|
+
static BOOL HasSuffix(NSString *src, NSString *tail)
|
26
|
+
{
|
27
|
+
NSInteger loc = [src rangeOfString:tail].location;
|
28
|
+
if (loc == NSNotFound) {
|
29
|
+
return NO;
|
30
|
+
}
|
31
|
+
|
32
|
+
return loc == src.length - tail.length;
|
33
|
+
}
|
34
|
+
|
35
|
+
+ (void)load {
|
36
|
+
[super load];
|
37
|
+
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidFinishLaunching:) name:UIApplicationDidFinishLaunchingNotification object:nil];
|
38
|
+
}
|
39
|
+
|
40
|
+
+ (void)applicationDidFinishLaunching:(id)note {
|
41
|
+
[self watchPlist];
|
42
|
+
[self watchAPI];
|
43
|
+
}
|
44
|
+
|
45
|
+
+ (void)watchPlist {
|
46
|
+
NSString *resPath = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"PBResourcesPath"];
|
47
|
+
if (resPath == nil) {
|
48
|
+
NSLog(@"PBPlayground: Please define PBResourcesPath in Info.plist with value '$(SRCROOT)/[path-to-resources]'!");
|
49
|
+
return;
|
50
|
+
}
|
51
|
+
|
52
|
+
if (![[NSFileManager defaultManager] fileExistsAtPath:resPath]) {
|
53
|
+
NSLog(@"PBPlayground: PBResourcesPath is not exists! (%@)", resPath);
|
54
|
+
return;
|
55
|
+
}
|
56
|
+
|
57
|
+
kResWatcher = [[PBDirectoryWatcher alloc] init];
|
58
|
+
[kResWatcher watchDir:resPath handler:^(NSString *path, BOOL initial, PBDirEvent event) {
|
59
|
+
switch (event) {
|
60
|
+
case PBDirEventNewFile:
|
61
|
+
if (HasSuffix(path, PLIST_SUFFIX)) {
|
62
|
+
NSBundle *updatedBundle = [NSBundle bundleWithPath:[path stringByDeletingLastPathComponent]];
|
63
|
+
[Pbind addResourcesBundle:updatedBundle];
|
64
|
+
}
|
65
|
+
break;
|
66
|
+
|
67
|
+
case PBDirEventModifyFile:
|
68
|
+
if (HasSuffix(path, PLIST_SUFFIX)) {
|
69
|
+
[Pbind reloadViewsOnPlistUpdate:path];
|
70
|
+
}
|
71
|
+
break;
|
72
|
+
|
73
|
+
case PBDirEventDeleteFile:
|
74
|
+
if (HasSuffix(path, PLIST_SUFFIX)) {
|
75
|
+
[Pbind reloadViewsOnPlistUpdate:path];
|
76
|
+
}
|
77
|
+
break;
|
78
|
+
|
79
|
+
default:
|
80
|
+
break;
|
81
|
+
}
|
82
|
+
}];
|
83
|
+
}
|
84
|
+
|
85
|
+
+ (void)watchAPI {
|
86
|
+
NSString *serverPath = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"PBLocalhost"];
|
87
|
+
if (serverPath == nil) {
|
88
|
+
NSLog(@"PBPlayground: Please define PBLocalhost in Info.plist with value '$(SRCROOT)/[path-to-api]'!");
|
89
|
+
return;
|
90
|
+
}
|
91
|
+
|
92
|
+
if (![[NSFileManager defaultManager] fileExistsAtPath:serverPath]) {
|
93
|
+
NSLog(@"PBPlayground: PBLocalhost is not exists! (%@)", serverPath);
|
94
|
+
return;
|
95
|
+
}
|
96
|
+
|
97
|
+
kAPIWatcher = [[PBDirectoryWatcher alloc] init];
|
98
|
+
[kAPIWatcher watchDir:serverPath handler:^(NSString *path, BOOL initial, PBDirEvent event) {
|
99
|
+
switch (event) {
|
100
|
+
case PBDirEventNewFile:
|
101
|
+
if (HasSuffix(path, IGNORES_SUFFIX)) {
|
102
|
+
kIgnoreAPIs = [self ignoreAPIsWithContentsOfFile:path];
|
103
|
+
}
|
104
|
+
break;
|
105
|
+
|
106
|
+
case PBDirEventModifyFile:
|
107
|
+
if (HasSuffix(path, JSON_SUFFIX)) {
|
108
|
+
[self reloadViewsOnJSONChange:path deleted:NO];
|
109
|
+
} else if (HasSuffix(path, IGNORES_SUFFIX)) {
|
110
|
+
[self reloadViewsOnIgnoresChange:path deleted:NO];
|
111
|
+
}
|
112
|
+
break;
|
113
|
+
|
114
|
+
case PBDirEventDeleteFile:
|
115
|
+
if (HasSuffix(path, JSON_SUFFIX)) {
|
116
|
+
[self reloadViewsOnJSONChange:path deleted:YES];
|
117
|
+
} else if (HasSuffix(path, IGNORES_SUFFIX)) {
|
118
|
+
[self reloadViewsOnIgnoresChange:path deleted:YES];
|
119
|
+
}
|
120
|
+
break;
|
121
|
+
|
122
|
+
default:
|
123
|
+
break;
|
124
|
+
}
|
125
|
+
}];
|
126
|
+
|
127
|
+
[PBClient registerDebugServer:^id(PBClient *client, PBRequest *request) {
|
128
|
+
NSString *action = request.action;
|
129
|
+
if ([action characterAtIndex:0] == '/') {
|
130
|
+
action = [action substringFromIndex:1]; // bypass '/'
|
131
|
+
}
|
132
|
+
|
133
|
+
if (kIgnoreAPIs != nil && [kIgnoreAPIs containsObject:action]) {
|
134
|
+
return nil;
|
135
|
+
}
|
136
|
+
|
137
|
+
NSString *jsonName = [NSString stringWithFormat:@"%@/%@.json", [[client class] description], action];
|
138
|
+
NSString *jsonPath = [serverPath stringByAppendingPathComponent:jsonName];
|
139
|
+
if (![[NSFileManager defaultManager] fileExistsAtPath:jsonPath]) {
|
140
|
+
NSLog(@"PBPlayground: Missing '%@', ignores!", jsonName);
|
141
|
+
return nil;
|
142
|
+
}
|
143
|
+
NSData *jsonData = [NSData dataWithContentsOfFile:jsonPath];
|
144
|
+
NSError *error = nil;
|
145
|
+
id response = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
|
146
|
+
if (error != nil) {
|
147
|
+
NSLog(@"PBPlayground: Invalid '%@', ignores!", jsonName);
|
148
|
+
return nil;
|
149
|
+
}
|
150
|
+
|
151
|
+
return response;
|
152
|
+
}];
|
153
|
+
}
|
154
|
+
|
155
|
+
+ (NSArray *)ignoreAPIsWithContentsOfFile:(NSString *)path {
|
156
|
+
NSString *content = [[NSString alloc] initWithData:[NSData dataWithContentsOfFile:path] encoding:NSUTF8StringEncoding];
|
157
|
+
return [[content componentsSeparatedByString:@"\n"] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"NOT (SELF BEGINSWITH '//') AND NOT (SELF == '')"]];
|
158
|
+
}
|
159
|
+
|
160
|
+
+ (void)reloadViewsOnJSONChange:(NSString *)path deleted:(BOOL)deleted {
|
161
|
+
NSArray *components = [path componentsSeparatedByString:@"/"];
|
162
|
+
NSString *name = [components lastObject];
|
163
|
+
components = [name componentsSeparatedByString:@"."];
|
164
|
+
name = [components firstObject];
|
165
|
+
[Pbind reloadViewsOnAPIUpdate:name];
|
166
|
+
}
|
167
|
+
|
168
|
+
+ (void)reloadViewsOnIgnoresChange:(NSString *)path deleted:(BOOL)deleted {
|
169
|
+
BOOL clear = deleted;
|
170
|
+
NSArray *oldIgnores = kIgnoreAPIs;
|
171
|
+
NSArray *newIgnores = [self ignoreAPIsWithContentsOfFile:path];
|
172
|
+
if (newIgnores.count == 0) {
|
173
|
+
clear = YES;
|
174
|
+
}
|
175
|
+
if (clear) {
|
176
|
+
kIgnoreAPIs = nil;
|
177
|
+
for (NSString *action in oldIgnores) {
|
178
|
+
[Pbind reloadViewsOnAPIUpdate:action];
|
179
|
+
}
|
180
|
+
return;
|
181
|
+
}
|
182
|
+
|
183
|
+
NSArray *changedIgnores;
|
184
|
+
|
185
|
+
if (oldIgnores != nil) {
|
186
|
+
NSArray *deletedIgnores = [oldIgnores filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"NOT SELF IN %@", newIgnores]];
|
187
|
+
NSArray *addedIgnores = [newIgnores filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"NOT SELF IN %@", oldIgnores]];
|
188
|
+
changedIgnores = [deletedIgnores arrayByAddingObjectsFromArray:addedIgnores];
|
189
|
+
} else {
|
190
|
+
changedIgnores = newIgnores;
|
191
|
+
}
|
192
|
+
|
193
|
+
kIgnoreAPIs = newIgnores;
|
194
|
+
if (changedIgnores.count > 0) {
|
195
|
+
for (NSString *action in changedIgnores) {
|
196
|
+
[Pbind reloadViewsOnAPIUpdate:action];
|
197
|
+
}
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
@end
|
202
|
+
|
203
|
+
#endif
|
data/source/PBLocalhost/ignore.h
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
// Add API actions at each line to prevent it from local
|
2
|
-
//
|
1
|
+
// Add API actions at each line to prevent it from local mocking.
|
2
|
+
// You can use [⌘+/] to switch whether ignores or not.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pbind
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Galen Lin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-11
|
11
|
+
date: 2016-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: xcodeproj
|
@@ -60,12 +60,13 @@ files:
|
|
60
60
|
- bin/pbind
|
61
61
|
- lib/pbind.rb
|
62
62
|
- lib/pbind/command.rb
|
63
|
+
- lib/pbind/command/mock.rb
|
63
64
|
- lib/pbind/command/watch.rb
|
65
|
+
- source/PBLiveLoader/PBDirectoryWatcher.h
|
66
|
+
- source/PBLiveLoader/PBDirectoryWatcher.m
|
67
|
+
- source/PBLiveLoader/PBLiveLoader.h
|
68
|
+
- source/PBLiveLoader/PBLiveLoader.m
|
64
69
|
- source/PBLocalhost/ignore.h
|
65
|
-
- source/PBPlayground/PBPlayground.h
|
66
|
-
- source/PBPlayground/PBPlayground.m
|
67
|
-
- source/PBPlayground/SGDirWatchdog.h
|
68
|
-
- source/PBPlayground/SGDirWatchdog.m
|
69
70
|
homepage: http://rubygems.org/gems/pbind
|
70
71
|
licenses:
|
71
72
|
- MIT
|
@@ -1,19 +0,0 @@
|
|
1
|
-
//
|
2
|
-
// PBPlayground.h
|
3
|
-
// Pbind
|
4
|
-
//
|
5
|
-
// Created by Galen Lin on 16/9/22.
|
6
|
-
// Copyright © 2016年 galenlin. All rights reserved.
|
7
|
-
//
|
8
|
-
|
9
|
-
#include <targetconditionals.h>
|
10
|
-
|
11
|
-
#if (DEBUG && TARGET_IPHONE_SIMULATOR)
|
12
|
-
|
13
|
-
#import <Foundation/Foundation.h>
|
14
|
-
|
15
|
-
@interface PBPlayground : NSObject
|
16
|
-
|
17
|
-
@end
|
18
|
-
|
19
|
-
#endif
|
@@ -1,237 +0,0 @@
|
|
1
|
-
//
|
2
|
-
// PBPlayground.m
|
3
|
-
// Pbind
|
4
|
-
//
|
5
|
-
// Created by Galen Lin on 16/9/22.
|
6
|
-
// Copyright © 2016年 galenlin. All rights reserved.
|
7
|
-
//
|
8
|
-
|
9
|
-
#import "PBPlayground.h"
|
10
|
-
|
11
|
-
#if (DEBUG && TARGET_IPHONE_SIMULATOR)
|
12
|
-
|
13
|
-
#import "SGDirWatchdog.h"
|
14
|
-
#import <Pbind/Pbind.h>
|
15
|
-
|
16
|
-
#include <stdio.h>
|
17
|
-
#include <string.h>
|
18
|
-
#include <sys/types.h>
|
19
|
-
#include <dirent.h>
|
20
|
-
#include <sys/stat.h>
|
21
|
-
|
22
|
-
typedef void(^file_handler)(const char *parent, const char *current, const char *name);
|
23
|
-
|
24
|
-
int walk_dir(const char *path, int depth, file_handler handler) {
|
25
|
-
DIR *d;
|
26
|
-
struct dirent *file;
|
27
|
-
struct stat sb;
|
28
|
-
char subdir[256];
|
29
|
-
|
30
|
-
if (!(d = opendir(path))) {
|
31
|
-
NSLog(@"error opendir %s!", path);
|
32
|
-
return -1;
|
33
|
-
}
|
34
|
-
|
35
|
-
while ((file = readdir(d)) != NULL) {
|
36
|
-
const char *name = file->d_name;
|
37
|
-
if (*name == '.') {
|
38
|
-
continue;
|
39
|
-
}
|
40
|
-
|
41
|
-
sprintf(subdir, "%s/%s", path, name);
|
42
|
-
if (stat(subdir, &sb) < 0) {
|
43
|
-
continue;
|
44
|
-
}
|
45
|
-
|
46
|
-
if (S_ISDIR(sb.st_mode)) {
|
47
|
-
walk_dir(subdir, depth + 1, handler);
|
48
|
-
continue;
|
49
|
-
}
|
50
|
-
|
51
|
-
handler(path, subdir, name);
|
52
|
-
}
|
53
|
-
|
54
|
-
closedir(d);
|
55
|
-
|
56
|
-
return 0;
|
57
|
-
}
|
58
|
-
|
59
|
-
UIViewController *topcontroller(UIViewController *controller)
|
60
|
-
{
|
61
|
-
UIViewController *presentedController = [controller presentedViewController];
|
62
|
-
if (presentedController != nil) {
|
63
|
-
return topcontroller(controller);
|
64
|
-
}
|
65
|
-
|
66
|
-
if ([controller isKindOfClass:[UINavigationController class]]) {
|
67
|
-
return topcontroller([(id)controller topViewController]);
|
68
|
-
}
|
69
|
-
|
70
|
-
if ([controller isKindOfClass:[UITabBarController class]]) {
|
71
|
-
return topcontroller([(id)controller selectedViewController]);
|
72
|
-
}
|
73
|
-
|
74
|
-
return controller;
|
75
|
-
}
|
76
|
-
|
77
|
-
@implementation PBPlayground
|
78
|
-
|
79
|
-
static NSMutableDictionary<NSString *, SGDirWatchdog *> *kPlistWatchdogs;
|
80
|
-
static NSMutableDictionary<NSString *, SGDirWatchdog *> *kJsonWatchdogs;
|
81
|
-
|
82
|
-
static SGDirWatchdog *kIgnoreAPIWatchdog;
|
83
|
-
static NSArray *kIgnoreAPIs;
|
84
|
-
static NSString *kIgnoresFile;
|
85
|
-
|
86
|
-
static dispatch_block_t onPlistUpdate = ^{
|
87
|
-
UIViewController *controller = [[[UIApplication sharedApplication].delegate window] rootViewController];
|
88
|
-
controller = topcontroller(controller);
|
89
|
-
[controller.view pb_reloadPlist];
|
90
|
-
};
|
91
|
-
|
92
|
-
static dispatch_block_t onJsonUpdate = ^{
|
93
|
-
UIViewController *controller = [[[UIApplication sharedApplication].delegate window] rootViewController];
|
94
|
-
controller = topcontroller(controller);
|
95
|
-
[controller.view pb_reloadClient];
|
96
|
-
};
|
97
|
-
|
98
|
-
static dispatch_block_t onIgnoresUpdate = ^{
|
99
|
-
if (![[NSFileManager defaultManager] fileExistsAtPath:kIgnoresFile]) {
|
100
|
-
return;
|
101
|
-
}
|
102
|
-
|
103
|
-
NSString *content = [[NSString alloc] initWithData:[NSData dataWithContentsOfFile:kIgnoresFile] encoding:NSUTF8StringEncoding];
|
104
|
-
kIgnoreAPIs = [[content componentsSeparatedByString:@"\n"] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"NOT (SELF BEGINSWITH '//')"]];
|
105
|
-
onJsonUpdate();
|
106
|
-
};
|
107
|
-
|
108
|
-
|
109
|
-
+ (void)load {
|
110
|
-
[super load];
|
111
|
-
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidFinishLaunching:) name:UIApplicationDidFinishLaunchingNotification object:nil];
|
112
|
-
}
|
113
|
-
|
114
|
-
+ (void)applicationDidFinishLaunching:(id)note {
|
115
|
-
[self watchPlist];
|
116
|
-
[self watchAPI];
|
117
|
-
}
|
118
|
-
|
119
|
-
+ (void)watchPlist {
|
120
|
-
NSString *resPath = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"PBResourcesPath"];
|
121
|
-
if (resPath == nil) {
|
122
|
-
NSLog(@"PBPlayground: Please define PBResourcesPath in Info.plist with value '$(SRCROOT)/[path-to-resources]'!");
|
123
|
-
return;
|
124
|
-
}
|
125
|
-
|
126
|
-
if (![[NSFileManager defaultManager] fileExistsAtPath:resPath]) {
|
127
|
-
NSLog(@"PBPlayground: PBResourcesPath is not exists! (%@)", resPath);
|
128
|
-
return;
|
129
|
-
}
|
130
|
-
|
131
|
-
NSMutableArray *resPaths = [[NSMutableArray alloc] init];
|
132
|
-
|
133
|
-
walk_dir([resPath UTF8String], 0, ^(const char *parent, const char *current, const char *name) {
|
134
|
-
size_t len = strlen(name);
|
135
|
-
if (len < 7) return;
|
136
|
-
|
137
|
-
char *p = (char *)name + len - 6;
|
138
|
-
if (strcmp(p, ".plist") != 0) return;
|
139
|
-
|
140
|
-
NSString *parentPath = [[NSString alloc] initWithUTF8String:parent];
|
141
|
-
if (![resPaths containsObject:parentPath]) {
|
142
|
-
[resPaths addObject:parentPath];
|
143
|
-
}
|
144
|
-
});
|
145
|
-
|
146
|
-
if (resPaths.count == 0) {
|
147
|
-
NSLog(@"PBPlayground: Could not found any *.plist!");
|
148
|
-
return;
|
149
|
-
}
|
150
|
-
|
151
|
-
kPlistWatchdogs = [NSMutableDictionary dictionaryWithCapacity:resPaths.count];
|
152
|
-
|
153
|
-
for (NSString *path in resPaths) {
|
154
|
-
[Pbind addResourcesBundle:[NSBundle bundleWithPath:path]];
|
155
|
-
|
156
|
-
SGDirWatchdog *watchdog = [[SGDirWatchdog alloc] initWithPath:path update:onPlistUpdate];
|
157
|
-
[kPlistWatchdogs setValue:watchdog forKey:path];
|
158
|
-
[watchdog start];
|
159
|
-
}
|
160
|
-
}
|
161
|
-
|
162
|
-
+ (void)watchAPI {
|
163
|
-
NSString *serverPath = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"PBLocalhost"];
|
164
|
-
if (serverPath == nil) {
|
165
|
-
NSLog(@"PBPlayground: Please define PBLocalhost in Info.plist with value '$(SRCROOT)/[path-to-api]'!");
|
166
|
-
return;
|
167
|
-
}
|
168
|
-
|
169
|
-
if (![[NSFileManager defaultManager] fileExistsAtPath:serverPath]) {
|
170
|
-
NSLog(@"PBPlayground: PBLocalhost is not exists! (%@)", serverPath);
|
171
|
-
return;
|
172
|
-
}
|
173
|
-
|
174
|
-
kIgnoreAPIWatchdog = [[SGDirWatchdog alloc] initWithPath:serverPath update:onIgnoresUpdate];
|
175
|
-
kIgnoresFile = [serverPath stringByAppendingPathComponent:@"ignore.h"];
|
176
|
-
onIgnoresUpdate();
|
177
|
-
[kIgnoreAPIWatchdog start];
|
178
|
-
|
179
|
-
NSMutableArray *jsonPaths = [[NSMutableArray alloc] init];
|
180
|
-
|
181
|
-
walk_dir([serverPath UTF8String], 0, ^(const char *parent, const char *current, const char *name) {
|
182
|
-
size_t len = strlen(name);
|
183
|
-
if (len < 6) return;
|
184
|
-
|
185
|
-
char *p = (char *)name + len - 5;
|
186
|
-
if (strcmp(p, ".json") != 0) return;
|
187
|
-
|
188
|
-
NSString *parentPath = [[NSString alloc] initWithUTF8String:parent];
|
189
|
-
if (![jsonPaths containsObject:parentPath]) {
|
190
|
-
[jsonPaths addObject:parentPath];
|
191
|
-
}
|
192
|
-
});
|
193
|
-
|
194
|
-
if (jsonPaths.count == 0) {
|
195
|
-
NSLog(@"PBPlayground: Could not found any *.json!");
|
196
|
-
return;
|
197
|
-
}
|
198
|
-
|
199
|
-
kJsonWatchdogs = [NSMutableDictionary dictionaryWithCapacity:jsonPaths.count];
|
200
|
-
|
201
|
-
for (NSString *path in jsonPaths) {
|
202
|
-
SGDirWatchdog *watchdog = [[SGDirWatchdog alloc] initWithPath:path update:onJsonUpdate];
|
203
|
-
[kPlistWatchdogs setValue:watchdog forKey:path];
|
204
|
-
[watchdog start];
|
205
|
-
}
|
206
|
-
|
207
|
-
[PBClient registerDebugServer:^id(PBClient *client, PBRequest *request) {
|
208
|
-
NSString *action = request.action;
|
209
|
-
if ([action characterAtIndex:0] == '/') {
|
210
|
-
action = [action substringFromIndex:1]; // bypass '/'
|
211
|
-
}
|
212
|
-
|
213
|
-
if (kIgnoreAPIs != nil && [kIgnoreAPIs containsObject:action]) {
|
214
|
-
return nil;
|
215
|
-
}
|
216
|
-
|
217
|
-
NSString *jsonName = [NSString stringWithFormat:@"%@/%@.json", [[client class] description], action];
|
218
|
-
NSString *jsonPath = [serverPath stringByAppendingPathComponent:jsonName];
|
219
|
-
if (![[NSFileManager defaultManager] fileExistsAtPath:jsonPath]) {
|
220
|
-
NSLog(@"PBPlayground: Missing '%@', ignores!", jsonName);
|
221
|
-
return nil;
|
222
|
-
}
|
223
|
-
NSData *jsonData = [NSData dataWithContentsOfFile:jsonPath];
|
224
|
-
NSError *error = nil;
|
225
|
-
id response = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
|
226
|
-
if (error != nil) {
|
227
|
-
NSLog(@"PBPlayground: Invalid '%@', ignores!", jsonName);
|
228
|
-
return nil;
|
229
|
-
}
|
230
|
-
|
231
|
-
return response;
|
232
|
-
}];
|
233
|
-
}
|
234
|
-
|
235
|
-
@end
|
236
|
-
|
237
|
-
#endif
|