Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

base fork: livereload/LiveReload
...
head fork: livereload/LiveReload
  • 6 commits
  • 10 files changed
  • 0 commit comments
  • 1 contributor
9 mac/ATPathSpec/ATPathSpec/ATPathSpec.h
View
@@ -55,11 +55,15 @@ typedef enum {
} ATPathSpecErrorCode;
+extern NSString *const ATPathSpecMatchInfoMatchedSuffix;
+extern NSString *const ATPathSpecMatchInfoMatchedStaticName;
+
+
@interface ATMask : NSObject
+ (ATMask *)maskWithString:(NSString *)string syntaxOptions:(ATPathSpecSyntaxOptions)options;
-- (BOOL)matchesName:(NSString *)name;
+- (BOOL)matchesName:(NSString *)name matchInfo:(NSDictionary **)matchInfo;
- (NSString *)stringRepresentationWithSyntaxOptions:(ATPathSpecSyntaxOptions)options;
@@ -81,8 +85,9 @@ typedef enum {
- (ATPathSpec *)negatedPathSpec;
-- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type;
+- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type matchInfo:(NSDictionary **)matchInfo;
- (BOOL)matchesPath:(NSString *)path type:(ATPathSpecEntryType)type;
+- (NSDictionary *)matchInfoForPath:(NSString *)path type:(ATPathSpecEntryType)type;
- (NSArray *)matchingPathsInArray:(NSArray *)paths type:(ATPathSpecEntryType)type;
141 mac/ATPathSpec/ATPathSpec/ATPathSpec.m
View
@@ -8,6 +8,10 @@
NSString *const ATPathSpecErrorSpecStringKey = @"ATPathSpecErrorSpecString";
+NSString *const ATPathSpecMatchInfoMatchedSuffix = @"MatchedSuffix";
+NSString *const ATPathSpecMatchInfoMatchedStaticName = @"MatchedStaticName";
+
+
static NSString *ATPathSpecTokenTypeNames[] = {
@"NONE",
@"Mask",
@@ -102,6 +106,27 @@
return [NSString stringWithFormat:@"^%@$", regex];
}
+NSString *ATPathSpec_StaticSuffixFromPatternString(NSString *pattern, ATPathSpecSyntaxOptions options) {
+ BOOL star = !!(options & ATPathSpecSyntaxOptionsAllowStarWildcard);
+ BOOL question = !!(options & ATPathSpecSyntaxOptionsAllowQuestionMarkWildcard);
+
+ if (!star)
+ return nil;
+
+ NSRange range = [pattern rangeOfString:@"*" options:NSBackwardsSearch];
+ if (range.location == NSNotFound)
+ return nil;
+
+ NSString *candidate = [pattern substringFromIndex:range.location + range.length];
+ if (candidate.length == 0)
+ return nil;
+
+ if (question && [candidate rangeOfString:@"?"].location != NSNotFound)
+ return nil;
+
+ return candidate;
+}
+
NSString *ATPathSpecAdjustTrailingSlash(NSString *path, ATPathSpecEntryType type) {
if (type == ATPathSpecEntryTypeFolder)
return ATPathSpecAddTrailingSlash(path);
@@ -186,7 +211,7 @@ + (ATMask *)maskWithString:(NSString *)string syntaxOptions:(ATPathSpecSyntaxOpt
}
}
-- (BOOL)matchesName:(NSString *)name {
+- (BOOL)matchesName:(NSString *)name matchInfo:(NSDictionary **)matchInfo {
abort();
}
@@ -215,8 +240,13 @@ - (id)initWithName:(NSString *)name {
return self;
}
-- (BOOL)matchesName:(NSString *)name {
- return [_name isEqualToString:name];
+- (BOOL)matchesName:(NSString *)name matchInfo:(NSDictionary **)matchInfo {
+ if ([_name isEqualToString:name]) {
+ if (matchInfo)
+ *matchInfo = @{ATPathSpecMatchInfoMatchedStaticName: _name};
+ return YES;
+ }
+ return NO;
}
- (NSString *)stringRepresentationWithSyntaxOptions:(ATPathSpecSyntaxOptions)options {
@@ -238,12 +268,14 @@ - (id)initWithSuffix:(NSString *)suffix {
return self;
}
-- (BOOL)matchesName:(NSString *)name {
+- (BOOL)matchesName:(NSString *)name matchInfo:(NSDictionary **)matchInfo {
NSUInteger nameLen = name.length, suffixLen = _suffix.length;
if (nameLen < _suffix.length || NSOrderedSame != [name compare:_suffix options:NSLiteralSearch range:NSMakeRange(nameLen - suffixLen, suffixLen)])
- return ATPathSpecMatchResultUnknown;
+ return NO;
- return ATPathSpecMatchResultMatched;
+ if (matchInfo)
+ *matchInfo = @{ATPathSpecMatchInfoMatchedSuffix: _suffix};
+ return YES;
}
- (NSString *)stringRepresentationWithSyntaxOptions:(ATPathSpecSyntaxOptions)options {
@@ -255,6 +287,7 @@ - (NSString *)stringRepresentationWithSyntaxOptions:(ATPathSpecSyntaxOptions)opt
@implementation ATPatternMask {
NSString *_regex;
+ NSString *_staticSuffix;
}
@synthesize pattern = _pattern;
@@ -264,12 +297,22 @@ - (id)initWithPattern:(NSString *)pattern syntaxOptions:(ATPathSpecSyntaxOptions
if (self) {
_pattern = [pattern copy];
_regex = ATPathSpec_RegexFromPatternString(_pattern, options);
+ _staticSuffix = ATPathSpec_StaticSuffixFromPatternString(_pattern, options);
}
return self;
}
-- (BOOL)matchesName:(NSString *)name {
- return [name isMatchedByRegex:_regex];
+- (BOOL)matchesName:(NSString *)name matchInfo:(NSDictionary **)matchInfo {
+ if ([name isMatchedByRegex:_regex]) {
+ if (matchInfo) {
+ if (_staticSuffix)
+ *matchInfo = @{ATPathSpecMatchInfoMatchedSuffix: _staticSuffix};
+ else
+ *matchInfo = @{};
+ }
+ return YES;
+ }
+ return NO;
}
- (NSString *)stringRepresentationWithSyntaxOptions:(ATPathSpecSyntaxOptions)options {
@@ -678,13 +721,21 @@ + (ATPathSpec *)pathSpecMatchingPath:(NSString *)path type:(ATPathSpecEntryType)
}
- (BOOL)matchesPath:(NSString *)path type:(ATPathSpecEntryType)type {
- return [self matchResultForPath:path type:type] == ATPathSpecMatchResultMatched;
+ return [self matchResultForPath:path type:type matchInfo:NULL] == ATPathSpecMatchResultMatched;
}
-- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type {
+- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type matchInfo:(NSDictionary **)matchInfo {
abort();
}
+- (NSDictionary *)matchInfoForPath:(NSString *)path type:(ATPathSpecEntryType)type {
+ NSDictionary *result;
+ if ([self matchResultForPath:path type:type matchInfo:&result] == ATPathSpecMatchResultMatched)
+ return result;
+ else
+ return nil;
+}
+
- (ATPathSpec *)negatedPathSpec {
return [[ATNegatedPathSpec alloc] initWithSpec:self];
}
@@ -730,7 +781,7 @@ - (NSArray *)matchingPathsInArray:(NSArray *)paths type:(ATPathSpecEntryType)typ
@implementation ATEmptyPathSpec : ATPathSpec
-- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type {
+- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type matchInfo:(NSDictionary **)matchInfo {
return NO;
}
@@ -768,23 +819,26 @@ - (id)initWithMask:(ATMask *)mask type:(ATPathSpecEntryType)type syntaxOptions:(
return self;
}
-- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type {
+- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type matchInfo:(NSDictionary **)matchInfo {
if (_fuzzyEnabled && (_type == ATPathSpecEntryTypeFolder || _type == ATPathSpecEntryTypeFileOrFolder)) {
NSArray *components = path.pathComponents;
- if (type == ATPathSpecEntryTypeFile)
- components = [components subarrayWithRange:NSMakeRange(0, components.count - 1)];
+ components = [components subarrayWithRange:NSMakeRange(0, components.count - 1)];
for (NSString *component in components) {
- if ([_mask matchesName:component])
+ if ([_mask matchesName:component matchInfo:NULL]) {
+ if (matchInfo)
+ *matchInfo = @{};
return ATPathSpecMatchResultMatched;
+ }
}
- if (type != ATPathSpecEntryTypeFile)
- return ATPathSpecMatchResultUnknown;
}
if (!ATPathSpecEntryType_Match(_type, type))
return ATPathSpecMatchResultUnknown;
- return [_mask matchesName:[path lastPathComponent]];
+ if ([_mask matchesName:[path lastPathComponent] matchInfo:matchInfo])
+ return ATPathSpecMatchResultMatched;
+ else
+ return ATPathSpecMatchResultUnknown;
}
- (NSString *)stringRepresentationWithSyntaxOptions:(ATPathSpecSyntaxOptions)options {
@@ -817,7 +871,7 @@ - (id)initWithMasks:(NSArray *)masks type:(ATPathSpecEntryType)type syntaxOption
return self;
}
-- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type {
+- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type matchInfo:(NSDictionary **)matchInfo {
BOOL fuzzy = (_fuzzyEnabled && (_type == ATPathSpecEntryTypeFolder || _type == ATPathSpecEntryTypeFileOrFolder));
BOOL typesCompatible = ATPathSpecEntryType_Match(_type, type);
@@ -838,14 +892,17 @@ - (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEnt
if (fuzzy && !typesCompatible && pcount == mcount)
return ATPathSpecMatchResultUnknown; // full match not possible because the entry types are different
- NSInteger index = 0;
+ NSUInteger index = 0;
for (ATMask *mask in _masks) {
NSString *component = components[index++];
- if (![mask matchesName:component])
+ if (![mask matchesName:component matchInfo:(index == pcount ? matchInfo : NULL)])
return ATPathSpecMatchResultUnknown;
}
-
+
+ if (matchInfo && index < pcount)
+ *matchInfo = @{};
+
return ATPathSpecMatchResultMatched;
}
@@ -884,8 +941,14 @@ - (ATPathSpec *)negatedPathSpec {
return _spec;
}
-- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type {
- return [_spec matchResultForPath:path type:type] != ATPathSpecMatchResultMatched;
+- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type matchInfo:(NSDictionary **)matchInfo {
+ if ([_spec matchResultForPath:path type:type matchInfo:NULL] != ATPathSpecMatchResultMatched) {
+ if (matchInfo)
+ *matchInfo = @{};
+ return YES;
+ } else {
+ return NO;
+ }
}
- (BOOL)isComplexExpression {
@@ -913,9 +976,9 @@ - (id)initWithSpecs:(NSArray *)specs {
return self;
}
-- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type {
+- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type matchInfo:(NSDictionary **)matchInfo {
for (ATPathSpec *spec in _specs) {
- ATPathSpecMatchResult result = [spec matchResultForPath:path type:type];
+ ATPathSpecMatchResult result = [spec matchResultForPath:path type:type matchInfo:matchInfo];
if (result == ATPathSpecMatchResultMatched)
return ATPathSpecMatchResultMatched;
}
@@ -951,12 +1014,34 @@ - (id)initWithSpecs:(NSArray *)specs {
return self;
}
-- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type {
+- (ATPathSpecMatchResult)matchResultForPath:(NSString *)path type:(ATPathSpecEntryType)type matchInfo:(NSDictionary **)matchInfo {
+ NSDictionary *mergedMatchInfo;
+ if (matchInfo)
+ mergedMatchInfo = @{};
+
for (ATPathSpec *spec in _specs) {
- ATPathSpecMatchResult result = [spec matchResultForPath:path type:type];
+ ATPathSpecMatchResult result;
+ if (matchInfo) {
+ NSDictionary *itemMatchInfo = nil;
+ result = [spec matchResultForPath:path type:type matchInfo:&itemMatchInfo];
+ if (result == ATPathSpecMatchResultMatched && itemMatchInfo.count > 0) {
+ if (mergedMatchInfo.count == 0) {
+ mergedMatchInfo = itemMatchInfo;
+ } else {
+ NSMutableDictionary *mutable = [mergedMatchInfo mutableCopy];
+ [mutable setValuesForKeysWithDictionary:itemMatchInfo];
+ mergedMatchInfo = [mutable copy];
+ }
+ }
+ } else {
+ result = [spec matchResultForPath:path type:type matchInfo:NULL];
+ }
if (result != ATPathSpecMatchResultMatched)
return ATPathSpecMatchResultUnknown;
}
+
+ if (matchInfo)
+ *matchInfo = mergedMatchInfo;
return ATPathSpecMatchResultMatched;
}
5 mac/ATPathSpec/ATPathSpecExample.xcodeproj/project.pbxproj
View
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
+ 430ABDF6186BFE0B00407561 /* ATPathSpecMatchInfoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 430ABDF5186BFE0B00407561 /* ATPathSpecMatchInfoTests.m */; };
4398656817BCBF1E00EC6471 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4398656717BCBF1E00EC6471 /* Foundation.framework */; };
4398656B17BCBF1E00EC6471 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4398656A17BCBF1E00EC6471 /* main.m */; };
4398657B17BCBF6C00EC6471 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4398657A17BCBF6C00EC6471 /* XCTest.framework */; };
@@ -47,6 +48,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ 430ABDF5186BFE0B00407561 /* ATPathSpecMatchInfoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ATPathSpecMatchInfoTests.m; sourceTree = "<group>"; };
4398656417BCBF1E00EC6471 /* ATPathSpecExample */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ATPathSpecExample; sourceTree = BUILT_PRODUCTS_DIR; };
4398656717BCBF1E00EC6471 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
4398656A17BCBF1E00EC6471 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
@@ -143,6 +145,7 @@
4398657C17BCBF6C00EC6471 /* ATPathSpecTests */ = {
isa = PBXGroup;
children = (
+ 430ABDF5186BFE0B00407561 /* ATPathSpecMatchInfoTests.m */,
439865A417BE1B4900EC6471 /* ATPathSpecIntroTests.m */,
4398659017BCF12900EC6471 /* ATPathSpecTokenizerTests.m */,
4398658217BCBF6C00EC6471 /* ATPathSpecSingleComponentTests.m */,
@@ -277,6 +280,7 @@
439865A317BE186500EC6471 /* ATPathSpecMetadataTests.m in Sources */,
4398659117BCF12900EC6471 /* ATPathSpecTokenizerTests.m in Sources */,
439865A117BE109E00EC6471 /* ATPathSpecMultiComponentTests.m in Sources */,
+ 430ABDF6186BFE0B00407561 /* ATPathSpecMatchInfoTests.m in Sources */,
439865A517BE1B4900EC6471 /* ATPathSpecIntroTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -453,6 +457,7 @@
4398658917BCBF6C00EC6471 /* Release */,
);
defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
89 mac/ATPathSpec/ATPathSpecTests/ATPathSpecMatchInfoTests.m
View
@@ -0,0 +1,89 @@
+//
+// ATPathSpecMatchInfoTests.m
+// ATPathSpecExample
+//
+// Created by Andrey Tarantsov on 26.12.2013.
+// Copyright (c) 2013 Andrey Tarantsov. All rights reserved.
+//
+
+#import <XCTest/XCTest.h>
+#import "ATPathSpec.h"
+
+@interface ATPathSpecMatchInfoTests : XCTestCase
+@end
+
+@implementation ATPathSpecMatchInfoTests
+
+- (void)testStaticNameMatch {
+ ATPathSpec *spec = [ATPathSpec pathSpecWithString:@"README.txt" syntaxOptions:ATPathSpecSyntaxFlavorExtended];
+ NSDictionary *info = [spec matchInfoForPath:@"docs/README.txt" type:ATPathSpecEntryTypeFile];
+ XCTAssertNotNil(info);
+ XCTAssertEqualObjects(info[ATPathSpecMatchInfoMatchedStaticName], @"README.txt");
+ XCTAssertNil(info[ATPathSpecMatchInfoMatchedSuffix]);
+}
+
+- (void)testStaticNameInSubdirMatch {
+ ATPathSpec *spec = [ATPathSpec pathSpecWithString:@"docs/README.txt" syntaxOptions:ATPathSpecSyntaxFlavorExtended];
+ NSDictionary *info = [spec matchInfoForPath:@"docs/README.txt" type:ATPathSpecEntryTypeFile];
+ XCTAssertNotNil(info);
+ XCTAssertEqualObjects(info[ATPathSpecMatchInfoMatchedStaticName], @"README.txt");
+ XCTAssertNil(info[ATPathSpecMatchInfoMatchedSuffix]);
+}
+
+- (void)testSuffixMaskMatch {
+ ATPathSpec *spec = [ATPathSpec pathSpecWithString:@"*.txt" syntaxOptions:ATPathSpecSyntaxFlavorExtended];
+ NSDictionary *info = [spec matchInfoForPath:@"docs/README.txt" type:ATPathSpecEntryTypeFile];
+ XCTAssertNotNil(info);
+ XCTAssertNil(info[ATPathSpecMatchInfoMatchedStaticName]);
+ XCTAssertEqualObjects(info[ATPathSpecMatchInfoMatchedSuffix], @".txt");
+}
+
+- (void)testDoubleExtensionSuffixMaskMatch {
+ ATPathSpec *spec = [ATPathSpec pathSpecWithString:@"*.coffee.md" syntaxOptions:ATPathSpecSyntaxFlavorExtended];
+ NSDictionary *info = [spec matchInfoForPath:@"docs/something.coffee.md" type:ATPathSpecEntryTypeFile];
+ XCTAssertNotNil(info);
+ XCTAssertNil(info[ATPathSpecMatchInfoMatchedStaticName]);
+ XCTAssertEqualObjects(info[ATPathSpecMatchInfoMatchedSuffix], @".coffee.md");
+}
+
+- (void)testPatternMatch {
+ ATPathSpec *spec = [ATPathSpec pathSpecWithString:@"*o*/READ*.txt" syntaxOptions:ATPathSpecSyntaxFlavorExtended];
+ NSDictionary *info = [spec matchInfoForPath:@"docs/README.txt" type:ATPathSpecEntryTypeFile];
+ XCTAssertNotNil(info);
+ XCTAssertNil(info[ATPathSpecMatchInfoMatchedStaticName]);
+ XCTAssertEqualObjects(info[ATPathSpecMatchInfoMatchedSuffix], @".txt");
+}
+
+- (void)testMaskMatchInPath {
+ ATPathSpec *spec = [ATPathSpec pathSpecWithString:@"*.txt" syntaxOptions:ATPathSpecSyntaxFlavorGitignore];
+ NSDictionary *info = [spec matchInfoForPath:@"docs.txt/README.md" type:ATPathSpecEntryTypeFile];
+ XCTAssertNotNil(info);
+ XCTAssertNil(info[ATPathSpecMatchInfoMatchedStaticName]);
+ XCTAssertNil(info[ATPathSpecMatchInfoMatchedSuffix]);
+}
+
+- (void)testPatternMatchWithNegation {
+ ATPathSpec *spec = [ATPathSpec pathSpecWithString:@"*.txt !~*" syntaxOptions:ATPathSpecSyntaxFlavorExtended];
+ NSDictionary *info = [spec matchInfoForPath:@"docs/README.txt" type:ATPathSpecEntryTypeFile];
+ XCTAssertNotNil(info);
+ XCTAssertNil(info[ATPathSpecMatchInfoMatchedStaticName]);
+ XCTAssertEqualObjects(info[ATPathSpecMatchInfoMatchedSuffix], @".txt");
+}
+
+- (void)testWildMatchWithNegation {
+ ATPathSpec *spec = [ATPathSpec pathSpecWithString:@"READ* !~*.txt" syntaxOptions:ATPathSpecSyntaxFlavorExtended];
+ NSDictionary *info = [spec matchInfoForPath:@"docs/README.txt" type:ATPathSpecEntryTypeFile];
+ XCTAssertNotNil(info);
+ XCTAssertNil(info[ATPathSpecMatchInfoMatchedStaticName]);
+ XCTAssertNil(info[ATPathSpecMatchInfoMatchedSuffix]);
+}
+
+- (void)testStaticAndPatternIntersectionMatch {
+ ATPathSpec *spec = [ATPathSpec pathSpecWithString:@"README.txt & *.txt" syntaxOptions:ATPathSpecSyntaxFlavorExtended];
+ NSDictionary *info = [spec matchInfoForPath:@"docs/README.txt" type:ATPathSpecEntryTypeFile];
+ XCTAssertNotNil(info);
+ XCTAssertEqualObjects(info[ATPathSpecMatchInfoMatchedStaticName], @"README.txt");
+ XCTAssertEqualObjects(info[ATPathSpecMatchInfoMatchedSuffix], @".txt");
+}
+
+@end
11 mac/Classes/Model/Actions/CompileFileAction.m
View
@@ -5,6 +5,7 @@
//#import "Plugin.h"
#import "LRFile2.h"
#import "LRFile.h"
+#import "LRPathProcessing.h"
@implementation CompileFileAction
@@ -34,11 +35,11 @@ - (void)configureStep:(ScriptInvocationStep *)step forFile:(LRFile2 *)file {
[step addFileValue:file forSubstitutionKey:@"src"];
- // we cheat a little, reusing the impl from LRFile (TODO should extract the common helpers)
- LRFile *fakeFile = [[LRFile alloc] initWithFile:file.relativePath memento:nil];
- fakeFile.destinationDirectory = self.outputFilterOption.subfolder;
- fakeFile.destinationNameMask = self.type.manifest[@"output"];
- NSString *destinationRelativePath = fakeFile.destinationPath;
+ NSString *destinationName = LRDeriveDestinationFileName([file.relativePath lastPathComponent], self.type.manifest[@"output"], self.intrinsicInputPathSpec);
+
+ NSString *destinationRelativePath = nil;
+ if (self.outputFilterOption.subfolder)
+ destinationRelativePath = [self.outputFilterOption.subfolder stringByAppendingPathComponent:destinationName];
LRFile2 *destinationFile = [LRFile2 fileWithRelativePath:destinationRelativePath project:step.project];
[step addFileValue:destinationFile forSubstitutionKey:@"dst"];
30 mac/Classes/Model/Project/Project.m
View
@@ -539,6 +539,18 @@ - (void)fileSystemMonitor:(FSMonitor *)monitor detectedChange:(FSChange *)change
}
}
+- (NSArray *)rootPathsForPaths:(id<NSFastEnumeration>)paths {
+ NSMutableSet *result = [NSMutableSet new];
+ for (NSString *path in paths) {
+ NSSet *rootPaths = [_importGraph rootReferencingPathsForPath:path];
+ if (rootPaths.count > 0)
+ [result addObjectsFromArray:rootPaths.allObjects];
+ else
+ [result addObject:path];
+ }
+ return [result.allObjects copy];
+}
+
- (void)processBatchOfPendingChanges:(NSSet *)pathes {
BOOL invokePostProcessor = _pendingPostProcessing;
_pendingPostProcessing = NO;
@@ -560,16 +572,9 @@ - (void)processBatchOfPendingChanges:(NSSet *)pathes {
[self performSelector:@selector(rescanRecentlyChangedPaths) withObject:nil afterDelay:1.0];
#endif
- for (NSString *relativePath in pathes) {
- NSSet *realPaths = [_importGraph rootReferencingPathsForPath:relativePath];
- if ([realPaths count] > 0) {
- NSLog(@"Instead of imported file %@, processing changes in %@", relativePath, [[realPaths allObjects] componentsJoinedByString:@", "]);
- for (NSString *path in realPaths) {
- [self processChangeAtPath:path reloadRequests:reloadRequests];
- }
- } else {
- [self processChangeAtPath:relativePath reloadRequests:reloadRequests];
- }
+ NSArray *pathsToProcess = [self rootPathsForPaths:pathes];
+ for (NSString *relativePath in pathsToProcess) {
+ [self processChangeAtPath:relativePath reloadRequests:reloadRequests];
}
NSArray *actions = [self.actionList.activeActions copy];
@@ -580,7 +585,10 @@ - (void)processBatchOfPendingChanges:(NSSet *)pathes {
[perFileActions enumerateObjectsAsynchronouslyUsingBlock:^(Action *action, NSUInteger idx, void (^callback1)(BOOL stop)) {
NSArray *matchingPaths = [action.inputPathSpec matchingPathsInArray:pathArray type:ATPathSpecEntryTypeFile];
- [matchingPaths enumerateObjectsAsynchronouslyUsingBlock:^(NSString *path, NSUInteger idx, void (^callback2)(BOOL stop)) {
+ NSArray *rootPaths = [self rootPathsForPaths:matchingPaths];
+ NSArray *matchingRootPaths = [action.inputPathSpec matchingPathsInArray:rootPaths type:ATPathSpecEntryTypeFile];
+
+ [matchingRootPaths enumerateObjectsAsynchronouslyUsingBlock:^(NSString *path, NSUInteger idx, void (^callback2)(BOOL stop)) {
LRFile2 *file = [LRFile2 fileWithRelativePath:path project:self];
if ([action shouldInvokeForFile:file]) {
[action compileFile:file inProject:self completionHandler:^(BOOL invoked, ToolOutput *output, NSError *error) {
6 mac/Classes/Utilities/LRPathProcessing.h
View
@@ -0,0 +1,6 @@
+
+#import <Foundation/Foundation.h>
+
+@class ATPathSpec;
+
+NSString *LRDeriveDestinationFileName(NSString *sourceFileName, NSString *destinationNameMask, ATPathSpec *sourcePathSpec);
29 mac/Classes/Utilities/LRPathProcessing.m
View
@@ -0,0 +1,29 @@
+
+#import "LRPathProcessing.h"
+#import "ATPathSpec.h"
+
+
+NSString *LRDeriveDestinationFileName(NSString *sourceFileName, NSString *destinationNameMask, ATPathSpec *sourcePathSpec) {
+ NSString *sourceBaseName = nil;
+
+ // source spec introspection required to handle extensions like ".coffee.md"
+ NSDictionary *matchInfo = [sourcePathSpec matchInfoForPath:sourceFileName type:ATPathSpecEntryTypeFile];
+ if (matchInfo) {
+ NSString *suffix = matchInfo[ATPathSpecMatchInfoMatchedSuffix];
+ if (suffix && [sourceFileName hasSuffix:suffix]) {
+ NSRange range = [sourceFileName rangeOfString:suffix options:NSBackwardsSearch];
+ sourceBaseName = [sourceFileName substringToIndex:range.location];
+ }
+ }
+
+ if (!sourceBaseName) {
+ sourceBaseName = [sourceFileName stringByDeletingPathExtension];
+ }
+
+ // handle a mask like "*.php" applied to a source file named like "foo.php.jade"
+ while ([destinationNameMask pathExtension].length > 0 && [sourceBaseName pathExtension].length > 0 && [[destinationNameMask pathExtension] isEqualToString:[sourceBaseName pathExtension]]) {
+ destinationNameMask = [destinationNameMask stringByDeletingPathExtension];
+ }
+
+ return [destinationNameMask stringByReplacingOccurrencesOfString:@"*" withString:sourceBaseName];
+}
24 mac/LiveReload.xcodeproj/project.pbxproj
View
@@ -52,6 +52,8 @@
43059222151E8FA400CC3F88 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43059221151E8FA400CC3F88 /* CoreServices.framework */; };
43059225151E90DE00CC3F88 /* DockIcon.m in Sources */ = {isa = PBXBuildFile; fileRef = 43059224151E90DE00CC3F88 /* DockIcon.m */; };
43097094183F075B00A96442 /* LRActionManifest.m in Sources */ = {isa = PBXBuildFile; fileRef = 43097093183F075B00A96442 /* LRActionManifest.m */; };
+ 430ABDF1186BF1EA00407561 /* LRPathProcessingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 430ABDF0186BF1EA00407561 /* LRPathProcessingTests.m */; };
+ 430ABDF4186BF20500407561 /* LRPathProcessing.m in Sources */ = {isa = PBXBuildFile; fileRef = 430ABDF3186BF20500407561 /* LRPathProcessing.m */; };
430D7F5C18443AD700203400 /* LRVersionSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 430D7F5B18443AD700203400 /* LRVersionSpec.m */; };
430D7F5F18443BC600203400 /* LRVersionTag.m in Sources */ = {isa = PBXBuildFile; fileRef = 430D7F5E18443BC600203400 /* LRVersionTag.m */; };
430D7F621845901100203400 /* LRVersionOption.m in Sources */ = {isa = PBXBuildFile; fileRef = 430D7F611845901100203400 /* LRVersionOption.m */; };
@@ -430,6 +432,9 @@
4309708F183F052C00A96442 /* LRManifestErrorSink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LRManifestErrorSink.h; sourceTree = "<group>"; };
43097092183F075B00A96442 /* LRActionManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LRActionManifest.h; sourceTree = "<group>"; };
43097093183F075B00A96442 /* LRActionManifest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LRActionManifest.m; sourceTree = "<group>"; };
+ 430ABDF0186BF1EA00407561 /* LRPathProcessingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LRPathProcessingTests.m; sourceTree = "<group>"; };
+ 430ABDF2186BF20500407561 /* LRPathProcessing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LRPathProcessing.h; sourceTree = "<group>"; };
+ 430ABDF3186BF20500407561 /* LRPathProcessing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LRPathProcessing.m; sourceTree = "<group>"; };
430D7F5A18443AD700203400 /* LRVersionSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LRVersionSpec.h; sourceTree = "<group>"; };
430D7F5B18443AD700203400 /* LRVersionSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LRVersionSpec.m; sourceTree = "<group>"; };
430D7F5D18443BC600203400 /* LRVersionTag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LRVersionTag.h; sourceTree = "<group>"; };
@@ -899,7 +904,7 @@
823DDF2D13F8DA3F00529AD2 /* StatusItemStateRotation1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = StatusItemStateRotation1.png; sourceTree = "<group>"; };
823DDF2E13F8DA3F00529AD2 /* StatusItemStateRotation2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = StatusItemStateRotation2.png; sourceTree = "<group>"; };
8D1107310486CEB800E47090 /* LiveReload-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "LiveReload-Info.plist"; sourceTree = "<group>"; };
- 8D1107320486CEB800E47090 /* LiveReload Pro.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "LiveReload Pro.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8D1107320486CEB800E47090 /* LiveReload.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LiveReload.app; sourceTree = BUILT_PRODUCTS_DIR; };
C01FCF5008A954540054247C /* RSVerticallyCenteredTextFieldCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSVerticallyCenteredTextFieldCell.h; sourceTree = "<group>"; };
C01FCF5008A954540054247D /* RSVerticallyCenteredTextFieldCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSVerticallyCenteredTextFieldCell.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -963,7 +968,7 @@
19C28FACFE9D520D11CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
- 8D1107320486CEB800E47090 /* LiveReload Pro.app */,
+ 8D1107320486CEB800E47090 /* LiveReload.app */,
4396F1B817F77A8900AA8200 /* com.tarantsov.GlitterInstallationService.xpc */,
4371095118585DB800FCB4C2 /* LiveReloadTests.xctest */,
);
@@ -1620,6 +1625,7 @@
4371095318585DB800FCB4C2 /* LiveReloadTests */ = {
isa = PBXGroup;
children = (
+ 430ABDF0186BF1EA00407561 /* LRPathProcessingTests.m */,
4371095918585DB800FCB4C2 /* LiveReloadTests.m */,
4371095418585DB800FCB4C2 /* Supporting Files */,
);
@@ -2065,6 +2071,8 @@
43996B4217B001BA00B09954 /* NSString+SmartRegexpCaptures.m */,
43122C0E1814E27600BF8121 /* LRCommandLine.h */,
43122C0F1814E27600BF8121 /* LRCommandLine.m */,
+ 430ABDF2186BF20500407561 /* LRPathProcessing.h */,
+ 430ABDF3186BF20500407561 /* LRPathProcessing.m */,
);
path = Utilities;
sourceTree = "<group>";
@@ -2200,7 +2208,7 @@
name = LiveReload;
productInstallPath = "$(HOME)/Applications";
productName = LiveReload;
- productReference = 8D1107320486CEB800E47090 /* LiveReload Pro.app */;
+ productReference = 8D1107320486CEB800E47090 /* LiveReload.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
@@ -2353,6 +2361,7 @@
buildActionMask = 2147483647;
files = (
4371095A18585DB800FCB4C2 /* LiveReloadTests.m in Sources */,
+ 430ABDF1186BF1EA00407561 /* LRPathProcessingTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2445,6 +2454,7 @@
43059209151DF2DE00CC3F88 /* MASReceipt.m in Sources */,
433D2197182646E300E81A09 /* Project.m in Sources */,
43059225151E90DE00CC3F88 /* DockIcon.m in Sources */,
+ 430ABDF4186BF20500407561 /* LRPathProcessing.m in Sources */,
439A76B015B28EF100E50057 /* LicenseCodeViewController.m in Sources */,
439A76B415B28F4300E50057 /* LicenseCodeWindowController.m in Sources */,
433D22041826AD9200E81A09 /* LRPackageContainer.m in Sources */,
@@ -2810,7 +2820,7 @@
INSTALL_PATH = "$(HOME)/Applications";
MACOSX_DEPLOYMENT_TARGET = 10.8;
OTHER_LDFLAGS = "-lz";
- PRODUCT_NAME = "LiveReload Pro";
+ PRODUCT_NAME = LiveReload;
PROVISIONING_PROFILE = "";
};
name = Testing;
@@ -3056,7 +3066,7 @@
INSTALL_PATH = "$(HOME)/Applications";
MACOSX_DEPLOYMENT_TARGET = 10.8;
OTHER_LDFLAGS = "-lz";
- PRODUCT_NAME = "LiveReload Pro";
+ PRODUCT_NAME = LiveReload;
};
name = AppStore;
};
@@ -3075,7 +3085,7 @@
INSTALL_PATH = "$(HOME)/Applications";
MACOSX_DEPLOYMENT_TARGET = 10.8;
OTHER_LDFLAGS = "-lz";
- PRODUCT_NAME = "LiveReload Pro";
+ PRODUCT_NAME = LiveReload;
PROVISIONING_PROFILE = "";
};
name = Debug;
@@ -3093,7 +3103,7 @@
INSTALL_PATH = "$(HOME)/Applications";
MACOSX_DEPLOYMENT_TARGET = 10.8;
OTHER_LDFLAGS = "-lz";
- PRODUCT_NAME = "LiveReload Pro";
+ PRODUCT_NAME = LiveReload;
PROVISIONING_PROFILE = "";
};
name = Release;
26 mac/LiveReloadTests/LRPathProcessingTests.m
View
@@ -0,0 +1,26 @@
+
+#import <XCTest/XCTest.h>
+#import "LRPathProcessing.h"
+#import "ATPathSpec.h"
+
+@interface LRPathProcessingTests : XCTestCase
+@end
+
+@implementation LRPathProcessingTests
+
+- (void)testTrivialCase {
+ NSString *result = LRDeriveDestinationFileName(@"test.less", @"*.css", [ATPathSpec pathSpecWithString:@"*.less" syntaxOptions:ATPathSpecSyntaxFlavorExtended]);
+ XCTAssertEqualObjects(result, @"test.css");
+}
+
+- (void)testMultipleSourceExtensions {
+ NSString *result = LRDeriveDestinationFileName(@"test.scss", @"*.css", [ATPathSpec pathSpecWithString:@"*.sass *.scss" syntaxOptions:ATPathSpecSyntaxFlavorExtended]);
+ XCTAssertEqualObjects(result, @"test.css");
+}
+
+- (void)testDoubleExtension {
+ NSString *result = LRDeriveDestinationFileName(@"test.coffee.md", @"*.js", [ATPathSpec pathSpecWithString:@"*.coffee *.coffee.md" syntaxOptions:ATPathSpecSyntaxFlavorExtended]);
+ XCTAssertEqualObjects(result, @"test.js");
+}
+
+@end

No commit comments for this range

Something went wrong with that request. Please try again.