Browse Source

[1541] Changes after review:

- added comments
- script now uses OptionParser for command line options
- unnecessary code removed
- several coding style improvements
Tomek Mrugalski 13 years ago
parent
commit
aa72029e21
1 changed files with 79 additions and 59 deletions
  1. 79 59
      tools/git-obsolete-branch.py

+ 79 - 59
tools/git-obsolete-branch.py

@@ -15,44 +15,57 @@
 # PERFORMANCE OF THIS SOFTWARE.
 
 #
-# This script lists obsolete (fully merged) branches. It is useful for periodic maintenance
-# of our GIT tree.
-
-# It is good to use following command before running this script:
+# This script lists obsolete (fully merged) branches. It is useful for periodic
+# maintenance of our GIT tree.
+#
+# It is good idea to use following command before running this script:
 #
 # git pull
 # git remote prune origin
 #
 # This script requires python 2.7 or 3.
 #
-# I have limited experience in Python. If things are done in a strange or uncommon way, there
-# are no obscure reasons to do it that way, just plain lack of experience.
+# I have limited experience in Python. If things are done in a strange or
+# uncommon way, there are no obscure reasons to do it that way, just plain
+# lack of experience.
 #
 #                                                                        tomek
 
 import string
 import subprocess
 import sys
+from optparse import OptionParser
 
 class Branch:
-    MERGED=1
-    NOTMERGED=2
-    name = ""
+    MERGED = 1
+    NOTMERGED = 2
+    name = None
     status = NOTMERGED
-    last_commit = ""
+    last_commit = None
 
 
 def branch_list_get(verbose):
+    """ Generates a list of available remote branches and
+        checks their status (merged/unmerged). A branch is merged
+        if all changes on that branch are also on master. """
+
+    # call git branch -r (list of remote branches)
     txt_list = subprocess.check_output(["git", "branch", "-r"])
 
     txt_list = txt_list.split(b"\n")
 
+    # we will store list of suitable branches here
     out = []
     for branch in txt_list:
+        # skip empty lines
         if len(branch) == 0:
             continue
+
+        # skip branches that are aliases (something -> something_else)
         if branch.find(b"->") != -1:
             continue
+
+        # don't complain about master
         if branch == b"origin/master":
             continue
 
@@ -66,110 +79,117 @@ def branch_list_get(verbose):
         if verbose:
             print("Checking branch %s" % branch_info.name)
 
+        # get a diff with changes that are on that branch only
+        # i.e. all unmerged code.
         cmd = ["git", "diff", "master..." + branch_info.name ]
         diff = subprocess.check_output(cmd)
-        if (len(diff) == 0):
+        if len(diff) == 0:
+            # No diff? Then all changes from that branch are on master as well.
             branch_info.status = Branch.MERGED
-            # let's get the last contributor
-            cmd = [ "git" , "log", "-n", "1", "--pretty=\"%ai,%ae,%an\"", branch_info.name ]
 
+            # let's get the last contributor with extra formatting
+            # see man git-log and search for PRETTY FORMATS.
+            # %ai = date, %ae = author e-mail, %an = author name
+            cmd = [ "git" , "log", "-n", "1", "--pretty=\"%ai,%ae,%an\"", branch_info.name ]
             offender = subprocess.check_output(cmd)
             offender = offender.strip(b"\n\"")
 
             # comment out this 2 lines to disable obfuscation
             offender = offender.replace(b"@", b"(at)")
-            offender = offender.replace(b".", b"(dot)")
+            # Obfuscating a dot does not work too well for folks that use initials
+            #offender = offender.replace(b".", b"(dot)")
 
             branch_info.last_commit = offender.decode("utf-8")
 
         else:
+            # diff is not empty, so there is something to merge
             branch_info.status = Branch.NOTMERGED
 
         out.append(branch_info)
-#        return (out)
-    return (out)
+    return out
 
 def branch_print(branches, csv, print_merged, print_notmerged, print_stats):
+    """ prints out list of branches with specified details (using
+        human-readable (or CSV) format. It is possible to specify,
+        which branches should be printed (merged, notmerged) and
+        also print out summary statistics """
+
+    # counters used for statistics
     merged = 0
     notmerged = 0
+
+    # compact list of merged/notmerged branches
     merged_str = ""
     notmerged_str = ""
     for branch in branches:
-        if (branch.status==Branch.MERGED):
+        if branch.status==Branch.MERGED:
             merged = merged + 1
-            if (not print_merged):
+            if not print_merged:
                 continue
-            if (csv):
+            if csv:
                 print("%s,merged,%s" % (branch.name, branch.last_commit) )
             else:
                 merged_str = merged_str + " " + branch.name
         else:
             # NOT MERGED
             notmerged = notmerged + 1
-            if (not print_notmerged):
+            if not print_notmerged:
                 continue
-            if (csv):
+            if csv:
                 print("%s,notmerged,%s" % (branch.name, branch.last_commit) )
             else:
                 notmerged_str = notmerged_str + " " + branch.name
 
-    if (not csv):
-        if (print_merged):
+    if not csv:
+        if print_merged:
             print("Merged branches    : %s" % (merged_str))
-        if (print_notmerged):
+        if print_notmerged:
             print("NOT merged branches: %s" % (notmerged_str))
 
-    if (print_stats):
+    if print_stats:
         print("#----------")
         print("#Merged    : %d" % merged)
         print("#Not merged: %d" % notmerged)
 
-def show_help():
-    print("This script prints out merged and/or unmerged branches of a GIT tree.")
-    print("Supported command-line options:")
-    print("")
-    print("--csv          produce CSV (coma separated value) output")
-    print("--unmerged     lists umerged branches")
-    print("--skip-merged  do not print merged branches (that are listed by default)")
-    print("--stats        prints out statistics")
-    print("--help         prints out this help")
+
+def parse_args(args = sys.argv[1:], Parser=OptionParser):
+
+    parser = Parser(description="This script prints out merged and/or unmerged"
+                    " branches of a GIT tree.")
+
+    parser.add_option("-c", "--csv", action="store_true",
+                      default=False, help="generates CSV output")
+    parser.add_option("-u", "--unmerged", action="store_true",
+                      default=False, help="lists unmerged branches")
+    parser.add_option("-m", "--skip-merged", action="store_true",
+                      default=False, help="omits listing merged branches")
+    parser.add_option("-s", "--stats", action="store_true",
+                      default=False, help="prints also statistics")
+
+    (options, args) = parser.parse_args(args)
+
+    if args:
+        parser.print_help()
+        sys.exit(1)
+
+    return options
 
 def main():
     usage = """%prog
     Lists all obsolete (fully merged into master) branches.
     """
 
-    csv = False
-    merged = True
-    unmerged = False
-    stats = False
-
-    for x in sys.argv[1:]:
-        if x == "--csv":
-            csv = True
-        elif x == "--unmerged":
-            unmerged = True
-        elif x == "--skip-merged":
-            merged = False
-        elif x == "--stats":
-            stats = True
-        elif x == "--help":
-            show_help()
-            return
-        else:
-            print("Invalid parameter: %s" % x)
-            print("")
-            show_help()
-            return
+    options = parse_args()
+    csv = options.csv
+    merged = not options.skip_merged
+    unmerged = options.unmerged
+    stats = options.stats
 
     if csv:
         print("branch name,status,date,last commit(mail),last commit(name)")
 
     branch_list = branch_list_get(not csv)
 
-#   Uncomment this to print out also merged branches
-#    branch_print(branch_list, False, True, False)
-
     branch_print(branch_list, csv, merged, unmerged, stats)
 
 if __name__ == '__main__':