aboutsummaryrefslogtreecommitdiffstats
path: root/libbe
diff options
context:
space:
mode:
authorW. Trevor King <wking@drexel.edu>2009-12-06 00:44:22 -0500
committerW. Trevor King <wking@drexel.edu>2009-12-06 00:44:22 -0500
commit61010c1c6b055ef8fd33b01c088e3d095914e89a (patch)
treee967aadbc99dee314b5fc3deb8036369e79a4c99 /libbe
parentaf8bd49a6215029c08676a3d4a59cfcab1d80976 (diff)
parentff1ca79e6781447dbad6279d6c4cdad44fad5cdd (diff)
downloadbugseverywhere-61010c1c6b055ef8fd33b01c088e3d095914e89a.tar.gz
Merged be.target-as-bug
Highlights: * targets are now a special type of bug (severity 'target'), so you can do all the things you do with normal bugs to them as well (e.g. comment on them, link them into dependency trees, etc.) * new command `be due` to get/set bug due dates. * changes to `be depend` * added options --status, --severity * changes to `be list` * added blacklist capability to --status, --severity, --assigned * removed options --target, --cur-target Replace: 'be list --target TARGET' with 'be depend --status -closed,fixed,wontfix --severity -target \ $(be target --resolve TARGET)' 'be list --cur-target' with 'be depend --status -closed,fixed,wontfix --severity -target \ $(be target --resolve)' * changes to `be target` * added option --resolve * removed option --list Replace: 'be target --list' with 'be list --status all --severity target' * new function cmdutil.select_values() for whitelist/blacklist selection. * assorted cleanups and bugfixes
Diffstat (limited to 'libbe')
-rw-r--r--libbe/bug.py13
-rw-r--r--libbe/cmdutil.py53
-rw-r--r--libbe/upgrade.py60
3 files changed, 114 insertions, 12 deletions
diff --git a/libbe/bug.py b/libbe/bug.py
index 1a190c3..06c2cc5 100644
--- a/libbe/bug.py
+++ b/libbe/bug.py
@@ -56,6 +56,7 @@ class DiskAccessRequired (Exception):
# in order of increasing severity. (name, description) pairs
severity_def = (
+ ("target", "The issue is a target or milestone, not a bug."),
("wishlist","A feature that could improve usefulness, but not a bug."),
("minor","The standard bug level."),
("serious","A bug that requires workarounds."),
@@ -173,10 +174,6 @@ class Bug(settings_object.SavedSettingsObject):
def active(self):
return self.status in active_status_values
- @_versioned_property(name="target",
- doc="The deadline for fixing this bug")
- def target(): return {}
-
@_versioned_property(name="creator",
doc="The user who entered the bug into the system")
def creator(): return {}
@@ -295,7 +292,6 @@ class Bug(settings_object.SavedSettingsObject):
('severity', self.severity),
('status', self.status),
('assigned', self.assigned),
- ('target', self.target),
('reporter', self.reporter),
('creator', self.creator),
('created', timestring),
@@ -352,7 +348,7 @@ class Bug(settings_object.SavedSettingsObject):
if bug.tag != 'bug':
raise utility.InvalidXML( \
'bug', bug, 'root element must be <comment>')
- tags=['uuid','short-name','severity','status','assigned','target',
+ tags=['uuid','short-name','severity','status','assigned',
'reporter', 'creator','created','summary','extra-string']
self.explicit_attrs = []
uuid = None
@@ -620,7 +616,6 @@ class Bug(settings_object.SavedSettingsObject):
("Severity", self.severity),
("Status", self.status),
("Assigned", self._setting_attr_string("assigned")),
- ("Target", self._setting_attr_string("target")),
("Reporter", self._setting_attr_string("reporter")),
("Creator", self._setting_attr_string("creator")),
("Created", timestring)]
@@ -820,7 +815,6 @@ def cmp_attr(bug_1, bug_2, attr, invert=False):
cmp_uuid = lambda bug_1, bug_2 : cmp_attr(bug_1, bug_2, "uuid")
cmp_creator = lambda bug_1, bug_2 : cmp_attr(bug_1, bug_2, "creator")
cmp_assigned = lambda bug_1, bug_2 : cmp_attr(bug_1, bug_2, "assigned")
-cmp_target = lambda bug_1, bug_2 : cmp_attr(bug_1, bug_2, "target")
cmp_reporter = lambda bug_1, bug_2 : cmp_attr(bug_1, bug_2, "reporter")
cmp_summary = lambda bug_1, bug_2 : cmp_attr(bug_1, bug_2, "summary")
cmp_extra_strings = lambda bug_1, bug_2 : cmp_attr(bug_1, bug_2, "extra_strings")
@@ -846,8 +840,7 @@ def cmp_comments(bug_1, bug_2):
DEFAULT_CMP_FULL_CMP_LIST = \
(cmp_status, cmp_severity, cmp_assigned, cmp_time, cmp_creator,
- cmp_reporter, cmp_target, cmp_comments, cmp_summary, cmp_uuid,
- cmp_extra_strings)
+ cmp_reporter, cmp_comments, cmp_summary, cmp_uuid, cmp_extra_strings)
class BugCompoundComparator (object):
def __init__(self, cmp_list=DEFAULT_CMP_FULL_CMP_LIST):
diff --git a/libbe/cmdutil.py b/libbe/cmdutil.py
index dcd4ca9..b892bde 100644
--- a/libbe/cmdutil.py
+++ b/libbe/cmdutil.py
@@ -217,6 +217,59 @@ def underlined(instring):
return "%s\n%s" % (instring, "="*len(instring))
+def select_values(string, possible_values, name="unkown"):
+ """
+ This function allows the user to select values from a list of
+ possible values. The default is to select all the values:
+
+ >>> select_values(None, ['abc', 'def', 'hij'])
+ ['abc', 'def', 'hij']
+
+ The user selects values with a comma-separated limit_string.
+ Prepending a minus sign to such a list denotes blacklist mode:
+
+ >>> select_values('-abc,hij', ['abc', 'def', 'hij'])
+ ['def']
+
+ Without the leading -, the selection is in whitelist mode:
+
+ >>> select_values('abc,hij', ['abc', 'def', 'hij'])
+ ['abc', 'hij']
+
+ In either case, appropriate errors are raised if on of the
+ user-values is not in the list of possible values. The name
+ parameter lets you make the error message more clear:
+
+ >>> select_values('-xyz,hij', ['abc', 'def', 'hij'], name="foobar")
+ Traceback (most recent call last):
+ ...
+ UserError: Invalid foobar xyz
+ ['abc', 'def', 'hij']
+ >>> select_values('xyz,hij', ['abc', 'def', 'hij'], name="foobar")
+ Traceback (most recent call last):
+ ...
+ UserError: Invalid foobar xyz
+ ['abc', 'def', 'hij']
+ """
+ possible_values = list(possible_values) # don't alter the original
+ if string == None:
+ pass
+ elif string.startswith('-'):
+ blacklisted_values = set(string[1:].split(','))
+ for value in blacklisted_values:
+ if value not in possible_values:
+ raise UserError('Invalid %s %s\n %s'
+ % (name, value, possible_values))
+ possible_values.remove(value)
+ else:
+ whitelisted_values = string.split(',')
+ for value in whitelisted_values:
+ if value not in possible_values:
+ raise UserError('Invalid %s %s\n %s'
+ % (name, value, possible_values))
+ possible_values = whitelisted_values
+ return possible_values
+
def restrict_file_access(bugdir, path):
"""
Check that the file at path is inside bugdir.root. This is
diff --git a/libbe/upgrade.py b/libbe/upgrade.py
index 785249d..dc9d54f 100644
--- a/libbe/upgrade.py
+++ b/libbe/upgrade.py
@@ -22,6 +22,7 @@ import os, os.path
import sys
import libbe
+import bug
import encoding
import mapfile
import vcs
@@ -31,7 +32,8 @@ if libbe.TESTING == True:
# a list of all past versions
BUGDIR_DISK_VERSIONS = ["Bugs Everywhere Tree 1 0",
"Bugs Everywhere Directory v1.1",
- "Bugs Everywhere Directory v1.2"]
+ "Bugs Everywhere Directory v1.2",
+ "Bugs Everywhere Directory v1.3"]
# the current version
BUGDIR_DISK_VERSION = BUGDIR_DISK_VERSIONS[-1]
@@ -142,9 +144,63 @@ class Upgrade_1_1_to_1_2 (Upgrader):
settings["vcs_name"] = settings.pop("rcs_name")
mapfile.map_save(self.vcs, path, settings)
+class Upgrade_1_2_to_1_3 (Upgrader):
+ initial_version = "Bugs Everywhere Directory v1.2"
+ final_version = "Bugs Everywhere Directory v1.3"
+ def __init__(self, *args, **kwargs):
+ Upgrader.__init__(self, *args, **kwargs)
+ self._targets = {} # key: target text,value: new target bug
+ path = self.get_path('settings')
+ settings = mapfile.map_load(self.vcs, path)
+ if 'vcs_name' in settings:
+ old_vcs = self.vcs
+ self.vcs = vcs.vcs_by_name(settings['vcs_name'])
+ self.vcs.root(self.root)
+ self.vcs.encoding = old_vcs.encoding
+
+ def _target_bug(self, target_text):
+ if target_text not in self._targets:
+ _bug = bug.Bug(bugdir=self, summary=target_text)
+ # note: we're not a bugdir, but all Bug.save() needs is
+ # .root, .vcs, and .get_path(), which we have.
+ _bug.severity = 'target'
+ self._targets[target_text] = _bug
+ return self._targets[target_text]
+
+ def _upgrade_bugdir_mapfile(self):
+ path = self.get_path('settings')
+ settings = mapfile.map_load(self.vcs, path)
+ if 'target' in settings:
+ settings['target'] = self._target_bug(settings['target']).uuid
+ mapfile.map_save(self.vcs, path, settings)
+
+ def _upgrade_bug_mapfile(self, bug_uuid):
+ import becommands.depend
+ path = self.get_path('bugs', bug_uuid, 'values')
+ settings = mapfile.map_load(self.vcs, path)
+ if 'target' in settings:
+ target_bug = self._target_bug(settings['target'])
+ _bug = bug.Bug(bugdir=self, uuid=bug_uuid, from_disk=True)
+ # note: we're not a bugdir, but all Bug.load_settings()
+ # needs is .root, .vcs, and .get_path(), which we have.
+ becommands.depend.add_block(target_bug, _bug)
+ _bug.settings.pop('target')
+ _bug.save()
+
+ def _upgrade(self):
+ """
+ Bug value field "target" -> target bugs.
+ Bugdir value field "target" -> pointer to current target bug.
+ """
+ for bug_uuid in os.listdir(self.get_path('bugs')):
+ self._upgrade_bug_mapfile(bug_uuid)
+ self._upgrade_bugdir_mapfile()
+ for _bug in self._targets.values():
+ _bug.save()
upgraders = [Upgrade_1_0_to_1_1,
- Upgrade_1_1_to_1_2]
+ Upgrade_1_1_to_1_2,
+ Upgrade_1_2_to_1_3]
upgrade_classes = {}
for upgrader in upgraders:
upgrade_classes[(upgrader.initial_version,upgrader.final_version)]=upgrader