From 16a391aaf9d3934f7297b7a8fb87184cf555882f Mon Sep 17 00:00:00 2001 From: Aaron Bentley Date: Thu, 14 Apr 2005 18:07:49 +0000 Subject: [PATCH] Added preliminary tree-diffing support --- becommands/diff.py | 35 ++++++++++++++++++++++++++++++ becommands/template | 21 ++++++++++++++++++ libbe/arch.py | 23 ++++++++++++++------ libbe/bugdir.py | 9 ++++++++ libbe/diff.py | 52 +++++++++++++++++++++++++++++++++++++++++++++ libbe/template | 48 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 182 insertions(+), 6 deletions(-) create mode 100644 becommands/diff.py create mode 100644 becommands/template create mode 100644 libbe/diff.py create mode 100644 libbe/template diff --git a/becommands/diff.py b/becommands/diff.py new file mode 100644 index 0000000..bf8b66d --- /dev/null +++ b/becommands/diff.py @@ -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 index 0000000..3c871e6 --- /dev/null +++ b/becommands/template @@ -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 diff --git a/libbe/arch.py b/libbe/arch.py index 7e1cd1f..21a6809 100644 --- a/libbe/arch.py +++ b/libbe/arch.py @@ -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) diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 16c1544..8583b68 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -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 index 0000000..3c348a0 --- /dev/null +++ b/libbe/diff.py @@ -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 index 0000000..467eee4 --- /dev/null +++ b/libbe/template @@ -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) + + + -- 2.26.2