~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/fetch.py

Branch now uses BzrDir reasonably sanely.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
30
31
 
67
68
    return f.count_copied, f.failed_revisions
68
69
 
69
70
 
70
 
 
71
 
class Fetcher(object):
72
 
    """Pull revisions and texts from one branch to another.
73
 
 
74
 
    This doesn't update the destination's history; that can be done
75
 
    separately if desired.  
76
 
 
77
 
    revision_limit
78
 
        If set, pull only up to this revision_id.
79
 
 
80
 
    After running:
81
 
 
82
 
    last_revision -- if last_revision
83
 
        is given it will be that, otherwise the last revision of
84
 
        from_branch
85
 
 
 
71
class RepoFetcher(object):
 
72
    """Pull revisions and texts from one repository to another.
 
73
 
 
74
    last_revision
 
75
        if set, try to limit to the data this revision references.
 
76
 
 
77
    after running:
86
78
    count_copied -- number of revisions copied
87
 
 
88
79
    count_weaves -- number of file weaves copied
89
80
    """
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))
94
 
        
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
98
90
        if pb is None:
99
91
            self.pb = bzrlib.ui.ui_factory.progress_bar()
100
92
        else:
101
93
            self.pb = pb
102
 
        self.from_branch.lock_read()
 
94
        self.from_repository.lock_read()
103
95
        try:
104
 
            self.to_branch.lock_write()
 
96
            self.to_repository.lock_write()
105
97
            try:
106
98
                self.__fetch()
107
99
            finally:
108
 
                self.to_branch.unlock()
 
100
                self.to_repository.unlock()
109
101
        finally:
110
 
            self.from_branch.unlock()
 
102
            self.from_repository.unlock()
111
103
 
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.
117
109
        """
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 = []
139
129
            self.pb.clear()
140
130
 
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
 
135
            return None
 
136
        if (self._last_revision != NULL_REVISION and
145
137
            self.to_repository.has_revision(self._last_revision)):
146
 
            return
 
138
            return None
 
139
            
147
140
        try:
148
 
            branch_from_revs = set(self.from_repository.get_ancestry(self._last_revision))
149
 
        except WeaveError:
 
141
            if self._last_revision is NULL_REVISION:
 
142
                branch_from_revs = set(self.from_repository.all_revision_ids() +
 
143
                                       [None])
 
144
            else:
 
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])
151
149
 
152
 
        self.dest_last_rev = self.to_branch.last_revision()
153
 
        branch_to_revs = set(self.to_repository.get_ancestry(self.dest_last_rev))
154
 
 
 
150
        branch_to_revs = set(self.to_repository.all_revision_ids() + [None])
155
151
        return branch_from_revs.difference(branch_to_revs)
156
152
 
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,
 
156
            revs,
 
157
            pb=self.pb)
160
158
 
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)
163
161
        count = 0
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)
167
165
            count +=1
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())
172
170
 
173
171
            if to_weave.numversions() > 0:
174
172
                # destination has contents, must merge
181
179
                to_weave = from_weave.copy()
182
180
 
183
181
            self.to_weaves.put_weave(file_id, to_weave,
184
 
                self.to_branch.get_transaction())
 
182
                self.to_repository.get_transaction())
185
183
 
186
184
        self.pb.clear()
187
185
 
201
199
            to_weave = from_weave.copy()
202
200
 
203
201
        self.to_control.put_weave('inventory', to_weave,
204
 
            self.to_branch.get_transaction())
 
202
            self.to_repository.get_transaction())
205
203
 
206
204
        self.pb.clear()
207
205
 
 
206
 
 
207
class Fetcher(object):
 
208
    """Pull revisions and texts from one branch to another.
 
209
 
 
210
    This doesn't update the destination's history; that can be done
 
211
    separately if desired.  
 
212
 
 
213
    revision_limit
 
214
        If set, pull only up to this revision_id.
 
215
 
 
216
    After running:
 
217
 
 
218
    last_revision -- if last_revision
 
219
        is given it will be that, otherwise the last revision of
 
220
        from_branch
 
221
 
 
222
    count_copied -- number of revisions copied
 
223
 
 
224
    count_weaves -- number of file weaves copied
 
225
    """
 
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))
 
230
        
 
231
        self.to_branch = to_branch
 
232
        self.from_branch = from_branch
 
233
        self._last_revision = last_revision
 
234
        if pb is None:
 
235
            self.pb = bzrlib.ui.ui_factory.progress_bar()
 
236
        else:
 
237
            self.pb = pb
 
238
        self.from_branch.lock_read()
 
239
        try:
 
240
            self.to_branch.lock_write()
 
241
            try:
 
242
                self.__fetch()
 
243
            finally:
 
244
                self.to_branch.unlock()
 
245
        finally:
 
246
            self.from_branch.unlock()
 
247
 
 
248
    def __fetch(self):
 
249
        self._find_last_revision()
 
250
        repo_fetcher = RepoFetcher(to_repository=self.to_branch.repository,
 
251
                                   from_repository=self.from_branch.repository,
 
252
                                   pb=self.pb,
 
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
 
259
 
208
260
    def _find_last_revision(self):
209
261
        """Find the limiting source revision.
210
262