diff options
Diffstat (limited to 'becommands')
-rw-r--r-- | becommands/__init__.py | 0 | ||||
-rw-r--r-- | becommands/assign.py | 87 | ||||
-rw-r--r-- | becommands/close.py | 60 | ||||
-rw-r--r-- | becommands/comment.py | 226 | ||||
-rw-r--r-- | becommands/commit.py | 78 | ||||
-rw-r--r-- | becommands/depend.py | 339 | ||||
-rw-r--r-- | becommands/diff.py | 120 | ||||
-rw-r--r-- | becommands/help.py | 68 | ||||
-rw-r--r-- | becommands/html.py | 607 | ||||
-rw-r--r-- | becommands/init.py | 100 | ||||
-rw-r--r-- | becommands/list.py | 248 | ||||
-rw-r--r-- | becommands/merge.py | 165 | ||||
-rw-r--r-- | becommands/new.py | 80 | ||||
-rw-r--r-- | becommands/open.py | 58 | ||||
-rw-r--r-- | becommands/remove.py | 62 | ||||
-rw-r--r-- | becommands/set.py | 130 | ||||
-rw-r--r-- | becommands/severity.py | 103 | ||||
-rw-r--r-- | becommands/show.py | 116 | ||||
-rw-r--r-- | becommands/status.py | 115 | ||||
-rw-r--r-- | becommands/subscribe.py | 390 | ||||
-rw-r--r-- | becommands/tag.py | 134 | ||||
-rw-r--r-- | becommands/target.py | 95 |
22 files changed, 0 insertions, 3381 deletions
diff --git a/becommands/__init__.py b/becommands/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/becommands/__init__.py +++ /dev/null diff --git a/becommands/assign.py b/becommands/assign.py deleted file mode 100644 index 794f028..0000000 --- a/becommands/assign.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc. -# Marien Zwart <marienz@gentoo.org> -# Thomas Gerigk <tgerigk@gmx.de> -# W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Assign an individual or group to fix a bug""" -from libbe import cmdutil, bugdir -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> import os - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> bd.bug_from_shortname("a").assigned is None - True - - >>> execute(["a"], manipulate_encodings=False) - >>> bd._clear_bugs() - >>> bd.bug_from_shortname("a").assigned == bd.user_id - True - - >>> execute(["a", "someone"], manipulate_encodings=False) - >>> bd._clear_bugs() - >>> print bd.bug_from_shortname("a").assigned - someone - - >>> execute(["a","none"], manipulate_encodings=False) - >>> bd._clear_bugs() - >>> bd.bug_from_shortname("a").assigned is None - True - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser, - bugid_args={0: lambda bug : bug.active==True}) - assert(len(args) in (0, 1, 2)) - if len(args) == 0: - raise cmdutil.UsageError("Please specify a bug id.") - if len(args) > 2: - help() - raise cmdutil.UsageError("Too many arguments.") - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - bug = cmdutil.bug_from_shortname(bd, args[0]) - bug = bd.bug_from_shortname(args[0]) - if len(args) == 1: - bug.assigned = bd.user_id - elif len(args) == 2: - if args[1] == "none": - bug.assigned = None - else: - bug.assigned = args[1] - bd.save() - -def get_parser(): - parser = cmdutil.CmdOptionParser("be assign BUG-ID [ASSIGNEE]") - return parser - -longhelp = """ -Assign a person to fix a bug. - -By default, the bug is self-assigned. If an assignee is specified, the bug -will be assigned to that person. - -Assignees should be the person's Bugs Everywhere identity, the string that -appears in Creator fields. - -To un-assign a bug, specify "none" for the assignee. -""" - -def help(): - return get_parser().help_str() + longhelp diff --git a/becommands/close.py b/becommands/close.py deleted file mode 100644 index 0532ed2..0000000 --- a/becommands/close.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc. -# Marien Zwart <marienz@gentoo.org> -# Thomas Gerigk <tgerigk@gmx.de> -# W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Close a bug""" -from libbe import cmdutil, bugdir -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> from libbe import bugdir - >>> import os - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> print bd.bug_from_shortname("a").status - open - >>> execute(["a"], manipulate_encodings=False) - >>> bd._clear_bugs() - >>> print bd.bug_from_shortname("a").status - closed - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser, - bugid_args={0: lambda bug : bug.active==True}) - if len(args) == 0: - raise cmdutil.UsageError("Please specify a bug id.") - if len(args) > 1: - raise cmdutil.UsageError("Too many arguments.") - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - bug = cmdutil.bug_from_shortname(bd, args[0]) - bug.status = "closed" - bd.save() - -def get_parser(): - parser = cmdutil.CmdOptionParser("be close BUG-ID") - return parser - -longhelp=""" -Close the bug identified by BUG-ID. -""" - -def help(): - return get_parser().help_str() + longhelp diff --git a/becommands/comment.py b/becommands/comment.py deleted file mode 100644 index 950a95a..0000000 --- a/becommands/comment.py +++ /dev/null @@ -1,226 +0,0 @@ -# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc. -# Chris Ball <cjb@laptop.org> -# W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Add a comment to a bug""" -from libbe import cmdutil, bugdir, comment, editor -import os -import sys -try: # import core module, Python >= 2.5 - from xml.etree import ElementTree -except ImportError: # look for non-core module - from elementtree import ElementTree -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> import time - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> execute(["a", "This is a comment about a"], manipulate_encodings=False) - >>> bd._clear_bugs() - >>> bug = cmdutil.bug_from_shortname(bd, "a") - >>> bug.load_comments(load_full=False) - >>> comment = bug.comment_root[0] - >>> print comment.body - This is a comment about a - <BLANKLINE> - >>> comment.author == bd.user_id - True - >>> comment.time <= int(time.time()) - True - >>> comment.in_reply_to is None - True - - >>> if 'EDITOR' in os.environ: - ... del os.environ["EDITOR"] - >>> execute(["b"], manipulate_encodings=False) - Traceback (most recent call last): - UserError: No comment supplied, and EDITOR not specified. - - >>> os.environ["EDITOR"] = "echo 'I like cheese' > " - >>> execute(["b"], manipulate_encodings=False) - >>> bd._clear_bugs() - >>> bug = cmdutil.bug_from_shortname(bd, "b") - >>> bug.load_comments(load_full=False) - >>> comment = bug.comment_root[0] - >>> print comment.body - I like cheese - <BLANKLINE> - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - complete(options, args, parser) - if len(args) == 0: - raise cmdutil.UsageError("Please specify a bug or comment id.") - if len(args) > 2: - raise cmdutil.UsageError("Too many arguments.") - - shortname = args[0] - if shortname.count(':') > 1: - raise cmdutil.UserError("Invalid id '%s'." % shortname) - elif shortname.count(':') == 1: - # Split shortname generated by Comment.comment_shortnames() - bugname = shortname.split(':')[0] - is_reply = True - else: - bugname = shortname - is_reply = False - - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - bug = cmdutil.bug_from_shortname(bd, bugname) - bug.load_comments(load_full=False) - if is_reply: - parent = bug.comment_root.comment_from_shortname(shortname, - bug_shortname=bugname) - else: - parent = bug.comment_root - - if len(args) == 1: # try to launch an editor for comment-body entry - try: - if parent == bug.comment_root: - parent_body = bug.summary+"\n" - else: - parent_body = parent.body - estr = "Please enter your comment above\n\n> %s\n" \ - % ("\n> ".join(parent_body.splitlines())) - body = editor.editor_string(estr) - except editor.CantFindEditor, e: - raise cmdutil.UserError, "No comment supplied, and EDITOR not specified." - if body is None: - raise cmdutil.UserError("No comment entered.") - elif args[1] == '-': # read body from stdin - binary = not (options.content_type == None - or options.content_type.startswith("text/")) - if not binary: - body = sys.stdin.read() - if not body.endswith('\n'): - body+='\n' - else: # read-in without decoding - body = sys.__stdin__.read() - else: # body = arg[1] - body = args[1] - if not body.endswith('\n'): - body+='\n' - - if options.XML == False: - new = parent.new_reply(body=body, content_type=options.content_type) - if options.author != None: - new.author = options.author - if options.alt_id != None: - new.alt_id = options.alt_id - else: # import XML comment [list] - # read in the comments - str_body = body.encode("unicode_escape").replace(r'\n', '\n') - comment_list = ElementTree.XML(str_body) - if comment_list.tag not in ["bug", "comment-list"]: - raise comment.InvalidXML( - comment_list, "root element must be <bug> or <comment-list>") - new_comments = [] - ids = [] - for c in bug.comment_root.traverse(): - ids.append(c.uuid) - if c.alt_id != None: - ids.append(c.alt_id) - for child in comment_list.getchildren(): - if child.tag == "comment": - new = comment.Comment(bug) - new.from_xml(unicode(ElementTree.tostring(child)).decode("unicode_escape")) - if new.alt_id in ids: - raise cmdutil.UserError( - "Clashing comment alt_id: %s" % new.alt_id) - ids.append(new.uuid) - if new.alt_id != None: - ids.append(new.alt_id) - if new.in_reply_to == None: - new.in_reply_to = parent.uuid - new_comments.append(new) - else: - print >> sys.stderr, "Ignoring unknown tag %s in %s" \ - % (child.tag, comment_list.tag) - try: - comment.list_to_root(new_comments,bug,root=parent, # link new comments - ignore_missing_references=options.ignore_missing_references) - except comment.MissingReference, e: - raise cmdutil.UserError(e) - # Protect against programmer error causing data loss: - kids = [c.uuid for c in parent.traverse()] - for nc in new_comments: - assert nc.uuid in kids, "%s wasn't added to %s" % (nc.uuid, parent.uuid) - nc.save() - -def get_parser(): - parser = cmdutil.CmdOptionParser("be comment ID [COMMENT]") - parser.add_option("-a", "--author", metavar="AUTHOR", dest="author", - help="Set the comment author", default=None) - parser.add_option("--alt-id", metavar="ID", dest="alt_id", - help="Set an alternate comment ID", default=None) - parser.add_option("-c", "--content-type", metavar="MIME", dest="content_type", - help="Set comment content-type (e.g. text/plain)", default=None) - parser.add_option("-x", "--xml", action="store_true", default=False, - dest='XML', help="Use COMMENT to specify an XML comment description rather than the comment body. The root XML element should be either <bug> or <comment-list> with one or more <comment> children. The syntax for the <comment> elements should match that generated by 'be show --xml COMMENT-ID'. Unrecognized tags are ignored. Missing tags are left at the default value. The comment UUIDs are always auto-generated, so if you set a <uuid> field, but no <alt-id> field, your <uuid> will be used as the comment's <alt-id>. An exception is raised if <alt-id> conflicts with an existing comment.") - parser.add_option("-i", "--ignore-missing-references", action="store_true", - dest="ignore_missing_references", - help="For XML import, if any comment's <in-reply-to> refers to a non-existent comment, ignore it (instead of raising an exception).") - return parser - -longhelp=""" -To add a comment to a bug, use the bug ID as the argument. To reply -to another comment, specify the comment name (as shown in "be show" -output). COMMENT, if specified, should be either the text of your -comment or "-", in which case the text will be read from stdin. If -you do not specify a COMMENT, $EDITOR is used to launch an editor. If -COMMENT is unspecified and EDITOR is not set, no comment will be -created. -""" - -def help(): - return get_parser().help_str() + longhelp - -def complete(options, args, parser): - for option,value in cmdutil.option_value_pairs(options, parser): - if value == "--complete": - # no argument-options at the moment, so this is future-proofing - raise cmdutil.GetCompletions() - for pos,value in enumerate(args): - if value == "--complete": - if pos == 0: # fist positional argument is a bug or comment id - if len(args) >= 2: - partial = args[1].split(':')[0] # take only bugid portion - else: - partial = "" - ids = [] - try: - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=False) - bugs = [] - for uuid in bd.list_uuids(): - if uuid.startswith(partial): - bug = bd.bug_from_uuid(uuid) - if bug.active == True: - bugs.append(bug) - for bug in bugs: - shortname = bd.bug_shortname(bug) - ids.append(shortname) - bug.load_comments(load_full=False) - for id,comment in bug.comment_shortnames(shortname): - ids.append(id) - except bugdir.NoBugDir: - pass - raise cmdutil.GetCompletions(ids) - raise cmdutil.GetCompletions() diff --git a/becommands/commit.py b/becommands/commit.py deleted file mode 100644 index dc70e7e..0000000 --- a/becommands/commit.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (C) 2009 W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Commit the currently pending changes to the repository""" -from libbe import cmdutil, bugdir, editor, vcs -import sys -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> import os, time - >>> from libbe import bug - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> full_path = "testfile" - >>> test_contents = "A test file" - >>> bd.vcs.set_file_contents(full_path, test_contents) - >>> execute(["Added %s." % (full_path)], manipulate_encodings=False) # doctest: +ELLIPSIS - Committed ... - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser) - if len(args) != 1: - raise cmdutil.UsageError("Please supply a commit message") - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - if args[0] == '-': # read summary from stdin - assert options.body != "EDITOR", \ - "Cannot spawn and editor when the summary is using stdin." - summary = sys.stdin.readline() - else: - summary = args[0] - if options.body == None: - body = None - elif options.body == "EDITOR": - body = editor.editor_string("Please enter your commit message above") - else: - body = bd.vcs.get_file_contents(options.body, allow_no_vcs=True) - try: - revision = bd.vcs.commit(summary, body=body, - allow_empty=options.allow_empty) - except vcs.EmptyCommit, e: - print e - return 1 - else: - print "Committed %s" % revision - -def get_parser(): - parser = cmdutil.CmdOptionParser("be commit COMMENT") - parser.add_option("-b", "--body", metavar="FILE", dest="body", - help='Provide a detailed body for the commit message. In the special case that FILE == "EDITOR", spawn an editor to enter the body text (in which case you cannot use stdin for the summary)', default=None) - parser.add_option("-a", "--allow-empty", dest="allow_empty", - help="Allow empty commits", - default=False, action="store_true") - return parser - -longhelp=""" -Commit the current repository status. The summary specified on the -commandline is a string (only one line) that describes the commit -briefly or "-", in which case the string will be read from stdin. -""" - -def help(): - return get_parser().help_str() + longhelp diff --git a/becommands/depend.py b/becommands/depend.py deleted file mode 100644 index f72b8ba..0000000 --- a/becommands/depend.py +++ /dev/null @@ -1,339 +0,0 @@ -# Copyright (C) 2009 W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Add/remove bug dependencies""" -from libbe import cmdutil, bugdir, tree -import os, copy -__desc__ = __doc__ - -BLOCKS_TAG="BLOCKS:" -BLOCKED_BY_TAG="BLOCKED-BY:" - -class BrokenLink (Exception): - def __init__(self, blocked_bug, blocking_bug, blocks=True): - if blocks == True: - msg = "Missing link: %s blocks %s" \ - % (blocking_bug.uuid, blocked_bug.uuid) - else: - msg = "Missing link: %s blocked by %s" \ - % (blocked_bug.uuid, blocking_bug.uuid) - Exception.__init__(self, msg) - self.blocked_bug = blocked_bug - self.blocking_bug = blocking_bug - - -def execute(args, manipulate_encodings=True): - """ - >>> from libbe import utility - >>> bd = bugdir.SimpleBugDir() - >>> bd.save() - >>> os.chdir(bd.root) - >>> execute(["a", "b"], manipulate_encodings=False) - a blocked by: - b - >>> execute(["a"], manipulate_encodings=False) - a blocked by: - b - >>> execute(["--show-status", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - a blocked by: - b closed - >>> execute(["b", "a"], manipulate_encodings=False) - b blocked by: - a - b blocks: - a - >>> execute(["--show-status", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - a blocked by: - b closed - a blocks: - b closed - >>> execute(["-r", "b", "a"], manipulate_encodings=False) - b blocks: - a - >>> execute(["-r", "a", "b"], manipulate_encodings=False) - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser, - bugid_args={0: lambda bug : bug.active==True, - 1: lambda bug : bug.active==True}) - - if options.repair == True: - if len(args) > 0: - raise cmdutil.UsageError("No arguments with --repair calls.") - elif len(args) < 1: - raise cmdutil.UsageError("Please a bug id.") - elif len(args) > 2: - help() - raise cmdutil.UsageError("Too many arguments.") - elif len(args) == 2 and options.tree_depth != None: - raise cmdutil.UsageError("Only one bug id used in tree mode.") - - - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - if options.repair == True: - good,fixed,broken = check_dependencies(bd, repair_broken_links=True) - assert len(broken) == 0, broken - if len(fixed) > 0: - print "Fixed the following links:" - print "\n".join(["%s |-- %s" % (blockee.uuid, blocker.uuid) - for blockee,blocker in fixed]) - return 0 - - bugA = cmdutil.bug_from_shortname(bd, args[0]) - - if options.tree_depth != None: - dtree = DependencyTree(bd, bugA, options.tree_depth) - if len(dtree.blocked_by_tree()) > 0: - print "%s blocked by:" % bugA.uuid - for depth,node in dtree.blocked_by_tree().thread(): - if depth == 0: continue - print "%s%s" % (" "*(depth), node.bug.string(shortlist=True)) - if len(dtree.blocks_tree()) > 0: - print "%s blocks:" % bugA.uuid - for depth,node in dtree.blocks_tree().thread(): - if depth == 0: continue - print "%s%s" % (" "*(depth), node.bug.string(shortlist=True)) - return 0 - - if len(args) == 2: - bugB = cmdutil.bug_from_shortname(bd, args[1]) - if options.remove == True: - remove_block(bugA, bugB) - else: # add the dependency - add_block(bugA, bugB) - - blocked_by = get_blocked_by(bd, bugA) - if len(blocked_by) > 0: - print "%s blocked by:" % bugA.uuid - if options.show_status == True: - print '\n'.join(["%s\t%s" % (bug.uuid, bug.status) - for bug in blocked_by]) - else: - print '\n'.join([bug.uuid for bug in blocked_by]) - blocks = get_blocks(bd, bugA) - if len(blocks) > 0: - print "%s blocks:" % bugA.uuid - if options.show_status == True: - print '\n'.join(["%s\t%s" % (bug.uuid, bug.status) - for bug in blocks]) - else: - print '\n'.join([bug.uuid for bug in blocks]) - -def get_parser(): - parser = cmdutil.CmdOptionParser("be depend BUG-ID [BUG-ID]\nor: be depend --repair") - parser.add_option("-r", "--remove", action="store_true", - dest="remove", default=False, - help="Remove dependency (instead of adding it)") - parser.add_option("-s", "--show-status", action="store_true", - dest="show_status", default=False, - help="Show status of blocking bugs") - parser.add_option("-t", "--tree-depth", metavar="DEPTH", default=None, - type="int", dest="tree_depth", - help="Print dependency tree rooted at BUG-ID with DEPTH levels of both blockers and blockees. Set DEPTH <= 0 to disable the depth limit.") - parser.add_option("--repair", action="store_true", - dest="repair", default=False, - help="Check for and repair one-way links") - return parser - -longhelp=""" -Set a dependency with the second bug (B) blocking the first bug (A). -If bug B is not specified, just print a list of bugs blocking (A). - -To search for bugs blocked by a particular bug, try - $ be list --extra-strings BLOCKED-BY:<your-bug-uuid> - -In repair mode, add the missing direction to any one-way links. - -The "|--" symbol in the repair-mode output is inspired by the -"negative feedback" arrow common in biochemistry. See, for example - http://www.nature.com/nature/journal/v456/n7223/images/nature07513-f5.0.jpg -""" - -def help(): - return get_parser().help_str() + longhelp - -# internal helper functions - -def _generate_blocks_string(blocked_bug): - return "%s%s" % (BLOCKS_TAG, blocked_bug.uuid) - -def _generate_blocked_by_string(blocking_bug): - return "%s%s" % (BLOCKED_BY_TAG, blocking_bug.uuid) - -def _parse_blocks_string(string): - assert string.startswith(BLOCKS_TAG) - return string[len(BLOCKS_TAG):] - -def _parse_blocked_by_string(string): - assert string.startswith(BLOCKED_BY_TAG) - return string[len(BLOCKED_BY_TAG):] - -def _add_remove_extra_string(bug, string, add): - estrs = bug.extra_strings - if add == True: - estrs.append(string) - else: # remove the string - estrs.remove(string) - bug.extra_strings = estrs # reassign to notice change - -def _get_blocks(bug): - uuids = [] - for line in bug.extra_strings: - if line.startswith(BLOCKS_TAG): - uuids.append(_parse_blocks_string(line)) - return uuids - -def _get_blocked_by(bug): - uuids = [] - for line in bug.extra_strings: - if line.startswith(BLOCKED_BY_TAG): - uuids.append(_parse_blocked_by_string(line)) - return uuids - -def _repair_one_way_link(blocked_bug, blocking_bug, blocks=None): - if blocks == True: # add blocks link - blocks_string = _generate_blocks_string(blocked_bug) - _add_remove_extra_string(blocking_bug, blocks_string, add=True) - else: # add blocked by link - blocked_by_string = _generate_blocked_by_string(blocking_bug) - _add_remove_extra_string(blocked_bug, blocked_by_string, add=True) - -# functions exposed to other modules - -def add_block(blocked_bug, blocking_bug): - blocked_by_string = _generate_blocked_by_string(blocking_bug) - _add_remove_extra_string(blocked_bug, blocked_by_string, add=True) - blocks_string = _generate_blocks_string(blocked_bug) - _add_remove_extra_string(blocking_bug, blocks_string, add=True) - -def remove_block(blocked_bug, blocking_bug): - blocked_by_string = _generate_blocked_by_string(blocking_bug) - _add_remove_extra_string(blocked_bug, blocked_by_string, add=False) - blocks_string = _generate_blocks_string(blocked_bug) - _add_remove_extra_string(blocking_bug, blocks_string, add=False) - -def get_blocks(bugdir, bug): - """ - Return a list of bugs that the given bug blocks. - """ - blocks = [] - for uuid in _get_blocks(bug): - blocks.append(bugdir.bug_from_uuid(uuid)) - return blocks - -def get_blocked_by(bugdir, bug): - """ - Return a list of bugs blocking the given bug blocks. - """ - blocked_by = [] - for uuid in _get_blocked_by(bug): - blocked_by.append(bugdir.bug_from_uuid(uuid)) - return blocked_by - -def check_dependencies(bugdir, repair_broken_links=False): - """ - Check that links are bi-directional for all bugs in bugdir. - - >>> bd = bugdir.SimpleBugDir(sync_with_disk=False) - >>> a = bd.bug_from_uuid("a") - >>> b = bd.bug_from_uuid("b") - >>> blocked_by_string = _generate_blocked_by_string(b) - >>> _add_remove_extra_string(a, blocked_by_string, add=True) - >>> good,repaired,broken = check_dependencies(bd, repair_broken_links=False) - >>> good - [] - >>> repaired - [] - >>> broken - [(Bug(uuid='a'), Bug(uuid='b'))] - >>> _get_blocks(b) - [] - >>> good,repaired,broken = check_dependencies(bd, repair_broken_links=True) - >>> _get_blocks(b) - ['a'] - >>> good - [] - >>> repaired - [(Bug(uuid='a'), Bug(uuid='b'))] - >>> broken - [] - """ - if bugdir.sync_with_disk == True: - bugdir.load_all_bugs() - good_links = [] - fixed_links = [] - broken_links = [] - for bug in bugdir: - for blocker in get_blocked_by(bugdir, bug): - blocks = get_blocks(bugdir, blocker) - if (bug, blocks) in good_links+fixed_links+broken_links: - continue # already checked that link - if bug not in blocks: - if repair_broken_links == True: - _repair_one_way_link(bug, blocker, blocks=True) - fixed_links.append((bug, blocker)) - else: - broken_links.append((bug, blocker)) - else: - good_links.append((bug, blocker)) - for blockee in get_blocks(bugdir, bug): - blocked_by = get_blocked_by(bugdir, blockee) - if (blockee, bug) in good_links+fixed_links+broken_links: - continue # already checked that link - if bug not in blocked_by: - if repair_broken_links == True: - _repair_one_way_link(blockee, bug, blocks=False) - fixed_links.append((blockee, bug)) - else: - broken_links.append((blockee, bug)) - else: - good_links.append((blockee, bug)) - return (good_links, fixed_links, broken_links) - -class DependencyTree (object): - """ - Note: should probably be DependencyDiGraph. - """ - def __init__(self, bugdir, root_bug, depth_limit=0): - self.bugdir = bugdir - self.root_bug = root_bug - self.depth_limit = depth_limit - def _build_tree(self, child_fn): - root = tree.Tree() - root.bug = self.root_bug - root.depth = 0 - stack = [root] - while len(stack) > 0: - node = stack.pop() - if self.depth_limit > 0 and node.depth == self.depth_limit: - continue - for bug in child_fn(self.bugdir, node.bug): - child = tree.Tree() - child.bug = bug - child.depth = node.depth+1 - node.append(child) - stack.append(child) - return root - def blocks_tree(self): - if not hasattr(self, "_blocks_tree"): - self._blocks_tree = self._build_tree(get_blocks) - return self._blocks_tree - def blocked_by_tree(self): - if not hasattr(self, "_blocked_by_tree"): - self._blocked_by_tree = self._build_tree(get_blocked_by) - return self._blocked_by_tree diff --git a/becommands/diff.py b/becommands/diff.py deleted file mode 100644 index b6ac5b0..0000000 --- a/becommands/diff.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc. -# W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -"""Compare bug reports with older tree""" -from libbe import cmdutil, bugdir, diff -import os -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> import os - >>> bd = bugdir.SimpleBugDir() - >>> bd.set_sync_with_disk(True) - >>> original = bd.vcs.commit("Original status") - >>> bug = bd.bug_from_uuid("a") - >>> bug.status = "closed" - >>> changed = bd.vcs.commit("Closed bug a") - >>> os.chdir(bd.root) - >>> if bd.vcs.versioned == True: - ... execute([original], manipulate_encodings=False) - ... else: - ... print "Modified bugs:\\n a:cm: Bug A\\n Changed bug settings:\\n status: open -> closed" - Modified bugs: - a:cm: Bug A - Changed bug settings: - status: open -> closed - >>> if bd.vcs.versioned == True: - ... execute(["--modified", original], manipulate_encodings=False) - ... else: - ... print "a" - a - >>> if bd.vcs.versioned == False: - ... execute([original], manipulate_encodings=False) - ... else: - ... print "This directory is not revision-controlled." - This directory is not revision-controlled. - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser) - if len(args) == 0: - revision = None - if len(args) == 1: - revision = args[0] - if len(args) > 1: - raise cmdutil.UsageError("Too many arguments.") - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - if bd.vcs.versioned == False: - print "This directory is not revision-controlled." - else: - if revision == None: # get the most recent revision - revision = bd.vcs.revision_id(-1) - old_bd = bd.duplicate_bugdir(revision) - d = diff.Diff(old_bd, bd) - tree = d.report_tree() - - uuids = [] - if options.all == True: - options.new = options.modified = options.removed = True - if options.new == True: - uuids.extend([c.name for c in tree.child_by_path("/bugs/new")]) - if options.modified == True: - uuids.extend([c.name for c in tree.child_by_path("/bugs/mod")]) - if options.removed == True: - uuids.extend([c.name for c in tree.child_by_path("/bugs/rem")]) - if (options.new or options.modified or options.removed) == True: - print "\n".join(uuids) - else : - rep = tree.report_string() - if rep != None: - print rep - bd.remove_duplicate_bugdir() - -def get_parser(): - parser = cmdutil.CmdOptionParser("be diff [options] REVISION") - # boolean options - bools = (("n", "new", "Print UUIDS for new bugs"), - ("m", "modified", "Print UUIDS for modified bugs"), - ("r", "removed", "Print UUIDS for removed bugs"), - ("a", "all", "Print UUIDS for all changed bugs")) - for s in bools: - attr = s[1].replace('-','_') - short = "-%c" % s[0] - long = "--%s" % s[1] - help = s[2] - parser.add_option(short, long, action="store_true", - default=False, dest=attr, help=help) - return parser - -longhelp=""" -Uses the VCS to compare the current tree with a previous tree, and -prints a pretty report. If REVISION is given, it is a specifier for -the particular previous tree to use. Specifiers are specific to their -VCS. - -For Arch your specifier must be a fully-qualified revision name. - -Besides the standard summary output, you can use the options to output -UUIDS for the different categories. This output can be used as the -input to 'be show' to get and understanding of the current status. -""" - -def help(): - return get_parser().help_str() + longhelp diff --git a/becommands/help.py b/becommands/help.py deleted file mode 100644 index a8f346a..0000000 --- a/becommands/help.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (C) 2006-2009 Aaron Bentley and Panometrics, Inc. -# Thomas Gerigk <tgerigk@gmx.de> -# W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Print help for given subcommand""" -from libbe import cmdutil, utility -__desc__ = __doc__ - -def execute(args, manipulate_encodings=False): - """ - Print help of specified command (the manipulate_encodings argument - is ignored). - - >>> execute(["help"]) - Usage: be help [COMMAND] - <BLANKLINE> - Options: - -h, --help Print a help message - --complete Print a list of available completions - <BLANKLINE> - Print help for specified command or list of all commands. - <BLANKLINE> - """ - parser = get_parser() - options, args = parser.parse_args(args) - complete(options, args, parser) - if len(args) > 1: - raise cmdutil.UsageError("Too many arguments.") - if len(args) == 0: - print cmdutil.help() - else: - try: - print cmdutil.help(args[0]) - except AttributeError: - print "No help available" - -def get_parser(): - parser = cmdutil.CmdOptionParser("be help [COMMAND]") - return parser - -longhelp=""" -Print help for specified command or list of all commands. -""" - -def help(): - return get_parser().help_str() + longhelp - -def complete(options, args, parser): - for option, value in cmdutil.option_value_pairs(options, parser): - if value == "--complete": - # no argument-options at the moment, so this is future-proofing - raise cmdutil.GetCompletions() - if "--complete" in args: - cmds = [command for command,module in cmdutil.iter_commands()] - raise cmdutil.GetCompletions(cmds) diff --git a/becommands/html.py b/becommands/html.py deleted file mode 100644 index b0640da..0000000 --- a/becommands/html.py +++ /dev/null @@ -1,607 +0,0 @@ -# Copyright (C) 2009 Gianluca Montecchi <gian@grys.it> -# W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Generate a static HTML dump of the current repository status""" -from libbe import cmdutil, bugdir, bug -import codecs, os, os.path, re, string, time -import xml.sax.saxutils, htmlentitydefs - -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> import os - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> execute([], manipulate_encodings=False) - >>> os.path.exists("./html_export") - True - >>> os.path.exists("./html_export/index.html") - True - >>> os.path.exists("./html_export/index_inactive.html") - True - >>> os.path.exists("./html_export/bugs") - True - >>> os.path.exists("./html_export/bugs/a.html") - True - >>> os.path.exists("./html_export/bugs/b.html") - True - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - complete(options, args, parser) - cmdutil.default_complete(options, args, parser) - - if len(args) > 0: - raise cmdutil.UsageError, 'Too many arguments.' - - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - bd.load_all_bugs() - - html_gen = HTMLGen(bd, template=options.template, verbose=options.verbose, - title=options.title, index_header=options.index_header) - if options.exp_template == True: - html_gen.write_default_template(options.exp_template_dir) - return - html_gen.run(options.out_dir) - -def get_parser(): - parser = cmdutil.CmdOptionParser('be html [options]') - parser.add_option('-o', '--output', metavar='DIR', dest='out_dir', - help='Set the output path (%default)', default='./html_export') - parser.add_option('-t', '--template-dir', metavar='DIR', dest='template', - help='Use a different template, defaults to internal templates', - default=None) - parser.add_option('--title', metavar='STRING', dest='title', - help='Set the bug repository title (%default)', - default='BugsEverywhere Issue Tracker') - parser.add_option('--index-header', metavar='STRING', dest='index_header', - help='Set the index page headers (%default)', - default='BugsEverywhere Bug List') - parser.add_option('-v', '--verbose', action='store_true', - metavar='verbose', dest='verbose', - help='Verbose output, default is %default', default=False) - parser.add_option('-e', '--export-template', action='store_true', - dest='exp_template', - help='Export the default template and exit.', default=False) - parser.add_option('-d', '--export-template-dir', metavar='DIR', - dest='exp_template_dir', default='./default-templates/', - help='Set the directory for the template export (%default)') - return parser - -longhelp=""" -Generate a set of html pages representing the current state of the bug -directory. -""" - -def help(): - return get_parser().help_str() + longhelp - -def complete(options, args, parser): - for option, value in cmdutil.option_value_pairs(options, parser): - if "--complete" in args: - raise cmdutil.GetCompletions() # no positional arguments for list - -class HTMLGen (object): - def __init__(self, bd, template=None, verbose=False, encoding=None, - title="Site Title", index_header="Index Header", - ): - self.generation_time = time.ctime() - self.bd = bd - self.verbose = verbose - self.title = title - self.index_header = index_header - if encoding != None: - self.encoding = encoding - else: - self.encoding = self.bd.encoding - if template == None: - self.template = "default" - else: - self.template = os.path.abspath(os.path.expanduser(template)) - self._load_default_templates() - - if template != None: - self._load_user_templates() - - def run(self, out_dir): - if self.verbose == True: - print "Creating the html output in %s using templates in %s" \ - % (out_dir, self.template) - - bugs_active = [] - bugs_inactive = [] - bugs = [b for b in self.bd] - bugs.sort() - bugs_active = [b for b in bugs if b.active == True] - bugs_inactive = [b for b in bugs if b.active != True] - - self._create_output_directories(out_dir) - self._write_css_file() - for b in bugs: - if b.active: - up_link = "../index.html" - else: - up_link = "../index_inactive.html" - self._write_bug_file(b, up_link) - self._write_index_file( - bugs_active, title=self.title, - index_header=self.index_header, bug_type="active") - self._write_index_file( - bugs_inactive, title=self.title, - index_header=self.index_header, bug_type="inactive") - - def _create_output_directories(self, out_dir): - if self.verbose: - print "Creating output directories" - self.out_dir = self._make_dir(out_dir) - self.out_dir_bugs = self._make_dir( - os.path.join(self.out_dir, "bugs")) - - def _write_css_file(self): - if self.verbose: - print "Writing css file" - assert hasattr(self, "out_dir"), \ - "Must run after ._create_output_directories()" - self._write_file(self.css_file, - [self.out_dir,"style.css"]) - - def _write_bug_file(self, bug, up_link): - if self.verbose: - print "\tCreating bug file for %s" % self.bd.bug_shortname(bug) - assert hasattr(self, "out_dir_bugs"), \ - "Must run after ._create_output_directories()" - - bug.load_comments(load_full=True) - comment_entries = self._generate_bug_comment_entries(bug) - filename = "%s.html" % bug.uuid - fullpath = os.path.join(self.out_dir_bugs, filename) - template_info = {'title':self.title, - 'charset':self.encoding, - 'up_link':up_link, - 'shortname':self.bd.bug_shortname(bug), - 'comment_entries':comment_entries, - 'generation_time':self.generation_time} - for attr in ['uuid', 'severity', 'status', 'assigned', 'target', - 'reporter', 'creator', 'time_string', 'summary']: - template_info[attr] = self._escape(getattr(bug, attr)) - self._write_file(self.bug_file % template_info, [fullpath]) - - def _generate_bug_comment_entries(self, bug): - assert hasattr(self, "out_dir_bugs"), \ - "Must run after ._create_output_directories()" - - stack = [] - comment_entries = [] - for depth,comment in bug.comment_root.thread(flatten=False): - while len(stack) > depth: - # pop non-parents off the stack - stack.pop(-1) - # close non-parent <div class="comment... - comment_entries.append("</div>\n") - assert len(stack) == depth - stack.append(comment) - if depth == 0: - comment_entries.append('<div class="comment root">') - else: - comment_entries.append('<div class="comment">') - template_info = {} - for attr in ['uuid', 'author', 'date', 'body']: - value = getattr(comment, attr) - if attr == 'body': - save_body = False - if comment.content_type == 'text/html': - pass # no need to escape html... - elif comment.content_type.startswith('text/'): - value = '<pre>\n'+self._escape(value)+'\n</pre>' - elif comment.content_type.startswith('image/'): - save_body = True - value = '<img src="./%s/%s" />' \ - % (bug.uuid, comment.uuid) - else: - save_body = True - value = '<a href="./%s/%s">Link to %s file</a>.' \ - % (bug.uuid, comment.uuid, comment.content_type) - if save_body == True: - per_bug_dir = os.path.join(self.out_dir_bugs, bug.uuid) - if not os.path.exists(per_bug_dir): - os.mkdir(per_bug_dir) - comment_path = os.path.join(per_bug_dir, comment.uuid) - self._write_file( - '<Files %s>\n ForceType %s\n</Files>' \ - % (comment.uuid, comment.content_type), - [per_bug_dir, '.htaccess'], mode='a') - self._write_file( - comment.body, - [per_bug_dir, comment.uuid], mode='wb') - else: - value = self._escape(value) - template_info[attr] = value - comment_entries.append(self.bug_comment_entry % template_info) - while len(stack) > 0: - stack.pop(-1) - comment_entries.append("</div>\n") # close every remaining <div class="comment... - return '\n'.join(comment_entries) - - def _write_index_file(self, bugs, title, index_header, bug_type="active"): - if self.verbose: - print "Writing %s index file for %d bugs" % (bug_type, len(bugs)) - assert hasattr(self, "out_dir"), "Must run after ._create_output_directories()" - esc = self._escape - - bug_entries = self._generate_index_bug_entries(bugs) - - if bug_type == "active": - filename = "index.html" - elif bug_type == "inactive": - filename = "index_inactive.html" - else: - raise Exception, "Unrecognized bug_type: '%s'" % bug_type - template_info = {'title':title, - 'index_header':index_header, - 'charset':self.encoding, - 'active_class':'tab sel', - 'inactive_class':'tab nsel', - 'bug_entries':bug_entries, - 'generation_time':self.generation_time} - if bug_type == "inactive": - template_info['active_class'] = 'tab nsel' - template_info['inactive_class'] = 'tab sel' - - self._write_file(self.index_file % template_info, - [self.out_dir, filename]) - - def _generate_index_bug_entries(self, bugs): - bug_entries = [] - for bug in bugs: - if self.verbose: - print "\tCreating bug entry for %s" % self.bd.bug_shortname(bug) - template_info = {'shortname':self.bd.bug_shortname(bug)} - for attr in ['uuid', 'severity', 'status', 'assigned', 'target', - 'reporter', 'creator', 'time_string', 'summary']: - template_info[attr] = self._escape(getattr(bug, attr)) - bug_entries.append(self.index_bug_entry % template_info) - return '\n'.join(bug_entries) - - def _escape(self, string): - if string == None: - return "" - chars = [] - for char in string: - codepoint = ord(char) - if codepoint in htmlentitydefs.codepoint2name: - char = "&%s;" % htmlentitydefs.codepoint2name[codepoint] - #else: xml.sax.saxutils.escape(char) - chars.append(char) - return "".join(chars) - - def _load_user_templates(self): - for filename,attr in [('style.css','css_file'), - ('index_file.tpl','index_file'), - ('index_bug_entry.tpl','index_bug_entry'), - ('bug_file.tpl','bug_file'), - ('bug_comment_entry.tpl','bug_comment_entry')]: - fullpath = os.path.join(self.template, filename) - if os.path.exists(fullpath): - setattr(self, attr, self._read_file([fullpath])) - - def _make_dir(self, dir_path): - dir_path = os.path.abspath(os.path.expanduser(dir_path)) - if not os.path.exists(dir_path): - try: - os.makedirs(dir_path) - except: - raise cmdutil.UsageError, "Cannot create output directory '%s'." % dir_path - return dir_path - - def _write_file(self, content, path_array, mode='w'): - f = codecs.open(os.path.join(*path_array), mode, self.encoding) - f.write(content) - f.close() - - def _read_file(self, path_array, mode='r'): - f = codecs.open(os.path.join(*path_array), mode, self.encoding) - content = f.read() - f.close() - return content - - def write_default_template(self, out_dir): - if self.verbose: - print "Creating output directories" - self.out_dir = self._make_dir(out_dir) - if self.verbose: - print "Creating css file" - self._write_css_file() - if self.verbose: - print "Creating index_file.tpl file" - self._write_file(self.index_file, - [self.out_dir, "index_file.tpl"]) - if self.verbose: - print "Creating index_bug_entry.tpl file" - self._write_file(self.index_bug_entry, - [self.out_dir, "index_bug_entry.tpl"]) - if self.verbose: - print "Creating bug_file.tpl file" - self._write_file(self.bug_file, - [self.out_dir, "bug_file.tpl"]) - if self.verbose: - print "Creating bug_comment_entry.tpl file" - self._write_file(self.bug_comment_entry, - [self.out_dir, "bug_comment_entry.tpl"]) - - def _load_default_templates(self): - self.css_file = """ - body { - font-family: "lucida grande", "sans serif"; - color: #333; - width: auto; - margin: auto; - } - - div.main { - padding: 20px; - margin: auto; - padding-top: 0; - margin-top: 1em; - background-color: #fcfcfc; - } - - div.footer { - font-size: small; - padding-left: 20px; - padding-right: 20px; - padding-top: 5px; - padding-bottom: 5px; - margin: auto; - background: #305275; - color: #fffee7; - } - - table { - border-style: solid; - border: 10px #313131; - border-spacing: 0; - width: auto; - } - - tb { border: 1px; } - - tr { - vertical-align: top; - width: auto; - } - - td { - border-width: 0; - border-style: none; - padding-right: 0.5em; - padding-left: 0.5em; - width: auto; - } - - img { border-style: none; } - - h1 { - padding: 0.5em; - background-color: #305275; - margin-top: 0; - margin-bottom: 0; - color: #fff; - margin-left: -20px; - margin-right: -20px; - } - - ul { - list-style-type: none; - padding: 0; - } - - p { width: auto; } - - a, a:visited { - background: inherit; - text-decoration: none; - } - - a { color: #003d41; } - a:visited { color: #553d41; } - .footer a { color: #508d91; } - - /* bug index pages */ - - td.tab { - padding-right: 1em; - padding-left: 1em; - } - - td.sel.tab { - background-color: #afafaf; - border: 1px solid #afafaf; - font-weight:bold; - } - - td.nsel.tab { border: 0px; } - - table.bug_list { - background-color: #afafaf; - border: 2px solid #afafaf; - } - - .bug_list tr { width: auto; } - tr.wishlist { background-color: #B4FF9B; } - tr.minor { background-color: #FCFF98; } - tr.serious { background-color: #FFB648; } - tr.critical { background-color: #FF752A; } - tr.fatal { background-color: #FF3300; } - - /* bug detail pages */ - - td.bug_detail_label { text-align: right; } - td.bug_detail { } - td.bug_comment_label { text-align: right; vertical-align: top; } - td.bug_comment { } - - div.comment { - padding: 20px; - padding-top: 20px; - margin: auto; - margin-top: 0; - } - - div.root.comment { - padding: 0px; - /* padding-top: 0px; */ - padding-bottom: 20px; - } - """ - - self.index_file = """ - <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> - <head> - <title>%(title)s</title> - <meta http-equiv="Content-Type" content="text/html; charset=%(charset)s" /> - <link rel="stylesheet" href="style.css" type="text/css" /> - </head> - <body> - - <div class="main"> - <h1>%(index_header)s</h1> - <p></p> - <table> - - <tr> - <td class="%(active_class)s"><a href="index.html">Active Bugs</a></td> - <td class="%(inactive_class)s"><a href="index_inactive.html">Inactive Bugs</a></td> - </tr> - - </table> - <table class="bug_list"> - <tbody> - - %(bug_entries)s - - </tbody> - </table> - </div> - - <div class="footer"> - <p>Generated by <a href="http://www.bugseverywhere.org/"> - BugsEverywhere</a> on %(generation_time)s</p> - <p> - <a href="http://validator.w3.org/check?uri=referer">Validate XHTML</a> | - <a href="http://jigsaw.w3.org/css-validator/check?uri=referer">Validate CSS</a> - </p> - </div> - - </body> - </html> - """ - - self.index_bug_entry =""" - <tr class="%(severity)s"> - <td><a href="bugs/%(uuid)s.html">%(shortname)s</a></td> - <td><a href="bugs/%(uuid)s.html">%(status)s</a></td> - <td><a href="bugs/%(uuid)s.html">%(severity)s</a></td> - <td><a href="bugs/%(uuid)s.html">%(summary)s</a></td> - <td><a href="bugs/%(uuid)s.html">%(time_string)s</a></td> - </tr> - """ - - self.bug_file = """ - <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> - <head> - <title>%(title)s</title> - <meta http-equiv="Content-Type" content="text/html; charset=%(charset)s" /> - <link rel="stylesheet" href="../style.css" type="text/css" /> - </head> - <body> - - <div class="main"> - <h1>BugsEverywhere Bug List</h1> - <h5><a href="%(up_link)s">Back to Index</a></h5> - <h2>Bug: %(shortname)s</h2> - <table> - <tbody> - - <tr><td class="bug_detail_label">ID :</td> - <td class="bug_detail">%(uuid)s</td></tr> - <tr><td class="bug_detail_label">Short name :</td> - <td class="bug_detail">%(shortname)s</td></tr> - <tr><td class="bug_detail_label">Status :</td> - <td class="bug_detail">%(status)s</td></tr> - <tr><td class="bug_detail_label">Severity :</td> - <td class="bug_detail">%(severity)s</td></tr> - <tr><td class="bug_detail_label">Assigned :</td> - <td class="bug_detail">%(assigned)s</td></tr> - <tr><td class="bug_detail_label">Reporter :</td> - <td class="bug_detail">%(reporter)s</td></tr> - <tr><td class="bug_detail_label">Creator :</td> - <td class="bug_detail">%(creator)s</td></tr> - <tr><td class="bug_detail_label">Created :</td> - <td class="bug_detail">%(time_string)s</td></tr> - <tr><td class="bug_detail_label">Summary :</td> - <td class="bug_detail">%(summary)s</td></tr> - </tbody> - </table> - - <hr/> - - %(comment_entries)s - - </div> - <h5><a href="%(up_link)s">Back to Index</a></h5> - - <div class="footer"> - <p>Generated by <a href="http://www.bugseverywhere.org/"> - BugsEverywhere</a> on %(generation_time)s</p> - <p> - <a href="http://validator.w3.org/check?uri=referer">Validate XHTML</a> | - <a href="http://jigsaw.w3.org/css-validator/check?uri=referer">Validate CSS</a> - </p> - </div> - - </body> - </html> - """ - - self.bug_comment_entry =""" - <table> - <tr> - <td class="bug_comment_label">Comment:</td> - <td class="bug_comment"> - --------- Comment ---------<br/> - Name: %(uuid)s<br/> - From: %(author)s<br/> - Date: %(date)s<br/> - <br/> - %(body)s - </td> - </tr> - </table> - """ - - # strip leading whitespace - for attr in ['css_file', 'index_file', 'index_bug_entry', 'bug_file', - 'bug_comment_entry']: - value = getattr(self, attr) - value = value.replace('\n'+' '*12, '\n') - setattr(self, attr, value.strip()+'\n') diff --git a/becommands/init.py b/becommands/init.py deleted file mode 100644 index a6098ba..0000000 --- a/becommands/init.py +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc. -# W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Assign the root directory for bug tracking""" -import os.path -from libbe import cmdutil, bugdir -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> from libbe import utility, vcs - >>> import os - >>> dir = utility.Dir() - >>> try: - ... bugdir.BugDir(dir.path) - ... except bugdir.NoBugDir, e: - ... True - True - >>> execute(['--root', dir.path], manipulate_encodings=False) - No revision control detected. - Directory initialized. - >>> dir.cleanup() - - >>> dir = utility.Dir() - >>> os.chdir(dir.path) - >>> vcs = vcs.installed_vcs() - >>> vcs.init('.') - >>> print vcs.name - Arch - >>> execute([], manipulate_encodings=False) - Using Arch for revision control. - Directory initialized. - >>> vcs.cleanup() - - >>> try: - ... execute(['--root', '.'], manipulate_encodings=False) - ... except cmdutil.UserError, e: - ... str(e).startswith("Directory already initialized: ") - True - >>> execute(['--root', '/highly-unlikely-to-exist'], manipulate_encodings=False) - Traceback (most recent call last): - UserError: No such directory: /highly-unlikely-to-exist - >>> os.chdir('/') - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser) - if len(args) > 0: - raise cmdutil.UsageError - try: - bd = bugdir.BugDir(options.root_dir, from_disk=False, - sink_to_existing_root=False, - assert_new_BugDir=True, - manipulate_encodings=manipulate_encodings) - except bugdir.NoRootEntry: - raise cmdutil.UserError("No such directory: %s" % options.root_dir) - except bugdir.AlreadyInitialized: - raise cmdutil.UserError("Directory already initialized: %s" % options.root_dir) - bd.save() - if bd.vcs.name is not "None": - print "Using %s for revision control." % bd.vcs.name - else: - print "No revision control detected." - print "Directory initialized." - -def get_parser(): - parser = cmdutil.CmdOptionParser("be init") - parser.add_option("-r", "--root", metavar="DIR", dest="root_dir", - help="Set root dir to something other than the current directory.", - default=".") - return parser - -longhelp=""" -This command initializes Bugs Everywhere support for the specified directory -and all its subdirectories. It will auto-detect any supported revision control -system. You can use "be set vcs_name" to change the vcs being used. - -The directory defaults to your current working directory. - -It is usually a good idea to put the Bugs Everywhere root at the source code -root, but you can put it anywhere. If you root Bugs Everywhere in a -subdirectory, then only bugs created in that subdirectory (and its children) -will appear there. -""" - -def help(): - return get_parser().help_str() + longhelp diff --git a/becommands/list.py b/becommands/list.py deleted file mode 100644 index 12e1e29..0000000 --- a/becommands/list.py +++ /dev/null @@ -1,248 +0,0 @@ -# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc. -# Chris Ball <cjb@laptop.org> -# Oleg Romanyshyn <oromanyshyn@panoramicfeedback.com> -# W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""List bugs""" -from libbe import cmdutil, bugdir, bug -import os -import re -__desc__ = __doc__ - -# get a list of * for cmp_*() comparing two bugs. -AVAILABLE_CMPS = [fn[4:] for fn in dir(bug) if fn[:4] == 'cmp_'] -AVAILABLE_CMPS.remove("attr") # a cmp_* template. - -def execute(args, manipulate_encodings=True): - """ - >>> import os - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> execute([], manipulate_encodings=False) - a:om: Bug A - >>> execute(["--status", "all"], manipulate_encodings=False) - a:om: Bug A - b:cm: Bug B - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - complete(options, args, parser) - if len(args) > 0: - raise cmdutil.UsageError("Too many arguments.") - cmp_list = [] - if options.sort_by != None: - for cmp in options.sort_by.split(','): - if cmp not in AVAILABLE_CMPS: - raise cmdutil.UserError( - "Invalid sort on '%s'.\nValid sorts:\n %s" - % (cmp, '\n '.join(AVAILABLE_CMPS))) - cmp_list.append(eval('bug.cmp_%s' % cmp)) - - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - bd.load_all_bugs() - # select status - if options.status != None: - if options.status == "all": - status = bug.status_values - else: - status = options.status.split(',') - else: - status = [] - if options.active == True: - status.extend(list(bug.active_status_values)) - if options.unconfirmed == True: - status.append("unconfirmed") - if options.open == True: - status.append("opened") - if options.test == True: - status.append("test") - if status == []: # set the default value - status = bug.active_status_values - # select severity - if options.severity != None: - if options.severity == "all": - severity = bug.severity_values - else: - severity = options.severity.split(',') - else: - severity = [] - if options.wishlist == True: - severity.extend("wishlist") - if options.important == True: - serious = bug.severity_values.index("serious") - severity.append(list(bug.severity_values[serious:])) - if severity == []: # set the default value - severity = bug.severity_values - # select assigned - if options.assigned != None: - if options.assigned == "all": - assigned = "all" - else: - assigned = options.assigned.split(',') - else: - assigned = [] - if options.mine == True: - assigned.extend('-') - if assigned == []: # set the default value - assigned = "all" - for i in range(len(assigned)): - if assigned[i] == '-': - assigned[i] = bd.user_id - # select target - if options.target != None: - if options.target == "all": - target = "all" - else: - target = options.target.split(',') - else: - target = [] - if options.cur_target == True: - target.append(bd.target) - if target == []: # set the default value - target = "all" - if options.extra_strings != None: - extra_string_regexps = [re.compile(x) for x in options.extra_strings.split(',')] - - def filter(bug): - if status != "all" and not bug.status in status: - return False - if severity != "all" and not bug.severity in severity: - return False - if assigned != "all" and not bug.assigned in assigned: - return False - if target != "all" and not bug.target in target: - return False - if options.extra_strings != None: - if len(bug.extra_strings) == 0 and len(extra_string_regexps) > 0: - return False - for string in bug.extra_strings: - for regexp in extra_string_regexps: - if not regexp.match(string): - return False - return True - - bugs = [b for b in bd if filter(b) ] - if len(bugs) == 0 and options.xml == False: - print "No matching bugs found" - - def list_bugs(cur_bugs, title=None, just_uuids=False, xml=False): - if xml == True: - print '<?xml version="1.0" encoding="%s" ?>' % bd.encoding - print "<bugs>" - if len(cur_bugs) > 0: - if title != None and xml == False: - print cmdutil.underlined(title) - for bg in cur_bugs: - if xml == True: - print bg.xml(show_comments=True) - elif just_uuids: - print bg.uuid - else: - print bg.string(shortlist=True) - if xml == True: - print "</bugs>" - - # sort bugs - cmp_list.extend(bug.DEFAULT_CMP_FULL_CMP_LIST) - cmp_fn = bug.BugCompoundComparator(cmp_list=cmp_list) - bugs.sort(cmp_fn) - - # print list of bugs - list_bugs(bugs, just_uuids=options.uuids, xml=options.xml) - -def get_parser(): - parser = cmdutil.CmdOptionParser("be list [options]") - parser.add_option("-s", "--status", metavar="STATUS", dest="status", - help="List bugs matching STATUS", default=None) - parser.add_option("-v", "--severity", metavar="SEVERITY", dest="severity", - help="List bugs matching SEVERITY", default=None) - parser.add_option("-a", "--assigned", metavar="ASSIGNED", dest="assigned", - help="List bugs matching ASSIGNED", default=None) - parser.add_option("-t", "--target", metavar="TARGET", dest="target", - help="List bugs matching TARGET", default=None) - parser.add_option("-e", "--extra-strings", metavar="STRINGS", dest="extra_strings", - help="List bugs matching _all_ extra strings in comma-seperated list STRINGS. e.g. --extra-strings TAG:working,TAG:xml", default=None) - parser.add_option("-S", "--sort", metavar="SORT-BY", dest="sort_by", - help="Adjust bug-sort criteria with comma-separated list SORT-BY. e.g. \"--sort creator,time\". Available criteria: %s" % ','.join(AVAILABLE_CMPS), default=None) - # boolean options. All but uuids and xml are special cases of long forms - bools = (("u", "uuids", "Only print the bug UUIDS"), - ("w", "wishlist", "List bugs with 'wishlist' severity"), - ("i", "important", "List bugs with >= 'serious' severity"), - ("A", "active", "List all active bugs"), - ("U", "unconfirmed", "List unconfirmed bugs"), - ("o", "open", "List open bugs"), - ("T", "test", "List bugs in testing"), - ("m", "mine", "List bugs assigned to you"), - ("c", "cur-target", "List bugs for the current target"), - ("x", "xml", "Dump as XML")) - for s in bools: - attr = s[1].replace('-','_') - short = "-%c" % s[0] - long = "--%s" % s[1] - help = s[2] - parser.add_option(short, long, action="store_true", - dest=attr, help=help) - return parser - - -def help(): - longhelp=""" -This command lists bugs. Normally it prints a short string like - 576:om: Allow attachments -Where - 576 the bug id - o the bug status is 'open' (first letter) - m the bug severity is 'minor' (first letter) - Allo... the bug summary string - -You can optionally (-u) print only the bug ids. - -There are several criteria that you can filter by: - * status - * severity - * assigned (who the bug is assigned to) - * target (bugfix deadline) -Allowed values for each criterion may be given in a comma seperated -list. The special string "all" may be used with any of these options -to match all values of the criterion. - -status - %s -severity - %s -assigned - free form, with the string '-' being a shortcut for yourself. -target - free form - -In addition, there are some shortcut options that set boolean flags. -The boolean options are ignored if the matching string option is used. -""" % (','.join(bug.status_values), - ','.join(bug.severity_values)) - return get_parser().help_str() + longhelp - -def complete(options, args, parser): - for option, value in cmdutil.option_value_pairs(options, parser): - if value == "--complete": - if option == "status": - raise cmdutil.GetCompletions(bug.status_values) - elif option == "severity": - raise cmdutil.GetCompletions(bug.severity_values) - raise cmdutil.GetCompletions() - if "--complete" in args: - raise cmdutil.GetCompletions() # no positional arguments for list diff --git a/becommands/merge.py b/becommands/merge.py deleted file mode 100644 index f212b01..0000000 --- a/becommands/merge.py +++ /dev/null @@ -1,165 +0,0 @@ -# Copyright (C) 2008-2009 W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Merge duplicate bugs""" -from libbe import cmdutil, bugdir -import os, copy -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> from libbe import utility - >>> bd = bugdir.SimpleBugDir() - >>> bd.set_sync_with_disk(True) - >>> a = bd.bug_from_shortname("a") - >>> a.comment_root.time = 0 - >>> dummy = a.new_comment("Testing") - >>> dummy.time = 1 - >>> dummy = dummy.new_reply("Testing...") - >>> dummy.time = 2 - >>> b = bd.bug_from_shortname("b") - >>> b.status = "open" - >>> b.comment_root.time = 0 - >>> dummy = b.new_comment("1 2") - >>> dummy.time = 1 - >>> dummy = dummy.new_reply("1 2 3 4") - >>> dummy.time = 2 - >>> os.chdir(bd.root) - >>> execute(["a", "b"], manipulate_encodings=False) - Merging bugs a and b - >>> bd._clear_bugs() - >>> a = bd.bug_from_shortname("a") - >>> a.load_comments() - >>> mergeA = a.comment_from_shortname(":3") - >>> mergeA.time = 3 - >>> print a.string(show_comments=True) # doctest: +ELLIPSIS - ID : a - Short name : a - Severity : minor - Status : open - Assigned : - Target : - Reporter : - Creator : John Doe <jdoe@example.com> - Created : ... - Bug A - --------- Comment --------- - Name: a:1 - From: ... - Date: ... - <BLANKLINE> - Testing - --------- Comment --------- - Name: a:2 - From: ... - Date: ... - <BLANKLINE> - Testing... - --------- Comment --------- - Name: a:3 - From: ... - Date: ... - <BLANKLINE> - Merged from bug b - --------- Comment --------- - Name: a:4 - From: ... - Date: ... - <BLANKLINE> - 1 2 - --------- Comment --------- - Name: a:5 - From: ... - Date: ... - <BLANKLINE> - 1 2 3 4 - >>> b = bd.bug_from_shortname("b") - >>> b.load_comments() - >>> mergeB = b.comment_from_shortname(":3") - >>> mergeB.time = 3 - >>> print b.string(show_comments=True) # doctest: +ELLIPSIS - ID : b - Short name : b - Severity : minor - Status : closed - Assigned : - Target : - Reporter : - Creator : Jane Doe <jdoe@example.com> - Created : ... - Bug B - --------- Comment --------- - Name: b:1 - From: ... - Date: ... - <BLANKLINE> - 1 2 - --------- Comment --------- - Name: b:2 - From: ... - Date: ... - <BLANKLINE> - 1 2 3 4 - --------- Comment --------- - Name: b:3 - From: ... - Date: ... - <BLANKLINE> - Merged into bug a - >>> print b.status - closed - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser, - bugid_args={0: lambda bug : bug.active==True, - 1: lambda bug : bug.active==True}) - - if len(args) < 2: - raise cmdutil.UsageError("Please specify two bug ids.") - if len(args) > 2: - help() - raise cmdutil.UsageError("Too many arguments.") - - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - bugA = cmdutil.bug_from_shortname(bd, args[0]) - bugA.load_comments() - bugB = cmdutil.bug_from_shortname(bd, args[1]) - bugB.load_comments() - mergeA = bugA.new_comment("Merged from bug %s" % bugB.uuid) - newCommTree = copy.deepcopy(bugB.comment_root) - for comment in newCommTree.traverse(): # all descendant comments - comment.bug = bugA - comment.save() # force onto disk under bugA - for comment in newCommTree: # just the child comments - mergeA.add_reply(comment, allow_time_inversion=True) - bugB.new_comment("Merged into bug %s" % bugA.uuid) - bugB.status = "closed" - print "Merging bugs %s and %s" % (bugA.uuid, bugB.uuid) - -def get_parser(): - parser = cmdutil.CmdOptionParser("be merge BUG-ID BUG-ID") - return parser - -longhelp=""" -The second bug (B) is merged into the first (A). This adds merge -comments to both bugs, closes B, and appends B's comment tree to A's -merge comment. -""" - -def help(): - return get_parser().help_str() + longhelp diff --git a/becommands/new.py b/becommands/new.py deleted file mode 100644 index a8ee2ec..0000000 --- a/becommands/new.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc. -# W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Create a new bug""" -from libbe import cmdutil, bugdir -import sys -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> import os, time - >>> from libbe import bug - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> bug.uuid_gen = lambda: "X" - >>> execute (["this is a test",], manipulate_encodings=False) - Created bug with ID X - >>> bd._clear_bugs() - >>> bug = bd.bug_from_uuid("X") - >>> print bug.summary - this is a test - >>> bug.time <= int(time.time()) - True - >>> print bug.severity - minor - >>> bug.target == None - True - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser) - if len(args) != 1: - raise cmdutil.UsageError("Please supply a summary message") - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - if args[0] == '-': # read summary from stdin - summary = sys.stdin.readline() - else: - summary = args[0] - bug = bd.new_bug(summary=summary.strip()) - if options.reporter != None: - bug.reporter = options.reporter - else: - bug.reporter = bug.creator - if options.assigned != None: - bug.assigned = options.assigned - elif bd.default_assignee != None: - bug.assigned = bd.default_assignee - print "Created bug with ID %s" % bd.bug_shortname(bug) - -def get_parser(): - parser = cmdutil.CmdOptionParser("be new SUMMARY") - parser.add_option("-r", "--reporter", metavar="REPORTER", dest="reporter", - help="The user who reported the bug", default=None) - parser.add_option("-a", "--assigned", metavar="ASSIGNED", dest="assigned", - help="The developer in charge of the bug", default=None) - return parser - -longhelp=""" -Create a new bug, with a new ID. The summary specified on the -commandline is a string (only one line) that describes the bug briefly -or "-", in which case the string will be read from stdin. -""" - -def help(): - return get_parser().help_str() + longhelp diff --git a/becommands/open.py b/becommands/open.py deleted file mode 100644 index 0c6bf05..0000000 --- a/becommands/open.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc. -# Marien Zwart <marienz@gentoo.org> -# Thomas Gerigk <tgerigk@gmx.de> -# W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Re-open a bug""" -from libbe import cmdutil, bugdir -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> import os - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> print bd.bug_from_shortname("b").status - closed - >>> execute(["b"], manipulate_encodings=False) - >>> bd._clear_bugs() - >>> print bd.bug_from_shortname("b").status - open - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser, - bugid_args={0: lambda bug : bug.active==False}) - if len(args) == 0: - raise cmdutil.UsageError, "Please specify a bug id." - if len(args) > 1: - raise cmdutil.UsageError, "Too many arguments." - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - bug = cmdutil.bug_from_shortname(bd, args[0]) - bug.status = "open" - -def get_parser(): - parser = cmdutil.CmdOptionParser("be open BUG-ID") - return parser - -longhelp=""" -Mark a bug as 'open'. -""" - -def help(): - return get_parser().help_str() + longhelp diff --git a/becommands/remove.py b/becommands/remove.py deleted file mode 100644 index 8d85033..0000000 --- a/becommands/remove.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright (C) 2008-2009 W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Remove (delete) a bug and its comments""" -from libbe import cmdutil, bugdir -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> from libbe import mapfile - >>> import os - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> print bd.bug_from_shortname("b").status - closed - >>> execute (["b"], manipulate_encodings=False) - Removed bug b - >>> bd._clear_bugs() - >>> try: - ... bd.bug_from_shortname("b") - ... except bugdir.NoBugMatches: - ... print "Bug not found" - Bug not found - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser, - bugid_args={0: lambda bug : bug.active==True}) - if len(args) != 1: - raise cmdutil.UsageError, "Please specify a bug id." - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - bug = cmdutil.bug_from_shortname(bd, args[0]) - bd.remove_bug(bug) - print "Removed bug %s" % bug.uuid - -def get_parser(): - parser = cmdutil.CmdOptionParser("be remove BUG-ID") - return parser - -longhelp=""" -Remove (delete) an existing bug. Use with caution: if you're not using a -revision control system, there may be no way to recover the lost information. -You should use this command, for example, to get rid of blank or otherwise -mangled bugs. -""" - -def help(): - return get_parser().help_str() + longhelp diff --git a/becommands/set.py b/becommands/set.py deleted file mode 100644 index f7e68d3..0000000 --- a/becommands/set.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc. -# Chris Ball <cjb@laptop.org> -# Marien Zwart <marienz@gentoo.org> -# Thomas Gerigk <tgerigk@gmx.de> -# W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Change tree settings""" -import textwrap -from libbe import cmdutil, bugdir, vcs, settings_object -__desc__ = __doc__ - -def _value_string(bd, setting): - val = bd.settings.get(setting, settings_object.EMPTY) - if val == settings_object.EMPTY: - default = getattr(bd, bd._setting_name_to_attr_name(setting)) - if default not in [None, settings_object.EMPTY]: - val = "None (%s)" % default - else: - val = None - return str(val) - -def execute(args, manipulate_encodings=True): - """ - >>> import os - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> execute(["target"], manipulate_encodings=False) - None - >>> execute(["target", "tomorrow"], manipulate_encodings=False) - >>> execute(["target"], manipulate_encodings=False) - tomorrow - >>> execute(["target", "none"], manipulate_encodings=False) - >>> execute(["target"], manipulate_encodings=False) - None - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - complete(options, args, parser) - if len(args) > 2: - raise cmdutil.UsageError, "Too many arguments" - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - if len(args) == 0: - keys = bd.settings_properties - keys.sort() - for key in keys: - print "%16s: %s" % (key, _value_string(bd, key)) - elif len(args) == 1: - print _value_string(bd, args[0]) - else: - if args[1] == "none": - setattr(bd, args[0], settings_object.EMPTY) - else: - if args[0] not in bd.settings_properties: - msg = "Invalid setting %s\n" % args[0] - msg += 'Allowed settings:\n ' - msg += '\n '.join(bd.settings_properties) - raise cmdutil.UserError(msg) - old_setting = bd.settings.get(args[0]) - setattr(bd, args[0], args[1]) - -def get_parser(): - parser = cmdutil.CmdOptionParser("be set [NAME] [VALUE]") - return parser - -def get_bugdir_settings(): - settings = [] - for s in bugdir.BugDir.settings_properties: - settings.append(s) - settings.sort() - documented_settings = [] - for s in settings: - set = getattr(bugdir.BugDir, s) - dstr = set.__doc__.strip() - # per-setting comment adjustments - if s == "vcs_name": - lines = dstr.split('\n') - while lines[0].startswith("This property defaults to") == False: - lines.pop(0) - assert len(lines) != None, \ - "Unexpected vcs_name docstring:\n '%s'" % dstr - lines.insert( - 0, "The name of the revision control system to use.\n") - dstr = '\n'.join(lines) - doc = textwrap.wrap(dstr, width=70, initial_indent=' ', - subsequent_indent=' ') - documented_settings.append("%s\n%s" % (s, '\n'.join(doc))) - return documented_settings - -longhelp=""" -Show or change per-tree settings. - -If name and value are supplied, the name is set to a new value. -If no value is specified, the current value is printed. -If no arguments are provided, all names and values are listed. - -To unset a setting, set it to "none". - -Allowed settings are: - -%s""" % ('\n'.join(get_bugdir_settings()),) - -def help(): - return get_parser().help_str() + longhelp - -def complete(options, args, parser): - for option, value in cmdutil.option_value_pairs(options, parser): - if value == "--complete": - # no argument-options at the moment, so this is future-proofing - raise cmdutil.GetCompletions() - for pos,value in enumerate(args): - if value == "--complete": - if pos == 0: # first positional argument is a setting name - props = bugdir.BugDir.settings_properties - raise cmdutil.GetCompletions(props) - raise cmdutil.GetCompletions() # no positional arguments for list diff --git a/becommands/severity.py b/becommands/severity.py deleted file mode 100644 index 660586e..0000000 --- a/becommands/severity.py +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc. -# Marien Zwart <marienz@gentoo.org> -# Thomas Gerigk <tgerigk@gmx.de> -# W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Show or change a bug's severity level""" -from libbe import cmdutil, bugdir, bug -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> import os - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> execute(["a"], manipulate_encodings=False) - minor - >>> execute(["a", "wishlist"], manipulate_encodings=False) - >>> execute(["a"], manipulate_encodings=False) - wishlist - >>> execute(["a", "none"], manipulate_encodings=False) - Traceback (most recent call last): - UserError: Invalid severity level: none - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - complete(options, args, parser) - if len(args) not in (1,2): - raise cmdutil.UsageError - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - bug = cmdutil.bug_from_shortname(bd, args[0]) - if len(args) == 1: - print bug.severity - elif len(args) == 2: - try: - bug.severity = args[1] - except ValueError, e: - if e.name != "severity": - raise e - raise cmdutil.UserError ("Invalid severity level: %s" % e.value) - -def get_parser(): - parser = cmdutil.CmdOptionParser("be severity BUG-ID [SEVERITY]") - return parser - -def help(): - longhelp=[""" -Show or change a bug's severity level. - -If no severity is specified, the current value is printed. If a severity level -is specified, it will be assigned to the bug. - -Severity levels are: -"""] - try: # See if there are any per-tree severity configurations - bd = bugdir.BugDir(from_disk=True, manipulate_encodings=False) - except bugdir.NoBugDir, e: - pass # No tree, just show the defaults - longest_severity_len = max([len(s) for s in bug.severity_values]) - for severity in bug.severity_values : - description = bug.severity_description[severity] - s = "%*s : %s\n" % (longest_severity_len, severity, description) - longhelp.append(s) - longhelp = ''.join(longhelp) - return get_parser().help_str() + longhelp - -def complete(options, args, parser): - for option,value in cmdutil.option_value_pairs(options, parser): - if value == "--complete": - # no argument-options at the moment, so this is future-proofing - raise cmdutil.GetCompletions() - for pos,value in enumerate(args): - if value == "--complete": - try: # See if there are any per-tree severity configurations - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=False) - except bugdir.NoBugDir: - bd = None - if pos == 0: # fist positional argument is a bug id - ids = [] - if bd != None: - bd.load_all_bugs() - filter = lambda bg : bg.active==True - bugs = [bg for bg in bd if filter(bg)==True] - ids = [bd.bug_shortname(bg) for bg in bugs] - raise cmdutil.GetCompletions(ids) - elif pos == 1: # second positional argument is a severity - raise cmdutil.GetCompletions(bug.severity_values) - raise cmdutil.GetCompletions() diff --git a/becommands/show.py b/becommands/show.py deleted file mode 100644 index 50bd6eb..0000000 --- a/becommands/show.py +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc. -# Chris Ball <cjb@laptop.org> -# Thomas Gerigk <tgerigk@gmx.de> -# Thomas Habets <thomas@habets.pp.se> -# W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Show a particular bug""" -import sys -from libbe import cmdutil, bugdir -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> import os - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> execute (["a",], manipulate_encodings=False) # doctest: +ELLIPSIS - ID : a - Short name : a - Severity : minor - Status : open - Assigned : - Target : - Reporter : - Creator : John Doe <jdoe@example.com> - Created : ... - Bug A - <BLANKLINE> - >>> execute (["--xml", "a"], manipulate_encodings=False) # doctest: +ELLIPSIS - <?xml version="1.0" encoding="..." ?> - <bug> - <uuid>a</uuid> - <short-name>a</short-name> - <severity>minor</severity> - <status>open</status> - <creator>John Doe <jdoe@example.com></creator> - <created>...</created> - <summary>Bug A</summary> - </bug> - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser, - bugid_args={-1: lambda bug : bug.active==True}) - if len(args) == 0: - raise cmdutil.UsageError - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - if options.XML: - print '<?xml version="1.0" encoding="%s" ?>' % bd.encoding - for shortname in args: - if shortname.count(':') > 1: - raise cmdutil.UserError("Invalid id '%s'." % shortname) - elif shortname.count(':') == 1: - # Split shortname generated by Comment.comment_shortnames() - bugname = shortname.split(':')[0] - is_comment = True - else: - bugname = shortname - is_comment = False - if is_comment == True and options.comments == False: - continue - bug = cmdutil.bug_from_shortname(bd, bugname) - if is_comment == False: - if options.XML: - print bug.xml(show_comments=options.comments) - else: - print bug.string(show_comments=options.comments) - else: - comment = bug.comment_root.comment_from_shortname( - shortname, bug_shortname=bugname) - if options.XML: - print comment.xml(shortname=shortname) - else: - if len(args) == 1 and options.only_raw_body == True: - sys.__stdout__.write(comment.body) - else: - print comment.string(shortname=shortname) - if shortname != args[-1] and options.XML == False: - print "" # add a blank line between bugs/comments - -def get_parser(): - parser = cmdutil.CmdOptionParser("be show [options] ID [ID ...]") - parser.add_option("-x", "--xml", action="store_true", default=False, - dest='XML', help="Dump as XML") - parser.add_option("--only-raw-body", action="store_true", - dest='only_raw_body', - help="When printing only a single comment, just print it's body. This allows extraction of non-text content types.") - parser.add_option("-c", "--no-comments", dest="comments", - action="store_false", default=True, - help="Disable comment output. This is useful if you just want more details on a bug's current status.") - return parser - -longhelp=""" -Show all information about the bugs or comments whose IDs are given. - -It's probably not a good idea to mix bug and comment IDs in a single -call, but you're free to do so if you like. -""" - -def help(): - return get_parser().help_str() + longhelp diff --git a/becommands/status.py b/becommands/status.py deleted file mode 100644 index f315003..0000000 --- a/becommands/status.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (C) 2008-2009 W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Show or change a bug's status""" -from libbe import cmdutil, bugdir, bug -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> import os - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> execute(["a"], manipulate_encodings=False) - open - >>> execute(["a", "closed"], manipulate_encodings=False) - >>> execute(["a"], manipulate_encodings=False) - closed - >>> execute(["a", "none"], manipulate_encodings=False) - Traceback (most recent call last): - UserError: Invalid status: none - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - complete(options, args, parser) - if len(args) not in (1,2): - raise cmdutil.UsageError - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - bug = cmdutil.bug_from_shortname(bd, args[0]) - if len(args) == 1: - print bug.status - else: - try: - bug.status = args[1] - except ValueError, e: - if e.name != "status": - raise - raise cmdutil.UserError ("Invalid status: %s" % e.value) - -def get_parser(): - parser = cmdutil.CmdOptionParser("be status BUG-ID [STATUS]") - return parser - - -def help(): - try: # See if there are any per-tree status configurations - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=False) - except bugdir.NoBugDir, e: - pass # No tree, just show the defaults - longest_status_len = max([len(s) for s in bug.status_values]) - active_statuses = [] - for status in bug.active_status_values : - description = bug.status_description[status] - s = "%*s : %s" % (longest_status_len, status, description) - active_statuses.append(s) - inactive_statuses = [] - for status in bug.inactive_status_values : - description = bug.status_description[status] - s = "%*s : %s" % (longest_status_len, status, description) - inactive_statuses.append(s) - longhelp=""" -Show or change a bug's status. - -If no status is specified, the current value is printed. If a status -is specified, it will be assigned to the bug. - -There are two classes of statuses, active and inactive, which are only -important for commands like "be list" that show only active bugs by -default. - -Active status levels are: - %s -Inactive status levels are: - %s - -You can overide the list of allowed statuses on a per-repository basis. -See "be set --help" for more details. -""" % ('\n '.join(active_statuses), '\n '.join(inactive_statuses)) - return get_parser().help_str() + longhelp - -def complete(options, args, parser): - for option,value in cmdutil.option_value_pairs(options, parser): - if value == "--complete": - # no argument-options at the moment, so this is future-proofing - raise cmdutil.GetCompletions() - for pos,value in enumerate(args): - if value == "--complete": - try: # See if there are any per-tree status configurations - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=False) - except bugdir.NoBugDir: - bd = None - if pos == 0: # fist positional argument is a bug id - ids = [] - if bd != None: - bd.load_all_bugs() - ids = [bd.bug_shortname(bg) for bg in bd] - raise cmdutil.GetCompletions(ids) - elif pos == 1: # second positional argument is a status - raise cmdutil.GetCompletions(bug.status_values) - raise cmdutil.GetCompletions() diff --git a/becommands/subscribe.py b/becommands/subscribe.py deleted file mode 100644 index 0a23057..0000000 --- a/becommands/subscribe.py +++ /dev/null @@ -1,390 +0,0 @@ -# Copyright (C) 2009 W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""(Un)subscribe to change notification""" -from libbe import cmdutil, bugdir, tree -import os, copy -__desc__ = __doc__ - -TAG="SUBSCRIBE:" - -class SubscriptionType (tree.Tree): - """ - Trees of subscription types to allow users to select exactly what - notifications they want to subscribe to. - """ - def __init__(self, type_name, *args, **kwargs): - tree.Tree.__init__(self, *args, **kwargs) - self.type = type_name - def __str__(self): - return self.type - def __repr__(self): - return "<SubscriptionType: %s>" % str(self) - def string_tree(self, indent=0): - lines = [] - for depth,node in self.thread(): - lines.append("%s%s" % (" "*(indent+2*depth), node)) - return "\n".join(lines) - -BUGDIR_TYPE_NEW = SubscriptionType("new") -BUGDIR_TYPE_ALL = SubscriptionType("all", [BUGDIR_TYPE_NEW]) - -# same name as BUGDIR_TYPE_ALL for consistency -BUG_TYPE_ALL = SubscriptionType(str(BUGDIR_TYPE_ALL)) - -INVALID_TYPE = SubscriptionType("INVALID") - -class InvalidType (ValueError): - def __init__(self, type_name, type_root): - msg = "Invalid type %s for tree:\n%s" \ - % (type_name, type_root.string_tree(4)) - ValueError.__init__(self, msg) - self.type_name = type_name - self.type_root = type_root - - -def execute(args, manipulate_encodings=True): - """ - >>> bd = bugdir.SimpleBugDir() - >>> bd.set_sync_with_disk(True) - >>> os.chdir(bd.root) - >>> a = bd.bug_from_shortname("a") - >>> print a.extra_strings - [] - >>> execute(["-s","John Doe <j@doe.com>", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: - John Doe <j@doe.com> all * - >>> bd._clear_bugs() # resync our copy of bug - >>> a = bd.bug_from_shortname("a") - >>> print a.extra_strings - ['SUBSCRIBE:John Doe <j@doe.com>\\tall\\t*'] - >>> execute(["-s","Jane Doe <J@doe.com>", "-S", "a.com,b.net", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: - Jane Doe <J@doe.com> all a.com,b.net - John Doe <j@doe.com> all * - >>> execute(["-s","Jane Doe <J@doe.com>", "-S", "a.edu", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: - Jane Doe <J@doe.com> all a.com,a.edu,b.net - John Doe <j@doe.com> all * - >>> execute(["-u", "-s","Jane Doe <J@doe.com>", "-S", "a.com", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: - Jane Doe <J@doe.com> all a.edu,b.net - John Doe <j@doe.com> all * - >>> execute(["-s","Jane Doe <J@doe.com>", "-S", "*", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: - Jane Doe <J@doe.com> all * - John Doe <j@doe.com> all * - >>> execute(["-u", "-s","Jane Doe <J@doe.com>", "a"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for a: - John Doe <j@doe.com> all * - >>> execute(["-u", "-s","John Doe <j@doe.com>", "a"], manipulate_encodings=False) - >>> execute(["-s","Jane Doe <J@doe.com>", "-t", "new", "DIR"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for bug directory: - Jane Doe <J@doe.com> new * - >>> execute(["-s","Jane Doe <J@doe.com>", "DIR"], manipulate_encodings=False) # doctest: +NORMALIZE_WHITESPACE - Subscriptions for bug directory: - Jane Doe <J@doe.com> all * - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser, - bugid_args={0: lambda bug : bug.active==True}) - - if len(args) > 1: - help() - raise cmdutil.UsageError("Too many arguments.") - - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - - subscriber = options.subscriber - if subscriber == None: - subscriber = bd.user_id - if options.unsubscribe == True: - if options.servers == None: - options.servers = "INVALID" - if options.types == None: - options.types = "INVALID" - else: - if options.servers == None: - options.servers = "*" - if options.types == None: - options.types = "all" - servers = options.servers.split(",") - types = options.types.split(",") - - if len(args) == 0 or args[0] == "DIR": # directory-wide subscriptions - type_root = BUGDIR_TYPE_ALL - entity = bd - entity_name = "bug directory" - else: # bug-specific subscriptions - type_root = BUG_TYPE_ALL - bug = bd.bug_from_shortname(args[0]) - entity = bug - entity_name = bug.uuid - if options.list_all == True: - entity_name = "anything in the bug directory" - - types = [type_from_name(name, type_root, default=INVALID_TYPE, - default_ok=options.unsubscribe) - for name in types] - estrs = entity.extra_strings - if options.list == True or options.list_all == True: - pass - else: # alter subscriptions - if options.unsubscribe == True: - estrs = unsubscribe(estrs, subscriber, types, servers, type_root) - else: # add the tag - estrs = subscribe(estrs, subscriber, types, servers, type_root) - entity.extra_strings = estrs # reassign to notice change - - if options.list_all == True: - bd.load_all_bugs() - subscriptions = get_bugdir_subscribers(bd, servers[0]) - else: - subscriptions = [] - for estr in entity.extra_strings: - if estr.startswith(TAG): - subscriptions.append(estr[len(TAG):]) - - if len(subscriptions) > 0: - print "Subscriptions for %s:" % entity_name - print '\n'.join(subscriptions) - - -def get_parser(): - parser = cmdutil.CmdOptionParser("be subscribe ID") - parser.add_option("-u", "--unsubscribe", action="store_true", - dest="unsubscribe", default=False, - help="Unsubscribe instead of subscribing.") - parser.add_option("-a", "--list-all", action="store_true", - dest="list_all", default=False, - help="List all subscribers (no ID argument, read only action).") - parser.add_option("-l", "--list", action="store_true", - dest="list", default=False, - help="List subscribers (read only action).") - parser.add_option("-s", "--subscriber", dest="subscriber", - metavar="SUBSCRIBER", - help="Email address of the subscriber (defaults to bugdir.user_id).") - parser.add_option("-S", "--servers", dest="servers", metavar="SERVERS", - help="Servers from which you want notification.") - parser.add_option("-t", "--type", dest="types", metavar="TYPES", - help="Types of changes you wish to be notified about.") - return parser - -longhelp=""" -ID can be either a bug id, or blank/"DIR", in which case it refers to the -whole bug directory. - -SERVERS specifies the servers from which you would like to receive -notification. Multiple severs may be specified in a comma-separated -list, or you can use "*" to match all servers (the default). If you -have not selected a server, it should politely refrain from notifying -you of changes, although there is no way to guarantee this behavior. - -Available TYPES: - For bugs: -%s - For DIR : -%s - -For unsubscription, any listed SERVERS and TYPES are removed from your -subscription. Either the catch-all server "*" or type "%s" will -remove SUBSCRIBER entirely from the specified ID. - -This command is intended for use primarily by public interfaces, since -if you're just hacking away on your private repository, you'll known -what's changed ;). This command just (un)sets the appropriate -subscriptions, and leaves it up to each interface to perform the -notification. -""" % (BUG_TYPE_ALL.string_tree(6), BUGDIR_TYPE_ALL.string_tree(6), - BUGDIR_TYPE_ALL) - -def help(): - return get_parser().help_str() + longhelp - -# internal helper functions - -def _generate_string(subscriber, types, servers): - types = sorted([str(t) for t in types]) - servers = sorted(servers) - return "%s%s\t%s\t%s" % (TAG,subscriber,",".join(types),",".join(servers)) - -def _parse_string(string, type_root): - assert string.startswith(TAG), string - string = string[len(TAG):] - subscriber,types,servers = string.split("\t") - types = [type_from_name(name, type_root) for name in types.split(",")] - return (subscriber,types,servers.split(",")) - -def _get_subscriber(extra_strings, subscriber, type_root): - for i,string in enumerate(extra_strings): - if string.startswith(TAG): - s,ts,srvs = _parse_string(string, type_root) - if s == subscriber: - return i,s,ts,srvs # match! - return None # no match - -# functions exposed to other modules - -def type_from_name(name, type_root, default=None, default_ok=False): - if name == str(type_root): - return type_root - for t in type_root.traverse(): - if name == str(t): - return t - if default_ok: - return default - raise InvalidType(name, type_root) - -def subscribe(extra_strings, subscriber, types, servers, type_root): - args = _get_subscriber(extra_strings, subscriber, type_root) - if args == None: # no match - extra_strings.append(_generate_string(subscriber, types, servers)) - return extra_strings - # Alter matched string - i,s,ts,srvs = args - for t in types: - if t not in ts: - ts.append(t) - # remove descendant types - all_ts = copy.copy(ts) - for t in all_ts: - for tt in all_ts: - if tt in ts and t.has_descendant(tt): - ts.remove(tt) - if "*" in servers+srvs: - srvs = ["*"] - else: - srvs = list(set(servers+srvs)) - extra_strings[i] = _generate_string(subscriber, ts, srvs) - return extra_strings - -def unsubscribe(extra_strings, subscriber, types, servers, type_root): - args = _get_subscriber(extra_strings, subscriber, type_root) - if args == None: # no match - return extra_strings # pass - # Remove matched string - i,s,ts,srvs = args - all_ts = copy.copy(ts) - for t in types: - for tt in all_ts: - if tt in ts and t.has_descendant(tt): - ts.remove(tt) - if "*" in servers+srvs: - srvs = [] - else: - for srv in servers: - if srv in srvs: - srvs.remove(srv) - if len(ts) == 0 or len(srvs) == 0: - extra_strings.pop(i) - else: - extra_strings[i] = _generate_string(subscriber, ts, srvs) - return extra_strings - -def get_subscribers(extra_strings, type, server, type_root, - match_ancestor_types=False, - match_descendant_types=False): - """ - Set match_ancestor_types=True if you want to find eveyone who - cares about your particular type. - - Set match_descendant_types=True if you want to find subscribers - who may only care about some subset of your type. This is useful - for generating lists of all the subscribers in a given set of - extra_strings. - - >>> def sgs(*args, **kwargs): - ... return sorted(get_subscribers(*args, **kwargs)) - >>> es = [] - >>> es = subscribe(es, "John Doe <j@doe.com>", [BUGDIR_TYPE_ALL], ["a.com"], BUGDIR_TYPE_ALL) - >>> es = subscribe(es, "Jane Doe <J@doe.com>", [BUGDIR_TYPE_NEW], ["*"], BUGDIR_TYPE_ALL) - >>> sgs(es, BUGDIR_TYPE_ALL, "a.com", BUGDIR_TYPE_ALL) - ['John Doe <j@doe.com>'] - >>> sgs(es, BUGDIR_TYPE_ALL, "a.com", BUGDIR_TYPE_ALL, match_descendant_types=True) - ['Jane Doe <J@doe.com>', 'John Doe <j@doe.com>'] - >>> sgs(es, BUGDIR_TYPE_ALL, "b.net", BUGDIR_TYPE_ALL, match_descendant_types=True) - ['Jane Doe <J@doe.com>'] - >>> sgs(es, BUGDIR_TYPE_NEW, "a.com", BUGDIR_TYPE_ALL) - ['Jane Doe <J@doe.com>'] - >>> sgs(es, BUGDIR_TYPE_NEW, "a.com", BUGDIR_TYPE_ALL, match_ancestor_types=True) - ['Jane Doe <J@doe.com>', 'John Doe <j@doe.com>'] - """ - for string in extra_strings: - if not string.startswith(TAG): - continue - subscriber,types,servers = _parse_string(string, type_root) - type_match = False - if type in types: - type_match = True - if type_match == False and match_ancestor_types == True: - for t in types: - if t.has_descendant(type): - type_match = True - break - if type_match == False and match_descendant_types == True: - for t in types: - if type.has_descendant(t): - type_match = True - break - server_match = False - if server in servers or servers == ["*"] or server == "*": - server_match = True - if type_match == True and server_match == True: - yield subscriber - -def get_bugdir_subscribers(bugdir, server): - """ - I have a bugdir. Who cares about it, and what do they care about? - Returns a dict of dicts: - subscribers[user][id] = types - where id is either a bug.uuid (in the case of a bug subscription) - or "DIR" (in the case of a bugdir subscription). - - Only checks bugs that are currently in memory, so you might want - to call bugdir.load_all_bugs() first. - - >>> bd = bugdir.SimpleBugDir(sync_with_disk=False) - >>> a = bd.bug_from_shortname("a") - >>> bd.extra_strings = subscribe(bd.extra_strings, "John Doe <j@doe.com>", [BUGDIR_TYPE_ALL], ["a.com"], BUGDIR_TYPE_ALL) - >>> bd.extra_strings = subscribe(bd.extra_strings, "Jane Doe <J@doe.com>", [BUGDIR_TYPE_NEW], ["*"], BUGDIR_TYPE_ALL) - >>> a.extra_strings = subscribe(a.extra_strings, "John Doe <j@doe.com>", [BUG_TYPE_ALL], ["a.com"], BUG_TYPE_ALL) - >>> subscribers = get_bugdir_subscribers(bd, "a.com") - >>> subscribers["Jane Doe <J@doe.com>"]["DIR"] - [<SubscriptionType: new>] - >>> subscribers["John Doe <j@doe.com>"]["DIR"] - [<SubscriptionType: all>] - >>> subscribers["John Doe <j@doe.com>"]["a"] - [<SubscriptionType: all>] - >>> get_bugdir_subscribers(bd, "b.net") - {'Jane Doe <J@doe.com>': {'DIR': [<SubscriptionType: new>]}} - >>> bd.cleanup() - """ - subscribers = {} - for sub in get_subscribers(bugdir.extra_strings, BUGDIR_TYPE_ALL, server, - BUGDIR_TYPE_ALL, match_descendant_types=True): - i,s,ts,srvs = _get_subscriber(bugdir.extra_strings,sub,BUGDIR_TYPE_ALL) - subscribers[sub] = {"DIR":ts} - for bug in bugdir: - for sub in get_subscribers(bug.extra_strings, BUG_TYPE_ALL, server, - BUG_TYPE_ALL, match_descendant_types=True): - i,s,ts,srvs = _get_subscriber(bug.extra_strings,sub,BUG_TYPE_ALL) - if sub in subscribers: - subscribers[sub][bug.uuid] = ts - else: - subscribers[sub] = {bug.uuid:ts} - return subscribers diff --git a/becommands/tag.py b/becommands/tag.py deleted file mode 100644 index ecd853f..0000000 --- a/becommands/tag.py +++ /dev/null @@ -1,134 +0,0 @@ -# Copyright (C) 2009 W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Tag a bug, or search bugs for tags""" -from libbe import cmdutil, bugdir -import os, copy -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> from libbe import utility - >>> bd = bugdir.SimpleBugDir() - >>> bd.set_sync_with_disk(True) - >>> os.chdir(bd.root) - >>> a = bd.bug_from_shortname("a") - >>> print a.extra_strings - [] - >>> execute(["a", "GUI"], manipulate_encodings=False) - Tags for a: - GUI - >>> bd._clear_bugs() # resync our copy of bug - >>> a = bd.bug_from_shortname("a") - >>> print a.extra_strings - ['TAG:GUI'] - >>> execute(["a", "later"], manipulate_encodings=False) - Tags for a: - GUI - later - >>> execute(["a"], manipulate_encodings=False) - Tags for a: - GUI - later - >>> execute(["--list"], manipulate_encodings=False) - GUI - later - >>> execute(["a", "Alphabetically first"], manipulate_encodings=False) - Tags for a: - Alphabetically first - GUI - later - >>> bd._clear_bugs() # resync our copy of bug - >>> a = bd.bug_from_shortname("a") - >>> print a.extra_strings - ['TAG:Alphabetically first', 'TAG:GUI', 'TAG:later'] - >>> a.extra_strings = [] - >>> print a.extra_strings - [] - >>> execute(["a"], manipulate_encodings=False) - >>> bd._clear_bugs() # resync our copy of bug - >>> a = bd.bug_from_shortname("a") - >>> print a.extra_strings - [] - >>> execute(["a", "Alphabetically first"], manipulate_encodings=False) - Tags for a: - Alphabetically first - >>> execute(["--remove", "a", "Alphabetically first"], manipulate_encodings=False) - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser, - bugid_args={0: lambda bug : bug.active==True}) - - if len(args) == 0 and options.list == False: - raise cmdutil.UsageError("Please specify a bug id.") - elif len(args) > 2 or (len(args) > 0 and options.list == True): - help() - raise cmdutil.UsageError("Too many arguments.") - - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - if options.list: - bd.load_all_bugs() - tags = [] - for bug in bd: - for estr in bug.extra_strings: - if estr.startswith("TAG:"): - tag = estr[4:] - if tag not in tags: - tags.append(tag) - tags.sort() - if len(tags) > 0: - print '\n'.join(tags) - return - bug = cmdutil.bug_from_shortname(bd, args[0]) - if len(args) == 2: - given_tag = args[1] - estrs = bug.extra_strings - tag_string = "TAG:%s" % given_tag - if options.remove == True: - estrs.remove(tag_string) - else: # add the tag - estrs.append(tag_string) - bug.extra_strings = estrs # reassign to notice change - - tags = [] - for estr in bug.extra_strings: - if estr.startswith("TAG:"): - tags.append(estr[4:]) - - if len(tags) > 0: - print "Tags for %s:" % bug.uuid - print '\n'.join(tags) - -def get_parser(): - parser = cmdutil.CmdOptionParser("be tag BUG-ID [TAG]\nor: be tag --list") - parser.add_option("-r", "--remove", action="store_true", dest="remove", - help="Remove TAG (instead of adding it)") - parser.add_option("-l", "--list", action="store_true", dest="list", - help="List all available tags and exit") - return parser - -longhelp=""" -If TAG is given, add TAG to BUG-ID. If it is not specified, just -print the tags for BUG-ID. - -To search for bugs with a particular tag, try - $ be list --extra-strings TAG:<your-tag> -""" - -def help(): - return get_parser().help_str() + longhelp diff --git a/becommands/target.py b/becommands/target.py deleted file mode 100644 index 7e41451..0000000 --- a/becommands/target.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc. -# Chris Ball <cjb@laptop.org> -# Gianluca Montecchi <gian@grys.it> -# Marien Zwart <marienz@gentoo.org> -# Thomas Gerigk <tgerigk@gmx.de> -# W. Trevor King <wking@drexel.edu> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -"""Show or change a bug's target for fixing""" -from libbe import cmdutil, bugdir -__desc__ = __doc__ - -def execute(args, manipulate_encodings=True): - """ - >>> import os - >>> bd = bugdir.SimpleBugDir() - >>> os.chdir(bd.root) - >>> execute(["a"], manipulate_encodings=False) - No target assigned. - >>> execute(["a", "tomorrow"], manipulate_encodings=False) - >>> execute(["a"], manipulate_encodings=False) - tomorrow - >>> execute(["--list"], manipulate_encodings=False) - tomorrow - >>> execute(["a", "none"], manipulate_encodings=False) - >>> execute(["a"], manipulate_encodings=False) - No target assigned. - >>> bd.cleanup() - """ - parser = get_parser() - options, args = parser.parse_args(args) - cmdutil.default_complete(options, args, parser, - bugid_args={0: lambda bug : bug.active==True}) - - if len(args) not in (1, 2): - if not (options.list == True and len(args) == 0): - raise cmdutil.UsageError - bd = bugdir.BugDir(from_disk=True, - manipulate_encodings=manipulate_encodings) - if options.list: - ts = set([bd.bug_from_uuid(bug).target for bug in bd.list_uuids()]) - for target in sorted(ts): - if target and isinstance(target,str): - print target - return - bug = cmdutil.bug_from_shortname(bd, args[0]) - if len(args) == 1: - if bug.target is None: - print "No target assigned." - else: - print bug.target - else: - assert len(args) == 2 - if args[1] == "none": - bug.target = None - else: - bug.target = args[1] - -def get_parser(): - parser = cmdutil.CmdOptionParser("be target BUG-ID [TARGET]\nor: be target --list") - parser.add_option("-l", "--list", action="store_true", dest="list", - help="List all available targets and exit") - return parser - -longhelp=""" -Show or change a bug's target for fixing. - -If no target is specified, the current value is printed. If a target -is specified, it will be assigned to the bug. - -Targets are freeform; any text may be specified. They will generally be -milestone names or release numbers. - -The value "none" can be used to unset the target. - -In the alternative `be target --list` form print a list of all -currently specified targets. Note that bug status -(i.e. opened/closed) is ignored. If you want to list all bugs -matching a current target, see `be list --target TARGET'. -""" - -def help(): - return get_parser().help_str() + longhelp |