diff options
-rw-r--r-- | Foundation/GTMNSFileHandle+UniqueName.h | 81 | ||||
-rw-r--r-- | Foundation/GTMNSFileHandle+UniqueName.m | 120 | ||||
-rw-r--r-- | Foundation/GTMNSFileHandle+UniqueNameTest.m | 167 | ||||
-rw-r--r-- | Foundation/GTMNSFileManager+PathTest.m | 19 | ||||
-rw-r--r-- | Foundation/GTMPathTest.m | 11 | ||||
-rw-r--r-- | GTM.xcodeproj/project.pbxproj | 14 | ||||
-rw-r--r-- | GTMiPhone.xcodeproj/project.pbxproj | 10 | ||||
-rw-r--r-- | ReleaseNotes.txt | 5 |
8 files changed, 404 insertions, 23 deletions
diff --git a/Foundation/GTMNSFileHandle+UniqueName.h b/Foundation/GTMNSFileHandle+UniqueName.h new file mode 100644 index 0000000..38197cd --- /dev/null +++ b/Foundation/GTMNSFileHandle+UniqueName.h @@ -0,0 +1,81 @@ +// +// GTMNSFileHandle+UniqueName.h +// +// Copyright 2010 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> +#import "GTMDefines.h" + +@interface NSFileHandle (GTMFileHandleUniqueNameAdditions) + +// Creates a read/write temporary file in NSTemporaryDirectory with mode 0600. +// The template should be similar to the template passed to mkstemp. +// If there is an extension on the nameTemplate it will remain. An example +// template is "MyAppXXXXXX.txt". +// If |path| is not nil, it will contain the derived path for the file. +// The file descriptor wrapped by the NSFileHandle will be closed on dealloc. ++ (id)gtm_fileHandleForTemporaryFileBasedOn:(NSString *)nameTemplate + finalPath:(NSString **)path; + +// Return an opened read/write file handle with mode 0600 based on a template. +// The template should be similar to the template passed to mkstemp. +// If there is an extension on the pathTemplate it will remain. An example +// template is "/Applications/MyAppXXXXXX.txt". +// If |path| is not nil, it will contain the derived path for the file. +// The file descriptor wrapped by the NSFileHandle will be closed on dealloc. ++ (id)gtm_fileHandleWithUniqueNameBasedOn:(NSString *)pathTemplate + finalPath:(NSString **)path; + +// Same as fileHandleWithUniqueNameBasedOn:finalName: but splits up the +// template from the directory. ++ (id)gtm_fileHandleWithUniqueNameBasedOn:(NSString *)nameTemplate + inDirectory:(NSString *)directory + finalPath:(NSString **)path; + + +// Same as fileHandleWithUniqueNameBasedOn:inDirectory:finalName: but finds +// the directory using the |directory| and |mask| arguments. ++ (id)gtm_fileHandleWithUniqueNameBasedOn:(NSString *)nameTemplate + inDirectory:(NSSearchPathDirectory)directory + domainMask:(NSSearchPathDomainMask)mask + finalPath:(NSString **)path; +@end + +@interface NSFileManager (GTMFileManagerUniqueNameAdditions) + +// Creates a new directory in NSTemporaryDirectory with mode 0700. +// The template should be similar to the template passed to mkdtemp. +- (NSString *)gtm_createTemporaryDirectoryBasedOn:(NSString *)nameTemplate; + +// Return the path to a directory with mode 0700 based on a template. +// The template should be similar to the template passed to mkdtemp. +- (NSString *)gtm_createDirectoryWithUniqueNameBasedOn:(NSString *)nameTemplate; + +// Same as createDirectoryWithUniqueNameBasedOn: but splits up the +// template from the directory. +- (NSString *)gtm_createDirectoryWithUniqueNameBasedOn:(NSString *)pathTemplate + inDirectory:(NSString *)directory; + +// Same as createDirectoryWithUniqueNameBasedOn:inDirectory: but finds +// the directory using the |directory| and |mask| arguments. +- (NSString *)gtm_createDirectoryWithUniqueNameBasedOn:(NSString *)pathTemplate + inDirectory:(NSSearchPathDirectory)directory + domainMask:(NSSearchPathDomainMask)mask; +@end + +// Same template as you would pass to mktemp. Note that this has the same +// potential race conditions for use with file creation as mktemp does. +GTM_EXTERN NSString *GTMUniqueFileObjectPathBasedOn(NSString *pathTemplate); diff --git a/Foundation/GTMNSFileHandle+UniqueName.m b/Foundation/GTMNSFileHandle+UniqueName.m new file mode 100644 index 0000000..fc790ee --- /dev/null +++ b/Foundation/GTMNSFileHandle+UniqueName.m @@ -0,0 +1,120 @@ +// +// GTMNSFileHandle+UniqueName.m +// +// Copyright 2010 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 "GTMNSFileHandle+UniqueName.h" +#include <unistd.h> + +NSString *GTMUniqueFileObjectPathBasedOn(NSString *pathTemplate) { + if (!pathTemplate) return nil; + char *pathTemplateCString = strdup([pathTemplate fileSystemRepresentation]); + if (!pathTemplateCString) return nil; + char *newCName = mktemp(pathTemplateCString); + NSString *newName = newCName ? [NSString stringWithUTF8String:newCName] : nil; + free(pathTemplateCString); + return newName; +} + +@implementation NSFileHandle (GTMFileHandleUniqueNameAdditions) + ++ (id)gtm_fileHandleWithUniqueNameBasedOn:(NSString *)pathTemplate + finalPath:(NSString **)path { + if (!pathTemplate) return nil; + NSString *extension = [pathTemplate pathExtension]; + char *pathTemplateCString = strdup([pathTemplate fileSystemRepresentation]); + if (!pathTemplateCString) return nil; + int fileDescriptor = mkstemps(pathTemplateCString, (int)[extension length]); + if (fileDescriptor == -1) { + free(pathTemplateCString); + return nil; + } + NSFileHandle *handle + = [[[NSFileHandle alloc] initWithFileDescriptor:fileDescriptor + closeOnDealloc:YES] autorelease]; + if (handle && path) { + *path = [NSString stringWithUTF8String:pathTemplateCString]; + } + free(pathTemplateCString); + return handle; +} + ++ (id)gtm_fileHandleWithUniqueNameBasedOn:(NSString *)nameTemplate + inDirectory:(NSString *)directory + finalPath:(NSString **)path { + NSString *fullPath = [directory stringByAppendingPathComponent:nameTemplate]; + return [self gtm_fileHandleWithUniqueNameBasedOn:fullPath finalPath:path]; +} + ++ (id)gtm_fileHandleWithUniqueNameBasedOn:(NSString *)nameTemplate + inDirectory:(NSSearchPathDirectory)directory + domainMask:(NSSearchPathDomainMask)mask + finalPath:(NSString **)path { + NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(directory, + mask, + YES); + if ([searchPaths count] == 0) return nil; + NSString *searchPath = [searchPaths objectAtIndex:0]; + return [self gtm_fileHandleWithUniqueNameBasedOn:nameTemplate + inDirectory:searchPath + finalPath:path]; +} + ++ (id)gtm_fileHandleForTemporaryFileBasedOn:(NSString *)nameTemplate + finalPath:(NSString **)path { + return [self gtm_fileHandleWithUniqueNameBasedOn:nameTemplate + inDirectory:NSTemporaryDirectory() + finalPath:path]; +} + +@end + +@implementation NSFileManager (GTMFileManagerUniqueNameAdditions) + +- (NSString *)gtm_createDirectoryWithUniqueNameBasedOn:(NSString *)pathTemplate { + if (!pathTemplate) return nil; + char *pathTemplateCString = strdup([pathTemplate fileSystemRepresentation]); + if (!pathTemplateCString) return nil; + char *outCName = mkdtemp(pathTemplateCString); + NSString *outName = outCName ? [NSString stringWithUTF8String:outCName] : nil; + free(pathTemplateCString); + return outName; +} + +- (NSString *)gtm_createDirectoryWithUniqueNameBasedOn:(NSString *)nameTemplate + inDirectory:(NSString *)directory { + NSString *fullPath = [directory stringByAppendingPathComponent:nameTemplate]; + return [self gtm_createDirectoryWithUniqueNameBasedOn:fullPath]; +} + +- (NSString *)gtm_createDirectoryWithUniqueNameBasedOn:(NSString *)nameTemplate + inDirectory:(NSSearchPathDirectory)directory + domainMask:(NSSearchPathDomainMask)mask { + NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(directory, + mask, + YES); + if ([searchPaths count] == 0) return nil; + NSString *searchPath = [searchPaths objectAtIndex:0]; + return [self gtm_createDirectoryWithUniqueNameBasedOn:nameTemplate + inDirectory:searchPath]; +} + +- (NSString *)gtm_createTemporaryDirectoryBasedOn:(NSString *)nameTemplate { + return [self gtm_createDirectoryWithUniqueNameBasedOn:nameTemplate + inDirectory:NSTemporaryDirectory()]; +} + +@end diff --git a/Foundation/GTMNSFileHandle+UniqueNameTest.m b/Foundation/GTMNSFileHandle+UniqueNameTest.m new file mode 100644 index 0000000..833edc9 --- /dev/null +++ b/Foundation/GTMNSFileHandle+UniqueNameTest.m @@ -0,0 +1,167 @@ +// +// GTMNSFileHandle+UniqueNameTest.m +// +// Copyright 2010 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 "GTMSenTestCase.h" +#import "GTMNSFileHandle+UniqueName.h" + +@interface GTMNSFileHandle_UniqueNameTest : GTMTestCase +@end + +@implementation GTMNSFileHandle_UniqueNameTest + +- (void)testGTMUniqueFileObjectPathBasedOn { + NSString *path = GTMUniqueFileObjectPathBasedOn(nil); + STAssertNil(path, nil); + path = GTMUniqueFileObjectPathBasedOn(@"/System"); + STAssertNil(path, nil); + path = GTMUniqueFileObjectPathBasedOn(@"/Users/HappyXXXXXX"); + STAssertTrue([path hasPrefix:@"/Users/Happy"], nil); + STAssertNotEqualObjects(path, @"/Users/HappyXXXXXX", nil); +} + +- (void)testFileHandleWithUniqueNameBasedOnFinalPath { + NSFileHandle *handle + = [NSFileHandle gtm_fileHandleWithUniqueNameBasedOn:nil + finalPath:nil]; + STAssertNil(handle, nil); + + // Try and create a file where we shouldn't be able to. + NSString *path = nil; + handle = [NSFileHandle gtm_fileHandleWithUniqueNameBasedOn:@"/System/HappyXXX.txt" + finalPath:&path]; + STAssertNil(handle, nil); + STAssertNil(path, nil); + + NSFileManager *fm = [NSFileManager defaultManager]; + NSString *tempDir + = [fm gtm_createTemporaryDirectoryBasedOn:@"GTMNSFileHandle_UniqueNameTestXXXXXX"]; + STAssertNotNil(tempDir, nil); + BOOL isDirectory = NO; + STAssertTrue([fm fileExistsAtPath:tempDir isDirectory:&isDirectory] + && isDirectory, nil); + + // Test with extension + handle = [NSFileHandle gtm_fileHandleWithUniqueNameBasedOn:@"HappyXXX.txt" + inDirectory:tempDir + finalPath:&path]; + STAssertNotNil(handle, nil); + STAssertEqualObjects([path pathExtension], @"txt", nil); + STAssertTrue([fm fileExistsAtPath:path], nil); + + // Test without extension + handle = [NSFileHandle gtm_fileHandleWithUniqueNameBasedOn:@"HappyXXX" + inDirectory:tempDir + finalPath:&path]; + STAssertNotNil(handle, nil); + STAssertEqualObjects([path pathExtension], @"", nil); + STAssertTrue([fm fileExistsAtPath:path], nil); + + // Test passing in same name twice + NSString *fullPath = [tempDir stringByAppendingPathComponent:@"HappyXXX"]; + NSString *newPath = nil; + handle = [NSFileHandle gtm_fileHandleWithUniqueNameBasedOn:fullPath + finalPath:&newPath]; + STAssertNotNil(handle, nil); + STAssertNotNil(newPath, nil); + STAssertNotEqualObjects(path, newPath, nil); + STAssertTrue([fm fileExistsAtPath:newPath], nil); + + // Test passing in same name twice with no template + fullPath = [tempDir stringByAppendingPathComponent:@"Sad"]; + newPath = nil; + handle = [NSFileHandle gtm_fileHandleWithUniqueNameBasedOn:fullPath + finalPath:&newPath]; + STAssertNotNil(handle, nil); + STAssertNotNil(newPath, nil); + + newPath = nil; + handle = [NSFileHandle gtm_fileHandleWithUniqueNameBasedOn:fullPath + finalPath:&newPath]; + STAssertNil(handle, nil); + STAssertNil(newPath, nil); + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + [fm removeFileAtPath:tempDir handler:nil]; +#else // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + [fm removeItemAtPath:tempDir error:nil]; +#endif + +} + +- (void)testFileHandleWithUniqueNameBasedOnInDirectorySearchMaskFinalPath { + NSFileManager *fm = [NSFileManager defaultManager]; + NSString *path = nil; + NSFileHandle *handle + = [NSFileHandle gtm_fileHandleWithUniqueNameBasedOn:nil + inDirectory:NSCachesDirectory + domainMask:NSUserDomainMask + finalPath:&path]; + STAssertNil(handle, nil); + STAssertNil(path, nil); + + handle = [NSFileHandle gtm_fileHandleWithUniqueNameBasedOn:@"HappyXXX.txt" + inDirectory:NSCachesDirectory + domainMask:NSUserDomainMask + finalPath:&path]; + STAssertNotNil(handle, nil); + STAssertNotNil(path, nil); + STAssertTrue([fm fileExistsAtPath:path], nil); +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + [fm removeFileAtPath:path handler:nil]; +#else // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + [fm removeItemAtPath:path error:nil]; +#endif +} + +@end + +@interface GTMNSFileManager_UniqueNameTest : GTMTestCase +@end + +@implementation GTMNSFileManager_UniqueNameTest + +- (void)testCreateDirectoryWithUniqueNameBasedOn { + NSFileManager *fm = [NSFileManager defaultManager]; + NSString *path + = [fm gtm_createDirectoryWithUniqueNameBasedOn:@"/System/HappyXXX.txt"]; + STAssertNil(path, nil); +} + +- (void)testCreateDirectoryWithUniqueNameBasedOnInDirectorySearchMask { + NSFileManager *fm = [NSFileManager defaultManager]; + NSString *path = [fm gtm_createDirectoryWithUniqueNameBasedOn:nil + inDirectory:NSCachesDirectory + domainMask:NSUserDomainMask]; + STAssertNil(path, nil); + + path = [fm gtm_createDirectoryWithUniqueNameBasedOn:@"HappyXXX.txt" + inDirectory:NSCachesDirectory + domainMask:NSUserDomainMask]; + STAssertNotNil(path, nil); + BOOL isDirectory = NO; + STAssertTrue([fm fileExistsAtPath:path isDirectory:&isDirectory] + && isDirectory, nil); +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + [fm removeFileAtPath:path handler:nil]; +#else // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + [fm removeItemAtPath:path error:nil]; +#endif +} + +@end + diff --git a/Foundation/GTMNSFileManager+PathTest.m b/Foundation/GTMNSFileManager+PathTest.m index 2ce8683..db51c9b 100644 --- a/Foundation/GTMNSFileManager+PathTest.m +++ b/Foundation/GTMNSFileManager+PathTest.m @@ -18,6 +18,7 @@ #import "GTMSenTestCase.h" #import "GTMNSFileManager+Path.h" +#import "GTMNSFileHandle+UniqueName.h" @interface GTMNSFileManager_PathTest : GTMTestCase { NSString *baseDir_; @@ -28,22 +29,10 @@ - (void)setUp { // make a directory to scribble in - NSString *base = NSTemporaryDirectory(); - base = [base stringByAppendingPathComponent:@"GTMNSFileManager_PathTest"]; NSFileManager *fm = [NSFileManager defaultManager]; - STAssertFalse([fm fileExistsAtPath:base], @"File exists at %@", base); -#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 - NSError *error = nil; - STAssertTrue([fm createDirectoryAtPath:base - withIntermediateDirectories:YES - attributes:nil - error:&error], - @"Unable to create %@: %@", base, error); -#else - STAssertTrue([fm createDirectoryAtPath:base attributes:nil], - @"Unable to create %@", base); -#endif - baseDir_ = [base retain]; + baseDir_ + = [[fm gtm_createTemporaryDirectoryBasedOn:@"GTMNSFileManager_PathTestXXXXXX"] + retain]; } - (void)tearDown { diff --git a/Foundation/GTMPathTest.m b/Foundation/GTMPathTest.m index 1e58f50..59e3199 100644 --- a/Foundation/GTMPathTest.m +++ b/Foundation/GTMPathTest.m @@ -19,6 +19,7 @@ #import "GTMSenTestCase.h" #import "GTMPath.h" #import "GTMUnitTestDevLog.h" +#import "GTMNSFileHandle+UniqueName.h" #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 // NSFileManager has improved substantially in Leopard and beyond, so GTMPath @@ -33,15 +34,11 @@ @implementation GTMPathTest - (void)setUp { - NSString *tmp = NSTemporaryDirectory(); - STAssertNotNil(tmp, nil); + NSFileManager *mgr = [NSFileManager defaultManager]; + testDirectory_ + = [[mgr gtm_createTemporaryDirectoryBasedOn:@"GTMPathTestXXXXXX"] retain]; - testDirectory_ = [[tmp stringByAppendingPathComponent:@"GTMPathTest"] retain]; STAssertNotNil(testDirectory_, nil); - - NSFileManager *mgr = [NSFileManager defaultManager]; - BOOL created = [mgr createDirectoryAtPath:testDirectory_ attributes:nil]; - STAssertTrue(created, nil); } - (void)tearDown { diff --git a/GTM.xcodeproj/project.pbxproj b/GTM.xcodeproj/project.pbxproj index 52c865b..299e470 100644 --- a/GTM.xcodeproj/project.pbxproj +++ b/GTM.xcodeproj/project.pbxproj @@ -104,6 +104,10 @@ 8B21BE9211532CDC00DD2686 /* GTMNSAnimatablePropertyContainerTest.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8B21BE9111532CDC00DD2686 /* GTMNSAnimatablePropertyContainerTest.xib */; }; 8B21DE56117E5CB7000E004F /* GTMLocalizedString.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B21DE54117E5CB7000E004F /* GTMLocalizedString.h */; }; 8B2789960EF855FB00D68C01 /* GTMUnitTestingWindow.10.5.6.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 8B2789950EF855FB00D68C01 /* GTMUnitTestingWindow.10.5.6.tiff */; }; + 8B29078711F8D1BF0064F50F /* GTMNSFileHandle+UniqueName.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B29078511F8D1BF0064F50F /* GTMNSFileHandle+UniqueName.m */; }; + 8B29078811F8D1BF0064F50F /* GTMNSFileHandle+UniqueNameTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B29078611F8D1BF0064F50F /* GTMNSFileHandle+UniqueNameTest.m */; }; + 8B29080911F8E1630064F50F /* GTMNSFileHandle+UniqueName.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B29078511F8D1BF0064F50F /* GTMNSFileHandle+UniqueName.m */; }; + 8B29080A11F8E1670064F50F /* GTMNSFileHandle+UniqueName.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B29078411F8D1BF0064F50F /* GTMNSFileHandle+UniqueName.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8B307FF81056B773006C4C7A /* GTMNSNumber+64Bit.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B307FF61056B773006C4C7A /* GTMNSNumber+64Bit.m */; }; 8B307FF91056B773006C4C7A /* GTMNSNumber+64Bit.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B307FF71056B773006C4C7A /* GTMNSNumber+64Bit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8B3080151056B917006C4C7A /* GTMNSNumber+64BitTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B3080141056B917006C4C7A /* GTMNSNumber+64BitTest.m */; }; @@ -609,6 +613,9 @@ 8B21BE9111532CDC00DD2686 /* GTMNSAnimatablePropertyContainerTest.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = GTMNSAnimatablePropertyContainerTest.xib; sourceTree = "<group>"; }; 8B21DE54117E5CB7000E004F /* GTMLocalizedString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMLocalizedString.h; sourceTree = "<group>"; }; 8B2789950EF855FB00D68C01 /* GTMUnitTestingWindow.10.5.6.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = GTMUnitTestingWindow.10.5.6.tiff; sourceTree = "<group>"; }; + 8B29078411F8D1BF0064F50F /* GTMNSFileHandle+UniqueName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSFileHandle+UniqueName.h"; sourceTree = "<group>"; }; + 8B29078511F8D1BF0064F50F /* GTMNSFileHandle+UniqueName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSFileHandle+UniqueName.m"; sourceTree = "<group>"; }; + 8B29078611F8D1BF0064F50F /* GTMNSFileHandle+UniqueNameTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSFileHandle+UniqueNameTest.m"; sourceTree = "<group>"; }; 8B307FF61056B773006C4C7A /* GTMNSNumber+64Bit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSNumber+64Bit.m"; sourceTree = "<group>"; }; 8B307FF71056B773006C4C7A /* GTMNSNumber+64Bit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSNumber+64Bit.h"; sourceTree = "<group>"; }; 8B3080141056B917006C4C7A /* GTMNSNumber+64BitTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSNumber+64BitTest.m"; sourceTree = "<group>"; }; @@ -1433,6 +1440,9 @@ F43E4DD60D4E56320041161F /* GTMNSEnumerator+Filter.h */, F43E4DD70D4E56320041161F /* GTMNSEnumerator+Filter.m */, F43E4DD80D4E56320041161F /* GTMNSEnumerator+FilterTest.m */, + 8B29078411F8D1BF0064F50F /* GTMNSFileHandle+UniqueName.h */, + 8B29078511F8D1BF0064F50F /* GTMNSFileHandle+UniqueName.m */, + 8B29078611F8D1BF0064F50F /* GTMNSFileHandle+UniqueNameTest.m */, 8B8EC87B0EF17C270044D13F /* GTMNSFileManager+Carbon.h */, 8B8EC87C0EF17C270044D13F /* GTMNSFileManager+Carbon.m */, 8B8EC87F0EF17C2F0044D13F /* GTMNSFileManager+CarbonTest.m */, @@ -1664,6 +1674,7 @@ 8B21DE56117E5CB7000E004F /* GTMLocalizedString.h in Headers */, 8BB7802E11B6C4EA00AB31AF /* GTMGoogleSearch.h in Headers */, 8BCB59F011C00ED6009B6C40 /* GTMNSScanner+Unsigned.h in Headers */, + 8B29080A11F8E1670064F50F /* GTMNSFileHandle+UniqueName.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2223,6 +2234,8 @@ 8B17FD15117638D500E7A908 /* GTMFoundationUnitTestingUtilities.m in Sources */, 8B455F5E1193870A00ABD707 /* GTMLocalizedStringTest.m in Sources */, 8BCB59F311C00EF6009B6C40 /* GTMNSScanner+UnsignedTest.m in Sources */, + 8B29078711F8D1BF0064F50F /* GTMNSFileHandle+UniqueName.m in Sources */, + 8B29078811F8D1BF0064F50F /* GTMNSFileHandle+UniqueNameTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2300,6 +2313,7 @@ 8BDB8A9A1152E1B200C411B1 /* GTMNSAnimatablePropertyContainer.m in Sources */, 8BB77A0611B5A0A100AB31AF /* GTMGoogleSearch.m in Sources */, 8BCB59F111C00ED6009B6C40 /* GTMNSScanner+Unsigned.m in Sources */, + 8B29080911F8E1630064F50F /* GTMNSFileHandle+UniqueName.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/GTMiPhone.xcodeproj/project.pbxproj b/GTMiPhone.xcodeproj/project.pbxproj index f2984d5..651b263 100644 --- a/GTMiPhone.xcodeproj/project.pbxproj +++ b/GTMiPhone.xcodeproj/project.pbxproj @@ -57,6 +57,8 @@ 64D0F5EE0FD3E68400506CC7 /* GTMUIImage+Resize_100x100_to_40x60.png in Resources */ = {isa = PBXBuildFile; fileRef = 64D0F5DC0FD3E68400506CC7 /* GTMUIImage+Resize_100x100_to_40x60.png */; }; 64D0F5EF0FD3E68400506CC7 /* GTMUIImage+Resize_100x100_to_50x50.png in Resources */ = {isa = PBXBuildFile; fileRef = 64D0F5DD0FD3E68400506CC7 /* GTMUIImage+Resize_100x100_to_50x50.png */; }; 67A7820C0E00927400EBF506 /* GTMIPhoneUnitTestDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 67A7820B0E00927400EBF506 /* GTMIPhoneUnitTestDelegate.m */; }; + 8B2908B211F8E7070064F50F /* GTMNSFileHandle+UniqueName.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B2908B011F8E7070064F50F /* GTMNSFileHandle+UniqueName.m */; }; + 8B2908B311F8E7070064F50F /* GTMNSFileHandle+UniqueNameTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B2908B111F8E7070064F50F /* GTMNSFileHandle+UniqueNameTest.m */; }; 8B308BCE0DAD0B8400183556 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B308BCD0DAD0B8400183556 /* QuartzCore.framework */; }; 8B3AA8F30E032FC7007E31B5 /* GTMNSString+URLArguments.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B3AA8F10E032FC7007E31B5 /* GTMNSString+URLArguments.m */; }; 8B3AA8F40E032FC7007E31B5 /* GTMNSString+URLArgumentsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B3AA8F20E032FC7007E31B5 /* GTMNSString+URLArgumentsTest.m */; }; @@ -190,6 +192,9 @@ 67A7820B0E00927400EBF506 /* GTMIPhoneUnitTestDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMIPhoneUnitTestDelegate.m; sourceTree = "<group>"; }; 8B23010811C180E2001FA319 /* DebugiPhone40.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugiPhone40.xcconfig; sourceTree = "<group>"; }; 8B23010911C180E2001FA319 /* ReleaseiPhone40.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ReleaseiPhone40.xcconfig; sourceTree = "<group>"; }; + 8B2908AF11F8E7070064F50F /* GTMNSFileHandle+UniqueName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSFileHandle+UniqueName.h"; sourceTree = "<group>"; }; + 8B2908B011F8E7070064F50F /* GTMNSFileHandle+UniqueName.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSFileHandle+UniqueName.m"; sourceTree = "<group>"; }; + 8B2908B111F8E7070064F50F /* GTMNSFileHandle+UniqueNameTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSFileHandle+UniqueNameTest.m"; sourceTree = "<group>"; }; 8B30806F1056BDCE006C4C7A /* GTMNSNumber+64Bit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSNumber+64Bit.h"; sourceTree = "<group>"; }; 8B3080701056BDCE006C4C7A /* GTMNSNumber+64Bit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSNumber+64Bit.m"; sourceTree = "<group>"; }; 8B3080711056BDCE006C4C7A /* GTMNSNumber+64BitTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSNumber+64BitTest.m"; sourceTree = "<group>"; }; @@ -497,6 +502,9 @@ 8BC047840DAE928A00C2D1CA /* GTMNSFileManager+Path.h */, 8BC047850DAE928A00C2D1CA /* GTMNSFileManager+Path.m */, 8BC047860DAE928A00C2D1CA /* GTMNSFileManager+PathTest.m */, + 8B2908AF11F8E7070064F50F /* GTMNSFileHandle+UniqueName.h */, + 8B2908B011F8E7070064F50F /* GTMNSFileHandle+UniqueName.m */, + 8B2908B111F8E7070064F50F /* GTMNSFileHandle+UniqueNameTest.m */, 8B30806F1056BDCE006C4C7A /* GTMNSNumber+64Bit.h */, 8B3080701056BDCE006C4C7A /* GTMNSNumber+64Bit.m */, 8B3080711056BDCE006C4C7A /* GTMNSNumber+64BitTest.m */, @@ -859,6 +867,8 @@ 8BCB5AB111C02D7D009B6C40 /* GTMNSScanner+Unsigned.m in Sources */, 8BCB5AB211C02D7D009B6C40 /* GTMNSScanner+UnsignedTest.m in Sources */, 8BFFCD7811C1934900E45777 /* GTMNSObject+KeyValueObservingTest.m in Sources */, + 8B2908B211F8E7070064F50F /* GTMNSFileHandle+UniqueName.m in Sources */, + 8B2908B311F8E7070064F50F /* GTMNSFileHandle+UniqueNameTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt index d2434ae..a96bd0d 100644 --- a/ReleaseNotes.txt +++ b/ReleaseNotes.txt @@ -417,7 +417,10 @@ Changes since 1.5.1 http://vocaro.com/trevor/blog/wp-content/uploads/2009/10/UIImage+Resize.h http://vocaro.com/trevor/blog/wp-content/uploads/2009/10/UIImage+Resize.m - +- Added support for creating uniquely named files and directories easily with + GTMNSFileHandle+UniqueName. + + Release 1.5.1 Changes since 1.5.0 16-June-2008 |