diff options
Diffstat (limited to 'libbe')
-rw-r--r-- | libbe/bugdir.py | 29 | ||||
-rw-r--r-- | libbe/cmdutil.py | 57 | ||||
-rw-r--r-- | libbe/diff.py | 21 | ||||
-rw-r--r-- | libbe/mapfile.py | 10 |
4 files changed, 108 insertions, 9 deletions
diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 766ccd9..414b47e 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -242,6 +242,9 @@ class Bug(object): if self.time is not None: self.time = utility.str_to_time(self.time) + def __repr__(self): + return "Bug(uuid=%r)" % self.uuid + def get_path(self, file): return os.path.join(self.path, self.uuid, file) @@ -345,16 +348,18 @@ class Comment(object): self.date = utility.str_to_time(mapfile["Date"]) self.From = mapfile["From"] self.in_reply_to = mapfile.get("In-reply-to") + self.content_type = mapfile.get("Content-type", "text/plain") self.body = file(self.get_path("body")).read().decode("utf-8") else: self.date = None self.From = None self.in_reply_to = None + self.content_type = "text/plain" self.body = None def save(self): map_file = {"Date": utility.time_to_str(self.date)} - add_headers(self, map_file, ("From", "in_reply_to")) + add_headers(self, map_file, ("From", "in_reply_to", "content_type")) if not os.path.exists(self.get_path(None)): self.bug.rcs.mkdir(self.get_path(None)) map_save(self.bug.rcs, self.get_path("values"), map_file) @@ -367,7 +372,27 @@ class Comment(object): if name is None: return my_dir return os.path.join(my_dir, name) - + + +def thread_comments(comments): + child_map = {} + top_comments = [] + for comment in comments: + child_map[comment.uuid] = [] + for comment in comments: + if comment.in_reply_to is None or comment.in_reply_to not in child_map: + top_comments.append(comment) + continue + child_map[comment.in_reply_to].append(comment) + + def recurse_children(comment): + child_list = [] + for child in child_map[comment.uuid]: + child_list.append(recurse_children(child)) + return (comment, child_list) + return [recurse_children(c) for c in top_comments] + + def pyname_to_header(name): return name.capitalize().replace('_', '-') diff --git a/libbe/cmdutil.py b/libbe/cmdutil.py index 2f24490..079601e 100644 --- a/libbe/cmdutil.py +++ b/libbe/cmdutil.py @@ -19,6 +19,8 @@ import plugin import locale import os import optparse +from textwrap import TextWrapper +from StringIO import StringIO import utility def unique_name(bug, bugs): @@ -118,6 +120,34 @@ def raise_get_help(option, opt, value, parser): raise GetHelp +def iter_comment_name(bug, unique_name): + """Iterate through id, comment pairs, in date order. + (This is a user-friendly id, not the comment uuid) + """ + def key(comment): + return comment.date + for num, comment in enumerate(sorted(bug.list_comments(), key=key)): + yield ("%s:%d" % (unique_name, num+1), comment) + + +def comment_from_name(bug, unique_name, name): + """Use a comment name to look up a comment""" + for cur_name, comment in iter_comment_name(bug, unique_name): + if name == cur_name: + return comment + raise KeyError(name) + + +def get_bug_and_comment(identifier, bug_dir=None): + ids = identifier.split(':') + bug = get_bug(ids[0], bug_dir) + if len(ids) == 2: + comment = comment_from_name(bug, ids[0], identifier) + else: + comment = None + return bug, comment + + class CmdOptionParser(optparse.OptionParser): def __init__(self, usage): optparse.OptionParser.__init__(self, usage) @@ -148,6 +178,24 @@ def underlined(instring): return "%s\n%s" % (instring, "="*len(instring)) +def print_threaded_comments(comments, name_map, indent=""): + """Print a threaded display of comments""" + tw = TextWrapper(initial_indent = indent, subsequent_indent = indent, + width=80) + for comment, children in comments: + s = StringIO() + print >> s, "--------- Comment ---------" + print >> s, "Name: %s" % name_map[comment.uuid] + print >> s, "From: %s" % comment.From + print >> s, "Date: %s\n" % utility.time_to_str(comment.date) + print >> s, comment.body.rstrip('\n') + + s.seek(0) + for line in s: + print tw.fill(line).rstrip('\n') + print_threaded_comments(children, name_map, indent=indent+" ") + + def bug_tree(dir=None): """Retrieve the bug tree specified by the user. If no directory is specified, the current working directory is used. @@ -167,6 +215,15 @@ def bug_tree(dir=None): except bugdir.NoBugDir, e: raise UserErrorWrap(e) +def print_command_list(): + cmdlist = [] + print """Bugs Everywhere - Distributed bug tracking + +Supported commands""" + for name, module in iter_commands(): + cmdlist.append((name, module.__doc__)) + for name, desc in cmdlist: + print "be %s\n %s" % (name, desc) def _test(): import doctest diff --git a/libbe/diff.py b/libbe/diff.py index 82dc219..c1dc429 100644 --- a/libbe/diff.py +++ b/libbe/diff.py @@ -16,6 +16,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """Compare two bug trees""" from libbe import cmdutil, bugdir +from libbe.utility import time_to_str def diff(old_tree, new_tree): old_bug_map = old_tree.bug_map() @@ -85,9 +86,25 @@ def change_lines(old, new, attributes): def bug_changes(old, new, bugs): change_list = change_lines(old, new, ("time", "creator", "severity", "target", "summary", "status", "assigned")) - if len(change_list) == 0: + + old_comment_ids = list(old.iter_comment_ids()) + new_comment_ids = list(new.iter_comment_ids()) + change_strings = ["%s: %s -> %s" % f for f in change_list] + for comment_id in new_comment_ids: + if comment_id not in old_comment_ids: + summary = comment_summary(new.get_comment(comment_id), "new") + change_strings.append(summary) + for comment_id in old_comment_ids: + if comment_id not in new_comment_ids: + summary = comment_summary(new.get_comment(comment_id), "removed") + change_strings.append(summary) + + if len(change_strings) == 0: return None return "%s%s\n" % (cmdutil.bug_summary(new, bugs, shortlist=True), - "\n".join(["%s: %s -> %s" % f for f in change_list])) + "\n".join(change_strings)) +def comment_summary(comment, status): + return "%8s comment from %s on %s" % (status, comment.From, + time_to_str(comment.date)) diff --git a/libbe/mapfile.py b/libbe/mapfile.py index bbbd860..6a304fd 100644 --- a/libbe/mapfile.py +++ b/libbe/mapfile.py @@ -75,18 +75,18 @@ def parse(f): """ Parse a format-2 mapfile. >>> parse('\\n\\n\\nq=p\\n\\n\\n\\n')['q'] - 'p' + u'p' >>> parse('\\n\\nq=\\'p\\'\\n\\n\\n\\n')['q'] - "\'p\'" + u"\'p\'" >>> f = utility.FileString() >>> generate(f, {"a":"b", "c":"d", "e":"f"}) >>> dict = parse(f) >>> dict["a"] - 'b' + u'b' >>> dict["c"] - 'd' + u'd' >>> dict["e"] - 'f' + u'f' """ f = utility.get_file(f) result = {} |