aboutsummaryrefslogtreecommitdiffstats
path: root/libbe
diff options
context:
space:
mode:
Diffstat (limited to 'libbe')
-rw-r--r--libbe/bugdir.py29
-rw-r--r--libbe/cmdutil.py57
-rw-r--r--libbe/diff.py21
-rw-r--r--libbe/mapfile.py10
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 = {}