diff options
author | Aaron Bentley <abentley@panoramicfeedback.com> | 2005-03-17 21:29:00 +0000 |
---|---|---|
committer | Aaron Bentley <abentley@panoramicfeedback.com> | 2005-03-17 21:29:00 +0000 |
commit | d7e4f9a09ffee3d248f5cc4be3cd4248a5c97af4 (patch) | |
tree | 12bd4e5c85b2f06ee9f3fabf06cf31a5a715b979 /libbe | |
parent | 22083d49fd56fb016df0cd7e416d1dd447182a93 (diff) | |
download | bugseverywhere-d7e4f9a09ffee3d248f5cc4be3cd4248a5c97af4.tar.gz |
Switched tree format to mapfile-based
Diffstat (limited to 'libbe')
-rw-r--r-- | libbe/bugdir.py | 96 | ||||
-rw-r--r-- | libbe/mapfile.py | 110 | ||||
-rw-r--r-- | libbe/rcs.py | 8 |
3 files changed, 73 insertions, 141 deletions
diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 9851e9d..58fa877 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -13,27 +13,40 @@ class NoBugDir(Exception): self.path = path -def tree_root(dir): +def tree_root(dir, old_version=False): rootdir = os.path.realpath(dir) while (True): versionfile=os.path.join(rootdir, ".be/version") if os.path.exists(versionfile): - test_version(versionfile) + if not old_version: + test_version(versionfile) break; elif rootdir == "/": raise NoBugDir(dir) rootdir=os.path.dirname(rootdir) return BugDir(os.path.join(rootdir, ".be")) +class BadTreeVersion(Exception): + def __init__(self, version): + Exception.__init__(self, "Unsupported tree version: %s" % version) + self.version = version + def test_version(path): - assert (file(path, "rb").read() == "Bugs Everywhere Tree 0 0\n") + tree_version = file(path, "rb").read() + if tree_version != TREE_VERSION_STRING: + raise BadTreeVersion(tree_version) + +def set_version(path): + rcs.set_file_contents(os.path.join(path, "version"), TREE_VERSION_STRING) + + +TREE_VERSION_STRING = "Bugs Everywhere Tree 1 0\n" def create_bug_dir(path): root = os.path.join(path, ".be") rcs.mkdir(root) rcs.mkdir(os.path.join(root, "bugs")) - rcs.set_file_contents(os.path.join(root, "version"), - "Bugs Everywhere Tree 0 0\n") + set_version(root) return BugDir(path) @@ -42,18 +55,24 @@ class BugDir: self.dir = dir self.bugs_path = os.path.join(self.dir, "bugs") - def list(self): + for uuid in self.list_uuids(): + yield Bug(self.bugs_path, uuid) + + def list_uuids(self): for uuid in os.listdir(self.bugs_path): if (uuid.startswith('.')): continue - yield Bug(self.bugs_path, uuid) + yield uuid def new_bug(self): uuid = names.uuid() path = os.path.join(self.bugs_path, uuid) rcs.mkdir(path) - return Bug(self.bugs_path, uuid) + bug = Bug(self.bugs_path, None) + bug.uuid = uuid + return bug + class InvalidValue(Exception): def __init__(self, name, value): msg = "Cannot assign value %s to %s" % (value, name) @@ -61,52 +80,48 @@ class InvalidValue(Exception): self.name = name self.value = value -def file_property(name, valid=None): + +def checked_property(name, valid): def getter(self): - value = self._get_value(name) - if valid is not None: - if value not in valid: - raise InvalidValue(name, value) + value = self.__getattribute__("_"+name) + if value not in valid: + raise InvalidValue(name, value) return value + def setter(self, value): - if valid is not None: - if value not in valid: - raise InvalidValue(name, value) - return self._set_value(name, value) + if value not in valid: + raise InvalidValue(name, value) + return self.__setattr__("_"+name, value) return property(getter, setter) + class Bug(object): + status = checked_property("status", (None, "open", "closed")) + severity = checked_property("severity", (None, "wishlist", "minor", + "serious", "critical", "fatal")) + def __init__(self, path, uuid): - self.path = os.path.join(path, uuid) + self.path = path self.uuid = uuid + if uuid is not None: + dict = mapfile.parse(file(self.get_path("values"))) + else: + dict = {} - def get_path(self, file): - return os.path.join(self.path, file) + self.summary = dict.get("summary") + self.creator = dict.get("creator") + self.target = dict.get("target") + self.status = dict.get("status") + self.severity = dict.get("severity") - summary = file_property("summary") - creator = file_property("creator") - target = file_property("target") - status = file_property("status", valid=("open", "closed")) - severity = file_property("severity", valid=("wishlist", "minor", "serious", - "critical", "fatal")) + def get_path(self, file): + return os.path.join(self.path, self.uuid, file) def _get_active(self): return self.status == "open" active = property(_get_active) - def _get_value(self, name): - try: - return file(self.get_path(name), "rb").read().rstrip("\n") - except IOError, e: - if e.errno == errno.EEXIST: - return None - - def _set_value(self, name, value): - if value is None: - rcs.unlink(self.get_path(name)) - rcs.set_file_contents(self.get_path(name), "%s\n" % value) - def add_attr(self, map, name): value = self.__getattribute__(name) if value is not None: @@ -120,8 +135,7 @@ class Bug(object): self.add_attr(map, "status") self.add_attr(map, "severity") path = self.get_path("values") - output = file(path, "wb") if not os.path.exists(path): rcs.add_id(path) - mapfile.generate2(output, map) - + output = file(path, "wb") + mapfile.generate(output, map) diff --git a/libbe/mapfile.py b/libbe/mapfile.py index 6a8e23e..82eadae 100644 --- a/libbe/mapfile.py +++ b/libbe/mapfile.py @@ -12,92 +12,6 @@ class FileString(object): self.str += line -def parse(f): - """Parses a mapfile, returns a Dictionary - - >>> f = FileString("1:q\\n2:q\\n3:q\\n>p\\n4:q\\n5:q\\n6:q\\n") - >>> parse(f)["q"] - 'p' - >>> parse("1:q\\n2:q\\n3:q\\n>r\\n4:q\\n5:q\\n6:q\\n")["q"] - 'r' - >>> parse("1:q:5\\n>s\\n2:q:5\\n")["q:5"] - 's' - >>> parse("1:q\\n>s\\n2:q\\n1:q\\n>s\\n2:q\\n") - Traceback (most recent call last): - File "<stdin>", line 1, in ? - File "libbe/mapfile.py", line 41, in parse - assert (lnum == prev_num + 1) - AssertionError - >>> parse("1:q\\n>s\\n2:q\\n1:l\\n>s\\n2:l\\n1:q\\n>s\\n2:q\\n") - Traceback (most recent call last): - AssertionError - >>> parse("1:q\\n>s\\n>s\\n2:q\\n") - Traceback (most recent call last): - AssertionError - """ - if isinstance(f, basestring): - f = FileString(f) - result = {} - name = None - prev_num = None - for line in f: - value = None - # Handle values - if line.startswith(">"): - assert (name is not None) - assert (not result.has_key(name)) - result[name] = line[1:].rstrip("\n") - # Handle names - else: - lname = ":".join(line.split(":")[1:]).rstrip("\n") - lnum = int(line.split(":")[0]) - - #special-case the first execution - if name is None: - name = lname - - #ensure sequential operation - elif lname == name: - assert (lnum == prev_num + 1) - #if name changes, start over at 1 - else: - if lnum != 1: - assert(lname != name) - raise "%i %s %s" % (lnum, lname, name) - assert (lnum == 1) - name = lname - prev_num = lnum - return result - - -def generate(f, map, context=3): - """ - >>> f = FileString() - >>> generate(f, {"q":"p"}) - >>> f.str - '1:q\\n2:q\\n3:q\\n>p\\n4:q\\n5:q\\n6:q\\n' - >>> parse(f)["q"] - 'p' - >>> f = FileString() - >>> generate(f, {"a":"b", "c":"d", "e":"f"}) - >>> dict = parse(f) - >>> dict["a"] - 'b' - >>> dict["c"] - 'd' - >>> dict["e"] - 'f' - """ - assert(context > 0) - keys = map.keys() - keys.sort() - for key in keys: - for i in range(context): - f.write("%i:%s\n" % (i+1, key)) - f.write(">%s\n" % map[key]) - for i in range(context): - f.write("%i:%s\n" % (i+context+1, key)) - class IllegalKey(Exception): def __init__(self, key): Exception.__init__(self, 'Illegal key "%s"' % key) @@ -108,28 +22,28 @@ class IllegalValue(Exception): Exception.__init__(self, 'Illegal value "%s"' % value) self.value = value -def generate2(f, map, context=3): +def generate(f, map, context=3): """Generate a format-2 mapfile. This is a simpler format, but should merge better, because there's no chance of confusion for appends, and lines are unique for both key and value. >>> f = FileString() - >>> generate2(f, {"q":"p"}) + >>> generate(f, {"q":"p"}) >>> f.str '\\n\\n\\nq=p\\n\\n\\n\\n' - >>> generate2(f, {"q=":"p"}) + >>> generate(f, {"q=":"p"}) Traceback (most recent call last): IllegalKey: Illegal key "q=" - >>> generate2(f, {"q\\n":"p"}) + >>> generate(f, {"q\\n":"p"}) Traceback (most recent call last): IllegalKey: Illegal key "q\\n" - >>> generate2(f, {"":"p"}) + >>> generate(f, {"":"p"}) Traceback (most recent call last): IllegalKey: Illegal key "" - >>> generate2(f, {">q":"p"}) + >>> generate(f, {">q":"p"}) Traceback (most recent call last): IllegalKey: Illegal key ">q" - >>> generate2(f, {"q":"p\\n"}) + >>> generate(f, {"q":"p\\n"}) Traceback (most recent call last): IllegalValue: Illegal value "p\\n" """ @@ -160,16 +74,16 @@ def get_file(f): else: return f -def parse2(f): +def parse(f): """ Parse a format-2 mapfile. - >>> parse2('\\n\\n\\nq=p\\n\\n\\n\\n')['q'] + >>> parse('\\n\\n\\nq=p\\n\\n\\n\\n')['q'] 'p' - >>> parse2('\\n\\nq=\\'p\\'\\n\\n\\n\\n')['q'] + >>> parse('\\n\\nq=\\'p\\'\\n\\n\\n\\n')['q'] "\'p\'" >>> f = FileString() - >>> generate2(f, {"a":"b", "c":"d", "e":"f"}) - >>> dict = parse2(f) + >>> generate(f, {"a":"b", "c":"d", "e":"f"}) + >>> dict = parse(f) >>> dict["a"] 'b' >>> dict["c"] diff --git a/libbe/rcs.py b/libbe/rcs.py index 0da1513..dd0c008 100644 --- a/libbe/rcs.py +++ b/libbe/rcs.py @@ -10,5 +10,9 @@ def set_file_contents(path, contents): add_id(path) def unlink(path): - os.unlink(path) - delete_id(filename) + try: + os.unlink(path) + delete_id(path) + except OSError, e: + if e.errno != 2: + raise |