~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/fetch.py

  • Committer: Jelmer Vernooij
  • Date: 2005-10-02 13:14:12 UTC
  • mto: This revision was merged to the branch mainline in revision 1414.
  • Revision ID: jelmer@samba.org-20051002131412-c44d6cd10336ac94
Add test for empty commit messages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
16
16
 
17
 
from copy import copy
18
17
import os
19
18
from cStringIO import StringIO
20
19
 
21
 
import bzrlib
22
 
import bzrlib.errors as errors
23
 
from bzrlib.errors import (InstallFailed, NoSuchRevision, WeaveError,
24
 
                           MissingText)
 
20
import bzrlib.errors
25
21
from bzrlib.trace import mutter, note, warning
26
22
from bzrlib.branch import Branch
27
23
from bzrlib.progress import ProgressBar
28
24
from bzrlib.xml5 import serializer_v5
29
25
from bzrlib.osutils import sha_string, split_lines
 
26
from bzrlib.errors import InstallFailed, NoSuchRevision, WeaveError
30
27
 
31
28
"""Copying of history from one branch to another.
32
29
 
85
82
 
86
83
    count_copied -- number of revisions copied
87
84
 
88
 
    count_weaves -- number of file weaves copied
 
85
    count_texts -- number of file texts copied
89
86
    """
90
87
    def __init__(self, to_branch, from_branch, last_revision=None, pb=None):
91
88
        if to_branch == from_branch:
99
96
        self.failed_revisions = []
100
97
        self.count_copied = 0
101
98
        self.count_total = 0
102
 
        self.count_weaves = 0
103
 
        self.copied_file_ids = set()
104
 
        self.file_ids_names = {}
 
99
        self.count_texts = 0
105
100
        if pb is None:
106
101
            self.pb = bzrlib.ui.ui_factory.progress_bar()
107
102
        else:
108
103
            self.pb = pb
109
 
        self.from_branch.lock_read()
110
104
        try:
111
 
            self._fetch_revisions(last_revision)
112
 
        finally:
113
 
            self.from_branch.unlock()
114
 
            self.pb.clear()
115
 
 
116
 
    def _fetch_revisions(self, last_revision):
117
 
        self.last_revision = self._find_last_revision(last_revision)
 
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])
118
109
        mutter('fetch up to rev {%s}', self.last_revision)
119
 
        if (self.last_revision is not None and 
120
 
            self.to_branch.has_revision(self.last_revision)):
121
 
            return
122
110
        try:
123
111
            revs_to_fetch = self._compare_ancestries()
124
112
        except WeaveError:
126
114
        self._copy_revisions(revs_to_fetch)
127
115
        self.new_ancestry = revs_to_fetch
128
116
 
 
117
 
129
118
    def _find_last_revision(self, last_revision):
130
119
        """Find the limiting source revision.
131
120
 
133
122
 
134
123
        Returns the revision_id, or returns None if there's no history
135
124
        in the source branch."""
136
 
        if last_revision:
137
 
            return last_revision
138
125
        self.pb.update('get source history')
139
126
        from_history = self.from_branch.revision_history()
140
127
        self.pb.update('get destination history')
141
 
        if from_history:
 
128
        if last_revision:
 
129
            self.from_branch.get_revision(last_revision)
 
130
            return last_revision
 
131
        elif from_history:
142
132
            return from_history[-1]
143
133
        else:
144
134
            return None                 # no history in the source branch
176
166
                continue
177
167
            if self.to_branch.has_revision(rev_id):
178
168
                continue
179
 
            self.pb.update('copy revision', i, self.count_total)
 
169
            self.pb.update('fetch revision', i, self.count_total)
180
170
            self._copy_one_revision(rev_id)
181
171
            self.count_copied += 1
182
172
 
194
184
               rev.committer,
195
185
               len(rev.parent_ids))
196
186
        self._copy_new_texts(rev_id, inv)
197
 
        parents = rev.parent_ids
198
 
        new_parents = copy(parents)
199
 
        for parent in parents:
200
 
            if not self.to_branch.has_revision(parent):
201
 
                new_parents.pop(new_parents.index(parent))
202
 
        self._copy_inventory(rev_id, inv_xml, new_parents)
 
187
        self._copy_inventory(rev_id, inv_xml, rev.parent_ids)
 
188
        self._copy_ancestry(rev_id, rev.parent_ids)
203
189
        self.to_branch.revision_store.add(StringIO(rev_xml), rev_id)
204
 
        mutter('copied revision %s', rev_id)
 
190
 
205
191
 
206
192
    def _copy_inventory(self, rev_id, inv_xml, parent_ids):
207
193
        self.to_control.add_text('inventory', rev_id,
208
 
                                split_lines(inv_xml), parent_ids,
209
 
                                self.to_branch.get_transaction())
210
 
 
 
194
                                split_lines(inv_xml), parent_ids)
 
195
 
 
196
 
 
197
    def _copy_ancestry(self, rev_id, parent_ids):
 
198
        ancestry_lines = self.from_control.get_lines('ancestry', rev_id)
 
199
        self.to_control.add_text('ancestry', rev_id, ancestry_lines,
 
200
                                 parent_ids)
 
201
 
 
202
        
211
203
    def _copy_new_texts(self, rev_id, inv):
212
204
        """Copy any new texts occuring in this revision."""
213
205
        # TODO: Rather than writing out weaves every time, hold them
214
206
        # in memory until everything's done?  But this way is nicer
215
207
        # if it's interrupted.
216
208
        for path, ie in inv.iter_entries():
217
 
            self._copy_one_weave(rev_id, ie.file_id, ie.revision)
218
 
 
219
 
    def _copy_one_weave(self, rev_id, file_id, text_revision):
220
 
        """Copy one file weave, esuring the result contains text_revision."""
221
 
        # check if the revision is already there
222
 
        if file_id in self.file_ids_names.keys( ) and \
223
 
            text_revision in self.file_ids_names[file_id]:
224
 
                return        
225
 
        to_weave = self.to_weaves.get_weave_or_empty(file_id,
226
 
            self.to_branch.get_transaction())
227
 
        if not file_id in self.file_ids_names.keys( ):
228
 
            self.file_ids_names[file_id] = to_weave.names( )
229
 
        if text_revision in to_weave:
230
 
            return
231
 
        from_weave = self.from_weaves.get_weave(file_id,
232
 
            self.from_branch.get_transaction())
233
 
        if text_revision not in from_weave:
234
 
            raise MissingText(self.from_branch, text_revision, file_id)
235
 
        mutter('copy file {%s} modified in {%s}', file_id, rev_id)
236
 
 
237
 
        if to_weave.numversions() > 0:
238
 
            # destination has contents, must merge
239
 
            try:
240
 
                to_weave.join(from_weave)
241
 
            except errors.WeaveParentMismatch:
242
 
                to_weave.reweave(from_weave)
243
 
        else:
244
 
            # destination is empty, just replace it
245
 
            to_weave = from_weave.copy( )
246
 
        self.to_weaves.put_weave(file_id, to_weave,
247
 
            self.to_branch.get_transaction())
248
 
        self.count_weaves += 1
249
 
        self.copied_file_ids.add(file_id)
250
 
        self.file_ids_names[file_id] = to_weave.names()
251
 
        mutter('copied file {%s}', file_id)
 
209
            if ie.kind != 'file':
 
210
                continue
 
211
            if ie.text_version != rev_id:
 
212
                continue
 
213
            mutter('%s {%s} is changed in this revision',
 
214
                   path, ie.file_id)
 
215
            self._copy_one_text(rev_id, ie.file_id)
 
216
 
 
217
 
 
218
    def _copy_one_text(self, rev_id, file_id):
 
219
        """Copy one file text."""
 
220
        mutter('copy text version {%s} of file {%s}',
 
221
               rev_id, file_id)
 
222
        from_weave = self.from_weaves.get_weave(file_id)
 
223
        from_idx = from_weave.lookup(rev_id)
 
224
        from_parents = map(from_weave.idx_to_name, from_weave.parents(from_idx))
 
225
        text_lines = from_weave.get(from_idx)
 
226
        to_weave = self.to_weaves.get_weave_or_empty(file_id)
 
227
        to_parents = map(to_weave.lookup, from_parents)
 
228
        # it's ok to add even if the text is already there
 
229
        to_weave.add(rev_id, to_parents, text_lines)
 
230
        self.to_weaves.put_weave(file_id, to_weave)
 
231
        self.count_texts += 1
252
232
 
253
233
 
254
234
fetch = Fetcher