~bzr-pqm/bzr/bzr.dev

2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2006 Canonical Ltd
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tree creators for kernel-like trees"""
18
1943.1.1 by John Arbash Meinel
Create the kernel_like_tree rather than expecting the directory to exist. Required when the creator is called directly by another creator
19
import errno
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
20
import os
21
22
from bzrlib import (
23
    add,
24
    bzrdir,
25
    osutils,
1934.1.16 by John Arbash Meinel
Add a cache for a kernel-like inventory
26
    workingtree,
27
    xml5,
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
28
    )
29
30
from bzrlib.benchmarks.tree_creator import TreeCreator
31
32
33
class KernelLikeTreeCreator(TreeCreator):
34
    """Create a basic tree with ~10k unversioned files""" 
35
36
    def __init__(self, test, link_working=False, url=None):
37
        super(KernelLikeTreeCreator, self).__init__(test,
38
            tree_name='kernel_like_tree',
39
            link_working=link_working,
40
            link_bzr=False)
41
42
        self._url = url
43
44
    def create(self, root):
45
        """Create all the kernel files in the given location.
46
47
        This is overloaded for compatibility reasons.
48
        """
49
        if self._url is not None:
50
            b = bzrdir.BzrDir.create_branch_convenience(self._url)
51
            d = bzrdir.BzrDir.create(root)
52
            bzrlib.branch.BranchReferenceFormat().initialize(d, b)
53
            tree = d.create_workingtree()
54
        else:
55
            tree = bzrdir.BzrDir.create_standalone_workingtree(root)
56
57
        if not self._link_working or not self.is_caching_enabled():
58
            # Turns out that 'shutil.copytree()' is no faster than
59
            # just creating them. Probably the python overhead.
60
            # Plain _make_kernel_files takes 3-5s
61
            # cp -a takes 3s
62
            # using hardlinks takes < 1s.
63
            self._create_tree(root=root, in_cache=False)
64
            return tree
65
66
        self.ensure_cached()
67
        cache_dir = self._get_cache_dir()
68
        osutils.copy_tree(cache_dir, root,
69
                          handlers={'file':os.link})
70
        return tree
71
72
    def _create_tree(self, root, in_cache=False):
73
        # a kernel tree has ~10000 and 500 directory, with most files around 
74
        # 3-4 levels deep. 
75
        # we simulate this by three levels of dirs named 0-7, givin 512 dirs,
76
        # and 20 files each.
77
        files = []
78
        for outer in range(8):
79
            files.append("%s/" % outer)
80
            for middle in range(8):
81
                files.append("%s/%s/" % (outer, middle))
82
                for inner in range(8):
83
                    prefix = "%s/%s/%s/" % (outer, middle, inner)
84
                    files.append(prefix)
85
                    files.extend([prefix + str(foo) for foo in range(20)])
86
        cwd = osutils.getcwd()
1943.1.1 by John Arbash Meinel
Create the kernel_like_tree rather than expecting the directory to exist. Required when the creator is called directly by another creator
87
        try:
88
            os.mkdir(root)
89
        except OSError, e:
90
            if e.errno not in (errno.EEXIST,):
91
                raise
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
92
        os.chdir(root)
93
        self._test.build_tree(files)
94
        os.chdir(cwd)
95
        if in_cache:
96
            self._protect_files(root)
97
98
99
class KernelLikeAddedTreeCreator(TreeCreator):
100
101
    def __init__(self, test, link_working=False, hot_cache=True):
102
        super(KernelLikeAddedTreeCreator, self).__init__(test,
103
            tree_name='kernel_like_added_tree',
104
            link_working=link_working,
105
            link_bzr=False,
106
            hot_cache=hot_cache)
107
108
    def _create_tree(self, root, in_cache=False):
109
        """Create a kernel-like tree with the all files added
110
111
        :param root: The root directory to create the files
112
        :param in_cache: Is this being created in the cache dir?
113
        """
114
        kernel_creator = KernelLikeTreeCreator(self._test,
115
                                               link_working=in_cache)
116
        tree = kernel_creator.create(root=root)
117
118
        # Add everything to it
119
        tree.lock_write()
120
        try:
121
            add.smart_add_tree(tree, [root], recurse=True, save=True)
122
            if in_cache:
123
                self._protect_files(root+'/.bzr')
124
        finally:
125
            tree.unlock()
126
        return tree
127
128
129
class KernelLikeCommittedTreeCreator(TreeCreator):
130
    """Create a tree with ~10K files, and a single commit adding all of them"""
131
132
    def __init__(self, test, link_working=False, link_bzr=False,
133
                 hot_cache=True):
134
        super(KernelLikeCommittedTreeCreator, self).__init__(test,
135
            tree_name='kernel_like_committed_tree',
136
            link_working=link_working,
137
            link_bzr=link_bzr,
138
            hot_cache=hot_cache)
139
140
    def _create_tree(self, root, in_cache=False):
141
        """Create a kernel-like tree with all files committed
142
143
        :param root: The root directory to create the files
144
        :param in_cache: Is this being created in the cache dir?
145
        """
146
        kernel_creator = KernelLikeAddedTreeCreator(self._test,
147
                                                    link_working=in_cache,
148
                                                    hot_cache=(not in_cache))
149
        tree = kernel_creator.create(root=root)
150
        tree.commit('first post', rev_id='r1')
151
152
        if in_cache:
153
            self._protect_files(root+'/.bzr')
154
        return tree
1934.1.16 by John Arbash Meinel
Add a cache for a kernel-like inventory
155
156
157
class KernelLikeInventoryCreator(TreeCreator):
158
    """Return just the memory representation of a committed kernel-like tree"""
159
160
    def __init__(self, test):
161
        super(KernelLikeInventoryCreator, self).__init__(test,
162
            tree_name='kernel_like_inventory',
163
            link_working=True,
164
            link_bzr=True,
165
            hot_cache=True)
166
167
    def ensure_cached(self):
168
        """Make sure we have a cached version of the kernel-like inventory"""
169
        cache_dir = self._get_cache_dir()
170
        if cache_dir is None:
171
            return
172
173
        if self.is_cached():
174
            return
175
176
        committed_creator = KernelLikeCommittedTreeCreator(self._test,
177
                                                           link_working=True,
178
                                                           link_bzr=True,
179
                                                           hot_cache=False)
180
        committed_creator.ensure_cached()
181
        committed_cache_dir = committed_creator._get_cache_dir()
182
        committed_tree = workingtree.WorkingTree.open(committed_cache_dir)
183
        rev_tree = committed_tree.basis_tree()
184
        os.mkdir(cache_dir)
185
        f = open(cache_dir+'/inventory', 'wb')
186
        try:
187
            xml5.serializer_v5.write_inventory(rev_tree.inventory, f)
188
        finally:
189
            f.close()
190
191
    def create(self):
192
        """Create a kernel like inventory
193
194
        :return: An Inventory object.
195
        """
196
        cache_dir = self._get_cache_dir()
197
        if cache_dir is None:
198
            return self._create_and_return()
199
200
        self.ensure_cached()
201
        return self._open_cached(cache_dir)
202
203
    def _create_and_return(self):
204
        """Create a kernel-like tree, and return its inventory"""
205
        creator = KernelLikeCommittedTreeCreator(self._test,
206
                                                 link_working=True,
207
                                                 link_bzr=True,
208
                                                 hot_cache=False)
209
        tree = creator.create('.')
210
        return tree.basis_tree().inventory
211
212
    def _open_cached(self, cache_dir):
213
        f = open(cache_dir + '/inventory', 'rb')
214
        try:
215
            return xml5.serializer_v5.read_inventory(f)
216
        finally:
217
            f.close()