~bzr-pqm/bzr/bzr.dev

4597.9.2 by Vincent Ladeuil
Merge bzr.dev into cleanup
1
# Copyright (C) 2006-2010 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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
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
    bzrdir,
24
    osutils,
1934.1.16 by John Arbash Meinel
Add a cache for a kernel-like inventory
25
    workingtree,
26
    xml5,
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
27
    )
28
29
from bzrlib.benchmarks.tree_creator import TreeCreator
30
31
32
class KernelLikeTreeCreator(TreeCreator):
2399.1.7 by John Arbash Meinel
Cleanup bzrlib/benchmarks/* so that everything at least has a valid doc string.
33
    """Create a basic tree with ~10k unversioned files"""
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
34
35
    def __init__(self, test, link_working=False, url=None):
36
        super(KernelLikeTreeCreator, self).__init__(test,
37
            tree_name='kernel_like_tree',
38
            link_working=link_working,
39
            link_bzr=False)
40
41
        self._url = url
42
43
    def create(self, root):
44
        """Create all the kernel files in the given location.
45
46
        This is overloaded for compatibility reasons.
47
        """
48
        if self._url is not None:
49
            b = bzrdir.BzrDir.create_branch_convenience(self._url)
50
            d = bzrdir.BzrDir.create(root)
5051.3.10 by Jelmer Vernooij
Pass colocated branch name around in more places.
51
            bzrlib.branch.BranchReferenceFormat().initialize(d,
52
                target_branch=b)
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
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):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
73
        # a kernel tree has ~10000 and 500 directory, with most files around
74
        # 3-4 levels deep.
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
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):
2399.1.7 by John Arbash Meinel
Cleanup bzrlib/benchmarks/* so that everything at least has a valid doc string.
100
    """Create a tree with ~10k versioned but not committed files"""
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
101
102
    def __init__(self, test, link_working=False, hot_cache=True):
103
        super(KernelLikeAddedTreeCreator, self).__init__(test,
104
            tree_name='kernel_like_added_tree',
105
            link_working=link_working,
106
            link_bzr=False,
107
            hot_cache=hot_cache)
108
109
    def _create_tree(self, root, in_cache=False):
110
        """Create a kernel-like tree with the all files added
111
112
        :param root: The root directory to create the files
113
        :param in_cache: Is this being created in the cache dir?
114
        """
115
        kernel_creator = KernelLikeTreeCreator(self._test,
116
                                               link_working=in_cache)
117
        tree = kernel_creator.create(root=root)
118
119
        # Add everything to it
120
        tree.lock_write()
121
        try:
2568.2.7 by Robert Collins
Fix missed tests.
122
            tree.smart_add([root], recurse=True, save=True)
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
123
            if in_cache:
124
                self._protect_files(root+'/.bzr')
125
        finally:
126
            tree.unlock()
127
        return tree
128
129
130
class KernelLikeCommittedTreeCreator(TreeCreator):
131
    """Create a tree with ~10K files, and a single commit adding all of them"""
132
133
    def __init__(self, test, link_working=False, link_bzr=False,
134
                 hot_cache=True):
135
        super(KernelLikeCommittedTreeCreator, self).__init__(test,
136
            tree_name='kernel_like_committed_tree',
137
            link_working=link_working,
138
            link_bzr=link_bzr,
139
            hot_cache=hot_cache)
140
141
    def _create_tree(self, root, in_cache=False):
142
        """Create a kernel-like tree with all files committed
143
144
        :param root: The root directory to create the files
145
        :param in_cache: Is this being created in the cache dir?
146
        """
147
        kernel_creator = KernelLikeAddedTreeCreator(self._test,
148
                                                    link_working=in_cache,
149
                                                    hot_cache=(not in_cache))
150
        tree = kernel_creator.create(root=root)
151
        tree.commit('first post', rev_id='r1')
152
153
        if in_cache:
154
            self._protect_files(root+'/.bzr')
155
        return tree
1934.1.16 by John Arbash Meinel
Add a cache for a kernel-like inventory
156
157
158
class KernelLikeInventoryCreator(TreeCreator):
159
    """Return just the memory representation of a committed kernel-like tree"""
160
161
    def __init__(self, test):
162
        super(KernelLikeInventoryCreator, self).__init__(test,
163
            tree_name='kernel_like_inventory',
164
            link_working=True,
165
            link_bzr=True,
166
            hot_cache=True)
167
168
    def ensure_cached(self):
169
        """Make sure we have a cached version of the kernel-like inventory"""
170
        cache_dir = self._get_cache_dir()
171
        if cache_dir is None:
172
            return
173
174
        if self.is_cached():
175
            return
176
177
        committed_creator = KernelLikeCommittedTreeCreator(self._test,
178
                                                           link_working=True,
179
                                                           link_bzr=True,
180
                                                           hot_cache=False)
181
        committed_creator.ensure_cached()
182
        committed_cache_dir = committed_creator._get_cache_dir()
183
        committed_tree = workingtree.WorkingTree.open(committed_cache_dir)
184
        rev_tree = committed_tree.basis_tree()
185
        os.mkdir(cache_dir)
186
        f = open(cache_dir+'/inventory', 'wb')
187
        try:
188
            xml5.serializer_v5.write_inventory(rev_tree.inventory, f)
189
        finally:
190
            f.close()
191
2399.1.7 by John Arbash Meinel
Cleanup bzrlib/benchmarks/* so that everything at least has a valid doc string.
192
    def create(self, root=None):
1934.1.16 by John Arbash Meinel
Add a cache for a kernel-like inventory
193
        """Create a kernel like inventory
194
2399.1.7 by John Arbash Meinel
Cleanup bzrlib/benchmarks/* so that everything at least has a valid doc string.
195
        :param root: Exists to mimic the base class, but this class
196
            returns only an in-memory Inventory, so it should always be None.
1934.1.16 by John Arbash Meinel
Add a cache for a kernel-like inventory
197
        :return: An Inventory object.
198
        """
199
        cache_dir = self._get_cache_dir()
200
        if cache_dir is None:
201
            return self._create_and_return()
202
203
        self.ensure_cached()
204
        return self._open_cached(cache_dir)
205
206
    def _create_and_return(self):
207
        """Create a kernel-like tree, and return its inventory"""
208
        creator = KernelLikeCommittedTreeCreator(self._test,
209
                                                 link_working=True,
210
                                                 link_bzr=True,
211
                                                 hot_cache=False)
212
        tree = creator.create('.')
2817.2.1 by Robert Collins
* Inventory serialisation no longer double-sha's the content.
213
        basis = tree.basis_tree()
214
        basis.lock_read()
215
        try:
216
            return basis.inventory
217
        finally:
218
            basis.unlock()
1934.1.16 by John Arbash Meinel
Add a cache for a kernel-like inventory
219
220
    def _open_cached(self, cache_dir):
221
        f = open(cache_dir + '/inventory', 'rb')
222
        try:
223
            return xml5.serializer_v5.read_inventory(f)
224
        finally:
225
            f.close()