commit cbf4876173974398ee921a4739210e4159d092ab
parent 06867d886ee65ae47a8b8714de3878a580286ff2
Author: Dan Stillman <dstillman@zotero.org>
Date: Fri, 7 Aug 2015 15:36:46 -0400
Fix attachment renaming
Fixes #822
Diffstat:
6 files changed, 96 insertions(+), 34 deletions(-)
diff --git a/chrome/content/zotero/bindings/attachmentbox.xml b/chrome/content/zotero/bindings/attachmentbox.xml
@@ -135,7 +135,35 @@
</property>
- <!-- Private properties -->
+ <!-- Methods -->
+
+ <constructor>
+ <![CDATA[
+ this._notifierID = Zotero.Notifier.registerObserver(this, ['item'], 'attachmentbox');
+ ]]>
+ </constructor>
+
+ <destructor>
+ <![CDATA[
+ Zotero.Notifier.unregisterObserver(this._notifierID);
+ ]]>
+ </destructor>
+
+ <method name="notify">
+ <parameter name="event"/>
+ <parameter name="type"/>
+ <parameter name="ids"/>
+ <body><![CDATA[
+ if (event != 'modify' || !this.item || !this.item.id) return;
+ for (let i = 0; i < ids.length; i++) {
+ if (ids[i] != this.item.id) {
+ continue;
+ }
+ this.refresh();
+ break;
+ }
+ ]]></body>
+ </method>
<method name="refresh">
<body><![CDATA[
diff --git a/chrome/content/zotero/xpcom/data/item.js b/chrome/content/zotero/xpcom/data/item.js
@@ -2434,7 +2434,7 @@ Zotero.Item.prototype.fileExistsCached = function () {
* false Attachment file not found
*/
Zotero.Item.prototype.renameAttachmentFile = Zotero.Promise.coroutine(function* (newName, overwrite) {
- var origPath = yield this.getFilePath();
+ var origPath = yield this.getFilePathAsync();
if (!origPath) {
Zotero.debug("Attachment file not found in renameAttachmentFile()", 2);
return false;
@@ -2442,20 +2442,19 @@ Zotero.Item.prototype.renameAttachmentFile = Zotero.Promise.coroutine(function*
try {
var origName = OS.Path.basename(origPath);
- var origModDate = yield OS.File.stat(origPath).lastModificationDate;
+ var origModDate = (yield OS.File.stat(origPath)).lastModificationDate;
newName = Zotero.File.getValidFileName(newName);
- var destPath = OS.Path.join(OS.Path.dirname(origPath), newName);
- var destName = OS.Path.basename(destPath);
-
// Ignore if no change
- //
- // Note: Just comparing origName to newName isn't reliable
- if (origFileName === destName) {
+ if (origName === newName) {
+ Zotero.debug("Filename has not changed");
return true;
}
+ var destPath = OS.Path.join(OS.Path.dirname(origPath), newName);
+ var destName = OS.Path.basename(destPath);
+
// Update mod time and clear hash so the file syncs
// TODO: use an integer counter instead of mod time for change detection
// Update mod time first, because it may fail for read-only files on Windows
@@ -2475,8 +2474,8 @@ Zotero.Item.prototype.renameAttachmentFile = Zotero.Promise.coroutine(function*
yield this.relinkAttachmentFile(destPath);
yield Zotero.DB.executeTransaction(function* () {
- Zotero.Sync.Storage.setSyncedHash(this.id, null, false);
- Zotero.Sync.Storage.setSyncState(this.id, Zotero.Sync.Storage.SYNC_STATE_TO_UPLOAD);
+ yield Zotero.Sync.Storage.setSyncedHash(this.id, null, false);
+ yield Zotero.Sync.Storage.setSyncState(this.id, Zotero.Sync.Storage.SYNC_STATE_TO_UPLOAD);
}.bind(this));
return true;
@@ -2529,7 +2528,7 @@ Zotero.Item.prototype.relinkAttachmentFile = Zotero.Promise.coroutine(function*
try {
// If selected file isn't in the attachment's storage directory,
// copy it in and use that one instead
- var storageDir = Zotero.Attachments.getStorageDirectory(this.id).path;
+ var storageDir = Zotero.Attachments.getStorageDirectory(this).path;
if (this.isImportedAttachment() && OS.Path.dirname(path) != storageDir) {
// If file with same name already exists in the storage directory,
// move it out of the way
@@ -2560,7 +2559,7 @@ Zotero.Item.prototype.relinkAttachmentFile = Zotero.Promise.coroutine(function*
this.attachmentPath = Zotero.Attachments.getPath(Zotero.File.pathToFile(newPath), linkMode);
- yield this.save({
+ yield this.saveTx({
skipDateModifiedUpdate: true,
skipClientDateModifiedUpdate: skipItemUpdate
});
diff --git a/chrome/content/zotero/xpcom/storage.js b/chrome/content/zotero/xpcom/storage.js
@@ -499,7 +499,7 @@ Zotero.Sync.Storage = new function () {
*/
this.getSyncState = function (itemID) {
var sql = "SELECT syncState FROM itemAttachments WHERE itemID=?";
- return Zotero.DB.valueQuery(sql, itemID);
+ return Zotero.DB.valueQueryAsync(sql, itemID);
}
@@ -507,7 +507,7 @@ Zotero.Sync.Storage = new function () {
* @param {Integer} itemID
* @param {Integer} syncState Constant from Zotero.Sync.Storage
*/
- this.setSyncState = function (itemID, syncState) {
+ this.setSyncState = Zotero.Promise.method(function (itemID, syncState) {
switch (syncState) {
case this.SYNC_STATE_TO_UPLOAD:
case this.SYNC_STATE_TO_DOWNLOAD:
@@ -517,13 +517,12 @@ Zotero.Sync.Storage = new function () {
break;
default:
- throw "Invalid sync state '" + syncState
- + "' in Zotero.Sync.Storage.setSyncState()"
+ throw new Error("Invalid sync state '" + syncState);
}
var sql = "UPDATE itemAttachments SET syncState=? WHERE itemID=?";
- return Zotero.DB.valueQuery(sql, [syncState, itemID]);
- }
+ return Zotero.DB.valueQueryAsync(sql, [syncState, itemID]);
+ });
/**
@@ -572,18 +571,18 @@ Zotero.Sync.Storage = new function () {
/**
- * @param {Integer} itemID
- * @return {String|NULL} File hash, or NULL if never synced
+ * @param {Integer} itemID
+ * @return {Promise<String|null|false>} - File hash, null if never synced, if false if
+ * file doesn't exist
*/
- this.getSyncedHash = function (itemID) {
+ this.getSyncedHash = Zotero.Promise.coroutine(function* (itemID) {
var sql = "SELECT storageHash FROM itemAttachments WHERE itemID=?";
- var hash = Zotero.DB.valueQuery(sql, itemID);
+ var hash = yield Zotero.DB.valueQueryAsync(sql, itemID);
if (hash === false) {
- throw "Item " + itemID + " not found in "
- + "Zotero.Sync.Storage.getSyncedHash()";
+ throw new Error("Item " + itemID + " not found");
}
return hash;
- }
+ })
/**
@@ -592,24 +591,22 @@ Zotero.Sync.Storage = new function () {
* @param {Boolean} [updateItem=FALSE] Update dateModified field of
* attachment item
*/
- this.setSyncedHash = function (itemID, hash, updateItem) {
+ this.setSyncedHash = Zotero.Promise.coroutine(function* (itemID, hash, updateItem) {
if (hash !== null && hash.length != 32) {
throw ("Invalid file hash '" + hash + "' in Zotero.Storage.setSyncedHash()");
}
- Zotero.DB.beginTransaction();
+ Zotero.DB.requireTransaction();
var sql = "UPDATE itemAttachments SET storageHash=? WHERE itemID=?";
- Zotero.DB.valueQuery(sql, [hash, itemID]);
+ yield Zotero.DB.queryAsync(sql, [hash, itemID]);
if (updateItem) {
// Update item date modified so the new mod time will be synced
var sql = "UPDATE items SET clientDateModified=? WHERE itemID=?";
- Zotero.DB.query(sql, [Zotero.DB.transactionDateTime, itemID]);
+ yield Zotero.DB.queryAsync(sql, [Zotero.DB.transactionDateTime, itemID]);
}
-
- Zotero.DB.commitTransaction();
- }
+ });
/**
diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js
@@ -4104,7 +4104,7 @@ var ZoteroPane = new function()
newName = newName + ext;
}
- var renamed = item.renameAttachmentFile(newName);
+ var renamed = yield item.renameAttachmentFile(newName);
if (renamed !== true) {
Zotero.debug("Could not rename file (" + renamed + ")");
continue;
diff --git a/test/tests/itemPaneTest.js b/test/tests/itemPaneTest.js
@@ -29,6 +29,22 @@ describe("Item pane", function () {
})
})
+ describe("Attachment pane", function () {
+ it("should refresh on file rename", function* () {
+ var file = getTestDataDirectory();
+ file.append('test.png');
+ var item = yield Zotero.Attachments.importFromFile({
+ file: file
+ });
+ var newName = 'test2.png';
+ yield item.renameAttachmentFile(newName);
+
+ var itemBox = doc.getElementById('zotero-attachment-box');
+ var label = itemBox._id('fileName');
+ assert.equal(label.value, newName);
+ })
+ })
+
describe("Note pane", function () {
it("should refresh on note update", function* () {
var item = new Zotero.Item('note');
diff --git a/test/tests/itemTest.js b/test/tests/itemTest.js
@@ -539,6 +539,28 @@ describe("Zotero.Item", function () {
});
})
+ describe("#renameAttachmentFile()", function () {
+ it("should rename an attached file", function* () {
+ var file = getTestDataDirectory();
+ file.append('test.png');
+ var item = yield Zotero.Attachments.importFromFile({
+ file: file
+ });
+ var newName = 'test2.png';
+ yield item.renameAttachmentFile(newName);
+ assert.equal(item.attachmentFilename, newName);
+ var path = yield item.getFilePathAsync();
+ assert.equal(OS.Path.basename(path), newName)
+ yield OS.File.exists(path);
+
+ assert.equal(
+ (yield Zotero.Sync.Storage.getSyncState(item.id)),
+ Zotero.Sync.Storage.SYNC_STATE_TO_UPLOAD
+ );
+ assert.isNull(yield Zotero.Sync.Storage.getSyncedHash(item.id));
+ })
+ })
+
describe("#setTags", function () {
it("should save an array of tags in API JSON format", function* () {
var tags = [