Commits

Alex Willmer committed 713fc94

Check for existence of linked tickets, warn on validate, discard on display

  • Participants
  • Parent commits 83593df
  • Branches ticket-links-trunk

Comments (0)

Files changed (3)

File trac/ticket/links.py

 #
 # Author: Joachim Hoessler <hoessler@gmail.com>
 
+from trac.resource import ResourceNotFound
 from trac.ticket.api import (ITicketLinkController, ITicketManipulator,
                              TicketSystem)
 from trac.ticket.model import Ticket
         else:
             return TicketSystem(self.env).default_copy_fields
     
+    def get_validator(self, end):
+        return self._validators.get(end)
+        
     def prepare_ticket(self, req, ticket, fields, actions):
         pass
         
         action = req.args.get('action')
         ticket_system = TicketSystem(self.env)
         
-        for end, validator in self._validators.items():
+        for end in ticket_system.link_ends_map:
+            check = self.validate_links_exist(ticket, end)
+            if check:
+                yield None, check
+                continue
+            
+            validator_name = self.get_validator(end)
+            if validator_name == 'no_cycle':
+                validator = self.validate_no_cycle
+            elif validator_name == 'parent_child' and end == self.PARENT_END:
+                validator = self.validate_parent
+            else:
+                validator = self.validate_any
+            
             check = validator(ticket, end)
             if check:
                 yield None, check
             
-        for end in self._blockers:
-            if action == 'resolve':
+            if action == 'resolve' and self.is_blocker(end):
                 blockers = self.find_blockers(ticket, end, [])
                 if blockers:
                     blockers_str = ', '.join('#%s' % x for x in uniq(blockers))
                            % (end,  blockers_str))
                     yield None, msg
     
+    def validate_links_exist(self, ticket, end):
+        ticket_system = TicketSystem(self.env)
+        links = ticket_system.parse_links(ticket[end])
+        bad_links = []
+        for link in links:
+            try:
+                tkt = Ticket(self.env, link)
+            except ResourceNotFound:
+                bad_links.append(link)
+        if bad_links:
+            return ("Tickets linked in '%s' do not exist: [%s]" 
+                    % (end, ', '.join('#%s' % link for link in bad_links)))
+          
     def validate_no_cycle(self, ticket, end):
         cycle = self.find_cycle(ticket, end, [])
         if cycle != None:
             return "Multiple links in '%s': #%s -> [%s]" \
                    % (self.render_end(end), ticket.id, parents_str)
     
+    def validate_any(self, ticket, end):
+        return None
+    
     def _get_links_config(self):
         links = []
         labels = {}
                 labels[end2] = label2
             
             validator = config.get(name + '.validator')
-            if validator == 'no_cycle':
-                validators[end1] = self.validate_no_cycle
+            if validator:
+                validators[end1] = validator
                 if end2:
-                    validators[end2] = self.validate_no_cycle
-            elif validator == 'parent_child':
-                if end1 == self.PARENT_END:
-                    validators[end1] = self.validate_parent
-                elif end2 == self.PARENT_END:
-                    validators[end2] = self.validate_parent
-            
+                    validators[end2] = validator
+                
             blockers[end1] = config.getbool(end1 + '.blocks', default=False)
             if end2:
                 blockers[end2] = config.getbool(end2 + '.blocks', default=False)

File trac/ticket/tests/links.py

         self.assertEqual(len(tickets), 1)
         self.assertEqual(tickets[0]['id'], 1)
     
-
+    def test_validator_links_exists(self):
+        ticket1 = self._create_a_ticket()
+        ticket1.insert()
+        ticket2 = self._create_a_ticket()
+        ticket2['dependson'] = '#1'
+        links_provider = LinksProvider(self.env)
+        issues = links_provider.validate_ticket(self.req, ticket2)
+        self.assertEquals(sum(1 for _ in issues), 0)
+        ticket2['dependson'] = '#404'
+        issues = links_provider.validate_ticket(self.req, ticket2)
+        self.assertEquals(sum(1 for _ in issues), 1)
+        
     def test_validator_no_cyle(self):
         ticket1 = self._create_a_ticket()
         ticket1.insert()

File trac/ticket/web_ui.py

         new_linked = [(field['label'], self._other_end(field, link_ends_map))
                       for field in link_fields]
         
+        linked_tickets = []
+        linked_rejects = []
+        for field in link_fields:
+            for tkt_id in ticket_sys.parse_links(ticket[field['name']]):
+                try:
+                    tkt = Ticket(self.env, tkt_id)
+                    linked_tickets.append(tkt)
+                except ResourceNotFound:
+                    linked_rejects.append(tkt_id)
+                
         return {'ticket': ticket,
                 'linked_tickets': 
                         [(field['label'], 
-                          format_to_oneliner(self.env, context, '#%s' % tkt_id), 
-                          Ticket(self.env, tkt_id)) 
-                         for field in link_fields
-                         for tkt_id in ticket_sys
-                                            .parse_links(ticket[field['name']])
-                         ],
+                          format_to_oneliner(self.env, context, 
+                                             '#%s' % tkt.id),
+                          tkt)
+                         for tkt in linked_tickets],
                 'newlinked_options': new_linked,
                 'context': context,
                 'preserve_newlines': self.must_preserve_newlines}