aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Foundation/GTMNSFileHandle+UniqueName.h81
-rw-r--r--Foundation/GTMNSFileHandle+UniqueName.m120
-rw-r--r--Foundation/GTMNSFileHandle+UniqueNameTest.m167
-rw-r--r--Foundation/GTMNSFileManager+PathTest.m19
-rw-r--r--Foundation/GTMPathTest.m11
-rw-r--r--GTM.xcodeproj/project.pbxproj14
-rw-r--r--GTMiPhone.xcodeproj/project.pbxproj10
-rw-r--r--ReleaseNotes.txt5
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