~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/missing.py

(vila) Forbid more operations on ReadonlyTransportDecorator (Vincent Ladeuil)

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""Display what revisions are missing in 'other' from 'this' and vice versa."""
18
18
 
19
 
from bzrlib.log import (
20
 
    LogRevision,
 
19
from __future__ import absolute_import
 
20
 
 
21
from bzrlib import (
 
22
    log,
 
23
    symbol_versioning,
21
24
    )
22
 
 
23
 
 
24
 
def iter_log_revisions(revisions, revision_source, verbose):
25
 
    last_tree = revision_source.revision_tree(None)
 
25
import bzrlib.revision as _mod_revision
 
26
 
 
27
 
 
28
def iter_log_revisions(revisions, revision_source, verbose, rev_tag_dict=None):
 
29
    last_tree = revision_source.revision_tree(_mod_revision.NULL_REVISION)
26
30
    last_rev_id = None
27
 
    for revno, rev_id in revisions:
 
31
 
 
32
    if rev_tag_dict is None:
 
33
        rev_tag_dict = {}
 
34
    for rev in revisions:
 
35
        # We need the following for backward compatibilty (hopefully
 
36
        # this will be deprecated soon :-/) -- vila 080911
 
37
        if len(rev) == 2:
 
38
            revno, rev_id = rev
 
39
            merge_depth = 0
 
40
        else:
 
41
            revno, rev_id, merge_depth = rev
28
42
        rev = revision_source.get_revision(rev_id)
29
43
        if verbose:
30
 
            remote_tree = revision_source.revision_tree(rev_id)
31
 
            parent_rev_id = rev.parent_ids[0]
32
 
            if last_rev_id == parent_rev_id:
33
 
                parent_tree = last_tree
34
 
            else:
35
 
                parent_tree = revision_source.revision_tree(parent_rev_id)
36
 
            revision_tree = revision_source.revision_tree(rev_id)
37
 
            last_rev_id = rev_id
38
 
            last_tree = revision_tree
39
 
            delta = revision_tree.changes_from(parent_tree)
 
44
            delta = revision_source.get_revision_delta(rev_id)
40
45
        else:
41
46
            delta = None
42
 
        yield LogRevision(rev, revno, delta=delta)
43
 
 
44
 
 
45
 
def find_unmerged(local_branch, remote_branch, restrict='all'):
 
47
        yield log.LogRevision(rev, revno, merge_depth, delta=delta,
 
48
                              tags=rev_tag_dict.get(rev_id))
 
49
 
 
50
 
 
51
def find_unmerged(local_branch, remote_branch, restrict='all',
 
52
                  include_merged=None, backward=False,
 
53
                  local_revid_range=None, remote_revid_range=None,
 
54
                  include_merges=symbol_versioning.DEPRECATED_PARAMETER):
46
55
    """Find revisions from each side that have not been merged.
47
56
 
48
57
    :param local_branch: Compare the history of local_branch
52
61
        unique revisions from both sides. If 'local', we will return None
53
62
        for the remote revisions, similarly if 'remote' we will return None for
54
63
        the local revisions.
 
64
    :param include_merged: Show mainline revisions only if False,
 
65
        all revisions otherwise.
 
66
    :param backward: Show oldest versions first when True, newest versions
 
67
        first when False.
 
68
    :param local_revid_range: Revision-id range for filtering local_branch
 
69
        revisions (lower bound, upper bound)
 
70
    :param remote_revid_range: Revision-id range for filtering remote_branch
 
71
        revisions (lower bound, upper bound)
 
72
    :param include_merges: Deprecated historical alias for include_merged
55
73
 
56
74
    :return: A list of [(revno, revision_id)] for the mainline revisions on
57
75
        each side.
58
76
    """
 
77
    if symbol_versioning.deprecated_passed(include_merges):
 
78
        symbol_versioning.warn(
 
79
            'include_merges was deprecated in 2.5.'
 
80
            ' Use include_merged instead.',
 
81
            DeprecationWarning, stacklevel=2)
 
82
        if include_merged is None:
 
83
            include_merged = include_merges
 
84
    if include_merged is None:
 
85
        include_merged = False
59
86
    local_branch.lock_read()
60
87
    try:
61
88
        remote_branch.lock_read()
62
89
        try:
63
 
            return _find_unmerged(local_branch,
64
 
                remote_branch, restrict=restrict)
 
90
            return _find_unmerged(
 
91
                local_branch, remote_branch, restrict=restrict,
 
92
                include_merged=include_merged, backward=backward,
 
93
                local_revid_range=local_revid_range,
 
94
                remote_revid_range=remote_revid_range)
65
95
        finally:
66
96
            remote_branch.unlock()
67
97
    finally:
68
98
        local_branch.unlock()
69
99
 
70
100
 
71
 
def _enumerate_mainline(ancestry, graph, tip_revno, tip):
 
101
def _enumerate_mainline(ancestry, graph, tip_revno, tip, backward=True):
72
102
    """Enumerate the mainline revisions for these revisions.
73
103
 
74
104
    :param ancestry: A set of revisions that we care about
75
105
    :param graph: A Graph which lets us find the parents for a revision
76
106
    :param tip_revno: The revision number for the tip revision
77
107
    :param tip: The tip of mainline
 
108
    :param backward: Show oldest versions first when True, newest versions
 
109
        first when False.
78
110
    :return: [(revno, revision_id)] for all revisions in ancestry that
79
111
        are left-hand parents from tip, or None if ancestry is None.
80
112
    """
95
127
        parents = parent_map.get(cur)
96
128
        if not parents:
97
129
            break # Ghost, we are done
98
 
        mainline.append((cur_revno, cur))
 
130
        mainline.append((str(cur_revno), cur))
99
131
        cur = parents[0]
100
132
        cur_revno -= 1
101
 
    mainline.reverse()
 
133
    if not backward:
 
134
        mainline.reverse()
102
135
    return mainline
103
136
 
104
137
 
105
 
def _find_unmerged(local_branch, remote_branch, restrict):
 
138
def _enumerate_with_merges(branch, ancestry, graph, tip_revno, tip,
 
139
                           backward=True):
 
140
    """Enumerate the revisions for the ancestry.
 
141
 
 
142
    :param branch: The branch we care about
 
143
    :param ancestry: A set of revisions that we care about
 
144
    :param graph: A Graph which lets us find the parents for a revision
 
145
    :param tip_revno: The revision number for the tip revision
 
146
    :param tip: The tip of the ancsetry
 
147
    :param backward: Show oldest versions first when True, newest versions
 
148
        first when False.
 
149
    :return: [(revno, revision_id)] for all revisions in ancestry that
 
150
        are parents from tip, or None if ancestry is None.
 
151
    """
 
152
    if ancestry is None:
 
153
        return None
 
154
    if not ancestry: #Empty ancestry, no need to do any work
 
155
        return []
 
156
 
 
157
    merge_sorted_revisions = branch.iter_merge_sorted_revisions()
 
158
    # Now that we got the correct revnos, keep only the relevant
 
159
    # revisions.
 
160
    merge_sorted_revisions = [
 
161
        # log.reverse_by_depth expects seq_num to be present, but it is
 
162
        # stripped by iter_merge_sorted_revisions()
 
163
        (0, revid, n, d, e) for revid, n, d, e in merge_sorted_revisions
 
164
        if revid in ancestry]
 
165
    if not backward:
 
166
        merge_sorted_revisions = log.reverse_by_depth(merge_sorted_revisions)
 
167
    revline = []
 
168
    for seq, rev_id, merge_depth, revno, end_of_merge in merge_sorted_revisions:
 
169
        revline.append(('.'.join(map(str, revno)), rev_id, merge_depth))
 
170
    return revline
 
171
 
 
172
 
 
173
def _filter_revs(graph, revs, revid_range):
 
174
    if revid_range is None or revs is None:
 
175
        return revs
 
176
    return [rev for rev in revs
 
177
        if graph.is_between(rev[1], revid_range[0], revid_range[1])]
 
178
 
 
179
 
 
180
def _find_unmerged(local_branch, remote_branch, restrict,
 
181
                   include_merged, backward,
 
182
                   local_revid_range=None, remote_revid_range=None):
106
183
    """See find_unmerged.
107
184
 
108
185
    The branches should already be locked before entering.
112
189
    if local_revno == remote_revno and local_revision_id == remote_revision_id:
113
190
        # A simple shortcut when the tips are at the same point
114
191
        return [], []
115
 
    graph = local_branch.repository.get_graph(
116
 
                remote_branch.repository)
 
192
    graph = local_branch.repository.get_graph(remote_branch.repository)
117
193
    if restrict == 'remote':
118
194
        local_extra = None
119
 
        remote_extra = graph.find_unique_ancestors(
120
 
            remote_revision_id, [local_revision_id])
 
195
        remote_extra = graph.find_unique_ancestors(remote_revision_id,
 
196
                                                   [local_revision_id])
121
197
    elif restrict == 'local':
122
198
        remote_extra = None
123
 
        local_extra = graph.find_unique_ancestors(
124
 
            local_revision_id, [remote_revision_id])
 
199
        local_extra = graph.find_unique_ancestors(local_revision_id,
 
200
                                                  [remote_revision_id])
125
201
    else:
126
202
        if restrict != 'all':
127
203
            raise ValueError('param restrict not one of "all", "local",'
128
204
                             ' "remote": %r' % (restrict,))
129
 
        local_extra, remote_extra = graph.find_difference(
130
 
            local_revision_id, remote_revision_id)
131
 
    # Now that we have unique ancestors, compute just the mainline, and
132
 
    # generate revnos for them.
133
 
    local_mainline = _enumerate_mainline(local_extra, graph, local_revno,
134
 
                                         local_revision_id)
135
 
    remote_mainline = _enumerate_mainline(remote_extra, graph, remote_revno,
136
 
                                          remote_revision_id)
137
 
    return local_mainline, remote_mainline
 
205
        local_extra, remote_extra = graph.find_difference(local_revision_id,
 
206
                                                          remote_revision_id)
 
207
    if include_merged:
 
208
        locals = _enumerate_with_merges(local_branch, local_extra,
 
209
                                        graph, local_revno,
 
210
                                        local_revision_id, backward)
 
211
        remotes = _enumerate_with_merges(remote_branch, remote_extra,
 
212
                                         graph, remote_revno,
 
213
                                         remote_revision_id, backward)
 
214
    else:
 
215
        # Now that we have unique ancestors, compute just the mainline, and
 
216
        # generate revnos for them.
 
217
        locals = _enumerate_mainline(local_extra, graph, local_revno,
 
218
                                     local_revision_id, backward)
 
219
        remotes = _enumerate_mainline(remote_extra, graph, remote_revno,
 
220
                                      remote_revision_id, backward)
 
221
    return _filter_revs(graph, locals, local_revid_range), _filter_revs(graph,
 
222
        remotes, remote_revid_range)
138
223
 
139
224
 
140
225
def sorted_revisions(revisions, history_map):