New data directory handling

- Use $HOME/Zotero if zotero.sqlite exists, and set it as a custom data
  directory so that 4.0 uses it if loaded (resulting in a
  newer-db-version error instead of an empty database)
- Don't prompt whether to use data directory from the other version's
  profile directory (i.e., Firefox or Standalone) -- just do it
This commit is contained in:
Dan Stillman 2016-10-30 22:47:42 -04:00
parent f00a50bf5a
commit f2163b3433
3 changed files with 125 additions and 139 deletions

View File

@ -36,7 +36,6 @@ Components.utils.import("resource://gre/modules/osfile.jsm");
// Privileged (public) methods // Privileged (public) methods
this.init = init; this.init = init;
this.getProfileDirectory = getProfileDirectory; this.getProfileDirectory = getProfileDirectory;
this.getZoteroDirectory = getZoteroDirectory;
this.getStorageDirectory = getStorageDirectory; this.getStorageDirectory = getStorageDirectory;
this.getZoteroDatabase = getZoteroDatabase; this.getZoteroDatabase = getZoteroDatabase;
this.chooseZoteroDirectory = chooseZoteroDirectory; this.chooseZoteroDirectory = chooseZoteroDirectory;
@ -304,71 +303,6 @@ Components.utils.import("resource://gre/modules/osfile.jsm");
} }
_addToolbarIcon(); _addToolbarIcon();
return; return;
} else if(e.name == "ZOTERO_DIR_MAY_EXIST") {
var app = Zotero.isStandalone ? Zotero.getString('app.standalone') : Zotero.getString('app.firefox');
var altApp = !Zotero.isStandalone ? Zotero.getString('app.standalone') : Zotero.getString('app.firefox');
var message = Zotero.getString("dataDir.standaloneMigration.description", [app, altApp]);
if(e.multipleProfiles) {
message += "\n\n"+Zotero.getString("dataDir.standaloneMigration.multipleProfiles", [app, altApp]);
}
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
createInstance(Components.interfaces.nsIPromptService);
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_YES)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_NO)
+ (ps.BUTTON_POS_2) * (ps.BUTTON_TITLE_IS_STRING);
var index = ps.confirmEx(null, Zotero.getString("dataDir.standaloneMigration.title"), message,
buttonFlags, null, null,
Zotero.getString('dataDir.standaloneMigration.selectCustom'),
null, {});
// Migrate data directory
if (index == 0) {
// copy prefs
var prefsFile = e.profile.clone();
prefsFile.append("prefs.js");
if(prefsFile.exists()) {
// build sandbox
var sandbox = new Components.utils.Sandbox("http://www.example.com/");
Components.utils.evalInSandbox(
"var prefs = {};"+
"function user_pref(key, val) {"+
"prefs[key] = val;"+
"}"
, sandbox);
// remove comments
var prefsJs = Zotero.File.getContents(prefsFile);
prefsJs = prefsJs.replace(/^#[^\r\n]*$/mg, "");
// evaluate
Components.utils.evalInSandbox(prefsJs, sandbox);
var prefs = sandbox.prefs;
for(var key in prefs) {
if(key.substr(0, ZOTERO_CONFIG.PREF_BRANCH.length) === ZOTERO_CONFIG.PREF_BRANCH
&& key !== "extensions.zotero.firstRun2") {
Zotero.Prefs.set(key.substr(ZOTERO_CONFIG.PREF_BRANCH.length), prefs[key]);
}
}
}
// also set data dir if no custom data dir is now defined
if(!Zotero.Prefs.get("useDataDir")) {
var dir = e.dir.QueryInterface(Components.interfaces.nsILocalFile);
Zotero.Prefs.set('dataDir', dir.persistentDescriptor);
Zotero.Prefs.set('lastDataDir', dir.path);
Zotero.Prefs.set('useDataDir', true);
}
}
// Create new data directory
else if (index == 1) {
Zotero.File.createDirectoryIfMissing(e.curDir);
}
// Locate new data directory
else if (index == 2) {
Zotero.chooseZoteroDirectory(true);
}
} }
// DEBUG: handle more startup errors // DEBUG: handle more startup errors
else { else {
@ -979,7 +913,7 @@ Components.utils.import("resource://gre/modules/osfile.jsm");
return [defaultProfile, nSections > 1]; return [defaultProfile, nSections > 1];
} }
function getZoteroDirectory(){ this.getZoteroDirectory = function () {
if (_zoteroDirectory != false) { if (_zoteroDirectory != false) {
// Return a clone of the file pointer so that callers can modify it // Return a clone of the file pointer so that callers can modify it
return _zoteroDirectory.clone(); return _zoteroDirectory.clone();
@ -1002,69 +936,129 @@ Components.utils.import("resource://gre/modules/osfile.jsm");
} }
} }
else { else {
var file = Zotero.getProfileDirectory(); let homeDir = OS.Constants.Path.homeDir;
file.append('zotero'); let dataDir = OS.Path.join(homeDir, ZOTERO_CONFIG.CLIENT_NAME);
// if standalone and no directory yet, check Firefox directory //
// or if in Firefox and no directory yet, check standalone Zotero directory // TODO: asyncify
if(!file.exists()) { //
var prefDir = Services.dirsvc
.get("DefProfRt", Components.interfaces.nsILocalFile).parent.parent;
if(Zotero.isStandalone) { // Check for ~/Zotero/zotero.sqlite
if(Zotero.isWin) { dataDir = Zotero.File.pathToFile(dataDir);
prefDir = prefDir.parent; let dbFile = dataDir.clone();
prefDir.append("Mozilla"); dbFile.append(ZOTERO_CONFIG.ID + '.sqlite');
prefDir.append("Firefox"); if (dbFile.exists()) {
} else if(Zotero.isMac) { Zotero.debug("Using data directory " + dataDir.path);
prefDir.append("Firefox"); _zoteroDirectory = dataDir;
} else {
prefDir.append(".mozilla"); // Set as a custom data directory so that 4.0 uses it
prefDir.append("firefox"); this.setDataDirectory(dataDir.path);
}
return dataDir.clone();
}
// Check for 'zotero' dir in profile dir
let profileSubdir = Zotero.getProfileDirectory();
profileSubdir.append('zotero');
if (profileSubdir.exists()) {
Zotero.debug("Using data directory " + profileSubdir.path);
_zoteroDirectory = profileSubdir;
return profileSubdir.clone();
}
//
// If Standalone and no directory yet, check Firefox directory, or vice versa
//
let prefDir = OS.Path.dirname(
OS.Path.dirname(
OS.Path.dirname(
OS.Constants.Path.profileDir
)
)
);
if(Zotero.isStandalone) {
if (Zotero.isWin) {
prefDir = OS.Path.join(OS.Path.dirname(prefDir), "Mozilla", "Firefox");
}
else if (Zotero.isMac) {
prefDir = OS.Path.join(prefDir, "Firefox");
}
else {
prefDir = OS.Path.join(prefDir, ".mozilla", "firefox");
}
}
else {
if (Zotero.isWin) {
prefDir = OS.Path.join(OS.Path.dirname(prefDir), "Zotero", "Zotero");
}
else if (Zotero.isMac) {
prefDir = OS.Path.join(prefDir, "Zotero");
} else { } else {
if(Zotero.isWin) { prefDir = OS.Path.join(prefDir, ".zotero", "zotero");
prefDir = prefDir.parent;
prefDir.append("Zotero");
prefDir.append("Zotero");
} else if(Zotero.isMac) {
prefDir.append("Zotero");
} else {
prefDir.append(".zotero");
prefDir.append("zotero");
}
} }
}
Zotero.debug("Looking for existing profile in "+prefDir.path); Zotero.debug("Looking for existing profile in " + prefDir);
// get default profile // get default profile
var defProfile; var defProfile;
try { try {
defProfile = getDefaultProfile(prefDir); defProfile = getDefaultProfile(Zotero.File.pathToFile(prefDir));
} catch(e) { } catch(e) {
Zotero.debug("An error occurred locating the Firefox profile; not "+ Zotero.debug("An error occurred locating the Firefox profile; not "+
"attempting to migrate from Zotero for Firefox"); "attempting to migrate from Zotero for Firefox");
Zotero.logError(e); Zotero.logError(e);
} }
if(defProfile) { if(defProfile) {
// get Zotero directory // get Zotero directory
var zoteroDir = defProfile[0].clone(); let profileDir = defProfile[0].path;
zoteroDir.append("zotero"); let zoteroDir = OS.Path.join(profileDir, ZOTERO_CONFIG.ID);
if(zoteroDir.exists()) { // if Zotero directory exists in default profile for alternative app, use it
// if Zotero directory exists in default profile for alternative app, ask if (Zotero.File.pathToFile(zoteroDir).exists()) {
// whether to use let multipleProfiles = defProfile[1];
var e = { name:"ZOTERO_DIR_MAY_EXIST", curDir:file, profile:defProfile[0], dir:zoteroDir, multipleProfiles:defProfile[1] };
throw (e); // copy prefs
let prefsFile = OS.Path.join(profileDir, "prefs.js");
if (Zotero.File.pathToFile(prefsFile).exists()) {
// build sandbox
var sandbox = new Components.utils.Sandbox("http://www.example.com/");
Components.utils.evalInSandbox(
"var prefs = {};"+
"function user_pref(key, val) {"+
"prefs[key] = val;"+
"}"
, sandbox);
// remove comments
var prefsJs = Zotero.File.getContents(prefsFile);
prefsJs = prefsJs.replace(/^#[^\r\n]*$/mg, "");
// evaluate
Components.utils.evalInSandbox(prefsJs, sandbox);
var prefs = sandbox.prefs;
for(var key in prefs) {
if(key.substr(0, ZOTERO_CONFIG.PREF_BRANCH.length) === ZOTERO_CONFIG.PREF_BRANCH
&& key !== "extensions.zotero.firstRun2") {
Zotero.Prefs.set(key.substr(ZOTERO_CONFIG.PREF_BRANCH.length), prefs[key]);
}
}
} }
// also set data dir if no custom data dir is now defined
if(!Zotero.Prefs.get("useDataDir")) {
this.setDataDirectory(zoteroDir);
}
file = Zotero.File.pathToFile(zoteroDir);
} }
} }
Zotero.File.createDirectoryIfMissing(file); Zotero.File.createDirectoryIfMissing(file);
} }
Zotero.debug("Using data directory " + file.path); Zotero.debug("Using data directory " + file.path);
_zoteroDirectory = file; _zoteroDirectory = file;
return file.clone(); return file.clone();
} }
@ -1140,16 +1134,7 @@ Components.utils.import("resource://gre/modules/osfile.jsm");
var fp = Components.classes["@mozilla.org/filepicker;1"] var fp = Components.classes["@mozilla.org/filepicker;1"]
.createInstance(nsIFilePicker); .createInstance(nsIFilePicker);
fp.init(win, Zotero.getString('dataDir.selectDir'), nsIFilePicker.modeGetFolder); fp.init(win, Zotero.getString('dataDir.selectDir'), nsIFilePicker.modeGetFolder);
try { fp.displayDirectory = Zotero.getZoteroDirectory();
fp.displayDirectory = Zotero.getZoteroDirectory();
} catch (e) {
if(e.name == "ZOTERO_DIR_MAY_EXIST") {
fp.displayDirectory = e.dir;
}
else {
throw e;
}
}
fp.appendFilters(nsIFilePicker.filterAll); fp.appendFilters(nsIFilePicker.filterAll);
if (fp.show() == nsIFilePicker.returnOK) { if (fp.show() == nsIFilePicker.returnOK) {
var file = fp.file; var file = fp.file;
@ -1205,10 +1190,7 @@ Components.utils.import("resource://gre/modules/osfile.jsm");
} }
} }
// Set new data directory this.setDataDirectory(file.path);
Zotero.Prefs.set('dataDir', file.persistentDescriptor);
Zotero.Prefs.set('lastDataDir', file.path);
Zotero.Prefs.set('useDataDir', true);
break; break;
} }
@ -1264,10 +1246,8 @@ Components.utils.import("resource://gre/modules/osfile.jsm");
continue; continue;
} }
// Set new data directory this.setDataDirectory(file.path);
Zotero.Prefs.set('dataDir', file.persistentDescriptor);
Zotero.Prefs.set('lastDataDir', file.path);
Zotero.Prefs.set('useDataDir', true);
return file; return file;
} else { } else {
return false; return false;
@ -1305,6 +1285,15 @@ Components.utils.import("resource://gre/modules/osfile.jsm");
} }
this.setDataDirectory = function (path) {
let dir = Zotero.File.pathToFile(path);
Zotero.Prefs.set('dataDir', dir.persistentDescriptor);
Zotero.Prefs.set('lastDataDir', dir.path);
Zotero.Prefs.set('useDataDir', true);
};
/** /**
* Launch a file, the best way we can * Launch a file, the best way we can
*/ */

View File

@ -130,10 +130,6 @@ dataDir.selectedDirEmpty.useNewDir = Use the new directory?
dataDir.moveFilesToNewLocation = Be sure to move files from your existing Zotero data directory to the new location before reopening %1$S. dataDir.moveFilesToNewLocation = Be sure to move files from your existing Zotero data directory to the new location before reopening %1$S.
dataDir.incompatibleDbVersion.title = Incompatible Database Version dataDir.incompatibleDbVersion.title = Incompatible Database Version
dataDir.incompatibleDbVersion.text = The currently selected data directory is not compatible with Zotero Standalone, which can share a database only with Zotero for Firefox 2.1b3 or later.\n\nUpgrade to the latest version of Zotero for Firefox first or select a different data directory for use with Zotero Standalone. dataDir.incompatibleDbVersion.text = The currently selected data directory is not compatible with Zotero Standalone, which can share a database only with Zotero for Firefox 2.1b3 or later.\n\nUpgrade to the latest version of Zotero for Firefox first or select a different data directory for use with Zotero Standalone.
dataDir.standaloneMigration.title = Existing Zotero Library Found
dataDir.standaloneMigration.description = This appears to be your first time using %1$S. Would you like %1$S to import settings from %2$S and use your existing data directory?
dataDir.standaloneMigration.multipleProfiles = %1$S will share its data directory with the most recently used profile.
dataDir.standaloneMigration.selectCustom = Custom Data Directory…
app.standalone = Zotero Standalone app.standalone = Zotero Standalone
app.firefox = Zotero for Firefox app.firefox = Zotero for Firefox

View File

@ -1,5 +1,6 @@
var ZOTERO_CONFIG = { var ZOTERO_CONFIG = {
GUID: 'zotero@chnm.gmu.edu', GUID: 'zotero@chnm.gmu.edu',
ID: 'zotero', // used for db filename, etc.
CLIENT_NAME: 'Zotero', CLIENT_NAME: 'Zotero',
DOMAIN_NAME: 'zotero.org', DOMAIN_NAME: 'zotero.org',
REPOSITORY_URL: 'https://repo.zotero.org/repo/', REPOSITORY_URL: 'https://repo.zotero.org/repo/',