f9caf7baf085f2b81a7cb2b0943af85ed4604aa6
[redakcja.git] / apps / api / handlers / manage_handlers.py
1 # -*- encoding: utf-8 -*-
2
3 import logging
4 log = logging.getLogger('platforma.api.manage')
5
6 __author__= "Ɓukasz Rekucki"
7 __date__ = "$2009-09-25 15:49:50$"
8 __doc__ = "Module documentation."
9
10 from piston.handler import BaseHandler
11 from wlrepo import UpdateException
12
13 from api.utils import hglibrary
14 from api.models import PullRequest
15 from api.response import *
16 import datetime
17
18 class PullRequestListHandler(BaseHandler):
19     allowed_methods = ('GET',)
20
21     def read(self, request):
22         if request.user.has_perm('change_pullrequest'):
23             return PullRequest.objects.all()
24         else:
25             return PullRequest.objects.filter(commiter=request.user)
26
27
28 class PullRequestHandler(BaseHandler):
29     allowed_methods = ('GET', 'PUT')
30
31     def read(self, request, prq_id):
32         return PullRequest.objects.get(id=prq_id)
33
34     def update(self, request, prq_id):
35         """Change the status of request"""
36
37         if not request.user.has_perm('change_pullrequest'):
38             return AccessDenied().django_response("Insufficient priviliges")
39         
40         prq = PullRequest.objects.get(id=prq_id)
41
42         if not prq:
43             return EntityNotFound().django_response()
44
45         action = request.PUT.get('action', None)
46
47         if action == 'accept':
48             return self.accept_merge(request.user, prq)
49         elif action == 'reject' and prq.status in ['N', 'R']:
50             return self.reject_merge(request.user, prq)
51         else:
52             return BadRequest().django_response()
53
54
55     @hglibrary
56     def accept_merge(self, user, prq, lib):
57         if prq.status not in ['N', 'E']:
58             return BadRequest().django_response({
59                 'reason': 'invalid-state',
60                 'message': "This pull request is alredy resolved. Can't accept."
61             })
62             
63         src_doc = lib.document_for_rev( prq.source_revision )
64
65         lock = lib.lock()
66         try:
67             if not src_doc.up_to_date():
68                 # This revision is no longer up to date, thus
69                 # it needs to be updated, before push:
70                 #
71                 #  Q: where to put the updated revision ?
72                 #  A: create a special user branch named prq-#prqid
73                 prq_doc = src_doc.take("$prq-%d" % prq.id)
74
75                 # This could be not the first time we try this,
76                 # so the prq_doc could already be there
77                 # and up to date
78
79                 try:
80                     prq_doc = prq_doc.update(user.username)
81                     prq.source_revision = str(prq_doc.revision)
82                     src_doc = prq_doc
83                 except UpdateException, e:
84                     # this can happen only if the merge program
85                     # is misconfigured - try returning an entity conflict
86                     # TODO: put some useful infor here
87                     prq.status = 'E'
88                     prq.save()
89                     return EntityConflict().django_response({
90                         'reason': 'update-failed',
91                         'message': e.message })                
92
93             # check if there are conflicts
94             if src_doc.has_conflict_marks():
95                 prq.status = 'E'
96                 prq.save()
97                 # Now, the user must resolve the conflict
98                 return EntityConflict().django_response({
99                     "reason": "unresolved-conflicts",
100                     "message": "There are conflict in the document. Resolve the conflicts retry accepting."
101                 })
102
103             # So, we have an up-to-date, non-conflicting document
104             changed = src_doc.share(prq.comment)
105
106             if not changed:
107                 # this is actually very bad, but not critical
108                 log.error("Unsynched pull request: %d" % prq.id)                
109
110             # sync state with repository
111             prq.status = 'A'
112             prq.merged_revision = str(src_doc.shared().revision)
113             prq.merged_timestamp = datetime.datetime.now()
114             prq.save()
115
116             return SuccessAllOk().django_response({
117                 'status': prq.status,
118                 'merged_into': prq.merged_revision,
119                 'merged_at': prq.merged_timestamp
120             })
121         finally:
122             lock.release()
123     
124     def reject_merge(self, prq, lib):
125         prq.status = 'R'
126         prq.save()
127
128         return SuccessAllOk().django_response({
129             'status': prq.status
130         })
131         
132
133         
134
135
136         
137