- Address "Delete reconciliation unimplemented for collections" message

- If collection items were added/removed on both sides, items from both sides were not always added
- Fix a couple other related glitches which may or may not have shown up before the above issues were fixed
This commit is contained in:
Dan Stillman 2009-10-12 08:14:11 +00:00
parent d8bdb6c11d
commit 67831bcb79
3 changed files with 37 additions and 37 deletions

View File

@ -2472,6 +2472,13 @@ Zotero.Schema = new function(){
Zotero.DB.query("UPDATE version SET schema='storage_webdav' WHERE schema='storage'");
}
if (i==64) {
Zotero.DB.query("ALTER TABLE syncDeleteLog RENAME TO syncDeleteLogOld");
Zotero.DB.query("CREATE TABLE syncDeleteLog (\n syncObjectTypeID INT NOT NULL,\n libraryID INT NOT NULL,\n key TEXT NOT NULL,\n timestamp INT NOT NULL,\n UNIQUE (syncObjectTypeID, libraryID, key),\n FOREIGN KEY (syncObjectTypeID) REFERENCES syncObjectTypes(syncObjectTypeID)\n)");
Zotero.DB.query("INSERT INTO syncDeleteLog SELECT * FROM syncDeleteLogOld");
Zotero.DB.query("DROP TABLE syncDeleteLogOld");
}
Zotero.wait();
}

View File

@ -374,7 +374,7 @@ Zotero.Sync.EventListener = new function () {
Zotero.DB.beginTransaction();
if (event == 'delete') {
var sql = "INSERT INTO syncDeleteLog VALUES (?, ?, ?, ?)";
var sql = "REPLACE INTO syncDeleteLog VALUES (?, ?, ?, ?)";
var syncStatement = Zotero.DB.getStatement(sql);
if (isItem && Zotero.Sync.Storage.active) {
@ -2337,6 +2337,7 @@ Zotero.Sync.Server.Data = new function() {
Zotero.debug("Processing remote " + type + " " + libraryID + "/" + key, 4);
var isNewObject;
var localDelete = false;
var skipCR = false;
// Get local object with same library and key
var obj = Zotero[Types].getByLibraryAndKey(libraryID, key);
@ -2391,8 +2392,6 @@ Zotero.Sync.Server.Data = new function() {
}
// Mark other types for conflict resolution
else {
var skipCR = false;
// Skip item if dateModified is the only modified
// field (and no linked creators changed)
switch (type) {
@ -2455,8 +2454,7 @@ Zotero.Sync.Server.Data = new function() {
break;
case 'collection':
// TODO: move childItemStore to syncSession
var changed = _mergeCollection(obj, remoteObj, childItemStore, syncSession);
var changed = _mergeCollection(obj, remoteObj, syncSession);
if (!changed) {
syncSession.removeFromUpdated(obj);
continue;
@ -2476,7 +2474,6 @@ Zotero.Sync.Server.Data = new function() {
// TODO: order reconcile by parent/child?
if (!skipCR) {
Zotero.debug("ADDING " + type + " TO CR");
toReconcile.push([
obj,
remoteObj
@ -2512,15 +2509,16 @@ Zotero.Sync.Server.Data = new function() {
localDelete = true;
break;
// Auto-restore locally deleted tags that have
// changed remotely
// Auto-restore locally deleted tags and collections that
// have changed remotely
case 'tag':
case 'collection':
syncSession.removeFromDeleted(fakeObj);
var msg = _generateAutoChangeMessage(
type, null, xmlNode.@name.toString()
);
alert(msg);
continue;
break;
default:
alert('Delete reconciliation unimplemented for ' + types);
@ -2539,7 +2537,11 @@ Zotero.Sync.Server.Data = new function() {
}
// Create or overwrite locally
obj = Zotero.Sync.Server.Data['xmlTo' + Type](xmlNode, obj);
//
// If we skipped CR above, we already have an object to use
if (!skipCR) {
obj = Zotero.Sync.Server.Data['xmlTo' + Type](xmlNode, obj);
}
if (isNewObject && type == 'tag') {
// If a local tag matches the name of a different remote tag,
@ -2653,6 +2655,7 @@ Zotero.Sync.Server.Data = new function() {
break;
case 'tag':
case 'collection':
var msg = _generateAutoChangeMessage(
type, obj.name, null
);
@ -2961,7 +2964,7 @@ Zotero.Sync.Server.Data = new function() {
}
function _mergeCollection(localObj, remoteObj, childItemStore, syncSession) {
function _mergeCollection(localObj, remoteObj, syncSession) {
var diff = localObj.diff(remoteObj, false, true);
if (!diff) {
return false;
@ -2972,20 +2975,18 @@ Zotero.Sync.Server.Data = new function() {
// Local is newer
if (diff[0].primary.dateModified > diff[1].primary.dateModified) {
Zotero.debug("Local is newer");
var remoteIsTarget = false;
var targetObj = localObj;
var targetDiff = diff[0];
var otherDiff = diff[1];
}
// Remote is newer
else {
Zotero.debug("Remote is newer");
var remoteIsTarget = true;
var targetObj = remoteObj;
var targetDiff = diff[1];
var otherDiff = diff[0];
}
if (targetDiff.fields.name) {
if (diff[0].fields.name) {
if (!syncSession.suppressWarnings) {
var msg = _generateAutoChangeMessage(
'collection', diff[0].fields.name, diff[1].fields.name, remoteIsTarget
@ -2997,27 +2998,26 @@ Zotero.Sync.Server.Data = new function() {
// Check for child collections in the other object
// that aren't in the target one
if (otherDiff.childCollections.length) {
if (diff[1].childCollections.length) {
// TODO: log
// TODO: add
throw ("Collection hierarchy conflict resolution is unimplemented");
}
// Add items in other object to target one
if (otherDiff.childItems.length) {
var childItems = targetObj.getChildItems(true);
// Add items to local object, which is what's saved
if (diff[1].childItems.length) {
var childItems = localObj.getChildItems(true);
if (childItems) {
targetObj.childItems = childItems.concat(otherDiff.childItems);
localObj.childItems = childItems.concat(diff[1].childItems);
}
else {
targetObj.childItems = otherDiff.childItems;
localObj.childItems = diff[1].childItems;
}
if (!syncSession.suppressWarnings) {
var msg = _generateCollectionItemMergeMessage(
targetObj.name,
otherDiff.childItems,
remoteIsTarget
diff[0].childItems.concat(diff[1].childItems)
);
// TODO: log rather than alert
alert(msg);
@ -3123,25 +3123,18 @@ Zotero.Sync.Server.Data = new function() {
/**
* @param {String} collectionName
* @param {Integer[]} addedItemIDs
* @param {Boolean} remoteIsTarget
*/
function _generateCollectionItemMergeMessage(collectionName, addedItemIDs, remoteIsTarget) {
function _generateCollectionItemMergeMessage(collectionName, addedItemIDs) {
// TODO: localize
var introMsg = "Items in the collection '" + collectionName + "' have been "
+ "added and/or removed in multiple locations."
introMsg += " ";
if (remoteIsTarget) {
introMsg += "The following items have been added to the remote collection:";
}
else {
introMsg += "The following items have been added to the local collection:";
}
introMsg += " The following items have been added to the collection:";
var itemText = [];
for each(var id in addedItemIDs) {
var item = Zotero.Items.get(id);
var title = item.getField('title');
var text = " - " + title;
var text = " \u2022 " + title;
var firstCreator = item.getField('firstCreator');
if (firstCreator) {
text += " (" + firstCreator + ")";

View File

@ -1,4 +1,4 @@
-- 63
-- 64
-- This file creates tables containing user-specific data for new users --
-- any changes made here must be mirrored in transition steps in schema.js::_migrateSchema()
@ -258,10 +258,10 @@ CREATE INDEX fulltextItemWords_itemID ON fulltextItemWords(itemID);
CREATE TABLE syncDeleteLog (
syncObjectTypeID INT NOT NULL,
libraryID INT,
libraryID INT NOT NULL,
key TEXT NOT NULL,
timestamp INT NOT NULL,
UNIQUE (libraryID, key),
UNIQUE (syncObjectTypeID, libraryID, key),
FOREIGN KEY (syncObjectTypeID) REFERENCES syncObjectTypes(syncObjectTypeID)
);
CREATE INDEX syncDeleteLog_timestamp ON syncDeleteLog(timestamp);