Fix relative path support to sync properly
Dual boot and VM setups worked, but only absolute paths were synced, because syncing uses attachmentPath, which was resolving relative paths itself (#51). attachmentPath now returns what's in the database (as it did originally), and getFile() does the resolving instead. This means that anything relying on attachmentPath directly needs to be aware that it might get a placeholder-prefixed relative path.
This commit is contained in:
parent
c128c53704
commit
41c9a4a433
|
@ -364,22 +364,30 @@ Zotero_Preferences.Attachment_Base_Directory = {
|
|||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
for (let i=0; i<allAttachments.length; i++) {
|
||||
let attachmentID = allAttachments[i];
|
||||
let relPath = false
|
||||
|
||||
try {
|
||||
let attachment = Zotero.Items.get(attachmentID);
|
||||
attachmentFile.persistentDescriptor = attachment.attachmentPath;
|
||||
// This will return FALSE for relative paths if base directory
|
||||
// isn't currently set
|
||||
attachmentFile = attachment.getFile(false, true);
|
||||
// Get existing relative path
|
||||
let path = attachment.attachmentPath;
|
||||
if (path.indexOf(Zotero.Attachments.BASE_PATH_PLACEHOLDER) == 0) {
|
||||
relPath = path.substr(Zotero.Attachments.BASE_PATH_PLACEHOLDER.length);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
// Don't deal with bad attachment paths. Just skip them.
|
||||
Zotero.debug(e, 2);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If a file with the same relative path exists within the new base directory,
|
||||
// don't touch the attachment, since it will continue to work
|
||||
let isExistingRelativeAttachment = oldRelativeAttachmentIDs.indexOf(attachmentID) != -1;
|
||||
if (isExistingRelativeAttachment && oldBasePathFile) {
|
||||
let relFile = attachmentFile.clone();
|
||||
let relPath = attachmentFile.getRelativeDescriptor(oldBasePathFile);
|
||||
if (relPath) {
|
||||
let relFile = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
relFile.setRelativeDescriptor(newBasePathFile, relPath);
|
||||
if (relFile.exists()) {
|
||||
numNewAttachments++;
|
||||
|
@ -390,14 +398,14 @@ Zotero_Preferences.Attachment_Base_Directory = {
|
|||
// Files within the new base directory need to be updated to use
|
||||
// relative paths (or, if the new base directory is an ancestor or
|
||||
// descendant of the old one, new relative paths)
|
||||
if (Zotero.File.directoryContains(newBasePathFile, attachmentFile)) {
|
||||
newAttachmentPaths[attachmentID] = isExistingRelativeAttachment
|
||||
if (attachmentFile && Zotero.File.directoryContains(newBasePathFile, attachmentFile)) {
|
||||
newAttachmentPaths[attachmentID] = relPath
|
||||
? attachmentFile.persistentDescriptor : null;
|
||||
numNewAttachments++;
|
||||
}
|
||||
// Existing relative attachments not within the new base directory
|
||||
// will be converted to absolute paths
|
||||
else if (isExistingRelativeAttachment && oldBasePathFile) {
|
||||
else if (relPath && oldBasePathFile) {
|
||||
newAttachmentPaths[attachmentID] = attachmentFile.persistentDescriptor;
|
||||
numOldAttachments++;
|
||||
}
|
||||
|
@ -464,7 +472,9 @@ Zotero_Preferences.Attachment_Base_Directory = {
|
|||
let attachment = Zotero.Items.get(id);
|
||||
if (newAttachmentPaths[id]) {
|
||||
attachment.attachmentPath = newAttachmentPaths[id];
|
||||
attachment.save();
|
||||
attachment.save({
|
||||
skipDateModifiedUpdate: true
|
||||
});
|
||||
}
|
||||
else {
|
||||
attachment.updateAttachmentPath();
|
||||
|
|
|
@ -1013,6 +1013,104 @@ Zotero.Attachments = new function(){
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* If file is within the attachment base directory, return a relative
|
||||
* path prefixed by BASE_PATH_PLACEHOLDER. Otherwise, return unchanged.
|
||||
*/
|
||||
this.getBaseDirectoryRelativePath = function (path) {
|
||||
if (!path || path.indexOf(this.BASE_PATH_PLACEHOLDER) == 0) {
|
||||
return path;
|
||||
}
|
||||
|
||||
var basePath = Zotero.Prefs.get('baseAttachmentPath');
|
||||
if (!basePath) {
|
||||
return path;
|
||||
}
|
||||
|
||||
// Get nsIFile for base directory
|
||||
var baseDir = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
try {
|
||||
baseDir.persistentDescriptor = basePath;
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e, 1);
|
||||
Components.utils.reportError(e);
|
||||
return path;
|
||||
}
|
||||
|
||||
// Get nsIFile for file
|
||||
var attachmentFile = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
try {
|
||||
attachmentFile.persistentDescriptor = path;
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e, 1);
|
||||
Components.utils.reportError(e);
|
||||
return path;
|
||||
}
|
||||
|
||||
if (Zotero.File.directoryContains(baseDir, attachmentFile)) {
|
||||
path = this.BASE_PATH_PLACEHOLDER
|
||||
+ attachmentFile.getRelativeDescriptor(baseDir);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a file from this path, if we can
|
||||
*
|
||||
* @param {String} path Absolute path or relative path prefixed
|
||||
* by BASE_PATH_PLACEHOLDER
|
||||
* @param {Boolean} asFile Return nsIFile instead of path
|
||||
* @return {String|nsIFile|FALSE} Persistent descriptor string, file,
|
||||
* of FALSE if no path
|
||||
*/
|
||||
this.resolveRelativePath = function (path) {
|
||||
if (path.indexOf(Zotero.Attachments.BASE_PATH_PLACEHOLDER) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var basePath = Zotero.Prefs.get('baseAttachmentPath');
|
||||
if (!basePath) {
|
||||
Zotero.debug("No base attachment path set -- can't resolve '" + path + "'", 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get file from base directory
|
||||
var baseDir = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
try {
|
||||
baseDir.persistentDescriptor = basePath;
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e, 1);
|
||||
Components.utils.reportError(e);
|
||||
Zotero.debug("Invalid base attachment path -- can't resolve'" + row.path + "'", 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get file from relative path
|
||||
var relativePath = path.substr(
|
||||
Zotero.Attachments.BASE_PATH_PLACEHOLDER.length
|
||||
);
|
||||
var file = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
try {
|
||||
file.setRelativeDescriptor(baseDir, relativePath);
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug("Invalid relative descriptor '" + relativePath + "'", 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of files in the attachment directory
|
||||
*
|
||||
|
|
|
@ -76,7 +76,6 @@ Zotero.Item.prototype._init = function () {
|
|||
this._changedSource = false;
|
||||
this._changedAttachmentData = false;
|
||||
|
||||
this._skipModTimeUpdate = false;
|
||||
this._previousData = {};
|
||||
|
||||
this._bestAttachmentState = null;
|
||||
|
@ -1251,7 +1250,11 @@ Zotero.Item.prototype.removeRelatedItem = function (itemID) {
|
|||
*
|
||||
* Returns true on item update or itemID of new item
|
||||
*/
|
||||
Zotero.Item.prototype.save = function() {
|
||||
Zotero.Item.prototype.save = function(options) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
Zotero.Items.editCheck(this);
|
||||
|
||||
if (!this.hasChanged()) {
|
||||
|
@ -1527,37 +1530,16 @@ Zotero.Item.prototype.save = function() {
|
|||
var path = this.attachmentPath;
|
||||
var syncState = this.attachmentSyncState;
|
||||
|
||||
// Save attachment within attachment base directory as relative path
|
||||
if (this.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE && path) {
|
||||
let basePath = Zotero.Prefs.get('baseAttachmentPath');
|
||||
if (basePath != '' && Zotero.Prefs.get('saveRelativeAttachmentPath')) {
|
||||
let baseDir = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
try {
|
||||
baseDir.persistentDescriptor = basePath;
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e, 1);
|
||||
Components.utils.reportError(e);
|
||||
baseDir = null;
|
||||
}
|
||||
|
||||
if (baseDir) {
|
||||
let attachmentFile = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
try {
|
||||
attachmentFile.persistentDescriptor = path;
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e, 1);
|
||||
Components.utils.reportError(e);
|
||||
attachmentFile = null;
|
||||
}
|
||||
|
||||
if (attachmentFile && Zotero.File.directoryContains(baseDir, attachmentFile)) {
|
||||
path = Zotero.Attachments.BASE_PATH_PLACEHOLDER
|
||||
+ attachmentFile.getRelativeDescriptor(baseDir);
|
||||
}
|
||||
if (this.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE) {
|
||||
// Save attachment within attachment base directory as relative path
|
||||
if (Zotero.Prefs.get('saveRelativeAttachmentPath')) {
|
||||
path = Zotero.Attachments.getBaseDirectoryRelativePath(path);
|
||||
}
|
||||
// If possible, convert relative path to absolute
|
||||
else {
|
||||
let file = Zotero.Attachments.resolveRelativePath(path);
|
||||
if (file) {
|
||||
path = file.persistentDescriptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1669,8 +1651,11 @@ Zotero.Item.prototype.save = function() {
|
|||
sql += field + '=?, ';
|
||||
sqlValues.push(this.getField(field));
|
||||
}
|
||||
else if ((field == 'dateModified' || field == 'clientDateModified')
|
||||
&& !this._skipModTimeUpdate) {
|
||||
else if (field == 'dateModified' && !options.skipDateModifiedUpdate) {
|
||||
sql += field + '=?, ';
|
||||
sqlValues.push(Zotero.DB.transactionDateTime);
|
||||
}
|
||||
else if (field == 'clientDateModified' && !options.skipClientDateModifiedUpdate) {
|
||||
sql += field + '=?, ';
|
||||
sqlValues.push(Zotero.DB.transactionDateTime);
|
||||
}
|
||||
|
@ -1962,37 +1947,16 @@ Zotero.Item.prototype.save = function() {
|
|||
var path = this.attachmentPath;
|
||||
var syncState = this.attachmentSyncState;
|
||||
|
||||
// Save attachment within attachment base directory as relative path
|
||||
if (this.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE && path) {
|
||||
let basePath = Zotero.Prefs.get('baseAttachmentPath');
|
||||
if (basePath != '' && Zotero.Prefs.get('saveRelativeAttachmentPath')) {
|
||||
let baseDir = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
try {
|
||||
baseDir.persistentDescriptor = basePath;
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e, 1);
|
||||
Components.utils.reportError(e);
|
||||
baseDir = null;
|
||||
}
|
||||
|
||||
if (baseDir) {
|
||||
let attachmentFile = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
try {
|
||||
attachmentFile.persistentDescriptor = path;
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e, 1);
|
||||
Components.utils.reportError(e);
|
||||
attachmentFile = null;
|
||||
}
|
||||
|
||||
if (attachmentFile && Zotero.File.directoryContains(baseDir, attachmentFile)) {
|
||||
path = Zotero.Attachments.BASE_PATH_PLACEHOLDER
|
||||
+ attachmentFile.getRelativeDescriptor(baseDir);
|
||||
}
|
||||
if (this.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE) {
|
||||
// Save attachment within attachment base directory as relative path
|
||||
if (Zotero.Prefs.get('saveRelativeAttachmentPath')) {
|
||||
path = Zotero.Attachments.getBaseDirectoryRelativePath(path);
|
||||
}
|
||||
// If possible, convert relative path to absolute
|
||||
else {
|
||||
let file = Zotero.Attachments.resolveRelativePath(path);
|
||||
if (file) {
|
||||
path = file.persistentDescriptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2864,6 +2828,7 @@ Zotero.Item.prototype.getFile = function(row, skipExistsCheck) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Imported file with relative path
|
||||
if (row.linkMode == Zotero.Attachments.LINK_MODE_IMPORTED_URL ||
|
||||
row.linkMode == Zotero.Attachments.LINK_MODE_IMPORTED_FILE) {
|
||||
try {
|
||||
|
@ -2913,6 +2878,15 @@ Zotero.Item.prototype.getFile = function(row, skipExistsCheck) {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Linked file with relative path
|
||||
else if (row.linkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE &&
|
||||
row.path.indexOf(Zotero.Attachments.BASE_PATH_PLACEHOLDER) == 0) {
|
||||
var file = Zotero.Attachments.resolveRelativePath(row.path);
|
||||
if (!file) {
|
||||
updateAttachmentStates(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
var file = Components.classes["@mozilla.org/file/local;1"].
|
||||
createInstance(Components.interfaces.nsILocalFile);
|
||||
|
@ -3073,11 +3047,10 @@ Zotero.Item.prototype.relinkAttachmentFile = function(file, skipItemUpdate) {
|
|||
var path = Zotero.Attachments.getPath(file, linkMode);
|
||||
this.attachmentPath = path;
|
||||
|
||||
if (skipItemUpdate) {
|
||||
this._skipModTimeUpdate = true;
|
||||
}
|
||||
this.save();
|
||||
this._skipModTimeUpdate = false;
|
||||
this.save({
|
||||
skipDateModifiedUpdate: true,
|
||||
skipClientDateModifiedUpdate: skipItemUpdate
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -3274,58 +3247,20 @@ Zotero.Item.prototype.__defineGetter__('attachmentPath', function () {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
var pathIsRelative = false;
|
||||
|
||||
if (this._attachmentPath !== null) {
|
||||
pathIsRelative = this._attachmentPath.indexOf(Zotero.Attachments.BASE_PATH_PLACEHOLDER) == 0
|
||||
&& this.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE;
|
||||
if (!pathIsRelative) {
|
||||
return this._attachmentPath;
|
||||
}
|
||||
}
|
||||
else if (!this.id) {
|
||||
return this._attachmentPath;
|
||||
}
|
||||
|
||||
if (!this.id) {
|
||||
return '';
|
||||
}
|
||||
else {
|
||||
var sql = "SELECT path FROM itemAttachments WHERE itemID=?";
|
||||
var path = Zotero.DB.valueQuery(sql, this.id);
|
||||
if (!path) {
|
||||
this._attachmentPath = '';
|
||||
return this._attachmentPath;
|
||||
}
|
||||
|
||||
this._attachmentPath = path;
|
||||
|
||||
pathIsRelative = path.indexOf(Zotero.Attachments.BASE_PATH_PLACEHOLDER) == 0
|
||||
&& this.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE;
|
||||
}
|
||||
|
||||
if (pathIsRelative) {
|
||||
var basePath = Zotero.Prefs.get('baseAttachmentPath');
|
||||
// If the base path has been cleared, don't try to recreate the full attachment path
|
||||
if (basePath == '') {
|
||||
return '';
|
||||
}
|
||||
var baseDir = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
try {
|
||||
baseDir.persistentDescriptor = basePath;
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e, 1);
|
||||
Components.utils.reportError(e);
|
||||
return '';
|
||||
}
|
||||
|
||||
var relativePath = this._attachmentPath.substr(
|
||||
Zotero.Attachments.BASE_PATH_PLACEHOLDER.length
|
||||
);
|
||||
var attachmentFile = Components.classes["@mozilla.org/file/local;1"]
|
||||
.createInstance(Components.interfaces.nsILocalFile);
|
||||
attachmentFile.setRelativeDescriptor(baseDir,relativePath);
|
||||
return attachmentFile.persistentDescriptor;
|
||||
var sql = "SELECT path FROM itemAttachments WHERE itemID=?";
|
||||
var path = Zotero.DB.valueQuery(sql, this.id);
|
||||
if (!path) {
|
||||
path = '';
|
||||
}
|
||||
|
||||
this._attachmentPath = path;
|
||||
return path;
|
||||
});
|
||||
|
||||
|
@ -3366,7 +3301,9 @@ Zotero.Item.prototype.updateAttachmentPath = function () {
|
|||
this._changedAttachmentData = {};
|
||||
}
|
||||
this._changedAttachmentData.path = true;
|
||||
this.save();
|
||||
this.save({
|
||||
skipDateModifiedUpdate: true
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -4019,7 +4019,9 @@ Zotero.Sync.Server.Data = new function() {
|
|||
var msg = Zotero.getString('sync.error.invalidCharsFilename', filename);
|
||||
var e = new Zotero.Error(msg, 0, { dialogButtonText: null });
|
||||
throw (e);
|
||||
|
||||
}
|
||||
if (item.attachment.linkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE) {
|
||||
path = Zotero.Attachments.getBaseDirectoryRelativePath(path);
|
||||
}
|
||||
var pathElem = doc.createElement('path');
|
||||
pathElem.appendChild(doc.createTextNode(path));
|
||||
|
|
|
@ -3444,8 +3444,9 @@ var ZoteroPane = new function()
|
|||
}
|
||||
|
||||
var file = item.getFile();
|
||||
Zotero.debug("Opening " + file.path);
|
||||
if (file) {
|
||||
Zotero.debug("Opening " + file.path);
|
||||
|
||||
if(forceExternalViewer !== undefined) {
|
||||
var externalViewer = forceExternalViewer;
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue
Block a user