class TracDatabase(object):
    def __init__(self, path):
        self.env = Environment(path)
        self.loginNameCache = {}
        self.fieldNameCache = {}
        from trac.db.api import DatabaseManager
        self.using_postgres = \
            DatabaseManager(self.env).connection_uri.startswith("postgres:")

    def hasTickets(self):
        return int(self.env.db_query("SELECT count(*) FROM ticket")[0][0] > 0)

    def assertNoTickets(self):
        if self.hasTickets():
            raise Exception("Will not modify database with existing tickets!")

    def setSeverityList(self, s):
        """Remove all severities, set them to `s`"""
        self.assertNoTickets()

        with self.env.db_transaction as db:
            db("DELETE FROM enum WHERE type='severity'")
            for value, i in s:
                print("  inserting severity '%s' - '%s'" % (value, i))
                db("""INSERT INTO enum (type, name, value)
                      VALUES (%s, %s, %s)""",
                   ("severity", value, i))

    def setPriorityList(self, s):
        """Remove all priorities, set them to `s`"""
        self.assertNoTickets()

        with self.env.db_transaction as db:
            db("DELETE FROM enum WHERE type='priority'")
            for value, i in s:
                print("  inserting priority '%s' - '%s'" % (value, i))
                db("INSERT INTO enum (type, name, value) VALUES (%s, %s, %s)",
                   ("priority", value, i))

    def setComponentList(self, l, key):
        """Remove all components, set them to `l`"""
        self.assertNoTickets()

        with self.env.db_transaction as db:
            db("DELETE FROM component")
            for comp in l:
                print("  inserting component '%s', owner '%s'"
                      % (comp[key], comp['owner']))
                db("INSERT INTO component (name, owner) VALUES (%s, %s)",
                   (comp[key], comp['owner']))

    def setVersionList(self, v, key):
        """Remove all versions, set them to `v`"""
        self.assertNoTickets()

        with self.env.db_transaction as db:
            db("DELETE FROM version")
            for vers in v:
                print("  inserting version '%s'" % vers[key])
                db("INSERT INTO version (name) VALUES (%s)",
                   (vers[key],))

    def setMilestoneList(self, m, key):
        """Remove all milestones, set them to `m`"""
        self.assertNoTickets()

        with self.env.db_transaction as db:
            db("DELETE FROM milestone")
            for ms in m:
                milestone = ms[key]
                print("  inserting milestone '%s'" % milestone)
                db("INSERT INTO milestone (name) VALUES (%s)",
                   (milestone,))

    def addTicket(self, id, time, changetime, component, severity, priority,
                  owner, reporter, cc, version, milestone, status, resolution,
                  summary, description, keywords, customfields):

        desc = description
        type = "defect"

        if SEVERITIES:
            if severity.lower() == "enhancement":
                severity = "minor"
                type = "enhancement"

        else:
            if priority.lower() == "enhancement":
                priority = "minor"
                type = "enhancement"

        if PREFORMAT_COMMENTS:
            desc = '{{{\n%s\n}}}' % desc

        if REPLACE_BUG_NO:
            if BUG_NO_RE.search(desc):
                desc = re.sub(BUG_NO_RE, BUG_NO_REPL, desc)

        if priority in PRIORITIES_MAP:
            priority = PRIORITIES_MAP[priority]

        print("  inserting ticket %s -- %s" % (id, summary))

        with self.env.db_transaction as db:
            db("""INSERT INTO ticket (id, type, time, changetime, component,
                                      severity, priority, owner, reporter, cc,
                                      version, milestone, status, resolution,
                                      summary, description, keywords)
                  VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
                          %s, %s, %s, %s)
                  """, (id, type, datetime2epoch(time),
                        datetime2epoch(changetime), component, severity,
                        priority, owner, reporter, cc, version, milestone,
                        status.lower(), resolution, summary, desc, keywords))

        if self.using_postgres:
            with self.env.db_transaction as db:
                c = db.cursor()
                c.execute("""
                    SELECT SETVAL('ticket_id_seq', MAX(id)) FROM ticket;
                    SELECT SETVAL('report_id_seq', MAX(id)) FROM report""")
                ticket_id = db.get_last_id(c, 'ticket')

        # add all custom fields to ticket
        for name, value in customfields.iteritems():
            self.addTicketCustomField(ticket_id, name, value)

        return ticket_id

    def addTicketCustomField(self, ticket_id, field_name, field_value):
        if field_value is None:
            return
        self.env.db_transaction("""
            INSERT INTO ticket_custom (ticket, name, value) VALUES (%s, %s, %s)
            """, (ticket_id, field_name, field_value))

    def addTicketComment(self, ticket, time, author, value):
        comment = value

        if PREFORMAT_COMMENTS:
            comment = '{{{\n%s\n}}}' % comment

        if REPLACE_BUG_NO:
            if BUG_NO_RE.search(comment):
                comment = re.sub(BUG_NO_RE, BUG_NO_REPL, comment)

        with self.env.db_transaction as db:
            db("""INSERT INTO ticket_change (ticket, time, author, field,
                                             oldvalue, newvalue)
                  VALUES (%s, %s, %s, %s, %s, %s)
                  """, (ticket, datetime2epoch(time), author, 'comment', '',
                        comment))

    def addTicketChange(self, ticket, time, author, field, oldvalue, newvalue):

        if field == "owner":
            if oldvalue in LOGIN_MAP:
                oldvalue = LOGIN_MAP[oldvalue]
            if newvalue in LOGIN_MAP:
                newvalue = LOGIN_MAP[newvalue]

        if field == "priority":
            if oldvalue.lower() in PRIORITIES_MAP:
                oldvalue = PRIORITIES_MAP[oldvalue.lower()]
            if newvalue.lower() in PRIORITIES_MAP:
                newvalue = PRIORITIES_MAP[newvalue.lower()]

        # Doesn't make sense if we go from highest -> highest, for example.
        if oldvalue == newvalue:
            return

        with self.env.db_transaction as db:
            db("""INSERT INTO ticket_change (ticket, time, author, field,
                                             oldvalue, newvalue)
                  VALUES (%s, %s, %s, %s, %s, %s)
                  """, (ticket, datetime2epoch(time), author, field,
                        oldvalue, newvalue))

    def addAttachment(self, author, a):
        if a['filename'] != '':
            description = a['description']
            id = a['bug_id']
            filename = a['filename']
            filedata = io.BytesIO(a['thedata'])
            filesize = len(filedata.getvalue())
            time = a['creation_ts']
            print("    ->inserting attachment '%s' for ticket %s -- %s"
                  % (filename, id, description))
            attachment = Attachment(self.env, 'ticket', id)
            attachment.author = author
            attachment.description = description
            attachment.insert(filename, filedata, filesize,
                              datetime2epoch(time))
            del attachment

    def getLoginName(self, cursor, userid):
        if userid not in self.loginNameCache:
            cursor.execute("SELECT * FROM profiles WHERE userid = %s", userid)
            loginName = cursor.fetchall()

            if loginName:
                loginName = loginName[0]['login_name']
            else:
                print("WARNING: unknown bugzilla userid %d, recording as"
                      "         anonymous" % userid)
                loginName = "anonymous"

            loginName = LOGIN_MAP.get(loginName, loginName)

            self.loginNameCache[userid] = loginName

        return self.loginNameCache[userid]

    def getFieldName(self, cursor, fieldid):
        if fieldid not in self.fieldNameCache:
            # fielddefs.fieldid got changed to fielddefs.id in Bugzilla
            # 2.23.3.
            if BZ_VERSION >= 2233:
                cursor.execute("SELECT * FROM fielddefs WHERE id = %s",
                               fieldid)
            else:
                cursor.execute("SELECT * FROM fielddefs WHERE fieldid = %s",
                               fieldid)
            fieldName = cursor.fetchall()

            if fieldName:
                fieldName = fieldName[0]['name'].lower()
            else:
                print("WARNING: unknown bugzilla fieldid %d, "
                      "         recording as unknown" % fieldid)
                fieldName = "unknown"

            self.fieldNameCache[fieldid] = fieldName

        return self.fieldNameCache[fieldid]
Example #2
0
class TracDatabase(object):
    def __init__(self, path):
        self.env = Environment(path)
        self.loginNameCache = {}
        self.fieldNameCache = {}
        from trac.db.api import DatabaseManager
	self.using_postgres = \
                DatabaseManager(self.env).connection_uri.startswith("postgres:")

    def hasTickets(self):
        return int(self.env.db_query("SELECT count(*) FROM ticket")[0][0] > 0)

    def assertNoTickets(self):
        if self.hasTickets():
            raise Exception("Will not modify database with existing tickets!")

    def setSeverityList(self, s):
        """Remove all severities, set them to `s`"""
        self.assertNoTickets()

        with self.env.db_transaction as db:
            db("DELETE FROM enum WHERE type='severity'")
            for value, i in s:
                #print "  inserting severity '%s' - '%s'" % (value, i)
                db("""INSERT INTO enum (type, name, value)
                      VALUES (%s, %s, %s)""",
                   ("severity", value, i))

    def setPriorityList(self, s):
        """Remove all priorities, set them to `s`"""
        self.assertNoTickets()

        with self.env.db_transaction as db:
            db("DELETE FROM enum WHERE type='priority'")
            for value, i in s:
                print "  inserting priority '%s' - '%s'" % (value, i)
                db("INSERT INTO enum (type, name, value) VALUES (%s, %s, %s)",
                   ("priority", value, i))

    def setComponentList(self, l):
        """Remove all components, set them to `l`"""
        self.assertNoTickets()

        with self.env.db_transaction as db:
            db("DELETE FROM component")
            for comp in l:
                #print "  inserting component '%s', owner '%s'" % \
                #                (comp, DEF_OWNER)
                db("INSERT INTO component (name, owner) VALUES (%s, %s)",
                   (comp, DEF_OWNER))

    def setVersionList(self, v, key):
        """Remove all versions, set them to `v`"""
        self.assertNoTickets()

        with self.env.db_transaction as db:
            db("DELETE FROM version")
            for vers in v:
                print "  inserting version '%s'" % (vers[key])
                db("INSERT INTO version (name) VALUES (%s)",
                   (vers[key],))

    def setMilestoneList(self, m, key):
        """Remove all milestones, set them to `m`"""
        self.assertNoTickets()

        with self.env.db_transaction as db:
            db("DELETE FROM milestone")
            for ms in m:
                milestone = ms[key]
                print "  inserting milestone '%s'" % (milestone)
                db("INSERT INTO milestone (name) VALUES (%s)",
                   (milestone,))

    def addTicket(self, id, time, changetime, component, severity, priority,
                  owner, reporter, cc, version, milestone, status, resolution,
                  summary, description, keywords, customfields):

        desc = description
        type = "defect"

        if SEVERITIES:
            if severity.lower() == "enhancement":
                severity = "minor"
                type = "enhancement"

        else:
            if priority.lower() == "enhancement":
                priority = "minor"
                type = "enhancement"

        if PREFORMAT_COMMENTS:
            desc = '{{{\n%s\n}}}' % desc

        if REPLACE_BUG_NO:
            if BUG_NO_RE.search(desc):
                desc = re.sub(BUG_NO_RE, BUG_NO_REPL, desc)

        if PRIORITIES_MAP.has_key(priority):
            priority = PRIORITIES_MAP[priority]

        print "  inserting ticket %s -- %s" % (id, summary)

        with self.env.db_transaction as db:
            db("""INSERT INTO ticket (id, type, time, changetime, component,
                                      severity, priority, owner, reporter, cc,
                                      version, milestone, status, resolution,
                                      summary, description, keywords)
                  VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
                          %s, %s, %s, %s)
                  """, (id, type, datetime2epoch(time),
                        datetime2epoch(changetime), component, severity,
                        priority, owner, reporter, cc, version, milestone,
                        status.lower(), resolution, summary, desc, keywords))

        if self.using_postgres:
            with self.env.db_transaction as db:
                c = db.cursor()
                c.execute("""
                    SELECT SETVAL('ticket_id_seq', MAX(id)) FROM ticket;
                    SELECT SETVAL('report_id_seq', MAX(id)) FROM report""")
                ticket_id = db.get_last_id(c, 'ticket')

        # add all custom fields to ticket
        for name, value in customfields.iteritems():
            self.addTicketCustomField(ticket_id, name, value)

        #return ticket_id

    def addTicketCustomField(self, ticket_id, field_name, field_value):
        if field_value == None:
            return
        self.env.db_transaction("""
            INSERT INTO ticket_custom (ticket, name, value) VALUES (%s, %s, %s)
            """, (ticket_id, field_name, field_value))

    def addTicketComment(self, ticket, time, author, value):
        comment = value

        if PREFORMAT_COMMENTS:
          comment = '{{{\n%s\n}}}' % comment

        if REPLACE_BUG_NO:
            if BUG_NO_RE.search(comment):
                comment = re.sub(BUG_NO_RE, BUG_NO_REPL, comment)

        with self.env.db_transaction as db:
                db("""INSERT INTO ticket_change (ticket, time, author, field,
                                             oldvalue, newvalue)
                    VALUES (%s, %s, %s, %s, %s, %s)
                    """, (ticket, datetime2epoch(time), author, 'comment', '', 
                        comment))

    def addTicketChange(self, ticket, time, author, field, oldvalue, newvalue):

        if field == "owner":
            if LOGIN_MAP.has_key(oldvalue):
                oldvalue = LOGIN_MAP[oldvalue]
            if LOGIN_MAP.has_key(newvalue):
                newvalue = LOGIN_MAP[newvalue]

        if field == "priority":
            if PRIORITIES_MAP.has_key(oldvalue.lower()):
                oldvalue = PRIORITIES_MAP[oldvalue.lower()]
            if PRIORITIES_MAP.has_key(newvalue.lower()):
                newvalue = PRIORITIES_MAP[newvalue.lower()]

        # Doesn't make sense if we go from highest -> highest, for example.
        if oldvalue == newvalue:
            return

        with self.env.db_transaction as db:
            db("""INSERT INTO ticket_change (ticket, time, author, field,
                                             oldvalue, newvalue)
                  VALUES (%s, %s, %s, %s, %s, %s)
                  """, (ticket, datetime2epoch(time), author, field,
                        oldvalue, newvalue))

    def addAttachment(self, author, a):
        if a['filename'] != '':
            description = a['description'].strip()
            id = a['bug_id']
            filename = a['filename'].strip()
            filedata = StringIO(a['thedata'])
            filesize = len(filedata.getvalue())
            time = a['creation_ts']
            #print "author: " + author
            print "id: %d" % id
            print "filename: " + filename
            #print "filesize: %d" % filesize
            #print "description: " + description
            #print "    ->inserting attachment '%s' for ticket %s -- %s" % \
            #        (filename, id, description)
            
            attachment = Attachment(self.env, 'ticket', id)
            attachment.author = author
            attachment.description = description
            attachment.insert(filename, filedata, filesize, 
                              datetime2epoch(time))
            #del attachment

    def getLoginName(self, cursor, userid):
        if userid not in self.loginNameCache:
            cursor.execute("SELECT * FROM profiles WHERE userid = %s", (userid))
            loginName = cursor.fetchall()

            if loginName:
                loginName = loginName[0]['login_name']
            else:
                print """WARNING: unknown bugzilla userid %d, recording as
                         anonymous""" % (userid)
                loginName = "anonymous"

            loginName = LOGIN_MAP.get(loginName, loginName)

            self.loginNameCache[userid] = loginName

        return self.loginNameCache[userid]

    def getFieldName(self, cursor, fieldid):
        if fieldid not in self.fieldNameCache:
            # fielddefs.fieldid got changed to fielddefs.id in Bugzilla
            # 2.23.3.
            if BZ_VERSION >= 2233:
                cursor.execute("SELECT * FROM fielddefs WHERE id = %s",
                               (fieldid))
            else:
                cursor.execute("SELECT * FROM fielddefs WHERE fieldid = %s",
                               (fieldid))
            fieldName = cursor.fetchall()

            if fieldName:
                fieldName = fieldName[0]['name'].lower()
            else:
                print "WARNING: unknown bugzilla fieldid %d, \
                                recording as unknown" % (userid)
                fieldName = "unknown"

            self.fieldNameCache[fieldid] = fieldName

        return self.fieldNameCache[fieldid]
Example #3
0
class TracDatabase(object):
    def __init__(self, path):
        self.env = Environment(path)

    def hasTickets(self):
        return int(self.env.db_query("SELECT count(*) FROM ticket")[0][0]) > 0

    def dbCheck(self):
        if self.hasTickets():
            raise DBNotEmpty

    def setTypeList(self, s):
        """Remove all types, set them to `s`"""
        self.dbCheck()
        with self.env.db_transaction as db:
            db("DELETE FROM enum WHERE type='ticket_type'")
            for i, value in enumerate(s):
                db("INSERT INTO enum (type, name, value) VALUES (%s, %s, %s)",
                   ("ticket_type", value, i))

    def setPriorityList(self, s):
        """Remove all priorities, set them to `s`"""
        self.dbCheck()
        with self.env.db_transaction as db:
            db("DELETE FROM enum WHERE type='priority'")
            for i, value in enumerate(s):
                db("INSERT INTO enum (type, name, value) VALUES (%s, %s, %s)",
                   ("priority", value, i))

    def setResolutionList(self, t):
        """Remove all resolutions, set them to `t` (index, name)"""
        self.dbCheck()
        with self.env.db_transaction as db:
            db("DELETE FROM enum WHERE type='resolution'")
            for value, name in t:
                db("INSERT INTO enum (type, name, value) VALUES (%s, %s, %s)",
                   ("resolution", name, value))

    def setComponentList(self, t):
        """Remove all components, set them to `t` (name, owner)"""
        self.dbCheck()
        with self.env.db_transaction as db:
            db("DELETE FROM component")
            for name, owner in t:
                db("INSERT INTO component (name, owner) VALUES (%s, %s)",
                   (name, owner))

    def setVersionList(self, v):
        """Remove all versions, set them to `v`"""
        self.dbCheck()
        with self.env.db_transaction as db:
            db("DELETE FROM version")
            for value in v:
                # time and description are also available
                db("INSERT INTO version (name) VALUES (%s)", value)

    def setMilestoneList(self, m):
        """Remove all milestones, set them to `m` ("""
        self.dbCheck()
        with self.env.db_transaction as db:
            db("DELETE FROM milestone")
            for value in m:
                # due, completed, description are also available
                db("INSERT INTO milestone (name) VALUES (%s)", value)

    def addTicket(self, type, time, changetime, component, priority, owner,
                  reporter, cc, version, milestone, status, resolution,
                  summary, description, keywords):
        """ ticket table db21.py format

        id              integer PRIMARY KEY,
        type            text,           -- the nature of the ticket
        time            integer,        -- the time it was created
        changetime      integer,
        component       text,
        severity        text,
        priority        text,
        owner           text,           -- who is this ticket assigned to
        reporter        text,
        cc              text,           -- email addresses to notify
        version         text,           --
        milestone       text,           --
        status          text,
        resolution      text,
        summary         text,           -- one-line summary
        description     text,           -- problem description (long)
        keywords        text
        """
        if status.lower() == 'open':
            if owner != '':
                status = 'assigned'
            else:
                status = 'new'

        with self.env.db_transaction as db:
            c = db.cursor()
            c.execute(
                """
                INSERT INTO ticket (type, time, changetime, component,
                                    priority, owner, reporter, cc, version,
                                    milestone, status, resolution, summary,
                                    description, keywords)
                VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
                        %s, %s)
                """, (type, time, changetime, component, priority, owner,
                      reporter, cc, version, milestone, status.lower(),
                      resolution, summary, '%s' % description, keywords))
            return db.get_last_id(c, 'ticket')

    def addTicketComment(self, ticket, time, author, value):
        with self.env.db_transaction as db:
            db(
                """
                INSERT INTO ticket_change (ticket, time, author, field,
                                           oldvalue, newvalue)
                VALUES (%s, %s, %s, %s, %s, %s)
                """, (ticket, time, author, 'comment', '', '%s' % value))

    def addTicketChange(self, ticket, time, author, field, oldvalue, newvalue):
        with self.env.db_transaction as db:
            db(
                """INSERT INTO ticket_change (ticket, time, author, field,
                                             oldvalue, newvalue)
                  VALUES (%s, %s, %s, %s, %s, %s)
                  """, (ticket, time, author, field, oldvalue, newvalue))