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
18
19
from cStringIO import StringIO
22
import bzrlib.errors as errors
23
from bzrlib.errors import (InstallFailed, NoSuchRevision, WeaveError,
21
25
from bzrlib.trace import mutter, note, warning
22
26
from bzrlib.branch import Branch
23
27
from bzrlib.progress import ProgressBar
24
28
from bzrlib.xml5 import serializer_v5
25
29
from bzrlib.osutils import sha_string, split_lines
26
from bzrlib.errors import InstallFailed, NoSuchRevision, WeaveError
28
31
"""Copying of history from one branch to another.
96
99
self.failed_revisions = []
97
100
self.count_copied = 0
98
101
self.count_total = 0
102
self.count_weaves = 0
103
self.copied_file_ids = set()
101
105
self.pb = bzrlib.ui.ui_factory.progress_bar()
108
self.from_branch.lock_read()
105
self.last_revision = self._find_last_revision(last_revision)
106
except NoSuchRevision, e:
107
mutter('failed getting last revision: %s', e)
108
raise InstallFailed([last_revision])
110
self._fetch_revisions(last_revision)
112
self.from_branch.unlock()
115
def _fetch_revisions(self, last_revision):
116
self.last_revision = self._find_last_revision(last_revision)
109
117
mutter('fetch up to rev {%s}', self.last_revision)
118
if (self.last_revision is not None and
119
self.to_branch.has_revision(self.last_revision)):
111
122
revs_to_fetch = self._compare_ancestries()
112
123
except WeaveError:
185
194
len(rev.parent_ids))
186
195
self._copy_new_texts(rev_id, inv)
187
196
parents = rev.parent_ids
197
new_parents = copy(parents)
188
198
for parent in parents:
189
199
if not self.to_branch.has_revision(parent):
190
parents.pop(parents.index(parent))
191
self._copy_inventory(rev_id, inv_xml, parents)
192
self._copy_ancestry(rev_id, parents)
200
new_parents.pop(new_parents.index(parent))
201
self._copy_inventory(rev_id, inv_xml, new_parents)
193
202
self.to_branch.revision_store.add(StringIO(rev_xml), rev_id)
203
mutter('copied revision %s', rev_id)
196
205
def _copy_inventory(self, rev_id, inv_xml, parent_ids):
197
206
self.to_control.add_text('inventory', rev_id,
198
split_lines(inv_xml), parent_ids)
201
def _copy_ancestry(self, rev_id, parent_ids):
202
ancestry_lines = self.from_control.get_lines('ancestry', rev_id)
203
self.to_control.add_text('ancestry', rev_id, ancestry_lines,
207
split_lines(inv_xml), parent_ids,
208
self.to_branch.get_transaction())
207
210
def _copy_new_texts(self, rev_id, inv):
208
211
"""Copy any new texts occuring in this revision."""
209
212
# TODO: Rather than writing out weaves every time, hold them
210
213
# in memory until everything's done? But this way is nicer
211
214
# if it's interrupted.
212
215
for path, ie in inv.iter_entries():
213
if not ie.has_text():
215
if ie.revision != rev_id:
217
mutter('%s {%s} is changed in this revision',
219
self._copy_one_text(rev_id, ie.file_id)
222
def _copy_one_text(self, rev_id, file_id):
223
"""Copy one file text."""
224
mutter('copy text version {%s} of file {%s}',
226
from_weave = self.from_weaves.get_weave(file_id)
227
from_idx = from_weave.lookup(rev_id)
228
from_parents = map(from_weave.idx_to_name, from_weave.parents(from_idx))
229
text_lines = from_weave.get(from_idx)
230
to_weave = self.to_weaves.get_weave_or_empty(file_id)
231
to_parents = map(to_weave.lookup, from_parents)
232
# it's ok to add even if the text is already there
233
to_weave.add(rev_id, to_parents, text_lines)
234
self.to_weaves.put_weave(file_id, to_weave)
235
self.count_texts += 1
216
self._copy_one_weave(rev_id, ie.file_id, ie.revision)
218
def _copy_one_weave(self, rev_id, file_id, text_revision):
219
"""Copy one file weave, esuring the result contains text_revision."""
220
to_weave = self.to_weaves.get_weave_or_empty(file_id,
221
self.to_branch.get_transaction())
222
if text_revision in to_weave:
224
from_weave = self.from_weaves.get_weave(file_id,
225
self.from_branch.get_transaction())
226
if text_revision not in from_weave:
227
raise MissingText(self.from_branch, text_revision, file_id)
228
mutter('copy file {%s} modified in {%s}', file_id, rev_id)
230
to_weave.join(from_weave)
231
except errors.WeaveParentMismatch:
232
to_weave.reweave(from_weave)
233
self.to_weaves.put_weave(file_id, to_weave,
234
self.to_branch.get_transaction())
235
self.count_weaves += 1
236
self.copied_file_ids.add(file_id)
237
mutter('copied file {%s}', file_id)