~jcsackett/charmworld/bac-tag-constraints

« back to all changes in this revision

Viewing changes to migrations/migrate.py

  • Committer: Rick Harding
  • Date: 2013-01-10 17:33:50 UTC
  • mto: This revision was merged to the branch mainline in revision 102.
  • Revision ID: rick.harding@canonical.com-20130110173350-fz1z91843morskow
Initial migrations code with a couple passing tests

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""Migrate data for the mongodb instance.
 
2
 
 
3
Loads migrations from the latest available in the versions directory.
 
4
 
 
5
"""
 
6
import os
 
7
import re
 
8
 
 
9
 
 
10
class DataStore(object):
 
11
    """Communicate with the data store to determine version status."""
 
12
 
 
13
    def __init__(self, db):
 
14
        """Talk to the data store
 
15
 
 
16
        :param db: The mongo db connection.
 
17
 
 
18
        """
 
19
        self.db = db
 
20
 
 
21
    def current_version(self):
 
22
        """Return the current version of the data store."""
 
23
        return self.db.version.find_one({
 
24
            '_id': 'version'
 
25
        })
 
26
 
 
27
    def version_datastore(self):
 
28
        """Init the data to track the current version in the datastore.
 
29
 
 
30
        The data store starts out with version 0.
 
31
 
 
32
        Raises exception if the store is already versioned.
 
33
        """
 
34
        if self.current_version:
 
35
            raise('Data store is already versioned: ' + self.current_version)
 
36
        self.db.version.insert({'_id': 'version', 'version': 0})
 
37
 
 
38
 
 
39
class Versions(object):
 
40
    FILENAME_WITH_VERSION = re.compile(r'^(\d{3,}).*')
 
41
 
 
42
    def _next_ver_num(self, use_timestamp_numbering):
 
43
        return self.latest + 1
 
44
 
 
45
    def _version_path(self, ver):
 
46
        """Returns path of file in versions repository"""
 
47
        return os.path.join(self.path, str(ver))
 
48
 
 
49
    def __init__(self, path):
 
50
        """Collect version scripts and store them in self.versions
 
51
 
 
52
        """
 
53
        # Create temporary list of files, allowing skipped version numbers.
 
54
        files = os.listdir(path)
 
55
        versions = {}
 
56
 
 
57
        for name in files:
 
58
            match = self.FILENAME_WITH_VERSION.match(name)
 
59
            if match:
 
60
                num = int(match.group(1))
 
61
                versions[num] = name
 
62
            else:
 
63
                pass  # Must be a helper file or something, let's ignore it.
 
64
 
 
65
        self.versions = {}
 
66
        version_numbers = versions.keys()
 
67
        version_numbers.sort()
 
68
 
 
69
        self.version_indexes = version_numbers
 
70
        for idx in version_numbers:
 
71
            self.versions[idx] = versions[idx]
 
72
 
 
73
    def create_new_python_version(self, description, **k):
 
74
        """Create Python files for new version"""
 
75
        ver = self._next_ver_num(k.pop('use_timestamp_numbering', False))
 
76
        extra = str_to_filename(description)
 
77
 
 
78
        if extra:
 
79
            if extra == '_':
 
80
                extra = ''
 
81
            elif not extra.startswith('_'):
 
82
                extra = '_%s' % extra
 
83
 
 
84
        filename = '%03d%s.py' % (ver, extra)
 
85
        filepath = self._version_path(filename)
 
86
 
 
87
        script.PythonScript.create(filepath, **k)
 
88
        self.versions[ver] = Version(ver, self.path, [filename])
 
89
 
 
90
    @property
 
91
    def latest(self):
 
92
        """:returns: Latest version in Collection"""
 
93
        return self.version_indexes[-1]