Added preliminary tree-diffing support
authorAaron Bentley <abentley@panoramicfeedback.com>
Thu, 14 Apr 2005 18:07:49 +0000 (18:07 +0000)
committerAaron Bentley <abentley@panoramicfeedback.com>
Thu, 14 Apr 2005 18:07:49 +0000 (18:07 +0000)
becommands/diff.py [new file with mode: 0644]
becommands/template [new file with mode: 0644]
libbe/arch.py
libbe/bugdir.py
libbe/diff.py [new file with mode: 0644]
libbe/template [new file with mode: 0644]

diff --git a/becommands/diff.py b/becommands/diff.py
new file mode 100644 (file)
index 0000000..bf8b66d
--- /dev/null
@@ -0,0 +1,35 @@
+# This is the standard command template.  To use it, please fill in values for
+# Short description, long help and COMMANDSPEC
+#
+"""Compare bug reports with older tree"""
+from libbe import bugdir, diff, cmdutil
+import os
+def execute(args):
+    options, args = get_parser().parse_args(args)
+    if len(args) == 0:
+        spec = None
+    elif len(args) == 1:
+        spec = args[0]
+    else:
+        raise cmdutil.UsageError
+    tree = bugdir.tree_root(".")
+    if tree.rcs_name == "None":
+        print "This directory is not revision-controlled."
+    else:
+        diff.diff_report(diff.reference_diff(tree, spec), tree)
+
+
+def get_parser():
+    parser = cmdutil.CmdOptionParser("be diff [specifier]")
+    return parser
+
+longhelp="""
+Uses the RCS to compare the current tree with a previous tree, and prints
+a pretty report.  If specifier is given, it is a specifier for the particular
+previous tree to use.  Specifiers are specific to their RCS.  
+
+For Arch: a fully-qualified revision name
+"""
+
+def help():
+    return get_parser().help_str() + longhelp
diff --git a/becommands/template b/becommands/template
new file mode 100644 (file)
index 0000000..3c871e6
--- /dev/null
@@ -0,0 +1,21 @@
+"""Short description"""
+from libbe import bugdir, cmdutil, names
+import os
+def execute(args):
+    options, args = get_parser().parse_args(args)
+    if len(args) > 0:
+        raise cmdutil.UsageError
+
+
+def get_parser():
+    parser = cmdutil.CmdOptionParser("be list [options]")
+#    parser.add_option("-w", "--wishlist", action="store_true", dest="wishlist",
+#                      help="List bugs with 'wishlist' severity")
+    return parser
+
+longhelp="""
+This is for the longwinded description
+"""
+
+def help():
+    return get_parser().help_str() + longhelp
index 7e1cd1f37c9b8b6da896ad562ff99976d0895bdb..21a68090ea6fff0cf2ce5cdb385e215faaa6fa21 100644 (file)
@@ -1,4 +1,4 @@
-from popen2 import Popen4
+from popen2 import Popen3
 import os
 import config
 client = config.get_val("arch_client")
@@ -7,17 +7,21 @@ if client is None:
     config.set_val("arch_client", client)
 
 def invoke(args):
-    q=Popen4(args)
+    q=Popen3(args, True)
     output = q.fromchild.read()
+    error = q.childerr.read()
     status = q.wait()
     if os.WIFEXITED(status):
-        return os.WEXITSTATUS(status)
-    raise Exception("Command failed")
+        return os.WEXITSTATUS(status), output, error
+    raise Exception("Command failed: %s" % error)
 
 def invoke_client(*args, **kwargs):
-    status = invoke((client,) + args)
+    cl_args = [client]
+    cl_args.extend(args)
+    status,output,error = invoke(cl_args)
     if status not in (0,):
-        raise Exception("Command failed")
+        raise Exception("Command failed: %s" % error)
+    return output
 
 def add_id(filename):
     invoke_client("add-id", filename)
@@ -35,6 +39,13 @@ def set_file_contents(path, contents):
     if add:
         add_id(path)
 
+
+def path_in_reference(bug_dir, spec):
+    if spec is not None:
+        return invoke_client("file-find", bug_dir, spec).rstrip('\n')
+    return invoke_client("file-find", bug_dir).rstrip('\n')
+
+
 def unlink(path):
     try:
         os.unlink(path)
index 16c1544746e2b5b71bcdc55f3dc4b1951db4e524..8583b6890d1bcc087966558e30d926f32bea4cd6 100644 (file)
@@ -98,10 +98,19 @@ class BugDir:
 
     rcs = property(get_rcs)
 
+    def get_reference_bugdir(self, spec):
+        return BugDir(self.rcs.path_in_reference(self.dir, spec))
+
     def list(self):
         for uuid in self.list_uuids():
             yield self.get_bug(uuid)
 
+    def bug_map(self):
+        bugs = {}
+        for bug in self.list():
+            bugs[bug.uuid] = bug
+        return bugs
+
     def get_bug(self, uuid):
         return Bug(self.bugs_path, uuid, self.rcs_name)
 
diff --git a/libbe/diff.py b/libbe/diff.py
new file mode 100644 (file)
index 0000000..3c348a0
--- /dev/null
@@ -0,0 +1,52 @@
+"""Compare two bug trees"""
+from libbe import cmdutil, bugdir
+
+def diff(old_tree, new_tree):
+    old_bug_map = old_tree.bug_map()
+    new_bug_map = new_tree.bug_map()
+    added = []
+    removed = []
+    modified = []
+    for old_bug in old_bug_map.itervalues():
+        new_bug = new_bug_map.get(old_bug.uuid)
+        if new_bug is None :
+            removed.append(old_bug)
+        else:
+            if old_bug != new_bug:
+                modified.append((old_bug, new_bug))
+    for new_bug in new_bug_map.itervalues():
+        if not old_bug_map.has_key(new_bug.uuid):
+            added.append(new_bug)
+    return (removed, modified, added)
+
+
+def reference_diff(bugdir, spec=None):
+    return diff(bugdir.get_reference_bugdir(spec), bugdir)
+    
+def diff_report(diff_data, bug_dir):
+    (removed, modified, added) = diff_data
+    bugs = list(bug_dir.list())
+    def modified_cmp(left, right):
+        return bugdir.cmp_severity(left[1], right[1])
+
+    added.sort(bugdir.cmp_severity)
+    removed.sort(bugdir.cmp_severity)
+    modified.sort(modified_cmp)
+
+    if len(added) > 0: 
+        print "New bug reports:"
+        for bug in added:
+            print cmdutil.bug_summary(bug, bugs, no_target=True)
+
+    if len(modified) > 0 and False:
+        print "modified bug reports:"
+        for old_bug, new_bug in modified: 
+            print cmdutil.bug_summary(new_bug, bugs, no_target=True)
+
+    if len(removed) > 0: 
+        print "Removed bug reports:"
+        for bug in removed:
+            print cmdutil.bug_summary(bug, bugs, no_target=True)
+   
+
+
diff --git a/libbe/template b/libbe/template
new file mode 100644 (file)
index 0000000..467eee4
--- /dev/null
@@ -0,0 +1,48 @@
+"""Compare two bug trees"""
+from bugdir import cmdutil
+
+def diff(old_tree, new_tree):
+    old_bug_map = old_tree.bug_map()
+    new_bug_map = new_tree.bug_map()
+    added = []
+    removed = []
+    modified = []
+    for old_bug in old_bug_map.itervalues():
+        new_bug = new_bug_map.get(bug.uuid)
+        if new_bug is None :
+            removed.append(old_bug)
+        else:
+            if old_bug != new_bug:
+                modified.append((old_bug, new_bug))
+    for new_bug in new_bug_map.itervalues():
+        if not old_bug_map.haskey(new_bug.id):
+            added.append(new_bug)
+    return (removed, modified, added)
+
+
+def reference_diff(bugdir, spec=None):
+    return diff(bugdir.reference_bugdir(), bugdir)
+    
+def diff_report(diff_data, bugdir)
+    (removed, modified, added) = diff_data
+    def modified_cmp(left, right):
+        return cmp_severity(left[1], right[1])
+
+    added.sort(bugdir.cmp_severity)
+    removed.sort(bugdir.cmp_severity)
+    modified.sort(modified_cmp)
+
+    print "New bug reports:"
+    for bug in added:
+        cmdutil.bug_summary(bug, bugdir, no_target=True)
+
+    print "modified bug reports:"
+    for old_bug, new_bug in modified: 
+        cmdutil.bug_summary(new_bug, bugdir, no_target=True)
+
+    print "Removed bug reports:"
+    for bug in removed:
+        cmdutil.bug_summary(bug, bugdir, no_target=True)
+   
+
+