/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/repository.py

Merge from bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2005, 2006 Canonical Ltd
2
 
 
 
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
33
33
from bzrlib.osutils import (safe_unicode, rand_bytes, compact_date, 
34
34
                            local_time_offset)
35
35
from bzrlib.revision import NULL_REVISION, Revision
 
36
from bzrlib.revisiontree import RevisionTree
36
37
from bzrlib.store.versioned import VersionedFileStore, WeaveStore
37
38
from bzrlib.store.text import TextStore
38
39
from bzrlib.symbol_versioning import (deprecated_method,
39
40
        zero_nine, 
40
41
        )
 
42
from bzrlib.testament import Testament
41
43
from bzrlib.trace import mutter, note
42
 
from bzrlib.tree import RevisionTree, EmptyTree
43
44
from bzrlib.tsort import topo_sort
44
 
from bzrlib.testament import Testament
45
 
from bzrlib.tree import EmptyTree
46
45
from bzrlib.weave import WeaveFile
47
46
 
48
47
 
347
346
                     t in self.revision_trees(required_trees))
348
347
        for revision in revisions:
349
348
            if not revision.parent_ids:
350
 
                old_tree = EmptyTree()
 
349
                old_tree = self.revision_tree(None)
351
350
            else:
352
351
                old_tree = trees[revision.parent_ids[0]]
353
 
            yield delta.compare_trees(old_tree, trees[revision.revision_id])
 
352
            yield trees[revision.revision_id].changes_from(old_tree)
354
353
 
355
354
    @needs_read_lock
356
355
    def get_revision_delta(self, revision_id):
565
564
    def revision_tree(self, revision_id):
566
565
        """Return Tree for a revision on this branch.
567
566
 
568
 
        `revision_id` may be None for the null revision, in which case
569
 
        an `EmptyTree` is returned."""
 
567
        `revision_id` may be None for the empty tree revision.
 
568
        """
570
569
        # TODO: refactor this to use an existing revision object
571
570
        # so we don't need to read it in twice.
572
571
        if revision_id is None or revision_id == NULL_REVISION:
573
 
            return EmptyTree()
 
572
            return RevisionTree(self, Inventory(root_id=None), NULL_REVISION)
574
573
        else:
575
574
            inv = self.get_revision_inventory(revision_id)
576
575
            return RevisionTree(self, inv, revision_id)
746
745
            present_parents.append(p_id)
747
746
            parent_trees[p_id] = repository.revision_tree(p_id)
748
747
        else:
749
 
            parent_trees[p_id] = EmptyTree()
 
748
            parent_trees[p_id] = repository.revision_tree(None)
750
749
 
751
750
    inv = revision_tree.inventory
752
751
    
 
752
    # backwards compatability hack: skip the root id.
 
753
    entries = inv.iter_entries()
 
754
    entries.next()
753
755
    # Add the texts that are not already present
754
 
    for path, ie in inv.iter_entries():
 
756
    for path, ie in entries:
755
757
        w = repository.weave_store.get_weave_or_empty(ie.file_id,
756
758
                repository.get_transaction())
757
759
        if ie.revision not in w:
1579
1581
            return
1580
1582
        self.target.fetch(self.source, revision_id=revision_id)
1581
1583
 
1582
 
    def _double_lock(self, lock_source, lock_target):
1583
 
        """Take out too locks, rolling back the first if the second throws."""
1584
 
        lock_source()
1585
 
        try:
1586
 
            lock_target()
1587
 
        except Exception:
1588
 
            # we want to ensure that we don't leave source locked by mistake.
1589
 
            # and any error on target should not confuse source.
1590
 
            self.source.unlock()
1591
 
            raise
1592
 
 
1593
1584
    @needs_write_lock
1594
1585
    def fetch(self, revision_id=None, pb=None):
1595
1586
        """Fetch the content required to construct revision_id.
1613
1604
                               pb=pb)
1614
1605
        return f.count_copied, f.failed_revisions
1615
1606
 
1616
 
    def lock_read(self):
1617
 
        """Take out a logical read lock.
1618
 
 
1619
 
        This will lock the source branch and the target branch. The source gets
1620
 
        a read lock and the target a read lock.
1621
 
        """
1622
 
        self._double_lock(self.source.lock_read, self.target.lock_read)
1623
 
 
1624
 
    def lock_write(self):
1625
 
        """Take out a logical write lock.
1626
 
 
1627
 
        This will lock the source branch and the target branch. The source gets
1628
 
        a read lock and the target a write lock.
1629
 
        """
1630
 
        self._double_lock(self.source.lock_read, self.target.lock_write)
1631
 
 
1632
1607
    @needs_read_lock
1633
1608
    def missing_revision_ids(self, revision_id=None):
1634
1609
        """Return the revision ids that source has that target does not.
1652
1627
        # that we've decided we need.
1653
1628
        return [rev_id for rev_id in source_ids if rev_id in result_set]
1654
1629
 
1655
 
    def unlock(self):
1656
 
        """Release the locks on source and target."""
1657
 
        try:
1658
 
            self.target.unlock()
1659
 
        finally:
1660
 
            self.source.unlock()
1661
 
 
1662
1630
 
1663
1631
class InterWeaveRepo(InterRepository):
1664
1632
    """Optimised code paths between Weave based repositories."""
2014
1982
            self._revprops.update(revprops)
2015
1983
 
2016
1984
        if timestamp is None:
2017
 
            self._timestamp = time.time()
2018
 
        else:
2019
 
            self._timestamp = long(timestamp)
 
1985
            timestamp = time.time()
 
1986
        # Restrict resolution to 1ms
 
1987
        self._timestamp = round(timestamp, 3)
2020
1988
 
2021
1989
        if timezone is None:
2022
1990
            self._timezone = local_time_offset()
2129
2097
        :param text_sha1: Optional SHA1 of the file contents.
2130
2098
        :param text_size: Optional size of the file contents.
2131
2099
        """
2132
 
        mutter('storing text of file {%s} in revision {%s} into %r',
2133
 
               file_id, self._new_revision_id, self.repository.weave_store)
 
2100
        # mutter('storing text of file {%s} in revision {%s} into %r',
 
2101
        #        file_id, self._new_revision_id, self.repository.weave_store)
2134
2102
        # special case to avoid diffing on renames or 
2135
2103
        # reparenting
2136
2104
        if (len(file_parents) == 1
2166
2134
        versionedfile.clear_cache()
2167
2135
 
2168
2136
 
2169
 
# Copied from xml.sax.saxutils
 
2137
_unescape_map = {
 
2138
    'apos':"'",
 
2139
    'quot':'"',
 
2140
    'amp':'&',
 
2141
    'lt':'<',
 
2142
    'gt':'>'
 
2143
}
 
2144
 
 
2145
 
 
2146
def _unescaper(match, _map=_unescape_map):
 
2147
    return _map[match.group(1)]
 
2148
 
 
2149
 
 
2150
_unescape_re = None
 
2151
 
 
2152
 
2170
2153
def _unescape_xml(data):
2171
 
    """Unescape &amp;, &lt;, and &gt; in a string of data.
2172
 
    """
2173
 
    data = data.replace("&lt;", "<")
2174
 
    data = data.replace("&gt;", ">")
2175
 
    # must do ampersand last
2176
 
    return data.replace("&amp;", "&")
 
2154
    """Unescape predefined XML entities in a string of data."""
 
2155
    global _unescape_re
 
2156
    if _unescape_re is None:
 
2157
        _unescape_re = re.compile('\&([^;]*);')
 
2158
    return _unescape_re.sub(_unescaper, data)