+
+class MergeHandler(BaseHandler):
+ allowed_methods = ('POST',)
+
+ @validate_form(forms.MergeRequestForm, 'POST')
+ @hglibrary
+ def create(self, request, form, docid, lib):
+ """Create a new document revision from the information provided by user"""
+
+ target_rev = form.cleaned_data['target_revision']
+
+ doc = lib.document(docid)
+ udoc = doc.take(request.user.username)
+
+ if target_rev == 'latest':
+ target_rev = udoc.revision
+
+ if str(udoc.revision) != target_rev:
+ # user think doesn't know he has an old version
+ # of his own branch.
+
+ # Updating is teorericly ok, but we need would
+ # have to force a refresh. Sharing may be not safe,
+ # 'cause it doesn't always result in update.
+
+ # In other words, we can't lie about the resource's state
+ # So we should just yield and 'out-of-date' conflict
+ # and let the client ask again with updated info.
+
+ # NOTE: this could result in a race condition, when there
+ # are 2 instances of the same user editing the same document.
+ # Instance "A" trying to update, and instance "B" always changing
+ # the document right before "A". The anwser to this problem is
+ # for the "A" to request a merge from 'latest' and then
+ # check the parent revisions in response, if he actually
+ # merge from where he thinks he should. If not, the client SHOULD
+ # update his internal state.
+ return response.EntityConflict().django_response({
+ "reason": "out-of-date",
+ "provided": target_rev,
+ "latest": udoc.revision })
+
+ if not request.user.has_perm('explorer.book.can_share'):
+ # User is not permitted to make a merge, right away
+ # So we instead create a pull request in the database
+ prq = PullRequest(
+ comitter=request.user,
+ document=docid,
+ source_revision = str(udoc.revision),
+ status="N",
+ comment = form.cleaned_data['message'] or '$AUTO$ Document shared.'
+ )
+
+ prq.save()
+ return response.RequestAccepted().django_response(\
+ ticket_status=prq.status, \
+ ticket_uri=reverse("pullrequest_view", args=[prq.id]) )
+
+ if form.cleaned_data['type'] == 'update':
+ # update is always performed from the file branch
+ # to the user branch
+ success, changed = udoc.update(request.user.username)
+
+ if form.cleaned_data['type'] == 'share':
+ success, changed = udoc.share(form.cleaned_data['message'])
+
+ if not success:
+ return response.EntityConflict().django_response({
+ 'reason': 'merge-failure',
+ })
+
+ if not changed:
+ return response.SuccessNoContent().django_response()
+
+ new_udoc = udoc.latest()
+
+ return response.SuccessAllOk().django_response({
+ "name": udoc.id,
+ "parent_user_resivion": udoc.revision,
+ "parent_revision": doc.revision,
+ "revision": ndoc.revision,
+ 'timestamp': ndoc.revision.timestamp,
+ })