source: mergebot/trunk/mergebot/ticket_actions.py

Last change on this file was 31, checked in by retracile, 14 years ago

subprocess.check_call is new in 2.5, use subprocess.call instead

File size: 4.8 KB
Line 
1import socket
2import time
3from subprocess import call
4
5from genshi.builder import tag
6
7from trac.core import implements, Component
8from trac.ticket.api import ITicketActionController
9from trac.ticket.default_workflow import ConfigurableTicketWorkflow
10from trac.web.chrome import add_warning
11
12from BranchActor import BranchActor
13from RebranchActor import RebranchActor
14from MergeActor import MergeActor
15from CheckMergeActor import CheckMergeActor
16from action_logic import is_branchable, is_rebranchable, is_mergeable, is_checkmergeable
17
18class MergebotActionController(Component):
19    """Support branching and merging operations for tickets.
20    """
21    implements(ITicketActionController)
22
23    # ITicketActionController
24    def get_ticket_actions(self, req, ticket):
25        controller = ConfigurableTicketWorkflow(self.env)
26        mergebot_operations = self._get_available_operations(req, ticket)
27        if mergebot_operations:
28            actions_we_handle = controller.get_actions_by_operation_for_req(req,
29                ticket, 'mergebot')
30        else:
31            actions_we_handle = []
32        return actions_we_handle
33
34    def get_all_status(self):
35        return []
36
37    def render_ticket_action_control(self, req, ticket, action):
38        actions = ConfigurableTicketWorkflow(self.env).actions
39        label = actions[action]['name']
40        hint = ''
41
42        control_id = action + '_mergebot_op'
43        mergebot_operations = self._get_available_operations(req, ticket)
44
45        # TODO: allow the configuration to specify a sub-set of permitted
46        # mergebot actions
47        #self.config.get('ticket-workflow', action + '.mergebot')
48
49        self.env.log.debug('render_ticket_action_control ops: %s', mergebot_operations)
50        selected_value = req.args.get(control_id) or mergebot_operations[0]
51        control = tag.select([tag.option(option, selected=(option == selected_value or None)) for option in mergebot_operations], name=control_id, id=control_id)
52
53        return (label, control, hint)
54
55
56    def get_ticket_changes(self, req, ticket, action):
57        control_id = action + '_mergebot_op'
58        selected_value = req.args.get(control_id)
59        add_warning(req, 'Mergebot operation %s will be triggered' % selected_value)
60        return {}
61
62    def daemon_address(self):
63        host = self.env.config.get('mergebot', 'listen.ip')
64        port = self.env.config.getint('mergebot', 'listen.port')
65        return (host, port)
66
67    def start_daemon(self):
68        retval = call(['mergebotdaemon', self.env.path])
69        if retval:
70            raise Exception('mergebotdaemon failed to start (%s)' % retval)
71        time.sleep(1) # bleh
72
73    def _daemon_cmd(self, cmd):
74        self.log.debug('Sending mergebotdaemon: %r' % cmd)
75        try:
76            info_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
77            info_socket.connect(self.daemon_address())
78        except socket.error, e:
79            # if we're refused, try starting the daemon and re-try
80            if e and e[0] == 111:
81                self.log.debug('connection to mergebotdaemon refused, trying to start mergebotdaemon')
82                self.start_daemon()
83            self.log.debug('Resending mergebotdaemon: %r' % cmd)
84            info_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
85            info_socket.connect(self.daemon_address())
86        info_socket.sendall(cmd)
87        self.log.debug('Reading mergebotdaemon response')
88        raw = info_socket.recv(4096)
89        info_socket.close()
90        self.log.debug('Reading mergebotdaemon response was %r' % raw)
91        return raw
92
93    def apply_action_side_effects(self, req, ticket, action):
94        self.log.info('applying mergebot side effect for ticket %s on action %s' % (ticket.id, action))
95        control_id = action + '_mergebot_op'
96        selected_value = req.args.get(control_id)
97
98        result = self._daemon_cmd('ADD %s %s %s %s %s\n\QUIT\n' % (ticket.id, selected_value, ticket['component'], ticket['version'], req.authname or 'anonymous'))
99        if 'OK' not in result:
100            add_warning(req, result) # adding warnings in this method doesn't seem to work
101
102    def _get_available_operations(self, req, ticket):
103        mergebot_ops = []
104        if req.perm.has_permission("MERGEBOT_BRANCH"):
105            if is_branchable(ticket):
106                mergebot_ops.append('branch')
107            if is_rebranchable(ticket):
108                mergebot_ops.append('rebranch')
109        if is_checkmergeable(ticket) and req.perm.has_permission('MERGEBOT_VIEW'):
110            mergebot_ops.append('checkmerge')
111        if ticket['version'].startswith("#"):
112            may_merge = req.perm.has_permission("MERGEBOT_MERGE_TICKET")
113        else:
114            may_merge = req.perm.has_permission("MERGEBOT_MERGE_RELEASE")
115        if may_merge and is_mergeable(ticket):
116            mergebot_ops.append('merge')
117        return mergebot_ops
Note: See TracBrowser for help on using the repository browser.