summaryrefslogtreecommitdiffstats
path: root/src/Backtrace/abrt-bz-dupchecker
blob: 01cafa01c4aa46e1f1ba007515f61f4910ab221f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/python
# -*- mode:python -*-
# ABRT Bugzilla Duplication Checker
# Downloads all backtraces reported by ABRT from Bugzilla,
# and search for duplicates using the newest ABRT duplication 
# checker.
#
# Some bugs in Bugzilla were reported by older ABRT
# versions, which had poor duplication detection.
#
# Please do not run this script unless it's neccessary to do so. 
# It forces Bugzilla to send data related to thousands of bug reports.

from bugzilla import RHBugzilla
from optparse import OptionParser
import sys
import os.path
import subprocess

parser = OptionParser(version="%prog 1.0")
parser.add_option("-u", "--user", dest="user",
                  help="Bugzilla user name (REQUIRED)", metavar="USERNAME")
parser.add_option("-p", "--password", dest="password",
                  help="Bugzilla password (REQUIRED)", metavar="PASSWORD")
parser.add_option("-b", "--bugzilla", dest="bugzilla",
                  help="Bugzilla URL (defaults to Red Hat Bugzilla)", metavar="URL")
parser.add_option("-v", "--verbose", dest="verbose",
                  help="Detailed output")

(options, args) = parser.parse_args()

if not options.user or len(options.user) == 0:
  parser.error("User name is required.\nTry {0} --help".format(sys.argv[0]))

if not options.password or len(options.password) == 0:
  parser.error("Password is required.\nTry {0} --help".format(sys.argv[0]))

if not options.bugzilla or len(options.bugzilla) == 0:
  options.bugzilla = "https://bugzilla.redhat.com/xmlrpc.cgi"

bz = RHBugzilla()
bz.connect(options.bugzilla)
bz.login(options.user, options.password)

buginfos = bz.query({'status_whiteboard_type':'allwordssubstr','status_whiteboard':'abrt_hash'})

print "{0} bugs found.".format(len(buginfos))

database = {}

for buginfo in buginfos:
  if not buginfo.bug_status in ["NEW", "ASSIGNED", "MODIFIED", "VERIFIED"]:
    if options.verbose:
      print "Bug {0} has status {1}, skipping.".format(buginfo.bug_id, buginfo.bug_status)
    continue

  # Skip bugs with already downloaded backtraces.
  filename = "{0}.bt".format(buginfo.bug_id)
  if os.path.isfile(filename):
    if options.verbose:
      print "Skipping {0} (already exists).".format(filename)
  else:
    # Get backtrace from bug and store it as a file.
    bug = bz.getbug(buginfo.bug_id)
    for attachment in bug.attachments:
      if attachment['filename'] == 'backtrace':
        data = bz.openattachment(attachment['id'])
        f = open(filename, 'w')
        f.write(data.read())
        f.close()
        if options.verbose:
          print "Attachment {0} downloaded.".format(filename)
  
  command = ["/usr/bin/abrt-backtrace"]
  command.append(filename)
  command.append("--single-thread")
  command.append("--frame-depth=5")
  command.append("--remove-exit-handlers")
  command.append("--remove-noncrash-frames")

  helper = subprocess.Popen(command, stdout=subprocess.PIPE)
  out, err = helper.communicate()
  helper.wait()

  if helper.returncode != 0:
    print "Problems parsing {0}".format(filename)
    continue

  # Empty backtrace is provided by Python apps.
  if len(out) == 0:
    continue

  if out in database:
    database[out].append(buginfo.bug_id)
    if options.verbose:
      print "Duplicate found: {0}".format(database[out])
      print "Backtrace: {0}".format(out)
  else:
    database[out] = [ buginfo.bug_id ]

bz.logout()

print "SUMMARY"
print "=========================================================================="

# The number of duplicates.
dupcount = 0
for key, value in database.items():
  if len(value) > 1:
    dupcount += len(value) - 1

print "Total number of duplicate bugs detected: {0}".format(dupcount)
print "------------------------------"

for key, value in database.items():
  if len(value) > 1:
    print "Duplicates: {0}".format(value)
    print "Backtrace: {0}".format(key)