util: Optionally search entire history when listing changes

The helper script to list changes currently only looks at the changes
between a branch point and two heads. This helps performance, but
sometimes misclassifies changes that exist both in the upstream
branch before the branch point and in a feature branch. Such changes
should normally not exist, but can be the product of an incorrect
rebase.

This change adds an option to the helper script to search the entire
upstream repo history when determining the set of upstream
changes. When this option is provided, the script lists the changes
that exist upstream before the branch point and in the feature branch
as "Incorrectly rebased changes".

Change-Id: I4cb72cea2152c49d0317dc43613be94a0a2de1e5
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/5161
diff --git a/util/maint/list_changes.py b/util/maint/list_changes.py
index 5cbcf59..78e4442 100755
--- a/util/maint/list_changes.py
+++ b/util/maint/list_changes.py
@@ -105,16 +105,21 @@
     def __str__(self):
         return "%s: %s" % (self.rev[0:8], self.log[0])
 
-def list_revs(upstream, branch):
-    """Get a generator that lists git revisions that exist in 'branch' but
-    not in 'upstream'.
+def list_revs(branch, baseline=None):
+    """Get a generator that lists git revisions that exist in 'branch'. If
+    the optional parameter 'baseline' is specified, the generator
+    excludes commits that exist on that branch.
 
     Returns: Generator of Commit objects
 
     """
 
-    changes = subprocess.check_output(
-        [ "git", "rev-list", "%s..%s" % (upstream, branch) ])
+    if baseline is not None:
+        query = "%s..%s" % (branch, baseline)
+    else:
+        query = str(branch)
+
+    changes = subprocess.check_output([ "git", "rev-list", query ])
 
     if changes == "":
         return
@@ -165,6 +170,9 @@
                         help="Print changes without Change-Id tags")
     parser.add_argument("--show-common", action="store_true",
                         help="Print common changes")
+    parser.add_argument("--deep-search", action="store_true",
+                        help="Use a deep search to find incorrectly " \
+                        "rebased changes")
 
     args = parser.parse_args()
 
@@ -200,6 +208,19 @@
         for rev in feature_unknown:
             print rev
 
+    if args.deep_search:
+        print "Incorrectly rebased changes:"
+        all_upstream_revs = list_revs(args.upstream)
+        all_upstream_cids = dict([
+            (c.change_id, c) for c in all_upstream_revs \
+            if c.change_id is not None ])
+        incorrect_outgoing = filter(
+            lambda r: r.change_id in all_upstream_cids,
+            outgoing)
+        for rev in incorrect_outgoing:
+            print rev
+
+
 
 
 if __name__ == "__main__":