Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jio-main
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Hardik Juneja
jio-main
Commits
bc17b228
Commit
bc17b228
authored
Jan 10, 2013
by
Sven Franck
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
jslint pass revisionstorage.js
parent
e45edf9f
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
834 additions
and
826 deletions
+834
-826
src/jio.storage/revisionstorage.js
src/jio.storage/revisionstorage.js
+834
-826
No files found.
src/jio.storage/revisionstorage.js
View file @
bc17b228
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global jIO: true, hex_sha256: true, setTimeout: true */
/**
* JIO Revision Storage.
* It manages document version and can generate conflicts.
...
...
@@ -8,869 +10,875 @@
* }
*/
jIO
.
addStorageType
(
'
revision
'
,
function
(
spec
,
my
)
{
"
use strict
"
;
var
that
,
priv
=
{};
spec
=
spec
||
{};
that
=
my
.
basicStorage
(
spec
,
my
);
priv
.
substorage_key
=
"
sub_storage
"
;
priv
.
doctree_suffix
=
"
.revision_tree.json
"
;
priv
.
substorage
=
spec
[
priv
.
substorage_key
];
that
.
specToStore
=
function
()
{
var
o
=
{};
o
[
priv
.
substorage_key
]
=
priv
.
substorage
;
return
o
;
"
use strict
"
;
var
that
,
priv
=
{};
spec
=
spec
||
{};
that
=
my
.
basicStorage
(
spec
,
my
);
priv
.
substorage_key
=
"
sub_storage
"
;
priv
.
doctree_suffix
=
"
.revision_tree.json
"
;
priv
.
substorage
=
spec
[
priv
.
substorage_key
];
that
.
specToStore
=
function
()
{
var
o
=
{};
o
[
priv
.
substorage_key
]
=
priv
.
substorage
;
return
o
;
};
/**
* Generate a new uuid
* @method generateUuid
* @return {string} The new uuid
*/
priv
.
generateUuid
=
function
()
{
var
S4
=
function
()
{
/* 65536 */
var
i
,
string
=
Math
.
floor
(
Math
.
random
()
*
0x10000
).
toString
(
16
);
for
(
i
=
string
.
length
;
i
<
4
;
i
+=
1
)
{
string
=
'
0
'
+
string
;
}
return
string
;
};
/**
* Generate a new uuid
* @method generateUuid
* @return {string} The new uuid
*/
priv
.
generateUuid
=
function
()
{
var
S4
=
function
()
{
var
i
,
string
=
Math
.
floor
(
Math
.
random
()
*
0x10000
/* 65536 */
).
toString
(
16
);
for
(
i
=
string
.
length
;
i
<
4
;
i
+=
1
)
{
string
=
'
0
'
+
string
;
}
return
string
;
};
return
S4
()
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
S4
()
+
S4
();
return
S4
()
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
S4
()
+
S4
();
};
/**
* Generates a hash code of a string
* @method hashCode
* @param {string} string The string to hash
* @return {string} The string hash code
*/
priv
.
hashCode
=
function
(
string
)
{
return
hex_sha256
(
string
);
};
/**
* Returns an array version of a revision string
* @method revisionToArray
* @param {string} revision The revision string
* @return {array} Array containing a revision number and a hash
*/
priv
.
revisionToArray
=
function
(
revision
)
{
if
(
typeof
revision
===
"
string
"
)
{
return
[
parseInt
(
revision
.
split
(
'
-
'
)[
0
],
10
),
revision
.
split
(
'
-
'
)[
1
]];
}
return
revision
;
};
/**
* Generates the next revision of [previous_revision]. [string] helps us
* to generate a hash code.
* @methode generateNextRev
* @param {string} previous_revision The previous revision
* @param {object} doc The document metadata
* @param {object} revisions The revision history
* @param {boolean} deleted_flag The deleted flag
* @return {array} 0:The next revision number and 1:the hash code
*/
priv
.
generateNextRevision
=
function
(
previous_revision
,
doc
,
revisions
,
deleted_flag
)
{
var
string
=
JSON
.
stringify
(
doc
)
+
JSON
.
stringify
(
revisions
)
+
JSON
.
stringify
(
deleted_flag
?
true
:
false
);
if
(
typeof
previous_revision
===
"
number
"
)
{
return
[
previous_revision
+
1
,
priv
.
hashCode
(
string
)];
}
previous_revision
=
priv
.
revisionToArray
(
previous_revision
);
return
[
previous_revision
[
0
]
+
1
,
priv
.
hashCode
(
string
)];
};
/**
* Checks a revision format
* @method checkRevisionFormat
* @param {string} revision The revision string
* @return {boolean} True if ok, else false
*/
priv
.
checkRevisionFormat
=
function
(
revision
)
{
return
(
/^
[
0-9
]
+-
[
0-9a-zA-Z
]
+$/
.
test
(
revision
));
};
/**
* Creates an empty document tree
* @method createDocumentTree
* @param {array} children An array of children (optional)
* @return {object} The new document tree
*/
priv
.
createDocumentTree
=
function
(
children
)
{
return
{
"
children
"
:
children
||
[]
};
/**
* Generates a hash code of a string
* @method hashCode
* @param {string} string The string to hash
* @return {string} The string hash code
*/
priv
.
hashCode
=
function
(
string
)
{
return
hex_sha256
(
string
);
};
/**
* Creates a new document tree node
* @method createDocumentTreeNode
* @param {string} revision The node revision
* @param {string} status The node status
* @param {array} children An array of children (optional)
* @return {object} The new document tree node
*/
priv
.
createDocumentTreeNode
=
function
(
revision
,
status
,
children
)
{
return
{
"
rev
"
:
revision
,
"
status
"
:
status
,
"
children
"
:
children
||
[]
};
/**
* Returns an array version of a revision string
* @method revisionToArray
* @param {string} revision The revision string
* @return {array} Array containing a revision number and a hash
*/
priv
.
revisionToArray
=
function
(
revision
)
{
if
(
typeof
revision
===
"
string
"
)
{
return
[
parseInt
(
revision
.
split
(
'
-
'
)[
0
],
10
),
revision
.
split
(
'
-
'
)[
1
]]
};
/**
* Gets the specific revision from a document tree.
* @method getRevisionFromDocumentTree
* @param {object} document_tree The document tree
* @param {string} revision The specific revision
* @return {array} The good revs info array
*/
priv
.
getRevisionFromDocumentTree
=
function
(
document_tree
,
revision
)
{
var
result
,
search
,
revs_info
=
[];
result
=
[];
// search method fills "result" with the good revs info
search
=
function
(
document_tree
)
{
var
i
;
if
(
document_tree
.
rev
!==
undefined
)
{
// node is not root
revs_info
.
unshift
({
"
rev
"
:
document_tree
.
rev
,
"
status
"
:
document_tree
.
status
});
if
(
document_tree
.
rev
===
revision
)
{
result
=
revs_info
;
return
;
}
return
revision
;
};
/**
* Generates the next revision of [previous_revision]. [string] helps us
* to generate a hash code.
* @methode generateNextRev
* @param {string} previous_revision The previous revision
* @param {object} doc The document metadata
* @param {object} revisions The revision history
* @param {boolean} deleted_flag The deleted flag
* @return {array} 0:The next revision number and 1:the hash code
*/
priv
.
generateNextRevision
=
function
(
previous_revision
,
doc
,
revisions
,
deleted_flag
)
{
var
string
=
JSON
.
stringify
(
doc
)
+
JSON
.
stringify
(
revisions
)
+
JSON
.
stringify
(
deleted_flag
?
true
:
false
);
if
(
typeof
previous_revision
===
"
number
"
)
{
return
[
previous_revision
+
1
,
priv
.
hashCode
(
string
)];
}
// This node has children
for
(
i
=
0
;
i
<
document_tree
.
children
.
length
;
i
+=
1
)
{
// searching deeper to find the good rev
search
(
document_tree
.
children
[
i
]);
if
(
result
.
length
>
0
)
{
// The result is already found
return
;
}
previous_revision
=
priv
.
revisionToArray
(
previous_revision
);
return
[
previous_revision
[
0
]
+
1
,
priv
.
hashCode
(
string
)];
};
/**
* Checks a revision format
* @method checkRevisionFormat
* @param {string} revision The revision string
* @return {boolean} True if ok, else false
*/
priv
.
checkRevisionFormat
=
function
(
revision
)
{
return
(
/^
[
0-9
]
+-
[
0-9a-zA-Z
]
+$/
.
test
(
revision
));
};
/**
* Creates an empty document tree
* @method createDocumentTree
* @param {array} children An array of children (optional)
* @return {object} The new document tree
*/
priv
.
createDocumentTree
=
function
(
children
)
{
return
{
"
children
"
:
children
||
[]};
revs_info
.
shift
();
}
};
/**
* Creates a new document tree node
* @method createDocumentTreeNode
* @param {string} revision The node revision
* @param {string} status The node status
* @param {array} children An array of children (optional)
* @return {object} The new document tree node
*/
priv
.
createDocumentTreeNode
=
function
(
revision
,
status
,
children
)
{
return
{
"
rev
"
:
revision
,
"
status
"
:
status
,
"
children
"
:
children
||
[]};
};
/**
* Gets the specific revision from a document tree.
* @method getRevisionFromDocumentTree
* @param {object} document_tree The document tree
* @param {string} revision The specific revision
* @return {array} The good revs info array
*/
priv
.
getRevisionFromDocumentTree
=
function
(
document_tree
,
revision
)
{
var
i
,
result
,
search
,
revs_info
=
[];
result
=
[];
// search method fills "result" with the good revs info
search
=
function
(
document_tree
)
{
var
i
;
if
(
typeof
document_tree
.
rev
!==
"
undefined
"
)
{
// node is not root
revs_info
.
unshift
({
"
rev
"
:
document_tree
.
rev
,
"
status
"
:
document_tree
.
status
});
if
(
document_tree
.
rev
===
revision
)
{
result
=
revs_info
;
return
;
}
}
// This node has children
for
(
i
=
0
;
i
<
document_tree
.
children
.
length
;
i
+=
1
)
{
// searching deeper to find the good rev
search
(
document_tree
.
children
[
i
]);
if
(
result
.
length
>
0
)
{
// The result is already found
return
;
}
revs_info
.
shift
();
}
};
search
(
document_tree
);
return
result
;
};
/**
* Gets the winner revision from a document tree.
* The winner is the deeper revision on the left.
* @method getWinnerRevisionFromDocumentTree
* @param {object} document_tree The document tree
* @return {array} The winner revs info array
*/
priv
.
getWinnerRevisionFromDocumentTree
=
function
(
document_tree
)
{
var
i
,
result
,
search
,
revs_info
=
[];
result
=
[];
// search method fills "result" with the winner revs info
search
=
function
(
document_tree
,
deep
)
{
var
i
;
if
(
typeof
document_tree
.
rev
!==
"
undefined
"
)
{
// node is not root
revs_info
.
unshift
({
"
rev
"
:
document_tree
.
rev
,
"
status
"
:
document_tree
.
status
});
}
if
(
document_tree
.
children
.
length
===
0
&&
document_tree
.
status
!==
"
deleted
"
)
{
// This node is a leaf
if
(
result
.
length
<
deep
)
{
// The leaf is deeper than result
result
=
[];
for
(
i
=
0
;
i
<
revs_info
.
length
;
i
+=
1
)
{
result
.
push
(
revs_info
[
i
]);
}
}
return
;
}
// This node has children
for
(
i
=
0
;
i
<
document_tree
.
children
.
length
;
i
+=
1
)
{
// searching deeper to find the deeper leaf
search
(
document_tree
.
children
[
i
],
deep
+
1
);
revs_info
.
shift
();
}
};
search
(
document_tree
,
0
);
return
result
;
};
/**
* Add a document revision to the document tree
* @method postToDocumentTree
* @param {object} doctree The document tree object
* @param {object} doc The document object
* @param {boolean} set_node_to_deleted Set the revision to deleted
* @return {array} The added document revs_info
*/
priv
.
postToDocumentTree
=
function
(
doctree
,
doc
,
set_node_to_deleted
)
{
var
i
,
revs_info
,
next_rev
,
next_rev_str
,
selectNode
,
selected_node
,
flag
;
flag
=
set_node_to_deleted
===
true
?
"
deleted
"
:
"
available
"
;
revs_info
=
[];
selected_node
=
doctree
;
selectNode
=
function
(
node
)
{
var
i
;
if
(
typeof
node
.
rev
!==
"
undefined
"
)
{
// node is not root
revs_info
.
unshift
({
"
rev
"
:
node
.
rev
,
"
status
"
:
node
.
status
});
}
if
(
node
.
rev
===
doc
.
_rev
)
{
selected_node
=
node
;
return
"
node_selected
"
;
}
else
{
for
(
i
=
0
;
i
<
node
.
children
.
length
;
i
+=
1
)
{
if
(
selectNode
(
node
.
children
[
i
])
===
"
node_selected
"
)
{
return
"
node_selected
"
;
}
revs_info
.
shift
();
}
}
};
if
(
typeof
doc
.
_rev
===
"
string
"
)
{
// document has a previous revision
if
(
selectNode
(
selected_node
)
!==
"
node_selected
"
)
{
// no node was selected, so add a node with a specific rev
revs_info
.
unshift
({
"
rev
"
:
doc
.
_rev
,
"
status
"
:
"
missing
"
});
selected_node
.
children
.
unshift
({
"
rev
"
:
doc
.
_rev
,
"
status
"
:
"
missing
"
,
"
children
"
:
[]
});
selected_node
=
selected_node
.
children
[
0
];
}
search
(
document_tree
);
return
result
;
};
/**
* Gets the winner revision from a document tree.
* The winner is the deeper revision on the left.
* @method getWinnerRevisionFromDocumentTree
* @param {object} document_tree The document tree
* @return {array} The winner revs info array
*/
priv
.
getWinnerRevisionFromDocumentTree
=
function
(
document_tree
)
{
var
result
,
search
,
revs_info
=
[];
result
=
[];
// search method fills "result" with the winner revs info
search
=
function
(
document_tree
,
deep
)
{
var
i
;
if
(
document_tree
.
rev
!==
undefined
)
{
// node is not root
revs_info
.
unshift
({
"
rev
"
:
document_tree
.
rev
,
"
status
"
:
document_tree
.
status
});
}
if
(
document_tree
.
children
.
length
===
0
&&
document_tree
.
status
!==
"
deleted
"
)
{
// This node is a leaf
if
(
result
.
length
<
deep
)
{
// The leaf is deeper than result
result
=
[];
for
(
i
=
0
;
i
<
revs_info
.
length
;
i
+=
1
)
{
result
.
push
(
revs_info
[
i
]);
}
}
next_rev
=
priv
.
generateNextRevision
(
doc
.
_rev
||
0
,
doc
,
priv
.
revsInfoToHistory
(
revs_info
),
set_node_to_deleted
);
next_rev_str
=
next_rev
.
join
(
"
-
"
);
// don't add if the next rev already exists
for
(
i
=
0
;
i
<
selected_node
.
children
.
length
;
i
+=
1
)
{
if
(
selected_node
.
children
[
i
].
rev
===
next_rev_str
)
{
revs_info
.
unshift
({
"
rev
"
:
next_rev_str
,
"
status
"
:
flag
});
if
(
selected_node
.
children
[
i
].
status
!==
flag
)
{
selected_node
.
children
[
i
].
status
=
flag
;
}
return
revs_info
;
}
return
;
}
// This node has children
for
(
i
=
0
;
i
<
document_tree
.
children
.
length
;
i
+=
1
)
{
// searching deeper to find the deeper leaf
search
(
document_tree
.
children
[
i
],
deep
+
1
);
revs_info
.
shift
();
}
};
search
(
document_tree
,
0
);
return
result
;
};
/**
* Add a document revision to the document tree
* @method postToDocumentTree
* @param {object} doctree The document tree object
* @param {object} doc The document object
* @param {boolean} set_node_to_deleted Set the revision to deleted
* @return {array} The added document revs_info
*/
priv
.
postToDocumentTree
=
function
(
doctree
,
doc
,
set_node_to_deleted
)
{
var
i
,
revs_info
,
next_rev
,
next_rev_str
,
selectNode
,
selected_node
,
flag
;
flag
=
set_node_to_deleted
===
true
?
"
deleted
"
:
"
available
"
;
revs_info
=
[];
selected_node
=
doctree
;
selectNode
=
function
(
node
)
{
var
i
;
if
(
node
.
rev
!==
undefined
)
{
// node is not root
revs_info
.
unshift
({
"
rev
"
:
node
.
rev
,
"
status
"
:
node
.
status
});
}
if
(
node
.
rev
===
doc
.
_rev
)
{
selected_node
=
node
;
return
"
node_selected
"
;
}
for
(
i
=
0
;
i
<
node
.
children
.
length
;
i
+=
1
)
{
if
(
selectNode
(
node
.
children
[
i
])
===
"
node_selected
"
)
{
return
"
node_selected
"
;
}
revs_info
.
shift
();
}
};
if
(
typeof
doc
.
_rev
===
"
string
"
)
{
// document has a previous revision
if
(
selectNode
(
selected_node
)
!==
"
node_selected
"
)
{
// no node was selected, so add a node with a specific rev
revs_info
.
unshift
({
"
rev
"
:
next_rev
.
join
(
'
-
'
)
,
"
status
"
:
flag
"
rev
"
:
doc
.
_rev
,
"
status
"
:
"
missing
"
});
selected_node
.
children
.
unshift
({
"
rev
"
:
next_rev
.
join
(
'
-
'
)
,
"
status
"
:
flag
,
"
children
"
:
[]
"
rev
"
:
doc
.
_rev
,
"
status
"
:
"
missing
"
,
"
children
"
:
[]
});
selected_node
=
selected_node
.
children
[
0
];
}
}
next_rev
=
priv
.
generateNextRevision
(
doc
.
_rev
||
0
,
doc
,
priv
.
revsInfoToHistory
(
revs_info
),
set_node_to_deleted
);
next_rev_str
=
next_rev
.
join
(
"
-
"
);
// don't add if the next rev already exists
for
(
i
=
0
;
i
<
selected_node
.
children
.
length
;
i
+=
1
)
{
if
(
selected_node
.
children
[
i
].
rev
===
next_rev_str
)
{
revs_info
.
unshift
({
"
rev
"
:
next_rev_str
,
"
status
"
:
flag
});
if
(
selected_node
.
children
[
i
].
status
!==
flag
)
{
selected_node
.
children
[
i
].
status
=
flag
;
}
return
revs_info
;
}
}
revs_info
.
unshift
({
"
rev
"
:
next_rev
.
join
(
'
-
'
),
"
status
"
:
flag
});
selected_node
.
children
.
unshift
({
"
rev
"
:
next_rev
.
join
(
'
-
'
),
"
status
"
:
flag
,
"
children
"
:
[]
});
return
revs_info
;
};
/**
* Gets an array of leaves revisions from document tree
* @method getLeavesFromDocumentTree
* @param {object} document_tree The document tree
* @param {string} except The revision to except
* @return {array} The array of leaves revisions
*/
priv
.
getLeavesFromDocumentTree
=
function
(
document_tree
,
except
)
{
var
result
,
search
;
result
=
[];
// search method fills [result] with the winner revision
search
=
function
(
document_tree
)
{
var
i
;
if
(
except
!==
undefined
&&
except
===
document_tree
.
rev
)
{
return
;
}
if
(
document_tree
.
children
.
length
===
0
&&
document_tree
.
status
!==
"
deleted
"
)
{
// This node is a leaf
result
.
push
(
document_tree
.
rev
);
return
;
}
// This node has children
for
(
i
=
0
;
i
<
document_tree
.
children
.
length
;
i
+=
1
)
{
// searching deeper to find the deeper leaf
search
(
document_tree
.
children
[
i
]);
}
};
/**
* Gets an array of leaves revisions from document tree
* @method getLeavesFromDocumentTree
* @param {object} document_tree The document tree
* @param {string} except The revision to except
* @return {array} The array of leaves revisions
*/
priv
.
getLeavesFromDocumentTree
=
function
(
document_tree
,
except
)
{
var
i
,
result
,
search
;
result
=
[];
// search method fills [result] with the winner revision
search
=
function
(
document_tree
)
{
var
i
;
if
(
except
!==
undefined
&&
except
===
document_tree
.
rev
)
{
return
;
}
if
(
document_tree
.
children
.
length
===
0
&&
document_tree
.
status
!==
"
deleted
"
)
{
// This node is a leaf
result
.
push
(
document_tree
.
rev
);
return
;
}
// This node has children
for
(
i
=
0
;
i
<
document_tree
.
children
.
length
;
i
+=
1
)
{
// searching deeper to find the deeper leaf
search
(
document_tree
.
children
[
i
]);
}
};
search
(
document_tree
);
return
result
;
};
/**
* Check if revision is a leaf
* @method isRevisionALeaf
* @param {string} revision revision to check
* @param {array} leaves all leaves on tree
* @return {boolean} true/false
*/
priv
.
isRevisionALeaf
=
function
(
document_tree
,
revision
)
{
var
i
,
result
,
search
;
result
=
undefined
;
// search method fills "result" with the good revs info
search
=
function
(
document_tree
)
{
var
i
;
if
(
typeof
document_tree
.
rev
!==
"
undefined
"
)
{
// node is not root
if
(
document_tree
.
rev
===
revision
)
{
if
(
document_tree
.
children
.
length
===
0
)
{
// This node is a leaf
result
=
true
return
;
}
result
=
false
;
return
;
}
}
// This node has children
for
(
i
=
0
;
i
<
document_tree
.
children
.
length
;
i
+=
1
)
{
// searching deeper to find the good rev
search
(
document_tree
.
children
[
i
]);
if
(
result
!==
undefined
)
{
// The result is already found
return
;
}
}
};
search
(
document_tree
);
return
result
||
false
;
};
/**
* Convert revs_info to a simple revisions history
* @method revsInfoToHistory
* @param {array} revs_info The revs info
* @return {object} The revisions history
*/
priv
.
revsInfoToHistory
=
function
(
revs_info
)
{
var
revisions
=
{
"
start
"
:
0
,
"
ids
"
:[]},
i
;
if
(
revs_info
.
length
>
0
)
{
revisions
.
start
=
parseInt
(
revs_info
[
0
].
rev
.
split
(
'
-
'
)[
0
],
10
);
}
for
(
i
=
0
;
i
<
revs_info
.
length
;
i
+=
1
)
{
revisions
.
ids
.
push
(
revs_info
[
i
].
rev
.
split
(
'
-
'
)[
1
]);
search
(
document_tree
);
return
result
;
};
/**
* Check if revision is a leaf
* @method isRevisionALeaf
* @param {string} revision revision to check
* @param {array} leaves all leaves on tree
* @return {boolean} true/false
*/
priv
.
isRevisionALeaf
=
function
(
document_tree
,
revision
)
{
var
result
,
search
;
result
=
undefined
;
// search method fills "result" with the good revs info
search
=
function
(
document_tree
)
{
var
i
;
if
(
document_tree
.
rev
!==
undefined
)
{
// node is not root
if
(
document_tree
.
rev
===
revision
)
{
if
(
document_tree
.
children
.
length
===
0
)
{
// This node is a leaf
result
=
true
;
return
;
}
result
=
false
;
return
;
}
return
revisions
;
};
/**
* Returns the revision of the revision position from a revs_info array.
* @method getRevisionFromPosition
* @param {array} revs_info The revs_info array
* @param {number} rev_pos The revision position number
* @return {string} The revision of the good position (empty string if fail)
*/
priv
.
getRevisionFromPosition
=
function
(
revs_info
,
rev_pos
)
{
var
i
;
for
(
i
=
revs_info
.
length
-
1
;
i
>=
0
;
i
-=
1
)
{
if
(
priv
.
revisionToArray
(
revs_info
[
i
].
rev
)[
0
]
===
rev_pos
)
{
return
revs_info
[
i
].
rev
;
}
}
// This node has children
for
(
i
=
0
;
i
<
document_tree
.
children
.
length
;
i
+=
1
)
{
// searching deeper to find the good rev
search
(
document_tree
.
children
[
i
]);
if
(
result
!==
undefined
)
{
// The result is already found
return
;
}
return
''
;
}
};
/**
* Post the document metadata and create or update a document tree.
* Options:
* - {boolean} keep_revision_history To keep the previous revisions
* (false by default) (NYI).
* @method post
* @param {object} command The JIO command
*/
that
.
post
=
function
(
command
)
{
var
f
=
{},
doctree
,
revs_info
,
doc
,
docid
;
doc
=
command
.
cloneDoc
();
docid
=
command
.
getDocId
();
if
(
typeof
doc
.
_rev
===
"
string
"
&&
!
priv
.
checkRevisionFormat
(
doc
.
_rev
))
{
search
(
document_tree
);
return
result
||
false
;
};
/**
* Convert revs_info to a simple revisions history
* @method revsInfoToHistory
* @param {array} revs_info The revs info
* @return {object} The revisions history
*/
priv
.
revsInfoToHistory
=
function
(
revs_info
)
{
var
revisions
=
{
"
start
"
:
0
,
"
ids
"
:
[]
},
i
;
if
(
revs_info
.
length
>
0
)
{
revisions
.
start
=
parseInt
(
revs_info
[
0
].
rev
.
split
(
'
-
'
)[
0
],
10
);
}
for
(
i
=
0
;
i
<
revs_info
.
length
;
i
+=
1
)
{
revisions
.
ids
.
push
(
revs_info
[
i
].
rev
.
split
(
'
-
'
)[
1
]);
}
return
revisions
;
};
/**
* Returns the revision of the revision position from a revs_info array.
* @method getRevisionFromPosition
* @param {array} revs_info The revs_info array
* @param {number} rev_pos The revision position number
* @return {string} The revision of the good position (empty string if fail)
*/
priv
.
getRevisionFromPosition
=
function
(
revs_info
,
rev_pos
)
{
var
i
;
for
(
i
=
revs_info
.
length
-
1
;
i
>=
0
;
i
-=
1
)
{
if
(
priv
.
revisionToArray
(
revs_info
[
i
].
rev
)[
0
]
===
rev_pos
)
{
return
revs_info
[
i
].
rev
;
}
}
return
''
;
};
/**
* Post the document metadata and create or update a document tree.
* Options:
* - {boolean} keep_revision_history To keep the previous revisions
* (false by default) (NYI).
* @method post
* @param {object} command The JIO command
*/
that
.
post
=
function
(
command
)
{
var
f
=
{},
doctree
,
revs_info
,
doc
,
docid
;
doc
=
command
.
cloneDoc
();
docid
=
command
.
getDocId
();
if
(
typeof
doc
.
_rev
===
"
string
"
&&
!
priv
.
checkRevisionFormat
(
doc
.
_rev
))
{
that
.
error
({
"
status
"
:
31
,
"
statusText
"
:
"
Wrong Revision Format
"
,
"
error
"
:
"
wrong_revision_format
"
,
"
message
"
:
"
The document previous revision does not match
"
+
"
^[0-9]+-[0-9a-zA-Z]+$
"
,
"
reason
"
:
"
Previous revision is wrong
"
});
return
;
}
if
(
typeof
docid
!==
"
string
"
)
{
doc
.
_id
=
priv
.
generateUuid
();
docid
=
doc
.
_id
;
}
if
(
priv
.
update_doctree_allowed
===
undefined
)
{
priv
.
update_doctree_allowed
=
true
;
}
f
.
getDocumentTree
=
function
()
{
var
option
=
command
.
cloneOption
();
if
(
option
.
max_retry
===
0
)
{
option
.
max_retry
=
3
;
}
that
.
addJob
(
"
get
"
,
priv
.
substorage
,
docid
+
priv
.
doctree_suffix
,
option
,
function
(
response
)
{
doctree
=
response
;
if
(
priv
.
update_doctree_allowed
)
{
f
.
postDocument
(
"
put
"
);
}
else
{
that
.
error
({
"
status
"
:
31
,
"
statusText
"
:
"
Wrong Revision Format
"
,
"
error
"
:
"
wrong_revision_format
"
,
"
message
"
:
"
The document previous revision does not match
"
+
"
^[0-9]+-[0-9a-zA-Z]+$
"
,
"
reason
"
:
"
Previous revision is wrong
"
"
status
"
:
409
,
"
statusText
"
:
"
Conflict
"
,
"
error
"
:
"
conflict
"
,
"
message
"
:
"
Cannot update a document
"
,
"
reason
"
:
"
Document update conflict
"
});
return
;
}
if
(
typeof
docid
!==
"
string
"
)
{
doc
.
_id
=
priv
.
generateUuid
();
docid
=
doc
.
_id
;
}
},
function
(
err
)
{
switch
(
err
.
status
)
{
case
404
:
doctree
=
priv
.
createDocumentTree
();
f
.
postDocument
(
"
post
"
);
break
;
default
:
err
.
message
=
"
Cannot get document revision tree
"
;
that
.
error
(
err
);
break
;
}
}
if
(
priv
.
update_doctree_allowed
===
undefined
)
{
priv
.
update_doctree_allowed
=
true
;
}
f
.
getDocumentTree
=
function
()
{
var
option
=
command
.
cloneOption
();
if
(
option
[
"
max_retry
"
]
===
0
)
{
option
[
"
max_retry
"
]
=
3
;
}
that
.
addJob
(
"
get
"
,
priv
.
substorage
,
docid
+
priv
.
doctree_suffix
,
option
,
function
(
response
)
{
doctree
=
response
;
if
(
priv
.
update_doctree_allowed
)
{
f
.
postDocument
(
"
put
"
);
}
else
{
that
.
error
({
"
status
"
:
409
,
"
statusText
"
:
"
Conflict
"
,
"
error
"
:
"
conflict
"
,
"
message
"
:
"
Cannot update a document
"
,
"
reason
"
:
"
Document update conflict
"
});
}
},
function
(
err
)
{
switch
(
err
.
status
)
{
case
404
:
doctree
=
priv
.
createDocumentTree
();
f
.
postDocument
(
"
post
"
);
break
;
default
:
err
.
message
=
"
Cannot get document revision tree
"
;
that
.
error
(
err
);
break
;
}
}
);
};
f
.
postDocument
=
function
(
doctree_update_method
)
{
revs_info
=
priv
.
postToDocumentTree
(
doctree
,
doc
);
doc
.
_id
=
docid
+
"
.
"
+
revs_info
[
0
].
rev
;
that
.
addJob
(
"
post
"
,
priv
.
substorage
,
doc
,
command
.
cloneOption
(),
function
(
response
)
{
f
.
sendDocumentTree
(
doctree_update_method
);
},
function
(
err
)
{
switch
(
err
.
status
)
{
case
409
:
// file already exists
f
.
sendDocumentTree
(
doctree_update_method
);
break
;
default
:
err
.
message
=
"
Cannot upload document
"
.
that
.
error
(
err
);
break
;
}
}
);
};
f
.
sendDocumentTree
=
function
(
method
)
{
doctree
.
_id
=
docid
+
priv
.
doctree_suffix
;
that
.
addJob
(
method
,
priv
.
substorage
,
doctree
,
command
.
cloneOption
(),
function
(
response
)
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
docid
,
"
rev
"
:
revs_info
[
0
].
rev
});
},
function
(
err
)
{
// xxx do we try to delete the posted document ?
err
.
message
=
"
Cannot save document revision tree
"
;
that
.
error
(
err
);
}
);
};
f
.
getDocumentTree
();
);
};
/**
* Update the document metadata and update a document tree.
* Options:
* - {boolean} keep_revision_history To keep the previous revisions
* (false by default) (NYI).
* @method put
* @param {object} command The JIO command
*/
that
.
put
=
function
(
command
)
{
if
(
command
.
cloneDoc
().
_rev
===
undefined
)
{
priv
.
update_doctree_allowed
=
false
;
f
.
postDocument
=
function
(
doctree_update_method
)
{
revs_info
=
priv
.
postToDocumentTree
(
doctree
,
doc
);
doc
.
_id
=
docid
+
"
.
"
+
revs_info
[
0
].
rev
;
that
.
addJob
(
"
post
"
,
priv
.
substorage
,
doc
,
command
.
cloneOption
(),
function
()
{
f
.
sendDocumentTree
(
doctree_update_method
);
},
function
(
err
)
{
switch
(
err
.
status
)
{
case
409
:
// file already exists
f
.
sendDocumentTree
(
doctree_update_method
);
break
;
default
:
err
.
message
=
"
Cannot upload document
"
;
that
.
error
(
err
);
break
;
}
}
that
.
post
(
command
);
);
};
/**
* Get the document metadata or attachment.
* Options:
* - {boolean} revs Add simple revision history (false by default).
* - {boolean} revs_info Add revs info (false by default).
* - {boolean} conflicts Add conflict object (false by default).
* @method get
* @param {object} command The JIO command
*/
that
.
get
=
function
(
command
)
{
var
f
=
{},
doctree
,
revs_info
,
prev_rev
,
option
;
option
=
command
.
cloneOption
();
if
(
option
[
"
max_retry
"
]
===
0
)
{
option
[
"
max_retry
"
]
=
3
;
}
prev_rev
=
command
.
getOption
(
"
rev
"
);
if
(
typeof
prev_rev
===
"
string
"
)
{
if
(
!
priv
.
checkRevisionFormat
(
prev_rev
))
{
that
.
error
({
"
status
"
:
31
,
"
statusText
"
:
"
Wrong Revision Format
"
,
"
error
"
:
"
wrong_revision_format
"
,
"
message
"
:
"
The document previous revision does not match
"
+
"
[0-9]+-[0-9a-zA-Z]+
"
,
"
reason
"
:
"
Previous revision is wrong
"
});
return
;
}
}
f
.
getDocumentTree
=
function
()
{
that
.
addJob
(
"
get
"
,
priv
.
substorage
,
command
.
getDocId
()
+
priv
.
doctree_suffix
,
option
,
function
(
response
)
{
doctree
=
response
;
if
(
prev_rev
===
undefined
)
{
revs_info
=
priv
.
getWinnerRevisionFromDocumentTree
(
doctree
);
prev_rev
=
revs_info
[
0
].
rev
;
}
else
{
revs_info
=
priv
.
getRevisionFromDocumentTree
(
doctree
,
prev_rev
);
}
f
.
getDocument
(
command
.
getDocId
()
+
"
.
"
+
prev_rev
,
command
.
getAttachmentId
());
},
function
(
err
)
{
switch
(
err
.
status
)
{
case
404
:
that
.
error
(
err
);
break
;
default
:
err
.
message
=
"
Cannot get document revision tree
"
;
that
.
error
(
err
);
break
;
}
}
);
};
f
.
getDocument
=
function
(
docid
,
attmtid
)
{
that
.
addJob
(
"
get
"
,
priv
.
substorage
,
docid
,
option
,
function
(
response
)
{
var
attmt
;
if
(
typeof
response
!==
"
string
"
)
{
if
(
attmtid
!==
undefined
)
{
if
(
response
.
_attachments
!==
undefined
)
{
attmt
=
response
.
_attachments
[
attmtid
];
if
(
attmt
!==
undefined
)
{
prev_rev
=
priv
.
getRevisionFromPosition
(
revs_info
,
attmt
.
revpos
);
f
.
getDocument
(
command
.
getDocId
()
+
"
.
"
+
prev_rev
+
"
/
"
+
attmtid
);
return
;
}
}
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Cannot find the attachment
"
,
"
reason
"
:
"
Attachment is missing
"
});
return
;
}
response
.
_id
=
command
.
getDocId
();
response
.
_rev
=
prev_rev
;
if
(
command
.
getOption
(
"
revs
"
)
===
true
)
{
response
.
_revisions
=
priv
.
revsInfoToHistory
(
revs_info
);
}
if
(
command
.
getOption
(
"
revs_info
"
)
===
true
)
{
response
.
_revs_info
=
revs_info
;
}
if
(
command
.
getOption
(
"
conflicts
"
)
===
true
)
{
response
.
_conflicts
=
priv
.
getLeavesFromDocumentTree
(
doctree
,
prev_rev
);
if
(
response
.
_conflicts
.
length
===
0
)
{
delete
response
.
_conflicts
;
}
}
}
that
.
success
(
response
);
},
function
(
err
)
{
that
.
error
(
err
);
}
);
};
if
(
command
.
getAttachmentId
()
&&
prev_rev
!==
undefined
)
{
f
.
getDocument
(
command
.
getDocId
()
+
"
.
"
+
prev_rev
+
"
/
"
+
command
.
getAttachmentId
());
}
else
{
f
.
getDocumentTree
();
f
.
sendDocumentTree
=
function
(
method
)
{
doctree
.
_id
=
docid
+
priv
.
doctree_suffix
;
that
.
addJob
(
method
,
priv
.
substorage
,
doctree
,
command
.
cloneOption
(),
function
()
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
docid
,
"
rev
"
:
revs_info
[
0
].
rev
});
},
function
(
err
)
{
// xxx do we try to delete the posted document ?
err
.
message
=
"
Cannot save document revision tree
"
;
that
.
error
(
err
);
}
);
};
/**
* Remove document or attachment.
* Options:
* - {boolean} keep_revision_history To keep the previous revisions
* @method remove
* @param {object} command The JIO command
*/
that
.
remove
=
function
(
command
)
{
var
f
=
{},
del_rev
,
option
,
new_doc
,
revs_info
,
new_id
;
option
=
command
.
cloneOption
();
if
(
option
[
"
max_retry
"
]
===
0
)
{
option
[
"
max_retry
"
]
=
3
;
f
.
getDocumentTree
();
};
/**
* Update the document metadata and update a document tree.
* Options:
* - {boolean} keep_revision_history To keep the previous revisions
* (false by default) (NYI).
* @method put
* @param {object} command The JIO command
*/
that
.
put
=
function
(
command
)
{
if
(
command
.
cloneDoc
().
_rev
===
undefined
)
{
priv
.
update_doctree_allowed
=
false
;
}
that
.
post
(
command
);
};
/**
* Get the document metadata or attachment.
* Options:
* - {boolean} revs Add simple revision history (false by default).
* - {boolean} revs_info Add revs info (false by default).
* - {boolean} conflicts Add conflict object (false by default).
* @method get
* @param {object} command The JIO command
*/
that
.
get
=
function
(
command
)
{
var
f
=
{},
doctree
,
revs_info
,
prev_rev
,
option
;
option
=
command
.
cloneOption
();
if
(
option
.
max_retry
===
0
)
{
option
.
max_retry
=
3
;
}
prev_rev
=
command
.
getOption
(
"
rev
"
);
if
(
typeof
prev_rev
===
"
string
"
)
{
if
(
!
priv
.
checkRevisionFormat
(
prev_rev
))
{
that
.
error
({
"
status
"
:
31
,
"
statusText
"
:
"
Wrong Revision Format
"
,
"
error
"
:
"
wrong_revision_format
"
,
"
message
"
:
"
The document previous revision does not match
"
+
"
[0-9]+-[0-9a-zA-Z]+
"
,
"
reason
"
:
"
Previous revision is wrong
"
});
return
;
}
}
f
.
getDocumentTree
=
function
()
{
that
.
addJob
(
"
get
"
,
priv
.
substorage
,
command
.
getDocId
()
+
priv
.
doctree_suffix
,
option
,
function
(
response
)
{
doctree
=
response
;
if
(
prev_rev
===
undefined
)
{
revs_info
=
priv
.
getWinnerRevisionFromDocumentTree
(
doctree
);
prev_rev
=
revs_info
[
0
].
rev
;
}
else
{
revs_info
=
priv
.
getRevisionFromDocumentTree
(
doctree
,
prev_rev
);
}
f
.
getDocument
(
command
.
getDocId
()
+
"
.
"
+
prev_rev
,
command
.
getAttachmentId
());
},
function
(
err
)
{
switch
(
err
.
status
)
{
case
404
:
that
.
error
(
err
);
break
;
default
:
err
.
message
=
"
Cannot get document revision tree
"
;
that
.
error
(
err
);
break
;
}
}
del_rev
=
command
.
getDoc
().
_rev
;
f
.
removeDocument
=
function
(
docid
,
doctree
)
{
if
(
command
.
getOption
(
"
keep_revision_history
"
)
!==
true
)
{
if
(
command
.
getAttachmentId
()
===
undefined
){
// update tree
revs_info
=
priv
.
postToDocumentTree
(
doctree
,
command
.
getDoc
(),
true
);
// remove revision
that
.
addJob
(
"
remove
"
,
priv
.
substorage
,
docid
,
option
,
function
(
response
)
{
// put tree
doctree
.
_id
=
command
.
getDocId
()
+
priv
.
doctree_suffix
;
that
.
addJob
(
"
put
"
,
priv
.
substorage
,
doctree
,
command
.
cloneOption
(),
function
(
response
)
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
(),
"
rev
"
:
revs_info
[
0
].
rev
});
},
function
(
err
){
that
.
error
({
"
status
"
:
409
,
"
statusText
"
:
"
Conflict
"
,
"
error
"
:
"
conflict
"
,
"
message
"
:
"
Document update conflict.
"
,
"
reason
"
:
"
Cannot update document tree
"
});
return
;
}
);
},
function
(
err
)
{
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
File not found
"
,
"
reason
"
:
"
Document was not found
"
});
return
;
}
);
}
else
{
// get previsous document
that
.
addJob
(
"
get
"
,
priv
.
substorage
,
command
.
getDocId
()
+
"
.
"
+
del_rev
,
option
,
function
(
response
)
{
// update tree
revs_info
=
priv
.
postToDocumentTree
(
doctree
,
command
.
getDoc
());
new_doc
=
response
;
delete
new_doc
.
_attachments
;
new_doc
.
_id
=
new_doc
.
_id
+
"
.
"
+
revs_info
[
0
].
rev
;
// post new document version
that
.
addJob
(
"
post
"
,
priv
.
substorage
,
new_doc
,
command
.
cloneOption
(),
function
(
response
)
{
// put tree
doctree
.
_id
=
command
.
getDocId
()
+
priv
.
doctree_suffix
;
that
.
addJob
(
"
put
"
,
priv
.
substorage
,
doctree
,
command
.
cloneOption
(),
function
(
response
)
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
new_doc
.
_id
,
"
rev
"
:
revs_info
[
0
].
rev
});
},
function
(
err
)
{
err
.
message
=
"
Cannot save document revision tree
"
;
that
.
error
(
err
);
}
);
},
function
(
err
){
that
.
error
({
"
status
"
:
409
,
"
statusText
"
:
"
Conflict
"
,
"
error
"
:
"
conflict
"
,
"
message
"
:
"
Document update conflict.
"
,
"
reason
"
:
"
Cannot update document
"
});
return
;
}
);
},
function
(
err
)
{
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
File not found
"
,
"
reason
"
:
"
Document was not found
"
});
return
;
}
);
);
};
f
.
getDocument
=
function
(
docid
,
attmtid
)
{
that
.
addJob
(
"
get
"
,
priv
.
substorage
,
docid
,
option
,
function
(
response
)
{
var
attmt
;
if
(
typeof
response
!==
"
string
"
)
{
if
(
attmtid
!==
undefined
)
{
if
(
response
.
_attachments
!==
undefined
)
{
attmt
=
response
.
_attachments
[
attmtid
];
if
(
attmt
!==
undefined
)
{
prev_rev
=
priv
.
getRevisionFromPosition
(
revs_info
,
attmt
.
revpos
);
f
.
getDocument
(
command
.
getDocId
()
+
"
.
"
+
prev_rev
+
"
/
"
+
attmtid
);
return
;
}
}
else
{
// keep history = update document tree only
}
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Cannot find the attachment
"
,
"
reason
"
:
"
Attachment is missing
"
});
return
;
}
};
if
(
typeof
del_rev
===
"
string
"
)
{
if
(
!
priv
.
checkRevisionFormat
(
del_rev
))
{
that
.
error
({
"
status
"
:
31
,
"
statusText
"
:
"
Wrong Revision Format
"
,
"
error
"
:
"
wrong_revision_format
"
,
"
message
"
:
"
The document previous revision does not match
"
+
"
[0-9]+-[0-9a-zA-Z]+
"
,
"
reason
"
:
"
Previous revision is wrong
"
});
return
;
response
.
_id
=
command
.
getDocId
();
response
.
_rev
=
prev_rev
;
if
(
command
.
getOption
(
"
revs
"
)
===
true
)
{
response
.
_revisions
=
priv
.
revsInfoToHistory
(
revs_info
);
}
if
(
command
.
getOption
(
"
revs_info
"
)
===
true
)
{
response
.
_revs_info
=
revs_info
;
}
if
(
command
.
getOption
(
"
conflicts
"
)
===
true
)
{
response
.
_conflicts
=
priv
.
getLeavesFromDocumentTree
(
doctree
,
prev_rev
);
if
(
response
.
_conflicts
.
length
===
0
)
{
delete
response
.
_conflicts
;
}
}
}
that
.
success
(
response
);
},
function
(
err
)
{
that
.
error
(
err
);
}
// get doctree
that
.
addJob
(
);
};
if
(
command
.
getAttachmentId
()
&&
prev_rev
!==
undefined
)
{
f
.
getDocument
(
command
.
getDocId
()
+
"
.
"
+
prev_rev
+
"
/
"
+
command
.
getAttachmentId
());
}
else
{
f
.
getDocumentTree
();
}
};
/**
* Remove document or attachment.
* Options:
* - {boolean} keep_revision_history To keep the previous revisions
* @method remove
* @param {object} command The JIO command
*/
that
.
remove
=
function
(
command
)
{
var
f
=
{},
del_rev
,
option
,
new_doc
,
revs_info
;
option
=
command
.
cloneOption
();
if
(
option
.
max_retry
===
0
)
{
option
.
max_retry
=
3
;
}
del_rev
=
command
.
getDoc
().
_rev
;
f
.
removeDocument
=
function
(
docid
,
doctree
)
{
if
(
command
.
getOption
(
"
keep_revision_history
"
)
!==
true
)
{
if
(
command
.
getAttachmentId
()
===
undefined
)
{
// update tree
revs_info
=
priv
.
postToDocumentTree
(
doctree
,
command
.
getDoc
(),
true
);
// remove revision
that
.
addJob
(
"
remove
"
,
priv
.
substorage
,
docid
,
option
,
function
()
{
// put tree
doctree
.
_id
=
command
.
getDocId
()
+
priv
.
doctree_suffix
;
that
.
addJob
(
"
put
"
,
priv
.
substorage
,
doctree
,
command
.
cloneOption
(),
function
()
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
(),
"
rev
"
:
revs_info
[
0
].
rev
});
},
function
()
{
that
.
error
({
"
status
"
:
409
,
"
statusText
"
:
"
Conflict
"
,
"
error
"
:
"
conflict
"
,
"
message
"
:
"
Document update conflict.
"
,
"
reason
"
:
"
Cannot update document tree
"
});
return
;
}
);
},
function
()
{
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
File not found
"
,
"
reason
"
:
"
Document was not found
"
});
return
;
}
);
}
else
{
// get previsous document
that
.
addJob
(
"
get
"
,
priv
.
substorage
,
command
.
getDocId
()
+
priv
.
doctree_suffix
,
command
.
getDocId
()
+
"
.
"
+
del_rev
,
option
,
function
(
response
)
{
response
.
_conflicts
=
priv
.
getLeavesFromDocumentTree
(
response
);
if
(
del_rev
===
undefined
)
{
// no revision provided
that
.
error
({
"
status
"
:
409
,
"
statusText
"
:
"
Conflict
"
,
"
error
"
:
"
conflict
"
,
"
message
"
:
"
Document update conflict.
"
,
"
reason
"
:
"
Cannot delete a document without revision
"
});
return
;
}
else
{
// revision provided
if
(
priv
.
isRevisionALeaf
(
response
,
del_rev
)
===
true
){
if
(
typeof
command
.
getAttachmentId
()
===
"
string
"
){
f
.
removeDocument
(
command
.
getDocId
()
+
"
.
"
+
del_rev
+
"
/
"
+
command
.
getAttachmentId
(),
response
);
}
else
{
f
.
removeDocument
(
command
.
getDocId
()
+
"
.
"
+
del_rev
,
response
);
}
}
else
{
that
.
error
({
"
status
"
:
409
,
"
statusText
"
:
"
Conflict
"
,
"
error
"
:
"
conflict
"
,
"
message
"
:
"
Document update conflict.
"
,
"
reason
"
:
"
Trying to remove non-latest revision
"
});
return
;
// update tree
revs_info
=
priv
.
postToDocumentTree
(
doctree
,
command
.
getDoc
());
new_doc
=
response
;
delete
new_doc
.
_attachments
;
new_doc
.
_id
=
new_doc
.
_id
+
"
.
"
+
revs_info
[
0
].
rev
;
// post new document version
that
.
addJob
(
"
post
"
,
priv
.
substorage
,
new_doc
,
command
.
cloneOption
(),
function
()
{
// put tree
doctree
.
_id
=
command
.
getDocId
()
+
priv
.
doctree_suffix
;
that
.
addJob
(
"
put
"
,
priv
.
substorage
,
doctree
,
command
.
cloneOption
(),
function
()
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
new_doc
.
_id
,
"
rev
"
:
revs_info
[
0
].
rev
});
},
function
(
err
)
{
err
.
message
=
"
Cannot save document revision tree
"
;
that
.
error
(
err
);
}
);
},
function
()
{
that
.
error
({
"
status
"
:
409
,
"
statusText
"
:
"
Conflict
"
,
"
error
"
:
"
conflict
"
,
"
message
"
:
"
Document update conflict.
"
,
"
reason
"
:
"
Cannot update document
"
});
return
;
}
);
},
function
(
err
)
{
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Document tree not found, please checkdocument ID
"
,
"
reason
"
:
"
Incorrect document ID
"
});
return
;
function
()
{
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
File not found
"
,
"
reason
"
:
"
Document was not found
"
});
return
;
}
);
);
}
}
};
/**
* Get all documents
* @method allDocs
* @param {object} command The JIO command
*/
that
.
allDocs
=
function
(
command
)
{
setTimeout
(
function
()
{
that
.
error
({
"
status
"
:
405
,
"
statusText
"
:
"
Method Not Allowed
"
,
"
error
"
:
"
method_not_allowed
"
,
"
message
"
:
"
Your are not allowed to use this command
"
,
"
reason
"
:
"
LocalStorage forbids AllDocs command executions
"
});
if
(
typeof
del_rev
===
"
string
"
)
{
if
(
!
priv
.
checkRevisionFormat
(
del_rev
))
{
that
.
error
({
"
status
"
:
31
,
"
statusText
"
:
"
Wrong Revision Format
"
,
"
error
"
:
"
wrong_revision_format
"
,
"
message
"
:
"
The document previous revision does not match
"
+
"
[0-9]+-[0-9a-zA-Z]+
"
,
"
reason
"
:
"
Previous revision is wrong
"
});
};
return
that
;
});
return
;
}
}
// get doctree
that
.
addJob
(
"
get
"
,
priv
.
substorage
,
command
.
getDocId
()
+
priv
.
doctree_suffix
,
option
,
function
(
response
)
{
response
.
_conflicts
=
priv
.
getLeavesFromDocumentTree
(
response
);
if
(
del_rev
===
undefined
)
{
// no revision provided
that
.
error
({
"
status
"
:
409
,
"
statusText
"
:
"
Conflict
"
,
"
error
"
:
"
conflict
"
,
"
message
"
:
"
Document update conflict.
"
,
"
reason
"
:
"
Cannot delete a document without revision
"
});
return
;
}
// revision provided
if
(
priv
.
isRevisionALeaf
(
response
,
del_rev
)
===
true
)
{
if
(
typeof
command
.
getAttachmentId
()
===
"
string
"
)
{
f
.
removeDocument
(
command
.
getDocId
()
+
"
.
"
+
del_rev
+
"
/
"
+
command
.
getAttachmentId
(),
response
);
}
else
{
f
.
removeDocument
(
command
.
getDocId
()
+
"
.
"
+
del_rev
,
response
);
}
}
else
{
that
.
error
({
"
status
"
:
409
,
"
statusText
"
:
"
Conflict
"
,
"
error
"
:
"
conflict
"
,
"
message
"
:
"
Document update conflict.
"
,
"
reason
"
:
"
Trying to remove non-latest revision
"
});
return
;
}
},
function
()
{
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Document tree not found, please checkdocument ID
"
,
"
reason
"
:
"
Incorrect document ID
"
});
return
;
}
);
};
/**
* Get all documents
* @method allDocs
* @param {object} command The JIO command
*/
that
.
allDocs
=
function
()
{
setTimeout
(
function
()
{
that
.
error
({
"
status
"
:
405
,
"
statusText
"
:
"
Method Not Allowed
"
,
"
error
"
:
"
method_not_allowed
"
,
"
message
"
:
"
Your are not allowed to use this command
"
,
"
reason
"
:
"
LocalStorage forbids AllDocs command executions
"
});
});
};
return
that
;
});
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment