Permalink
Browse files

Don't store our data in ~/Documents

The Documents directory is potentially user-visible if the app
enables iTunes file sharing.
Instead, put our data files in ~/Library/Application Support/
CouchbaseMobile/.
Even better, make this configurable as a rootDirectory property
of the CouchbaseMobile object.

Change-Id: Ia40d22ea3341b3c892d00afde4ea5309587d8841
Reviewed-on: http://review.couchbase.org/10316
Tested-by: Farshid Ghods <farshid.ghods@gmail.com>
Reviewed-by: Jens Alfke <jens@couchbase.com>
  • Loading branch information...
1 parent 5a83f1c commit 53b345ef8cf699a192cf51a6260271cb1083dc15 @snej snej committed Oct 24, 2011
Showing with 55 additions and 19 deletions.
  1. +6 −1 Framework/Classes/CouchbaseMobile.h
  2. +49 −18 Framework/Classes/CouchbaseMobile.m
@@ -42,7 +42,7 @@
@private
id<CouchbaseDelegate> _delegate;
CFAbsoluteTime _timeStarted;
- NSString* _documentsDirectory;
+ NSString* _rootDirectory;
NSString* _bundlePath;
NSString* _iniFilePath;
NSURL* _serverURL;
@@ -87,6 +87,11 @@
require resources to go elsewhere, so in that case you might need to use a custom path.) */
- (id) initWithBundlePath: (NSString*)bundlePath;
+/** The root directory where Couchbase Mobile will store data files.
+ This defaults to ~/CouchbaseMobile.
+ You may NOT change this after starting the server. */
+@property (copy) NSString* rootDirectory;
+
/** The directory where CouchDB writes its log files. */
@property (readonly) NSString* logDirectory;
@@ -74,9 +74,27 @@ - (id) initWithBundlePath: (NSString*)bundlePath {
self = [super init];
if (self) {
_bundlePath = [bundlePath copy];
+
+ // rootDirectory defaults to ~/Library/Application Support/CouchbaseMobile.
+ // However, it used to be hardcoded to ~/Documents, so for backward compatibility
+ // (to keep apps from losing their data) we'll preserve that if we find a telltale
+ // ~/Documents/couchdb/ dir.
+
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,
YES);
- _documentsDirectory = [[paths objectAtIndex:0] copy];
+ NSString* documentsDir = [paths objectAtIndex:0];
+ BOOL isDir;
+ if ([[NSFileManager defaultManager]
+ fileExistsAtPath: [documentsDir stringByAppendingPathComponent: @"couchdb"]
+ isDirectory: &isDir] && isDir) {
+ _rootDirectory = [documentsDir copy];
+ NSLog(@"Couchbase: Found db files in ~/Documents, so using that as rootDirectory");
+ } else {
+ paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory,
+ NSUserDomainMask, YES);
+ _rootDirectory = [[[paths objectAtIndex:0]
+ stringByAppendingPathComponent: @"CouchbaseMobile"] copy];
+ }
}
return self;
}
@@ -92,7 +110,7 @@ - (id)init {
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
- [_documentsDirectory release];
+ [_rootDirectory release];
[_bundlePath release];
[_iniFilePath release];
[_serverURL release];
@@ -101,19 +119,31 @@ - (void)dealloc {
}
-@synthesize delegate = _delegate, iniFilePath=_iniFilePath, serverURL = _serverURL, error = _error, autoRestart = _autoRestart;
+@synthesize delegate = _delegate, iniFilePath = _iniFilePath, serverURL = _serverURL, error = _error, autoRestart = _autoRestart;
+- (NSString*) rootDirectory {
+ return _rootDirectory;
+}
+
+- (void) setRootDirectory:(NSString *)rootDirectory {
+ NSParameterAssert([rootDirectory hasPrefix: @"/"]);
+ NSAssert(!_started, @"Cannot set rootDirectory after starting server");
+ if (rootDirectory != _rootDirectory) {
+ [_rootDirectory release];
+ _rootDirectory = [rootDirectory copy];
+ }
+}
- (NSString*) logDirectory {
- return [_documentsDirectory stringByAppendingPathComponent:@"log"];
+ return [_rootDirectory stringByAppendingPathComponent:@"log"];
}
- (NSString*) databaseDirectory {
- return [_documentsDirectory stringByAppendingPathComponent:@"couchdb"];
+ return [_rootDirectory stringByAppendingPathComponent:@"couchdb"];
}
- (NSString*) localIniFilePath {
- return [_documentsDirectory stringByAppendingPathComponent:@"couchdb_local.ini"];
+ return [_rootDirectory stringByAppendingPathComponent:@"couchdb_local.ini"];
}
@@ -134,19 +164,20 @@ - (BOOL)start
_timeStarted = CFAbsoluteTimeGetCurrent();
NSLog(@"Couchbase: Starting CouchDB, using runtime files at: %@ (built %s, %s)",
_bundlePath, __DATE__, __TIME__);
+ NSLog(@"Couchbase: Storing data in %@", _rootDirectory);
if(![self createDir: self.logDirectory]
|| ![self createDir: self.databaseDirectory]
|| ![self createFile:self.localIniFilePath contents: @""]
- || ![self deleteFile:@"couch.uri" fromDir:_documentsDirectory])
+ || ![self deleteFile:@"couch.uri" fromDir:_rootDirectory])
{
return NO;
}
-
+
// Customize & install default_ios.ini:
if (![self installTemplateNamed: @"default_ios.ini"
fromDir: _bundlePath
- toDir: _documentsDirectory])
+ toDir: _rootDirectory])
return NO;
_started = YES;
@@ -164,7 +195,7 @@ - (void) maybeRestart {
}
- (void) restart {
- [[NSNotificationCenter defaultCenter]
+ [[NSNotificationCenter defaultCenter]
postNotificationName:kInternalRestartCouchNotification object:nil];
}
@@ -186,7 +217,7 @@ - (void)erlangThread {
// Yes, there are up to four layers of .ini files: Default, iOS, app, local.
erlang_args[11] = strdup([[_bundlePath stringByAppendingPathComponent:@"default.ini"]
fileSystemRepresentation]);
- erlang_args[12] = strdup([[_documentsDirectory stringByAppendingPathComponent:
+ erlang_args[12] = strdup([[_rootDirectory stringByAppendingPathComponent:
@"default_ios.ini"] fileSystemRepresentation]);
erlang_argc = 13;
if (_iniFilePath)
@@ -202,7 +233,7 @@ - (void)erlangThread {
setenv("ROOTDIR", erl_root, 1);
setenv("BINDIR", erl_bin, 1);
setenv("ERL_INETRC", erl_inetrc, 1);
-
+
[pool drain];
}
@@ -296,18 +327,18 @@ - (BOOL)createFile:(NSString*)path contents: (NSString*)contents {
- (BOOL)installItemNamed:(NSString*)name
fromDir:(NSString*)fromDir
toDir:(NSString*)toDir
- replace:(BOOL)replace
+ replace:(BOOL)replace
{
NSString *source = fromDir ? [fromDir stringByAppendingPathComponent: name] : name;
NSString *target = [toDir stringByAppendingPathComponent: [name lastPathComponent]];
-
+
NSError* error;
NSFileManager *fm= [NSFileManager defaultManager];
NSDate* targetModDate = [[fm attributesOfItemAtPath: target error:NULL] fileModificationDate];
if (targetModDate) {
if (!replace)
return YES; // Told not to overwrite, so return immediately
-
+
NSDate* sourceModDate = [[fm attributesOfItemAtPath: source error:&error]
fileModificationDate];
if (!sourceModDate) {
@@ -317,15 +348,15 @@ - (BOOL)installItemNamed:(NSString*)name
}
if ([targetModDate compare: sourceModDate] >= 0)
return YES; // target exists and is at least as new as the source
-
+
// Need to delete target first, or -copyItemAtPath will fail
if (![fm removeItemAtPath: target error: &error]) {
NSLog(@"Couchbase: Error installing to %@: %@", target, error);
self.error = error;
return NO;
}
}
-
+
// OK, do the copy:
if ([fm copyItemAtPath: source toPath: target error: &error]) {
NSLog(@"Couchbase: Installed %@ into %@", [name lastPathComponent], target);
@@ -374,7 +405,7 @@ - (BOOL)installTemplateNamed:(NSString*)name
options: 0
range: NSMakeRange(0, contents.length)];
[contents replaceOccurrencesOfString: @"$INSTALLDIR"
- withString: _documentsDirectory
+ withString: _rootDirectory
options: 0
range: NSMakeRange(0, contents.length)];
NSData* newData = [contents dataUsingEncoding: NSUTF8StringEncoding];

0 comments on commit 53b345e

Please sign in to comment.