Commit 5f78cad3 authored by Cédric Le Ninivin's avatar Cédric Le Ninivin

Release version 3.13.0

parent 397381d8
...@@ -7583,6 +7583,9 @@ return new Parser; ...@@ -7583,6 +7583,9 @@ return new Parser;
i, i,
value, value,
result_list; result_list;
if (obj === undefined) {
return undefined;
}
if (obj.constructor === Object) { if (obj.constructor === Object) {
key_list = Object.keys(obj).sort(); key_list = Object.keys(obj).sort();
result_list = []; result_list = [];
...@@ -7609,6 +7612,9 @@ return new Parser; ...@@ -7609,6 +7612,9 @@ return new Parser;
// https://gist.github.com/davoclavo/4424731 // https://gist.github.com/davoclavo/4424731
function dataURItoBlob(dataURI) { function dataURItoBlob(dataURI) {
if (dataURI === 'data:') {
return new Blob();
}
// convert base64 to raw binary data held in a string // convert base64 to raw binary data held in a string
var byteString = atob(dataURI.split(',')[1]), var byteString = atob(dataURI.split(',')[1]),
// separate out the mime component // separate out the mime component
...@@ -8442,7 +8448,7 @@ return new Parser; ...@@ -8442,7 +8448,7 @@ return new Parser;
this._signature_sub_storage = jIO.createJIO({ this._signature_sub_storage = jIO.createJIO({
type: "document", type: "document",
document_id: this._signature_hash, document_id: this._signature_hash,
sub_storage: spec.local_sub_storage sub_storage: spec.signature_storage || spec.local_sub_storage
}); });
this._use_remote_post = spec.use_remote_post || false; this._use_remote_post = spec.use_remote_post || false;
...@@ -8578,18 +8584,7 @@ return new Parser; ...@@ -8578,18 +8584,7 @@ return new Parser;
}); });
} }
function checkLocalDeletion(queue, destination, id, source) { function propagateDeletion(destination, id) {
var status_hash;
queue
.push(function () {
return context._signature_sub_storage.get(id);
})
.push(function (result) {
status_hash = result.hash;
return destination.get(id)
.push(function (doc) {
var remote_hash = generateHash(stringify(doc));
if (remote_hash === status_hash) {
return destination.remove(id) return destination.remove(id)
.push(function () { .push(function () {
return context._signature_sub_storage.remove(id); return context._signature_sub_storage.remove(id);
...@@ -8598,25 +8593,113 @@ return new Parser; ...@@ -8598,25 +8593,113 @@ return new Parser;
skip_document_dict[id] = null; skip_document_dict[id] = null;
}); });
} }
// Modifications on remote side
// Push them locally function checkAndPropagate(status_hash, local_hash, doc,
return propagateModification(destination, source, doc, source, destination, id,
remote_hash, id); conflict_force, conflict_revert,
conflict_ignore,
options) {
return destination.get(id)
.push(function (remote_doc) {
return [remote_doc, generateHash(stringify(remote_doc))];
}, function (error) { }, function (error) {
if ((error instanceof jIO.util.jIOError) && if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) { (error.status_code === 404)) {
return [null, null];
}
throw error;
})
.push(function (remote_list) {
var remote_doc = remote_list[0],
remote_hash = remote_list[1];
if (local_hash === remote_hash) {
// Same modifications on both side
if (local_hash === null) {
// Deleted on both side, drop signature
return context._signature_sub_storage.remove(id) return context._signature_sub_storage.remove(id)
.push(function () { .push(function () {
skip_document_dict[id] = null; skip_document_dict[id] = null;
}); });
} }
throw error;
return context._signature_sub_storage.put(id, {
"hash": local_hash
})
.push(function () {
skip_document_dict[id] = null;
}); });
}
if ((remote_hash === status_hash) || (conflict_force === true)) {
// Modified only locally. No conflict or force
if (local_hash === null) {
// Deleted locally
return propagateDeletion(destination, id);
}
return propagateModification(source, destination, doc,
local_hash, id,
{use_post: ((options.use_post) &&
(remote_hash === null))});
}
// Conflict cases
if (conflict_ignore === true) {
return;
}
if ((conflict_revert === true) || (local_hash === null)) {
// Automatically resolve conflict or force revert
if (remote_hash === null) {
// Deleted remotely
return propagateDeletion(source, id);
}
return propagateModification(
destination,
source,
remote_doc,
remote_hash,
id,
{use_post: ((options.use_revert_post) &&
(local_hash === null))}
);
}
// Minimize conflict if it can be resolved
if (remote_hash === null) {
// Copy remote modification remotely
return propagateModification(source, destination, doc,
local_hash, id,
{use_post: options.use_post});
}
throw new jIO.util.jIOError("Conflict on '" + id + "': " +
stringify(doc || '') + " !== " +
stringify(remote_doc || ''),
409);
});
}
function checkLocalDeletion(queue, destination, id, source,
conflict_force, conflict_revert,
conflict_ignore, options) {
var status_hash;
queue
.push(function () {
return context._signature_sub_storage.get(id);
})
.push(function (result) {
status_hash = result.hash;
return checkAndPropagate(status_hash, null, null,
source, destination, id,
conflict_force, conflict_revert,
conflict_ignore,
options);
}); });
} }
function checkSignatureDifference(queue, source, destination, id, function checkSignatureDifference(queue, source, destination, id,
conflict_force, conflict_ignore, conflict_force, conflict_revert,
conflict_ignore,
is_creation, is_modification, is_creation, is_modification,
getMethod, options) { getMethod, options) {
queue queue
...@@ -8625,7 +8708,7 @@ return new Parser; ...@@ -8625,7 +8708,7 @@ return new Parser;
if (is_creation === true) { if (is_creation === true) {
return RSVP.all([ return RSVP.all([
getMethod(id), getMethod(id),
{hash: undefined} {hash: null}
]); ]);
} }
if (is_modification === true) { if (is_modification === true) {
...@@ -8644,59 +8727,19 @@ return new Parser; ...@@ -8644,59 +8727,19 @@ return new Parser;
status_hash = result_list[1].hash; status_hash = result_list[1].hash;
if (local_hash !== status_hash) { if (local_hash !== status_hash) {
// Local modifications return checkAndPropagate(status_hash, local_hash, doc,
return destination.get(id) source, destination, id,
.push(function (remote_doc) { conflict_force, conflict_revert,
var remote_hash = generateHash(stringify(remote_doc)); conflict_ignore,
if (remote_hash !== status_hash) { options);
// Modifications on both sides
if (local_hash === remote_hash) {
// Same modifications on both side \o/
return context._signature_sub_storage.put(id, {
"hash": local_hash
})
.push(function () {
skip_document_dict[id] = null;
});
}
if (conflict_ignore === true) {
return;
}
if (conflict_force !== true) {
throw new jIO.util.jIOError("Conflict on '" + id + "': " +
stringify(doc) + " !== " +
stringify(remote_doc),
409);
}
}
return propagateModification(source, destination, doc,
local_hash, id);
}, function (error) {
var use_post;
if ((error instanceof jIO.util.jIOError) &&
(error.status_code === 404)) {
if (is_creation) {
// Remote document does not exists, create it following
// provided options
use_post = options.use_post;
} else {
// Remote document has been erased, put it to save
// modification
use_post = false;
}
return propagateModification(source, destination, doc,
local_hash, id,
{use_post: use_post});
}
throw error;
});
} }
}); });
} }
function checkBulkSignatureDifference(queue, source, destination, id_list, function checkBulkSignatureDifference(queue, source, destination, id_list,
document_status_list, options, document_status_list, options,
conflict_force, conflict_ignore) { conflict_force, conflict_revert,
conflict_ignore) {
queue queue
.push(function () { .push(function () {
return source.bulk(id_list); return source.bulk(id_list);
...@@ -8717,7 +8760,8 @@ return new Parser; ...@@ -8717,7 +8760,8 @@ return new Parser;
for (i = 0; i < result_list.length; i += 1) { for (i = 0; i < result_list.length; i += 1) {
checkSignatureDifference(sub_queue, source, destination, checkSignatureDifference(sub_queue, source, destination,
id_list[i].parameter_list[0], id_list[i].parameter_list[0],
conflict_force, conflict_ignore, conflict_force, conflict_revert,
conflict_ignore,
document_status_list[i].is_creation, document_status_list[i].is_creation,
document_status_list[i].is_modification, document_status_list[i].is_modification,
getResult(i), options); getResult(i), options);
...@@ -8731,6 +8775,9 @@ return new Parser; ...@@ -8731,6 +8775,9 @@ return new Parser;
if (!options.hasOwnProperty("use_post")) { if (!options.hasOwnProperty("use_post")) {
options.use_post = false; options.use_post = false;
} }
if (!options.hasOwnProperty("use_revert_post")) {
options.use_revert_post = false;
}
return queue return queue
.push(function () { .push(function () {
return RSVP.all([ return RSVP.all([
...@@ -8780,6 +8827,7 @@ return new Parser; ...@@ -8780,6 +8827,7 @@ return new Parser;
} else { } else {
checkSignatureDifference(queue, source, destination, key, checkSignatureDifference(queue, source, destination, key,
options.conflict_force, options.conflict_force,
options.conflict_revert,
options.conflict_ignore, options.conflict_ignore,
is_creation, is_modification, is_creation, is_modification,
source.get.bind(source), source.get.bind(source),
...@@ -8792,7 +8840,11 @@ return new Parser; ...@@ -8792,7 +8840,11 @@ return new Parser;
for (key in signature_dict) { for (key in signature_dict) {
if (signature_dict.hasOwnProperty(key)) { if (signature_dict.hasOwnProperty(key)) {
if (!local_dict.hasOwnProperty(key)) { if (!local_dict.hasOwnProperty(key)) {
checkLocalDeletion(queue, destination, key, source); checkLocalDeletion(queue, destination, key, source,
options.conflict_force,
options.conflict_revert,
options.conflict_ignore,
options);
} }
} }
} }
...@@ -8802,6 +8854,7 @@ return new Parser; ...@@ -8802,6 +8854,7 @@ return new Parser;
document_list, document_status_list, document_list, document_status_list,
options, options,
options.conflict_force, options.conflict_force,
options.conflict_revert,
options.conflict_ignore); options.conflict_ignore);
} }
}); });
...@@ -8853,10 +8906,10 @@ return new Parser; ...@@ -8853,10 +8906,10 @@ return new Parser;
use_post: context._use_remote_post, use_post: context._use_remote_post,
conflict_force: (context._conflict_handling === conflict_force: (context._conflict_handling ===
CONFLICT_KEEP_LOCAL), CONFLICT_KEEP_LOCAL),
conflict_ignore: ((context._conflict_handling === conflict_revert: (context._conflict_handling ===
CONFLICT_CONTINUE) || CONFLICT_KEEP_REMOTE),
(context._conflict_handling === conflict_ignore: (context._conflict_handling ===
CONFLICT_KEEP_REMOTE)), CONFLICT_CONTINUE),
check_modification: context._check_local_modification, check_modification: context._check_local_modification,
check_creation: context._check_local_creation, check_creation: context._check_local_creation,
check_deletion: context._check_local_deletion check_deletion: context._check_local_deletion
...@@ -8881,8 +8934,11 @@ return new Parser; ...@@ -8881,8 +8934,11 @@ return new Parser;
return pushStorage(context._remote_sub_storage, return pushStorage(context._remote_sub_storage,
context._local_sub_storage, { context._local_sub_storage, {
use_bulk_get: use_bulk_get, use_bulk_get: use_bulk_get,
use_revert_post: context._use_remote_post,
conflict_force: (context._conflict_handling === conflict_force: (context._conflict_handling ===
CONFLICT_KEEP_REMOTE), CONFLICT_KEEP_REMOTE),
conflict_revert: (context._conflict_handling ===
CONFLICT_KEEP_LOCAL),
conflict_ignore: (context._conflict_handling === conflict_ignore: (context._conflict_handling ===
CONFLICT_CONTINUE), CONFLICT_CONTINUE),
check_modification: context._check_remote_modification, check_modification: context._check_remote_modification,
...@@ -10872,7 +10928,7 @@ return new Parser; ...@@ -10872,7 +10928,7 @@ return new Parser;
sub_query, sub_query,
result_list, result_list,
local_roles, local_roles,
tmp_list = []; sort_list = [];
if (options.query) { if (options.query) {
parsed_query = jIO.QueryFactory.create(options.query); parsed_query = jIO.QueryFactory.create(options.query);
...@@ -10916,9 +10972,8 @@ return new Parser; ...@@ -10916,9 +10972,8 @@ return new Parser;
if (options.sort_on) { if (options.sort_on) {
for (i = 0; i < options.sort_on.length; i += 1) { for (i = 0; i < options.sort_on.length; i += 1) {
tmp_list.push(JSON.stringify(options.sort_on[i])); sort_list.push(JSON.stringify(options.sort_on[i]));
} }
options.sort_on = tmp_list;
} }
return jIO.util.ajax({ return jIO.util.ajax({
...@@ -10929,7 +10984,7 @@ return new Parser; ...@@ -10929,7 +10984,7 @@ return new Parser;
// XXX Force erp5 to return embedded document // XXX Force erp5 to return embedded document
select_list: options.select_list || ["title", "reference"], select_list: options.select_list || ["title", "reference"],
limit: options.limit, limit: options.limit,
sort_on: options.sort_on, sort_on: sort_list,
local_roles: local_roles local_roles: local_roles
}), }),
"xhrFields": { "xhrFields": {
...@@ -11801,9 +11856,11 @@ return new Parser; ...@@ -11801,9 +11856,11 @@ return new Parser;
*/ */
/*jslint nomen: true */ /*jslint nomen: true */
/*global indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange*/ /*global indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange, IDBOpenDBRequest,
DOMError, Event*/
(function (indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange) { (function (indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange, IDBOpenDBRequest,
DOMError) {
"use strict"; "use strict";
// Read only as changing it can lead to data corruption // Read only as changing it can lead to data corruption
...@@ -11862,7 +11919,14 @@ return new Parser; ...@@ -11862,7 +11919,14 @@ return new Parser;
if (request.result) { if (request.result) {
request.result.close(); request.result.close();
} }
if ((error !== undefined) &&
(error.target instanceof IDBOpenDBRequest) &&
(error.target.error instanceof DOMError)) {
reject("Connection to: " + db_name + " failed: " +
error.target.error.message);
} else {
reject(error); reject(error);
}
}; };
request.onabort = function () { request.onabort = function () {
...@@ -12223,7 +12287,7 @@ return new Parser; ...@@ -12223,7 +12287,7 @@ return new Parser;
}; };
jIO.addStorage("indexeddb", IndexedDBStorage); jIO.addStorage("indexeddb", IndexedDBStorage);
}(indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange)); }(indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange, IDBOpenDBRequest, DOMError));
;/* ;/*
* Copyright 2015, Nexedi SA * Copyright 2015, Nexedi SA
* Released under the LGPL license. * Released under the LGPL license.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
{ {
"name": "jio", "name": "jio",
"version": "v3.12.0", "version": "v3.13.0",
"license": "LGPLv3", "license": "LGPLv3",
"author": "Nexedi SA", "author": "Nexedi SA",
"contributors": [ "contributors": [
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment