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=NULL_REVISION, 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 None:
134
# explicit limit of None
136
if (self._last_revision != NULL_REVISION 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
if self._last_revision is NULL_REVISION:
142
branch_from_revs = set(self.from_repository.all_revision_ids() +
145
branch_from_revs = set(
146
self.from_repository.get_ancestry(self._last_revision))
147
except errors.NoSuchRevision:
150
148
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))
150
branch_to_revs = set(self.to_repository.all_revision_ids() + [None])
155
151
return branch_from_revs.difference(branch_to_revs)
157
153
def _fetch_revision_texts(self, revs):
158
154
self.to_repository.revision_store.copy_multi(
159
self.from_repository.revision_store, revs)
155
self.from_repository.revision_store,
161
159
def _fetch_weave_texts(self, revs):
162
file_ids = self.from_branch.fileid_involved_by_set(revs)
160
file_ids = self.from_repository.fileid_involved_by_set(revs)
164
162
num_file_ids = len(file_ids)
165
163
for file_id in file_ids:
166
164
self.pb.update("merge weave merge", count, num_file_ids)
168
166
to_weave = self.to_weaves.get_weave_or_empty(file_id,
169
self.to_branch.get_transaction())
167
self.to_repository.get_transaction())
170
168
from_weave = self.from_weaves.get_weave(file_id,
171
self.from_branch.get_transaction())
169
self.from_repository.get_transaction())
173
171
if to_weave.numversions() > 0:
174
172
# destination has contents, must merge
201
199
to_weave = from_weave.copy()
203
201
self.to_control.put_weave('inventory', to_weave,
204
self.to_branch.get_transaction())
202
self.to_repository.get_transaction())
207
class Fetcher(object):
208
"""Pull revisions and texts from one branch to another.
210
This doesn't update the destination's history; that can be done
211
separately if desired.
214
If set, pull only up to this revision_id.
218
last_revision -- if last_revision
219
is given it will be that, otherwise the last revision of
222
count_copied -- number of revisions copied
224
count_weaves -- number of file weaves copied
226
def __init__(self, to_branch, from_branch, last_revision=None, pb=None):
227
if to_branch.base == from_branch.base:
228
raise Exception("can't fetch from a branch to itself %s, %s" %
229
(from_branch.base, to_branch.base))
231
self.to_branch = to_branch
232
self.from_branch = from_branch
233
self._last_revision = last_revision
235
self.pb = bzrlib.ui.ui_factory.progress_bar()
238
self.from_branch.lock_read()
240
self.to_branch.lock_write()
244
self.to_branch.unlock()
246
self.from_branch.unlock()
249
self._find_last_revision()
250
repo_fetcher = RepoFetcher(to_repository=self.to_branch.repository,
251
from_repository=self.from_branch.repository,
253
last_revision=self._last_revision)
254
self.failed_revisions = repo_fetcher.failed_revisions
255
self.count_copied = repo_fetcher.count_copied
256
self.count_total = repo_fetcher.count_total
257
self.count_weaves = repo_fetcher.count_weaves
258
self.copied_file_ids = repo_fetcher.copied_file_ids
208
260
def _find_last_revision(self):
209
261
"""Find the limiting source revision.