~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/fetch.py

  • Committer: Martin Pool
  • Date: 2005-09-15 06:35:58 UTC
  • Revision ID: mbp@sourcefrog.net-20050915063558-f3b5bae25543c922
- add assertion

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
import bzrlib.errors
21
21
from bzrlib.trace import mutter, note, warning
22
 
from bzrlib.branch import Branch
 
22
from bzrlib.branch import Branch, INVENTORY_FILEID, ANCESTRY_FILEID
23
23
from bzrlib.progress import ProgressBar
24
24
from bzrlib.xml5 import serializer_v5
25
25
from bzrlib.osutils import sha_string, split_lines
45
45
# XXX: This doesn't handle ghost (not present in branch) revisions at
46
46
# all yet.  I'm not sure they really should be supported.
47
47
 
48
 
# NOTE: This doesn't copy revisions which may be present but not
49
 
# merged into the last revision.  I'm not sure we want to do that.
 
48
# TODO: This doesn't handle revisions which may be present but not
 
49
# merged into the last revision.
50
50
 
51
51
# - get a list of revisions that need to be pulled in
52
52
# - for each one, pull in that revision file
59
59
 
60
60
 
61
61
 
62
 
def greedy_fetch(to_branch, from_branch, revision=None, pb=None):
 
62
def greedy_fetch(to_branch, from_branch, revision, pb):
63
63
    f = Fetcher(to_branch, from_branch, revision, pb)
64
64
    return f.count_copied, f.failed_revisions
65
65
 
66
66
 
67
 
 
68
67
class Fetcher(object):
69
 
    """Pull revisions and texts from one branch to another.
70
 
 
71
 
    This doesn't update the destination's history; that can be done
72
 
    separately if desired.  
 
68
    """Pull history from one branch to another.
73
69
 
74
70
    revision_limit
75
71
        If set, pull only up to this revision_id.
76
 
 
77
 
    After running:
78
 
 
79
 
    last_revision -- if last_revision
80
 
        is given it will be that, otherwise the last revision of
81
 
        from_branch
82
 
 
83
 
    count_copied -- number of revisions copied
84
 
 
85
 
    count_texts -- number of file texts copied
86
 
    """
87
 
    def __init__(self, to_branch, from_branch, last_revision=None, pb=None):
 
72
        """
 
73
    def __init__(self, to_branch, from_branch, revision_limit=None, pb=None):
88
74
        self.to_branch = to_branch
89
 
        self.to_weaves = to_branch.weave_store
90
 
        self.to_control = to_branch.control_weaves
91
75
        self.from_branch = from_branch
92
 
        self.from_weaves = from_branch.weave_store
93
 
        self.from_control = from_branch.control_weaves
94
76
        self.failed_revisions = []
95
77
        self.count_copied = 0
96
78
        self.count_total = 0
97
 
        self.count_texts = 0
98
79
        if pb is None:
99
80
            self.pb = bzrlib.ui.ui_factory.progress_bar()
100
81
        else:
101
82
            self.pb = pb
102
 
        self.last_revision = self._find_last_revision(last_revision)
103
 
        mutter('fetch up to rev {%s}', self.last_revision)
 
83
        self.revision_limit = self._find_revision_limit(revision_limit)
104
84
        revs_to_fetch = self._compare_ancestries()
105
85
        self._copy_revisions(revs_to_fetch)
106
 
        self.new_ancestry = revs_to_fetch
107
86
 
108
87
        
109
88
 
110
 
    def _find_last_revision(self, last_revision):
 
89
    def _find_revision_limit(self, revision_limit):
111
90
        """Find the limiting source revision.
112
91
 
113
92
        Every ancestor of that revision will be merged across.
117
96
        self.pb.update('get source history')
118
97
        from_history = self.from_branch.revision_history()
119
98
        self.pb.update('get destination history')
120
 
        if last_revision:
121
 
            if last_revision not in from_history:
122
 
                raise NoSuchRevision(self.from_branch, last_revision)
 
99
        if revision_limit:
 
100
            if revision_limit not in from_history:
 
101
                raise NoSuchRevision(self.from_branch, revision_limit)
123
102
            else:
124
 
                return last_revision
 
103
                return revision_limit
125
104
        elif from_history:
126
105
            return from_history[-1]
127
106
        else:
134
113
        That is, every revision that's in the ancestry of the source
135
114
        branch and not in the destination branch."""
136
115
        self.pb.update('get source ancestry')
137
 
        self.from_ancestry = self.from_branch.get_ancestry(self.last_revision)
 
116
        self.from_ancestry = self.from_branch.get_ancestry(self.revision_limit)
138
117
 
139
118
        dest_last_rev = self.to_branch.last_revision()
140
119
        self.pb.update('get destination ancestry')
157
136
    def _copy_revisions(self, revs_to_fetch):
158
137
        i = 0
159
138
        for rev_id in revs_to_fetch:
160
 
            i += 1
161
 
            if self.to_branch.has_revision(rev_id):
162
 
                continue
163
139
            self.pb.update('fetch revision', i, self.count_total)
164
140
            self._copy_one_revision(rev_id)
165
 
            self.count_copied += 1
 
141
            i += 1                           
166
142
 
167
143
 
168
144
    def _copy_one_revision(self, rev_id):
176
152
        assert rev.inventory_sha1 == sha_string(inv_xml)
177
153
        mutter('  commiter %s, %d parents',
178
154
               rev.committer,
179
 
               len(rev.parent_ids))
 
155
               len(rev.parents))
180
156
        self._copy_new_texts(rev_id, inv)
181
 
        self._copy_inventory(rev_id, inv_xml, rev.parent_ids)
182
 
        self._copy_ancestry(rev_id, rev.parent_ids)
 
157
        self.to_branch.weave_store.add_text(INVENTORY_FILEID, rev_id,
 
158
                                            split_lines(inv_xml), rev.parents)
183
159
        self.to_branch.revision_store.add(StringIO(rev_xml), rev_id)
184
160
 
185
 
 
186
 
    def _copy_inventory(self, rev_id, inv_xml, parent_ids):
187
 
        self.to_control.add_text('inventory', rev_id,
188
 
                                split_lines(inv_xml), parent_ids)
189
 
 
190
 
 
191
 
    def _copy_ancestry(self, rev_id, parent_ids):
192
 
        ancestry_lines = self.from_control.get_lines('ancestry', rev_id)
193
 
        self.to_control.add_text('ancestry', rev_id, ancestry_lines,
194
 
                                 parent_ids)
195
 
 
196
161
        
197
162
    def _copy_new_texts(self, rev_id, inv):
198
163
        """Copy any new texts occuring in this revision."""
211
176
 
212
177
    def _copy_one_text(self, rev_id, file_id):
213
178
        """Copy one file text."""
214
 
        mutter('copy text version {%s} of file {%s}',
215
 
               rev_id, file_id)
216
 
        from_weave = self.from_weaves.get_weave(file_id)
 
179
        from_weave = self.from_branch.weave_store.get_weave(file_id)
217
180
        from_idx = from_weave.lookup(rev_id)
218
181
        from_parents = map(from_weave.idx_to_name, from_weave.parents(from_idx))
219
182
        text_lines = from_weave.get(from_idx)
220
 
        to_weave = self.to_weaves.get_weave_or_empty(file_id)
 
183
        to_weave = self.to_branch.weave_store.get_weave_or_empty(file_id)
221
184
        to_parents = map(to_weave.lookup, from_parents)
222
185
        # it's ok to add even if the text is already there
223
186
        to_weave.add(rev_id, to_parents, text_lines)
224
 
        self.to_weaves.put_weave(file_id, to_weave)
225
 
        self.count_texts += 1
226
 
 
227
 
 
228
 
fetch = Fetcher
 
187
        self.to_branch.weave_store.put_weave(file_id, to_weave)