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