X-Git-Url: https://git.mdrn.pl/redakcja.git/blobdiff_plain/46fdcc29313a6c0dd897b8060335061f433897fd..2fc23bdb4ec0198ab47ce73e7b5287375ae68a12:/apps/api/handlers/manage_handlers.py diff --git a/apps/api/handlers/manage_handlers.py b/apps/api/handlers/manage_handlers.py index b3e2760b..f2d41b1b 100644 --- a/apps/api/handlers/manage_handlers.py +++ b/apps/api/handlers/manage_handlers.py @@ -1,20 +1,25 @@ # -*- encoding: utf-8 -*- +import logging +log = logging.getLogger('platforma.api.manage') + __author__= "Łukasz Rekucki" __date__ = "$2009-09-25 15:49:50$" __doc__ = "Module documentation." -from piston.handler import BaseHandler, AnonymousBaseHandler +from piston.handler import BaseHandler +from wlrepo import UpdateException from api.utils import hglibrary -from explorer.models import PullRequest +from api.models import PullRequest from api.response import * +import datetime class PullRequestListHandler(BaseHandler): allowed_methods = ('GET',) def read(self, request): - if request.user.has_perm('explorer.book.can_share'): + if request.user.has_perm('change_pullrequest'): return PullRequest.objects.all() else: return PullRequest.objects.filter(commiter=request.user) @@ -29,7 +34,7 @@ class PullRequestHandler(BaseHandler): def update(self, request, prq_id): """Change the status of request""" - if not request.user.has_perm('explorer.document.can_share'): + if not request.user.has_perm('change_pullrequest'): return AccessDenied().django_response("Insufficient priviliges") prq = PullRequest.objects.get(id=prq_id) @@ -37,36 +42,84 @@ class PullRequestHandler(BaseHandler): if not prq: return EntityNotFound().django_response() - action = request.PUT.get('action', None) - if action == 'accept' and prq.status == 'N': - return self.accept_merge(prq) + if action == 'accept': + return self.accept_merge(request.user, prq) elif action == 'reject' and prq.status in ['N', 'R']: - return self.reject_merge(prq) + return self.reject_merge(request.user, prq) else: return BadRequest().django_response() @hglibrary - def accept_merge(self, prq, lib): - doc = lib.document( prq.document ) - udoc = doc.take( prq.comitter.username ) - success, changed = udoc.share(prq.comment) - - if not success: - return EntityConflict().django_response() - - doc = doc.latest() - - prq.status = 'A' - prq.merged_revisions = unicode(doc.revision) - prq.save() - - return SuccessAllOk().django_response({ - 'status': prq.status - }) - + def accept_merge(self, user, prq, lib): + if prq.status not in ['N', 'E']: + return BadRequest().django_response({ + 'reason': 'invalid-state', + 'message': "This pull request is alredy resolved. Can't accept." + }) + + src_doc = lib.document_for_revision( prq.source_revision ) + + lock = lib.lock() + try: + if not src_doc.up_to_date(): + # This revision is no longer up to date, thus + # it needs to be updated, before push: + # + # Q: where to put the updated revision ? + # A: create a special user branch named prq-#prqid + prq_doc = src_doc.take("$prq-%d" % prq.id) + + # This could be not the first time we try this, + # so the prq_doc could already be there + # and up to date + + try: + prq_doc = prq_doc.update(user.username) + prq.source_revision = str(prq_doc.revision) + src_doc = prq_doc + except UpdateException, e: + # this can happen only if the merge program + # is misconfigured - try returning an entity conflict + # TODO: put some useful infor here + prq.status = 'E' + prq.save() + return EntityConflict().django_response({ + 'reason': 'update-failed', + 'message': e.message }) + + # check if there are conflicts + if src_doc.has_conflict_marks(): + prq.status = 'E' + prq.save() + # Now, the user must resolve the conflict + return EntityConflict().django_response({ + "reason": "unresolved-conflicts", + "message": "There are conflict in the document. Resolve the conflicts retry accepting." + }) + + # So, we have an up-to-date, non-conflicting document + changed = src_doc.share(prq.comment) + + if not changed: + # this is actually very bad, but not critical + log.error("Unsynched pull request: %d" % prq.id) + + # sync state with repository + prq.status = 'A' + prq.merged_revision = str(src_doc.shared().revision) + prq.merged_timestamp = datetime.datetime.now() + prq.save() + + return SuccessAllOk().django_response({ + 'status': prq.status, + 'merged_into': prq.merged_revision, + 'merged_at': prq.merged_timestamp + }) + finally: + lock.release() def reject_merge(self, prq, lib): prq.status = 'R'