From a3d5316acfe99f835404d4f8728e5f8acaad4eff Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 25 Jul 2009 07:32:12 -0400 Subject: Added on_disk option to libbe.bugdir.simple_bug_dir(). Now you can easily generate simple_bug_dirs that live only in memory. --- libbe/bugdir.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 6e020ee..f98186e 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -548,7 +548,7 @@ settings easy. Don't set this attribute. Set .rcs instead, and return True -def simple_bug_dir(): +def simple_bug_dir(on_disk=True): """ For testing >>> bugdir = simple_bug_dir() @@ -557,11 +557,18 @@ def simple_bug_dir(): >>> print ls ['a', 'b'] """ - dir = utility.Dir() - assert os.path.exists(dir.path) - bugdir = BugDir(dir.path, sink_to_existing_root=False, allow_rcs_init=True, + if on_disk == True: + dir = utility.Dir() + assert os.path.exists(dir.path) + root = dir.path + rcs_init = True + else: + root = None + rcs_init = False + bugdir = BugDir(root, sink_to_existing_root=False, allow_rcs_init=rcs_init, manipulate_encodings=False) - bugdir._dir_ref = dir # postpone cleanup since dir.__del__() removes dir. + if on_disk == True: # postpone cleanup since dir.__del__() removes dir. + bugdir._dir_ref = dir bug_a = bugdir.new_bug("a", summary="Bug A") bug_a.creator = "John Doe " bug_a.time = 0 @@ -569,7 +576,8 @@ def simple_bug_dir(): bug_b.creator = "Jane Doe " bug_b.time = 0 bug_b.status = "closed" - bugdir.save() + if on_disk == True: + bugdir.save() return bugdir -- cgit From fa7dd91cd88377e8c41967ef00a9d31e44cb697b Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 25 Jul 2009 08:59:38 -0400 Subject: Added in_memory to BugDir.__init__ to disable saving/loading completely. The previous simple_bug_dir(on_disk==False) supprised me by loading my BE bugdir when called from the BE directory. This functionality could probably move out to Bug and Comment as well, but I have avoided that for now. --- libbe/bugdir.py | 94 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 17 deletions(-) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index f98186e..232ad47 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -17,11 +17,12 @@ # 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. +import copy +import errno import os import os.path -import errno +import sys import time -import copy import unittest import doctest @@ -99,7 +100,7 @@ class BugDir (list, settings_object.SavedSettingsObject): all bugs/comments/etc. that have been loaded into memory. If you've been living in memory and want to move to .sync_with_disk==True, but you're not sure if anything has been - changed in memoryy, a call to save() is a safe move. + changed in memory, a call to save() is a safe move. Regardless of .sync_with_disk, a call to .save() will write out all the contents that the BugDir instance has loaded into memory. @@ -109,7 +110,10 @@ class BugDir (list, settings_object.SavedSettingsObject): The BugDir will only load information from the file system when it loads new bugs/comments that it doesn't already have in memory, or when it explicitly asked to do so (e.g. .load() or - __init__(from_disk=True)). + __init__(from_disk=True)). If you want BugDir to live entirely in + memory (ignoring even explicit calls to .load(), .save(), etc.), + set in_memory = True. The in_memory option is ignored if + from_disk==True. Allow RCS initialization ======================== @@ -281,10 +285,11 @@ settings easy. Don't set this attribute. Set .rcs instead, and def __init__(self, root=None, sink_to_existing_root=True, assert_new_BugDir=False, allow_rcs_init=False, manipulate_encodings=True, - from_disk=False, rcs=None): + from_disk=False, in_memory=False, rcs=None): list.__init__(self) settings_object.SavedSettingsObject.__init__(self) self._manipulate_encodings = manipulate_encodings + self._in_memory = in_memory if root == None: root = os.getcwd() if sink_to_existing_root == True: @@ -299,6 +304,7 @@ settings easy. Don't set this attribute. Set .rcs instead, and if from_disk == True: self.sync_with_disk = True + self._in_memory = False self.load() else: self.sync_with_disk = False @@ -335,6 +341,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and return beroot def get_version(self, path=None, use_none_rcs=False): + if self._in_memory == True: + return TREE_VERSION_STRING if use_none_rcs == True: RCS = rcs.rcs_by_name("None") RCS.root(self.root) @@ -348,6 +356,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and return tree_version def set_version(self): + if self._in_memory == True: + return self.rcs.mkdir(self.get_path()) self.rcs.set_file_contents(self.get_path("version"), TREE_VERSION_STRING) @@ -377,7 +387,7 @@ settings easy. Don't set this attribute. Set .rcs instead, and raise NotImplementedError, \ "BugDir cannot handle version '%s' yet." % version else: - if not os.path.exists(self.get_path()): + if not os.path.exists(self.get_path()) and self._in_memory == False: raise NoBugDir(self.get_path()) self.load_settings() @@ -386,6 +396,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and def load_all_bugs(self): "Warning: this could take a while." + if self._in_memory == True: + return self._clear_bugs() for uuid in self.list_uuids(): self._load_bug(uuid) @@ -403,6 +415,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and self.set_version() self.save_settings() for bug in self: + if self._in_memory == True: + return bug.save() def load_settings(self): @@ -414,6 +428,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and self._setup_status(self.active_status, self.inactive_status) def _get_settings(self, settings_path): + if self._in_memory == True: + return {} allow_no_rcs = not self.rcs.path_in_root(settings_path) # allow_no_rcs=True should only be for the special case of # configuring duplicate bugdir settings @@ -429,6 +445,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and self._save_settings(self.get_path("settings"), settings) def _save_settings(self, settings_path, settings): + if self._in_memory == True: + return allow_no_rcs = not self.rcs.path_in_root(settings_path) # allow_no_rcs=True should only be for the special case of # configuring duplicate bugdir settings @@ -458,7 +476,7 @@ settings easy. Don't set this attribute. Set .rcs instead, and def list_uuids(self): uuids = [] - if os.path.exists(self.get_path()): + if self._in_memory == False and os.path.exists(self.get_path()): # list the uuids on disk for uuid in os.listdir(self.get_path("bugs")): if not (uuid.startswith('.')): @@ -550,22 +568,26 @@ settings easy. Don't set this attribute. Set .rcs instead, and def simple_bug_dir(on_disk=True): """ - For testing + For testing. Set on_disk==False for a memory-only bugdir. >>> bugdir = simple_bug_dir() - >>> ls = list(bugdir.list_uuids()) - >>> ls.sort() - >>> print ls + >>> uuids = list(bugdir.list_uuids()) + >>> uuids.sort() + >>> print uuids ['a', 'b'] """ if on_disk == True: dir = utility.Dir() assert os.path.exists(dir.path) root = dir.path + in_memory = False rcs_init = True else: - root = None + root = "/" + in_memory = True rcs_init = False - bugdir = BugDir(root, sink_to_existing_root=False, allow_rcs_init=rcs_init, + bugdir = BugDir(root, sink_to_existing_root=False, + in_memory=in_memory, + allow_rcs_init=rcs_init, manipulate_encodings=False) if on_disk == True: # postpone cleanup since dir.__del__() removes dir. bugdir._dir_ref = dir @@ -582,8 +604,6 @@ def simple_bug_dir(on_disk=True): class BugDirTestCase(unittest.TestCase): - def __init__(self, *args, **kwargs): - unittest.TestCase.__init__(self, *args, **kwargs) def setUp(self): self.dir = utility.Dir() self.bugdir = BugDir(self.dir.path, sink_to_existing_root=False, @@ -680,5 +700,45 @@ class BugDirTestCase(unittest.TestCase): def testSyncedComments(self): self.testComments(sync_with_disk=True) -unitsuite = unittest.TestLoader().loadTestsFromTestCase(BugDirTestCase) -suite = unittest.TestSuite([unitsuite])#, doctest.DocTestSuite()]) +class SimpleBugDirTestCase (unittest.TestCase): + def setUp(self): + # create a pre-existing bugdir in a temporary directory + self.dir = utility.Dir() + os.chdir(self.dir.path) + self.bugdir = BugDir(self.dir.path, sink_to_existing_root=False, + allow_rcs_init=True) + self.bugdir.new_bug("preexisting", summary="Hopefully not imported") + self.bugdir.save() + def tearDown(self): + self.dir.cleanup() + def testOnDiskCleanLoad(self): + """simple_bug_dir(on_disk==True) should not import preexisting bugs.""" + bugdir = simple_bug_dir(on_disk=True) + self.failUnless(bugdir._in_memory == False, bugdir._in_memory) + uuids = sorted([bug.uuid for bug in bugdir]) + self.failUnless(uuids == ['a', 'b'], uuids) + bugdir._clear_bugs() + uuids = sorted([bug.uuid for bug in bugdir]) + self.failUnless(uuids == [], uuids) + bugdir.load_all_bugs() + uuids = sorted([bug.uuid for bug in bugdir]) + self.failUnless(uuids == ['a', 'b'], uuids) + def testInMemoryCleanLoad(self): + """simple_bug_dir(on_disk==False) should not import preexisting bugs.""" + bugdir = simple_bug_dir(on_disk=False) + self.failUnless(bugdir._in_memory == True, bugdir._in_memory) + uuids = sorted([bug.uuid for bug in bugdir]) + self.failUnless(uuids == ['a', 'b'], uuids) + bugdir.load_all_bugs() + uuids = sorted([bug.uuid for bug in bugdir]) + self.failUnless(uuids == ['a', 'b'], uuids) + bugdir._clear_bugs() + uuids = sorted([bug.uuid for bug in bugdir]) + self.failUnless(uuids == [], uuids) + bugdir.load_all_bugs() + uuids = sorted([bug.uuid for bug in bugdir]) + self.failUnless(uuids == [], uuids) + + +unitsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) +suite = unittest.TestSuite([unitsuite, doctest.DocTestSuite()]) -- cgit From 058dbd6da7c085674680254b68bdba8a6acda117 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sun, 26 Jul 2009 20:04:32 -0400 Subject: BugDir._in_memory was a stupid idea. Took it back out. It was too confusing having three memory access levels: 1) syncronized 2) explicit 3) memory-only with .sync_with_disk selecting between 1 and 2/3 and ._in_memory selecting between 2/3. Now there are only two: 1) syncronized 2) memory-only excepting explicit BugDir.save() calls. I avoid the problem of non-syncronized loading of on-disk bugs in simple_bug_dir by restricting .list_uuids() to in-memory bugs when .sync_with_disk==True. Beyond that, I shifted the order of the BugDir methods around a bit so that they were better grouped according to general idea. Note that the DiskAccessRequired exceptions on filesystem access when .sync_with_disk==False should be propogated to the Bug and Comment methods, but I haven't done that yet. --- libbe/bugdir.py | 250 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 147 insertions(+), 103 deletions(-) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 232ad47..7380172 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -63,6 +63,11 @@ class MultipleBugMatches(ValueError): self.shortname = shortname self.matches = matches +class DiskAccessRequired (Exception): + def __init__(self, goal): + msg = "Cannot %s without accessing the disk" % goal + Exception.__init__(self, msg) + TREE_VERSION_STRING = "Bugs Everywhere Tree 1 0\n" @@ -100,7 +105,8 @@ class BugDir (list, settings_object.SavedSettingsObject): all bugs/comments/etc. that have been loaded into memory. If you've been living in memory and want to move to .sync_with_disk==True, but you're not sure if anything has been - changed in memory, a call to save() is a safe move. + changed in memory, a call to save() immediately before the + .set_sync_with_disk(True) call is a safe move. Regardless of .sync_with_disk, a call to .save() will write out all the contents that the BugDir instance has loaded into memory. @@ -108,12 +114,8 @@ class BugDir (list, settings_object.SavedSettingsObject): changes, this .save() call will be a waste of time. The BugDir will only load information from the file system when it - loads new bugs/comments that it doesn't already have in memory, or - when it explicitly asked to do so (e.g. .load() or - __init__(from_disk=True)). If you want BugDir to live entirely in - memory (ignoring even explicit calls to .load(), .save(), etc.), - set in_memory = True. The in_memory option is ignored if - from_disk==True. + loads new settings/bugs/comments that it doesn't already have in + memory and .sync_with_disk == True. Allow RCS initialization ======================== @@ -284,12 +286,10 @@ settings easy. Don't set this attribute. Set .rcs instead, and def __init__(self, root=None, sink_to_existing_root=True, assert_new_BugDir=False, allow_rcs_init=False, - manipulate_encodings=True, - from_disk=False, in_memory=False, rcs=None): + manipulate_encodings=True, from_disk=False, rcs=None): list.__init__(self) settings_object.SavedSettingsObject.__init__(self) self._manipulate_encodings = manipulate_encodings - self._in_memory = in_memory if root == None: root = os.getcwd() if sink_to_existing_root == True: @@ -304,7 +304,6 @@ settings easy. Don't set this attribute. Set .rcs instead, and if from_disk == True: self.sync_with_disk = True - self._in_memory = False self.load() else: self.sync_with_disk = False @@ -316,15 +315,13 @@ settings easy. Don't set this attribute. Set .rcs instead, and self.rcs = rcs self._setup_user_id(self.user_id) - def set_sync_with_disk(self, value): - self.sync_with_disk = value - for bug in self: - bug.set_sync_with_disk(value) + # methods for getting the BugDir situated in the filesystem def _find_root(self, path): """ Search for an existing bug database dir and it's ancestors and - return a BugDir rooted there. + return a BugDir rooted there. Only called by __init__, and + then only if sink_to_existing_root == True. """ if not os.path.exists(path): raise NoRootEntry(path) @@ -340,9 +337,77 @@ settings easy. Don't set this attribute. Set .rcs instead, and raise NoBugDir(path) return beroot + def _guess_rcs(self, allow_rcs_init=False): + """ + Only called by __init__. + """ + deepdir = self.get_path() + if not os.path.exists(deepdir): + deepdir = os.path.dirname(deepdir) + new_rcs = rcs.detect_rcs(deepdir) + install = False + if new_rcs.name == "None": + if allow_rcs_init == True: + new_rcs = rcs.installed_rcs() + new_rcs.init(self.root) + return new_rcs + + def get_path(self, *args): + """ + Return a path relative to .root. + """ + my_dir = os.path.join(self.root, ".be") + if len(args) == 0: + return my_dir + assert args[0] in ["version", "settings", "bugs"], str(args) + return os.path.join(my_dir, *args) + + # methods for saving/loading/accessing settings and properties. + + def _get_settings(self, settings_path, for_duplicate_bugdir=False): + allow_no_rcs = not self.rcs.path_in_root(settings_path) + if allow_no_rcs == True: + assert for_duplicate_bugdir == True + if self.sync_with_disk == False and for_duplicate_bugdir == False: + # duplicates can ignore this bugdir's .sync_with_disk status + raise DiskAccessRequired("_get settings") + try: + settings = mapfile.map_load(self.rcs, settings_path, allow_no_rcs) + except rcs.NoSuchFile: + settings = {"rcs_name": "None"} + return settings + + def _save_settings(self, settings_path, settings, + for_duplicate_bugdir=False): + allow_no_rcs = not self.rcs.path_in_root(settings_path) + if allow_no_rcs == True: + assert for_duplicate_bugdir == True + if self.sync_with_disk == False and for_duplicate_bugdir == False: + # duplicates can ignore this bugdir's .sync_with_disk status + raise DiskAccessRequired("_save settings") + self.rcs.mkdir(self.get_path(), allow_no_rcs) + mapfile.map_save(self.rcs, settings_path, settings, allow_no_rcs) + + def load_settings(self): + self.settings = self._get_settings(self.get_path("settings")) + self._setup_saved_settings() + self._setup_user_id(self.user_id) + self._setup_encoding(self.encoding) + self._setup_severities(self.severities) + self._setup_status(self.active_status, self.inactive_status) + self.rcs = rcs.rcs_by_name(self.rcs_name) + self._setup_user_id(self.user_id) + + def save_settings(self): + settings = self._get_saved_settings() + self._save_settings(self.get_path("settings"), settings) + def get_version(self, path=None, use_none_rcs=False): - if self._in_memory == True: - return TREE_VERSION_STRING + """ + Requires disk access. + """ + if self.sync_with_disk == False: + raise DiskAccessRequired("get version") if use_none_rcs == True: RCS = rcs.rcs_by_name("None") RCS.root(self.root) @@ -356,102 +421,77 @@ settings easy. Don't set this attribute. Set .rcs instead, and return tree_version def set_version(self): - if self._in_memory == True: - return + """ + Requires disk access. + """ + if self.sync_with_disk == False: + raise DiskAccessRequired("set version") self.rcs.mkdir(self.get_path()) self.rcs.set_file_contents(self.get_path("version"), TREE_VERSION_STRING) - def get_path(self, *args): - my_dir = os.path.join(self.root, ".be") - if len(args) == 0: - return my_dir - assert args[0] in ["version", "settings", "bugs"], str(args) - return os.path.join(my_dir, *args) + # methods controlling disk access - def _guess_rcs(self, allow_rcs_init=False): - deepdir = self.get_path() - if not os.path.exists(deepdir): - deepdir = os.path.dirname(deepdir) - new_rcs = rcs.detect_rcs(deepdir) - install = False - if new_rcs.name == "None": - if allow_rcs_init == True: - new_rcs = rcs.installed_rcs() - new_rcs.init(self.root) - return new_rcs + def set_sync_with_disk(self, value): + """ + Adjust .sync_with_disk for the BugDir and all it's children. + See the BugDir docstring for a description of the role of + .sync_with_disk. + """ + self.sync_with_disk = value + for bug in self: + bug.set_sync_with_disk(value) def load(self): + """ + Reqires disk access + """ version = self.get_version(use_none_rcs=True) if version != TREE_VERSION_STRING: raise NotImplementedError, \ "BugDir cannot handle version '%s' yet." % version else: - if not os.path.exists(self.get_path()) and self._in_memory == False: + if not os.path.exists(self.get_path()): raise NoBugDir(self.get_path()) self.load_settings() - self.rcs = rcs.rcs_by_name(self.rcs_name) - self._setup_user_id(self.user_id) - def load_all_bugs(self): - "Warning: this could take a while." - if self._in_memory == True: - return + """ + Requires disk access. + Warning: this could take a while. + """ + if self.sync_with_disk == False: + raise DiskAccessRequired("load all bugs") self._clear_bugs() for uuid in self.list_uuids(): self._load_bug(uuid) def save(self): """ + Note that this command writes to disk _regardless_ of the + status of .sync_with_disk. + Save any loaded contents to disk. Because of lazy loading of bugs and comments, this is actually not too inefficient. - However, if self.sync_with_disk = True, then any changes are + However, if .sync_with_disk = True, then any changes are automatically written to disk as soon as they happen, so calling this method will just waste time (unless something else has been messing with your on-disk files). + + Requires disk access. """ + sync_with_disk = self.sync_with_disk + if sync_with_disk == False: + self.set_sync_with_disk(True) self.set_version() self.save_settings() for bug in self: - if self._in_memory == True: - return bug.save() + if sync_with_disk == False: + self.set_sync_with_disk(sync_with_disk) - def load_settings(self): - self.settings = self._get_settings(self.get_path("settings")) - self._setup_saved_settings() - self._setup_user_id(self.user_id) - self._setup_encoding(self.encoding) - self._setup_severities(self.severities) - self._setup_status(self.active_status, self.inactive_status) - - def _get_settings(self, settings_path): - if self._in_memory == True: - return {} - allow_no_rcs = not self.rcs.path_in_root(settings_path) - # allow_no_rcs=True should only be for the special case of - # configuring duplicate bugdir settings - - try: - settings = mapfile.map_load(self.rcs, settings_path, allow_no_rcs) - except rcs.NoSuchFile: - settings = {"rcs_name": "None"} - return settings - - def save_settings(self): - settings = self._get_saved_settings() - self._save_settings(self.get_path("settings"), settings) - - def _save_settings(self, settings_path, settings): - if self._in_memory == True: - return - allow_no_rcs = not self.rcs.path_in_root(settings_path) - # allow_no_rcs=True should only be for the special case of - # configuring duplicate bugdir settings - self.rcs.mkdir(self.get_path(), allow_no_rcs) - mapfile.map_save(self.rcs, settings_path, settings, allow_no_rcs) + # methods for managing duplicate BugDirs def duplicate_bugdir(self, revision): duplicate_path = self.rcs.duplicate_repo(revision) @@ -460,23 +500,27 @@ settings easy. Don't set this attribute. Set .rcs instead, and # initialized for versioning duplicate_settings_path = os.path.join(duplicate_path, ".be", "settings") - duplicate_settings = self._get_settings(duplicate_settings_path) + duplicate_settings = self._get_settings(duplicate_settings_path, + for_duplicate_bugdir=True) if "rcs_name" in duplicate_settings: duplicate_settings["rcs_name"] = "None" duplicate_settings["user_id"] = self.user_id if "disabled" in bug.status_values: # Hack to support old versions of BE bugs duplicate_settings["inactive_status"] = self.inactive_status - self._save_settings(duplicate_settings_path, duplicate_settings) + self._save_settings(duplicate_settings_path, duplicate_settings, + for_duplicate_bugdir=True) return BugDir(duplicate_path, from_disk=True, manipulate_encodings=self._manipulate_encodings) def remove_duplicate_bugdir(self): self.rcs.remove_duplicate_repo() + # methods for managing bugs + def list_uuids(self): uuids = [] - if self._in_memory == False and os.path.exists(self.get_path()): + if self.sync_with_disk == True and os.path.exists(self.get_path()): # list the uuids on disk for uuid in os.listdir(self.get_path("bugs")): if not (uuid.startswith('.')): @@ -494,6 +538,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and self._bug_map_gen() def _load_bug(self, uuid): + if self.sync_with_disk == False: + raise DiskAccessRequired("_load bug") bg = bug.Bug(bugdir=self, uuid=uuid, from_disk=True) self.append(bg) self._bug_map_gen() @@ -532,7 +578,7 @@ settings easy. Don't set this attribute. Set .rcs instead, and def bug_from_shortname(self, shortname): """ - >>> bd = simple_bug_dir() + >>> bd = simple_bug_dir(sync_with_disk=False) >>> bug_a = bd.bug_from_shortname('a') >>> print type(bug_a) @@ -566,30 +612,30 @@ settings easy. Don't set this attribute. Set .rcs instead, and return True -def simple_bug_dir(on_disk=True): +def simple_bug_dir(sync_with_disk=True): """ - For testing. Set on_disk==False for a memory-only bugdir. + For testing. Set sync_with_disk==False for a memory-only bugdir. >>> bugdir = simple_bug_dir() >>> uuids = list(bugdir.list_uuids()) >>> uuids.sort() >>> print uuids ['a', 'b'] """ - if on_disk == True: + if sync_with_disk == True: dir = utility.Dir() assert os.path.exists(dir.path) root = dir.path - in_memory = False + assert_new_BugDir = True rcs_init = True else: root = "/" - in_memory = True + assert_new_BugDir = False rcs_init = False bugdir = BugDir(root, sink_to_existing_root=False, - in_memory=in_memory, + assert_new_BugDir=assert_new_BugDir, allow_rcs_init=rcs_init, manipulate_encodings=False) - if on_disk == True: # postpone cleanup since dir.__del__() removes dir. + if sync_with_disk == True: # postpone cleanup since dir.__del__() removes dir. bugdir._dir_ref = dir bug_a = bugdir.new_bug("a", summary="Bug A") bug_a.creator = "John Doe " @@ -598,8 +644,9 @@ def simple_bug_dir(on_disk=True): bug_b.creator = "Jane Doe " bug_b.time = 0 bug_b.status = "closed" - if on_disk == True: + if sync_with_disk == True: bugdir.save() + bugdir.set_sync_with_disk(True) return bugdir @@ -673,9 +720,12 @@ class BugDirTestCase(unittest.TestCase): rep.new_reply("And they have six legs.") if sync_with_disk == False: self.bugdir.save() + self.bugdir.set_sync_with_disk(True) self.bugdir._clear_bugs() bug = self.bugdir.bug_from_uuid("a") bug.load_comments() + if sync_with_disk == False: + self.bugdir.set_sync_with_disk(False) self.failUnless(len(bug.comment_root)==1, len(bug.comment_root)) for index,comment in enumerate(bug.comments()): if index == 0: @@ -683,7 +733,6 @@ class BugDirTestCase(unittest.TestCase): self.failUnless(repLoaded.uuid == rep.uuid, repLoaded.uuid) self.failUnless(comment.sync_with_disk == True, comment.sync_with_disk) - #load_settings() self.failUnless(comment.content_type == "text/plain", comment.content_type) self.failUnless(repLoaded.settings["Content-type"]=="text/plain", @@ -712,9 +761,8 @@ class SimpleBugDirTestCase (unittest.TestCase): def tearDown(self): self.dir.cleanup() def testOnDiskCleanLoad(self): - """simple_bug_dir(on_disk==True) should not import preexisting bugs.""" - bugdir = simple_bug_dir(on_disk=True) - self.failUnless(bugdir._in_memory == False, bugdir._in_memory) + """simple_bug_dir(sync_with_disk==True) should not import preexisting bugs.""" + bugdir = simple_bug_dir(sync_with_disk=True) uuids = sorted([bug.uuid for bug in bugdir]) self.failUnless(uuids == ['a', 'b'], uuids) bugdir._clear_bugs() @@ -724,20 +772,16 @@ class SimpleBugDirTestCase (unittest.TestCase): uuids = sorted([bug.uuid for bug in bugdir]) self.failUnless(uuids == ['a', 'b'], uuids) def testInMemoryCleanLoad(self): - """simple_bug_dir(on_disk==False) should not import preexisting bugs.""" - bugdir = simple_bug_dir(on_disk=False) - self.failUnless(bugdir._in_memory == True, bugdir._in_memory) + """simple_bug_dir(sync_with_disk==False) should not import preexisting bugs.""" + bugdir = simple_bug_dir(sync_with_disk=False) uuids = sorted([bug.uuid for bug in bugdir]) self.failUnless(uuids == ['a', 'b'], uuids) - bugdir.load_all_bugs() + self.failUnlessRaises(DiskAccessRequired, bugdir.load_all_bugs) uuids = sorted([bug.uuid for bug in bugdir]) self.failUnless(uuids == ['a', 'b'], uuids) bugdir._clear_bugs() uuids = sorted([bug.uuid for bug in bugdir]) self.failUnless(uuids == [], uuids) - bugdir.load_all_bugs() - uuids = sorted([bug.uuid for bug in bugdir]) - self.failUnless(uuids == [], uuids) unitsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) -- cgit From 58e2b9fe7a13e7cd99e085059867453496712593 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 27 Jul 2009 05:11:33 -0400 Subject: .sync_with_disk fixes for libbe.bugdir and .comment. In BugDir, only call bug.remove if bug.sync_with_disk==True. If it's just in memory, automatic garbage collection is sufficient cleanup. Comment.set_sync_with_disk() had been setting .sync_with_disk=True regardless of the value passed in. Fixed now. Also some minor textual adjustments. --- libbe/bugdir.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 7380172..e9854c9 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -352,6 +352,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and new_rcs.init(self.root) return new_rcs + # methods for saving/loading/accessing settings and properties. + def get_path(self, *args): """ Return a path relative to .root. @@ -362,8 +364,6 @@ settings easy. Don't set this attribute. Set .rcs instead, and assert args[0] in ["version", "settings", "bugs"], str(args) return os.path.join(my_dir, *args) - # methods for saving/loading/accessing settings and properties. - def _get_settings(self, settings_path, for_duplicate_bugdir=False): allow_no_rcs = not self.rcs.path_in_root(settings_path) if allow_no_rcs == True: @@ -556,7 +556,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and def remove_bug(self, bug): self.remove(bug) - bug.remove() + if bug.sync_with_disk == True: + bug.remove() def bug_shortname(self, bug): """ @@ -763,6 +764,7 @@ class SimpleBugDirTestCase (unittest.TestCase): def testOnDiskCleanLoad(self): """simple_bug_dir(sync_with_disk==True) should not import preexisting bugs.""" bugdir = simple_bug_dir(sync_with_disk=True) + self.failUnless(bugdir.sync_with_disk==True, bugdir.sync_with_disk) uuids = sorted([bug.uuid for bug in bugdir]) self.failUnless(uuids == ['a', 'b'], uuids) bugdir._clear_bugs() @@ -774,6 +776,7 @@ class SimpleBugDirTestCase (unittest.TestCase): def testInMemoryCleanLoad(self): """simple_bug_dir(sync_with_disk==False) should not import preexisting bugs.""" bugdir = simple_bug_dir(sync_with_disk=False) + self.failUnless(bugdir.sync_with_disk==False, bugdir.sync_with_disk) uuids = sorted([bug.uuid for bug in bugdir]) self.failUnless(uuids == ['a', 'b'], uuids) self.failUnlessRaises(DiskAccessRequired, bugdir.load_all_bugs) -- cgit From 4e8882e74aad64859a16f17fa6bef8c04b33913d Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Wed, 29 Jul 2009 15:46:37 -0400 Subject: Added clean messages on bug_from_shortname failure. So user's don't get confused. --- libbe/bugdir.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 6e020ee..f7345fd 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -62,6 +62,12 @@ class MultipleBugMatches(ValueError): self.shortname = shortname self.matches = matches +class NoBugMatches(KeyError): + def __init__(self, shortname): + msg = "No bug matches %s" % shortname + KeyError.__init__(self, msg) + self.shortname = shortname + TREE_VERSION_STRING = "Bugs Everywhere Tree 1 0\n" @@ -530,7 +536,7 @@ settings easy. Don't set this attribute. Set .rcs instead, and raise MultipleBugMatches(shortname, matches) if len(matches) == 1: return self.bug_from_uuid(matches[0]) - raise KeyError("No bug matches %s" % shortname) + raise NoBugMatches(shortname) def bug_from_uuid(self, uuid): if not self.has_bug(uuid): -- cgit From c0e6288158f30802866495c5ae433474c7daf16e Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Fri, 31 Jul 2009 04:25:21 -0400 Subject: Fixed libbe.bugdir.BugDirTestCase.testComments(sync_with_disk=False). --- libbe/bugdir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 1bb307c..8ec5a31 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -738,7 +738,7 @@ class BugDirTestCase(unittest.TestCase): if index == 0: repLoaded = comment self.failUnless(repLoaded.uuid == rep.uuid, repLoaded.uuid) - self.failUnless(comment.sync_with_disk == True, + self.failUnless(comment.sync_with_disk == sync_with_disk, comment.sync_with_disk) self.failUnless(comment.content_type == "text/plain", comment.content_type) -- cgit From 3c4ce1b4519186007f2568569b1bff55cdbb108f Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Fri, 31 Jul 2009 05:24:05 -0400 Subject: Return to original directory after libbe.bugdir.SimpleBugDirTestCase(). This was causing strange "RCS not found" errors in the bzr and hg unittests. For example, the bzr tests all passed: wking@thor:be.wtk-rr$ python test.py bzr ... Ran 12 tests in 24.143s OK Except when run after the bugdir tests: wking@thor:be.wtk-rr$ python test.py bugdir bzr ... Ran 19 tests in 1.862s FAILED (errors=12) Where the failures were all AssertionError: bzr RCS not found Fixed by returning to intial directory after SimpleBugDirTestCase execution. Problem is due to Python issues with unlinked directories though, so bzr/hg will _still_ not work from unlinked directories. This is for Python 2.5.4 on Ubuntu 8.04.3, but probably effects other pythons too. Details: Isolated problem to unlinked directories: mkdir /tmp/a cd /tmp/a rmdir /tmp/a python /home/wking/src/fun/be/be.wtk-rr/test.py bzr which fails with the same "RCS not found" errors because bzr fails: wking@thor:/$ mkdir /tmp/a; cd /tmp/a; rmdir /tmp/a; bzr --help; cd /; rmdir: removing directory, /tmp/a 'import site' failed; use -v for traceback bzr: ERROR: Couldn't import bzrlib and dependencies. Please check bzrlib is on your PYTHONPATH. Traceback (most recent call last): File "/usr/bin/bzr", line 64, in import bzrlib ImportError: No module named bzrlib which fails becase 'import site' fails: wking@thor:/$ mkdir /tmp/a; cd /tmp/a; rmdir /tmp/a; python -c 'import site'; cd /; rmdir: removing directory, /tmp/a 'import site' failed; use -v for traceback Traceback (most recent call last): File "", line 1, in File "/home/wking/lib/python/site.py", line 73, in __boot() File "/home/wking/lib/python/site.py", line 33, in __boot imp.load_module('site',stream,path,descr) File "/usr/lib/python2.5/site.py", line 408, in main() File "/usr/lib/python2.5/site.py", line 392, in main paths_in_sys = removeduppaths() File "/usr/lib/python2.5/site.py", line 96, in removeduppaths dir, dircase = makepath(dir) File "/usr/lib/python2.5/site.py", line 72, in makepath dir = os.path.abspath(os.path.join(*paths)) File "/usr/lib/python2.5/posixpath.py", line 403, in abspath path = join(os.getcwd(), path) OSError: [Errno 2] No such file or directory which fails because our cwd doesn't exist. That makes sense ;). Still I think Python should be able to handle it, so I reported it http://bugs.python.org/issue6612 --- libbe/bugdir.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 8ec5a31..0bcf27e 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -760,12 +760,14 @@ class SimpleBugDirTestCase (unittest.TestCase): def setUp(self): # create a pre-existing bugdir in a temporary directory self.dir = utility.Dir() + self.original_working_dir = os.getcwd() os.chdir(self.dir.path) self.bugdir = BugDir(self.dir.path, sink_to_existing_root=False, allow_rcs_init=True) self.bugdir.new_bug("preexisting", summary="Hopefully not imported") self.bugdir.save() def tearDown(self): + os.chdir(self.original_working_dir) self.dir.cleanup() def testOnDiskCleanLoad(self): """simple_bug_dir(sync_with_disk==True) should not import preexisting bugs.""" -- cgit From 58cba607535cd33c97fd5dc3737c9da4afa9a6bb Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Fri, 31 Jul 2009 14:59:06 -0400 Subject: Improved unittest cleanup by adding BugDir.cleanup(). Also simple_bug_dir -> SimpleBugDir class, which allows me to add utility.Dir cleanup to SimpleBugDir.cleanup(). Still having a bit of trouble with the becommand.new tests due to bugdir loading though... --- libbe/bugdir.py | 81 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 34 deletions(-) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 0bcf27e..0eb4a6c 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -321,6 +321,12 @@ settings easy. Don't set this attribute. Set .rcs instead, and self.rcs = rcs self._setup_user_id(self.user_id) + def __del__(self): + self.cleanup() + + def cleanup(self): + self.rcs.cleanup() + # methods for getting the BugDir situated in the filesystem def _find_root(self, path): @@ -585,12 +591,13 @@ settings easy. Don't set this attribute. Set .rcs instead, and def bug_from_shortname(self, shortname): """ - >>> bd = simple_bug_dir(sync_with_disk=False) + >>> bd = SimpleBugDir(sync_with_disk=False) >>> bug_a = bd.bug_from_shortname('a') >>> print type(bug_a) >>> print bug_a a:om: Bug A + >>> bd.cleanup() """ matches = [] self._bug_map_gen() @@ -619,43 +626,47 @@ settings easy. Don't set this attribute. Set .rcs instead, and return True -def simple_bug_dir(sync_with_disk=True): +class SimpleBugDir (BugDir): """ For testing. Set sync_with_disk==False for a memory-only bugdir. - >>> bugdir = simple_bug_dir() + >>> bugdir = SimpleBugDir() >>> uuids = list(bugdir.list_uuids()) >>> uuids.sort() >>> print uuids ['a', 'b'] + >>> bugdir.cleanup() """ - if sync_with_disk == True: - dir = utility.Dir() - assert os.path.exists(dir.path) - root = dir.path - assert_new_BugDir = True - rcs_init = True - else: - root = "/" - assert_new_BugDir = False - rcs_init = False - bugdir = BugDir(root, sink_to_existing_root=False, + def __init__(self, sync_with_disk=True): + if sync_with_disk == True: + dir = utility.Dir() + assert os.path.exists(dir.path) + root = dir.path + assert_new_BugDir = True + rcs_init = True + else: + root = "/" + assert_new_BugDir = False + rcs_init = False + BugDir.__init__(self, root, sink_to_existing_root=False, assert_new_BugDir=assert_new_BugDir, allow_rcs_init=rcs_init, manipulate_encodings=False) - if sync_with_disk == True: # postpone cleanup since dir.__del__() removes dir. - bugdir._dir_ref = dir - bug_a = bugdir.new_bug("a", summary="Bug A") - bug_a.creator = "John Doe " - bug_a.time = 0 - bug_b = bugdir.new_bug("b", summary="Bug B") - bug_b.creator = "Jane Doe " - bug_b.time = 0 - bug_b.status = "closed" - if sync_with_disk == True: - bugdir.save() - bugdir.set_sync_with_disk(True) - return bugdir - + if sync_with_disk == True: # postpone cleanup since dir.__del__() removes dir. + self._dir_ref = dir + bug_a = self.new_bug("a", summary="Bug A") + bug_a.creator = "John Doe " + bug_a.time = 0 + bug_b = self.new_bug("b", summary="Bug B") + bug_b.creator = "Jane Doe " + bug_b.time = 0 + bug_b.status = "closed" + if sync_with_disk == True: + self.save() + self.set_sync_with_disk(True) + def cleanup(self): + if hasattr(self, "_dir_ref"): + self._dir_ref.cleanup() + BugDir.cleanup(self) class BugDirTestCase(unittest.TestCase): def setUp(self): @@ -664,7 +675,7 @@ class BugDirTestCase(unittest.TestCase): allow_rcs_init=True) self.rcs = self.bugdir.rcs def tearDown(self): - self.rcs.cleanup() + self.bugdir.cleanup() self.dir.cleanup() def fullPath(self, path): return os.path.join(self.dir.path, path) @@ -768,10 +779,11 @@ class SimpleBugDirTestCase (unittest.TestCase): self.bugdir.save() def tearDown(self): os.chdir(self.original_working_dir) + self.bugdir.cleanup() self.dir.cleanup() def testOnDiskCleanLoad(self): - """simple_bug_dir(sync_with_disk==True) should not import preexisting bugs.""" - bugdir = simple_bug_dir(sync_with_disk=True) + """SimpleBugDir(sync_with_disk==True) should not import preexisting bugs.""" + bugdir = SimpleBugDir(sync_with_disk=True) self.failUnless(bugdir.sync_with_disk==True, bugdir.sync_with_disk) uuids = sorted([bug.uuid for bug in bugdir]) self.failUnless(uuids == ['a', 'b'], uuids) @@ -781,9 +793,10 @@ class SimpleBugDirTestCase (unittest.TestCase): bugdir.load_all_bugs() uuids = sorted([bug.uuid for bug in bugdir]) self.failUnless(uuids == ['a', 'b'], uuids) + bugdir.cleanup() def testInMemoryCleanLoad(self): - """simple_bug_dir(sync_with_disk==False) should not import preexisting bugs.""" - bugdir = simple_bug_dir(sync_with_disk=False) + """SimpleBugDir(sync_with_disk==False) should not import preexisting bugs.""" + bugdir = SimpleBugDir(sync_with_disk=False) self.failUnless(bugdir.sync_with_disk==False, bugdir.sync_with_disk) uuids = sorted([bug.uuid for bug in bugdir]) self.failUnless(uuids == ['a', 'b'], uuids) @@ -793,7 +806,7 @@ class SimpleBugDirTestCase (unittest.TestCase): bugdir._clear_bugs() uuids = sorted([bug.uuid for bug in bugdir]) self.failUnless(uuids == [], uuids) - + bugdir.cleanup() unitsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) suite = unittest.TestSuite([unitsuite, doctest.DocTestSuite()]) -- cgit From 7e3f2172564953b6eb2cbfc13eb07d7031cc7331 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 11 Aug 2009 14:46:26 -0400 Subject: Handle BugDir.list_uuids() in the case of missing ".be/bugs/". Previously: $ be init $ be list ... File ".../libbe/bugdir.py", line 537, in list_uuids for uuid in os.listdir(self.get_path("bugs")): OSError: [Errno 2] No such file or directory: '.../.be/bugs' --- libbe/bugdir.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 0eb4a6c..ee6c943 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -534,10 +534,11 @@ settings easy. Don't set this attribute. Set .rcs instead, and uuids = [] if self.sync_with_disk == True and os.path.exists(self.get_path()): # list the uuids on disk - for uuid in os.listdir(self.get_path("bugs")): - if not (uuid.startswith('.')): - uuids.append(uuid) - yield uuid + if os.path.exists(self.get_path("bugs")): + for uuid in os.listdir(self.get_path("bugs")): + if not (uuid.startswith('.')): + uuids.append(uuid) + yield uuid # and the ones that are still just in memory for bug in self: if bug.uuid not in uuids: -- cgit From baa45573a54bf8f7fdcd7fc53d13f9f160954da7 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 31 Aug 2009 11:50:28 -0400 Subject: Made get_path() definitions consistent between bugdirs, bugs, and comments. --- libbe/bugdir.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index ee6c943..64fea1f 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -370,11 +370,11 @@ settings easy. Don't set this attribute. Set .rcs instead, and """ Return a path relative to .root. """ - my_dir = os.path.join(self.root, ".be") + dir = os.path.join(self.root, ".be") if len(args) == 0: - return my_dir + return dir assert args[0] in ["version", "settings", "bugs"], str(args) - return os.path.join(my_dir, *args) + return os.path.join(dir, *args) def _get_settings(self, settings_path, for_duplicate_bugdir=False): allow_no_rcs = not self.rcs.path_in_root(settings_path) -- cgit From 830522c293a479636d7bfc0fff125ec57f06e9a3 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 31 Aug 2009 12:32:05 -0400 Subject: Added libbe/upgrade.py to handle upgrading on-disk bugdirs. --- libbe/bugdir.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 64fea1f..544f6b2 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -26,18 +26,18 @@ import time import unittest import doctest +import bug +import encoding from properties import Property, doc_property, local_property, \ defaulting_property, checked_property, fn_checked_property, \ cached_property, primed_property, change_hook_property, \ settings_property -import settings_object import mapfile -import bug import rcs -import encoding +import settings_object +import upgrade import utility - class NoBugDir(Exception): def __init__(self, path): msg = "The directory \"%s\" has no bug directory." % path @@ -75,9 +75,6 @@ class DiskAccessRequired (Exception): Exception.__init__(self, msg) -TREE_VERSION_STRING = "Bugs Everywhere Tree 1 0\n" - - class BugDir (list, settings_object.SavedSettingsObject): """ Sink to existing root @@ -429,8 +426,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and if path == None: path = self.get_path("version") - tree_version = RCS.get_file_contents(path) - return tree_version + version = RCS.get_file_contents(path).rstrip("\n") + return version def set_version(self): """ @@ -440,7 +437,7 @@ settings easy. Don't set this attribute. Set .rcs instead, and raise DiskAccessRequired("set version") self.rcs.mkdir(self.get_path()) self.rcs.set_file_contents(self.get_path("version"), - TREE_VERSION_STRING) + upgrade.BUGDIR_DISK_VERSION+"\n") # methods controlling disk access @@ -459,9 +456,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and Reqires disk access """ version = self.get_version(use_none_rcs=True) - if version != TREE_VERSION_STRING: - raise NotImplementedError, \ - "BugDir cannot handle version '%s' yet." % version + if version != upgrade.BUGDIR_DISK_VERSION: + upgrade.upgrade(self.root, version) else: if not os.path.exists(self.get_path()): raise NoBugDir(self.get_path()) -- cgit From 5e8576a48fae6e9f7a9699d57571e926d7e6e236 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 31 Aug 2009 13:16:48 -0400 Subject: Upgrade duplicate bugdirs if necessary (e.g. for `be diff'). Also moved pre-YAML mapfile handling in mapfile.parse() into upgrade.Upgrade_1_0_to_2._upgrade_mapfile(). --- libbe/bugdir.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 544f6b2..5946c04 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -411,7 +411,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and settings = self._get_saved_settings() self._save_settings(self.get_path("settings"), settings) - def get_version(self, path=None, use_none_rcs=False): + def get_version(self, path=None, use_none_rcs=False, + for_duplicate_bugdir=False): """ Requires disk access. """ @@ -426,7 +427,11 @@ settings easy. Don't set this attribute. Set .rcs instead, and if path == None: path = self.get_path("version") - version = RCS.get_file_contents(path).rstrip("\n") + allow_no_rcs = not RCS.path_in_root(path) + if allow_no_rcs == True: + assert for_duplicate_bugdir == True + version = RCS.get_file_contents( + path, allow_no_rcs=allow_no_rcs).rstrip("\n") return version def set_version(self): @@ -504,6 +509,12 @@ settings easy. Don't set this attribute. Set .rcs instead, and def duplicate_bugdir(self, revision): duplicate_path = self.rcs.duplicate_repo(revision) + duplicate_version_path = os.path.join(duplicate_path, ".be", "version") + version = self.get_version(duplicate_version_path, + for_duplicate_bugdir=True) + if version != upgrade.BUGDIR_DISK_VERSION: + upgrade.upgrade(duplicate_path, version) + # setup revision RCS as None, since the duplicate may not be # initialized for versioning duplicate_settings_path = os.path.join(duplicate_path, -- cgit From 6d3fc831cdbba47a90b03706f25af1682abe862b Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 31 Aug 2009 13:43:32 -0400 Subject: RCS -> VCS, BUGDIR_DISK_VERSION -> v1.2 --- libbe/bugdir.py | 154 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 77 insertions(+), 77 deletions(-) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 5946c04..3be579f 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -33,7 +33,7 @@ from properties import Property, doc_property, local_property, \ cached_property, primed_property, change_hook_property, \ settings_property import mapfile -import rcs +import vcs import settings_object import upgrade import utility @@ -120,11 +120,11 @@ class BugDir (list, settings_object.SavedSettingsObject): loads new settings/bugs/comments that it doesn't already have in memory and .sync_with_disk == True. - Allow RCS initialization + Allow VCS initialization ======================== This one is for testing purposes. Setting it to True allows the - BugDir to search for an installed RCS backend and initialize it in + BugDir to search for an installed VCS backend and initialize it in the root directory. This is a convenience option for supporting tests of versioning functionality (e.g. .duplicate_bugdir). @@ -181,9 +181,9 @@ class BugDir (list, settings_object.SavedSettingsObject): def encoding(): return {} def _setup_user_id(self, user_id): - self.rcs.user_id = user_id + self.vcs.user_id = user_id def _guess_user_id(self): - return self.rcs.get_user_id() + return self.vcs.get_user_id() def _set_user_id(self, old_user_id, new_user_id): self._setup_user_id(new_user_id) self._prop_save_settings(old_user_id, new_user_id) @@ -191,7 +191,7 @@ class BugDir (list, settings_object.SavedSettingsObject): @_versioned_property(name="user_id", doc= """The user's prefered name, e.g. 'John Doe '. Note -that the Arch RCS backend *enforces* ids with this format.""", +that the Arch VCS backend *enforces* ids with this format.""", change_hook=_set_user_id, generator=_guess_user_id) def user_id(): return {} @@ -201,32 +201,32 @@ that the Arch RCS backend *enforces* ids with this format.""", """The default assignee for new bugs e.g. 'John Doe '.""") def default_assignee(): return {} - @_versioned_property(name="rcs_name", - doc="""The name of the current RCS. Kept seperate to make saving/loading -settings easy. Don't set this attribute. Set .rcs instead, and -.rcs_name will be automatically adjusted.""", + @_versioned_property(name="vcs_name", + doc="""The name of the current VCS. Kept seperate to make saving/loading +settings easy. Don't set this attribute. Set .vcs instead, and +.vcs_name will be automatically adjusted.""", default="None", allowed=["None", "Arch", "bzr", "darcs", "git", "hg"]) - def rcs_name(): return {} + def vcs_name(): return {} - def _get_rcs(self, rcs_name=None): + def _get_vcs(self, vcs_name=None): """Get and root a new revision control system""" - if rcs_name == None: - rcs_name = self.rcs_name - new_rcs = rcs.rcs_by_name(rcs_name) - self._change_rcs(None, new_rcs) - return new_rcs - def _change_rcs(self, old_rcs, new_rcs): - new_rcs.encoding = self.encoding - new_rcs.root(self.root) - self.rcs_name = new_rcs.name + if vcs_name == None: + vcs_name = self.vcs_name + new_vcs = vcs.vcs_by_name(vcs_name) + self._change_vcs(None, new_vcs) + return new_vcs + def _change_vcs(self, old_vcs, new_vcs): + new_vcs.encoding = self.encoding + new_vcs.root(self.root) + self.vcs_name = new_vcs.name @Property - @change_hook_property(hook=_change_rcs) - @cached_property(generator=_get_rcs) - @local_property("rcs") + @change_hook_property(hook=_change_vcs) + @cached_property(generator=_get_vcs) + @local_property("vcs") @doc_property(doc="A revision control system instance.") - def rcs(): return {} + def vcs(): return {} def _bug_map_gen(self): map = {} @@ -288,8 +288,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and def __init__(self, root=None, sink_to_existing_root=True, - assert_new_BugDir=False, allow_rcs_init=False, - manipulate_encodings=True, from_disk=False, rcs=None): + assert_new_BugDir=False, allow_vcs_init=False, + manipulate_encodings=True, from_disk=False, vcs=None): list.__init__(self) settings_object.SavedSettingsObject.__init__(self) self._manipulate_encodings = manipulate_encodings @@ -301,9 +301,9 @@ settings easy. Don't set this attribute. Set .rcs instead, and if not os.path.exists(root): raise NoRootEntry(root) self.root = root - # get a temporary rcs until we've loaded settings + # get a temporary vcs until we've loaded settings self.sync_with_disk = False - self.rcs = self._guess_rcs() + self.vcs = self._guess_vcs() if from_disk == True: self.sync_with_disk = True @@ -313,16 +313,16 @@ settings easy. Don't set this attribute. Set .rcs instead, and if assert_new_BugDir == True: if os.path.exists(self.get_path()): raise AlreadyInitialized, self.get_path() - if rcs == None: - rcs = self._guess_rcs(allow_rcs_init) - self.rcs = rcs + if vcs == None: + vcs = self._guess_vcs(allow_vcs_init) + self.vcs = vcs self._setup_user_id(self.user_id) def __del__(self): self.cleanup() def cleanup(self): - self.rcs.cleanup() + self.vcs.cleanup() # methods for getting the BugDir situated in the filesystem @@ -346,20 +346,20 @@ settings easy. Don't set this attribute. Set .rcs instead, and raise NoBugDir(path) return beroot - def _guess_rcs(self, allow_rcs_init=False): + def _guess_vcs(self, allow_vcs_init=False): """ Only called by __init__. """ deepdir = self.get_path() if not os.path.exists(deepdir): deepdir = os.path.dirname(deepdir) - new_rcs = rcs.detect_rcs(deepdir) + new_vcs = vcs.detect_vcs(deepdir) install = False - if new_rcs.name == "None": - if allow_rcs_init == True: - new_rcs = rcs.installed_rcs() - new_rcs.init(self.root) - return new_rcs + if new_vcs.name == "None": + if allow_vcs_init == True: + new_vcs = vcs.installed_vcs() + new_vcs.init(self.root) + return new_vcs # methods for saving/loading/accessing settings and properties. @@ -374,28 +374,28 @@ settings easy. Don't set this attribute. Set .rcs instead, and return os.path.join(dir, *args) def _get_settings(self, settings_path, for_duplicate_bugdir=False): - allow_no_rcs = not self.rcs.path_in_root(settings_path) - if allow_no_rcs == True: + allow_no_vcs = not self.vcs.path_in_root(settings_path) + if allow_no_vcs == True: assert for_duplicate_bugdir == True if self.sync_with_disk == False and for_duplicate_bugdir == False: # duplicates can ignore this bugdir's .sync_with_disk status raise DiskAccessRequired("_get settings") try: - settings = mapfile.map_load(self.rcs, settings_path, allow_no_rcs) - except rcs.NoSuchFile: - settings = {"rcs_name": "None"} + settings = mapfile.map_load(self.vcs, settings_path, allow_no_vcs) + except vcs.NoSuchFile: + settings = {"vcs_name": "None"} return settings def _save_settings(self, settings_path, settings, for_duplicate_bugdir=False): - allow_no_rcs = not self.rcs.path_in_root(settings_path) - if allow_no_rcs == True: + allow_no_vcs = not self.vcs.path_in_root(settings_path) + if allow_no_vcs == True: assert for_duplicate_bugdir == True if self.sync_with_disk == False and for_duplicate_bugdir == False: # duplicates can ignore this bugdir's .sync_with_disk status raise DiskAccessRequired("_save settings") - self.rcs.mkdir(self.get_path(), allow_no_rcs) - mapfile.map_save(self.rcs, settings_path, settings, allow_no_rcs) + self.vcs.mkdir(self.get_path(), allow_no_vcs) + mapfile.map_save(self.vcs, settings_path, settings, allow_no_vcs) def load_settings(self): self.settings = self._get_settings(self.get_path("settings")) @@ -404,34 +404,34 @@ settings easy. Don't set this attribute. Set .rcs instead, and self._setup_encoding(self.encoding) self._setup_severities(self.severities) self._setup_status(self.active_status, self.inactive_status) - self.rcs = rcs.rcs_by_name(self.rcs_name) + self.vcs = vcs.vcs_by_name(self.vcs_name) self._setup_user_id(self.user_id) def save_settings(self): settings = self._get_saved_settings() self._save_settings(self.get_path("settings"), settings) - def get_version(self, path=None, use_none_rcs=False, + def get_version(self, path=None, use_none_vcs=False, for_duplicate_bugdir=False): """ Requires disk access. """ if self.sync_with_disk == False: raise DiskAccessRequired("get version") - if use_none_rcs == True: - RCS = rcs.rcs_by_name("None") - RCS.root(self.root) - RCS.encoding = encoding.get_encoding() + if use_none_vcs == True: + VCS = vcs.vcs_by_name("None") + VCS.root(self.root) + VCS.encoding = encoding.get_encoding() else: - RCS = self.rcs + VCS = self.vcs if path == None: path = self.get_path("version") - allow_no_rcs = not RCS.path_in_root(path) - if allow_no_rcs == True: + allow_no_vcs = not VCS.path_in_root(path) + if allow_no_vcs == True: assert for_duplicate_bugdir == True - version = RCS.get_file_contents( - path, allow_no_rcs=allow_no_rcs).rstrip("\n") + version = VCS.get_file_contents( + path, allow_no_vcs=allow_no_vcs).rstrip("\n") return version def set_version(self): @@ -440,8 +440,8 @@ settings easy. Don't set this attribute. Set .rcs instead, and """ if self.sync_with_disk == False: raise DiskAccessRequired("set version") - self.rcs.mkdir(self.get_path()) - self.rcs.set_file_contents(self.get_path("version"), + self.vcs.mkdir(self.get_path()) + self.vcs.set_file_contents(self.get_path("version"), upgrade.BUGDIR_DISK_VERSION+"\n") # methods controlling disk access @@ -460,7 +460,7 @@ settings easy. Don't set this attribute. Set .rcs instead, and """ Reqires disk access """ - version = self.get_version(use_none_rcs=True) + version = self.get_version(use_none_vcs=True) if version != upgrade.BUGDIR_DISK_VERSION: upgrade.upgrade(self.root, version) else: @@ -507,7 +507,7 @@ settings easy. Don't set this attribute. Set .rcs instead, and # methods for managing duplicate BugDirs def duplicate_bugdir(self, revision): - duplicate_path = self.rcs.duplicate_repo(revision) + duplicate_path = self.vcs.duplicate_repo(revision) duplicate_version_path = os.path.join(duplicate_path, ".be", "version") version = self.get_version(duplicate_version_path, @@ -515,14 +515,14 @@ settings easy. Don't set this attribute. Set .rcs instead, and if version != upgrade.BUGDIR_DISK_VERSION: upgrade.upgrade(duplicate_path, version) - # setup revision RCS as None, since the duplicate may not be + # setup revision VCS as None, since the duplicate may not be # initialized for versioning duplicate_settings_path = os.path.join(duplicate_path, ".be", "settings") duplicate_settings = self._get_settings(duplicate_settings_path, for_duplicate_bugdir=True) - if "rcs_name" in duplicate_settings: - duplicate_settings["rcs_name"] = "None" + if "vcs_name" in duplicate_settings: + duplicate_settings["vcs_name"] = "None" duplicate_settings["user_id"] = self.user_id if "disabled" in bug.status_values: # Hack to support old versions of BE bugs @@ -533,7 +533,7 @@ settings easy. Don't set this attribute. Set .rcs instead, and return BugDir(duplicate_path, from_disk=True, manipulate_encodings=self._manipulate_encodings) def remove_duplicate_bugdir(self): - self.rcs.remove_duplicate_repo() + self.vcs.remove_duplicate_repo() # methods for managing bugs @@ -650,14 +650,14 @@ class SimpleBugDir (BugDir): assert os.path.exists(dir.path) root = dir.path assert_new_BugDir = True - rcs_init = True + vcs_init = True else: root = "/" assert_new_BugDir = False - rcs_init = False + vcs_init = False BugDir.__init__(self, root, sink_to_existing_root=False, assert_new_BugDir=assert_new_BugDir, - allow_rcs_init=rcs_init, + allow_vcs_init=vcs_init, manipulate_encodings=False) if sync_with_disk == True: # postpone cleanup since dir.__del__() removes dir. self._dir_ref = dir @@ -680,8 +680,8 @@ class BugDirTestCase(unittest.TestCase): def setUp(self): self.dir = utility.Dir() self.bugdir = BugDir(self.dir.path, sink_to_existing_root=False, - allow_rcs_init=True) - self.rcs = self.bugdir.rcs + allow_vcs_init=True) + self.vcs = self.bugdir.vcs def tearDown(self): self.bugdir.cleanup() self.dir.cleanup() @@ -694,13 +694,13 @@ class BugDirTestCase(unittest.TestCase): self.assertRaises(AlreadyInitialized, BugDir, self.dir.path, assertNewBugDir=True) def versionTest(self): - if self.rcs.versioned == False: + if self.vcs.versioned == False: return - original = self.bugdir.rcs.commit("Began versioning") + original = self.bugdir.vcs.commit("Began versioning") bugA = self.bugdir.bug_from_uuid("a") bugA.status = "fixed" self.bugdir.save() - new = self.rcs.commit("Fixed bug a") + new = self.vcs.commit("Fixed bug a") dupdir = self.bugdir.duplicate_bugdir(original) self.failUnless(dupdir.root != self.bugdir.root, "%s, %s" % (dupdir.root, self.bugdir.root)) @@ -782,7 +782,7 @@ class SimpleBugDirTestCase (unittest.TestCase): self.original_working_dir = os.getcwd() os.chdir(self.dir.path) self.bugdir = BugDir(self.dir.path, sink_to_existing_root=False, - allow_rcs_init=True) + allow_vcs_init=True) self.bugdir.new_bug("preexisting", summary="Hopefully not imported") self.bugdir.save() def tearDown(self): -- cgit From e67058f13ce09ab6870c8bd8ebfa2f198bd06b47 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 31 Aug 2009 13:54:09 -0400 Subject: BugDir.duplicate_bugdir() fix for when parent bugdir's sync_with_disk == False. --- libbe/bugdir.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index 3be579f..af43917 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -510,8 +510,14 @@ settings easy. Don't set this attribute. Set .vcs instead, and duplicate_path = self.vcs.duplicate_repo(revision) duplicate_version_path = os.path.join(duplicate_path, ".be", "version") - version = self.get_version(duplicate_version_path, - for_duplicate_bugdir=True) + try: + version = self.get_version(duplicate_version_path, + for_duplicate_bugdir=True) + except DiskAccessRequired: + self.sync_with_disk = True # temporarily allow access + version = self.get_version(duplicate_version_path, + for_duplicate_bugdir=True) + self.sync_with_disk = False if version != upgrade.BUGDIR_DISK_VERSION: upgrade.upgrade(duplicate_path, version) -- cgit From 027cda3613f7a81de557d6dd929d0d4de40192a1 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 31 Aug 2009 14:19:40 -0400 Subject: Added docstrings to libbe submodules. Also a few minor tweaks to the module imports. --- libbe/bugdir.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'libbe/bugdir.py') diff --git a/libbe/bugdir.py b/libbe/bugdir.py index af43917..c4f0f91 100644 --- a/libbe/bugdir.py +++ b/libbe/bugdir.py @@ -17,6 +17,11 @@ # 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. + +""" +Define the BugDir class for representing bug comments. +""" + import copy import errno import os @@ -38,6 +43,7 @@ import settings_object import upgrade import utility + class NoBugDir(Exception): def __init__(self, path): msg = "The directory \"%s\" has no bug directory." % path -- cgit