예제 #1
0
 def _prepare_links(self, tkt):
     links = TicketLinks(self.env, tkt)
     links.blocking = set(
         int(n) for n in self.NUMBERS_RE.findall(tkt['blocking'] or ''))
     links.blocked_by = set(
         int(n) for n in self.NUMBERS_RE.findall(tkt['blockedby'] or ''))
     return links
예제 #2
0
    def _depgraph_all(self, req):
        """
		Produces a dependency graph including all tickets, even those which
		do not block other tickets and are not blocked by other tickets
		"""
        result = ""
        db = self.env.get_db_cnx()
        cursor = db.cursor()

        sql = "SELECT id, priority, summary FROM ticket WHERE status != 'closed' ORDER BY id DESC;"
        cursor.execute(sql)
        tickets = cursor.fetchall()

        for ticket in tickets:
            links = TicketLinks(self.env, int(ticket[0]))
            blockers = links.blocked_by
            if len(blockers) == 0 and len(links.blocking) == 0:
                # Orphan ticket, not blocked and not blocking, skip
                continue

            bgcolor, border = self._get_color(ticket[1])
            result += "\"" + str(ticket[0]) + "\" [ URL=\"" \
              + req.href.ticket(int(ticket[0])) \
              + "\" fontcolor=\"#bb0000\" fillcolor=\"" + bgcolor \
              + "\" color=\"" + border \
              + "\" tooltip=\"" + ticket[2].replace('"', '"') \
              + "\" ]\n"
            # Use blocked_by() from mastertickets.model.TicketLinks
            for blocker in blockers:
                #				result += "\"%s\" -> \"%s\"" % (str(ticket[0]), str(blocker))
                result += "\"%s\" -> \"%s\"" % (str(blocker), str(ticket[0]))

        return result
예제 #3
0
    def post_process_request(self, req, template, data, content_type):
        from mastertickets.model import TicketLinks
        if req.path_info.startswith('/ticket'):
            ticket_id = req.path_info[8:]
            links = TicketLinks(self.env, ticket_id)
            if len(links.blocked_by) > 0:
                depgraph_href = req.href.depgraph(ticket_id)
            else:
                depgraph_href = None
            add_ctxtnav(req, "Dependency Graph", depgraph_href,
                        "Dependency Graph")
        if req.path_info.startswith('/query'):
            query = {}
            percent_enc = re.compile('\%[0-9a-fA-F]')
            for line in data['query'].to_string().splitlines():
                if '=' in line:
                    if line.startswith('query:?'):
                        line = line[7:]
                    line = re.sub(percent_enc, self._unescape, line)
                    key, value = line.split('=')
                    if key in query:
                        query[key].append(value)
                    else:
                        query[key] = [value]

            add_ctxtnav(
                req,
                tag.a('Dependency Graph', href=req.href('depgraph', **query)))

        return template, data, content_type
예제 #4
0
    def validate_ticket(self, req, ticket):
        tid = ticket.id
        links = self._prepare_links(ticket)

        if req.args.get('action') == 'resolve' and \
                req.args.get('action_resolve_resolve_resolution') == 'fixed':
            for i in links.blocked_by:
                if Ticket(self.env, i)['status'] != 'closed':
                    yield None, "Ticket #%s is blocking this ticket" % i

        # Check that ticket does not have itself as a blocker
        if tid in links.blocking | links.blocked_by:
            yield 'blocked_by', "This ticket is blocking itself"
            return

        # Check that there aren't any blocked_by in blocking or their parents
        blocking = links.blocking.copy()
        while len(blocking) > 0:
            if len(links.blocked_by & blocking) > 0:
                yield 'blocked_by', "This ticket has circular dependencies"
                return
            new_blocking = set()
            for link in blocking:
                tmp_tkt = Ticket(self.env, link)
                new_blocking |= TicketLinks(self.env, tmp_tkt).blocking
            blocking = new_blocking

        for field in ('blocking', 'blockedby'):
            try:
                ids = self.NUMBERS_RE.findall(ticket[field] or '')
                for tid in ids[:]:
                    for _ in self.env.db_query(
                            """
                            SELECT id FROM ticket WHERE id=%s
                            """, (tid, )):
                        break
                    else:
                        ids.remove(tid)
                ticket[field] = ', '.join(sorted(ids, key=lambda x: int(x)))
            except Exception, e:
                self.log.debug("MasterTickets: Error parsing %s \"%s\": %s",
                               field, ticket[field], e)
                yield field, "Not a valid list of ticket IDs"
예제 #5
0
    def _depgraph(self, req, base, depth):
        try:
            ticket = int(base)
        except ValueError:
            if base.startswith('query:'):
                base = base[6:]
            elif base.startswith('report:'):
                req.perm.assert_permission('REPORT_VIEW')

                db = self.env.get_db_cnx()
                cursor = db.cursor()
                cursor.execute('SELECT query FROM report WHERE id=%s;',
                               int(base[7:]))
                base = ''.join([line.strip() for line in cursor.splitlines()])
            else:
                raise TracError('Unknown ticket identifier.')

            from trac.ticket.query import Query
            query = Query.from_string(self.env, base, max=0)
            return ''.join(self._depgraph(req, ticket['id'], -1) \
                for ticket in query.execute(req))

        self.log.debug('called depgraph(%s, %s)' % (str(ticket), str(depth)))
        if ticket in self._seen_tickets:
            return ''

        self._seen_tickets.append(ticket)
        links = TicketLinks(self.env, ticket)
        blockers = links.blocked_by
        if depth >= 0 and (len(blockers) == 0 and len(links.blocking) == 0):
            # Orphan ticket, not belonging to query, skip
            return ''

        db = self.env.get_db_cnx()
        cursor = db.cursor()
        sql = ("SELECT summary, priority FROM ticket WHERE id = %s;" \
          % (str(ticket)))
        cursor.execute(sql)
        summary, priority = cursor.fetchone()

        if depth == 0:
            bgcolor = "#cceecc"
            border = "#00cc00"
        else:
            bgcolor, border = self._get_color(priority)

        depth = (depth > -1 and depth or 0)

        result = "\"" + str(ticket) + "\" [ URL=\"" \
          + req.href.ticket(int(ticket)) \
          + "\" fillcolor=\"" + bgcolor + "\" color=\"" + border \
          + "\" fontcolor=\"#bb0000\" tooltip=\"" \
          + summary.replace('"', '"') + "\" ]\n"
        if self._maxdepth > 0 and depth >= self._maxdepth:
            return result

        # Use blocked_by() from mastertickets.model.TicketLinks
        blockers = TicketLinks(self.env, ticket).blocked_by
        for blocker in blockers:
            result += self._depgraph(req, int(blocker), depth + 1)
            #			result += "\"%s\" -> \"%s\"\n" % (str(ticket), str(blocker))
            result += "\"%s\" -> \"%s\"\n" % (str(blocker), str(ticket))

        return result
예제 #6
0
 def ticket_deleted(self, tkt):
     links = TicketLinks(self.env, tkt)
     links.blocking = set()
     links.blocked_by = set()
     links.save('trac', "Ticket #%s deleted" % tkt.id)
예제 #7
0
 def ticket_deleted(self, tkt):
     links = TicketLinks(self.env, tkt)
     links.blocking = set()
     links.blocked_by = set()
     links.save('trac', "Ticket #%s deleted" % tkt.id)
예제 #8
0
 def _prepare_links(self, tkt):
     links = TicketLinks(self.env, tkt)
     links.blocking = set(int(n) for n in self.NUMBERS_RE.findall(tkt['blocking'] or ''))
     links.blocked_by = set(int(n) for n in self.NUMBERS_RE.findall(tkt['blockedby'] or ''))
     return links