bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 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 | |
| 23 | from bzrlib.errors import InstallFailed, NoSuchRevision, WeaveError | |
| 1231
by Martin Pool - more progress on fetch on top of weaves | 24 | from bzrlib.trace import mutter, note, warning | 
| 1352
by Martin Pool - store control weaves in .bzr/, not mixed in with file weaves | 25 | 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 | 26 | from bzrlib.progress import ProgressBar | 
| 1231
by Martin Pool - more progress on fetch on top of weaves | 27 | from bzrlib.xml5 import serializer_v5 | 
| 28 | from bzrlib.osutils import sha_string, split_lines | |
| 29 | ||
| 30 | """Copying of history from one branch to another.
 | |
| 31 | ||
| 32 | The basic plan is that every branch knows the history of everything
 | |
| 33 | that has merged into it.  As the first step of a merge, pull, or
 | |
| 34 | branch operation we copy history from the source into the destination
 | |
| 35 | branch.
 | |
| 36 | ||
| 37 | The copying is done in a slightly complicated order.  We don't want to
 | |
| 38 | add a revision to the store until everything it refers to is also
 | |
| 39 | stored, so that if a revision is present we can totally recreate it.
 | |
| 40 | However, we can't know what files are included in a revision until we
 | |
| 41 | read its inventory.  Therefore, we first pull the XML and hold it in
 | |
| 42 | memory until we've updated all of the files referenced.
 | |
| 43 | """
 | |
| 44 | ||
| 45 | # TODO: Avoid repeatedly opening weaves so many times.
 | |
| 974.1.27
by aaron.bentley at utoronto Initial greedy fetch work | 46 | |
| 1238
by Martin Pool - remove a lot of dead code from fetch | 47 | # XXX: This doesn't handle ghost (not present in branch) revisions at
 | 
| 1240
by Martin Pool - clean up fetch code and add progress bar | 48 | # all yet.  I'm not sure they really should be supported.
 | 
| 49 | ||
| 1262
by Martin Pool - fetch should also copy ancestry records | 50 | # NOTE: This doesn't copy revisions which may be present but not
 | 
| 51 | # 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 | 52 | |
| 53 | # - get a list of revisions that need to be pulled in
 | |
| 54 | # - for each one, pull in that revision file
 | |
| 55 | #   and get the inventory, and store the inventory with right
 | |
| 56 | #   parents.
 | |
| 57 | # - and get the ancestry, and store that with right parents too
 | |
| 58 | # - and keep a note of all file ids and version seen
 | |
| 59 | # - then go through all files; for each one get the weave,
 | |
| 60 | #   and add in all file versions
 | |
| 61 | ||
| 62 | ||
| 1219
by Martin Pool - BROKEN: start refactoring fetch code to work well with weaves | 63 | |
| 1260
by Martin Pool - some updates for fetch/update function | 64 | 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 | 65 | f = Fetcher(to_branch, from_branch, revision, pb) | 
| 66 | return f.count_copied, f.failed_revisions | |
| 67 | ||
| 68 | ||
| 1265
by Martin Pool - add function-style synonym 'fetch' | 69 | |
| 1219
by Martin Pool - BROKEN: start refactoring fetch code to work well with weaves | 70 | class Fetcher(object): | 
| 1260
by Martin Pool - some updates for fetch/update function | 71 | """Pull revisions and texts from one branch to another. | 
| 72 | ||
| 73 |     This doesn't update the destination's history; that can be done
 | |
| 74 |     separately if desired.  
 | |
| 1231
by Martin Pool - more progress on fetch on top of weaves | 75 | |
| 76 |     revision_limit
 | |
| 77 |         If set, pull only up to this revision_id.
 | |
| 1260
by Martin Pool - some updates for fetch/update function | 78 | |
| 79 |     After running:
 | |
| 80 | ||
| 81 |     last_revision -- if last_revision
 | |
| 82 |         is given it will be that, otherwise the last revision of
 | |
| 83 |         from_branch
 | |
| 84 | ||
| 85 |     count_copied -- number of revisions copied
 | |
| 86 | ||
| 1405
by Robert Collins remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave | 87 |     count_weaves -- number of file weaves copied
 | 
| 1260
by Martin Pool - some updates for fetch/update function | 88 |     """
 | 
| 89 | def __init__(self, to_branch, from_branch, last_revision=None, pb=None): | |
| 1393.1.17
by Martin Pool - add assertion to fetch | 90 | if to_branch == from_branch: | 
| 91 | raise Exception("can't fetch from a branch to itself") | |
| 1219
by Martin Pool - BROKEN: start refactoring fetch code to work well with weaves | 92 | self.to_branch = to_branch | 
| 1260
by Martin Pool - some updates for fetch/update function | 93 | self.to_weaves = to_branch.weave_store | 
| 1392
by Robert Collins reinstate testfetch test case | 94 | self.to_control = to_branch.control_weaves | 
| 1219
by Martin Pool - BROKEN: start refactoring fetch code to work well with weaves | 95 | self.from_branch = from_branch | 
| 1260
by Martin Pool - some updates for fetch/update function | 96 | self.from_weaves = from_branch.weave_store | 
| 1392
by Robert Collins reinstate testfetch test case | 97 | self.from_control = from_branch.control_weaves | 
| 1231
by Martin Pool - more progress on fetch on top of weaves | 98 | self.failed_revisions = [] | 
| 99 | self.count_copied = 0 | |
| 1240
by Martin Pool - clean up fetch code and add progress bar | 100 | 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 | 101 | self.count_weaves = 0 | 
| 1404
by Robert Collins only pull remote text weaves once per fetch operation | 102 | self.copied_file_ids = set() | 
| 1219
by Martin Pool - BROKEN: start refactoring fetch code to work well with weaves | 103 | if pb is None: | 
| 104 | self.pb = bzrlib.ui.ui_factory.progress_bar() | |
| 105 | else: | |
| 106 | self.pb = pb | |
| 1437
by Robert Collins lock during fetch, which is a separate code path to the special case of cloning | 107 | self.from_branch.lock_read() | 
| 1392
by Robert Collins reinstate testfetch test case | 108 | try: | 
| 1425
by Robert Collins merge from Aaron - unbreaks open_containing and the fetch progress bar | 109 | self._fetch_revisions(last_revision) | 
| 1185.12.15
by Aaron Bentley Cleared progress bar properly after fetch | 110 | finally: | 
| 1437
by Robert Collins lock during fetch, which is a separate code path to the special case of cloning | 111 | self.from_branch.unlock() | 
| 1185.12.15
by Aaron Bentley Cleared progress bar properly after fetch | 112 | self.pb.clear() | 
| 1231
by Martin Pool - more progress on fetch on top of weaves | 113 | |
| 1425
by Robert Collins merge from Aaron - unbreaks open_containing and the fetch progress bar | 114 | def _fetch_revisions(self, last_revision): | 
| 1185.12.21
by aaron.bentley at utoronto Cleaned up Fetcher._find_last_revision | 115 | self.last_revision = self._find_last_revision(last_revision) | 
| 1425
by Robert Collins merge from Aaron - unbreaks open_containing and the fetch progress bar | 116 | 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 | 117 | if (self.last_revision is not None and | 
| 118 | self.to_branch.has_revision(self.last_revision)): | |
| 119 |             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 | 120 | try: | 
| 1425
by Robert Collins merge from Aaron - unbreaks open_containing and the fetch progress bar | 121 | revs_to_fetch = self._compare_ancestries() | 
| 122 | except WeaveError: | |
| 123 | raise InstallFailed([self.last_revision]) | |
| 124 | self._copy_revisions(revs_to_fetch) | |
| 125 | self.new_ancestry = revs_to_fetch | |
| 1240
by Martin Pool - clean up fetch code and add progress bar | 126 | |
| 1260
by Martin Pool - some updates for fetch/update function | 127 | def _find_last_revision(self, last_revision): | 
| 1240
by Martin Pool - clean up fetch code and add progress bar | 128 | """Find the limiting source revision. | 
| 129 | ||
| 130 |         Every ancestor of that revision will be merged across.
 | |
| 131 | ||
| 132 |         Returns the revision_id, or returns None if there's no history
 | |
| 133 |         in the source branch."""
 | |
| 1185.12.21
by aaron.bentley at utoronto Cleaned up Fetcher._find_last_revision | 134 | if last_revision: | 
| 135 | return last_revision | |
| 1240
by Martin Pool - clean up fetch code and add progress bar | 136 | self.pb.update('get source history') | 
| 137 | from_history = self.from_branch.revision_history() | |
| 138 | self.pb.update('get destination history') | |
| 1185.12.21
by aaron.bentley at utoronto Cleaned up Fetcher._find_last_revision | 139 | if from_history: | 
| 1240
by Martin Pool - clean up fetch code and add progress bar | 140 | return from_history[-1] | 
| 141 | else: | |
| 142 | return None # no history in the source branch | |
| 1231
by Martin Pool - more progress on fetch on top of weaves | 143 | |
| 144 | ||
| 145 | def _compare_ancestries(self): | |
| 146 | """Get a list of revisions that must be copied. | |
| 147 | ||
| 148 |         That is, every revision that's in the ancestry of the source
 | |
| 149 |         branch and not in the destination branch."""
 | |
| 1240
by Martin Pool - clean up fetch code and add progress bar | 150 | self.pb.update('get source ancestry') | 
| 1260
by Martin Pool - some updates for fetch/update function | 151 | self.from_ancestry = self.from_branch.get_ancestry(self.last_revision) | 
| 1240
by Martin Pool - clean up fetch code and add progress bar | 152 | |
| 1241
by Martin Pool - rename last_patch to last_revision | 153 | dest_last_rev = self.to_branch.last_revision() | 
| 1240
by Martin Pool - clean up fetch code and add progress bar | 154 | self.pb.update('get destination ancestry') | 
| 155 | if dest_last_rev: | |
| 156 | dest_ancestry = self.to_branch.get_ancestry(dest_last_rev) | |
| 157 | else: | |
| 158 | dest_ancestry = [] | |
| 159 | ss = set(dest_ancestry) | |
| 1231
by Martin Pool - more progress on fetch on top of weaves | 160 | to_fetch = [] | 
| 161 | for rev_id in self.from_ancestry: | |
| 162 | if rev_id not in ss: | |
| 163 | to_fetch.append(rev_id) | |
| 1219
by Martin Pool - BROKEN: start refactoring fetch code to work well with weaves | 164 | mutter('need to get revision {%s}', rev_id) | 
| 1231
by Martin Pool - more progress on fetch on top of weaves | 165 | mutter('need to get %d revisions in total', len(to_fetch)) | 
| 1240
by Martin Pool - clean up fetch code and add progress bar | 166 | self.count_total = len(to_fetch) | 
| 1231
by Martin Pool - more progress on fetch on top of weaves | 167 | return to_fetch | 
| 168 | ||
| 169 | def _copy_revisions(self, revs_to_fetch): | |
| 1240
by Martin Pool - clean up fetch code and add progress bar | 170 | i = 0 | 
| 1231
by Martin Pool - more progress on fetch on top of weaves | 171 | for rev_id in revs_to_fetch: | 
| 1261
by Martin Pool - new method Branch.has_revision | 172 | i += 1 | 
| 1390
by Robert Collins pair programming worx... merge integration and weave | 173 | if rev_id is None: | 
| 174 |                 continue
 | |
| 1261
by Martin Pool - new method Branch.has_revision | 175 | if self.to_branch.has_revision(rev_id): | 
| 176 |                 continue
 | |
| 1240
by Martin Pool - clean up fetch code and add progress bar | 177 | self.pb.update('fetch revision', i, self.count_total) | 
| 1231
by Martin Pool - more progress on fetch on top of weaves | 178 | self._copy_one_revision(rev_id) | 
| 1260
by Martin Pool - some updates for fetch/update function | 179 | self.count_copied += 1 | 
| 1231
by Martin Pool - more progress on fetch on top of weaves | 180 | |
| 181 | ||
| 182 | def _copy_one_revision(self, rev_id): | |
| 183 | """Copy revision and everything referenced by it.""" | |
| 184 | mutter('copying revision {%s}', rev_id) | |
| 185 | rev_xml = self.from_branch.get_revision_xml(rev_id) | |
| 186 | inv_xml = self.from_branch.get_inventory_xml(rev_id) | |
| 187 | rev = serializer_v5.read_revision_from_string(rev_xml) | |
| 188 | inv = serializer_v5.read_inventory_from_string(inv_xml) | |
| 189 | assert rev.revision_id == rev_id | |
| 190 | assert rev.inventory_sha1 == sha_string(inv_xml) | |
| 191 | mutter(' commiter %s, %d parents', | |
| 192 | rev.committer, | |
| 1313
by Martin Pool - rename to Revision.parent_ids to avoid confusion with old usage | 193 | len(rev.parent_ids)) | 
| 1231
by Martin Pool - more progress on fetch on top of weaves | 194 | self._copy_new_texts(rev_id, inv) | 
| 1092.2.26
by Robert Collins fetch should work with ghosts | 195 | parents = rev.parent_ids | 
| 1480
by Robert Collins BUGFIX: fetch was not skipping all missing parents for inventory insertion | 196 | new_parents = copy(parents) | 
| 1092.2.26
by Robert Collins fetch should work with ghosts | 197 | for parent in parents: | 
| 198 | if not self.to_branch.has_revision(parent): | |
| 1480
by Robert Collins BUGFIX: fetch was not skipping all missing parents for inventory insertion | 199 | new_parents.pop(new_parents.index(parent)) | 
| 200 | self._copy_inventory(rev_id, inv_xml, new_parents) | |
| 1262
by Martin Pool - fetch should also copy ancestry records | 201 | self.to_branch.revision_store.add(StringIO(rev_xml), rev_id) | 
| 1404
by Robert Collins only pull remote text weaves once per fetch operation | 202 | mutter('copied revision %s', rev_id) | 
| 1262
by Martin Pool - fetch should also copy ancestry records | 203 | |
| 204 | def _copy_inventory(self, rev_id, inv_xml, parent_ids): | |
| 1352
by Martin Pool - store control weaves in .bzr/, not mixed in with file weaves | 205 | self.to_control.add_text('inventory', rev_id, | 
| 1417.1.8
by Robert Collins use transactions in the weave store interface, which enables caching for log | 206 | split_lines(inv_xml), parent_ids, | 
| 207 | self.to_branch.get_transaction()) | |
| 1262
by Martin Pool - fetch should also copy ancestry records | 208 | |
| 1231
by Martin Pool - more progress on fetch on top of weaves | 209 | def _copy_new_texts(self, rev_id, inv): | 
| 210 | """Copy any new texts occuring in this revision.""" | |
| 211 |         # TODO: Rather than writing out weaves every time, hold them
 | |
| 212 |         # in memory until everything's done?  But this way is nicer
 | |
| 213 |         # if it's interrupted.
 | |
| 214 | for path, ie in inv.iter_entries(): | |
| 1092.2.22
by Robert Collins text_version and name_version unification looking reasonable | 215 | if ie.revision != rev_id: | 
| 1231
by Martin Pool - more progress on fetch on top of weaves | 216 |                 continue
 | 
| 217 | mutter('%s {%s} is changed in this revision', | |
| 218 | path, ie.file_id) | |
| 1405
by Robert Collins remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave | 219 | self._copy_one_weave(rev_id, ie.file_id) | 
| 220 | ||
| 221 | def _copy_one_weave(self, rev_id, file_id): | |
| 222 | """Copy one file weave.""" | |
| 1404
by Robert Collins only pull remote text weaves once per fetch operation | 223 | mutter('copy file {%s} modified in {%s}', file_id, rev_id) | 
| 224 | if file_id in self.copied_file_ids: | |
| 225 | mutter('file {%s} already copied', file_id) | |
| 226 |             return
 | |
| 1185.1.51
by Robert Collins merge in reweave support | 227 | from_weave = self.from_weaves.get_weave(file_id, | 
| 1417.1.8
by Robert Collins use transactions in the weave store interface, which enables caching for log | 228 | self.from_branch.get_transaction()) | 
| 229 | to_weave = self.to_weaves.get_weave_or_empty(file_id, | |
| 230 | self.to_branch.get_transaction()) | |
| 1185.13.4
by Robert Collins make reweave visible as a weave method, and quickly integrate into fetch | 231 | try: | 
| 232 | to_weave.join(from_weave) | |
| 233 | except errors.WeaveParentMismatch: | |
| 234 | to_weave.reweave(from_weave) | |
| 1417.1.8
by Robert Collins use transactions in the weave store interface, which enables caching for log | 235 | self.to_weaves.put_weave(file_id, to_weave, | 
| 236 | self.to_branch.get_transaction()) | |
| 1405
by Robert Collins remove some of the upgrade code that was duplicated with inventory_entry, and give all inventory entries a weave | 237 | self.count_weaves += 1 | 
| 1404
by Robert Collins only pull remote text weaves once per fetch operation | 238 | self.copied_file_ids.add(file_id) | 
| 239 | mutter('copied file {%s}', file_id) | |
| 1265
by Martin Pool - add function-style synonym 'fetch' | 240 | |
| 241 | ||
| 242 | fetch = Fetcher |