~bzr-pqm/bzr/bzr.dev

974.1.27 by aaron.bentley at utoronto
Initial greedy fetch work
1
# Copyright (C) 2005 by Canonical Ltd
2
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1218 by Martin Pool
- fix up import
16
1480 by Robert Collins
BUGFIX: fetch was not skipping all missing parents for inventory insertion
17
from copy import copy
1218 by Martin Pool
- fix up import
18
import os
1231 by Martin Pool
- more progress on fetch on top of weaves
19
from cStringIO import StringIO
1218 by Martin Pool
- fix up import
20
1185.13.4 by Robert Collins
make reweave visible as a weave method, and quickly integrate into fetch
21
import bzrlib
22
import bzrlib.errors as errors
1185.35.42 by Aaron Bentley
Fixed fetch to be safer wrt ghosts and corrupt branches
23
from bzrlib.errors import (InstallFailed, NoSuchRevision, WeaveError,
24
                           MissingText)
1231 by Martin Pool
- more progress on fetch on top of weaves
25
from bzrlib.trace import mutter, note, warning
1352 by Martin Pool
- store control weaves in .bzr/, not mixed in with file weaves
26
from bzrlib.branch import Branch
974.1.28 by aaron.bentley at utoronto
factored install_revisions out of update_revisions, updated test cases for greedy_fetch
27
from bzrlib.progress import ProgressBar
1231 by Martin Pool
- more progress on fetch on top of weaves
28
from bzrlib.xml5 import serializer_v5
29
from bzrlib.osutils import sha_string, split_lines
30
31
"""Copying of history from one branch to another.
32
33
The basic plan is that every branch knows the history of everything
34
that has merged into it.  As the first step of a merge, pull, or
35
branch operation we copy history from the source into the destination
36
branch.
37
38
The copying is done in a slightly complicated order.  We don't want to
39
add a revision to the store until everything it refers to is also
40
stored, so that if a revision is present we can totally recreate it.
41
However, we can't know what files are included in a revision until we
42
read its inventory.  Therefore, we first pull the XML and hold it in
43
memory until we've updated all of the files referenced.
44
"""
45
46
# TODO: Avoid repeatedly opening weaves so many times.
974.1.27 by aaron.bentley at utoronto
Initial greedy fetch work
47
1238 by Martin Pool
- remove a lot of dead code from fetch
48
# XXX: This doesn't handle ghost (not present in branch) revisions at
1240 by Martin Pool
- clean up fetch code and add progress bar
49
# all yet.  I'm not sure they really should be supported.
50
1262 by Martin Pool
- fetch should also copy ancestry records
51
# NOTE: This doesn't copy revisions which may be present but not
52
# merged into the last revision.  I'm not sure we want to do that.
1238 by Martin Pool
- remove a lot of dead code from fetch
53
54
# - get a list of revisions that need to be pulled in
55
# - for each one, pull in that revision file
56
#   and get the inventory, and store the inventory with right
57
#   parents.
58
# - and get the ancestry, and store that with right parents too
59
# - and keep a note of all file ids and version seen
60
# - then go through all files; for each one get the weave,
61
#   and add in all file versions
62
63
1219 by Martin Pool
- BROKEN: start refactoring fetch code to work well with weaves
64
1260 by Martin Pool
- some updates for fetch/update function
65
def greedy_fetch(to_branch, from_branch, revision=None, pb=None):
1219 by Martin Pool
- BROKEN: start refactoring fetch code to work well with weaves
66
    f = Fetcher(to_branch, from_branch, revision, pb)
67
    return f.count_copied, f.failed_revisions
68
69
1265 by Martin Pool
- add function-style synonym 'fetch'
70
1219 by Martin Pool
- BROKEN: start refactoring fetch code to work well with weaves
71
class Fetcher(object):
1260 by Martin Pool
- some updates for fetch/update function
72
    """Pull revisions and texts from one branch to another.
73
74
    This doesn't update the destination's history; that can be done
75
    separately if desired.  
1231 by Martin Pool
- more progress on fetch on top of weaves
76
77
    revision_limit
78
        If set, pull only up to this revision_id.
1260 by Martin Pool
- some updates for fetch/update function
79
80
    After running:
81
82
    last_revision -- if last_revision
83
        is given it will be that, otherwise the last revision of
84
        from_branch
85
86
    count_copied -- number of revisions copied
87
1405 by Robert Collins
remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave
88
    count_weaves -- number of file weaves copied
1260 by Martin Pool
- some updates for fetch/update function
89
    """
90
    def __init__(self, to_branch, from_branch, last_revision=None, pb=None):
1393.1.17 by Martin Pool
- add assertion to fetch
91
        if to_branch == from_branch:
92
            raise Exception("can't fetch from a branch to itself")
1219 by Martin Pool
- BROKEN: start refactoring fetch code to work well with weaves
93
        self.to_branch = to_branch
1260 by Martin Pool
- some updates for fetch/update function
94
        self.to_weaves = to_branch.weave_store
1392 by Robert Collins
reinstate testfetch test case
95
        self.to_control = to_branch.control_weaves
1219 by Martin Pool
- BROKEN: start refactoring fetch code to work well with weaves
96
        self.from_branch = from_branch
1260 by Martin Pool
- some updates for fetch/update function
97
        self.from_weaves = from_branch.weave_store
1392 by Robert Collins
reinstate testfetch test case
98
        self.from_control = from_branch.control_weaves
1231 by Martin Pool
- more progress on fetch on top of weaves
99
        self.failed_revisions = []
100
        self.count_copied = 0
1240 by Martin Pool
- clean up fetch code and add progress bar
101
        self.count_total = 0
1405 by Robert Collins
remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave
102
        self.count_weaves = 0
1404 by Robert Collins
only pull remote text weaves once per fetch operation
103
        self.copied_file_ids = set()
1185.33.55 by Martin Pool
[patch] weave fetch optimizations (Goffredo Baroncelli)
104
        self.file_ids_names = {}
1219 by Martin Pool
- BROKEN: start refactoring fetch code to work well with weaves
105
        if pb is None:
106
            self.pb = bzrlib.ui.ui_factory.progress_bar()
107
        else:
108
            self.pb = pb
1437 by Robert Collins
lock during fetch, which is a separate code path to the special case of cloning
109
        self.from_branch.lock_read()
1392 by Robert Collins
reinstate testfetch test case
110
        try:
1185.64.4 by Goffredo Baroncelli
Apply some style changes on the basis of Robert suggest
111
            revs = self._revids_to_fetch(last_revision )
1185.64.3 by Goffredo Baroncelli
This patch changes the fetch code. Before, the original code expanded every inventory and
112
            # nothing to do
113
            if revs: 
114
                self._fetch_revision_texts( revs )
115
                self._fetch_weave_texts( revs )
116
                self._fetch_inventory_weave( revs )
117
                self.count_copied += len(revs)
1185.12.15 by Aaron Bentley
Cleared progress bar properly after fetch
118
        finally:
1437 by Robert Collins
lock during fetch, which is a separate code path to the special case of cloning
119
            self.from_branch.unlock()
1185.12.15 by Aaron Bentley
Cleared progress bar properly after fetch
120
            self.pb.clear()
1231 by Martin Pool
- more progress on fetch on top of weaves
121
1185.64.4 by Goffredo Baroncelli
Apply some style changes on the basis of Robert suggest
122
    def _revids_to_fetch(self, last_revision):
1185.12.21 by aaron.bentley at utoronto
Cleaned up Fetcher._find_last_revision
123
        self.last_revision = self._find_last_revision(last_revision)
1425 by Robert Collins
merge from Aaron - unbreaks open_containing and the fetch progress bar
124
        mutter('fetch up to rev {%s}', self.last_revision)
1440 by Robert Collins
further tuning of pull, do not do a local merge or fetch at all, if the remote branch is no newer than we are
125
        if (self.last_revision is not None and 
126
            self.to_branch.has_revision(self.last_revision)):
127
            return
1417.1.13 by Robert Collins
do not download remote ancestry.weave if the target revision we are stopping at is in our local store
128
        try:
1185.64.3 by Goffredo Baroncelli
This patch changes the fetch code. Before, the original code expanded every inventory and
129
            branch_from_revs = set(self.from_branch.get_ancestry(self.last_revision))
1425 by Robert Collins
merge from Aaron - unbreaks open_containing and the fetch progress bar
130
        except WeaveError:
131
            raise InstallFailed([self.last_revision])
1185.64.3 by Goffredo Baroncelli
This patch changes the fetch code. Before, the original code expanded every inventory and
132
133
        self.dest_last_rev = self.to_branch.last_revision()
134
        branch_to_revs = set(self.to_branch.get_ancestry(self.dest_last_rev))
135
136
        return branch_from_revs.difference( branch_to_revs )
137
138
    def _fetch_revision_texts( self, revs ):
139
        self.to_branch.revision_store.copy_multi(
140
            self.from_branch.revision_store, revs )
141
142
    def _fetch_weave_texts( self, revs ):
1185.64.7 by Goffredo Baroncelli
added test for function fileid_involved
143
        file_ids = self.from_branch.fileid_involved_by_set( revs )
1185.64.3 by Goffredo Baroncelli
This patch changes the fetch code. Before, the original code expanded every inventory and
144
        count = 0
145
        num_file_ids = len(file_ids)
146
        for file_id in file_ids:
147
            self.pb.update( "merge weave merge",count,num_file_ids)
148
            count +=1
149
            to_weave = self.to_weaves.get_weave_or_empty(file_id,
150
                self.to_branch.get_transaction())
151
            from_weave = self.from_weaves.get_weave(file_id,
152
                self.from_branch.get_transaction())
153
154
            if to_weave.numversions() > 0:
155
                # destination has contents, must merge
156
                try:
157
                    to_weave.join(from_weave)
158
                except errors.WeaveParentMismatch:
159
                    to_weave.reweave(from_weave)
160
            else:
161
                # destination is empty, just replace it
162
                to_weave = from_weave.copy( )
163
164
            self.to_weaves.put_weave(file_id, to_weave,
165
                self.to_branch.get_transaction())
166
167
        self.pb.clear( )
168
169
    def _fetch_inventory_weave( self, revs ):
170
        self.pb.update( "inventory merge",0,1)
1185.64.4 by Goffredo Baroncelli
Apply some style changes on the basis of Robert suggest
171
1185.64.3 by Goffredo Baroncelli
This patch changes the fetch code. Before, the original code expanded every inventory and
172
        from_weave = self.from_control.get_weave('inventory',
173
                self.from_branch.get_transaction())
174
        to_weave = self.to_control.get_weave('inventory',
175
                self.to_branch.get_transaction())
1185.64.4 by Goffredo Baroncelli
Apply some style changes on the basis of Robert suggest
176
1185.64.3 by Goffredo Baroncelli
This patch changes the fetch code. Before, the original code expanded every inventory and
177
        if to_weave.numversions() > 0:
178
            # destination has contents, must merge
179
            try:
180
                to_weave.join(from_weave)
181
            except errors.WeaveParentMismatch:
182
                to_weave.reweave(from_weave)
183
        else:
184
            # destination is empty, just replace it
185
            to_weave = from_weave.copy( )
186
187
        self.to_control.put_weave('inventory', to_weave,
188
            self.to_branch.get_transaction())
1185.64.4 by Goffredo Baroncelli
Apply some style changes on the basis of Robert suggest
189
1185.64.3 by Goffredo Baroncelli
This patch changes the fetch code. Before, the original code expanded every inventory and
190
        self.pb.clear( )
1240 by Martin Pool
- clean up fetch code and add progress bar
191
1260 by Martin Pool
- some updates for fetch/update function
192
    def _find_last_revision(self, last_revision):
1240 by Martin Pool
- clean up fetch code and add progress bar
193
        """Find the limiting source revision.
194
195
        Every ancestor of that revision will be merged across.
196
197
        Returns the revision_id, or returns None if there's no history
198
        in the source branch."""
1185.12.21 by aaron.bentley at utoronto
Cleaned up Fetcher._find_last_revision
199
        if last_revision:
200
            return last_revision
1240 by Martin Pool
- clean up fetch code and add progress bar
201
        self.pb.update('get source history')
202
        from_history = self.from_branch.revision_history()
203
        self.pb.update('get destination history')
1185.12.21 by aaron.bentley at utoronto
Cleaned up Fetcher._find_last_revision
204
        if from_history:
1240 by Martin Pool
- clean up fetch code and add progress bar
205
            return from_history[-1]
206
        else:
207
            return None                 # no history in the source branch
1265 by Martin Pool
- add function-style synonym 'fetch'
208
209
fetch = Fetcher