X-Git-Url: https://git.mdrn.pl/redakcja.git/blobdiff_plain/e823ad27e90d5cba05fb2ea8ac2a0d258be2f707..aeb0dad220c5e4da9ddd5e8df9f6b0dc554f513f:/apps/api/handlers/manage_handlers.py diff --git a/apps/api/handlers/manage_handlers.py b/apps/api/handlers/manage_handlers.py index 96159582..f2d41b1b 100644 --- a/apps/api/handlers/manage_handlers.py +++ b/apps/api/handlers/manage_handlers.py @@ -1,25 +1,137 @@ # -*- 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 explorer.models import PullRequest +from api.utils import hglibrary +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) class PullRequestHandler(BaseHandler): - allowed_methods = ('GET',) + allowed_methods = ('GET', 'PUT') def read(self, request, prq_id): - return PullRequest.objects.get(id=prq_id) \ No newline at end of file + return PullRequest.objects.get(id=prq_id) + + def update(self, request, prq_id): + """Change the status of request""" + + if not request.user.has_perm('change_pullrequest'): + return AccessDenied().django_response("Insufficient priviliges") + + prq = PullRequest.objects.get(id=prq_id) + + if not prq: + return EntityNotFound().django_response() + + action = request.PUT.get('action', None) + + if action == 'accept': + return self.accept_merge(request.user, prq) + elif action == 'reject' and prq.status in ['N', 'R']: + return self.reject_merge(request.user, prq) + else: + return BadRequest().django_response() + + + @hglibrary + 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' + prq.save() + + return SuccessAllOk().django_response({ + 'status': prq.status + }) + + + + + + +