//
// P4SearchItem.m
// Perforce
//
// Created by Adam Czubernat on 13/01/2014.
// Copyright (c) 2014 Perforce Software, Inc. All rights reserved.
//
#import "P4SearchItem.h"
@interface P4SearchItem () {
__weak P4NetworkOperation *runningOperation;
}
- (NSString *)queryForSearchTerms:(NSString *)terms;
- (id)initWithDictionary:(NSDictionary *)dictionary parentItem:(P4Item *)parent;
@end
@implementation P4SearchItem
@synthesize searchQuery;
@synthesize searchDirectory, searchWorkspaceOnly;
@synthesize searchFilenames, searchContents, searchTags;
@synthesize searchResultTags, searchFilteredTags;
#pragma mark - Public
- (void)setSearchQuery:(NSString *)string {
searchQuery = string;
localPath = [@"search://" stringByAppendingString:searchQuery];
}
#pragma mark - P4Item Override
- (id)init {
self = [super init];
if (self) {
flags.directory = YES;
searchFilenames =
searchContents =
searchTags = YES;
name = @"Search";
localPath = @"search://";
[[P4Workspace sharedInstance] addObserver:self];
}
return self;
}
- (void)dealloc {
[runningOperation cancel];
runningOperation = nil;
}
- (id)defaultAction {
if (!flags.tracked)
return [P4ItemAction
actionForItem:self name:@"Open read only"
selector:@selector(openFromDepot)];
if (status)
return [P4ItemAction
actionForItem:self name:@"Open"
selector:@selector(open)];
return [P4ItemAction
actionForItem:self name:@"Open and Checkout"
selector:@selector(openWithCheckout)];
}
- (NSArray *)actions {
if (flags.directory)
return nil;
// Use default on tracked files
if (flags.tracked)
return [super actions];
P4ItemAction *action;
NSMutableArray *actions = [NSMutableArray array];
BOOL dir = NO;
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:localPath
isDirectory:&dir];
if (localPath.length) {
action = [P4ItemAction
actionForItem:self name:@"Open"
selector:@selector(openWithCheckout)];
action.disabled = !exists || dir;
[actions addObject:action];
action = [P4ItemAction
actionForItem:self name:@"Open read only"
selector:@selector(open)];
action.disabled = !exists || dir;
[actions addObject:action];
}
[actions addObject:[P4ItemAction
actionForItem:self name:@"Open file from depot"
selector:@selector(openFromDepot)]];
if (localPath.length) {
action = [P4ItemAction
actionForItem:self name:@"Show in Finder"
selector:@selector(showInFinder)];
action.disabled = !exists || dir;
[actions addObject:action];
}
[actions addObject:[P4ItemAction
actionForItem:self name:@"Show Versions"
selector:@selector(showVersions)]];
return actions;
}
- (void)loadPath:(NSString *)path {
[runningOperation cancel];
runningOperation = nil;
children = @[];
flags.loading = YES;
searchResultTags = nil;
if (!searchQuery && path)
searchQuery = [path stringByRemovingPrefix:@"search://"];
[self setSearchQuery:searchQuery];
if (!searchQuery.length) {
[self performSelectorOnMainThread:@selector(finishLoading)
withObject:nil waitUntilDone:NO];
return;
}
runningOperation =
[[P4Workspace sharedInstance]
searchFiles:[self queryForSearchTerms:searchQuery]
path:searchDirectory
response:^(P4Operation *operation, NSArray *response) {
if (operation.error) {
if (operation.error.code == NSUserCancelledError)
[self finishLoading];
else
[self failWithError:operation.error];
return;
}
// Filter to unique paths
NSArray *files = [response valueForKeyPath:@"@distinctUnionOfObjects.depotFile"];
// Filter to search directory
if (searchDirectory.length) {
files = [files objectsAtIndexes:
[files indexesOfObjectsPassingTest:
^BOOL(NSString *path, NSUInteger idx, BOOL *stop) {
return [path hasPrefix:searchDirectory];
}]];
}
if (!files.count) {
[self finishLoading];
return;
}
NSString *fileList = [files componentsJoinedByString:@"\" \""];
NSMutableArray *filters = [NSMutableArray array];
[filters addObject:@"headRev"];
[filters addObject:@"^headAction=delete"];
[filters addObject:@"^headAction=move/delete"];
if (searchWorkspaceOnly)
[filters addObject:@"isMapped"];
NSString *filterList = [filters componentsJoinedByString:@" & "];
NSString *command = [NSString stringWithFormat:
@"fstat -F \"%@\" -A tags -Oah \"%@\"",
filterList, fileList];
[[P4Workspace sharedInstance]
runCommand:command
response:^(P4Operation *operation, NSArray *response) {
// Serialize children from response
NSMutableArray *array = [NSMutableArray arrayWithCapacity:512];
NSMutableSet *tagsSet = [NSMutableSet set];
// Make tags filter
NSPredicate *filter = !searchFilteredTags.count ? nil :
[NSPredicate predicateWithFormat:@"ANY SELF IN %@", searchFilteredTags];
for (NSDictionary *childDict in response) {
P4SearchItem *child = [[P4SearchItem alloc]
initWithDictionary:childDict
parentItem:self];
NSArray *childTags = [child tags];
if (!filter || [filter evaluateWithObject:childTags]) {
[array addObject:child];
[tagsSet addObjectsFromArray:childTags];
}
}
children = array;
searchResultTags = [[tagsSet allObjects] sortedArrayUsingSelector:
@selector(localizedStandardCompare:)];
[self finishLoading];
}];
}];
}
#pragma mark - Private
- (NSString *)queryForSearchTerms:(NSString *)search {
NSArray *words = [search arrayOfArguments];
NSString *term = (words.count > 1 ?
[words componentsJoinedByString:@"+"] :
[NSString stringWithFormat:@"*%@*", [words lastObject]]);
NSMutableArray *components = [NSMutableArray array];
if (searchFilenames)
[components addObject:@"filename:%1$@"];
if (searchTags)
[components addObject:@"p4attr_tags:%1$@"];
if (searchContents)
[components addObject:@"text:%1$@"];
NSString *query = [components componentsJoinedByString:@" OR "]; // Join components
query = [NSString stringWithFormat:query, term]; // Substitute terms
query = [NSString stringWithFormat:@"l:(%@)", query]; // Wrap into lucene query
return query;
}
- (id)initWithDictionary:(NSDictionary *)dictionary parentItem:(P4Item *)parentItem {
if (self = [super init]) {
parent = parentItem;
metadata = dictionary;
remotePath = [dictionary objectForKey:@"depotFile"];
name = remotePath.lastPathComponent;
// Create local path
localPath = [dictionary objectForKey:@"clientFile"];
NSString *client = [dictionary objectForKey:@"client"] ?: @"";
NSString *clientPrefix = [NSString stringWithFormat:@"//%@/", client];
if ([localPath hasPrefix:clientPrefix]) {
localPath = [localPath substringFromIndex:clientPrefix.length];
localPath = [[[P4Workspace sharedInstance] root] stringByAppendingPath:localPath];
}
// Set metadata
status = [metadata objectForKey:@"action"];
NSString *user = [metadata objectForKey:@"otherOpen0"];
NSDictionary *info = [[P4Workspace sharedInstance] userInfo:user];
statusOwner = [info objectForKey:@"Email"] ?: user;
flags.tracked = [metadata objectForKey:@"isMapped"] != nil;
[self refreshTags];
}
return self;
}
@end
# |
Change |
User |
Description |
Committed |
|
#1
|
10691 |
DWishR |
Populate //guest/DWishR/piper/.... |
|
|
//guest/perforce_software/piper/Perforce/Classes/Items/P4SearchItem.m |
#1
|
8919 |
Matt Attaway |
Initial add of Piper, a lightweight Perforce client for artists and designers. |
|
|