Commit tracker now prints information on closed issues

Change-Id: I09443d0045dd466390a4444982a618a5c93e7d1e
Signed-off-by: Charles Hofer <cphofer@us.ibm.com>
diff --git a/tools/commit-tracker b/tools/commit-tracker
index 3c7e7a2..b393984 100755
--- a/tools/commit-tracker
+++ b/tools/commit-tracker
@@ -24,12 +24,13 @@
 ###############################################################################
 
 import argparse
+import git
 import logging
 import os
 import re
+import requests
 import sys
 import time
-import git
 
 ###############################################################################
 # @class CommitReport
@@ -38,7 +39,7 @@
 ###############################################################################
 class CommitReport:
     def __init__(self, i_repo_uri, i_repo_name,  i_sha, i_nice_name,
-                 i_summary, i_insertions, i_deletions):
+                 i_summary, i_insertions, i_deletions, i_closed_issues):
         self.repo_uri = i_repo_uri
         self.repo_name = i_repo_name
         self.sha = i_sha
@@ -46,6 +47,7 @@
         self.summary = i_summary
         self.insertions = i_insertions
         self.deletions = i_deletions
+        self.closed_issues = i_closed_issues
         self.subreports = []
 
     def to_cl_string(self, i_level=0):
@@ -74,6 +76,12 @@
             l_deletions += l_commit.get_total_deletions()
         return l_deletions
 
+    def get_all_closed_issues(self):
+        l_closed_issues = self.closed_issues
+        for l_commit in self.subreports:
+            l_closed_issues.extend(l_commit.get_all_closed_issues())
+        return l_closed_issues
+
 ###############################################################################
 # @brief Main function for the script
 #
@@ -92,16 +100,21 @@
         l_args_obj.earliest_commit)
 
     # Compile issues, insertions, and deletions
+    l_issues = []
     l_total_deletions = 0
     l_total_insertions = 0
     for l_report in l_reports:
         l_total_deletions += l_report.get_total_deletions()
         l_total_insertions += l_report.get_total_insertions()
+        l_issues.extend(l_report.get_all_closed_issues())
 
     # Print commit information to the console
     print 'Commits'
     for l_report in l_reports:
         print l_report.to_cl_string()
+    print 'Closed issues...'
+    for l_issue in l_issues:
+        print '  ' + str(l_issue[0]) + ' ' + str(l_issue[1])
     print 'Insertions and Deletions'
     print str(l_total_insertions) + ' insertions'
     print str(l_total_deletions) + ' deletions'
@@ -181,7 +194,8 @@
                 to_prefix_name_rev(l_commit.name_rev),
                 l_commit.summary,
                 l_insertions,
-                l_deletions)
+                l_deletions,
+                get_closed_issues(l_commit))
 
             # Search the diffs for any bumps of submodule versions
             l_diffs = l_commit.diff(str(l_commit.hexsha) + '~1')
@@ -326,6 +340,56 @@
         deletions = int(deletion_match.group(1))
     return insertions, deletions
 
+###############################################################################
+# @brief Gets closed issues from the commit message
+#
+# @param i_commit : The commit to get closed issues for
+#
+# @return A list of tuples, the first element being the ID of the issue, the
+#         second being the title from GitHub
+###############################################################################
+def get_closed_issues(i_commit):
+    l_closed_issues = []
+
+    # Set up the regex
+    l_close_regex = re.compile(
+        '((F|f)ix((es|ed)?)|(C|c)lose((s|d)?)|(R|r)esolve((s|d)?)) '
+        + '+(?P<issue>[a-zA-Z0-9#]+\/[a-zA-Z0-9#]+)')
+    l_matches = l_close_regex.finditer(i_commit.message)
+
+    # Loop through all the matches getting each issue name
+    for l_match in l_matches:
+        l_issue_id = l_match.group('issue')
+        l_issue_title = get_issue_title(l_issue_id)
+        l_closed_issues.append((l_issue_id, l_issue_title))
+
+    return l_closed_issues
+
+###############################################################################
+# @brief Gets the title of an issue based on the issue ID
+#
+# @param i_issue_id : The ID of the issue to get the title for
+#
+# @return The title of the issue
+###############################################################################
+def get_issue_title(i_issue_id):
+    # Construct the URL
+    l_url_tail = re.sub('#', '/issues/', i_issue_id)
+    l_full_url = 'https://api.github.com/repos/' + l_url_tail
+    l_title = ''
+
+    # Send in the web request
+    l_response = requests.get(l_full_url)
+    if 200 == l_response.status_code:
+        l_issue = l_response.json()
+        l_title = l_issue['title']
+    else:
+        logging.error(l_response.text)
+        logging.error('Recieved status code ' \
+                      + str(l_response.status_code) \
+                      + ' when getting issue titles.')
+    return l_title
+
 ##############################################################################
 # @brief Cuts the hash in commit revision names down to its 7 digit prefix
 #