~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/fetch.py

  • Committer: Martin Pool
  • Date: 2005-09-13 23:14:42 UTC
  • Revision ID: mbp@sourcefrog.net-20050913231442-4fe4f9c1cbb967eb
- clean up fetch code and add progress bar

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
 
import sys
18
17
import os
19
18
from cStringIO import StringIO
20
19
 
24
23
from bzrlib.progress import ProgressBar
25
24
from bzrlib.xml5 import serializer_v5
26
25
from bzrlib.osutils import sha_string, split_lines
 
26
from bzrlib.errors import NoSuchRevision
27
27
 
28
28
"""Copying of history from one branch to another.
29
29
 
43
43
# TODO: Avoid repeatedly opening weaves so many times.
44
44
 
45
45
# XXX: This doesn't handle ghost (not present in branch) revisions at
46
 
# all yet.
 
46
# all yet.  I'm not sure they really should be supported.
 
47
 
 
48
# TODO: This doesn't handle revisions which may be present but not
 
49
# merged into the last revision.
47
50
 
48
51
# - get a list of revisions that need to be pulled in
49
52
# - for each one, pull in that revision file
70
73
    def __init__(self, to_branch, from_branch, revision_limit=None, pb=None):
71
74
        self.to_branch = to_branch
72
75
        self.from_branch = from_branch
73
 
        self.revision_limit = revision_limit
74
76
        self.failed_revisions = []
75
77
        self.count_copied = 0
 
78
        self.count_total = 0
76
79
        if pb is None:
77
80
            self.pb = bzrlib.ui.ui_factory.progress_bar()
78
81
        else:
79
82
            self.pb = pb
80
 
        self._load_histories()
 
83
        self.revision_limit = self._find_revision_limit(revision_limit)
81
84
        revs_to_fetch = self._compare_ancestries()
82
85
        self._copy_revisions(revs_to_fetch)
83
86
 
84
 
    def _load_histories(self):
85
 
        """Load histories of both branches, up to the limit."""
86
 
        self.from_history = self.from_branch.revision_history()
87
 
        self.to_history = self.to_branch.revision_history()
88
 
        if self.revision_limit:
89
 
            assert isinstance(revision_limit, basestring)
90
 
            try:
91
 
                rev_index = self.from_history.index(revision_limit)
92
 
            except ValueError:
93
 
                rev_index = None
94
 
            if rev_index is not None:
95
 
                self.from_history = self.from_history[:rev_index + 1]
 
87
        
 
88
 
 
89
    def _find_revision_limit(self, revision_limit):
 
90
        """Find the limiting source revision.
 
91
 
 
92
        Every ancestor of that revision will be merged across.
 
93
 
 
94
        Returns the revision_id, or returns None if there's no history
 
95
        in the source branch."""
 
96
        self.pb.update('get source history')
 
97
        from_history = self.from_branch.revision_history()
 
98
        self.pb.update('get destination history')
 
99
        if revision_limit:
 
100
            if revision_limit not in from_history:
 
101
                raise NoSuchRevision(self.from_branch, revision_limit)
96
102
            else:
97
 
                self.from_history = [revision]
 
103
                return revision_limit
 
104
        elif from_history:
 
105
            return from_history[-1]
 
106
        else:
 
107
            return None                 # no history in the source branch
98
108
            
99
109
 
100
110
    def _compare_ancestries(self):
102
112
 
103
113
        That is, every revision that's in the ancestry of the source
104
114
        branch and not in the destination branch."""
105
 
        if self.from_history:
106
 
            self.from_ancestry = self.from_branch.get_ancestry(self.from_history[-1])
107
 
        else:
108
 
            self.from_ancestry = []
109
 
        if self.to_history:
110
 
            self.to_history = self.to_branch.get_ancestry(self.to_history[-1])
111
 
        else:
112
 
            self.to_history = []
113
 
        ss = set(self.to_history)
 
115
        self.pb.update('get source ancestry')
 
116
        self.from_ancestry = self.from_branch.get_ancestry(self.revision_limit)
 
117
 
 
118
        dest_last_rev = self.to_branch.last_patch()
 
119
        self.pb.update('get destination ancestry')
 
120
        if dest_last_rev:
 
121
            dest_ancestry = self.to_branch.get_ancestry(dest_last_rev)
 
122
        else:
 
123
            dest_ancestry = []
 
124
        ss = set(dest_ancestry)
114
125
        to_fetch = []
115
126
        for rev_id in self.from_ancestry:
116
127
            if rev_id not in ss:
117
128
                to_fetch.append(rev_id)
118
129
                mutter('need to get revision {%s}', rev_id)
119
130
        mutter('need to get %d revisions in total', len(to_fetch))
 
131
        self.count_total = len(to_fetch)
120
132
        return to_fetch
121
133
                
122
134
 
123
135
 
124
136
    def _copy_revisions(self, revs_to_fetch):
 
137
        i = 0
125
138
        for rev_id in revs_to_fetch:
 
139
            self.pb.update('fetch revision', i, self.count_total)
126
140
            self._copy_one_revision(rev_id)
 
141
            i += 1                           
127
142
 
128
143
 
129
144
    def _copy_one_revision(self, rev_id):