aboutsummaryrefslogtreecommitdiffstats
path: root/libbe/storage/util/upgrade.py
diff options
context:
space:
mode:
Diffstat (limited to 'libbe/storage/util/upgrade.py')
-rw-r--r--libbe/storage/util/upgrade.py207
1 files changed, 153 insertions, 54 deletions
diff --git a/libbe/storage/util/upgrade.py b/libbe/storage/util/upgrade.py
index c94f171..ce6831d 100644
--- a/libbe/storage/util/upgrade.py
+++ b/libbe/storage/util/upgrade.py
@@ -23,8 +23,11 @@ import os, os.path
import sys
import libbe
-import libbe.bug as bug
+import libbe.bug
import libbe.storage.util.mapfile as mapfile
+#import libbe.storage.vcs # delay import to avoid cyclic dependency
+import libbe.ui.util.editor
+import libbe.util
import libbe.util.encoding as encoding
import libbe.util.id
@@ -33,7 +36,9 @@ import libbe.util.id
BUGDIR_DISK_VERSIONS = ['Bugs Everywhere Tree 1 0',
'Bugs Everywhere Directory v1.1',
'Bugs Everywhere Directory v1.2',
- 'Bugs Everywhere Directory v1.3']
+ 'Bugs Everywhere Directory v1.3',
+ 'Bugs Everywhere Directory v1.4',
+ ]
# the current version
BUGDIR_DISK_VERSION = BUGDIR_DISK_VERSIONS[-1]
@@ -43,30 +48,37 @@ class Upgrader (object):
initial_version = None
final_version = None
def __init__(self, repo):
+ import libbe.storage.vcs
+
self.repo = repo
+ vcs_name = self._get_vcs_name()
+ if vcs_name == None:
+ vcs_name = 'None'
+ self.vcs = libbe.storage.vcs.vcs_by_name(vcs_name)
+ self.vcs.repo = self.repo
+ self.vcs.root()
- def get_path(self, id):
+ def get_path(self, *args):
"""
- Return a path relative to .repo.
+ Return the absolute path using args relative to .be.
"""
- if id == 'version':
- return os.path.join(self.repo, id)
-
-TODO
- dir = os.path.join(self.root, '.be')
+ dir = os.path.join(self.repo, '.be')
if len(args) == 0:
return dir
- assert args[0] in ['version', 'settings', 'bugs'], str(args)
return os.path.join(dir, *args)
+ def _get_vcs_name(self):
+ return None
+
def check_initial_version(self):
path = self.get_path('version')
- version = encoding.get_file_contents(path).rstrip('\n')
- assert version == self.initial_version, version
+ version = encoding.get_file_contents(path, decode=True).rstrip('\n')
+ assert version == self.initial_version, '%s: %s' % (path, version)
def set_version(self):
path = self.get_path('version')
encoding.set_file_contents(path, self.final_version+'\n')
+ self.vcs._vcs_update(path)
def upgrade(self):
print >> sys.stderr, 'upgrading bugdir from "%s" to "%s"' \
@@ -82,11 +94,20 @@ TODO
class Upgrade_1_0_to_1_1 (Upgrader):
initial_version = "Bugs Everywhere Tree 1 0"
final_version = "Bugs Everywhere Directory v1.1"
+ def _get_vcs_name(self):
+ path = self.get_path('settings')
+ settings = encoding.get_file_contents(path)
+ for line in settings.splitlines(False):
+ fields = line.split('=')
+ if len(fields) == 2 and fields[0] == 'rcs_name':
+ return fields[1]
+ return None
+
def _upgrade_mapfile(self, path):
- contents = self.vcs.get_file_contents(path)
+ contents = encoding.get_file_contents(path, decode=True)
old_format = False
for line in contents.splitlines():
- if len(line.split("=")) == 2:
+ if len(line.split('=')) == 2:
old_format = True
break
if old_format == True:
@@ -105,43 +126,56 @@ class Upgrade_1_0_to_1_1 (Upgrader):
contents = '\n'.join(newlines)
# load the YAML and save
map = mapfile.parse(contents)
- mapfile.map_save(self.vcs, path, map)
+ contents = mapfile.generate(map)
+ encoding.set_file_contents(path, contents)
+ self.vcs._vcs_update(path)
def _upgrade(self):
"""
Comment value field "From" -> "Author".
Homegrown mapfile -> YAML.
"""
- path = self.get_path("settings")
+ path = self.get_path('settings')
self._upgrade_mapfile(path)
- for bug_uuid in os.listdir(self.get_path("bugs")):
- path = self.get_path("bugs", bug_uuid, "values")
+ for bug_uuid in os.listdir(self.get_path('bugs')):
+ path = self.get_path('bugs', bug_uuid, 'values')
self._upgrade_mapfile(path)
- c_path = ["bugs", bug_uuid, "comments"]
+ c_path = ['bugs', bug_uuid, 'comments']
if not os.path.exists(self.get_path(*c_path)):
continue # no comments for this bug
for comment_uuid in os.listdir(self.get_path(*c_path)):
- path_list = c_path + [comment_uuid, "values"]
+ path_list = c_path + [comment_uuid, 'values']
path = self.get_path(*path_list)
self._upgrade_mapfile(path)
- settings = mapfile.map_load(self.vcs, path)
- if "From" in settings:
- settings["Author"] = settings.pop("From")
- mapfile.map_save(self.vcs, path, settings)
+ settings = mapfile.parse(
+ encoding.get_file_contents(path))
+ if 'From' in settings:
+ settings['Author'] = settings.pop('From')
+ encoding.set_file_contents(
+ path, mapfile.generate(settings))
+ self.vcs._vcs_update(path)
class Upgrade_1_1_to_1_2 (Upgrader):
initial_version = "Bugs Everywhere Directory v1.1"
final_version = "Bugs Everywhere Directory v1.2"
+ def _get_vcs_name(self):
+ path = self.get_path('settings')
+ settings = mapfile.parse(encoding.get_file_contents(path))
+ if 'rcs_name' in settings:
+ return settings['rcs_name']
+ return None
+
def _upgrade(self):
"""
BugDir settings field "rcs_name" -> "vcs_name".
"""
- path = self.get_path("settings")
- settings = mapfile.map_load(self.vcs, path)
- if "rcs_name" in settings:
- settings["vcs_name"] = settings.pop("rcs_name")
- mapfile.map_save(self.vcs, path, settings)
+ path = self.get_path('settings')
+ settings = mapfile.parse(encoding.get_file_contents(path))
+ if 'rcs_name' in settings:
+ settings['vcs_name'] = settings.pop('rcs_name')
+ encoding.set_file_contents(path, mapfile.generate(settings))
+ self.vcs._vcs_update(path)
class Upgrade_1_2_to_1_3 (Upgrader):
initial_version = "Bugs Everywhere Directory v1.2"
@@ -149,42 +183,64 @@ class Upgrade_1_2_to_1_3 (Upgrader):
def __init__(self, *args, **kwargs):
Upgrader.__init__(self, *args, **kwargs)
self._targets = {} # key: target text,value: new target bug
+
+ def _get_vcs_name(self):
path = self.get_path('settings')
- settings = mapfile.map_load(self.vcs, path)
+ settings = mapfile.parse(encoding.get_file_contents(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
+ return settings['vcs_name']
+ return None
+
+ def _save_bug_settings(self, bug):
+ # The target bugs don't have comments
+ path = self.get_path('bugs', bug.uuid, 'values')
+ if not os.path.exists(path):
+ self.vcs._add_path(path, directory=False)
+ path = self.get_path('bugs', bug.uuid, 'values')
+ mf = mapfile.generate(bug._get_saved_settings())
+ encoding.set_file_contents(path, mf)
+ self.vcs._vcs_update(path)
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
+ bug = libbe.bug.Bug(summary=target_text)
+ 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)
+ mf = encoding.get_file_contents(path)
+ if mf == libbe.util.InvalidObject:
+ return # settings file does not exist
+ settings = mapfile.parse(mf)
if 'target' in settings:
settings['target'] = self._target_bug(settings['target']).uuid
- mapfile.map_save(self.vcs, path, settings)
+ mf = mapfile.generate(settings)
+ encoding.set_file_contents(path, mf)
+ self.vcs._vcs_update(path)
def _upgrade_bug_mapfile(self, bug_uuid):
- import becommands.depend
+ import libbe.command.depend as dep
path = self.get_path('bugs', bug_uuid, 'values')
- settings = mapfile.map_load(self.vcs, path)
+ mf = encoding.get_file_contents(path)
+ if mf == libbe.util.InvalidObject:
+ return # settings file does not exist
+ settings = mapfile.parse(mf)
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()
+
+ blocked_by_string = '%s%s' % (dep.BLOCKED_BY_TAG, bug_uuid)
+ dep._add_remove_extra_string(target_bug, blocked_by_string, add=True)
+ blocks_string = dep._generate_blocks_string(target_bug)
+ estrs = settings.get('extra_strings', [])
+ estrs.append(blocks_string)
+ settings['extra_strings'] = sorted(estrs)
+
+ settings.pop('target')
+ mf = mapfile.generate(settings)
+ encoding.set_file_contents(path, mf)
+ self.vcs._vcs_update(path)
def _upgrade(self):
"""
@@ -194,12 +250,55 @@ class Upgrade_1_2_to_1_3 (Upgrader):
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()
+ for bug in self._targets.values():
+ self._save_bug_settings(bug)
+
+class Upgrade_1_3_to_1_4 (Upgrader):
+ initial_version = "Bugs Everywhere Directory v1.3"
+ final_version = "Bugs Everywhere Directory v1.4"
+ def _get_vcs_name(self):
+ path = self.get_path('settings')
+ settings = mapfile.parse(encoding.get_file_contents(path))
+ if 'vcs_name' in settings:
+ return settings['vcs_name']
+ return None
+
+ def _upgrade(self):
+ """
+ add new directory "./be/BUGDIR-UUID"
+ "./be/bugs" -> "./be/BUGDIR-UUID/bugs"
+ "./be/settings" -> "./be/BUGDIR-UUID/settings"
+ """
+ self.repo = os.path.abspath(self.repo)
+ basenames = [p for p in os.listdir(self.get_path())]
+ if not 'bugs' in basenames and not 'settings' in basenames \
+ and len([p for p in basenames if len(p)==36]) == 1:
+ return # the user has upgraded the directory.
+ basenames = [p for p in basenames if p in ['bugs','settings']]
+ uuid = libbe.util.id.uuid_gen()
+ add = [self.get_path(uuid)]
+ move = [(self.get_path(p), self.get_path(uuid, p)) for p in basenames]
+ msg = ['Upgrading BE directory version v1.3 to v1.4',
+ '',
+ "Because BE's VCS drivers don't support 'move',",
+ 'please make the following changes with your VCS',
+ 'and re-run BE. Note that you can choose a different',
+ 'bugdir UUID to preserve uniformity across branches',
+ 'of a distributed repository.'
+ '',
+ 'add',
+ ' ' + '\n '.join(add),
+ 'move',
+ ' ' + '\n '.join(['%s %s' % (a,b) for a,b in move]),
+ ]
+ self.vcs._cached_path_id.destroy()
+ raise Exception('Need user assistance\n%s' % '\n'.join(msg))
+
upgraders = [Upgrade_1_0_to_1_1,
Upgrade_1_1_to_1_2,
- Upgrade_1_2_to_1_3]
+ Upgrade_1_2_to_1_3,
+ Upgrade_1_3_to_1_4]
upgrade_classes = {}
for upgrader in upgraders:
upgrade_classes[(upgrader.initial_version,upgrader.final_version)]=upgrader
@@ -213,10 +312,10 @@ def upgrade(path, current_version,
"""
if current_version not in BUGDIR_DISK_VERSIONS:
raise NotImplementedError, \
- "Cannot handle version '%s' yet." % version
+ "Cannot handle version '%s' yet." % current_version
if target_version not in BUGDIR_DISK_VERSIONS:
raise NotImplementedError, \
- "Cannot handle version '%s' yet." % version
+ "Cannot handle version '%s' yet." % current_version
if (current_version, target_version) in upgrade_classes:
# direct conversion