Files
cappuccino/Tools/XcodeCapp/XcodeCapp/XCCSourcesFinderOperation.m
T

172 lines
6.7 KiB
Objective-C

//
// FindSourceFilesOperation.m
// XcodeCapp
//
// Created by Aparajita on 4/27/13.
// Copyright (c) 2013 Cappuccino Project. All rights reserved.
//
#import "XCCSourcesFinderOperation.h"
#import "XCCSourceProcessingOperation.h"
#import "XCCTaskLauncher.h"
NSString * const XCCSourcesFinderOperationDidStartNotification = @"XCCSourcesFinderOperationDidStartNotification";
NSString * const XCCSourcesFinderOperationDidEndNotification = @"XCCSourcesFinderOperationDidEndNotification";
NSString * const XCCNeedSourceToProjectPathMappingNotification = @"XCCNeedSourceToProjectPathMappingNotification";
@implementation XCCSourcesFinderOperation
#pragma mark - Initialization
- (instancetype)initWithCappuccinoProject:(XCCCappuccinoProject *)aCappuccinoProject taskLauncher:(XCCTaskLauncher*)aTaskLauncher sourcePath:(NSString *)sourcePath
{
if (self = [super initWithCappuccinoProject:aCappuccinoProject taskLauncher:aTaskLauncher])
{
self.operationName = @"Searching for Objective-J files";
self.operationDescription = self.cappuccinoProject.name;
self->searchPath = sourcePath;
}
return self;
}
#pragma mark - Utilities
- (NSArray *)_findSourceFilesAtProjectPath:(NSString *)aProjectPath
{
NSError *error = NULL;
NSString *projectPath = [self.cappuccinoProject.projectPath stringByAppendingPathComponent:aProjectPath];
NSFileManager *fm = [NSFileManager defaultManager];
NSMutableArray *sourcePaths = [@[] mutableCopy];
NSArray *urls = [fm contentsOfDirectoryAtURL:[NSURL fileURLWithPath:projectPath.stringByResolvingSymlinksInPath]
includingPropertiesForKeys:@[NSURLIsDirectoryKey, NSURLIsSymbolicLinkKey]
options:NSDirectoryEnumerationSkipsHiddenFiles | NSDirectoryEnumerationSkipsPackageDescendants | NSDirectoryEnumerationSkipsSubdirectoryDescendants
error:&error];
if (!urls)
return [@[] mutableCopy];
for (NSURL *url in urls)
{
NSString *filename = url.lastPathComponent;
NSString *projectRelativePath = [aProjectPath stringByAppendingPathComponent:filename];
NSString *realPath = url.path;
NSURL *resolvedURL = url;
NSNumber *isDirectory;
NSNumber *isSymlink;
[url getResourceValue:&isSymlink forKey:NSURLIsSymbolicLinkKey error:nil];
if (isSymlink.boolValue == YES)
{
resolvedURL = [url URLByResolvingSymlinksInPath];
if ([resolvedURL checkResourceIsReachableAndReturnError:nil])
{
filename = resolvedURL.lastPathComponent;
realPath = resolvedURL.path;
}
else
continue;
}
[resolvedURL getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:nil];
if (isDirectory.boolValue == YES)
{
if ([XCCCappuccinoProject shouldIgnoreDirectoryNamed:filename])
{
NSLog(@"%@: ignored symlinked directory: %@", self.cappuccinoProject.name, projectRelativePath);
continue;
}
// If the resolved path is not within the project directory and is not ignored, add a mapping to it
// so we can map the resolved path back to the project directory later.
if (isSymlink.boolValue == YES)
{
NSString *fullProjectPath = [self.cappuccinoProject.projectPath stringByAppendingPathComponent:projectRelativePath];
if (![realPath hasPrefix:fullProjectPath] && ![XCCCappuccinoProject pathMatchesIgnoredPaths:fullProjectPath cappuccinoProjectIgnoredPathPredicates:self.cappuccinoProject.ignoredPathPredicates])
{
NSLog(@"%@: symlinked directory: %@ -> %@", self.cappuccinoProject.name, projectRelativePath, realPath);
NSMutableDictionary *info = [self operationInformations];
info[@"sourcePath"] = realPath;
info[@"projectPath"] = fullProjectPath;
[self dispatchNotificationName:XCCNeedSourceToProjectPathMappingNotification userInfo:info];
}
else
NSLog(@"%@: ignored symlinked directory: %@", self.cappuccinoProject.name, projectRelativePath);
}
NSLog(@"%@: found directory. checking for source files: %@", self.cappuccinoProject.name, filename);
[sourcePaths addObjectsFromArray:[self _findSourceFilesAtProjectPath:projectRelativePath]];
continue;
}
if ([XCCCappuccinoProject pathMatchesIgnoredPaths:realPath cappuccinoProjectIgnoredPathPredicates:self.cappuccinoProject.ignoredPathPredicates])
continue;
NSString *projectSourcePath = [self.cappuccinoProject.projectPath stringByAppendingPathComponent:projectRelativePath];
if ([XCCCappuccinoProject isObjjFile:filename] || [XCCCappuccinoProject isXibFile:filename])
{
NSLog(@"%@: found source file: %@", self.cappuccinoProject.name, filename);
NSString *processedPath;
if ([XCCCappuccinoProject isObjjFile:filename])
processedPath = [[self.cappuccinoProject shadowBasePathForProjectSourcePath:projectSourcePath] stringByAppendingPathExtension:@"h"];
else
processedPath = [projectSourcePath.stringByDeletingPathExtension stringByAppendingPathExtension:@"cib"];
if (![fm fileExistsAtPath:processedPath])
[sourcePaths addObject:projectSourcePath];
}
}
return sourcePaths;
}
#pragma mark - NSOperation API
- (void)main
{
NSLog(@"Finding source files started");
NSArray *sourcesPaths;
[self dispatchNotificationName:XCCSourcesFinderOperationDidStartNotification userInfo:@{@"cappuccinoProject": self.cappuccinoProject, @"sourcePaths" : @[]}];
@try
{
sourcesPaths = [self _findSourceFilesAtProjectPath:self->searchPath];
}
@catch (NSException *exception)
{
NSLog(@"Finding source files failed: %@", exception);
}
@finally
{
__block XCCSourcesFinderOperation *weakOperation = self;
__block NSArray * weakSourcesPaths = sourcesPaths;
self.completionBlock = ^{
[weakOperation dispatchNotificationName:XCCSourcesFinderOperationDidEndNotification userInfo:@{@"cappuccinoProject": weakOperation.cappuccinoProject, @"sourcePaths" : weakSourcesPaths}];
[weakOperation setCompletionBlock:nil];
};
}
NSLog(@"Finding source files ended");
}
@end