Index: trac/db_default.py
===================================================================
--- trac/db_default.py	(revision 921)
+++ trac/db_default.py	(working copy)
@@ -21,7 +21,7 @@
 
 
 # Database version identifier. Used for automatic upgrades.
-db_version = 7
+db_version = 8
 
 def __mkreports(reps):
     """Utility function used to create report data in same syntax as the
@@ -88,8 +88,8 @@
         reporter        text,
         cc              text,           -- email addresses to notify
         url             text,           -- url related to this ticket
-        version         text,           -- 
-        milestone       text,           -- 
+        version         text,           --
+        milestone       text,           --
         status          text,
         resolution      text,
         summary         text,           -- one-line summary
@@ -119,7 +119,7 @@
         description     text
 );
 CREATE TABLE permission (
-        username        text,           -- 
+        username        text,           --
         action          text,           -- allowable activity
         UNIQUE(username,action)
 );
@@ -188,13 +188,13 @@
 """,
 """
 SELECT p.value AS __color__,
-   id AS ticket, summary, component, version, milestone, severity, 
+   id AS ticket, summary, component, version, milestone, severity,
    (CASE status WHEN 'assigned' THEN owner||' *' ELSE owner END) AS owner,
    time AS created,
    changetime AS _changetime, description AS _description,
    reporter AS _reporter
   FROM ticket t, enum p
-  WHERE status IN ('new', 'assigned', 'reopened') 
+  WHERE status IN ('new', 'assigned', 'reopened')
 AND p.name = t.priority AND p.type = 'priority'
   ORDER BY p.value, milestone, severity, time
 """),
@@ -210,13 +210,13 @@
 """
 SELECT p.value AS __color__,
    version AS __group__,
-   id AS ticket, summary, component, version, severity, 
+   id AS ticket, summary, component, version, severity,
    (CASE status WHEN 'assigned' THEN owner||' *' ELSE owner END) AS owner,
    time AS created,
    changetime AS _changetime, description AS _description,
    reporter AS _reporter
   FROM ticket t, enum p
-  WHERE status IN ('new', 'assigned', 'reopened') 
+  WHERE status IN ('new', 'assigned', 'reopened')
 AND p.name = t.priority AND p.type = 'priority'
   ORDER BY (version IS NULL),version, p.value, severity, time
 """),
@@ -232,13 +232,13 @@
 """
 SELECT p.value AS __color__,
    milestone||' Release' AS __group__,
-   id AS ticket, summary, component, version, severity, 
+   id AS ticket, summary, component, version, severity,
    (CASE status WHEN 'assigned' THEN owner||' *' ELSE owner END) AS owner,
    time AS created,
    changetime AS _changetime, description AS _description,
    reporter AS _reporter
   FROM ticket t, enum p
-  WHERE status IN ('new', 'assigned', 'reopened') 
+  WHERE status IN ('new', 'assigned', 'reopened')
 AND p.name = t.priority AND p.type = 'priority'
   ORDER BY (milestone IS NULL),milestone, p.value, severity, time
 """),
@@ -284,24 +284,24 @@
 """
 SELECT p.value AS __color__,
    t.milestone AS __group__,
-   (CASE status 
+   (CASE status
       WHEN 'closed' THEN 'color: #777; background: #ddd; border-color: #ccc;'
-      ELSE 
+      ELSE
         (CASE owner WHEN '$USER' THEN 'font-weight: bold' END)
     END) AS __style__,
-   id AS ticket, summary, component, status, 
+   id AS ticket, summary, component, status,
    resolution,version, severity, priority, owner,
    changetime AS modified,
    time AS _time,reporter AS _reporter
   FROM ticket t,enum p
   WHERE p.name=t.priority AND p.type='priority'
-  ORDER BY (milestone IS NULL), milestone DESC, (status = 'closed'), 
+  ORDER BY (milestone IS NULL), milestone DESC, (status = 'closed'),
         (CASE status WHEN 'closed' THEN modified ELSE -p.value END) DESC
 """),
 #----------------------------------------------------------------------------
 ('My Tickets',
 """
-This report demonstrates the use of the automatically set 
+This report demonstrates the use of the automatically set
 $USER dynamic variable, replaced with the username of the
 logged in user when executed.
 """,
@@ -313,7 +313,7 @@
    changetime AS _changetime, description AS _description,
    reporter AS _reporter
   FROM ticket t, enum p
-  WHERE t.status IN ('new', 'assigned', 'reopened') 
+  WHERE t.status IN ('new', 'assigned', 'reopened')
 AND p.name = t.priority AND p.type = 'priority' AND owner = '$USER'
   ORDER BY (status = 'assigned') DESC, p.value, milestone, severity, time
 """),
@@ -325,17 +325,17 @@
 """,
 """
 SELECT p.value AS __color__,
-   (CASE owner 
-     WHEN '$USER' THEN 'My Tickets' 
-     ELSE 'Active Tickets' 
+   (CASE owner
+     WHEN '$USER' THEN 'My Tickets'
+     ELSE 'Active Tickets'
     END) AS __group__,
-   id AS ticket, summary, component, version, milestone, severity, 
+   id AS ticket, summary, component, version, milestone, severity,
    (CASE status WHEN 'assigned' THEN owner||' *' ELSE owner END) AS owner,
    time AS created,
    changetime AS _changetime, description AS _description,
    reporter AS _reporter
   FROM ticket t, enum p
-  WHERE status IN ('new', 'assigned', 'reopened') 
+  WHERE status IN ('new', 'assigned', 'reopened')
 AND p.name = t.priority AND p.type = 'priority'
   ORDER BY (owner = '$USER') DESC, p.value, milestone, severity, time
 """))
@@ -352,7 +352,7 @@
                 ('component2', 'somebody'))),
            ('milestone',
              ('name', 'time'),
-               (('', 0), 
+               (('', 0),
                 ('milestone1', 0),
                 ('milestone2', 0),
                 ('milestone3', 0),
@@ -446,4 +446,4 @@
   ('notification', 'smtp_replyto', 'trac@localhost'),
   ('timeline', 'changeset_show_files', 'false'),
   ('timeline', 'changeset_files_count', 3))
-   
+
Index: trac/Ticket.py
===================================================================
--- trac/Ticket.py	(revision 921)
+++ trac/Ticket.py	(working copy)
@@ -29,6 +29,7 @@
 import util
 from Module import Module
 from WikiFormatter import wiki_to_html
+from Wiki import wiki_to_oneliner
 from Notify import TicketNotifyEmail
 
 __all__ = ['Ticket', 'NewticketModule', 'TicketModule']
@@ -37,7 +38,7 @@
 class Ticket(UserDict):
     std_fields = ['time', 'component', 'severity', 'priority', 'milestone',
                   'reporter', 'owner', 'cc', 'url', 'version', 'status', 'resolution',
-                  'keywords', 'summary', 'description', 'reporter']
+                  'keywords', 'summary', 'description']
 
     def __init__(self, *args):
         UserDict.__init__(self)
@@ -78,6 +79,11 @@
         if rows:
             for r in rows:
                 self['custom_' + r[0]] = r[1]
+
+        self['dependson'] = self.get_dependson_list(db, id)
+        self['blocks'] = self.get_blocks_list(db, id)
+
+
         self._forget_changes()
 
     def populate(self, dict):
@@ -87,6 +93,9 @@
         for name in names:
             self[name] = dict.get(name, '')
 
+        self['blocks'] = dict.get('blocks','');
+        self['dependson'] = dict.get('dependson','');
+
         # We have to do an extra trick to catch unchecked checkboxes
         checkboxes = filter(lambda n: n[:9] == 'checkbox_', dict.keys())
         for name in ['custom_' + n[9:] for n in checkboxes]:
@@ -103,7 +112,7 @@
         self['time'] = now
         self['changetime'] = now
 
-        std_fields = filter(lambda n: n[:7] != 'custom_', self.keys())
+        std_fields = filter(lambda n: n[:7] != 'custom_' and n != 'dependson' and n != 'blocks' , self.keys())
         custom_fields = filter(lambda n: n[:7] == 'custom_', self.keys())
         std_values = map(lambda n, self=self: self[n], std_fields)
         nstr = string.join(std_fields, ',')
@@ -114,6 +123,15 @@
         for name in custom_fields:
             cursor.execute('INSERT INTO ticket_custom(ticket,name,value)'
                            ' VALUES(%d, %s, %s)', id, name[7:], self[name])
+        # Dependencies
+        cursor.execute('DELETE FROM dependencies WHERE dependson=%s',id)
+        cursor.executemany ('INSERT INTO dependencies (dependson,blocks) '
+                           "VALUES (" + str(id) + ",%s)",
+                           self['blocks'])
+        cursor.execute('DELETE FROM dependencies WHERE blocks=%s',id)
+        cursor.executemany ('INSERT INTO dependencies (blocks,dependson) '
+                           "VALUES (" + str(id) + ",%s)",
+                           self['dependson'])
         db.commit()
         self['id'] = id
         self._forget_changes()
@@ -141,22 +159,38 @@
                 cursor.execute('SELECT owner FROM component '
                                'WHERE name=%s', self['component'])
                 self['owner'] = cursor.fetchone()[0]
-           
 
+
         for name in self._old.keys():
             if name[:7] == 'custom_':
                 fname = name[7:]
                 cursor.execute('REPLACE INTO ticket_custom(ticket,name,value)'
                                ' VALUES(%s, %s, %s)', id, fname, self[name])
+            elif name == 'dependson':
+                fname = name
+                cursor.execute('DELETE FROM dependencies WHERE blocks=%s',id)
+                if len(self[name]) > 0:
+                    cursor.executemany ('INSERT INTO dependencies (blocks,dependson) '
+                                        "VALUES (" + str(id) + ",%s)",
+                                        string.split(self[name],','))
+            elif name == 'blocks':
+                fname = name
+                cursor.execute('DELETE FROM dependencies WHERE dependson=%s',id)
+                if len(self[name]) > 0:
+                    cursor.executemany ('INSERT INTO dependencies (dependson,blocks) '
+                                    "VALUES (" + str(id) + ",%s)",
+                                    string.split(self[name],','))
             else:
                 fname = name
                 cursor.execute ('UPDATE ticket SET %s=%s WHERE id=%s',
                                 fname, self[name], id)
 
-            cursor.execute ('INSERT INTO ticket_change '
-                            '(ticket, time, author, field, oldvalue, newvalue) '
-                            'VALUES (%s, %s, %s, %s, %s, %s)',
-                            id, when, author, fname, self._old[name], self[name])
+            # Weasle out on this one.
+            if fname != 'dependson' and fname != 'blocks':
+                cursor.execute ('INSERT INTO ticket_change '
+                                '(ticket, time, author, field, oldvalue, newvalue) '
+                                'VALUES (%s, %s, %s, %s, %s, %s)',
+                                id, when, author, fname, self._old[name], self[name])
         if comment:
             cursor.execute ('INSERT INTO ticket_change '
                             '(ticket,time,author,field,oldvalue,newvalue) '
@@ -195,7 +229,38 @@
             log.append((int(row[0]), row[1], row[2], row[3] or '', row[4] or ''))
         return log
 
+    def get_blocks_list(self, db, id):
+        # Determine Tickets this Ticket blocks
+        cursor = db.cursor ()
+        cursor.execute( 'SELECT blocks FROM dependencies WHERE dependson=%s', id )
 
+        blocks = [] # List of Tickets the current Ticket blocks
+        while 1:
+            row = cursor.fetchone()
+            if not row:
+                break
+            blocks.append(row['blocks']);
+
+        cursor.close ()
+
+        return blocks
+
+    def get_dependson_list(self, db, id):
+        # Determine Tickets this Ticket depends on
+        cursor = db.cursor ()
+        cursor.execute( 'SELECT dependson FROM dependencies WHERE blocks=%s', id )
+
+        dependson = [] # List of Tickets the current Ticket deepnds on
+        while 1:
+            row = cursor.fetchone()
+            if not row:
+                break
+            dependson.append(row['dependson']);
+
+        cursor.close ()
+
+        return dependson
+
 def get_custom_fields(env):
     cfg = env.get_config_items('ticket-custom')
     if not cfg:
@@ -387,6 +452,28 @@
                                            self.env, self.db))
         self.req.hdf.setValue('ticket.opened', time.strftime('%c', time.localtime(int(ticket['time']))))
 
+        # Dependencies
+        dependson = []
+        dependson_displ = []
+        for i in range(len(ticket['dependson'])):
+            dependson_displ.append( '#' + str(ticket['dependson'][i]) )
+            dependson.append( str(ticket['dependson'][i]) )
+        self.req.hdf.setValue('ticket.dependson_displ',
+                              wiki_to_oneliner(string.join(dependson_displ, ', '),
+                                            self.req.hdf, self.env, self.db))
+        self.req.hdf.setValue('ticket.dependson',
+                              string.join(dependson, ','))
+        blocks = []
+        blocks_displ = []
+        for i in range(len(ticket['blocks'])):
+            blocks_displ.append( '#' + str(ticket['blocks'][i]) )
+            blocks.append( str(ticket['blocks'][i]) )
+        self.req.hdf.setValue('ticket.blocks_displ',
+                              wiki_to_oneliner(string.join(blocks_displ, ', '),
+                                            self.req.hdf, self.env, self.db))
+        self.req.hdf.setValue('ticket.blocks',
+                              string.join(blocks, ','))
+
         changelog = ticket.get_changelog(self.db)
         curr_author = None
         curr_date   = 0
@@ -437,6 +524,16 @@
             self.req.hdf.setValue('ticket.action', action)
             reporter_id = self.args.get('author')
             comment = self.args.get('comment')
+            if self.args.has_key('dependson'):
+                ticket['dependson'] = string.split(self.args.get('dependson'),',')
+            else:
+                ticket['dependson'] = []
+
+            if self.args.has_key('blocks'):
+                ticket['blocks'] = string.split(self.args.get('blocks'),',')
+            else:
+                ticket['blocks'] = []
+
             if comment:
                 self.req.hdf.setValue('ticket.comment', comment)
                 # Wiki format a preview of comment
Index: templates/ticket.cs
===================================================================
--- templates/ticket.cs	(revision 921)
+++ templates/ticket.cs	(working copy)
@@ -41,8 +41,10 @@
   call:ticketprop("Version", "version", ticket.version, 0) ?><?cs
   call:ticketprop("Resolution", "resolution", ticket.resolution, 0) ?><?cs
   call:ticketprop("Milestone", "milestone", ticket.milestone, 0) ?><?cs
+  call:ticketprop("Keywords", "keywords", ticket.keywords, 0) ?><?cs
+  call:ticketprop("Depends On", "dependson", ticket.dependson_displ, 0) ?><?cs
   set:last_prop = #1 ?><?cs
-  call:ticketprop("Keywords", "keywords", ticket.keywords, 0) ?><?cs
+  call:ticketprop("Blocks", "blocks", ticket.blocks_displ, 0) ?><?cs
   set:last_prop = #0 ?>
  </tr></table><?cs if ticket.custom.0.name ?>
  <hr />
@@ -178,6 +180,10 @@
    <label for="keywords">Keywords:</label>
    <input type="text" id="keywords" name="keywords" size="20"
        value="<?cs var:ticket.keywords ?>" />
+   <br />
+   <label for="dependson">Depends On:</label>
+   <input type="text" id="dependson" name="dependson" size="20"
+       value="<?cs var:ticket.dependson ?>" />
   </div>
   <div class="col2">
    <label for="priority">Priority:</label><?cs
@@ -189,6 +195,10 @@
      var:ticket.owner ?>" disabled="disabled" /><br />
    <label for="cc">Cc:</label>
    <input type="text" id="cc" name="cc" size="30" value="<?cs var:ticket.cc ?>" />
+   <br />
+   <label for="blocks">Blocks:</label>
+   <input type="text" id="blocks" name="blocks" size="20"
+       value="<?cs var:ticket.blocks ?>" />
   </div>
   <div class="custom">
    <?cs call:ticket_custom_props(ticket) ?>
@@ -233,7 +243,7 @@
  <div class="buttons">
   <input type="reset" value="Reset" />&nbsp;
   <input type="submit" name="preview" value="Preview" />&nbsp;
-  <input type="submit" value="Submit changes" /> 
+  <input type="submit" value="Submit changes" />
  </div>
 </form>
 <?cs /if ?>
Index: templates/newticket.cs
===================================================================
--- templates/newticket.cs	(revision 921)
+++ templates/newticket.cs	(working copy)
@@ -2,7 +2,7 @@
 <?cs include "header.cs" ?>
 <?cs include "macros.cs" ?>
 <script type="text/javascript">
-addEvent(window, 'load', function() { document.getElementById('summary').focus()}); 
+addEvent(window, 'load', function() { document.getElementById('summary').focus()});
 </script>
 
 <div id="ctxtnav" class="nav"></div>
@@ -52,6 +52,10 @@
    <label for="keywords">Keywords:</label>
    <input type="text" id="keywords" name="keywords" size="20"
        value="<?cs var:ticket.keywords ?>" />
+   <br />
+   <label for="dependson">Depends On:</label>
+   <input type="text" id="dependson" name="dependson" size="20"
+       value="<?cs var:ticket.dependson ?>" />
   </div>
   <div class="col2">
    <label for="priority">Priority:</label><?cs
@@ -63,6 +67,10 @@
      var:newticket.owner ?>" /><br />
    <label for="cc">Cc:</label>
    <input type="text" id="cc" name="cc" size="30" value="<?cs var:newticket.cc ?>" />
+   <br />
+   <label for="blocks">Blocks:</label>
+   <input type="text" id="blocks" name="blocks" size="20"
+       value="<?cs var:ticket.blocks ?>" />
   </div>
   <div class="custom">
    <?cs call:ticket_custom_props(ticket) ?>
