/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
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
1185.65.10 by Robert Collins
Rename Controlfiles to LockableFiles.
16
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
17
from cStringIO import StringIO
18
19
from bzrlib.lazy_import import lazy_import
20
lazy_import(globals(), """
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
21
from binascii import hexlify
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
22
from copy import deepcopy
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
23
import re
24
import time
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
25
import unittest
26
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
27
from bzrlib import (
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
28
    bzrdir,
29
    check,
30
    delta,
31
    errors,
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
32
    generate_ids,
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
33
    gpg,
34
    graph,
1996.3.5 by John Arbash Meinel
Cleanup, deprecated, and get the tests passing again.
35
    knit,
2163.2.1 by John Arbash Meinel
Speed up the fileids_altered_by_revision_ids processing
36
    lazy_regex,
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
37
    lockable_files,
38
    lockdir,
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
39
    osutils,
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
40
    registry,
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
41
    revision as _mod_revision,
42
    symbol_versioning,
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
43
    transactions,
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
44
    ui,
45
    weave,
46
    weavefile,
47
    xml5,
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
48
    xml6,
49
    )
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
50
from bzrlib.osutils import (
51
    rand_bytes,
52
    compact_date, 
53
    local_time_offset,
54
    )
55
from bzrlib.revisiontree import RevisionTree
56
from bzrlib.store.versioned import VersionedFileStore
57
from bzrlib.store.text import TextStore
58
from bzrlib.testament import Testament
59
""")
60
1534.4.28 by Robert Collins
first cut at merge from integration.
61
from bzrlib.decorators import needs_read_lock, needs_write_lock
1563.2.12 by Robert Collins
Checkpointing: created InterObject to factor out common inter object worker code, added InterVersionedFile and tests to allow making join work between any versionedfile.
62
from bzrlib.inter import InterObject
1910.2.3 by Aaron Bentley
All tests pass
63
from bzrlib.inventory import Inventory, InventoryDirectory, ROOT_ID
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
64
from bzrlib.symbol_versioning import (
65
        deprecated_method,
66
        zero_nine,
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
67
        )
1904.2.3 by Martin Pool
Give a warning on access to old repository formats
68
from bzrlib.trace import mutter, note, warning
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
69
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
70
1904.2.5 by Martin Pool
Fix format warning inside test suite and add test
71
# Old formats display a warning, but only once
72
_deprecation_warning_done = False
73
74
1185.66.5 by Aaron Bentley
Renamed RevisionStorage to Repository
75
class Repository(object):
1185.70.3 by Martin Pool
Various updates to make storage branch mergeable:
76
    """Repository holding history for one or more branches.
77
78
    The repository holds and retrieves historical information including
79
    revisions and file history.  It's normally accessed only by the Branch,
80
    which views a particular line of development through that history.
81
82
    The Repository builds on top of Stores and a Transport, which respectively 
83
    describe the disk data format and the way of accessing the (possibly 
84
    remote) disk.
85
    """
1185.65.17 by Robert Collins
Merge from integration, mode-changes are broken.
86
2163.2.1 by John Arbash Meinel
Speed up the fileids_altered_by_revision_ids processing
87
    _file_ids_altered_regex = lazy_regex.lazy_compile(
88
        r'file_id="(?P<file_id>[^"]+)"'
89
        r'.*revision="(?P<revision_id>[^"]+)"'
90
        )
91
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
92
    @needs_write_lock
93
    def add_inventory(self, revid, inv, parents):
94
        """Add the inventory inv to the repository as revid.
95
        
96
        :param parents: The revision ids of the parents that revid
97
                        is known to have and are in the repository already.
98
99
        returns the sha1 of the serialized inventory.
100
        """
2229.2.3 by Aaron Bentley
change reserved_id to is_reserved_id, add check_not_reserved for DRY
101
        _mod_revision.check_not_reserved_id(revid)
1740.2.2 by Aaron Bentley
Add test for the basis inventory automatically adding the revision id.
102
        assert inv.revision_id is None or inv.revision_id == revid, \
103
            "Mismatch between inventory revision" \
104
            " id and insertion revid (%r, %r)" % (inv.revision_id, revid)
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
105
        assert inv.root is not None
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
106
        inv_text = self.serialise_inventory(inv)
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
107
        inv_sha1 = osutils.sha_string(inv_text)
1563.2.25 by Robert Collins
Merge in upstream.
108
        inv_vf = self.control_weaves.get_weave('inventory',
109
                                               self.get_transaction())
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
110
        self._inventory_add_lines(inv_vf, revid, parents, osutils.split_lines(inv_text))
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
111
        return inv_sha1
112
1740.3.6 by Jelmer Vernooij
Move inventory writing to the commit builder.
113
    def _inventory_add_lines(self, inv_vf, revid, parents, lines):
114
        final_parents = []
115
        for parent in parents:
116
            if parent in inv_vf:
117
                final_parents.append(parent)
118
119
        inv_vf.add_lines(revid, final_parents, lines)
120
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
121
    @needs_write_lock
122
    def add_revision(self, rev_id, rev, inv=None, config=None):
123
        """Add rev to the revision store as rev_id.
124
125
        :param rev_id: the revision id to use.
126
        :param rev: The revision object.
127
        :param inv: The inventory for the revision. if None, it will be looked
128
                    up in the inventory storer
129
        :param config: If None no digital signature will be created.
130
                       If supplied its signature_needed method will be used
131
                       to determine if a signature should be made.
132
        """
2229.2.3 by Aaron Bentley
change reserved_id to is_reserved_id, add check_not_reserved for DRY
133
        _mod_revision.check_not_reserved_id(rev_id)
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
134
        if config is not None and config.signature_needed():
135
            if inv is None:
136
                inv = self.get_inventory(rev_id)
137
            plaintext = Testament(rev, inv).as_short_text()
138
            self.store_revision_signature(
139
                gpg.GPGStrategy(config), plaintext, rev_id)
140
        if not rev_id in self.get_inventory_weave():
141
            if inv is None:
142
                raise errors.WeaveRevisionNotPresent(rev_id,
143
                                                     self.get_inventory_weave())
144
            else:
145
                # yes, this is not suitable for adding with ghosts.
146
                self.add_inventory(rev_id, inv, rev.parent_ids)
1608.2.1 by Martin Pool
[merge] Storage filename escaping
147
        self._revision_store.add_revision(rev, self.get_transaction())
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
148
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
149
    @needs_read_lock
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
150
    def _all_possible_ids(self):
151
        """Return all the possible revisions that we could find."""
1563.2.4 by Robert Collins
First cut at including the knit implementation of versioned_file.
152
        return self.get_inventory_weave().versions()
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
153
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
154
    def all_revision_ids(self):
155
        """Returns a list of all the revision ids in the repository. 
156
157
        This is deprecated because code should generally work on the graph
158
        reachable from a particular revision, and ignore any other revisions
159
        that might be present.  There is no direct replacement method.
160
        """
161
        return self._all_revision_ids()
162
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
163
    @needs_read_lock
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
164
    def _all_revision_ids(self):
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
165
        """Returns a list of all the revision ids in the repository. 
166
167
        These are in as much topological order as the underlying store can 
168
        present: for weaves ghosts may lead to a lack of correctness until
169
        the reweave updates the parents list.
170
        """
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
171
        if self._revision_store.text_store.listable():
172
            return self._revision_store.all_revision_ids(self.get_transaction())
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
173
        result = self._all_possible_ids()
174
        return self._eliminate_revisions_not_present(result)
175
1687.1.7 by Robert Collins
Teach Repository about break_lock.
176
    def break_lock(self):
177
        """Break a lock if one is present from another instance.
178
179
        Uses the ui factory to ask for confirmation if the lock may be from
180
        an active process.
181
        """
182
        self.control_files.break_lock()
183
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
184
    @needs_read_lock
185
    def _eliminate_revisions_not_present(self, revision_ids):
186
        """Check every revision id in revision_ids to see if we have it.
187
188
        Returns a set of the present revisions.
189
        """
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
190
        result = []
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
191
        for id in revision_ids:
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
192
            if self.has_revision(id):
193
               result.append(id)
194
        return result
195
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
196
    @staticmethod
197
    def create(a_bzrdir):
198
        """Construct the current default format repository in a_bzrdir."""
199
        return RepositoryFormat.get_default_format().initialize(a_bzrdir)
200
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
201
    def __init__(self, _format, a_bzrdir, control_files, _revision_store, control_store, text_store):
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
202
        """instantiate a Repository.
203
204
        :param _format: The format of the repository on disk.
205
        :param a_bzrdir: The BzrDir of the repository.
206
207
        In the future we will have a single api for all stores for
208
        getting file texts, inventories and revisions, then
209
        this construct will accept instances of those things.
210
        """
1608.2.1 by Martin Pool
[merge] Storage filename escaping
211
        super(Repository, self).__init__()
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
212
        self._format = _format
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
213
        # the following are part of the public API for Repository:
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
214
        self.bzrdir = a_bzrdir
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
215
        self.control_files = control_files
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
216
        self._revision_store = _revision_store
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
217
        self.text_store = text_store
1759.2.1 by Jelmer Vernooij
Fix some types (found using aspell).
218
        # backwards compatibility
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
219
        self.weave_store = text_store
1563.2.23 by Robert Collins
Add add_revision and get_revision methods to RevisionStore
220
        # not right yet - should be more semantically clear ? 
221
        # 
222
        self.control_store = control_store
223
        self.control_weaves = control_store
1608.2.1 by Martin Pool
[merge] Storage filename escaping
224
        # TODO: make sure to construct the right store classes, etc, depending
225
        # on whether escaping is required.
1904.2.3 by Martin Pool
Give a warning on access to old repository formats
226
        self._warn_if_deprecated()
1910.2.48 by Aaron Bentley
Update from review comments
227
        self._serializer = xml5.serializer_v5
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
228
1668.1.3 by Martin Pool
[patch] use the correct transaction when committing snapshot (Malone: #43959)
229
    def __repr__(self):
230
        return '%s(%r)' % (self.__class__.__name__, 
231
                           self.bzrdir.transport.base)
232
1694.2.6 by Martin Pool
[merge] bzr.dev
233
    def is_locked(self):
234
        return self.control_files.is_locked()
235
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
236
    def lock_write(self, token=None):
237
        """Lock this repository for writing.
238
        
239
        :param token: if this is already locked, then lock_write will fail
240
            unless the token matches the existing lock.
241
        :returns: a token if this instance supports tokens, otherwise None.
242
        :raises TokenLockingNotSupported: when a token is given but this
243
            instance doesn't support using token locks.
244
        :raises MismatchedToken: if the specified token doesn't match the token
245
            of the existing lock.
246
247
        XXX: this docstring is duplicated in many places, e.g. lockable_files.py
248
        """
249
        return self.control_files.lock_write(token=token)
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
250
251
    def lock_read(self):
1553.5.55 by Martin Pool
[revert] broken changes
252
        self.control_files.lock_read()
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
253
1694.2.6 by Martin Pool
[merge] bzr.dev
254
    def get_physical_lock_status(self):
255
        return self.control_files.get_physical_lock_status()
1624.3.36 by Olaf Conradi
Rename is_transport_locked() to get_physical_lock_status() as the
256
2018.5.75 by Andrew Bennetts
Add Repository.{dont_,}leave_lock_in_place.
257
    def leave_lock_in_place(self):
258
        """Tell this repository not to release the physical lock when this
259
        object is unlocked.
260
        """
261
        self.control_files.leave_in_place()
262
263
    def dont_leave_lock_in_place(self):
264
        """Tell this repository to release the physical lock when this
265
        object is unlocked, even if it didn't originally acquire it.
266
        """
267
        self.control_files.dont_leave_in_place()
268
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
269
    @needs_read_lock
2258.1.2 by Robert Collins
New version of gather_stats which gathers aggregate data too.
270
    def gather_stats(self, revid=None, committers=None):
2258.1.1 by Robert Collins
Move info branch statistics gathering into the repository to allow smart server optimisation (Robert Collins).
271
        """Gather statistics from a revision id.
272
2258.1.2 by Robert Collins
New version of gather_stats which gathers aggregate data too.
273
        :param revid: The revision id to gather statistics from, if None, then
274
            no revision specific statistics are gathered.
2258.1.1 by Robert Collins
Move info branch statistics gathering into the repository to allow smart server optimisation (Robert Collins).
275
        :param committers: Optional parameter controlling whether to grab
2258.1.2 by Robert Collins
New version of gather_stats which gathers aggregate data too.
276
            a count of committers from the revision specific statistics.
2258.1.1 by Robert Collins
Move info branch statistics gathering into the repository to allow smart server optimisation (Robert Collins).
277
        :return: A dictionary of statistics. Currently this contains:
278
            committers: The number of committers if requested.
279
            firstrev: A tuple with timestamp, timezone for the penultimate left
280
                most ancestor of revid, if revid is not the NULL_REVISION.
281
            latestrev: A tuple with timestamp, timezone for revid, if revid is
282
                not the NULL_REVISION.
2258.1.2 by Robert Collins
New version of gather_stats which gathers aggregate data too.
283
            revisions: The total revision count in the repository.
284
            size: An estimate disk size of the repository in bytes.
2258.1.1 by Robert Collins
Move info branch statistics gathering into the repository to allow smart server optimisation (Robert Collins).
285
        """
286
        result = {}
2258.1.2 by Robert Collins
New version of gather_stats which gathers aggregate data too.
287
        if revid and committers:
2258.1.1 by Robert Collins
Move info branch statistics gathering into the repository to allow smart server optimisation (Robert Collins).
288
            result['committers'] = 0
2258.1.2 by Robert Collins
New version of gather_stats which gathers aggregate data too.
289
        if revid and revid != _mod_revision.NULL_REVISION:
290
            if committers:
291
                all_committers = set()
292
            revisions = self.get_ancestry(revid)
293
            # pop the leading None
294
            revisions.pop(0)
295
            first_revision = None
296
            if not committers:
297
                # ignore the revisions in the middle - just grab first and last
298
                revisions = revisions[0], revisions[-1]
299
            for revision in self.get_revisions(revisions):
300
                if not first_revision:
301
                    first_revision = revision
302
                if committers:
303
                    all_committers.add(revision.committer)
304
            last_revision = revision
305
            if committers:
306
                result['committers'] = len(all_committers)
307
            result['firstrev'] = (first_revision.timestamp,
308
                first_revision.timezone)
309
            result['latestrev'] = (last_revision.timestamp,
310
                last_revision.timezone)
311
312
        # now gather global repository information
313
        if self.bzrdir.root_transport.listable():
314
            c, t = self._revision_store.total_size(self.get_transaction())
315
            result['revisions'] = c
316
            result['size'] = t
2258.1.1 by Robert Collins
Move info branch statistics gathering into the repository to allow smart server optimisation (Robert Collins).
317
        return result
318
319
    @needs_read_lock
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
320
    def missing_revision_ids(self, other, revision_id=None):
321
        """Return the revision ids that other has that this does not.
322
        
323
        These are returned in topological order.
324
325
        revision_id: only return revision ids included by revision_id.
326
        """
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
327
        return InterRepository.get(other, self).missing_revision_ids(revision_id)
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
328
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
329
    @staticmethod
330
    def open(base):
331
        """Open the repository rooted at base.
332
333
        For instance, if the repository is at URL/.bzr/repository,
334
        Repository.open(URL) -> a Repository instance.
335
        """
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
336
        control = bzrdir.BzrDir.open(base)
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
337
        return control.open_repository()
338
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
339
    def copy_content_into(self, destination, revision_id=None, basis=None):
1534.6.6 by Robert Collins
Move find_repository to bzrdir, its not quite ideal there but its simpler and until someone chooses to vary the search by branch type its completely sufficient.
340
        """Make a complete copy of the content in self into destination.
341
        
342
        This is a destructive operation! Do not use it on existing 
343
        repositories.
344
        """
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
345
        return InterRepository.get(self, destination).copy_content(revision_id, basis)
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
346
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
347
    def fetch(self, source, revision_id=None, pb=None):
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
348
        """Fetch the content required to construct revision_id from source.
349
350
        If revision_id is None all content is copied.
351
        """
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
352
        return InterRepository.get(source, self).fetch(revision_id=revision_id,
353
                                                       pb=pb)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
354
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
355
    def get_commit_builder(self, branch, parents, config, timestamp=None, 
356
                           timezone=None, committer=None, revprops=None, 
357
                           revision_id=None):
358
        """Obtain a CommitBuilder for this repository.
359
        
360
        :param branch: Branch to commit to.
361
        :param parents: Revision ids of the parents of the new revision.
362
        :param config: Configuration to use.
363
        :param timestamp: Optional timestamp recorded for commit.
364
        :param timezone: Optional timezone for timestamp.
365
        :param committer: Optional committer to set for commit.
366
        :param revprops: Optional dictionary of revision properties.
367
        :param revision_id: Optional revision id.
368
        """
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
369
        return _CommitBuilder(self, parents, config, timestamp, timezone,
370
                              committer, revprops, revision_id)
1740.3.1 by Jelmer Vernooij
Introduce and use CommitBuilder objects.
371
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
372
    def unlock(self):
373
        self.control_files.unlock()
374
1185.65.27 by Robert Collins
Tweak storage towards mergability.
375
    @needs_read_lock
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
376
    def clone(self, a_bzrdir, revision_id=None, basis=None):
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
377
        """Clone this repository into a_bzrdir using the current format.
378
379
        Currently no check is made that the format of this repository and
380
        the bzrdir format are compatible. FIXME RBC 20060201.
381
        """
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
382
        if not isinstance(a_bzrdir._format, self.bzrdir._format.__class__):
383
            # use target default format.
384
            result = a_bzrdir.create_repository()
385
        # FIXME RBC 20060209 split out the repository type to avoid this check ?
386
        elif isinstance(a_bzrdir._format,
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
387
                      (bzrdir.BzrDirFormat4,
388
                       bzrdir.BzrDirFormat5,
389
                       bzrdir.BzrDirFormat6)):
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
390
            result = a_bzrdir.open_repository()
391
        else:
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
392
            result = self._format.initialize(a_bzrdir, shared=self.is_shared())
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
393
        self.copy_content_into(result, revision_id, basis)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
394
        return result
395
1563.2.22 by Robert Collins
Move responsibility for repository.has_revision into RevisionStore
396
    @needs_read_lock
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
397
    def has_revision(self, revision_id):
1563.2.22 by Robert Collins
Move responsibility for repository.has_revision into RevisionStore
398
        """True if this repository has a copy of the revision."""
399
        return self._revision_store.has_revision_id(revision_id,
400
                                                    self.get_transaction())
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
401
1185.65.27 by Robert Collins
Tweak storage towards mergability.
402
    @needs_read_lock
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
403
    def get_revision_reconcile(self, revision_id):
404
        """'reconcile' helper routine that allows access to a revision always.
405
        
406
        This variant of get_revision does not cross check the weave graph
407
        against the revision one as get_revision does: but it should only
408
        be used by reconcile, or reconcile-alike commands that are correcting
409
        or testing the revision graph.
410
        """
1563.2.25 by Robert Collins
Merge in upstream.
411
        if not revision_id or not isinstance(revision_id, basestring):
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
412
            raise errors.InvalidRevisionId(revision_id=revision_id,
413
                                           branch=self)
1756.1.2 by Aaron Bentley
Show logs using get_revisions
414
        return self._revision_store.get_revisions([revision_id],
415
                                                  self.get_transaction())[0]
416
    @needs_read_lock
417
    def get_revisions(self, revision_ids):
418
        return self._revision_store.get_revisions(revision_ids,
419
                                                  self.get_transaction())
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
420
1185.65.27 by Robert Collins
Tweak storage towards mergability.
421
    @needs_read_lock
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
422
    def get_revision_xml(self, revision_id):
423
        rev = self.get_revision(revision_id) 
424
        rev_tmp = StringIO()
425
        # the current serializer..
426
        self._revision_store._serializer.write_revision(rev, rev_tmp)
427
        rev_tmp.seek(0)
428
        return rev_tmp.getvalue()
429
430
    @needs_read_lock
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
431
    def get_revision(self, revision_id):
432
        """Return the Revision object for a named revision"""
433
        r = self.get_revision_reconcile(revision_id)
434
        # weave corruption can lead to absent revision markers that should be
435
        # present.
436
        # the following test is reasonably cheap (it needs a single weave read)
437
        # and the weave is cached in read transactions. In write transactions
438
        # it is not cached but typically we only read a small number of
439
        # revisions. For knits when they are introduced we will probably want
440
        # to ensure that caching write transactions are in use.
441
        inv = self.get_inventory_weave()
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
442
        self._check_revision_parents(r, inv)
443
        return r
444
1756.3.19 by Aaron Bentley
Documentation and cleanups
445
    @needs_read_lock
1756.3.22 by Aaron Bentley
Tweaks from review
446
    def get_deltas_for_revisions(self, revisions):
1756.3.19 by Aaron Bentley
Documentation and cleanups
447
        """Produce a generator of revision deltas.
448
        
449
        Note that the input is a sequence of REVISIONS, not revision_ids.
450
        Trees will be held in memory until the generator exits.
451
        Each delta is relative to the revision's lefthand predecessor.
452
        """
1756.3.3 by Aaron Bentley
More refactoring, introduce revision_trees.
453
        required_trees = set()
454
        for revision in revisions:
455
            required_trees.add(revision.revision_id)
456
            required_trees.update(revision.parent_ids[:1])
457
        trees = dict((t.get_revision_id(), t) for 
458
                     t in self.revision_trees(required_trees))
459
        for revision in revisions:
460
            if not revision.parent_ids:
1852.5.1 by Robert Collins
Deprecate EmptyTree in favour of using Repository.revision_tree.
461
                old_tree = self.revision_tree(None)
1756.3.3 by Aaron Bentley
More refactoring, introduce revision_trees.
462
            else:
463
                old_tree = trees[revision.parent_ids[0]]
1852.10.3 by Robert Collins
Remove all uses of compare_trees and replace with Tree.changes_from throughout bzrlib.
464
            yield trees[revision.revision_id].changes_from(old_tree)
1756.3.3 by Aaron Bentley
More refactoring, introduce revision_trees.
465
1756.3.19 by Aaron Bentley
Documentation and cleanups
466
    @needs_read_lock
1744.2.2 by Johan Rydberg
Add get_revision_delta to Repository; and make Branch.get_revision_delta use it.
467
    def get_revision_delta(self, revision_id):
468
        """Return the delta for one revision.
469
470
        The delta is relative to the left-hand predecessor of the
471
        revision.
472
        """
1756.3.3 by Aaron Bentley
More refactoring, introduce revision_trees.
473
        r = self.get_revision(revision_id)
1756.3.22 by Aaron Bentley
Tweaks from review
474
        return list(self.get_deltas_for_revisions([r]))[0]
1744.2.2 by Johan Rydberg
Add get_revision_delta to Repository; and make Branch.get_revision_delta use it.
475
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
476
    def _check_revision_parents(self, revision, inventory):
477
        """Private to Repository and Fetch.
478
        
479
        This checks the parentage of revision in an inventory weave for 
480
        consistency and is only applicable to inventory-weave-for-ancestry
481
        using repository formats & fetchers.
482
        """
1563.2.25 by Robert Collins
Merge in upstream.
483
        weave_parents = inventory.get_parents(revision.revision_id)
484
        weave_names = inventory.versions()
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
485
        for parent_id in revision.parent_ids:
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
486
            if parent_id in weave_names:
487
                # this parent must not be a ghost.
488
                if not parent_id in weave_parents:
489
                    # but it is a ghost
490
                    raise errors.CorruptRepository(self)
491
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
492
    @needs_write_lock
493
    def store_revision_signature(self, gpg_strategy, plaintext, revision_id):
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
494
        signature = gpg_strategy.sign(plaintext)
495
        self._revision_store.add_revision_signature_text(revision_id,
496
                                                         signature,
497
                                                         self.get_transaction())
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
498
1694.2.6 by Martin Pool
[merge] bzr.dev
499
    def fileids_altered_by_revision_ids(self, revision_ids):
500
        """Find the file ids and versions affected by revisions.
501
502
        :param revisions: an iterable containing revision ids.
503
        :return: a dictionary mapping altered file-ids to an iterable of
504
        revision_ids. Each altered file-ids has the exact revision_ids that
505
        altered it listed explicitly.
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
506
        """
1910.2.48 by Aaron Bentley
Update from review comments
507
        assert self._serializer.support_altered_by_hack, \
1732.2.1 by Martin Pool
Remove obsolete fileid_involved from KnitRepository, fix error message.
508
            ("fileids_altered_by_revision_ids only supported for branches " 
509
             "which store inventory as unnested xml, not on %r" % self)
1694.2.6 by Martin Pool
[merge] bzr.dev
510
        selected_revision_ids = set(revision_ids)
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
511
        w = self.get_inventory_weave()
1694.2.6 by Martin Pool
[merge] bzr.dev
512
        result = {}
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
513
1694.2.6 by Martin Pool
[merge] bzr.dev
514
        # this code needs to read every new line in every inventory for the
515
        # inventories [revision_ids]. Seeing a line twice is ok. Seeing a line
1759.2.1 by Jelmer Vernooij
Fix some types (found using aspell).
516
        # not present in one of those inventories is unnecessary but not 
1594.2.6 by Robert Collins
Introduce a api specifically for looking at lines in some versions of the inventory, for fileid_involved.
517
        # harmful because we are filtering by the revision id marker in the
1694.2.6 by Martin Pool
[merge] bzr.dev
518
        # inventory lines : we only select file ids altered in one of those  
1759.2.2 by Jelmer Vernooij
Revert some of my spelling fixes and fix some typos after review by Aaron.
519
        # revisions. We don't need to see all lines in the inventory because
1594.2.6 by Robert Collins
Introduce a api specifically for looking at lines in some versions of the inventory, for fileid_involved.
520
        # only those added in an inventory in rev X can contain a revision=X
521
        # line.
2163.2.3 by John Arbash Meinel
Change to local variables to save another 300ms
522
        unescape_revid_cache = {}
523
        unescape_fileid_cache = {}
524
2163.2.5 by John Arbash Meinel
Inline the cache lookup, and explain why
525
        # jam 20061218 In a big fetch, this handles hundreds of thousands
526
        # of lines, so it has had a lot of inlining and optimizing done.
527
        # Sorry that it is a little bit messy.
2163.2.3 by John Arbash Meinel
Change to local variables to save another 300ms
528
        # Move several functions to be local variables, since this is a long
529
        # running loop.
530
        search = self._file_ids_altered_regex.search
2163.2.5 by John Arbash Meinel
Inline the cache lookup, and explain why
531
        unescape = _unescape_xml
2163.2.3 by John Arbash Meinel
Change to local variables to save another 300ms
532
        setdefault = result.setdefault
2039.1.1 by Aaron Bentley
Clean up progress properly when interrupted during fetch (#54000)
533
        pb = ui.ui_factory.nested_progress_bar()
534
        try:
535
            for line in w.iter_lines_added_or_present_in_versions(
2163.2.3 by John Arbash Meinel
Change to local variables to save another 300ms
536
                                        selected_revision_ids, pb=pb):
537
                match = search(line)
2163.2.1 by John Arbash Meinel
Speed up the fileids_altered_by_revision_ids processing
538
                if match is None:
539
                    continue
2163.2.5 by John Arbash Meinel
Inline the cache lookup, and explain why
540
                # One call to match.group() returning multiple items is quite a
541
                # bit faster than 2 calls to match.group() each returning 1
2163.2.1 by John Arbash Meinel
Speed up the fileids_altered_by_revision_ids processing
542
                file_id, revision_id = match.group('file_id', 'revision_id')
2163.2.5 by John Arbash Meinel
Inline the cache lookup, and explain why
543
544
                # Inlining the cache lookups helps a lot when you make 170,000
545
                # lines and 350k ids, versus 8.4 unique ids.
546
                # Using a cache helps in 2 ways:
547
                #   1) Avoids unnecessary decoding calls
548
                #   2) Re-uses cached strings, which helps in future set and
549
                #      equality checks.
550
                # (2) is enough that removing encoding entirely along with
551
                # the cache (so we are using plain strings) results in no
552
                # performance improvement.
553
                try:
554
                    revision_id = unescape_revid_cache[revision_id]
555
                except KeyError:
556
                    unescaped = unescape(revision_id)
557
                    unescape_revid_cache[revision_id] = unescaped
558
                    revision_id = unescaped
559
2039.1.1 by Aaron Bentley
Clean up progress properly when interrupted during fetch (#54000)
560
                if revision_id in selected_revision_ids:
2163.2.5 by John Arbash Meinel
Inline the cache lookup, and explain why
561
                    try:
562
                        file_id = unescape_fileid_cache[file_id]
563
                    except KeyError:
564
                        unescaped = unescape(file_id)
565
                        unescape_fileid_cache[file_id] = unescaped
566
                        file_id = unescaped
2163.2.3 by John Arbash Meinel
Change to local variables to save another 300ms
567
                    setdefault(file_id, set()).add(revision_id)
2039.1.1 by Aaron Bentley
Clean up progress properly when interrupted during fetch (#54000)
568
        finally:
569
            pb.finished()
1694.2.6 by Martin Pool
[merge] bzr.dev
570
        return result
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
571
1185.65.27 by Robert Collins
Tweak storage towards mergability.
572
    @needs_read_lock
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
573
    def get_inventory_weave(self):
574
        return self.control_weaves.get_weave('inventory',
575
            self.get_transaction())
576
1185.65.27 by Robert Collins
Tweak storage towards mergability.
577
    @needs_read_lock
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
578
    def get_inventory(self, revision_id):
579
        """Get Inventory object by hash."""
1740.2.3 by Aaron Bentley
Only reserialize the working tree basis inventory when needed.
580
        return self.deserialise_inventory(
581
            revision_id, self.get_inventory_xml(revision_id))
582
583
    def deserialise_inventory(self, revision_id, xml):
584
        """Transform the xml into an inventory object. 
585
586
        :param revision_id: The expected revision id of the inventory.
587
        :param xml: A serialised inventory.
588
        """
1910.2.48 by Aaron Bentley
Update from review comments
589
        result = self._serializer.read_inventory_from_string(xml)
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
590
        result.root.revision = revision_id
591
        return result
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
592
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
593
    def serialise_inventory(self, inv):
1910.2.48 by Aaron Bentley
Update from review comments
594
        return self._serializer.write_inventory_to_string(inv)
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
595
1185.65.27 by Robert Collins
Tweak storage towards mergability.
596
    @needs_read_lock
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
597
    def get_inventory_xml(self, revision_id):
598
        """Get inventory XML as a file object."""
599
        try:
600
            assert isinstance(revision_id, basestring), type(revision_id)
601
            iw = self.get_inventory_weave()
1563.2.18 by Robert Collins
get knit repositories really using knits for text storage.
602
            return iw.get_text(revision_id)
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
603
        except IndexError:
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
604
            raise errors.HistoryMissing(self, 'inventory', revision_id)
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
605
1185.65.27 by Robert Collins
Tweak storage towards mergability.
606
    @needs_read_lock
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
607
    def get_inventory_sha1(self, revision_id):
608
        """Return the sha1 hash of the inventory entry
609
        """
610
        return self.get_revision(revision_id).inventory_sha1
611
1185.65.27 by Robert Collins
Tweak storage towards mergability.
612
    @needs_read_lock
1590.1.1 by Robert Collins
Improve common_ancestor performance.
613
    def get_revision_graph(self, revision_id=None):
614
        """Return a dictionary containing the revision graph.
615
        
1836.3.1 by Robert Collins
(robertc) Teach repository.get_revision_graph, and revision.common_ancestor, about NULL_REVISION.
616
        :param revision_id: The revision_id to get a graph from. If None, then
617
        the entire revision graph is returned. This is a deprecated mode of
618
        operation and will be removed in the future.
1590.1.1 by Robert Collins
Improve common_ancestor performance.
619
        :return: a dictionary of revision_id->revision_parents_list.
620
        """
1836.3.1 by Robert Collins
(robertc) Teach repository.get_revision_graph, and revision.common_ancestor, about NULL_REVISION.
621
        # special case NULL_REVISION
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
622
        if revision_id == _mod_revision.NULL_REVISION:
1836.3.1 by Robert Collins
(robertc) Teach repository.get_revision_graph, and revision.common_ancestor, about NULL_REVISION.
623
            return {}
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
624
        a_weave = self.get_inventory_weave()
625
        all_revisions = self._eliminate_revisions_not_present(
626
                                a_weave.versions())
627
        entire_graph = dict([(node, a_weave.get_parents(node)) for 
1590.1.1 by Robert Collins
Improve common_ancestor performance.
628
                             node in all_revisions])
629
        if revision_id is None:
630
            return entire_graph
631
        elif revision_id not in entire_graph:
632
            raise errors.NoSuchRevision(self, revision_id)
633
        else:
634
            # add what can be reached from revision_id
635
            result = {}
636
            pending = set([revision_id])
637
            while len(pending) > 0:
638
                node = pending.pop()
639
                result[node] = entire_graph[node]
640
                for revision_id in result[node]:
641
                    if revision_id not in result:
642
                        pending.add(revision_id)
643
            return result
644
645
    @needs_read_lock
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
646
    def get_revision_graph_with_ghosts(self, revision_ids=None):
647
        """Return a graph of the revisions with ghosts marked as applicable.
648
649
        :param revision_ids: an iterable of revisions to graph or None for all.
650
        :return: a Graph object with the graph reachable from revision_ids.
651
        """
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
652
        result = graph.Graph()
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
653
        if not revision_ids:
1773.4.2 by Martin Pool
Cleanup of imports; undeprecate all_revision_ids()
654
            pending = set(self.all_revision_ids())
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
655
            required = set([])
656
        else:
657
            pending = set(revision_ids)
1836.3.1 by Robert Collins
(robertc) Teach repository.get_revision_graph, and revision.common_ancestor, about NULL_REVISION.
658
            # special case NULL_REVISION
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
659
            if _mod_revision.NULL_REVISION in pending:
660
                pending.remove(_mod_revision.NULL_REVISION)
1836.3.1 by Robert Collins
(robertc) Teach repository.get_revision_graph, and revision.common_ancestor, about NULL_REVISION.
661
            required = set(pending)
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
662
        done = set([])
663
        while len(pending):
664
            revision_id = pending.pop()
665
            try:
666
                rev = self.get_revision(revision_id)
667
            except errors.NoSuchRevision:
668
                if revision_id in required:
669
                    raise
670
                # a ghost
671
                result.add_ghost(revision_id)
672
                continue
673
            for parent_id in rev.parent_ids:
674
                # is this queued or done ?
675
                if (parent_id not in pending and
676
                    parent_id not in done):
677
                    # no, queue it.
678
                    pending.add(parent_id)
679
            result.add_node(revision_id, rev.parent_ids)
1594.2.15 by Robert Collins
Unfuck performance.
680
            done.add(revision_id)
1594.2.3 by Robert Collins
bugfix revision.MultipleRevisionSources.get_revision_graph to integrate ghosts between sources. [slow on weaves, fast on knits.
681
        return result
682
683
    @needs_read_lock
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
684
    def get_revision_inventory(self, revision_id):
685
        """Return inventory of a past revision."""
686
        # TODO: Unify this with get_inventory()
687
        # bzr 0.0.6 and later imposes the constraint that the inventory_id
688
        # must be the same as its revision, so this is trivial.
1534.4.28 by Robert Collins
first cut at merge from integration.
689
        if revision_id is None:
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
690
            # This does not make sense: if there is no revision,
691
            # then it is the current tree inventory surely ?!
692
            # and thus get_root_id() is something that looks at the last
693
            # commit on the branch, and the get_root_id is an inventory check.
694
            raise NotImplementedError
695
            # return Inventory(self.get_root_id())
696
        else:
697
            return self.get_inventory(revision_id)
698
1185.65.27 by Robert Collins
Tweak storage towards mergability.
699
    @needs_read_lock
1534.6.3 by Robert Collins
find_repository sufficiently robust.
700
    def is_shared(self):
701
        """Return True if this repository is flagged as a shared repository."""
1596.2.12 by Robert Collins
Merge and make Knit Repository use the revision store for all possible queries.
702
        raise NotImplementedError(self.is_shared)
1534.6.3 by Robert Collins
find_repository sufficiently robust.
703
1594.2.7 by Robert Collins
Add versionedfile.fix_parents api for correcting data post hoc.
704
    @needs_write_lock
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
705
    def reconcile(self, other=None, thorough=False):
1594.2.7 by Robert Collins
Add versionedfile.fix_parents api for correcting data post hoc.
706
        """Reconcile this repository."""
707
        from bzrlib.reconcile import RepoReconciler
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
708
        reconciler = RepoReconciler(self, thorough=thorough)
1594.2.7 by Robert Collins
Add versionedfile.fix_parents api for correcting data post hoc.
709
        reconciler.reconcile()
710
        return reconciler
711
    
1534.6.3 by Robert Collins
find_repository sufficiently robust.
712
    @needs_read_lock
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
713
    def revision_tree(self, revision_id):
714
        """Return Tree for a revision on this branch.
715
1852.5.1 by Robert Collins
Deprecate EmptyTree in favour of using Repository.revision_tree.
716
        `revision_id` may be None for the empty tree revision.
717
        """
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
718
        # TODO: refactor this to use an existing revision object
719
        # so we don't need to read it in twice.
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
720
        if revision_id is None or revision_id == _mod_revision.NULL_REVISION:
1731.1.61 by Aaron Bentley
Merge bzr.dev
721
            return RevisionTree(self, Inventory(root_id=None), 
722
                                _mod_revision.NULL_REVISION)
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
723
        else:
724
            inv = self.get_revision_inventory(revision_id)
1185.65.17 by Robert Collins
Merge from integration, mode-changes are broken.
725
            return RevisionTree(self, inv, revision_id)
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
726
1185.65.27 by Robert Collins
Tweak storage towards mergability.
727
    @needs_read_lock
1756.3.3 by Aaron Bentley
More refactoring, introduce revision_trees.
728
    def revision_trees(self, revision_ids):
729
        """Return Tree for a revision on this branch.
730
1756.3.19 by Aaron Bentley
Documentation and cleanups
731
        `revision_id` may not be None or 'null:'"""
1756.3.3 by Aaron Bentley
More refactoring, introduce revision_trees.
732
        assert None not in revision_ids
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
733
        assert _mod_revision.NULL_REVISION not in revision_ids
1756.3.5 by Aaron Bentley
Switch to get_texts, optimize get_texts
734
        texts = self.get_inventory_weave().get_texts(revision_ids)
1756.3.3 by Aaron Bentley
More refactoring, introduce revision_trees.
735
        for text, revision_id in zip(texts, revision_ids):
736
            inv = self.deserialise_inventory(revision_id, text)
737
            yield RevisionTree(self, inv, revision_id)
738
739
    @needs_read_lock
1185.66.2 by Aaron Bentley
Moved get_ancestry to RevisionStorage
740
    def get_ancestry(self, revision_id):
741
        """Return a list of revision-ids integrated by a revision.
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
742
743
        The first element of the list is always None, indicating the origin 
744
        revision.  This might change when we have history horizons, or 
745
        perhaps we should have a new API.
1185.66.2 by Aaron Bentley
Moved get_ancestry to RevisionStorage
746
        
747
        This is topologically sorted.
748
        """
749
        if revision_id is None:
750
            return [None]
1534.4.41 by Robert Collins
Branch now uses BzrDir reasonably sanely.
751
        if not self.has_revision(revision_id):
752
            raise errors.NoSuchRevision(self, revision_id)
1185.66.2 by Aaron Bentley
Moved get_ancestry to RevisionStorage
753
        w = self.get_inventory_weave()
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
754
        candidates = w.get_ancestry(revision_id)
755
        return [None] + candidates # self._eliminate_revisions_not_present(candidates)
1185.66.2 by Aaron Bentley
Moved get_ancestry to RevisionStorage
756
1185.65.4 by Aaron Bentley
Fixed cat command
757
    @needs_read_lock
758
    def print_file(self, file, revision_id):
1185.65.29 by Robert Collins
Implement final review suggestions.
759
        """Print `file` to stdout.
760
        
761
        FIXME RBC 20060125 as John Meinel points out this is a bad api
762
        - it writes to stdout, it assumes that that is valid etc. Fix
763
        by creating a new more flexible convenience function.
764
        """
1185.65.4 by Aaron Bentley
Fixed cat command
765
        tree = self.revision_tree(revision_id)
766
        # use inventory as it was in that revision
767
        file_id = tree.inventory.path2id(file)
768
        if not file_id:
1685.1.26 by John Arbash Meinel
Repository had a bug with what exception was raised when a file was missing
769
            # TODO: jam 20060427 Write a test for this code path
770
            #       it had a bug in it, and was raising the wrong
771
            #       exception.
772
            raise errors.BzrError("%r is not present in revision %s" % (file, revision_id))
1185.65.4 by Aaron Bentley
Fixed cat command
773
        tree.print_file(file_id)
774
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
775
    def get_transaction(self):
776
        return self.control_files.get_transaction()
777
1590.1.1 by Robert Collins
Improve common_ancestor performance.
778
    def revision_parents(self, revid):
779
        return self.get_inventory_weave().parent_names(revid)
780
1185.65.27 by Robert Collins
Tweak storage towards mergability.
781
    @needs_write_lock
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
782
    def set_make_working_trees(self, new_value):
783
        """Set the policy flag for making working trees when creating branches.
784
785
        This only applies to branches that use this repository.
786
787
        The default is 'True'.
788
        :param new_value: True to restore the default, False to disable making
789
                          working trees.
790
        """
1596.2.12 by Robert Collins
Merge and make Knit Repository use the revision store for all possible queries.
791
        raise NotImplementedError(self.set_make_working_trees)
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
792
    
793
    def make_working_trees(self):
794
        """Returns the policy for making working trees on new branches."""
1596.2.12 by Robert Collins
Merge and make Knit Repository use the revision store for all possible queries.
795
        raise NotImplementedError(self.make_working_trees)
1534.6.5 by Robert Collins
Cloning of repos preserves shared and make-working-tree attributes.
796
797
    @needs_write_lock
1185.65.1 by Aaron Bentley
Refactored out ControlFiles and RevisionStore from _Branch
798
    def sign_revision(self, revision_id, gpg_strategy):
799
        plaintext = Testament.from_revision(self, revision_id).as_short_text()
800
        self.store_revision_signature(gpg_strategy, plaintext, revision_id)
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
801
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
802
    @needs_read_lock
803
    def has_signature_for_revision_id(self, revision_id):
804
        """Query for a revision signature for revision_id in the repository."""
805
        return self._revision_store.has_signature(revision_id,
806
                                                  self.get_transaction())
807
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
808
    @needs_read_lock
809
    def get_signature_text(self, revision_id):
810
        """Return the text for a signature."""
811
        return self._revision_store.get_signature_text(revision_id,
812
                                                       self.get_transaction())
813
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
814
    @needs_read_lock
815
    def check(self, revision_ids):
816
        """Check consistency of all history of given revision_ids.
817
818
        Different repository implementations should override _check().
819
820
        :param revision_ids: A non-empty list of revision_ids whose ancestry
821
             will be checked.  Typically the last revision_id of a branch.
822
        """
823
        if not revision_ids:
824
            raise ValueError("revision_ids must be non-empty in %s.check" 
825
                    % (self,))
826
        return self._check(revision_ids)
827
828
    def _check(self, revision_ids):
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
829
        result = check.Check(self)
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
830
        result.check()
831
        return result
832
1904.2.3 by Martin Pool
Give a warning on access to old repository formats
833
    def _warn_if_deprecated(self):
1904.2.5 by Martin Pool
Fix format warning inside test suite and add test
834
        global _deprecation_warning_done
835
        if _deprecation_warning_done:
836
            return
837
        _deprecation_warning_done = True
1904.2.3 by Martin Pool
Give a warning on access to old repository formats
838
        warning("Format %s for %s is deprecated - please use 'bzr upgrade' to get better performance"
839
                % (self._format, self.bzrdir.transport.base))
840
1910.2.63 by Aaron Bentley
Add supports_rich_root member to repository
841
    def supports_rich_root(self):
842
        return self._format.rich_root_data
843
2150.2.2 by Robert Collins
Change the commit builder selected-revision-id test to use a unicode revision id where possible, leading to stricter testing of the hypothetical unicode revision id support in bzr.
844
    def _check_ascii_revisionid(self, revision_id, method):
845
        """Private helper for ascii-only repositories."""
846
        # weave repositories refuse to store revisionids that are non-ascii.
847
        if revision_id is not None:
848
            # weaves require ascii revision ids.
849
            if isinstance(revision_id, unicode):
850
                try:
851
                    revision_id.encode('ascii')
852
                except UnicodeEncodeError:
853
                    raise errors.NonAsciiRevisionId(method, self)
854
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
855
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
856
class AllInOneRepository(Repository):
857
    """Legacy support - the repository behaviour for all-in-one branches."""
858
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
859
    def __init__(self, _format, a_bzrdir, _revision_store, control_store, text_store):
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
860
        # we reuse one control files instance.
861
        dir_mode = a_bzrdir._control_files._dir_mode
862
        file_mode = a_bzrdir._control_files._file_mode
863
864
        def get_store(name, compressed=True, prefixed=False):
865
            # FIXME: This approach of assuming stores are all entirely compressed
866
            # or entirely uncompressed is tidy, but breaks upgrade from 
867
            # some existing branches where there's a mixture; we probably 
868
            # still want the option to look for both.
869
            relpath = a_bzrdir._control_files._escape(name)
870
            store = TextStore(a_bzrdir._control_files._transport.clone(relpath),
871
                              prefixed=prefixed, compressed=compressed,
872
                              dir_mode=dir_mode,
873
                              file_mode=file_mode)
874
            #if self._transport.should_cache():
875
            #    cache_path = os.path.join(self.cache_root, name)
876
            #    os.mkdir(cache_path)
877
            #    store = bzrlib.store.CachedStore(store, cache_path)
878
            return store
879
880
        # not broken out yet because the controlweaves|inventory_store
881
        # and text_store | weave_store bits are still different.
882
        if isinstance(_format, RepositoryFormat4):
1563.2.23 by Robert Collins
Add add_revision and get_revision methods to RevisionStore
883
            # cannot remove these - there is still no consistent api 
884
            # which allows access to this old info.
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
885
            self.inventory_store = get_store('inventory-store')
1563.2.18 by Robert Collins
get knit repositories really using knits for text storage.
886
            text_store = get_store('text-store')
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
887
        super(AllInOneRepository, self).__init__(_format, a_bzrdir, a_bzrdir._control_files, _revision_store, control_store, text_store)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
888
2150.2.2 by Robert Collins
Change the commit builder selected-revision-id test to use a unicode revision id where possible, leading to stricter testing of the hypothetical unicode revision id support in bzr.
889
    def get_commit_builder(self, branch, parents, config, timestamp=None,
890
                           timezone=None, committer=None, revprops=None,
891
                           revision_id=None):
892
        self._check_ascii_revisionid(revision_id, self.get_commit_builder)
893
        return Repository.get_commit_builder(self, branch, parents, config,
894
            timestamp, timezone, committer, revprops, revision_id)
895
1596.2.12 by Robert Collins
Merge and make Knit Repository use the revision store for all possible queries.
896
    @needs_read_lock
897
    def is_shared(self):
898
        """AllInOne repositories cannot be shared."""
899
        return False
900
901
    @needs_write_lock
902
    def set_make_working_trees(self, new_value):
903
        """Set the policy flag for making working trees when creating branches.
904
905
        This only applies to branches that use this repository.
906
907
        The default is 'True'.
908
        :param new_value: True to restore the default, False to disable making
909
                          working trees.
910
        """
911
        raise NotImplementedError(self.set_make_working_trees)
912
    
913
    def make_working_trees(self):
914
        """Returns the policy for making working trees on new branches."""
915
        return True
916
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
917
1185.82.84 by Aaron Bentley
Moved stuff around
918
def install_revision(repository, rev, revision_tree):
919
    """Install all revision data into a repository."""
920
    present_parents = []
921
    parent_trees = {}
922
    for p_id in rev.parent_ids:
923
        if repository.has_revision(p_id):
924
            present_parents.append(p_id)
925
            parent_trees[p_id] = repository.revision_tree(p_id)
926
        else:
1852.5.1 by Robert Collins
Deprecate EmptyTree in favour of using Repository.revision_tree.
927
            parent_trees[p_id] = repository.revision_tree(None)
1185.82.84 by Aaron Bentley
Moved stuff around
928
929
    inv = revision_tree.inventory
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
930
    entries = inv.iter_entries()
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
931
    # backwards compatability hack: skip the root id.
1910.2.63 by Aaron Bentley
Add supports_rich_root member to repository
932
    if not repository.supports_rich_root():
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
933
        path, root = entries.next()
934
        if root.revision != rev.revision_id:
1910.2.63 by Aaron Bentley
Add supports_rich_root member to repository
935
            raise errors.IncompatibleRevision(repr(repository))
1185.82.84 by Aaron Bentley
Moved stuff around
936
    # Add the texts that are not already present
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
937
    for path, ie in entries:
1185.82.84 by Aaron Bentley
Moved stuff around
938
        w = repository.weave_store.get_weave_or_empty(ie.file_id,
939
                repository.get_transaction())
940
        if ie.revision not in w:
941
            text_parents = []
1740.2.2 by Aaron Bentley
Add test for the basis inventory automatically adding the revision id.
942
            # FIXME: TODO: The following loop *may* be overlapping/duplicate
1759.2.1 by Jelmer Vernooij
Fix some types (found using aspell).
943
            # with InventoryEntry.find_previous_heads(). if it is, then there
1740.2.2 by Aaron Bentley
Add test for the basis inventory automatically adding the revision id.
944
            # is a latent bug here where the parents may have ancestors of each
945
            # other. RBC, AB
1185.82.84 by Aaron Bentley
Moved stuff around
946
            for revision, tree in parent_trees.iteritems():
947
                if ie.file_id not in tree:
948
                    continue
949
                parent_id = tree.inventory[ie.file_id].revision
950
                if parent_id in text_parents:
951
                    continue
952
                text_parents.append(parent_id)
953
                    
954
            vfile = repository.weave_store.get_weave_or_empty(ie.file_id, 
955
                repository.get_transaction())
956
            lines = revision_tree.get_file(ie.file_id).readlines()
957
            vfile.add_lines(rev.revision_id, text_parents, lines)
958
    try:
959
        # install the inventory
960
        repository.add_inventory(rev.revision_id, inv, present_parents)
961
    except errors.RevisionAlreadyPresent:
962
        pass
963
    repository.add_revision(rev.revision_id, rev, inv)
964
965
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
966
class MetaDirRepository(Repository):
967
    """Repositories in the new meta-dir layout."""
968
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
969
    def __init__(self, _format, a_bzrdir, control_files, _revision_store, control_store, text_store):
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
970
        super(MetaDirRepository, self).__init__(_format,
971
                                                a_bzrdir,
972
                                                control_files,
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
973
                                                _revision_store,
1563.2.23 by Robert Collins
Add add_revision and get_revision methods to RevisionStore
974
                                                control_store,
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
975
                                                text_store)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
976
        dir_mode = self.control_files._dir_mode
977
        file_mode = self.control_files._file_mode
978
1596.2.12 by Robert Collins
Merge and make Knit Repository use the revision store for all possible queries.
979
    @needs_read_lock
980
    def is_shared(self):
981
        """Return True if this repository is flagged as a shared repository."""
982
        return self.control_files._transport.has('shared-storage')
983
984
    @needs_write_lock
985
    def set_make_working_trees(self, new_value):
986
        """Set the policy flag for making working trees when creating branches.
987
988
        This only applies to branches that use this repository.
989
990
        The default is 'True'.
991
        :param new_value: True to restore the default, False to disable making
992
                          working trees.
993
        """
994
        if new_value:
995
            try:
996
                self.control_files._transport.delete('no-working-trees')
997
            except errors.NoSuchFile:
998
                pass
999
        else:
1000
            self.control_files.put_utf8('no-working-trees', '')
1001
    
1002
    def make_working_trees(self):
1003
        """Returns the policy for making working trees on new branches."""
1004
        return not self.control_files._transport.has('no-working-trees')
1005
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1006
2150.2.2 by Robert Collins
Change the commit builder selected-revision-id test to use a unicode revision id where possible, leading to stricter testing of the hypothetical unicode revision id support in bzr.
1007
class WeaveMetaDirRepository(MetaDirRepository):
1008
    """A subclass of MetaDirRepository to set weave specific policy."""
1009
1010
    def get_commit_builder(self, branch, parents, config, timestamp=None,
1011
                           timezone=None, committer=None, revprops=None,
1012
                           revision_id=None):
1013
        self._check_ascii_revisionid(revision_id, self.get_commit_builder)
1014
        return MetaDirRepository.get_commit_builder(self, branch, parents,
1015
            config, timestamp, timezone, committer, revprops, revision_id)
1016
1017
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
1018
class KnitRepository(MetaDirRepository):
1019
    """Knit format repository."""
1020
1904.2.3 by Martin Pool
Give a warning on access to old repository formats
1021
    def _warn_if_deprecated(self):
1022
        # This class isn't deprecated
1023
        pass
1024
1740.3.6 by Jelmer Vernooij
Move inventory writing to the commit builder.
1025
    def _inventory_add_lines(self, inv_vf, revid, parents, lines):
1026
        inv_vf.add_lines_with_ghosts(revid, parents, lines)
1027
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
1028
    @needs_read_lock
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
1029
    def _all_revision_ids(self):
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
1030
        """See Repository.all_revision_ids()."""
1732.2.4 by Martin Pool
Split check into Branch.check and Repository.check
1031
        # Knits get the revision graph from the index of the revision knit, so
1032
        # it's always possible even if they're on an unlistable transport.
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
1033
        return self._revision_store.all_revision_ids(self.get_transaction())
1034
1732.2.6 by Martin Pool
Restore removed fileid_involved* methods
1035
    def fileid_involved_between_revs(self, from_revid, to_revid):
1036
        """Find file_id(s) which are involved in the changes between revisions.
1037
1038
        This determines the set of revisions which are involved, and then
1039
        finds all file ids affected by those revisions.
1040
        """
1041
        vf = self._get_revision_vf()
1042
        from_set = set(vf.get_ancestry(from_revid))
1043
        to_set = set(vf.get_ancestry(to_revid))
1044
        changed = to_set.difference(from_set)
1045
        return self._fileid_involved_by_set(changed)
1046
1047
    def fileid_involved(self, last_revid=None):
1048
        """Find all file_ids modified in the ancestry of last_revid.
1049
1050
        :param last_revid: If None, last_revision() will be used.
1051
        """
1052
        if not last_revid:
1053
            changed = set(self.all_revision_ids())
1054
        else:
1055
            changed = set(self.get_ancestry(last_revid))
1056
        if None in changed:
1057
            changed.remove(None)
1058
        return self._fileid_involved_by_set(changed)
1059
1594.2.7 by Robert Collins
Add versionedfile.fix_parents api for correcting data post hoc.
1060
    @needs_read_lock
1061
    def get_ancestry(self, revision_id):
1062
        """Return a list of revision-ids integrated by a revision.
1063
        
1064
        This is topologically sorted.
1065
        """
1066
        if revision_id is None:
1067
            return [None]
1596.2.12 by Robert Collins
Merge and make Knit Repository use the revision store for all possible queries.
1068
        vf = self._get_revision_vf()
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
1069
        try:
1070
            return [None] + vf.get_ancestry(revision_id)
1071
        except errors.RevisionNotPresent:
1072
            raise errors.NoSuchRevision(self, revision_id)
1073
1074
    @needs_read_lock
1594.2.10 by Robert Collins
Teach knit fetching and branching to only duplicate relevant data avoiding unnecessary reconciles.
1075
    def get_revision(self, revision_id):
1076
        """Return the Revision object for a named revision"""
1077
        return self.get_revision_reconcile(revision_id)
1078
1079
    @needs_read_lock
1596.2.12 by Robert Collins
Merge and make Knit Repository use the revision store for all possible queries.
1080
    def get_revision_graph(self, revision_id=None):
1081
        """Return a dictionary containing the revision graph.
1836.3.1 by Robert Collins
(robertc) Teach repository.get_revision_graph, and revision.common_ancestor, about NULL_REVISION.
1082
1083
        :param revision_id: The revision_id to get a graph from. If None, then
1084
        the entire revision graph is returned. This is a deprecated mode of
1085
        operation and will be removed in the future.
1596.2.12 by Robert Collins
Merge and make Knit Repository use the revision store for all possible queries.
1086
        :return: a dictionary of revision_id->revision_parents_list.
1087
        """
1836.3.1 by Robert Collins
(robertc) Teach repository.get_revision_graph, and revision.common_ancestor, about NULL_REVISION.
1088
        # special case NULL_REVISION
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
1089
        if revision_id == _mod_revision.NULL_REVISION:
1836.3.1 by Robert Collins
(robertc) Teach repository.get_revision_graph, and revision.common_ancestor, about NULL_REVISION.
1090
            return {}
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
1091
        a_weave = self._get_revision_vf()
1092
        entire_graph = a_weave.get_graph()
1596.2.12 by Robert Collins
Merge and make Knit Repository use the revision store for all possible queries.
1093
        if revision_id is None:
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
1094
            return a_weave.get_graph()
1095
        elif revision_id not in a_weave:
1596.2.12 by Robert Collins
Merge and make Knit Repository use the revision store for all possible queries.
1096
            raise errors.NoSuchRevision(self, revision_id)
1097
        else:
1098
            # add what can be reached from revision_id
1099
            result = {}
1100
            pending = set([revision_id])
1101
            while len(pending) > 0:
1102
                node = pending.pop()
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
1103
                result[node] = a_weave.get_parents(node)
1596.2.12 by Robert Collins
Merge and make Knit Repository use the revision store for all possible queries.
1104
                for revision_id in result[node]:
1105
                    if revision_id not in result:
1106
                        pending.add(revision_id)
1107
            return result
1108
1109
    @needs_read_lock
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
1110
    def get_revision_graph_with_ghosts(self, revision_ids=None):
1111
        """Return a graph of the revisions with ghosts marked as applicable.
1112
1113
        :param revision_ids: an iterable of revisions to graph or None for all.
1114
        :return: a Graph object with the graph reachable from revision_ids.
1115
        """
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
1116
        result = graph.Graph()
1596.2.12 by Robert Collins
Merge and make Knit Repository use the revision store for all possible queries.
1117
        vf = self._get_revision_vf()
1628.1.7 by Robert Collins
Tune get_revision_graph_with_ghosts for Knit repositories.
1118
        versions = set(vf.versions())
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
1119
        if not revision_ids:
1773.4.2 by Martin Pool
Cleanup of imports; undeprecate all_revision_ids()
1120
            pending = set(self.all_revision_ids())
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
1121
            required = set([])
1122
        else:
1123
            pending = set(revision_ids)
1836.3.1 by Robert Collins
(robertc) Teach repository.get_revision_graph, and revision.common_ancestor, about NULL_REVISION.
1124
            # special case NULL_REVISION
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
1125
            if _mod_revision.NULL_REVISION in pending:
1126
                pending.remove(_mod_revision.NULL_REVISION)
1836.3.1 by Robert Collins
(robertc) Teach repository.get_revision_graph, and revision.common_ancestor, about NULL_REVISION.
1127
            required = set(pending)
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
1128
        done = set([])
1129
        while len(pending):
1130
            revision_id = pending.pop()
1131
            if not revision_id in versions:
1132
                if revision_id in required:
1133
                    raise errors.NoSuchRevision(self, revision_id)
1134
                # a ghost
1135
                result.add_ghost(revision_id)
1759.2.2 by Jelmer Vernooij
Revert some of my spelling fixes and fix some typos after review by Aaron.
1136
                # mark it as done so we don't try for it again.
1628.1.7 by Robert Collins
Tune get_revision_graph_with_ghosts for Knit repositories.
1137
                done.add(revision_id)
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
1138
                continue
1139
            parent_ids = vf.get_parents_with_ghosts(revision_id)
1140
            for parent_id in parent_ids:
1141
                # is this queued or done ?
1142
                if (parent_id not in pending and
1143
                    parent_id not in done):
1144
                    # no, queue it.
1145
                    pending.add(parent_id)
1146
            result.add_node(revision_id, parent_ids)
1628.1.7 by Robert Collins
Tune get_revision_graph_with_ghosts for Knit repositories.
1147
            done.add(revision_id)
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
1148
        return result
1594.2.7 by Robert Collins
Add versionedfile.fix_parents api for correcting data post hoc.
1149
1596.2.12 by Robert Collins
Merge and make Knit Repository use the revision store for all possible queries.
1150
    def _get_revision_vf(self):
1607.1.2 by Robert Collins
Merge in knit-using-revision-versioned-file-graph tuning work.
1151
        """:return: a versioned file containing the revisions."""
1596.2.12 by Robert Collins
Merge and make Knit Repository use the revision store for all possible queries.
1152
        vf = self._revision_store.get_revision_file(self.get_transaction())
1153
        return vf
1154
1594.2.7 by Robert Collins
Add versionedfile.fix_parents api for correcting data post hoc.
1155
    @needs_write_lock
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
1156
    def reconcile(self, other=None, thorough=False):
1594.2.7 by Robert Collins
Add versionedfile.fix_parents api for correcting data post hoc.
1157
        """Reconcile this repository."""
1158
        from bzrlib.reconcile import KnitReconciler
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
1159
        reconciler = KnitReconciler(self, thorough=thorough)
1594.2.7 by Robert Collins
Add versionedfile.fix_parents api for correcting data post hoc.
1160
        reconciler.reconcile()
1161
        return reconciler
1162
    
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
1163
    def revision_parents(self, revision_id):
1164
        return self._get_revision_vf().get_parents(revision_id)
1165
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
1166
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
1167
class KnitRepository2(KnitRepository):
1168
    """"""
1910.2.48 by Aaron Bentley
Update from review comments
1169
    def __init__(self, _format, a_bzrdir, control_files, _revision_store,
1170
                 control_store, text_store):
1171
        KnitRepository.__init__(self, _format, a_bzrdir, control_files,
1172
                              _revision_store, control_store, text_store)
1173
        self._serializer = xml6.serializer_v6
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
1174
1175
    def deserialise_inventory(self, revision_id, xml):
1176
        """Transform the xml into an inventory object. 
1177
1178
        :param revision_id: The expected revision id of the inventory.
1179
        :param xml: A serialised inventory.
1180
        """
1910.2.48 by Aaron Bentley
Update from review comments
1181
        result = self._serializer.read_inventory_from_string(xml)
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
1182
        assert result.root.revision is not None
1183
        return result
1184
1185
    def serialise_inventory(self, inv):
1186
        """Transform the inventory object into XML text.
1187
1188
        :param revision_id: The expected revision id of the inventory.
1189
        :param xml: A serialised inventory.
1190
        """
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
1191
        assert inv.revision_id is not None
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
1192
        assert inv.root.revision is not None
1910.2.48 by Aaron Bentley
Update from review comments
1193
        return KnitRepository.serialise_inventory(self, inv)
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
1194
1195
    def get_commit_builder(self, branch, parents, config, timestamp=None, 
1196
                           timezone=None, committer=None, revprops=None, 
1197
                           revision_id=None):
1198
        """Obtain a CommitBuilder for this repository.
1199
        
1200
        :param branch: Branch to commit to.
1201
        :param parents: Revision ids of the parents of the new revision.
1202
        :param config: Configuration to use.
1203
        :param timestamp: Optional timestamp recorded for commit.
1204
        :param timezone: Optional timezone for timestamp.
1205
        :param committer: Optional committer to set for commit.
1206
        :param revprops: Optional dictionary of revision properties.
1207
        :param revision_id: Optional revision id.
1208
        """
1209
        return RootCommitBuilder(self, parents, config, timestamp, timezone,
1210
                                 committer, revprops, revision_id)
1211
1910.2.46 by Aaron Bentley
Whitespace fix
1212
2241.1.2 by Martin Pool
change to using external Repository format registry
1213
class RepositoryFormatRegistry(registry.Registry):
1214
    """Registry of RepositoryFormats.
1215
    """
1216
    
1217
1218
format_registry = RepositoryFormatRegistry()
1219
"""Registry of formats, indexed by their identifying format string."""
1220
1221
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1222
class RepositoryFormat(object):
1223
    """A repository format.
1224
1225
    Formats provide three things:
1226
     * An initialization routine to construct repository data on disk.
1227
     * a format string which is used when the BzrDir supports versioned
1228
       children.
1229
     * an open routine which returns a Repository instance.
1230
1231
    Formats are placed in an dict by their format string for reference 
1232
    during opening. These should be subclasses of RepositoryFormat
1233
    for consistency.
1234
1235
    Once a format is deprecated, just deprecate the initialize and open
1236
    methods on the format class. Do not deprecate the object, as the 
1237
    object will be created every system load.
1238
1239
    Common instance attributes:
1240
    _matchingbzrdir - the bzrdir format that the repository format was
1241
    originally written to work with. This can be used if manually
1242
    constructing a bzrdir and repository, or more commonly for test suite
1243
    parameterisation.
1244
    """
1245
1904.2.3 by Martin Pool
Give a warning on access to old repository formats
1246
    def __str__(self):
1247
        return "<%s>" % self.__class__.__name__
1248
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1249
    @classmethod
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
1250
    def find_format(klass, a_bzrdir):
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
1251
        """Return the format for the repository object in a_bzrdir.
1252
        
1253
        This is used by bzr native formats that have a "format" file in
1254
        the repository.  Other methods may be used by different types of 
1255
        control directory.
1256
        """
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
1257
        try:
1258
            transport = a_bzrdir.get_repository_transport(None)
1259
            format_string = transport.get("format").read()
2241.1.2 by Martin Pool
change to using external Repository format registry
1260
            return format_registry.get(format_string)
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
1261
        except errors.NoSuchFile:
1262
            raise errors.NoRepositoryPresent(a_bzrdir)
1263
        except KeyError:
1740.5.6 by Martin Pool
Clean up many exception classes.
1264
            raise errors.UnknownFormatError(format=format_string)
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
1265
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
1266
    @classmethod
2241.1.2 by Martin Pool
change to using external Repository format registry
1267
    def register_format(klass, format):
1268
        format_registry.register(format.get_format_string(), format)
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
1269
1270
    @classmethod
1271
    def unregister_format(klass, format):
2241.1.2 by Martin Pool
change to using external Repository format registry
1272
        format_registry.remove(format.get_format_string())
1563.2.23 by Robert Collins
Add add_revision and get_revision methods to RevisionStore
1273
    
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
1274
    @classmethod
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1275
    def get_default_format(klass):
1276
        """Return the current default format."""
2204.5.3 by Aaron Bentley
zap old repository default handling
1277
        from bzrlib import bzrdir
1278
        return bzrdir.format_registry.make_bzrdir('default').repository_format
2241.1.1 by Martin Pool
Change RepositoryFormat to use a Registry rather than ad-hoc dictionary
1279
1280
    def _get_control_store(self, repo_transport, control_files):
1281
        """Return the control store for this repository."""
1282
        raise NotImplementedError(self._get_control_store)
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1283
1284
    def get_format_string(self):
1285
        """Return the ASCII format string that identifies this format.
1286
        
1287
        Note that in pre format ?? repositories the format string is 
1288
        not permitted nor written to disk.
1289
        """
1290
        raise NotImplementedError(self.get_format_string)
1291
1624.3.19 by Olaf Conradi
New call get_format_description to give a user-friendly description of a
1292
    def get_format_description(self):
1759.2.1 by Jelmer Vernooij
Fix some types (found using aspell).
1293
        """Return the short description for this format."""
1624.3.19 by Olaf Conradi
New call get_format_description to give a user-friendly description of a
1294
        raise NotImplementedError(self.get_format_description)
1295
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1296
    def _get_revision_store(self, repo_transport, control_files):
1297
        """Return the revision store object for this a_bzrdir."""
1556.1.5 by Robert Collins
Review feedback.
1298
        raise NotImplementedError(self._get_revision_store)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1299
1563.2.22 by Robert Collins
Move responsibility for repository.has_revision into RevisionStore
1300
    def _get_text_rev_store(self,
1301
                            transport,
1302
                            control_files,
1303
                            name,
1304
                            compressed=True,
1563.2.28 by Robert Collins
Add total_size to the revision_store api.
1305
                            prefixed=False,
1306
                            serializer=None):
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1307
        """Common logic for getting a revision store for a repository.
1308
        
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
1309
        see self._get_revision_store for the subclass-overridable method to 
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1310
        get the store for a repository.
1311
        """
1563.2.22 by Robert Collins
Move responsibility for repository.has_revision into RevisionStore
1312
        from bzrlib.store.revision.text import TextRevisionStore
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1313
        dir_mode = control_files._dir_mode
1314
        file_mode = control_files._file_mode
1563.2.22 by Robert Collins
Move responsibility for repository.has_revision into RevisionStore
1315
        text_store =TextStore(transport.clone(name),
1316
                              prefixed=prefixed,
1317
                              compressed=compressed,
1318
                              dir_mode=dir_mode,
1319
                              file_mode=file_mode)
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
1320
        _revision_store = TextRevisionStore(text_store, serializer)
1321
        return _revision_store
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1322
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
1323
    def _get_versioned_file_store(self,
1324
                                  name,
1325
                                  transport,
1326
                                  control_files,
1327
                                  prefixed=True,
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
1328
                                  versionedfile_class=weave.WeaveFile,
1946.2.5 by John Arbash Meinel
Make knit stores delay creation, but not control stores
1329
                                  versionedfile_kwargs={},
1608.2.12 by Martin Pool
Store-escaping must quote uppercase characters too, so that they're safely
1330
                                  escaped=False):
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
1331
        weave_transport = control_files._transport.clone(name)
1332
        dir_mode = control_files._dir_mode
1333
        file_mode = control_files._file_mode
1334
        return VersionedFileStore(weave_transport, prefixed=prefixed,
1608.2.12 by Martin Pool
Store-escaping must quote uppercase characters too, so that they're safely
1335
                                  dir_mode=dir_mode,
1336
                                  file_mode=file_mode,
1337
                                  versionedfile_class=versionedfile_class,
1946.2.5 by John Arbash Meinel
Make knit stores delay creation, but not control stores
1338
                                  versionedfile_kwargs=versionedfile_kwargs,
1608.2.12 by Martin Pool
Store-escaping must quote uppercase characters too, so that they're safely
1339
                                  escaped=escaped)
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
1340
1534.6.1 by Robert Collins
allow API creation of shared repositories
1341
    def initialize(self, a_bzrdir, shared=False):
1342
        """Initialize a repository of this format in a_bzrdir.
1343
1344
        :param a_bzrdir: The bzrdir to put the new repository in it.
1345
        :param shared: The repository should be initialized as a sharable one.
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
1346
        :returns: The new repository object.
1347
        
1534.6.1 by Robert Collins
allow API creation of shared repositories
1348
        This may raise UninitializableFormat if shared repository are not
1349
        compatible the a_bzrdir.
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1350
        """
1752.2.52 by Andrew Bennetts
Flesh out more Remote* methods needed to open and initialise remote branches/trees/repositories.
1351
        raise NotImplementedError(self.initialize)
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1352
1353
    def is_supported(self):
1354
        """Is this format supported?
1355
1356
        Supported formats must be initializable and openable.
1357
        Unsupported formats may not support initialization or committing or 
1358
        some other features depending on the reason for not being supported.
1359
        """
1360
        return True
1361
1910.2.12 by Aaron Bentley
Implement knit repo format 2
1362
    def check_conversion_target(self, target_format):
1363
        raise NotImplementedError(self.check_conversion_target)
1364
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1365
    def open(self, a_bzrdir, _found=False):
1366
        """Return an instance of this format for the bzrdir a_bzrdir.
1367
        
1368
        _found is a private parameter, do not use it.
1369
        """
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1370
        raise NotImplementedError(self.open)
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1371
1372
1534.6.1 by Robert Collins
allow API creation of shared repositories
1373
class PreSplitOutRepositoryFormat(RepositoryFormat):
1374
    """Base class for the pre split out repository formats."""
1375
1910.2.14 by Aaron Bentley
Fail when trying to use interrepository on Knit2 and Knit1
1376
    rich_root_data = False
1377
1534.6.1 by Robert Collins
allow API creation of shared repositories
1378
    def initialize(self, a_bzrdir, shared=False, _internal=False):
1379
        """Create a weave repository.
1380
        
1381
        TODO: when creating split out bzr branch formats, move this to a common
1382
        base for Format5, Format6. or something like that.
1383
        """
1384
        if shared:
1385
            raise errors.IncompatibleFormat(self, a_bzrdir._format)
1386
1387
        if not _internal:
1388
            # always initialized when the bzrdir is.
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1389
            return self.open(a_bzrdir, _found=True)
1534.6.1 by Robert Collins
allow API creation of shared repositories
1390
        
1391
        # Create an empty weave
1392
        sio = StringIO()
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
1393
        weavefile.write_weave_v5(weave.Weave(), sio)
1534.6.1 by Robert Collins
allow API creation of shared repositories
1394
        empty_weave = sio.getvalue()
1395
1396
        mutter('creating repository in %s.', a_bzrdir.transport.base)
1397
        dirs = ['revision-store', 'weaves']
1553.5.56 by Martin Pool
Format 7 repo now uses LockDir!
1398
        files = [('inventory.weave', StringIO(empty_weave)),
1534.6.1 by Robert Collins
allow API creation of shared repositories
1399
                 ]
1400
        
1759.2.2 by Jelmer Vernooij
Revert some of my spelling fixes and fix some typos after review by Aaron.
1401
        # FIXME: RBC 20060125 don't peek under the covers
1534.6.1 by Robert Collins
allow API creation of shared repositories
1402
        # NB: no need to escape relative paths that are url safe.
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
1403
        control_files = lockable_files.LockableFiles(a_bzrdir.transport,
1404
                                'branch-lock', lockable_files.TransportLock)
1553.5.63 by Martin Pool
Lock type is now mandatory for LockableFiles constructor
1405
        control_files.create_lock()
1534.6.1 by Robert Collins
allow API creation of shared repositories
1406
        control_files.lock_write()
1407
        control_files._transport.mkdir_multi(dirs,
1408
                mode=control_files._dir_mode)
1409
        try:
1410
            for file, content in files:
1411
                control_files.put(file, content)
1412
        finally:
1413
            control_files.unlock()
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1414
        return self.open(a_bzrdir, _found=True)
1415
1563.2.23 by Robert Collins
Add add_revision and get_revision methods to RevisionStore
1416
    def _get_control_store(self, repo_transport, control_files):
1417
        """Return the control store for this repository."""
1418
        return self._get_versioned_file_store('',
1419
                                              repo_transport,
1420
                                              control_files,
1421
                                              prefixed=False)
1422
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
1423
    def _get_text_store(self, transport, control_files):
1424
        """Get a store for file texts for this format."""
1425
        raise NotImplementedError(self._get_text_store)
1426
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1427
    def open(self, a_bzrdir, _found=False):
1428
        """See RepositoryFormat.open()."""
1429
        if not _found:
1430
            # we are being called directly and must probe.
1431
            raise NotImplementedError
1432
1433
        repo_transport = a_bzrdir.get_repository_transport(None)
1434
        control_files = a_bzrdir._control_files
1563.2.23 by Robert Collins
Add add_revision and get_revision methods to RevisionStore
1435
        text_store = self._get_text_store(repo_transport, control_files)
1436
        control_store = self._get_control_store(repo_transport, control_files)
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
1437
        _revision_store = self._get_revision_store(repo_transport, control_files)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1438
        return AllInOneRepository(_format=self,
1439
                                  a_bzrdir=a_bzrdir,
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
1440
                                  _revision_store=_revision_store,
1563.2.23 by Robert Collins
Add add_revision and get_revision methods to RevisionStore
1441
                                  control_store=control_store,
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
1442
                                  text_store=text_store)
1534.6.1 by Robert Collins
allow API creation of shared repositories
1443
1910.2.12 by Aaron Bentley
Implement knit repo format 2
1444
    def check_conversion_target(self, target_format):
1445
        pass
1446
1534.6.1 by Robert Collins
allow API creation of shared repositories
1447
1448
class RepositoryFormat4(PreSplitOutRepositoryFormat):
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1449
    """Bzr repository format 4.
1450
1451
    This repository format has:
1452
     - flat stores
1453
     - TextStores for texts, inventories,revisions.
1454
1455
    This format is deprecated: it indexes texts using a text id which is
1759.2.1 by Jelmer Vernooij
Fix some types (found using aspell).
1456
    removed in format 5; initialization and write support for this format
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1457
    has been removed.
1458
    """
1459
1460
    def __init__(self):
1461
        super(RepositoryFormat4, self).__init__()
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
1462
        self._matchingbzrdir = bzrdir.BzrDirFormat4()
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1463
1624.3.19 by Olaf Conradi
New call get_format_description to give a user-friendly description of a
1464
    def get_format_description(self):
1465
        """See RepositoryFormat.get_format_description()."""
1466
        return "Repository format 4"
1467
1534.6.1 by Robert Collins
allow API creation of shared repositories
1468
    def initialize(self, url, shared=False, _internal=False):
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1469
        """Format 4 branches cannot be created."""
1470
        raise errors.UninitializableFormat(self)
1471
1472
    def is_supported(self):
1473
        """Format 4 is not supported.
1474
1475
        It is not supported because the model changed from 4 to 5 and the
1476
        conversion logic is expensive - so doing it on the fly was not 
1477
        feasible.
1478
        """
1479
        return False
1480
1563.2.23 by Robert Collins
Add add_revision and get_revision methods to RevisionStore
1481
    def _get_control_store(self, repo_transport, control_files):
1482
        """Format 4 repositories have no formal control store at this point.
1483
        
1484
        This will cause any control-file-needing apis to fail - this is desired.
1485
        """
1486
        return None
1487
    
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1488
    def _get_revision_store(self, repo_transport, control_files):
1489
        """See RepositoryFormat._get_revision_store()."""
1563.2.28 by Robert Collins
Add total_size to the revision_store api.
1490
        from bzrlib.xml4 import serializer_v4
1563.2.22 by Robert Collins
Move responsibility for repository.has_revision into RevisionStore
1491
        return self._get_text_rev_store(repo_transport,
1492
                                        control_files,
1563.2.28 by Robert Collins
Add total_size to the revision_store api.
1493
                                        'revision-store',
1494
                                        serializer=serializer_v4)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1495
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
1496
    def _get_text_store(self, transport, control_files):
1497
        """See RepositoryFormat._get_text_store()."""
1498
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1499
1534.6.1 by Robert Collins
allow API creation of shared repositories
1500
class RepositoryFormat5(PreSplitOutRepositoryFormat):
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1501
    """Bzr control format 5.
1502
1503
    This repository format has:
1504
     - weaves for file texts and inventory
1505
     - flat stores
1506
     - TextStores for revisions and signatures.
1507
    """
1508
1509
    def __init__(self):
1510
        super(RepositoryFormat5, self).__init__()
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
1511
        self._matchingbzrdir = bzrdir.BzrDirFormat5()
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1512
1624.3.19 by Olaf Conradi
New call get_format_description to give a user-friendly description of a
1513
    def get_format_description(self):
1514
        """See RepositoryFormat.get_format_description()."""
1515
        return "Weave repository format 5"
1516
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1517
    def _get_revision_store(self, repo_transport, control_files):
1518
        """See RepositoryFormat._get_revision_store()."""
1519
        """Return the revision store object for this a_bzrdir."""
1563.2.22 by Robert Collins
Move responsibility for repository.has_revision into RevisionStore
1520
        return self._get_text_rev_store(repo_transport,
1521
                                        control_files,
1522
                                        'revision-store',
1523
                                        compressed=False)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1524
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
1525
    def _get_text_store(self, transport, control_files):
1526
        """See RepositoryFormat._get_text_store()."""
1527
        return self._get_versioned_file_store('weaves', transport, control_files, prefixed=False)
1528
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1529
1534.6.1 by Robert Collins
allow API creation of shared repositories
1530
class RepositoryFormat6(PreSplitOutRepositoryFormat):
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1531
    """Bzr control format 6.
1532
1533
    This repository format has:
1534
     - weaves for file texts and inventory
1535
     - hash subdirectory based stores.
1536
     - TextStores for revisions and signatures.
1537
    """
1538
1539
    def __init__(self):
1540
        super(RepositoryFormat6, self).__init__()
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
1541
        self._matchingbzrdir = bzrdir.BzrDirFormat6()
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1542
1624.3.19 by Olaf Conradi
New call get_format_description to give a user-friendly description of a
1543
    def get_format_description(self):
1544
        """See RepositoryFormat.get_format_description()."""
1545
        return "Weave repository format 6"
1546
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1547
    def _get_revision_store(self, repo_transport, control_files):
1548
        """See RepositoryFormat._get_revision_store()."""
1563.2.22 by Robert Collins
Move responsibility for repository.has_revision into RevisionStore
1549
        return self._get_text_rev_store(repo_transport,
1550
                                        control_files,
1551
                                        'revision-store',
1552
                                        compressed=False,
1553
                                        prefixed=True)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1554
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
1555
    def _get_text_store(self, transport, control_files):
1556
        """See RepositoryFormat._get_text_store()."""
1557
        return self._get_versioned_file_store('weaves', transport, control_files)
1558
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1559
1560
class MetaDirRepositoryFormat(RepositoryFormat):
1759.2.1 by Jelmer Vernooij
Fix some types (found using aspell).
1561
    """Common base class for the new repositories using the metadir layout."""
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1562
1910.2.14 by Aaron Bentley
Fail when trying to use interrepository on Knit2 and Knit1
1563
    rich_root_data = False
1564
1556.1.4 by Robert Collins
Add a new format for what will become knit, and the surrounding logic to upgrade repositories within metadirs, and tests for the same.
1565
    def __init__(self):
1566
        super(MetaDirRepositoryFormat, self).__init__()
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
1567
        self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
1556.1.4 by Robert Collins
Add a new format for what will become knit, and the surrounding logic to upgrade repositories within metadirs, and tests for the same.
1568
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1569
    def _create_control_files(self, a_bzrdir):
1570
        """Create the required files and the initial control_files object."""
1759.2.2 by Jelmer Vernooij
Revert some of my spelling fixes and fix some typos after review by Aaron.
1571
        # FIXME: RBC 20060125 don't peek under the covers
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
1572
        # NB: no need to escape relative paths that are url safe.
1573
        repository_transport = a_bzrdir.get_repository_transport(self)
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
1574
        control_files = lockable_files.LockableFiles(repository_transport,
1575
                                'lock', lockdir.LockDir)
1553.5.61 by Martin Pool
Locks protecting LockableFiles must now be explicitly created before use.
1576
        control_files.create_lock()
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1577
        return control_files
1578
1579
    def _upload_blank_content(self, a_bzrdir, dirs, files, utf8_files, shared):
1580
        """Upload the initial blank content."""
1581
        control_files = self._create_control_files(a_bzrdir)
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
1582
        control_files.lock_write()
1583
        try:
1553.5.49 by Martin Pool
Use LockDirs for repo format 7
1584
            control_files._transport.mkdir_multi(dirs,
1585
                    mode=control_files._dir_mode)
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
1586
            for file, content in files:
1587
                control_files.put(file, content)
1588
            for file, content in utf8_files:
1589
                control_files.put_utf8(file, content)
1534.6.1 by Robert Collins
allow API creation of shared repositories
1590
            if shared == True:
1591
                control_files.put_utf8('shared-storage', '')
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
1592
        finally:
1593
            control_files.unlock()
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1594
1595
1596
class RepositoryFormat7(MetaDirRepositoryFormat):
1597
    """Bzr repository 7.
1598
1599
    This repository format has:
1600
     - weaves for file texts and inventory
1601
     - hash subdirectory based stores.
1602
     - TextStores for revisions and signatures.
1603
     - a format marker of its own
1604
     - an optional 'shared-storage' flag
1605
     - an optional 'no-working-trees' flag
1606
    """
1607
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
1608
    def _get_control_store(self, repo_transport, control_files):
1609
        """Return the control store for this repository."""
1610
        return self._get_versioned_file_store('',
1611
                                              repo_transport,
1612
                                              control_files,
1613
                                              prefixed=False)
1614
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1615
    def get_format_string(self):
1616
        """See RepositoryFormat.get_format_string()."""
1617
        return "Bazaar-NG Repository format 7"
1618
1624.3.19 by Olaf Conradi
New call get_format_description to give a user-friendly description of a
1619
    def get_format_description(self):
1620
        """See RepositoryFormat.get_format_description()."""
1621
        return "Weave repository format 7"
1622
1910.2.12 by Aaron Bentley
Implement knit repo format 2
1623
    def check_conversion_target(self, target_format):
1624
        pass
1625
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
1626
    def _get_revision_store(self, repo_transport, control_files):
1627
        """See RepositoryFormat._get_revision_store()."""
1628
        return self._get_text_rev_store(repo_transport,
1629
                                        control_files,
1630
                                        'revision-store',
1631
                                        compressed=False,
1632
                                        prefixed=True,
1633
                                        )
1634
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
1635
    def _get_text_store(self, transport, control_files):
1636
        """See RepositoryFormat._get_text_store()."""
1637
        return self._get_versioned_file_store('weaves',
1638
                                              transport,
1639
                                              control_files)
1640
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1641
    def initialize(self, a_bzrdir, shared=False):
1642
        """Create a weave repository.
1643
1644
        :param shared: If true the repository will be initialized as a shared
1645
                       repository.
1646
        """
1647
        # Create an empty weave
1648
        sio = StringIO()
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
1649
        weavefile.write_weave_v5(weave.Weave(), sio)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1650
        empty_weave = sio.getvalue()
1651
1652
        mutter('creating repository in %s.', a_bzrdir.transport.base)
1653
        dirs = ['revision-store', 'weaves']
1654
        files = [('inventory.weave', StringIO(empty_weave)), 
1655
                 ]
1656
        utf8_files = [('format', self.get_format_string())]
1657
 
1658
        self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
1659
        return self.open(a_bzrdir=a_bzrdir, _found=True)
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
1660
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
1661
    def open(self, a_bzrdir, _found=False, _override_transport=None):
1662
        """See RepositoryFormat.open().
1663
        
1664
        :param _override_transport: INTERNAL USE ONLY. Allows opening the
1665
                                    repository at a slightly different url
1666
                                    than normal. I.e. during 'upgrade'.
1667
        """
1668
        if not _found:
1669
            format = RepositoryFormat.find_format(a_bzrdir)
1670
            assert format.__class__ ==  self.__class__
1671
        if _override_transport is not None:
1672
            repo_transport = _override_transport
1673
        else:
1674
            repo_transport = a_bzrdir.get_repository_transport(None)
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
1675
        control_files = lockable_files.LockableFiles(repo_transport,
1676
                                'lock', lockdir.LockDir)
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
1677
        text_store = self._get_text_store(repo_transport, control_files)
1678
        control_store = self._get_control_store(repo_transport, control_files)
1679
        _revision_store = self._get_revision_store(repo_transport, control_files)
2150.2.2 by Robert Collins
Change the commit builder selected-revision-id test to use a unicode revision id where possible, leading to stricter testing of the hypothetical unicode revision id support in bzr.
1680
        return WeaveMetaDirRepository(_format=self,
1681
            a_bzrdir=a_bzrdir,
1682
            control_files=control_files,
1683
            _revision_store=_revision_store,
1684
            control_store=control_store,
1685
            text_store=text_store)
1563.2.29 by Robert Collins
Remove all but fetch references to repository.revision_store.
1686
1534.4.47 by Robert Collins
Split out repository into .bzr/repository
1687
1910.2.11 by Aaron Bentley
Start work on Knit format 2
1688
class RepositoryFormatKnit(MetaDirRepositoryFormat):
1689
    """Bzr repository knit format (generalized). 
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1690
1691
    This repository format has:
1692
     - knits for file texts and inventory
1693
     - hash subdirectory based stores.
1694
     - knits for revisions and signatures
1695
     - TextStores for revisions and signatures.
1696
     - a format marker of its own
1697
     - an optional 'shared-storage' flag
1698
     - an optional 'no-working-trees' flag
1553.5.62 by Martin Pool
Add tests that MetaDir repositories use LockDirs
1699
     - a LockDir lock
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1700
    """
1701
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
1702
    def _get_control_store(self, repo_transport, control_files):
1703
        """Return the control store for this repository."""
1628.1.5 by Robert Collins
Make inventory knits not annotated, only delta compressed.
1704
        return VersionedFileStore(
1705
            repo_transport,
1706
            prefixed=False,
1707
            file_mode=control_files._file_mode,
1996.3.5 by John Arbash Meinel
Cleanup, deprecated, and get the tests passing again.
1708
            versionedfile_class=knit.KnitVersionedFile,
1709
            versionedfile_kwargs={'factory':knit.KnitPlainFactory()},
1628.1.5 by Robert Collins
Make inventory knits not annotated, only delta compressed.
1710
            )
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
1711
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
1712
    def _get_revision_store(self, repo_transport, control_files):
1713
        """See RepositoryFormat._get_revision_store()."""
1714
        from bzrlib.store.revision.knit import KnitRevisionStore
1715
        versioned_file_store = VersionedFileStore(
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
1716
            repo_transport,
1651.1.1 by Martin Pool
[merge][wip] Storage escaping
1717
            file_mode=control_files._file_mode,
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
1718
            prefixed=False,
1563.2.34 by Robert Collins
Remove the commit and rollback transaction methods as misleading, and implement a WriteTransaction
1719
            precious=True,
1996.3.5 by John Arbash Meinel
Cleanup, deprecated, and get the tests passing again.
1720
            versionedfile_class=knit.KnitVersionedFile,
1721
            versionedfile_kwargs={'delta':False,
1722
                                  'factory':knit.KnitPlainFactory(),
1723
                                 },
1608.2.12 by Martin Pool
Store-escaping must quote uppercase characters too, so that they're safely
1724
            escaped=True,
1651.1.1 by Martin Pool
[merge][wip] Storage escaping
1725
            )
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
1726
        return KnitRevisionStore(versioned_file_store)
1727
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
1728
    def _get_text_store(self, transport, control_files):
1729
        """See RepositoryFormat._get_text_store()."""
1730
        return self._get_versioned_file_store('knits',
1996.3.5 by John Arbash Meinel
Cleanup, deprecated, and get the tests passing again.
1731
                                  transport,
1732
                                  control_files,
1733
                                  versionedfile_class=knit.KnitVersionedFile,
1734
                                  versionedfile_kwargs={
1735
                                      'create_parent_dir':True,
1736
                                      'delay_create':True,
1737
                                      'dir_mode':control_files._dir_mode,
1738
                                  },
1739
                                  escaped=True)
1563.2.17 by Robert Collins
Change knits repositories to use a knit versioned file store for file texts.
1740
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1741
    def initialize(self, a_bzrdir, shared=False):
1742
        """Create a knit format 1 repository.
1743
1658.1.7 by Martin Pool
(RepositoryFormatKnit1.initialize) remove dead code that constructs weaves
1744
        :param a_bzrdir: bzrdir to contain the new repository; must already
1745
            be initialized.
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1746
        :param shared: If true the repository will be initialized as a shared
1747
                       repository.
1748
        """
1749
        mutter('creating repository in %s.', a_bzrdir.transport.base)
1707.3.29 by John Arbash Meinel
reverting 1734
1750
        dirs = ['revision-store', 'knits']
1658.1.7 by Martin Pool
(RepositoryFormatKnit1.initialize) remove dead code that constructs weaves
1751
        files = []
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1752
        utf8_files = [('format', self.get_format_string())]
1753
        
1754
        self._upload_blank_content(a_bzrdir, dirs, files, utf8_files, shared)
1563.2.25 by Robert Collins
Merge in upstream.
1755
        repo_transport = a_bzrdir.get_repository_transport(None)
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
1756
        control_files = lockable_files.LockableFiles(repo_transport,
1757
                                'lock', lockdir.LockDir)
1563.2.25 by Robert Collins
Merge in upstream.
1758
        control_store = self._get_control_store(repo_transport, control_files)
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
1759
        transaction = transactions.WriteTransaction()
1563.2.34 by Robert Collins
Remove the commit and rollback transaction methods as misleading, and implement a WriteTransaction
1760
        # trigger a write of the inventory store.
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
1761
        control_store.get_weave_or_empty('inventory', transaction)
1762
        _revision_store = self._get_revision_store(repo_transport, control_files)
2150.2.2 by Robert Collins
Change the commit builder selected-revision-id test to use a unicode revision id where possible, leading to stricter testing of the hypothetical unicode revision id support in bzr.
1763
        # the revision id here is irrelevant: it will not be stored, and cannot
1764
        # already exist.
1563.2.35 by Robert Collins
cleanup deprecation warnings and finish conversion so the inventory is knit based too.
1765
        _revision_store.has_revision_id('A', transaction)
1766
        _revision_store.get_signature_file(transaction)
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1767
        return self.open(a_bzrdir=a_bzrdir, _found=True)
1768
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
1769
    def open(self, a_bzrdir, _found=False, _override_transport=None):
1770
        """See RepositoryFormat.open().
1771
        
1772
        :param _override_transport: INTERNAL USE ONLY. Allows opening the
1773
                                    repository at a slightly different url
1774
                                    than normal. I.e. during 'upgrade'.
1775
        """
1776
        if not _found:
1777
            format = RepositoryFormat.find_format(a_bzrdir)
1778
            assert format.__class__ ==  self.__class__
1779
        if _override_transport is not None:
1780
            repo_transport = _override_transport
1781
        else:
1782
            repo_transport = a_bzrdir.get_repository_transport(None)
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
1783
        control_files = lockable_files.LockableFiles(repo_transport,
1784
                                'lock', lockdir.LockDir)
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
1785
        text_store = self._get_text_store(repo_transport, control_files)
1786
        control_store = self._get_control_store(repo_transport, control_files)
1787
        _revision_store = self._get_revision_store(repo_transport, control_files)
1788
        return KnitRepository(_format=self,
1789
                              a_bzrdir=a_bzrdir,
1790
                              control_files=control_files,
1791
                              _revision_store=_revision_store,
1792
                              control_store=control_store,
1793
                              text_store=text_store)
1794
1910.2.12 by Aaron Bentley
Implement knit repo format 2
1795
1910.2.11 by Aaron Bentley
Start work on Knit format 2
1796
class RepositoryFormatKnit1(RepositoryFormatKnit):
1797
    """Bzr repository knit format 1.
1798
1799
    This repository format has:
1800
     - knits for file texts and inventory
1801
     - hash subdirectory based stores.
1802
     - knits for revisions and signatures
1803
     - TextStores for revisions and signatures.
1804
     - a format marker of its own
1805
     - an optional 'shared-storage' flag
1806
     - an optional 'no-working-trees' flag
1807
     - a LockDir lock
1808
1809
    This format was introduced in bzr 0.8.
1810
    """
1811
    def get_format_string(self):
1812
        """See RepositoryFormat.get_format_string()."""
1813
        return "Bazaar-NG Knit Repository Format 1"
1814
1815
    def get_format_description(self):
1816
        """See RepositoryFormat.get_format_description()."""
1817
        return "Knit repository format 1"
1556.1.3 by Robert Collins
Rearrangment of Repository logic to be less type code driven, and bugfix InterRepository.missing_revision_ids
1818
1910.2.12 by Aaron Bentley
Implement knit repo format 2
1819
    def check_conversion_target(self, target_format):
1820
        pass
1821
1822
1823
class RepositoryFormatKnit2(RepositoryFormatKnit):
1824
    """Bzr repository knit format 2.
1825
1826
    THIS FORMAT IS EXPERIMENTAL
1827
    This repository format has:
1828
     - knits for file texts and inventory
1829
     - hash subdirectory based stores.
1830
     - knits for revisions and signatures
1831
     - TextStores for revisions and signatures.
1832
     - a format marker of its own
1833
     - an optional 'shared-storage' flag
1834
     - an optional 'no-working-trees' flag
1835
     - a LockDir lock
1836
     - Support for recording full info about the tree root
1837
1838
    """
1910.2.14 by Aaron Bentley
Fail when trying to use interrepository on Knit2 and Knit1
1839
    
1840
    rich_root_data = True
1841
1910.2.12 by Aaron Bentley
Implement knit repo format 2
1842
    def get_format_string(self):
1843
        """See RepositoryFormat.get_format_string()."""
1910.2.48 by Aaron Bentley
Update from review comments
1844
        return "Bazaar Knit Repository Format 2\n"
1910.2.12 by Aaron Bentley
Implement knit repo format 2
1845
1846
    def get_format_description(self):
1847
        """See RepositoryFormat.get_format_description()."""
1848
        return "Knit repository format 2"
1849
1850
    def check_conversion_target(self, target_format):
1910.2.14 by Aaron Bentley
Fail when trying to use interrepository on Knit2 and Knit1
1851
        if not target_format.rich_root_data:
1910.2.12 by Aaron Bentley
Implement knit repo format 2
1852
            raise errors.BadConversionTarget(
1853
                'Does not support rich root data.', target_format)
1854
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
1855
    def open(self, a_bzrdir, _found=False, _override_transport=None):
1856
        """See RepositoryFormat.open().
1857
        
1858
        :param _override_transport: INTERNAL USE ONLY. Allows opening the
1859
                                    repository at a slightly different url
1860
                                    than normal. I.e. during 'upgrade'.
1861
        """
1862
        if not _found:
1863
            format = RepositoryFormat.find_format(a_bzrdir)
1864
            assert format.__class__ ==  self.__class__
1865
        if _override_transport is not None:
1866
            repo_transport = _override_transport
1867
        else:
1868
            repo_transport = a_bzrdir.get_repository_transport(None)
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
1869
        control_files = lockable_files.LockableFiles(repo_transport, 'lock',
1870
                                                     lockdir.LockDir)
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
1871
        text_store = self._get_text_store(repo_transport, control_files)
1872
        control_store = self._get_control_store(repo_transport, control_files)
1873
        _revision_store = self._get_revision_store(repo_transport, control_files)
1874
        return KnitRepository2(_format=self,
1875
                               a_bzrdir=a_bzrdir,
1876
                               control_files=control_files,
1877
                               _revision_store=_revision_store,
1878
                               control_store=control_store,
1879
                               text_store=text_store)
1880
1881
1910.2.12 by Aaron Bentley
Implement knit repo format 2
1882
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1883
# formats which have no format string are not discoverable
1884
# and not independently creatable, so are not registered.
1666.1.6 by Robert Collins
Make knit the default format.
1885
RepositoryFormat.register_format(RepositoryFormat7())
2204.4.6 by Aaron Bentley
Fix default to work with RepositoryFormat.set_default_format
1886
# KEEP in sync with bzrdir.format_registry default
2204.5.3 by Aaron Bentley
zap old repository default handling
1887
RepositoryFormat.register_format(RepositoryFormatKnit1())
1910.2.42 by Aaron Bentley
Restore RepositoryFormatKnit1 as the default
1888
RepositoryFormat.register_format(RepositoryFormatKnit2())
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
1889
_legacy_formats = [RepositoryFormat4(),
1890
                   RepositoryFormat5(),
1891
                   RepositoryFormat6()]
1892
1893
1563.2.12 by Robert Collins
Checkpointing: created InterObject to factor out common inter object worker code, added InterVersionedFile and tests to allow making join work between any versionedfile.
1894
class InterRepository(InterObject):
1534.1.27 by Robert Collins
Start InterRepository with InterRepository.get.
1895
    """This class represents operations taking place between two repositories.
1896
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
1897
    Its instances have methods like copy_content and fetch, and contain
1534.1.27 by Robert Collins
Start InterRepository with InterRepository.get.
1898
    references to the source and target repositories these operations can be 
1899
    carried out on.
1900
1901
    Often we will provide convenience methods on 'repository' which carry out
1902
    operations with another repository - they will always forward to
1903
    InterRepository.get(other).method_name(parameters).
1904
    """
1905
1910.2.15 by Aaron Bentley
Back out inter.get changes, make optimizers an ordered list
1906
    _optimisers = []
1534.1.28 by Robert Collins
Allow for optimised InterRepository selection.
1907
    """The available optimised InterRepository types."""
1908
1910.2.15 by Aaron Bentley
Back out inter.get changes, make optimizers an ordered list
1909
    def copy_content(self, revision_id=None, basis=None):
1910
        raise NotImplementedError(self.copy_content)
1911
1912
    def fetch(self, revision_id=None, pb=None):
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
1913
        """Fetch the content required to construct revision_id.
1914
1910.7.17 by Andrew Bennetts
Various cosmetic changes.
1915
        The content is copied from self.source to self.target.
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
1916
1917
        :param revision_id: if None all content is copied, if NULL_REVISION no
1918
                            content is copied.
1919
        :param pb: optional progress bar to use for progress reports. If not
1920
                   provided a default one will be created.
1921
1922
        Returns the copied revision count and the failed revisions in a tuple:
1923
        (copied, failures).
1924
        """
1910.2.15 by Aaron Bentley
Back out inter.get changes, make optimizers an ordered list
1925
        raise NotImplementedError(self.fetch)
1926
   
1927
    @needs_read_lock
1928
    def missing_revision_ids(self, revision_id=None):
1929
        """Return the revision ids that source has that target does not.
1930
        
1931
        These are returned in topological order.
1932
1933
        :param revision_id: only return revision ids included by this
1934
                            revision_id.
1935
        """
1936
        # generic, possibly worst case, slow code path.
1937
        target_ids = set(self.target.all_revision_ids())
1938
        if revision_id is not None:
1939
            source_ids = self.source.get_ancestry(revision_id)
1963.2.6 by Robey Pointer
pychecker is on crack; go back to using 'is None'.
1940
            assert source_ids[0] is None
1910.2.15 by Aaron Bentley
Back out inter.get changes, make optimizers an ordered list
1941
            source_ids.pop(0)
1942
        else:
1943
            source_ids = self.source.all_revision_ids()
1944
        result_set = set(source_ids).difference(target_ids)
1945
        # this may look like a no-op: its not. It preserves the ordering
1946
        # other_ids had while only returning the members from other_ids
1947
        # that we've decided we need.
1948
        return [rev_id for rev_id in source_ids if rev_id in result_set]
1949
1950
1951
class InterSameDataRepository(InterRepository):
1952
    """Code for converting between repositories that represent the same data.
1953
    
1954
    Data format and model must match for this to work.
1955
    """
1956
1957
    _matching_repo_format = RepositoryFormat4()
1958
    """Repository format for testing with."""
1959
1910.2.14 by Aaron Bentley
Fail when trying to use interrepository on Knit2 and Knit1
1960
    @staticmethod
1961
    def is_compatible(source, target):
1962
        if source._format.rich_root_data == target._format.rich_root_data:
1963
            return True
1964
        else:
1965
            return False
1966
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
1967
    @needs_write_lock
1968
    def copy_content(self, revision_id=None, basis=None):
1969
        """Make a complete copy of the content in self into destination.
1970
        
1971
        This is a destructive operation! Do not use it on existing 
1972
        repositories.
1973
1974
        :param revision_id: Only copy the content needed to construct
1975
                            revision_id and its parents.
1976
        :param basis: Copy the needed data preferentially from basis.
1977
        """
1978
        try:
1979
            self.target.set_make_working_trees(self.source.make_working_trees())
1980
        except NotImplementedError:
1981
            pass
1982
        # grab the basis available data
1983
        if basis is not None:
1984
            self.target.fetch(basis, revision_id=revision_id)
1759.2.2 by Jelmer Vernooij
Revert some of my spelling fixes and fix some typos after review by Aaron.
1985
        # but don't bother fetching if we have the needed data now.
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
1986
        if (revision_id not in (None, _mod_revision.NULL_REVISION) and 
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
1987
            self.target.has_revision(revision_id)):
1988
            return
1989
        self.target.fetch(self.source, revision_id=revision_id)
1990
1991
    @needs_write_lock
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
1992
    def fetch(self, revision_id=None, pb=None):
1910.7.20 by Andrew Bennetts
Merge from bzr.dev
1993
        """See InterRepository.fetch()."""
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
1994
        from bzrlib.fetch import GenericRepoFetcher
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
1995
        mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
1910.2.15 by Aaron Bentley
Back out inter.get changes, make optimizers an ordered list
1996
               self.source, self.source._format, self.target, 
1997
               self.target._format)
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
1998
        f = GenericRepoFetcher(to_repository=self.target,
1999
                               from_repository=self.source,
2000
                               last_revision=revision_id,
2001
                               pb=pb)
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
2002
        return f.count_copied, f.failed_revisions
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
2003
1910.2.15 by Aaron Bentley
Back out inter.get changes, make optimizers an ordered list
2004
2005
class InterWeaveRepo(InterSameDataRepository):
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
2006
    """Optimised code paths between Weave based repositories."""
2007
1666.1.6 by Robert Collins
Make knit the default format.
2008
    _matching_repo_format = RepositoryFormat7()
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
2009
    """Repository format for testing with."""
2010
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
2011
    @staticmethod
2012
    def is_compatible(source, target):
2013
        """Be compatible with known Weave formats.
2014
        
1759.2.2 by Jelmer Vernooij
Revert some of my spelling fixes and fix some typos after review by Aaron.
2015
        We don't test for the stores being of specific types because that
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
2016
        could lead to confusing results, and there is no need to be 
2017
        overly general.
2018
        """
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
2019
        try:
2020
            return (isinstance(source._format, (RepositoryFormat5,
2021
                                                RepositoryFormat6,
2022
                                                RepositoryFormat7)) and
2023
                    isinstance(target._format, (RepositoryFormat5,
2024
                                                RepositoryFormat6,
2025
                                                RepositoryFormat7)))
2026
        except AttributeError:
2027
            return False
2028
    
2029
    @needs_write_lock
2030
    def copy_content(self, revision_id=None, basis=None):
2031
        """See InterRepository.copy_content()."""
2032
        # weave specific optimised path:
2033
        if basis is not None:
2034
            # copy the basis in, then fetch remaining data.
2035
            basis.copy_content_into(self.target, revision_id)
1759.2.2 by Jelmer Vernooij
Revert some of my spelling fixes and fix some typos after review by Aaron.
2036
            # the basis copy_content_into could miss-set this.
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
2037
            try:
2038
                self.target.set_make_working_trees(self.source.make_working_trees())
2039
            except NotImplementedError:
2040
                pass
2041
            self.target.fetch(self.source, revision_id=revision_id)
2042
        else:
2043
            try:
2044
                self.target.set_make_working_trees(self.source.make_working_trees())
2045
            except NotImplementedError:
2046
                pass
2047
            # FIXME do not peek!
2048
            if self.source.control_files._transport.listable():
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
2049
                pb = ui.ui_factory.nested_progress_bar()
1594.1.3 by Robert Collins
Fixup pb usage to use nested_progress_bar.
2050
                try:
1563.2.37 by Robert Collins
Merge in nested progress bars
2051
                    self.target.weave_store.copy_all_ids(
2052
                        self.source.weave_store,
2053
                        pb=pb,
2054
                        from_transaction=self.source.get_transaction(),
2055
                        to_transaction=self.target.get_transaction())
1594.1.3 by Robert Collins
Fixup pb usage to use nested_progress_bar.
2056
                    pb.update('copying inventory', 0, 1)
2057
                    self.target.control_weaves.copy_multi(
1563.2.37 by Robert Collins
Merge in nested progress bars
2058
                        self.source.control_weaves, ['inventory'],
2059
                        from_transaction=self.source.get_transaction(),
2060
                        to_transaction=self.target.get_transaction())
2061
                    self.target._revision_store.text_store.copy_all_ids(
2062
                        self.source._revision_store.text_store,
2063
                        pb=pb)
1594.1.3 by Robert Collins
Fixup pb usage to use nested_progress_bar.
2064
                finally:
2065
                    pb.finished()
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
2066
            else:
2067
                self.target.fetch(self.source, revision_id=revision_id)
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
2068
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
2069
    @needs_write_lock
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
2070
    def fetch(self, revision_id=None, pb=None):
2071
        """See InterRepository.fetch()."""
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
2072
        from bzrlib.fetch import GenericRepoFetcher
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
2073
        mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
2074
               self.source, self.source._format, self.target, self.target._format)
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
2075
        f = GenericRepoFetcher(to_repository=self.target,
2076
                               from_repository=self.source,
2077
                               last_revision=revision_id,
2078
                               pb=pb)
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
2079
        return f.count_copied, f.failed_revisions
2080
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
2081
    @needs_read_lock
2082
    def missing_revision_ids(self, revision_id=None):
2083
        """See InterRepository.missing_revision_ids()."""
2084
        # we want all revisions to satisfy revision_id in source.
1759.2.2 by Jelmer Vernooij
Revert some of my spelling fixes and fix some typos after review by Aaron.
2085
        # but we don't want to stat every file here and there.
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
2086
        # we want then, all revisions other needs to satisfy revision_id 
2087
        # checked, but not those that we have locally.
2088
        # so the first thing is to get a subset of the revisions to 
2089
        # satisfy revision_id in source, and then eliminate those that
2090
        # we do already have. 
2091
        # this is slow on high latency connection to self, but as as this
2092
        # disk format scales terribly for push anyway due to rewriting 
2093
        # inventory.weave, this is considered acceptable.
2094
        # - RBC 20060209
2095
        if revision_id is not None:
2096
            source_ids = self.source.get_ancestry(revision_id)
1963.2.6 by Robey Pointer
pychecker is on crack; go back to using 'is None'.
2097
            assert source_ids[0] is None
1668.1.14 by Martin Pool
merge olaf - InvalidRevisionId fixes
2098
            source_ids.pop(0)
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
2099
        else:
2100
            source_ids = self.source._all_possible_ids()
2101
        source_ids_set = set(source_ids)
2102
        # source_ids is the worst possible case we may need to pull.
2103
        # now we want to filter source_ids against what we actually
1759.2.2 by Jelmer Vernooij
Revert some of my spelling fixes and fix some typos after review by Aaron.
2104
        # have in target, but don't try to check for existence where we know
1534.1.34 by Robert Collins
Move missing_revision_ids from Repository to InterRepository, and eliminate the now unused Repository._compatible_formats method.
2105
        # we do not have a revision as that would be pointless.
2106
        target_ids = set(self.target._all_possible_ids())
2107
        possibly_present_revisions = target_ids.intersection(source_ids_set)
2108
        actually_present_revisions = set(self.target._eliminate_revisions_not_present(possibly_present_revisions))
2109
        required_revisions = source_ids_set.difference(actually_present_revisions)
2110
        required_topo_revisions = [rev_id for rev_id in source_ids if rev_id in required_revisions]
2111
        if revision_id is not None:
2112
            # we used get_ancestry to determine source_ids then we are assured all
2113
            # revisions referenced are present as they are installed in topological order.
2114
            # and the tip revision was validated by get_ancestry.
2115
            return required_topo_revisions
2116
        else:
2117
            # if we just grabbed the possibly available ids, then 
2118
            # we only have an estimate of whats available and need to validate
2119
            # that against the revision records.
2120
            return self.source._eliminate_revisions_not_present(required_topo_revisions)
2121
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
2122
1910.2.15 by Aaron Bentley
Back out inter.get changes, make optimizers an ordered list
2123
class InterKnitRepo(InterSameDataRepository):
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
2124
    """Optimised code paths between Knit based repositories."""
2125
2126
    _matching_repo_format = RepositoryFormatKnit1()
2127
    """Repository format for testing with."""
2128
2129
    @staticmethod
2130
    def is_compatible(source, target):
2131
        """Be compatible with known Knit formats.
2132
        
1759.2.2 by Jelmer Vernooij
Revert some of my spelling fixes and fix some typos after review by Aaron.
2133
        We don't test for the stores being of specific types because that
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
2134
        could lead to confusing results, and there is no need to be 
2135
        overly general.
2136
        """
2137
        try:
2138
            return (isinstance(source._format, (RepositoryFormatKnit1)) and
2139
                    isinstance(target._format, (RepositoryFormatKnit1)))
2140
        except AttributeError:
2141
            return False
2142
2143
    @needs_write_lock
2144
    def fetch(self, revision_id=None, pb=None):
2145
        """See InterRepository.fetch()."""
2146
        from bzrlib.fetch import KnitRepoFetcher
2147
        mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
2148
               self.source, self.source._format, self.target, self.target._format)
2149
        f = KnitRepoFetcher(to_repository=self.target,
2150
                            from_repository=self.source,
2151
                            last_revision=revision_id,
2152
                            pb=pb)
2153
        return f.count_copied, f.failed_revisions
2154
2155
    @needs_read_lock
2156
    def missing_revision_ids(self, revision_id=None):
2157
        """See InterRepository.missing_revision_ids()."""
2158
        if revision_id is not None:
2159
            source_ids = self.source.get_ancestry(revision_id)
1963.2.6 by Robey Pointer
pychecker is on crack; go back to using 'is None'.
2160
            assert source_ids[0] is None
1668.1.14 by Martin Pool
merge olaf - InvalidRevisionId fixes
2161
            source_ids.pop(0)
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
2162
        else:
2163
            source_ids = self.source._all_possible_ids()
2164
        source_ids_set = set(source_ids)
2165
        # source_ids is the worst possible case we may need to pull.
2166
        # now we want to filter source_ids against what we actually
1759.2.2 by Jelmer Vernooij
Revert some of my spelling fixes and fix some typos after review by Aaron.
2167
        # have in target, but don't try to check for existence where we know
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
2168
        # we do not have a revision as that would be pointless.
2169
        target_ids = set(self.target._all_possible_ids())
2170
        possibly_present_revisions = target_ids.intersection(source_ids_set)
2171
        actually_present_revisions = set(self.target._eliminate_revisions_not_present(possibly_present_revisions))
2172
        required_revisions = source_ids_set.difference(actually_present_revisions)
2173
        required_topo_revisions = [rev_id for rev_id in source_ids if rev_id in required_revisions]
2174
        if revision_id is not None:
2175
            # we used get_ancestry to determine source_ids then we are assured all
2176
            # revisions referenced are present as they are installed in topological order.
2177
            # and the tip revision was validated by get_ancestry.
2178
            return required_topo_revisions
2179
        else:
2180
            # if we just grabbed the possibly available ids, then 
2181
            # we only have an estimate of whats available and need to validate
2182
            # that against the revision records.
2183
            return self.source._eliminate_revisions_not_present(required_topo_revisions)
2184
1910.2.17 by Aaron Bentley
Get fetching from 1 to 2 under test
2185
1910.2.24 by Aaron Bentley
Got intra-repository fetch working between model1 and 2 for all types
2186
class InterModel1and2(InterRepository):
2187
2188
    _matching_repo_format = None
2189
2190
    @staticmethod
2191
    def is_compatible(source, target):
2192
        if not isinstance(source, Repository):
2193
            return False
2194
        if not isinstance(target, Repository):
2195
            return False
2196
        if not source._format.rich_root_data and target._format.rich_root_data:
2197
            return True
2198
        else:
2199
            return False
2200
2201
    @needs_write_lock
2202
    def fetch(self, revision_id=None, pb=None):
2203
        """See InterRepository.fetch()."""
2204
        from bzrlib.fetch import Model1toKnit2Fetcher
2205
        f = Model1toKnit2Fetcher(to_repository=self.target,
2206
                                 from_repository=self.source,
2207
                                 last_revision=revision_id,
2208
                                 pb=pb)
2209
        return f.count_copied, f.failed_revisions
2210
1910.2.26 by Aaron Bentley
Fix up some test cases
2211
    @needs_write_lock
2212
    def copy_content(self, revision_id=None, basis=None):
2213
        """Make a complete copy of the content in self into destination.
2214
        
2215
        This is a destructive operation! Do not use it on existing 
2216
        repositories.
2217
2218
        :param revision_id: Only copy the content needed to construct
2219
                            revision_id and its parents.
2220
        :param basis: Copy the needed data preferentially from basis.
2221
        """
2222
        try:
2223
            self.target.set_make_working_trees(self.source.make_working_trees())
2224
        except NotImplementedError:
2225
            pass
2226
        # grab the basis available data
2227
        if basis is not None:
2228
            self.target.fetch(basis, revision_id=revision_id)
2229
        # but don't bother fetching if we have the needed data now.
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
2230
        if (revision_id not in (None, _mod_revision.NULL_REVISION) and 
1910.2.26 by Aaron Bentley
Fix up some test cases
2231
            self.target.has_revision(revision_id)):
2232
            return
2233
        self.target.fetch(self.source, revision_id=revision_id)
2234
1910.2.24 by Aaron Bentley
Got intra-repository fetch working between model1 and 2 for all types
2235
1910.2.17 by Aaron Bentley
Get fetching from 1 to 2 under test
2236
class InterKnit1and2(InterKnitRepo):
2237
1910.2.24 by Aaron Bentley
Got intra-repository fetch working between model1 and 2 for all types
2238
    _matching_repo_format = None
2239
1910.2.17 by Aaron Bentley
Get fetching from 1 to 2 under test
2240
    @staticmethod
2241
    def is_compatible(source, target):
2242
        """Be compatible with Knit1 source and Knit2 target"""
2243
        try:
2244
            return (isinstance(source._format, (RepositoryFormatKnit1)) and
2245
                    isinstance(target._format, (RepositoryFormatKnit2)))
2246
        except AttributeError:
2247
            return False
2248
2249
    @needs_write_lock
2250
    def fetch(self, revision_id=None, pb=None):
2251
        """See InterRepository.fetch()."""
2252
        from bzrlib.fetch import Knit1to2Fetcher
2253
        mutter("Using fetch logic to copy between %s(%s) and %s(%s)",
2254
               self.source, self.source._format, self.target, 
2255
               self.target._format)
2256
        f = Knit1to2Fetcher(to_repository=self.target,
2257
                            from_repository=self.source,
2258
                            last_revision=revision_id,
2259
                            pb=pb)
2260
        return f.count_copied, f.failed_revisions
2261
2262
1910.2.15 by Aaron Bentley
Back out inter.get changes, make optimizers an ordered list
2263
InterRepository.register_optimiser(InterSameDataRepository)
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
2264
InterRepository.register_optimiser(InterWeaveRepo)
1563.2.31 by Robert Collins
Convert Knit repositories to use knits.
2265
InterRepository.register_optimiser(InterKnitRepo)
1910.2.24 by Aaron Bentley
Got intra-repository fetch working between model1 and 2 for all types
2266
InterRepository.register_optimiser(InterModel1and2)
1910.2.17 by Aaron Bentley
Get fetching from 1 to 2 under test
2267
InterRepository.register_optimiser(InterKnit1and2)
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
2268
2269
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
2270
class RepositoryTestProviderAdapter(object):
2271
    """A tool to generate a suite testing multiple repository formats at once.
2272
2273
    This is done by copying the test once for each transport and injecting
2274
    the transport_server, transport_readonly_server, and bzrdir_format and
2275
    repository_format classes into each copy. Each copy is also given a new id()
2276
    to make it easy to identify.
2277
    """
2278
2018.5.64 by Robert Collins
Allow Repository tests to be backed onto a specific VFS as needed.
2279
    def __init__(self, transport_server, transport_readonly_server, formats,
2280
        vfs_transport_factory=None):
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
2281
        self._transport_server = transport_server
2282
        self._transport_readonly_server = transport_readonly_server
2018.5.64 by Robert Collins
Allow Repository tests to be backed onto a specific VFS as needed.
2283
        self._vfs_transport_factory = vfs_transport_factory
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
2284
        self._formats = formats
2285
    
2286
    def adapt(self, test):
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
2287
        result = unittest.TestSuite()
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
2288
        for repository_format, bzrdir_format in self._formats:
2289
            new_test = deepcopy(test)
2290
            new_test.transport_server = self._transport_server
2291
            new_test.transport_readonly_server = self._transport_readonly_server
2018.5.64 by Robert Collins
Allow Repository tests to be backed onto a specific VFS as needed.
2292
            if self._vfs_transport_factory:
2293
                new_test.vfs_transport_factory = self._vfs_transport_factory
1534.4.40 by Robert Collins
Add RepositoryFormats and allow bzrdir.open or create _repository to be used.
2294
            new_test.bzrdir_format = bzrdir_format
2295
            new_test.repository_format = repository_format
2296
            def make_new_test_id():
2297
                new_id = "%s(%s)" % (new_test.id(), repository_format.__class__.__name__)
2298
                return lambda: new_id
2299
            new_test.id = make_new_test_id()
2300
            result.addTest(new_test)
2301
        return result
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
2302
2303
2304
class InterRepositoryTestProviderAdapter(object):
2305
    """A tool to generate a suite testing multiple inter repository formats.
2306
2307
    This is done by copying the test once for each interrepo provider and injecting
2308
    the transport_server, transport_readonly_server, repository_format and 
2309
    repository_to_format classes into each copy.
2310
    Each copy is also given a new id() to make it easy to identify.
2311
    """
2312
2313
    def __init__(self, transport_server, transport_readonly_server, formats):
2314
        self._transport_server = transport_server
2315
        self._transport_readonly_server = transport_readonly_server
2316
        self._formats = formats
2317
    
2318
    def adapt(self, test):
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
2319
        result = unittest.TestSuite()
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
2320
        for interrepo_class, repository_format, repository_format_to in self._formats:
2321
            new_test = deepcopy(test)
2322
            new_test.transport_server = self._transport_server
2323
            new_test.transport_readonly_server = self._transport_readonly_server
2324
            new_test.interrepo_class = interrepo_class
2325
            new_test.repository_format = repository_format
2326
            new_test.repository_format_to = repository_format_to
2327
            def make_new_test_id():
2328
                new_id = "%s(%s)" % (new_test.id(), interrepo_class.__name__)
2329
                return lambda: new_id
2330
            new_test.id = make_new_test_id()
2331
            result.addTest(new_test)
2332
        return result
2333
2334
    @staticmethod
2335
    def default_test_list():
2336
        """Generate the default list of interrepo permutations to test."""
2337
        result = []
2338
        # test the default InterRepository between format 6 and the current 
2339
        # default format.
1534.1.33 by Robert Collins
Move copy_content_into into InterRepository and InterWeaveRepo, and disable the default codepath test as we have optimised paths for all current combinations.
2340
        # XXX: robertc 20060220 reinstate this when there are two supported
2341
        # formats which do not have an optimal code path between them.
1910.2.24 by Aaron Bentley
Got intra-repository fetch working between model1 and 2 for all types
2342
        #result.append((InterRepository,
2343
        #               RepositoryFormat6(),
2344
        #               RepositoryFormatKnit1()))
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
2345
        for optimiser in InterRepository._optimisers:
1910.2.24 by Aaron Bentley
Got intra-repository fetch working between model1 and 2 for all types
2346
            if optimiser._matching_repo_format is not None:
2347
                result.append((optimiser,
2348
                               optimiser._matching_repo_format,
2349
                               optimiser._matching_repo_format
2350
                               ))
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
2351
        # if there are specific combinations we want to use, we can add them 
2352
        # here.
1910.2.24 by Aaron Bentley
Got intra-repository fetch working between model1 and 2 for all types
2353
        result.append((InterModel1and2, RepositoryFormat5(),
2354
                       RepositoryFormatKnit2()))
2355
        result.append((InterKnit1and2, RepositoryFormatKnit1(),
2356
                       RepositoryFormatKnit2()))
1534.1.29 by Robert Collins
Add a test environment for InterRepository objects, and remove the fetch corner case tests from test_repository.
2357
        return result
1556.1.4 by Robert Collins
Add a new format for what will become knit, and the surrounding logic to upgrade repositories within metadirs, and tests for the same.
2358
2359
2360
class CopyConverter(object):
2361
    """A repository conversion tool which just performs a copy of the content.
2362
    
2363
    This is slow but quite reliable.
2364
    """
2365
2366
    def __init__(self, target_format):
2367
        """Create a CopyConverter.
2368
2369
        :param target_format: The format the resulting repository should be.
2370
        """
2371
        self.target_format = target_format
2372
        
2373
    def convert(self, repo, pb):
2374
        """Perform the conversion of to_convert, giving feedback via pb.
2375
2376
        :param to_convert: The disk object to convert.
2377
        :param pb: a progress bar to use for progress information.
2378
        """
2379
        self.pb = pb
2380
        self.count = 0
1596.2.22 by Robert Collins
Fetch changes to use new pb.
2381
        self.total = 4
1556.1.4 by Robert Collins
Add a new format for what will become knit, and the surrounding logic to upgrade repositories within metadirs, and tests for the same.
2382
        # this is only useful with metadir layouts - separated repo content.
2383
        # trigger an assertion if not such
2384
        repo._format.get_format_string()
2385
        self.repo_dir = repo.bzrdir
2386
        self.step('Moving repository to repository.backup')
2387
        self.repo_dir.transport.move('repository', 'repository.backup')
2388
        backup_transport =  self.repo_dir.transport.clone('repository.backup')
1910.2.12 by Aaron Bentley
Implement knit repo format 2
2389
        repo._format.check_conversion_target(self.target_format)
1556.1.4 by Robert Collins
Add a new format for what will become knit, and the surrounding logic to upgrade repositories within metadirs, and tests for the same.
2390
        self.source_repo = repo._format.open(self.repo_dir,
2391
            _found=True,
2392
            _override_transport=backup_transport)
2393
        self.step('Creating new repository')
2394
        converted = self.target_format.initialize(self.repo_dir,
2395
                                                  self.source_repo.is_shared())
2396
        converted.lock_write()
2397
        try:
2398
            self.step('Copying content into repository.')
2399
            self.source_repo.copy_content_into(converted)
2400
        finally:
2401
            converted.unlock()
2402
        self.step('Deleting old repository content.')
2403
        self.repo_dir.transport.delete_tree('repository.backup')
2404
        self.pb.note('repository converted')
2405
2406
    def step(self, message):
2407
        """Update the pb by a step."""
2408
        self.count +=1
2409
        self.pb.update(message, self.count, self.total)
1596.1.1 by Martin Pool
Use simple xml unescaping rather than importing xml.sax
2410
2411
1740.3.1 by Jelmer Vernooij
Introduce and use CommitBuilder objects.
2412
class CommitBuilder(object):
2413
    """Provides an interface to build up a commit.
2414
2415
    This allows describing a tree to be committed without needing to 
2416
    know the internals of the format of the repository.
2417
    """
1910.2.4 by Aaron Bentley
Support old CommitBuilders
2418
    
2419
    record_root_entry = False
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
2420
    def __init__(self, repository, parents, config, timestamp=None, 
2421
                 timezone=None, committer=None, revprops=None, 
2422
                 revision_id=None):
2423
        """Initiate a CommitBuilder.
2424
2425
        :param repository: Repository to commit to.
2426
        :param parents: Revision ids of the parents of the new revision.
2427
        :param config: Configuration to use.
2428
        :param timestamp: Optional timestamp recorded for commit.
2429
        :param timezone: Optional timezone for timestamp.
2430
        :param committer: Optional committer to set for commit.
2431
        :param revprops: Optional dictionary of revision properties.
2432
        :param revision_id: Optional revision id.
2433
        """
2434
        self._config = config
2435
2436
        if committer is None:
2437
            self._committer = self._config.username()
2438
        else:
2439
            assert isinstance(committer, basestring), type(committer)
2440
            self._committer = committer
2441
1731.1.33 by Aaron Bentley
Revert no-special-root changes
2442
        self.new_inventory = Inventory(None)
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
2443
        self._new_revision_id = revision_id
1740.3.6 by Jelmer Vernooij
Move inventory writing to the commit builder.
2444
        self.parents = parents
1740.3.1 by Jelmer Vernooij
Introduce and use CommitBuilder objects.
2445
        self.repository = repository
1740.3.6 by Jelmer Vernooij
Move inventory writing to the commit builder.
2446
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
2447
        self._revprops = {}
2448
        if revprops is not None:
2449
            self._revprops.update(revprops)
2450
2451
        if timestamp is None:
1864.2.1 by John Arbash Meinel
Commit timestamp restricted to 1ms precision.
2452
            timestamp = time.time()
2453
        # Restrict resolution to 1ms
2454
        self._timestamp = round(timestamp, 3)
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
2455
2456
        if timezone is None:
2457
            self._timezone = local_time_offset()
2458
        else:
2459
            self._timezone = int(timezone)
2460
2461
        self._generate_revision_if_needed()
2462
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
2463
    def commit(self, message):
1740.3.8 by Jelmer Vernooij
Move make_revision() to commit builder.
2464
        """Make the actual commit.
2465
2466
        :return: The revision id of the recorded revision.
2467
        """
1996.3.4 by John Arbash Meinel
lazy_import bzrlib/repository.py
2468
        rev = _mod_revision.Revision(
2469
                       timestamp=self._timestamp,
1740.3.8 by Jelmer Vernooij
Move make_revision() to commit builder.
2470
                       timezone=self._timezone,
2471
                       committer=self._committer,
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
2472
                       message=message,
1740.3.8 by Jelmer Vernooij
Move make_revision() to commit builder.
2473
                       inventory_sha1=self.inv_sha1,
2474
                       revision_id=self._new_revision_id,
2475
                       properties=self._revprops)
2476
        rev.parent_ids = self.parents
2477
        self.repository.add_revision(self._new_revision_id, rev, 
2478
            self.new_inventory, self._config)
2479
        return self._new_revision_id
2480
2041.1.5 by John Arbash Meinel
CommitBuilder.get_tree => CommitBuilder.revision_tree
2481
    def revision_tree(self):
2041.1.1 by John Arbash Meinel
Add a 'get_tree()' call that returns a RevisionTree for the newly committed tree
2482
        """Return the tree that was just committed.
2483
2484
        After calling commit() this can be called to get a RevisionTree
2485
        representing the newly committed tree. This is preferred to
2486
        calling Repository.revision_tree() because that may require
2487
        deserializing the inventory, while we already have a copy in
2488
        memory.
2489
        """
2490
        return RevisionTree(self.repository, self.new_inventory,
2491
                            self._new_revision_id)
2492
1740.3.6 by Jelmer Vernooij
Move inventory writing to the commit builder.
2493
    def finish_inventory(self):
1740.3.9 by Jelmer Vernooij
Make the commit message the first argument of CommitBuilder.commit().
2494
        """Tell the builder that the inventory is finished."""
1910.2.3 by Aaron Bentley
All tests pass
2495
        if self.new_inventory.root is None:
1910.2.9 by Aaron Bentley
Inroduce assertDeprecated, and use it to test old commitbuilder API
2496
            symbol_versioning.warn('Root entry should be supplied to'
2497
                ' record_entry_contents, as of bzr 0.10.',
1910.2.3 by Aaron Bentley
All tests pass
2498
                 DeprecationWarning, stacklevel=2)
2499
            self.new_inventory.add(InventoryDirectory(ROOT_ID, '', None))
1757.1.2 by Robert Collins
Bugfix CommitBuilders recording of the inventory revision id.
2500
        self.new_inventory.revision_id = self._new_revision_id
1740.3.8 by Jelmer Vernooij
Move make_revision() to commit builder.
2501
        self.inv_sha1 = self.repository.add_inventory(
1740.3.6 by Jelmer Vernooij
Move inventory writing to the commit builder.
2502
            self._new_revision_id,
2503
            self.new_inventory,
2504
            self.parents
2505
            )
1740.3.1 by Jelmer Vernooij
Introduce and use CommitBuilder objects.
2506
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
2507
    def _gen_revision_id(self):
2508
        """Return new revision-id."""
2116.4.1 by John Arbash Meinel
Update file and revision id generators.
2509
        return generate_ids.gen_revision_id(self._config.username(),
2510
                                            self._timestamp)
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
2511
2512
    def _generate_revision_if_needed(self):
2513
        """Create a revision id if None was supplied.
2514
        
2515
        If the repository can not support user-specified revision ids
2150.2.2 by Robert Collins
Change the commit builder selected-revision-id test to use a unicode revision id where possible, leading to stricter testing of the hypothetical unicode revision id support in bzr.
2516
        they should override this function and raise CannotSetRevisionId
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
2517
        if _new_revision_id is not None.
2518
2150.2.2 by Robert Collins
Change the commit builder selected-revision-id test to use a unicode revision id where possible, leading to stricter testing of the hypothetical unicode revision id support in bzr.
2519
        :raises: CannotSetRevisionId
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
2520
        """
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
2521
        if self._new_revision_id is None:
2522
            self._new_revision_id = self._gen_revision_id()
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
2523
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
2524
    def record_entry_contents(self, ie, parent_invs, path, tree):
1740.3.1 by Jelmer Vernooij
Introduce and use CommitBuilder objects.
2525
        """Record the content of ie from tree into the commit if needed.
2526
1910.2.3 by Aaron Bentley
All tests pass
2527
        Side effect: sets ie.revision when unchanged
2528
1740.3.1 by Jelmer Vernooij
Introduce and use CommitBuilder objects.
2529
        :param ie: An inventory entry present in the commit.
2530
        :param parent_invs: The inventories of the parent revisions of the
2531
            commit.
2532
        :param path: The path the entry is at in the tree.
2533
        :param tree: The tree which contains this entry and should be used to 
2534
        obtain content.
2535
        """
1910.2.8 by Aaron Bentley
Fix commit_builder when root not passed to record_entry_contents
2536
        if self.new_inventory.root is None and ie.parent_id is not None:
1910.2.9 by Aaron Bentley
Inroduce assertDeprecated, and use it to test old commitbuilder API
2537
            symbol_versioning.warn('Root entry should be supplied to'
2538
                ' record_entry_contents, as of bzr 0.10.',
1910.2.8 by Aaron Bentley
Fix commit_builder when root not passed to record_entry_contents
2539
                 DeprecationWarning, stacklevel=2)
2540
            self.record_entry_contents(tree.inventory.root.copy(), parent_invs,
2541
                                       '', tree)
1907.1.1 by Aaron Bentley
Unshelved all changes except those related to removing RootEntry
2542
        self.new_inventory.add(ie)
1740.3.6 by Jelmer Vernooij
Move inventory writing to the commit builder.
2543
1740.3.4 by Jelmer Vernooij
Move inventory to commit builder.
2544
        # ie.revision is always None if the InventoryEntry is considered
2545
        # for committing. ie.snapshot will record the correct revision 
2546
        # which may be the sole parent if it is untouched.
1740.3.6 by Jelmer Vernooij
Move inventory writing to the commit builder.
2547
        if ie.revision is not None:
2548
            return
1910.2.3 by Aaron Bentley
All tests pass
2549
2550
        # In this revision format, root entries have no knit or weave
2551
        if ie is self.new_inventory.root:
2044.1.1 by Robert Collins
(Robert Collins) Forward merge from 0.11rc2 NEWS and performance-regression fix.
2552
            # When serializing out to disk and back in
2553
            # root.revision is always _new_revision_id
2554
            ie.revision = self._new_revision_id
1910.2.3 by Aaron Bentley
All tests pass
2555
            return
1740.3.1 by Jelmer Vernooij
Introduce and use CommitBuilder objects.
2556
        previous_entries = ie.find_previous_heads(
2557
            parent_invs,
2558
            self.repository.weave_store,
2559
            self.repository.get_transaction())
1740.3.6 by Jelmer Vernooij
Move inventory writing to the commit builder.
2560
        # we are creating a new revision for ie in the history store
2561
        # and inventory.
1740.3.7 by Jelmer Vernooij
Move committer, log, revprops, timestamp and timezone to CommitBuilder.
2562
        ie.snapshot(self._new_revision_id, path, previous_entries, tree, self)
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
2563
2564
    def modified_directory(self, file_id, file_parents):
2565
        """Record the presence of a symbolic link.
2566
2567
        :param file_id: The file_id of the link to record.
2568
        :param file_parents: The per-file parent revision ids.
2569
        """
2570
        self._add_text_to_weave(file_id, [], file_parents.keys())
1740.3.2 by Jelmer Vernooij
Move storing file texts to commit builder.
2571
    
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
2572
    def modified_file_text(self, file_id, file_parents,
2573
                           get_content_byte_lines, text_sha1=None,
2574
                           text_size=None):
1740.3.2 by Jelmer Vernooij
Move storing file texts to commit builder.
2575
        """Record the text of file file_id
2576
2577
        :param file_id: The file_id of the file to record the text of.
2578
        :param file_parents: The per-file parent revision ids.
2579
        :param get_content_byte_lines: A callable which will return the byte
2580
            lines for the file.
2581
        :param text_sha1: Optional SHA1 of the file contents.
2582
        :param text_size: Optional size of the file contents.
2583
        """
1711.2.101 by John Arbash Meinel
Clean up some unnecessary mutter() calls
2584
        # mutter('storing text of file {%s} in revision {%s} into %r',
2585
        #        file_id, self._new_revision_id, self.repository.weave_store)
1740.3.2 by Jelmer Vernooij
Move storing file texts to commit builder.
2586
        # special case to avoid diffing on renames or 
2587
        # reparenting
2588
        if (len(file_parents) == 1
2589
            and text_sha1 == file_parents.values()[0].text_sha1
2590
            and text_size == file_parents.values()[0].text_size):
2591
            previous_ie = file_parents.values()[0]
2592
            versionedfile = self.repository.weave_store.get_weave(file_id, 
2593
                self.repository.get_transaction())
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
2594
            versionedfile.clone_text(self._new_revision_id, 
1740.3.2 by Jelmer Vernooij
Move storing file texts to commit builder.
2595
                previous_ie.revision, file_parents.keys())
2596
            return text_sha1, text_size
2597
        else:
2598
            new_lines = get_content_byte_lines()
2599
            # TODO: Rather than invoking sha_strings here, _add_text_to_weave
2600
            # should return the SHA1 and size
2601
            self._add_text_to_weave(file_id, new_lines, file_parents.keys())
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
2602
            return osutils.sha_strings(new_lines), \
1740.3.2 by Jelmer Vernooij
Move storing file texts to commit builder.
2603
                sum(map(len, new_lines))
2604
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
2605
    def modified_link(self, file_id, file_parents, link_target):
2606
        """Record the presence of a symbolic link.
2607
2608
        :param file_id: The file_id of the link to record.
2609
        :param file_parents: The per-file parent revision ids.
2610
        :param link_target: Target location of this link.
2611
        """
2612
        self._add_text_to_weave(file_id, [], file_parents.keys())
2613
1740.3.2 by Jelmer Vernooij
Move storing file texts to commit builder.
2614
    def _add_text_to_weave(self, file_id, new_lines, parents):
2615
        versionedfile = self.repository.weave_store.get_weave_or_empty(
2616
            file_id, self.repository.get_transaction())
1740.3.3 by Jelmer Vernooij
Move storing directories and links to commit builder.
2617
        versionedfile.add_lines(self._new_revision_id, parents, new_lines)
1740.3.2 by Jelmer Vernooij
Move storing file texts to commit builder.
2618
        versionedfile.clear_cache()
1740.3.1 by Jelmer Vernooij
Introduce and use CommitBuilder objects.
2619
2620
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
2621
class _CommitBuilder(CommitBuilder):
1910.2.4 by Aaron Bentley
Support old CommitBuilders
2622
    """Temporary class so old CommitBuilders are detected properly
2623
    
2624
    Note: CommitBuilder works whether or not root entry is recorded.
2625
    """
2626
2627
    record_root_entry = True
2628
2629
1910.2.22 by Aaron Bentley
Make commits preserve root entry data
2630
class RootCommitBuilder(CommitBuilder):
2631
    """This commitbuilder actually records the root id"""
2632
    
2633
    record_root_entry = True
2634
2635
    def record_entry_contents(self, ie, parent_invs, path, tree):
2636
        """Record the content of ie from tree into the commit if needed.
2637
2638
        Side effect: sets ie.revision when unchanged
2639
2640
        :param ie: An inventory entry present in the commit.
2641
        :param parent_invs: The inventories of the parent revisions of the
2642
            commit.
2643
        :param path: The path the entry is at in the tree.
2644
        :param tree: The tree which contains this entry and should be used to 
2645
        obtain content.
2646
        """
2647
        assert self.new_inventory.root is not None or ie.parent_id is None
2648
        self.new_inventory.add(ie)
2649
2650
        # ie.revision is always None if the InventoryEntry is considered
2651
        # for committing. ie.snapshot will record the correct revision 
2652
        # which may be the sole parent if it is untouched.
2653
        if ie.revision is not None:
2654
            return
2655
2656
        previous_entries = ie.find_previous_heads(
2657
            parent_invs,
2658
            self.repository.weave_store,
2659
            self.repository.get_transaction())
2660
        # we are creating a new revision for ie in the history store
2661
        # and inventory.
2662
        ie.snapshot(self._new_revision_id, path, previous_entries, tree, self)
2663
2664
1843.2.4 by Aaron Bentley
Switch to John Meinel's _unescape_xml implementation
2665
_unescape_map = {
2666
    'apos':"'",
2667
    'quot':'"',
2668
    'amp':'&',
2669
    'lt':'<',
2670
    'gt':'>'
2671
}
2672
2673
2674
def _unescaper(match, _map=_unescape_map):
2675
    return _map[match.group(1)]
2676
2677
2678
_unescape_re = None
2679
2680
1596.1.1 by Martin Pool
Use simple xml unescaping rather than importing xml.sax
2681
def _unescape_xml(data):
1843.2.4 by Aaron Bentley
Switch to John Meinel's _unescape_xml implementation
2682
    """Unescape predefined XML entities in a string of data."""
2683
    global _unescape_re
2684
    if _unescape_re is None:
2120.2.1 by John Arbash Meinel
Remove tabs from source files, and add a test to keep it that way.
2685
        _unescape_re = re.compile('\&([^;]*);')
1843.2.4 by Aaron Bentley
Switch to John Meinel's _unescape_xml implementation
2686
    return _unescape_re.sub(_unescaper, data)