aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Foundation/GTMNSFileManager+Path.h71
-rw-r--r--Foundation/GTMNSFileManager+Path.m102
-rw-r--r--Foundation/GTMNSFileManager+PathTest.m58
-rw-r--r--GTM.xcodeproj/project.pbxproj12
-rw-r--r--ReleaseNotes.txt2
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