diff options
-rw-r--r-- | Foundation/GTMNSFileManager+Path.h | 71 | ||||
-rw-r--r-- | Foundation/GTMNSFileManager+Path.m | 102 | ||||
-rw-r--r-- | Foundation/GTMNSFileManager+PathTest.m | 58 | ||||
-rw-r--r-- | GTM.xcodeproj/project.pbxproj | 12 | ||||
-rw-r--r-- | ReleaseNotes.txt | 2 |
5 files changed, 245 insertions, 0 deletions
diff --git a/Foundation/GTMNSFileManager+Path.h b/Foundation/GTMNSFileManager+Path.h new file mode 100644 index 0000000..330c45e --- /dev/null +++ b/Foundation/GTMNSFileManager+Path.h @@ -0,0 +1,71 @@ +// +// GTMNSFileManager+Path.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import <Foundation/Foundation.h> + + +/// A few useful methods for dealing with paths. +@interface NSFileManager (GMFileManagerPathAdditions) + +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + +/// For the Unix-y at heart, this is "mkdir -p". It tries to create +/// the directory specified by |path|, and any intervening directories that +/// are needed. Each directory that is created is created with |attributes| +/// (see other NSFileManager doco for the details on |attributes|). +/// +/// If you are building for 10.5 or later, you should just use the new api: +/// createDirectoryAtPath:withIntermediateDirectories:attributes:error: +/// +/// Args: +/// path - the path of the directory to create. +/// attributes - these are defined in the "Constants" section of Apple's +/// NSFileManager doco +/// +/// Returns: +/// YES if |path| exists or was able to be created successfully +/// NO otherwise +/// +- (BOOL)gtm_createFullPathToDirectory:(NSString *)path + attributes:(NSDictionary *)attributes; + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + +/// Return an the paths for all resources in |directoryPath| that have the +/// |extension| file extension. +/// +/// Args: +/// extension - the file extension (excluding the leading ".") to match. +/// If nil, all files are matched. +/// directoryPath - the directory to look in. Subdirectories are not traversed. +/// +/// Returns: +/// An NSArray of absolute file paths that have |extension|. nil is returned +/// if |directoryPath| doesn't exist or can't be opened, and returns an empty +/// array if |directoryPath| is empty. ".", "..", and resource forks are never returned. +/// +- (NSArray *)gtm_filePathsWithExtension:(NSString *)extension + inDirectory:(NSString *)directoryPath; + +/// Same as -filePathsWithExtension:inDirectory: except |extensions| is an +/// NSArray of extensions to match. +/// +- (NSArray *)gtm_filePathsWithExtensions:(NSArray *)extensions + inDirectory:(NSString *)directoryPath; + +@end diff --git a/Foundation/GTMNSFileManager+Path.m b/Foundation/GTMNSFileManager+Path.m new file mode 100644 index 0000000..6dec24b --- /dev/null +++ b/Foundation/GTMNSFileManager+Path.m @@ -0,0 +1,102 @@ +// +// GTMNSFileManager+Path.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "GTMNSFileManager+Path.h" + +@implementation NSFileManager (GMFileManagerPathAdditions) + +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + +- (BOOL)gtm_createFullPathToDirectory:(NSString *)path + attributes:(NSDictionary *)attributes { + if (!path) return NO; + + BOOL isDir; + BOOL exists = [self fileExistsAtPath:path isDirectory:&isDir]; + + // Quick check for the case where we have nothing to do. + if (exists && isDir) + return YES; + + NSString *actualPath = @"/"; + NSEnumerator *directoryEnumerator = [[path pathComponents] objectEnumerator]; + NSString *directory; + + while ((directory = [directoryEnumerator nextObject])) { + actualPath = [actualPath stringByAppendingPathComponent:directory]; + + if ([self fileExistsAtPath:actualPath isDirectory:&isDir] && isDir) { + continue; + } else if ([self createDirectoryAtPath:actualPath attributes:attributes]) { + continue; + } else { + return NO; + } + } + + return YES; +} + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + +- (NSArray *)gtm_filePathsWithExtension:(NSString *)extension + inDirectory:(NSString *)directoryPath { + NSArray *extensions = nil; + + // Treat no extension and an empty extension as the user requesting all files + if (extension != nil && ![extension isEqualToString:@""]) + extensions = [NSArray arrayWithObject:extension]; + + return [self gtm_filePathsWithExtensions:extensions + inDirectory:directoryPath]; +} + +- (NSArray *)gtm_filePathsWithExtensions:(NSArray *)extensions + inDirectory:(NSString *)directoryPath { + if (directoryPath == nil) + return nil; + + // |basenames| will contain only the matching file names, not their full paths. + NSArray *basenames = [self directoryContentsAtPath:directoryPath]; + + // Check if dir doesn't exist or couldn't be opened. + if (basenames == nil) + return nil; + + // Check if dir is empty. + if ([basenames count] == 0) + return basenames; + + NSMutableArray *paths = [NSMutableArray arrayWithCapacity:[basenames count]]; + NSString *basename; + NSEnumerator *basenamesEnumerator = [basenames objectEnumerator]; + + // Convert all the |basenames| to full paths. + while ((basename = [basenamesEnumerator nextObject])) { + NSString *fullPath = [directoryPath stringByAppendingPathComponent:basename]; + [paths addObject:fullPath]; + } + + // Check if caller wants all files, regardless of extension. + if (extensions == nil || [extensions count] == 0) + return paths; + + return [paths pathsMatchingExtensions:extensions]; +} + +@end diff --git a/Foundation/GTMNSFileManager+PathTest.m b/Foundation/GTMNSFileManager+PathTest.m new file mode 100644 index 0000000..10b4cbd --- /dev/null +++ b/Foundation/GTMNSFileManager+PathTest.m @@ -0,0 +1,58 @@ +// +// GTMNSFileManager+PathTest.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import <SenTestingKit/SenTestingKit.h> +#import "GTMNSFileManager+Path.h" + +@interface GTMNSFileManager_PathTest : SenTestCase +@end + +@implementation GTMNSFileManager_PathTest + +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + +- (void)testCreateFullPathToDirectoryAttributes { + NSString *baseDir = + [NSTemporaryDirectory() stringByAppendingPathComponent:@"testCreateFullPathToDirectoryAttributes"]; + NSString *testPath = [baseDir stringByAppendingPathComponent:@"/foo/bar/baz"]; + NSFileManager *fm = [NSFileManager defaultManager]; + + STAssertFalse([fm fileExistsAtPath:testPath], + @"You must delete '%@' before running this test", baseDir); + + STAssertTrue([fm gtm_createFullPathToDirectory:testPath attributes:nil], + @"Failed to create nested testPath"); + + STAssertTrue([fm removeFileAtPath:baseDir handler:nil], + @"Failed to delete \'%@\'", baseDir); + + NSString *pathToFail = [@"/etc" stringByAppendingPathComponent:testPath]; + STAssertFalse([fm gtm_createFullPathToDirectory:pathToFail attributes:nil], + @"We were allowed to create a dir in '/etc'?!"); + + STAssertFalse([fm gtm_createFullPathToDirectory:nil attributes:nil], + @"Should have failed when passed (nil)"); +} + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + +- (void)testfilePathsWithExtensionsInDirectory { + // TODO: need a test for filePathsWithExtensions:inDirectory: +} + +@end diff --git a/GTM.xcodeproj/project.pbxproj b/GTM.xcodeproj/project.pbxproj index 7439100..abb4fef 100644 --- a/GTM.xcodeproj/project.pbxproj +++ b/GTM.xcodeproj/project.pbxproj @@ -22,6 +22,9 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + F413908F0D75F63C00F72B31 /* GTMNSFileManager+Path.h in Headers */ = {isa = PBXBuildFile; fileRef = F413908C0D75F63C00F72B31 /* GTMNSFileManager+Path.h */; }; + F41390900D75F63C00F72B31 /* GTMNSFileManager+Path.m in Sources */ = {isa = PBXBuildFile; fileRef = F413908D0D75F63C00F72B31 /* GTMNSFileManager+Path.m */; }; + F41390920D75F64D00F72B31 /* GTMNSFileManager+PathTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F413908E0D75F63C00F72B31 /* GTMNSFileManager+PathTest.m */; }; F428FF030D48E55E00382ED1 /* GTMNSBezierPath+CGPath.h in Headers */ = {isa = PBXBuildFile; fileRef = F428FEFF0D48E55E00382ED1 /* GTMNSBezierPath+CGPath.h */; }; F428FF040D48E55E00382ED1 /* GTMNSBezierPath+CGPath.m in Sources */ = {isa = PBXBuildFile; fileRef = F428FF000D48E55E00382ED1 /* GTMNSBezierPath+CGPath.m */; }; F428FF090D48E57300382ED1 /* GTMNSBezierPath+CGPathTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F428FF010D48E55E00382ED1 /* GTMNSBezierPath+CGPathTest.m */; }; @@ -128,6 +131,9 @@ 0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; }; 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; }; 32DBCF5E0370ADEE00C91783 /* GTM_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTM_Prefix.pch; sourceTree = "<group>"; }; + F413908C0D75F63C00F72B31 /* GTMNSFileManager+Path.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSFileManager+Path.h"; sourceTree = "<group>"; }; + F413908D0D75F63C00F72B31 /* GTMNSFileManager+Path.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSFileManager+Path.m"; sourceTree = "<group>"; }; + F413908E0D75F63C00F72B31 /* GTMNSFileManager+PathTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSFileManager+PathTest.m"; sourceTree = "<group>"; }; F428FEFF0D48E55E00382ED1 /* GTMNSBezierPath+CGPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSBezierPath+CGPath.h"; sourceTree = "<group>"; }; F428FF000D48E55E00382ED1 /* GTMNSBezierPath+CGPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSBezierPath+CGPath.m"; sourceTree = "<group>"; }; F428FF010D48E55E00382ED1 /* GTMNSBezierPath+CGPathTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSBezierPath+CGPathTest.m"; sourceTree = "<group>"; }; @@ -344,6 +350,9 @@ F43E4DD60D4E56320041161F /* GTMNSEnumerator+Filter.h */, F43E4DD70D4E56320041161F /* GTMNSEnumerator+Filter.m */, F43E4DD80D4E56320041161F /* GTMNSEnumerator+FilterTest.m */, + F413908C0D75F63C00F72B31 /* GTMNSFileManager+Path.h */, + F413908D0D75F63C00F72B31 /* GTMNSFileManager+Path.m */, + F413908E0D75F63C00F72B31 /* GTMNSFileManager+PathTest.m */, F48FE28E0D198D24009257D2 /* GTMNSString+HTML.h */, F48FE28F0D198D24009257D2 /* GTMNSString+HTML.m */, F48FE2900D198D24009257D2 /* GTMNSString+HTMLTest.m */, @@ -406,6 +415,7 @@ F43E4E610D4E5EC90041161F /* GTMNSData+zlib.h in Headers */, F437F55D0D50BC0A00F5C3A4 /* GTMRegex.h in Headers */, F47A79880D746EE9002302AB /* GTMScriptRunner.h in Headers */, + F413908F0D75F63C00F72B31 /* GTMNSFileManager+Path.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -558,6 +568,7 @@ F43E4DDE0D4E56380041161F /* GTMNSEnumerator+FilterTest.m in Sources */, F437F5620D50BC1D00F5C3A4 /* GTMRegexTest.m in Sources */, F47A798B0D746EFC002302AB /* GTMScriptRunnerTest.m in Sources */, + F41390920D75F64D00F72B31 /* GTMNSFileManager+PathTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -582,6 +593,7 @@ F43E4E620D4E5EC90041161F /* GTMNSData+zlib.m in Sources */, F437F55E0D50BC0A00F5C3A4 /* GTMRegex.m in Sources */, F47A79890D746EE9002302AB /* GTMScriptRunner.m in Sources */, + F41390900D75F63C00F72B31 /* GTMNSFileManager+Path.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt index fee7f61..369ac3b 100644 --- a/ReleaseNotes.txt +++ b/ReleaseNotes.txt @@ -22,6 +22,8 @@ Changes since 1.0.0 - Added GTMScriptRunner for spawning scripts. +- Added GTMNSFileManager+Path for two small helpers. + Release 1.0.0 14-January-2008 |