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
67
68
return f.count_copied, f.failed_revisions
71
class Fetcher(object):
72
"""Pull revisions and texts from one branch to another.
74
This doesn't update the destination's history; that can be done
75
separately if desired.
78
If set, pull only up to this revision_id.
82
last_revision -- if last_revision
83
is given it will be that, otherwise the last revision of
71
class RepoFetcher(object):
72
"""Pull revisions and texts from one repository to another.
75
if set, try to limit to the data this revision references.
86
78
count_copied -- number of revisions copied
88
79
count_weaves -- number of file weaves copied
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))
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
99
91
self.pb = bzrlib.ui.ui_factory.progress_bar()
102
self.from_branch.lock_read()
94
self.from_repository.lock_read()
104
self.to_branch.lock_write()
96
self.to_repository.lock_write()
108
self.to_branch.unlock()
100
self.to_repository.unlock()
110
self.from_branch.unlock()
102
self.from_repository.unlock()
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.
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 = []
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
136
if (self._last_revision != None and
145
137
self.to_repository.has_revision(self._last_revision)):
148
branch_from_revs = set(self.from_repository.get_ancestry(self._last_revision))
141
return self.to_repository.missing_revision_ids(self.from_repository,
143
except errors.NoSuchRevision:
150
144
raise InstallFailed([self._last_revision])
152
self.dest_last_rev = self.to_branch.last_revision()
153
branch_to_revs = set(self.to_repository.get_ancestry(self.dest_last_rev))
155
return branch_from_revs.difference(branch_to_revs)
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,
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)
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)
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())
173
164
if to_weave.numversions() > 0:
174
165
# destination has contents, must merge
181
172
to_weave = from_weave.copy()
183
174
self.to_weaves.put_weave(file_id, to_weave,
184
self.to_branch.get_transaction())
175
self.to_repository.get_transaction())
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)
197
187
if to_weave.numversions() > 0:
205
195
to_weave = from_weave.copy()
207
197
self.to_control.put_weave('inventory', to_weave,
208
self.to_branch.get_transaction())
198
self.to_repository.get_transaction())
203
class Fetcher(object):
204
"""Pull revisions and texts from one branch to another.
206
This doesn't update the destination's history; that can be done
207
separately if desired.
210
If set, pull only up to this revision_id.
214
last_revision -- if last_revision
215
is given it will be that, otherwise the last revision of
218
count_copied -- number of revisions copied
220
count_weaves -- number of file weaves copied
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))
227
self.to_branch = to_branch
228
self.from_branch = from_branch
229
self._last_revision = last_revision
231
self.pb = bzrlib.ui.ui_factory.progress_bar()
234
self.from_branch.lock_read()
236
self.to_branch.lock_write()
240
self.to_branch.unlock()
242
self.from_branch.unlock()
245
self._find_last_revision()
246
repo_fetcher = RepoFetcher(to_repository=self.to_branch.repository,
247
from_repository=self.from_branch.repository,
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
212
256
def _find_last_revision(self):
213
257
"""Find the limiting source revision.