Fix sync error on collection/search conflict

> Invalid data error for collection [key] in [library]: Unknown
> collection property 'dateAdded'"

Regression from 4b60c6ca27, probably
This commit is contained in:
Dan Stillman 2020-04-23 03:51:47 -04:00
parent f531ac7b60
commit 2c046a227b
2 changed files with 48 additions and 4 deletions

View file

@ -956,6 +956,7 @@ Zotero.Sync.Data.Local = {
);
// Transfer properties that aren't in the changeset
['version', 'dateAdded', 'dateModified'].forEach(x => {
if (jsonData[x] === undefined) return;
if (jsonDataLocal[x] !== jsonData[x]) {
Zotero.debug(`Applying remote '${x}' value`);
}
@ -1499,6 +1500,7 @@ Zotero.Sync.Data.Local = {
Zotero.debug("CHANGESET2");
Zotero.debug(changeset2);
const isAutoMergeType = objectType != 'item';
var conflicts = [];
var matchedLocalChanges = new Set();
@ -1602,7 +1604,7 @@ Zotero.Sync.Data.Local = {
// Automatically apply remote changes if both items are in trash and for non-items,
// even if in conflict
if ((objectType == 'item' && currentJSON.deleted && newJSON.deleted)
|| objectType != 'item') {
|| isAutoMergeType) {
continue;
}
@ -1613,12 +1615,23 @@ Zotero.Sync.Data.Local = {
}
}
// If there were local changes that weren't made remotely as well, the object needs to be
// kept as unsynced
var localChanged = changeset1.length > matchedLocalChanges.size;
// If we're applying remote changes automatically, only consider the local object as changed
// if fields were changed that weren't changed remotely
if (isAutoMergeType && localChanged) {
let remoteFields = new Set(changeset2.map(x => x.field));
if (changeset1.every(x => remoteFields.has(x.field))) {
localChanged = false;
}
}
return {
changes: changeset2,
conflicts,
// If there were local changes that weren't made remotely as well, the item needs to be
// kept as unsynced
localChanged: changeset1.length > matchedLocalChanges.size
localChanged
};
},

View file

@ -674,6 +674,37 @@ describe("Zotero.Sync.Data.Local", function() {
}
});
it("should automatically resolve collection name conflict", async function () {
var libraryID = Zotero.Libraries.userLibraryID;
var type = 'collection';
let obj = await createDataObject(type, { version: 5 });
let data = obj.toJSON();
await Zotero.Sync.Data.Local.saveCacheObjects(type, libraryID, [data]);
// Change local name
await modifyDataObject(obj);
var changedName = Zotero.Utilities.randomString();
// Create remote version with changed name
data.version = 10;
data.name = changedName;
let json = {
key: obj.key,
version: 10,
data
};
await Zotero.Sync.Data.Local.processObjectsFromJSON(
type, libraryID, [json], { stopOnError: true }
);
assert.equal(obj.version, 10);
assert.equal(obj.name, changedName);
assert.isTrue(obj.synced);
// Sync cache should match remote
var cacheJSON = await Zotero.Sync.Data.Local.getCacheObject(type, libraryID, data.key, data.version);
assert.propertyVal(cacheJSON.data, "name", changedName);
});
it("should delete older versions in sync cache after processing", function* () {
var libraryID = Zotero.Libraries.userLibraryID;