예제 #1
0
 def cmp(x, y):
     if x == y:
         return 0
     if x == '':
         if y == None:
             return -1
         else:
             return 1
     if y == '':
         if x == None:
             return 1
         else:
             return -1
     if x == None:
         return 1
     if y == None:
         return -1
     return packaging.compare_versions(x, y)
예제 #2
0
    def check_duplicate(self, id, report=None):
        '''Check whether a crash is already known.

        If the crash is new, it will be added to the duplicate database and the
        function returns None. If the crash is already known, the function
        returns a pair (crash_id, fixed_version), where fixed_version might be
        None if the crash is not fixed in the latest version yet. Depending on
        whether the version in report is smaller than/equal to the fixed
        version or larger, this calls close_duplicate() or mark_regression().
        
        If the report does not have a valid crash signature, this function does
        nothing and just returns None.
        
        By default, the report gets download()ed, but for performance reasons
        it can be explicitly passed to this function if it is already available.
        '''
        assert self.duplicate_db, 'init_duplicate_db() needs to be called before'

        if not report:
            report = self.download(id)

        self._mark_dup_checked(id, report)

        if 'DuplicateSignature' in report:
            sig = report['DuplicateSignature']
        else:
            sig = report.crash_signature()
        if not sig:
            return None

        existing = self._duplicate_search_signature(sig, id)

        # sort existing in ascending order, with unfixed last, so that
        # version comparisons find the closest fix first
        def cmp(x, y):
            if x == y:
                return 0
            if x == '':
                if y == None:
                    return -1
                else:
                    return 1
            if y == '':
                if x == None:
                    return 1
                else:
                    return -1
            if x == None:
                return 1
            if y == None:
                return -1
            return packaging.compare_versions(x, y)

        existing.sort(cmp, lambda k: k[1])

        if existing:
            # update status of existing master bugs
            for (ex_id, _) in existing:
                self._duplicate_db_sync_status(ex_id)
            existing = self._duplicate_search_signature(sig, id)
            existing.sort(cmp, lambda k: k[1])

        if not existing:
            # add a new entry
            cur = self.duplicate_db.cursor()
            cur.execute('INSERT INTO crashes VALUES (?, ?, ?, CURRENT_TIMESTAMP)', (_u(sig), id, None))
            self.duplicate_db.commit()
            return None

        try:
            report_package_version = report['Package'].split()[1]
        except (KeyError, IndexError):
            report_package_version = None

        # search the newest fixed id or an unfixed id to check whether there is
        # a regression (crash happening on a later version than the latest
        # fixed one)
        for (ex_id, ex_ver) in existing:
            if not ex_ver or \
               not report_package_version or \
                packaging.compare_versions(report_package_version, ex_ver) < 0: 
                self.close_duplicate(id, ex_id)
                break
        else:
            # regression, mark it as such in the crash db
            self.mark_regression(id, ex_id)

            # create a new record
            cur = self.duplicate_db.cursor()
            cur.execute('INSERT INTO crashes VALUES (?, ?, ?, CURRENT_TIMESTAMP)', (_u(sig), id, None))
            self.duplicate_db.commit()

            # we now track this as a new crash
            return None

        return (ex_id, ex_ver)