~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/fetch.py

Merge integration.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
from bzrlib.trace import mutter, note, warning
26
26
from bzrlib.branch import Branch
27
27
from bzrlib.progress import ProgressBar
 
28
from bzrlib.revision import NULL_REVISION
28
29
from bzrlib.xml5 import serializer_v5
29
30
from bzrlib.osutils import sha_string, split_lines
30
31
 
67
68
    return f.count_copied, f.failed_revisions
68
69
 
69
70
 
70
 
 
71
 
class Fetcher(object):
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.  
76
 
 
77
 
    revision_limit
78
 
        If set, pull only up to this revision_id.
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
 
 
 
71
class RepoFetcher(object):
 
72
    """Pull revisions and texts from one repository to another.
 
73
 
 
74
    last_revision
 
75
        if set, try to limit to the data this revision references.
 
76
 
 
77
    after running:
86
78
    count_copied -- number of revisions copied
87
 
 
88
79
    count_weaves -- number of file weaves copied
89
80
    """
90
 
    def __init__(self, to_branch, from_branch, last_revision=None, pb=None):
91
 
        if to_branch.base == from_branch.base:
92
 
            raise Exception("can't fetch from a branch to itself %s, %s" % 
93
 
                            (from_branch.base, to_branch.base))
94
 
        
95
 
        self.to_branch = to_branch
96
 
        self.from_branch = from_branch
 
81
    def __init__(self, to_repository, from_repository, last_revision=None, pb=None):
 
82
        if to_repository.bzrdir.transport.base == from_repository.bzrdir.transport.base:
 
83
            raise Exception("can't fetch from a repository to itself %s, %s" % 
 
84
                            (from_repository.bzrdir.transport.base,
 
85
                             to_repository.bzrdir.transport.base))
 
86
        self.to_repository = to_repository
 
87
        self.from_repository = from_repository
 
88
        # must not mutate self._last_revision as its potentially a shared instance
97
89
        self._last_revision = last_revision
98
90
        if pb is None:
99
91
            self.pb = bzrlib.ui.ui_factory.progress_bar()
100
92
        else:
101
93
            self.pb = pb
102
 
        self.from_branch.lock_read()
 
94
        self.from_repository.lock_read()
103
95
        try:
104
 
            self.to_branch.lock_write()
 
96
            self.to_repository.lock_write()
105
97
            try:
106
98
                self.__fetch()
107
99
            finally:
108
 
                self.to_branch.unlock()
 
100
                self.to_repository.unlock()
109
101
        finally:
110
 
            self.from_branch.unlock()
 
102
            self.from_repository.unlock()
111
103
 
112
104
    def __fetch(self):
113
105
        """Primary worker function.
115
107
        This initialises all the needed variables, and then fetches the 
116
108
        requested revisions, finally clearing the progress bar.
117
109
        """
118
 
        self.to_repository = self.to_branch.repository
119
110
        self.to_weaves = self.to_repository.weave_store
120
111
        self.to_control = self.to_repository.control_weaves
121
 
        self.from_repository = self.from_branch.repository
122
112
        self.from_weaves = self.from_repository.weave_store
123
113
        self.from_control = self.from_repository.control_weaves
124
114
        self.failed_revisions = []
139
129
            self.pb.clear()
140
130
 
141
131
    def _revids_to_fetch(self):
142
 
        self._find_last_revision()
143
132
        mutter('fetch up to rev {%s}', self._last_revision)
144
 
        if (self._last_revision is not None and 
 
133
        if self._last_revision is NULL_REVISION:
 
134
            # explicit limit of no revisions needed
 
135
            return None
 
136
        if (self._last_revision != None and
145
137
            self.to_repository.has_revision(self._last_revision)):
146
 
            return
 
138
            return None
 
139
            
147
140
        try:
148
 
            branch_from_revs = set(self.from_repository.get_ancestry(self._last_revision))
149
 
        except WeaveError:
 
141
            return self.to_repository.missing_revision_ids(self.from_repository,
 
142
                                                           self._last_revision)
 
143
        except errors.NoSuchRevision:
150
144
            raise InstallFailed([self._last_revision])
151
145
 
152
 
        self.dest_last_rev = self.to_branch.last_revision()
153
 
        branch_to_revs = set(self.to_repository.get_ancestry(self.dest_last_rev))
154
 
 
155
 
        return branch_from_revs.difference(branch_to_revs)
156
 
 
157
146
    def _fetch_revision_texts(self, revs):
158
147
        self.to_repository.revision_store.copy_multi(
159
 
            self.from_repository.revision_store, revs)
 
148
            self.from_repository.revision_store,
 
149
            revs,
 
150
            pb=self.pb)
160
151
 
161
152
    def _fetch_weave_texts(self, revs):
162
 
        file_ids = self.from_branch.fileid_involved_by_set(revs)
 
153
        file_ids = self.from_repository.fileid_involved_by_set(revs)
163
154
        count = 0
164
155
        num_file_ids = len(file_ids)
165
156
        for file_id in file_ids:
166
157
            self.pb.update("merge weaves", count, num_file_ids)
167
158
            count +=1
168
159
            to_weave = self.to_weaves.get_weave_or_empty(file_id,
169
 
                self.to_branch.get_transaction())
 
160
                self.to_repository.get_transaction())
170
161
            from_weave = self.from_weaves.get_weave(file_id,
171
 
                self.from_branch.get_transaction())
 
162
                self.from_repository.get_transaction())
172
163
 
173
164
            if to_weave.numversions() > 0:
174
165
                # destination has contents, must merge
181
172
                to_weave = from_weave.copy()
182
173
 
183
174
            self.to_weaves.put_weave(file_id, to_weave,
184
 
                self.to_branch.get_transaction())
185
 
 
 
175
                self.to_repository.get_transaction())
186
176
        self.pb.clear()
187
177
 
188
178
    def _fetch_inventory_weave(self, revs):
191
181
        to_weave = self.to_repository.get_inventory_weave()
192
182
        self.pb.update("inventory fetch", 1, 2)
193
183
        to_weave = self.to_control.get_weave('inventory',
194
 
                self.to_branch.get_transaction())
 
184
                self.to_repository.get_transaction())
195
185
        self.pb.update("inventory fetch", 2, 2)
196
186
 
197
187
        if to_weave.numversions() > 0:
205
195
            to_weave = from_weave.copy()
206
196
 
207
197
        self.to_control.put_weave('inventory', to_weave,
208
 
            self.to_branch.get_transaction())
 
198
            self.to_repository.get_transaction())
209
199
 
210
200
        self.pb.clear()
211
201
 
 
202
 
 
203
class Fetcher(object):
 
204
    """Pull revisions and texts from one branch to another.
 
205
 
 
206
    This doesn't update the destination's history; that can be done
 
207
    separately if desired.  
 
208
 
 
209
    revision_limit
 
210
        If set, pull only up to this revision_id.
 
211
 
 
212
    After running:
 
213
 
 
214
    last_revision -- if last_revision
 
215
        is given it will be that, otherwise the last revision of
 
216
        from_branch
 
217
 
 
218
    count_copied -- number of revisions copied
 
219
 
 
220
    count_weaves -- number of file weaves copied
 
221
    """
 
222
    def __init__(self, to_branch, from_branch, last_revision=None, pb=None):
 
223
        if to_branch.base == from_branch.base:
 
224
            raise Exception("can't fetch from a branch to itself %s, %s" % 
 
225
                            (from_branch.base, to_branch.base))
 
226
        
 
227
        self.to_branch = to_branch
 
228
        self.from_branch = from_branch
 
229
        self._last_revision = last_revision
 
230
        if pb is None:
 
231
            self.pb = bzrlib.ui.ui_factory.progress_bar()
 
232
        else:
 
233
            self.pb = pb
 
234
        self.from_branch.lock_read()
 
235
        try:
 
236
            self.to_branch.lock_write()
 
237
            try:
 
238
                self.__fetch()
 
239
            finally:
 
240
                self.to_branch.unlock()
 
241
        finally:
 
242
            self.from_branch.unlock()
 
243
 
 
244
    def __fetch(self):
 
245
        self._find_last_revision()
 
246
        repo_fetcher = RepoFetcher(to_repository=self.to_branch.repository,
 
247
                                   from_repository=self.from_branch.repository,
 
248
                                   pb=self.pb,
 
249
                                   last_revision=self._last_revision)
 
250
        self.failed_revisions = repo_fetcher.failed_revisions
 
251
        self.count_copied = repo_fetcher.count_copied
 
252
        self.count_total = repo_fetcher.count_total
 
253
        self.count_weaves = repo_fetcher.count_weaves
 
254
        self.copied_file_ids = repo_fetcher.copied_file_ids
 
255
 
212
256
    def _find_last_revision(self):
213
257
        """Find the limiting source revision.
214
258
 
225
269
            self._last_revision = from_history[-1]
226
270
        else:
227
271
            # no history in the source branch
228
 
            self._last_revision = None
 
272
            self._last_revision = NULL_REVISION
229
273
 
230
274
fetch = Fetcher