/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
# Copyright (C) 2005-2010 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
16
6379.6.1 by Jelmer Vernooij
Import absolute_import in a few places.
17
from __future__ import absolute_import
18
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
19
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
20
from .lazy_import import lazy_import
3224.5.31 by Andrew Bennetts
A couple more lazy imports, helps 'bzr log --line -r -1' a little.
21
lazy_import(globals(), """
1948.4.1 by John Arbash Meinel
Update number parsers to raise InvalidRevisionSpec. Update revno: itself so it supports negative numbers
22
import bisect
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
23
import datetime
5671.1.2 by Jelmer Vernooij
Lazy load gzip (we don't use it when doing 2a), remove some unused imports.
24
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
25
from breezy import (
5365.6.4 by Aaron Bentley
Implement mainline revision spec.
26
    branch as _mod_branch,
6630.1.1 by Jelmer Vernooij
Remove deprecated functionality.
27
    cache_utf8,
2325.2.5 by Marien Zwart
Call osutils.safe_revision_id instead of duplicating it.
28
    osutils,
1948.4.18 by John Arbash Meinel
Update branch: spec and tests
29
    revision,
5685.1.1 by Jelmer Vernooij
More lazy imports, lazy regexes in bzrlib.revisionspec.
30
    workingtree,
31
    )
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
32
from breezy.i18n import gettext
5685.1.1 by Jelmer Vernooij
More lazy imports, lazy regexes in bzrlib.revisionspec.
33
""")
34
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
35
from . import (
5685.1.1 by Jelmer Vernooij
More lazy imports, lazy regexes in bzrlib.revisionspec.
36
    errors,
5685.1.2 by Jelmer Vernooij
Merge bzr.dev.
37
    lazy_regex,
5685.1.1 by Jelmer Vernooij
More lazy imports, lazy regexes in bzrlib.revisionspec.
38
    registry,
1948.4.27 by John Arbash Meinel
Deprecate calling RevisionSpec directly, and instead use a helper function. Also merge the old RevisionSpec_int class into RevisionSpec_revno
39
    trace,
1948.4.1 by John Arbash Meinel
Update number parsers to raise InvalidRevisionSpec. Update revno: itself so it supports negative numbers
40
    )
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
41
1948.4.16 by John Arbash Meinel
Move the tests into the associated tester, remove redundant tests, some small PEP8 changes
42
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
43
class RevisionInfo(object):
2070.4.14 by John Arbash Meinel
Switch revisionspec to use the help defined as help_txt rather than the doc string
44
    """The results of applying a revision specification to a branch."""
45
46
    help_txt = """The results of applying a revision specification to a branch.
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
47
48
    An instance has two useful attributes: revno, and rev_id.
49
50
    They can also be accessed as spec[0] and spec[1] respectively,
51
    so that you can write code like:
52
    revno, rev_id = RevisionSpec(branch, spec)
53
    although this is probably going to be deprecated later.
54
55
    This class exists mostly to be the return value of a RevisionSpec,
56
    so that you can access the member you're interested in (number or id)
57
    or treat the result as a tuple.
58
    """
59
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
60
    def __init__(self, branch, revno=None, rev_id=None):
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
61
        self.branch = branch
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
62
        self._has_revno = (revno is not None)
63
        self._revno = revno
64
        self.rev_id = rev_id
65
        if self.rev_id is None and self._revno is not None:
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
66
            # allow caller to be lazy
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
67
            self.rev_id = branch.get_rev_id(self._revno)
68
69
    @property
70
    def revno(self):
71
        if not self._has_revno and self.rev_id is not None:
72
            try:
73
                self._revno = self.branch.revision_id_to_revno(self.rev_id)
74
            except errors.NoSuchRevision:
75
                self._revno = None
76
            self._has_revno = True
77
        return self._revno
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
78
6619.3.20 by Jelmer Vernooij
Apply 2to3 nonzero fix.
79
    def __bool__(self):
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
80
        if self.rev_id is None:
81
            return False
82
        # TODO: otherwise, it should depend on how I was built -
83
        # if it's in_history(branch), then check revision_history(),
84
        # if it's in_store(branch), do the check below
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
85
        return self.branch.repository.has_revision(self.rev_id)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
86
6619.3.23 by Jelmer Vernooij
Keep __nonzero__ around for Python2.
87
    __nonzero__ = __bool__
88
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
89
    def __len__(self):
90
        return 2
91
92
    def __getitem__(self, index):
93
        if index == 0: return self.revno
94
        if index == 1: return self.rev_id
95
        raise IndexError(index)
96
97
    def get(self):
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
98
        return self.branch.repository.get_revision(self.rev_id)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
99
100
    def __eq__(self, other):
101
        if type(other) not in (tuple, list, type(self)):
102
            return False
6619.3.18 by Jelmer Vernooij
Run 2to3 idioms fixer.
103
        if isinstance(other, type(self)) and self.branch is not other.branch:
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
104
            return False
105
        return tuple(self) == tuple(other)
106
107
    def __repr__(self):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
108
        return '<breezy.revisionspec.RevisionInfo object %s, %s for %r>' % (
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
109
            self.revno, self.rev_id, self.branch)
110
2220.2.3 by Martin Pool
Add tag: revision namespace.
111
    @staticmethod
6630.1.1 by Jelmer Vernooij
Remove deprecated functionality.
112
    def from_revision_id(branch, revision_id):
2220.2.3 by Martin Pool
Add tag: revision namespace.
113
        """Construct a RevisionInfo given just the id.
114
115
        Use this if you don't know or care what the revno is.
116
        """
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
117
        return RevisionInfo(branch, revno=None, rev_id=revision_id)
2220.2.3 by Martin Pool
Add tag: revision namespace.
118
1948.4.16 by John Arbash Meinel
Move the tests into the associated tester, remove redundant tests, some small PEP8 changes
119
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
120
class RevisionSpec(object):
2070.4.14 by John Arbash Meinel
Switch revisionspec to use the help defined as help_txt rather than the doc string
121
    """A parsed revision specification."""
122
123
    help_txt = """A parsed revision specification.
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
124
4569.2.3 by Matthew Fuller
Adjust the help test for the RevisionSpec class a bit to describe the
125
    A revision specification is a string, which may be unambiguous about
126
    what it represents by giving a prefix like 'date:' or 'revid:' etc,
127
    or it may have no prefix, in which case it's tried against several
128
    specifier types in sequence to determine what the user meant.
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
129
130
    Revision specs are an UI element, and they have been moved out
131
    of the branch class to leave "back-end" classes unaware of such
132
    details.  Code that gets a revno or rev_id from other code should
133
    not be using revision specs - revnos and revision ids are the
134
    accepted ways to refer to revisions internally.
135
136
    (Equivalent to the old Branch method get_revision_info())
137
    """
138
139
    prefix = None
4569.2.18 by Vincent Ladeuil
Small refactoring to unblock the submission.
140
    dwim_catchable_exceptions = (errors.InvalidRevisionSpec,)
4569.2.21 by Vincent Ladeuil
Fix some typos.
141
    """Exceptions that RevisionSpec_dwim._match_on will catch.
4569.2.18 by Vincent Ladeuil
Small refactoring to unblock the submission.
142
4569.2.21 by Vincent Ladeuil
Fix some typos.
143
    If the revspec is part of ``dwim_revspecs``, it may be tried with an
144
    invalid revspec and raises some exception. The exceptions mentioned here
145
    will not be reported to the user but simply ignored without stopping the
146
    dwim processing.
4569.2.18 by Vincent Ladeuil
Small refactoring to unblock the submission.
147
    """
1948.4.33 by John Arbash Meinel
Switch from get_revision_spec() to RevisionSpec.from_string() (as advised by Martin)
148
149
    @staticmethod
150
    def from_string(spec):
151
        """Parse a revision spec string into a RevisionSpec object.
152
153
        :param spec: A string specified by the user
154
        :return: A RevisionSpec object that understands how to parse the
155
            supplied notation.
156
        """
157
        if not isinstance(spec, (type(None), basestring)):
158
            raise TypeError('error')
159
160
        if spec is None:
161
            return RevisionSpec(None, _internal=True)
3966.2.1 by Jelmer Vernooij
Register revision specifiers in a registry.
162
        match = revspec_registry.get_prefix(spec)
163
        if match is not None:
164
            spectype, specsuffix = match
165
            trace.mutter('Returning RevisionSpec %s for %s',
166
                         spectype.__name__, spec)
167
            return spectype(spec, _internal=True)
1948.4.33 by John Arbash Meinel
Switch from get_revision_spec() to RevisionSpec.from_string() (as advised by Martin)
168
        else:
4569.2.18 by Vincent Ladeuil
Small refactoring to unblock the submission.
169
            # Otherwise treat it as a DWIM, build the RevisionSpec object and
170
            # wait for _match_on to be called.
4569.2.1 by Matthew Fuller
Implement a DWIM revspec type and use it to allow simpler user
171
            return RevisionSpec_dwim(spec, _internal=True)
1948.4.27 by John Arbash Meinel
Deprecate calling RevisionSpec directly, and instead use a helper function. Also merge the old RevisionSpec_int class into RevisionSpec_revno
172
173
    def __init__(self, spec, _internal=False):
174
        """Create a RevisionSpec referring to the Null revision.
175
176
        :param spec: The original spec supplied by the user
177
        :param _internal: Used to ensure that RevisionSpec is not being
1948.4.33 by John Arbash Meinel
Switch from get_revision_spec() to RevisionSpec.from_string() (as advised by Martin)
178
            called directly. Only from RevisionSpec.from_string()
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
179
        """
1948.4.27 by John Arbash Meinel
Deprecate calling RevisionSpec directly, and instead use a helper function. Also merge the old RevisionSpec_int class into RevisionSpec_revno
180
        if not _internal:
6630.1.1 by Jelmer Vernooij
Remove deprecated functionality.
181
            raise AssertionError(
182
                'Creating a RevisionSpec directly is not supported. '
183
                'Use RevisionSpec.from_string() instead.')
1948.4.27 by John Arbash Meinel
Deprecate calling RevisionSpec directly, and instead use a helper function. Also merge the old RevisionSpec_int class into RevisionSpec_revno
184
        self.user_spec = spec
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
185
        if self.prefix and spec.startswith(self.prefix):
186
            spec = spec[len(self.prefix):]
187
        self.spec = spec
188
189
    def _match_on(self, branch, revs):
1948.4.27 by John Arbash Meinel
Deprecate calling RevisionSpec directly, and instead use a helper function. Also merge the old RevisionSpec_int class into RevisionSpec_revno
190
        trace.mutter('Returning RevisionSpec._match_on: None')
3298.2.11 by Aaron Bentley
Update tests for null:, clea up slightly
191
        return RevisionInfo(branch, None, None)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
192
193
    def _match_on_and_check(self, branch, revs):
194
        info = self._match_on(branch, revs)
195
        if info:
196
            return info
3298.2.11 by Aaron Bentley
Update tests for null:, clea up slightly
197
        elif info == (None, None):
198
            # special case - nothing supplied
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
199
            return info
200
        elif self.prefix:
1948.4.27 by John Arbash Meinel
Deprecate calling RevisionSpec directly, and instead use a helper function. Also merge the old RevisionSpec_int class into RevisionSpec_revno
201
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
202
        else:
1948.4.2 by John Arbash Meinel
Update _match_on_and_check to raise the right error
203
            raise errors.InvalidRevisionSpec(self.spec, branch)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
204
205
    def in_history(self, branch):
6630.1.1 by Jelmer Vernooij
Remove deprecated functionality.
206
        return self._match_on_and_check(branch, revs=None)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
207
1432 by Robert Collins
branch: namespace
208
        # FIXME: in_history is somewhat broken,
209
        # it will return non-history revisions in many
210
        # circumstances. The expected facility is that
211
        # in_history only returns revision-history revs,
212
        # in_store returns any rev. RBC 20051010
213
    # aliases for now, when we fix the core logic, then they
214
    # will do what you expect.
215
    in_store = in_history
3298.2.8 by John Arbash Meinel
Get rid of .in_branch(need_revno=False) in favor of simpler .as_revision_id()
216
    in_branch = in_store
3060.3.2 by Lukáš Lalinský
Make RevisionSpec_last not load the whole history.
217
3298.2.4 by John Arbash Meinel
Introduce as_revision_id() as a function instead of in_branch(need_revno=False)
218
    def as_revision_id(self, context_branch):
219
        """Return just the revision_id for this revisions spec.
220
221
        Some revision specs require a context_branch to be able to determine
222
        their value. Not all specs will make use of it.
223
        """
224
        return self._as_revision_id(context_branch)
225
226
    def _as_revision_id(self, context_branch):
227
        """Implementation of as_revision_id()
228
229
        Classes should override this function to provide appropriate
230
        functionality. The default is to just call '.in_history().rev_id'
231
        """
232
        return self.in_history(context_branch).rev_id
233
3655.3.1 by Lukáš Lalinský
Fix `bzr st -rbranch:PATH_TO_BRANCH`
234
    def as_tree(self, context_branch):
235
        """Return the tree object for this revisions spec.
236
237
        Some revision specs require a context_branch to be able to determine
238
        the revision id and access the repository. Not all specs will make
239
        use of it.
240
        """
241
        return self._as_tree(context_branch)
242
243
    def _as_tree(self, context_branch):
3732.1.1 by Ian Clatworthy
fix bzr st -rbranch:path-to-branch (Lukas Lalinsky)
244
        """Implementation of as_tree().
3655.3.1 by Lukáš Lalinský
Fix `bzr st -rbranch:PATH_TO_BRANCH`
245
246
        Classes should override this function to provide appropriate
247
        functionality. The default is to just call '.as_revision_id()'
248
        and get the revision tree from context_branch's repository.
249
        """
250
        revision_id = self.as_revision_id(context_branch)
251
        return context_branch.repository.revision_tree(revision_id)
252
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
253
    def __repr__(self):
254
        # this is mostly for helping with testing
1948.4.32 by John Arbash Meinel
Clean up __repr__, as well as add tests that we can handle -r12:branch/
255
        return '<%s %s>' % (self.__class__.__name__,
256
                              self.user_spec)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
257
1881.1.4 by Matthieu Moy
needs_tree -> needs_branch
258
    def needs_branch(self):
259
        """Whether this revision spec needs a branch.
260
1711.2.99 by John Arbash Meinel
minor typo fix
261
        Set this to False the branch argument of _match_on is not used.
262
        """
1881.1.1 by Matthieu Moy
Fixed and tested "bzr diff" outside a working tree.
263
        return True
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
264
1907.4.1 by Matthieu Moy
Fixed merge to work nicely with -r revno:N:path
265
    def get_branch(self):
266
        """When the revision specifier contains a branch location, return it.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
267
1907.4.1 by Matthieu Moy
Fixed merge to work nicely with -r revno:N:path
268
        Otherwise, return None.
269
        """
270
        return None
271
1907.4.9 by Matthieu Moy
missing newline
272
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
273
# private API
274
4569.2.1 by Matthew Fuller
Implement a DWIM revspec type and use it to allow simpler user
275
class RevisionSpec_dwim(RevisionSpec):
276
    """Provides a DWIMish revision specifier lookup.
277
4569.2.18 by Vincent Ladeuil
Small refactoring to unblock the submission.
278
    Note that this does not go in the revspec_registry because by definition
279
    there is no prefix to identify it.  It's solely called from
280
    RevisionSpec.from_string() because the DWIMification happen when _match_on
281
    is called so the string describing the revision is kept here until needed.
4569.2.1 by Matthew Fuller
Implement a DWIM revspec type and use it to allow simpler user
282
    """
283
284
    help_txt = None
285
5685.1.1 by Jelmer Vernooij
More lazy imports, lazy regexes in bzrlib.revisionspec.
286
    _revno_regex = lazy_regex.lazy_compile(r'^(?:(\d+(\.\d+)*)|-\d+)(:.*)?$')
287
5671.5.1 by Jelmer Vernooij
Allow lazily registering possible DWIM revspecs.
288
    # The revspecs to try
289
    _possible_revspecs = []
290
4569.2.19 by Vincent Ladeuil
A bit more tweaks.
291
    def _try_spectype(self, rstype, branch):
292
        rs = rstype(self.spec, _internal=True)
4569.2.1 by Matthew Fuller
Implement a DWIM revspec type and use it to allow simpler user
293
        # Hit in_history to find out if it exists, or we need to try the
294
        # next type.
295
        return rs.in_history(branch)
296
297
    def _match_on(self, branch, revs):
298
        """Run the lookup and see what we can get."""
299
300
        # First, see if it's a revno
5685.1.1 by Jelmer Vernooij
More lazy imports, lazy regexes in bzrlib.revisionspec.
301
        if self._revno_regex.match(self.spec) is not None:
4569.2.1 by Matthew Fuller
Implement a DWIM revspec type and use it to allow simpler user
302
            try:
4569.2.19 by Vincent Ladeuil
A bit more tweaks.
303
                return self._try_spectype(RevisionSpec_revno, branch)
4569.2.18 by Vincent Ladeuil
Small refactoring to unblock the submission.
304
            except RevisionSpec_revno.dwim_catchable_exceptions:
305
                pass
306
307
        # Next see what has been registered
5671.5.1 by Jelmer Vernooij
Allow lazily registering possible DWIM revspecs.
308
        for objgetter in self._possible_revspecs:
309
            rs_class = objgetter.get_obj()
310
            try:
311
                return self._try_spectype(rs_class, branch)
312
            except rs_class.dwim_catchable_exceptions:
313
                pass
314
4569.2.18 by Vincent Ladeuil
Small refactoring to unblock the submission.
315
        # Well, I dunno what it is. Note that we don't try to keep track of the
316
        # first of last exception raised during the DWIM tries as none seems
317
        # really relevant.
4569.2.1 by Matthew Fuller
Implement a DWIM revspec type and use it to allow simpler user
318
        raise errors.InvalidRevisionSpec(self.spec, branch)
319
5671.5.3 by Jelmer Vernooij
Fix test.. not sure how I missed this.
320
    @classmethod
321
    def append_possible_revspec(cls, revspec):
5671.5.1 by Jelmer Vernooij
Allow lazily registering possible DWIM revspecs.
322
        """Append a possible DWIM revspec.
323
324
        :param revspec: Revision spec to try.
325
        """
5671.5.3 by Jelmer Vernooij
Fix test.. not sure how I missed this.
326
        cls._possible_revspecs.append(registry._ObjectGetter(revspec))
5671.5.1 by Jelmer Vernooij
Allow lazily registering possible DWIM revspecs.
327
5671.5.3 by Jelmer Vernooij
Fix test.. not sure how I missed this.
328
    @classmethod
329
    def append_possible_lazy_revspec(cls, module_name, member_name):
5671.5.1 by Jelmer Vernooij
Allow lazily registering possible DWIM revspecs.
330
        """Append a possible lazily loaded DWIM revspec.
331
332
        :param module_name: Name of the module with the revspec
333
        :param member_name: Name of the revspec within the module
334
        """
5671.5.3 by Jelmer Vernooij
Fix test.. not sure how I missed this.
335
        cls._possible_revspecs.append(
5671.5.1 by Jelmer Vernooij
Allow lazily registering possible DWIM revspecs.
336
            registry._LazyObjectGetter(module_name, member_name))
337
4569.2.1 by Matthew Fuller
Implement a DWIM revspec type and use it to allow simpler user
338
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
339
class RevisionSpec_revno(RevisionSpec):
2070.4.14 by John Arbash Meinel
Switch revisionspec to use the help defined as help_txt rather than the doc string
340
    """Selects a revision using a number."""
341
342
    help_txt = """Selects a revision using a number.
2023.1.1 by ghigo
add topics help
343
344
    Use an integer to specify a revision in the history of the branch.
4569.2.5 by Matthew Fuller
Update online documentation to match new DWIM behavior.
345
    Optionally a branch can be specified.  A negative number will count
346
    from the end of the branch (-1 is the last revision, -2 the previous
347
    one). If the negative number is larger than the branch's history, the
348
    first revision is returned.
2666.1.1 by Ian Clatworthy
Bazaar User Reference generated from online help
349
    Examples::
350
3651.2.1 by Daniel Clemente
Clarify that you don't have to write a path if you mean the current branch
351
      revno:1                   -> return the first revision of this branch
2023.1.1 by ghigo
add topics help
352
      revno:3:/path/to/branch   -> return the 3rd revision of
353
                                   the branch '/path/to/branch'
354
      revno:-1                  -> The last revision in a branch.
355
      -2:http://other/branch    -> The second to last revision in the
356
                                   remote branch.
357
      -1000000                  -> Most likely the first revision, unless
358
                                   your history is very long.
359
    """
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
360
    prefix = 'revno:'
361
362
    def _match_on(self, branch, revs):
363
        """Lookup a revision by revision number"""
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
364
        branch, revno, revision_id = self._lookup(branch)
3298.2.6 by John Arbash Meinel
Don't abstract through RevisionInfo for RevisionSpec_revno.as_revision_id()
365
        return RevisionInfo(branch, revno, revision_id)
366
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
367
    def _lookup(self, branch):
1948.4.1 by John Arbash Meinel
Update number parsers to raise InvalidRevisionSpec. Update revno: itself so it supports negative numbers
368
        loc = self.spec.find(':')
369
        if loc == -1:
370
            revno_spec = self.spec
371
            branch_spec = None
372
        else:
373
            revno_spec = self.spec[:loc]
374
            branch_spec = self.spec[loc+1:]
375
376
        if revno_spec == '':
1948.4.6 by John Arbash Meinel
A small bugfix, and more tests for revno:
377
            if not branch_spec:
1948.4.27 by John Arbash Meinel
Deprecate calling RevisionSpec directly, and instead use a helper function. Also merge the old RevisionSpec_int class into RevisionSpec_revno
378
                raise errors.InvalidRevisionSpec(self.user_spec,
1948.4.5 by John Arbash Meinel
Fix tests for negative entries, and add tests for revno:
379
                        branch, 'cannot have an empty revno and no branch')
1948.4.1 by John Arbash Meinel
Update number parsers to raise InvalidRevisionSpec. Update revno: itself so it supports negative numbers
380
            revno = None
381
        else:
382
            try:
383
                revno = int(revno_spec)
1988.4.5 by Robert Collins
revisions can now be specified using dotted-decimal revision numbers.
384
                dotted = False
385
            except ValueError:
386
                # dotted decimal. This arguably should not be here
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
387
                # but the from_string method is a little primitive
1988.4.5 by Robert Collins
revisions can now be specified using dotted-decimal revision numbers.
388
                # right now - RBC 20060928
389
                try:
390
                    match_revno = tuple((int(number) for number in revno_spec.split('.')))
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
391
                except ValueError as e:
1988.4.5 by Robert Collins
revisions can now be specified using dotted-decimal revision numbers.
392
                    raise errors.InvalidRevisionSpec(self.user_spec, branch, e)
393
394
                dotted = True
1948.4.1 by John Arbash Meinel
Update number parsers to raise InvalidRevisionSpec. Update revno: itself so it supports negative numbers
395
1948.4.6 by John Arbash Meinel
A small bugfix, and more tests for revno:
396
        if branch_spec:
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
397
            # the user has overriden the branch to look in.
398
            branch = _mod_branch.Branch.open(branch_spec)
1948.4.22 by John Arbash Meinel
Refactor common code from integer revno handlers
399
1988.4.5 by Robert Collins
revisions can now be specified using dotted-decimal revision numbers.
400
        if dotted:
401
            try:
3949.2.6 by Ian Clatworthy
review feedback from jam
402
                revision_id = branch.dotted_revno_to_revision_id(match_revno,
403
                    _cache_reverse=True)
3949.2.1 by Ian Clatworthy
Branch.dotted_revno_to_revision_id API
404
            except errors.NoSuchRevision:
3872.2.2 by Marius Kruger
* use NULL_REVISION in stead of None for rev_id
405
                raise errors.InvalidRevisionSpec(self.user_spec, branch)
1948.4.27 by John Arbash Meinel
Deprecate calling RevisionSpec directly, and instead use a helper function. Also merge the old RevisionSpec_int class into RevisionSpec_revno
406
            else:
1988.4.5 by Robert Collins
revisions can now be specified using dotted-decimal revision numbers.
407
                # there is no traditional 'revno' for dotted-decimal revnos.
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
408
                # so for API compatibility we return None.
3949.2.6 by Ian Clatworthy
review feedback from jam
409
                return branch, None, revision_id
1988.4.5 by Robert Collins
revisions can now be specified using dotted-decimal revision numbers.
410
        else:
3060.3.3 by Lukáš Lalinský
Make RevisionSpec_revid and RevisionSpec_revno not load the whole revision history.
411
            last_revno, last_revision_id = branch.last_revision_info()
1988.4.5 by Robert Collins
revisions can now be specified using dotted-decimal revision numbers.
412
            if revno < 0:
2249.4.2 by Wouter van Heyst
Convert callers of Branch.revision_history() to Branch.last_revision_info() where sensible.
413
                # if get_rev_id supported negative revnos, there would not be a
414
                # need for this special case.
3060.3.3 by Lukáš Lalinský
Make RevisionSpec_revid and RevisionSpec_revno not load the whole revision history.
415
                if (-revno) >= last_revno:
1988.4.5 by Robert Collins
revisions can now be specified using dotted-decimal revision numbers.
416
                    revno = 1
417
                else:
3060.3.3 by Lukáš Lalinský
Make RevisionSpec_revid and RevisionSpec_revno not load the whole revision history.
418
                    revno = last_revno + revno + 1
1988.4.5 by Robert Collins
revisions can now be specified using dotted-decimal revision numbers.
419
            try:
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
420
                revision_id = branch.get_rev_id(revno)
1988.4.5 by Robert Collins
revisions can now be specified using dotted-decimal revision numbers.
421
            except errors.NoSuchRevision:
422
                raise errors.InvalidRevisionSpec(self.user_spec, branch)
3298.2.6 by John Arbash Meinel
Don't abstract through RevisionInfo for RevisionSpec_revno.as_revision_id()
423
        return branch, revno, revision_id
3060.3.2 by Lukáš Lalinský
Make RevisionSpec_last not load the whole history.
424
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
425
    def _as_revision_id(self, context_branch):
426
        # We would have the revno here, but we don't really care
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
427
        branch, revno, revision_id = self._lookup(context_branch)
3298.2.6 by John Arbash Meinel
Don't abstract through RevisionInfo for RevisionSpec_revno.as_revision_id()
428
        return revision_id
3060.3.3 by Lukáš Lalinský
Make RevisionSpec_revid and RevisionSpec_revno not load the whole revision history.
429
1881.1.4 by Matthieu Moy
needs_tree -> needs_branch
430
    def needs_branch(self):
1881.1.1 by Matthieu Moy
Fixed and tested "bzr diff" outside a working tree.
431
        return self.spec.find(':') == -1
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
432
1907.4.1 by Matthieu Moy
Fixed merge to work nicely with -r revno:N:path
433
    def get_branch(self):
434
        if self.spec.find(':') == -1:
435
            return None
436
        else:
437
            return self.spec[self.spec.find(':')+1:]
438
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
439
# Old compatibility
1948.4.27 by John Arbash Meinel
Deprecate calling RevisionSpec directly, and instead use a helper function. Also merge the old RevisionSpec_int class into RevisionSpec_revno
440
RevisionSpec_int = RevisionSpec_revno
441
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
442
5365.6.4 by Aaron Bentley
Implement mainline revision spec.
443
class RevisionIDSpec(RevisionSpec):
444
445
    def _match_on(self, branch, revs):
446
        revision_id = self.as_revision_id(branch)
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
447
        return RevisionInfo.from_revision_id(branch, revision_id)
5365.6.4 by Aaron Bentley
Implement mainline revision spec.
448
449
450
class RevisionSpec_revid(RevisionIDSpec):
2070.4.14 by John Arbash Meinel
Switch revisionspec to use the help defined as help_txt rather than the doc string
451
    """Selects a revision using the revision id."""
452
453
    help_txt = """Selects a revision using the revision id.
2023.1.1 by ghigo
add topics help
454
455
    Supply a specific revision id, that can be used to specify any
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
456
    revision id in the ancestry of the branch.
2023.1.1 by ghigo
add topics help
457
    Including merges, and pending merges.
2666.1.1 by Ian Clatworthy
Bazaar User Reference generated from online help
458
    Examples::
459
2070.4.7 by ghigo
Updates on the basis of the Richard Wilbur suggestions
460
      revid:aaaa@bbbb-123456789 -> Select revision 'aaaa@bbbb-123456789'
3060.3.3 by Lukáš Lalinský
Make RevisionSpec_revid and RevisionSpec_revno not load the whole revision history.
461
    """
462
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
463
    prefix = 'revid:'
464
5365.6.4 by Aaron Bentley
Implement mainline revision spec.
465
    def _as_revision_id(self, context_branch):
2325.2.5 by Marien Zwart
Call osutils.safe_revision_id instead of duplicating it.
466
        # self.spec comes straight from parsing the command line arguments,
467
        # so we expect it to be a Unicode string. Switch it to the internal
468
        # representation.
6630.1.1 by Jelmer Vernooij
Remove deprecated functionality.
469
        if isinstance(self.spec, unicode):
470
            return cache_utf8.encode(self.spec)
471
        return self.spec
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
472
473
474
475
class RevisionSpec_last(RevisionSpec):
2070.4.14 by John Arbash Meinel
Switch revisionspec to use the help defined as help_txt rather than the doc string
476
    """Selects the nth revision from the end."""
477
478
    help_txt = """Selects the nth revision from the end.
2023.1.1 by ghigo
add topics help
479
480
    Supply a positive number to get the nth revision from the end.
2070.4.7 by ghigo
Updates on the basis of the Richard Wilbur suggestions
481
    This is the same as supplying negative numbers to the 'revno:' spec.
2666.1.1 by Ian Clatworthy
Bazaar User Reference generated from online help
482
    Examples::
483
2023.1.1 by ghigo
add topics help
484
      last:1        -> return the last revision
485
      last:3        -> return the revision 2 before the end.
3060.3.2 by Lukáš Lalinský
Make RevisionSpec_last not load the whole history.
486
    """
1185.1.39 by Robert Collins
Robey Pointers before: namespace to clear up usage of dates in revision parameters
487
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
488
    prefix = 'last:'
489
490
    def _match_on(self, branch, revs):
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
491
        revno, revision_id = self._revno_and_revision_id(branch)
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
492
        return RevisionInfo(branch, revno, revision_id)
493
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
494
    def _revno_and_revision_id(self, context_branch):
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
495
        last_revno, last_revision_id = context_branch.last_revision_info()
3060.3.2 by Lukáš Lalinský
Make RevisionSpec_last not load the whole history.
496
1948.4.9 by John Arbash Meinel
Cleanup and test last:
497
        if self.spec == '':
3060.3.2 by Lukáš Lalinský
Make RevisionSpec_last not load the whole history.
498
            if not last_revno:
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
499
                raise errors.NoCommits(context_branch)
500
            return last_revno, last_revision_id
1948.4.9 by John Arbash Meinel
Cleanup and test last:
501
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
502
        try:
503
            offset = int(self.spec)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
504
        except ValueError as e:
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
505
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch, e)
1948.4.9 by John Arbash Meinel
Cleanup and test last:
506
507
        if offset <= 0:
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
508
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
1948.4.9 by John Arbash Meinel
Cleanup and test last:
509
                                             'you must supply a positive value')
3060.3.2 by Lukáš Lalinský
Make RevisionSpec_last not load the whole history.
510
511
        revno = last_revno - offset + 1
1948.4.9 by John Arbash Meinel
Cleanup and test last:
512
        try:
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
513
            revision_id = context_branch.get_rev_id(revno)
1948.4.9 by John Arbash Meinel
Cleanup and test last:
514
        except errors.NoSuchRevision:
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
515
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch)
516
        return revno, revision_id
517
518
    def _as_revision_id(self, context_branch):
519
        # We compute the revno as part of the process, but we don't really care
520
        # about it.
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
521
        revno, revision_id = self._revno_and_revision_id(context_branch)
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
522
        return revision_id
3060.3.2 by Lukáš Lalinský
Make RevisionSpec_last not load the whole history.
523
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
524
525
1185.1.39 by Robert Collins
Robey Pointers before: namespace to clear up usage of dates in revision parameters
526
class RevisionSpec_before(RevisionSpec):
2070.4.14 by John Arbash Meinel
Switch revisionspec to use the help defined as help_txt rather than the doc string
527
    """Selects the parent of the revision specified."""
528
529
    help_txt = """Selects the parent of the revision specified.
2023.1.1 by ghigo
add topics help
530
3651.2.4 by Daniel Clemente
Reordered to put explanation first and exceptions after
531
    Supply any revision spec to return the parent of that revision.  This is
532
    mostly useful when inspecting revisions that are not in the revision history
533
    of a branch.
534
2023.1.1 by ghigo
add topics help
535
    It is an error to request the parent of the null revision (before:0).
536
2666.1.1 by Ian Clatworthy
Bazaar User Reference generated from online help
537
    Examples::
538
2023.1.1 by ghigo
add topics help
539
      before:1913    -> Return the parent of revno 1913 (revno 1912)
540
      before:revid:aaaa@bbbb-1234567890  -> return the parent of revision
2070.4.7 by ghigo
Updates on the basis of the Richard Wilbur suggestions
541
                                            aaaa@bbbb-1234567890
3651.2.5 by Daniel Clemente
Wrote specifical and simpler example for 'before:', and referred to 'bzr diff -c'
542
      bzr diff -r before:1913..1913
543
            -> Find the changes between revision 1913 and its parent (1912).
544
               (What changes did revision 1913 introduce).
545
               This is equivalent to:  bzr diff -c 1913
2023.1.1 by ghigo
add topics help
546
    """
1185.1.39 by Robert Collins
Robey Pointers before: namespace to clear up usage of dates in revision parameters
547
548
    prefix = 'before:'
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
549
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
550
    def _match_on(self, branch, revs):
551
        r = RevisionSpec.from_string(self.spec)._match_on(branch, revs)
1948.4.13 by John Arbash Meinel
Going before:0 is an error, and if you are on another history, use the leftmost parent
552
        if r.revno == 0:
1948.4.27 by John Arbash Meinel
Deprecate calling RevisionSpec directly, and instead use a helper function. Also merge the old RevisionSpec_int class into RevisionSpec_revno
553
            raise errors.InvalidRevisionSpec(self.user_spec, branch,
1948.4.13 by John Arbash Meinel
Going before:0 is an error, and if you are on another history, use the leftmost parent
554
                                         'cannot go before the null: revision')
555
        if r.revno is None:
556
            # We need to use the repository history here
557
            rev = branch.repository.get_revision(r.rev_id)
558
            if not rev.parent_ids:
2598.5.10 by Aaron Bentley
Return NULL_REVISION instead of None for the null revision
559
                revision_id = revision.NULL_REVISION
1948.4.13 by John Arbash Meinel
Going before:0 is an error, and if you are on another history, use the leftmost parent
560
            else:
561
                revision_id = rev.parent_ids[0]
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
562
            revno = None
1948.4.13 by John Arbash Meinel
Going before:0 is an error, and if you are on another history, use the leftmost parent
563
        else:
564
            revno = r.revno - 1
565
            try:
566
                revision_id = branch.get_rev_id(revno, revs)
1948.4.26 by John Arbash Meinel
Get rid of direct imports of exceptions
567
            except errors.NoSuchRevision:
1948.4.27 by John Arbash Meinel
Deprecate calling RevisionSpec directly, and instead use a helper function. Also merge the old RevisionSpec_int class into RevisionSpec_revno
568
                raise errors.InvalidRevisionSpec(self.user_spec,
1948.4.13 by John Arbash Meinel
Going before:0 is an error, and if you are on another history, use the leftmost parent
569
                                                 branch)
570
        return RevisionInfo(branch, revno, revision_id)
1185.1.39 by Robert Collins
Robey Pointers before: namespace to clear up usage of dates in revision parameters
571
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
572
    def _as_revision_id(self, context_branch):
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
573
        base_revision_id = RevisionSpec.from_string(self.spec)._as_revision_id(context_branch)
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
574
        if base_revision_id == revision.NULL_REVISION:
3495.1.1 by John Arbash Meinel
Fix bug #239933, use the right exception for -c0
575
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
576
                                         'cannot go before the null: revision')
3298.2.10 by Aaron Bentley
Refactor partial history code
577
        context_repo = context_branch.repository
578
        context_repo.lock_read()
579
        try:
580
            parent_map = context_repo.get_parent_map([base_revision_id])
581
        finally:
582
            context_repo.unlock()
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
583
        if base_revision_id not in parent_map:
584
            # Ghost, or unknown revision id
585
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
586
                'cannot find the matching revision')
587
        parents = parent_map[base_revision_id]
588
        if len(parents) < 1:
589
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
590
                'No parents for revision.')
591
        return parents[0]
3060.3.5 by Lukáš Lalinský
Add support for in_branch for the remaining RevisionSpec subclasses.
592
1185.1.39 by Robert Collins
Robey Pointers before: namespace to clear up usage of dates in revision parameters
593
594
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
595
class RevisionSpec_tag(RevisionSpec):
2220.2.3 by Martin Pool
Add tag: revision namespace.
596
    """Select a revision identified by tag name"""
597
598
    help_txt = """Selects a revision identified by a tag name.
599
1551.10.34 by Aaron Bentley
Fix tag: help
600
    Tags are stored in the branch and created by the 'tag' command.
2220.2.3 by Martin Pool
Add tag: revision namespace.
601
    """
2070.4.14 by John Arbash Meinel
Switch revisionspec to use the help defined as help_txt rather than the doc string
602
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
603
    prefix = 'tag:'
4569.2.18 by Vincent Ladeuil
Small refactoring to unblock the submission.
604
    dwim_catchable_exceptions = (errors.NoSuchTag, errors.TagsNotSupported)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
605
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
606
    def _match_on(self, branch, revs):
2220.2.3 by Martin Pool
Add tag: revision namespace.
607
        # Can raise tags not supported, NoSuchTag, etc
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
608
        return RevisionInfo.from_revision_id(branch,
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
609
            branch.tags.lookup_tag(self.spec))
3060.3.5 by Lukáš Lalinský
Add support for in_branch for the remaining RevisionSpec subclasses.
610
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
611
    def _as_revision_id(self, context_branch):
612
        return context_branch.tags.lookup_tag(self.spec)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
613
614
615
1948.4.12 by John Arbash Meinel
Some tests for the date: spec
616
class _RevListToTimestamps(object):
617
    """This takes a list of revisions, and allows you to bisect by date"""
618
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
619
    __slots__ = ['branch']
1948.4.12 by John Arbash Meinel
Some tests for the date: spec
620
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
621
    def __init__(self, branch):
1688.2.2 by Guillaume Pinot
Binary search for 'date:' revision.
622
        self.branch = branch
1948.4.12 by John Arbash Meinel
Some tests for the date: spec
623
1688.2.2 by Guillaume Pinot
Binary search for 'date:' revision.
624
    def __getitem__(self, index):
1948.4.12 by John Arbash Meinel
Some tests for the date: spec
625
        """Get the date of the index'd item"""
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
626
        r = self.branch.repository.get_revision(self.branch.get_rev_id(index))
1688.2.2 by Guillaume Pinot
Binary search for 'date:' revision.
627
        # TODO: Handle timezone.
628
        return datetime.datetime.fromtimestamp(r.timestamp)
1948.4.12 by John Arbash Meinel
Some tests for the date: spec
629
1688.2.2 by Guillaume Pinot
Binary search for 'date:' revision.
630
    def __len__(self):
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
631
        return self.branch.revno()
1688.2.2 by Guillaume Pinot
Binary search for 'date:' revision.
632
633
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
634
class RevisionSpec_date(RevisionSpec):
2070.4.14 by John Arbash Meinel
Switch revisionspec to use the help defined as help_txt rather than the doc string
635
    """Selects a revision on the basis of a datestamp."""
636
637
    help_txt = """Selects a revision on the basis of a datestamp.
2023.1.1 by ghigo
add topics help
638
639
    Supply a datestamp to select the first revision that matches the date.
640
    Date can be 'yesterday', 'today', 'tomorrow' or a YYYY-MM-DD string.
641
    Matches the first entry after a given date (either at midnight or
642
    at a specified time).
643
2666.1.1 by Ian Clatworthy
Bazaar User Reference generated from online help
644
    One way to display all the changes since yesterday would be::
2666.1.5 by Ian Clatworthy
Incorporate feedback from Alex B. & James W.
645
6622.1.30 by Jelmer Vernooij
Some more test fixes.
646
        brz log -r date:yesterday..
2023.1.1 by ghigo
add topics help
647
2666.1.1 by Ian Clatworthy
Bazaar User Reference generated from online help
648
    Examples::
649
2023.1.1 by ghigo
add topics help
650
      date:yesterday            -> select the first revision since yesterday
651
      date:2006-08-14,17:10:14  -> select the first revision after
652
                                   August 14th, 2006 at 5:10pm.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
653
    """
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
654
    prefix = 'date:'
5685.1.1 by Jelmer Vernooij
More lazy imports, lazy regexes in bzrlib.revisionspec.
655
    _date_regex = lazy_regex.lazy_compile(
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
656
            r'(?P<date>(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d))?'
657
            r'(,|T)?\s*'
658
            r'(?P<time>(?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d))?)?'
659
        )
660
661
    def _match_on(self, branch, revs):
2023.1.1 by ghigo
add topics help
662
        """Spec for date revisions:
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
663
          date:value
664
          value can be 'yesterday', 'today', 'tomorrow' or a YYYY-MM-DD string.
1185.1.39 by Robert Collins
Robey Pointers before: namespace to clear up usage of dates in revision parameters
665
          matches the first entry after a given date (either at midnight or
666
          at a specified time).
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
667
        """
2070.4.3 by John Arbash Meinel
code and doc cleanup
668
        #  XXX: This doesn't actually work
669
        #  So the proper way of saying 'give me all entries for today' is:
670
        #      -r date:yesterday..date:today
1185.1.39 by Robert Collins
Robey Pointers before: namespace to clear up usage of dates in revision parameters
671
        today = datetime.datetime.fromordinal(datetime.date.today().toordinal())
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
672
        if self.spec.lower() == 'yesterday':
673
            dt = today - datetime.timedelta(days=1)
674
        elif self.spec.lower() == 'today':
675
            dt = today
676
        elif self.spec.lower() == 'tomorrow':
677
            dt = today + datetime.timedelta(days=1)
678
        else:
5685.1.1 by Jelmer Vernooij
More lazy imports, lazy regexes in bzrlib.revisionspec.
679
            m = self._date_regex.match(self.spec)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
680
            if not m or (not m.group('date') and not m.group('time')):
1948.4.27 by John Arbash Meinel
Deprecate calling RevisionSpec directly, and instead use a helper function. Also merge the old RevisionSpec_int class into RevisionSpec_revno
681
                raise errors.InvalidRevisionSpec(self.user_spec,
1948.4.12 by John Arbash Meinel
Some tests for the date: spec
682
                                                 branch, 'invalid date')
683
684
            try:
685
                if m.group('date'):
686
                    year = int(m.group('year'))
687
                    month = int(m.group('month'))
688
                    day = int(m.group('day'))
689
                else:
690
                    year = today.year
691
                    month = today.month
692
                    day = today.day
693
694
                if m.group('time'):
695
                    hour = int(m.group('hour'))
696
                    minute = int(m.group('minute'))
697
                    if m.group('second'):
698
                        second = int(m.group('second'))
699
                    else:
700
                        second = 0
701
                else:
702
                    hour, minute, second = 0,0,0
703
            except ValueError:
1948.4.27 by John Arbash Meinel
Deprecate calling RevisionSpec directly, and instead use a helper function. Also merge the old RevisionSpec_int class into RevisionSpec_revno
704
                raise errors.InvalidRevisionSpec(self.user_spec,
1948.4.12 by John Arbash Meinel
Some tests for the date: spec
705
                                                 branch, 'invalid date')
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
706
707
            dt = datetime.datetime(year=year, month=month, day=day,
708
                    hour=hour, minute=minute, second=second)
1704.2.27 by Martin Pool
Run bisection search for revision date with lock held. (Robert Widhopf-Frenk)
709
        branch.lock_read()
710
        try:
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
711
            rev = bisect.bisect(_RevListToTimestamps(branch), dt, 1)
1704.2.27 by Martin Pool
Run bisection search for revision date with lock held. (Robert Widhopf-Frenk)
712
        finally:
713
            branch.unlock()
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
714
        if rev == branch.revno():
3298.2.11 by Aaron Bentley
Update tests for null:, clea up slightly
715
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
716
        return RevisionInfo(branch, rev)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
717
718
719
720
class RevisionSpec_ancestor(RevisionSpec):
2070.4.14 by John Arbash Meinel
Switch revisionspec to use the help defined as help_txt rather than the doc string
721
    """Selects a common ancestor with a second branch."""
722
723
    help_txt = """Selects a common ancestor with a second branch.
2023.1.1 by ghigo
add topics help
724
725
    Supply the path to a branch to select the common ancestor.
726
727
    The common ancestor is the last revision that existed in both
728
    branches. Usually this is the branch point, but it could also be
729
    a revision that was merged.
730
731
    This is frequently used with 'diff' to return all of the changes
732
    that your branch introduces, while excluding the changes that you
733
    have not merged from the remote branch.
734
2666.1.1 by Ian Clatworthy
Bazaar User Reference generated from online help
735
    Examples::
736
2023.1.1 by ghigo
add topics help
737
      ancestor:/path/to/branch
2070.4.7 by ghigo
Updates on the basis of the Richard Wilbur suggestions
738
      $ bzr diff -r ancestor:../../mainline/branch
2023.1.1 by ghigo
add topics help
739
    """
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
740
    prefix = 'ancestor:'
741
742
    def _match_on(self, branch, revs):
1551.10.33 by Aaron Bentley
Updates from review
743
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
744
        return self._find_revision_info(branch, self.spec)
745
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
746
    def _as_revision_id(self, context_branch):
747
        return self._find_revision_id(context_branch, self.spec)
748
1551.10.33 by Aaron Bentley
Updates from review
749
    @staticmethod
750
    def _find_revision_info(branch, other_location):
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
751
        revision_id = RevisionSpec_ancestor._find_revision_id(branch,
752
                                                              other_location)
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
753
        return RevisionInfo(branch, None, revision_id)
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
754
755
    @staticmethod
756
    def _find_revision_id(branch, other_location):
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
757
        from .branch import Branch
1948.4.18 by John Arbash Meinel
Update branch: spec and tests
758
3010.1.12 by Robert Collins
Lock branches while doing revision specification lookups.
759
        branch.lock_read()
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
760
        try:
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
761
            revision_a = revision.ensure_null(branch.last_revision())
762
            if revision_a == revision.NULL_REVISION:
763
                raise errors.NoCommits(branch)
3984.1.2 by Daniel Watkins
Added fix.
764
            if other_location == '':
765
                other_location = branch.get_parent()
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
766
            other_branch = Branch.open(other_location)
767
            other_branch.lock_read()
768
            try:
769
                revision_b = revision.ensure_null(other_branch.last_revision())
770
                if revision_b == revision.NULL_REVISION:
771
                    raise errors.NoCommits(other_branch)
772
                graph = branch.repository.get_graph(other_branch.repository)
3010.1.12 by Robert Collins
Lock branches while doing revision specification lookups.
773
                rev_id = graph.find_unique_lca(revision_a, revision_b)
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
774
            finally:
775
                other_branch.unlock()
776
            if rev_id == revision.NULL_REVISION:
777
                raise errors.NoCommonAncestor(revision_a, revision_b)
778
            return rev_id
3010.1.12 by Robert Collins
Lock branches while doing revision specification lookups.
779
        finally:
780
            branch.unlock()
1551.10.33 by Aaron Bentley
Updates from review
781
782
1432 by Robert Collins
branch: namespace
783
1948.4.16 by John Arbash Meinel
Move the tests into the associated tester, remove redundant tests, some small PEP8 changes
784
1432 by Robert Collins
branch: namespace
785
class RevisionSpec_branch(RevisionSpec):
2070.4.14 by John Arbash Meinel
Switch revisionspec to use the help defined as help_txt rather than the doc string
786
    """Selects the last revision of a specified branch."""
787
788
    help_txt = """Selects the last revision of a specified branch.
2023.1.1 by ghigo
add topics help
789
790
    Supply the path to a branch to select its last revision.
791
2666.1.1 by Ian Clatworthy
Bazaar User Reference generated from online help
792
    Examples::
793
2023.1.1 by ghigo
add topics help
794
      branch:/path/to/branch
1432 by Robert Collins
branch: namespace
795
    """
796
    prefix = 'branch:'
4569.2.18 by Vincent Ladeuil
Small refactoring to unblock the submission.
797
    dwim_catchable_exceptions = (errors.NotBranchError,)
1432 by Robert Collins
branch: namespace
798
799
    def _match_on(self, branch, revs):
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
800
        from .branch import Branch
1948.4.18 by John Arbash Meinel
Update branch: spec and tests
801
        other_branch = Branch.open(self.spec)
1432 by Robert Collins
branch: namespace
802
        revision_b = other_branch.last_revision()
1948.4.18 by John Arbash Meinel
Update branch: spec and tests
803
        if revision_b in (None, revision.NULL_REVISION):
1948.4.26 by John Arbash Meinel
Get rid of direct imports of exceptions
804
            raise errors.NoCommits(other_branch)
5318.1.1 by Martin von Gagern
Extract branch location from branch: revision specs.
805
        if branch is None:
806
            branch = other_branch
807
        else:
808
            try:
809
                # pull in the remote revisions so we can diff
810
                branch.fetch(other_branch, revision_b)
811
            except errors.ReadOnlyError:
812
                branch = other_branch
6336.1.1 by Jelmer Vernooij
Deprecate ``RevisionSpec.wants_revision_history`` and remove any uses of it.
813
        return RevisionInfo(branch, None, revision_b)
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
814
815
    def _as_revision_id(self, context_branch):
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
816
        from .branch import Branch
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
817
        other_branch = Branch.open(self.spec)
818
        last_revision = other_branch.last_revision()
819
        last_revision = revision.ensure_null(last_revision)
1551.19.33 by Aaron Bentley
Use as_revision_id for diff
820
        context_branch.fetch(other_branch, last_revision)
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
821
        if last_revision == revision.NULL_REVISION:
822
            raise errors.NoCommits(other_branch)
823
        return last_revision
824
3655.3.1 by Lukáš Lalinský
Fix `bzr st -rbranch:PATH_TO_BRANCH`
825
    def _as_tree(self, context_branch):
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
826
        from .branch import Branch
3655.3.1 by Lukáš Lalinský
Fix `bzr st -rbranch:PATH_TO_BRANCH`
827
        other_branch = Branch.open(self.spec)
828
        last_revision = other_branch.last_revision()
829
        last_revision = revision.ensure_null(last_revision)
830
        if last_revision == revision.NULL_REVISION:
831
            raise errors.NoCommits(other_branch)
832
        return other_branch.repository.revision_tree(last_revision)
833
5318.1.1 by Martin von Gagern
Extract branch location from branch: revision specs.
834
    def needs_branch(self):
835
        return False
836
837
    def get_branch(self):
838
        return self.spec
839
1551.10.32 by Aaron Bentley
Add submit: specifier, for merge-directive-like diffs
840
841
1551.10.33 by Aaron Bentley
Updates from review
842
class RevisionSpec_submit(RevisionSpec_ancestor):
1551.10.32 by Aaron Bentley
Add submit: specifier, for merge-directive-like diffs
843
    """Selects a common ancestor with a submit branch."""
844
845
    help_txt = """Selects a common ancestor with the submit branch.
846
847
    Diffing against this shows all the changes that were made in this branch,
848
    and is a good predictor of what merge will do.  The submit branch is
3565.2.1 by Christophe Troestler
(trivial) Corrected typos.
849
    used by the bundle and merge directive commands.  If no submit branch
1551.10.32 by Aaron Bentley
Add submit: specifier, for merge-directive-like diffs
850
    is specified, the parent branch is used instead.
851
852
    The common ancestor is the last revision that existed in both
853
    branches. Usually this is the branch point, but it could also be
854
    a revision that was merged.
855
2666.1.1 by Ian Clatworthy
Bazaar User Reference generated from online help
856
    Examples::
857
1551.10.32 by Aaron Bentley
Add submit: specifier, for merge-directive-like diffs
858
      $ bzr diff -r submit:
859
    """
1551.10.33 by Aaron Bentley
Updates from review
860
1551.10.32 by Aaron Bentley
Add submit: specifier, for merge-directive-like diffs
861
    prefix = 'submit:'
862
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
863
    def _get_submit_location(self, branch):
1551.10.32 by Aaron Bentley
Add submit: specifier, for merge-directive-like diffs
864
        submit_location = branch.get_submit_branch()
1551.10.35 by Aaron Bentley
Add note about which branch is selected by submit:
865
        location_type = 'submit branch'
1551.10.32 by Aaron Bentley
Add submit: specifier, for merge-directive-like diffs
866
        if submit_location is None:
867
            submit_location = branch.get_parent()
1551.10.35 by Aaron Bentley
Add note about which branch is selected by submit:
868
            location_type = 'parent branch'
1551.10.32 by Aaron Bentley
Add submit: specifier, for merge-directive-like diffs
869
        if submit_location is None:
870
            raise errors.NoSubmitBranch(branch)
6147.1.1 by Jonathan Riddell
use .format() instead of % for string formatting where there are multiple formats in one string to allow for translations
871
        trace.note(gettext('Using {0} {1}').format(location_type,
872
                                                        submit_location))
3298.2.5 by John Arbash Meinel
Start implementing everything in terms of cheaper _as_revision_id lookups.
873
        return submit_location
874
875
    def _match_on(self, branch, revs):
876
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
877
        return self._find_revision_info(branch,
878
            self._get_submit_location(branch))
879
880
    def _as_revision_id(self, context_branch):
881
        return self._find_revision_id(context_branch,
882
            self._get_submit_location(context_branch))
1551.10.33 by Aaron Bentley
Updates from review
883
1551.10.35 by Aaron Bentley
Add note about which branch is selected by submit:
884
5365.6.6 by Aaron Bentley
Implement 'annotate' revision-id.
885
class RevisionSpec_annotate(RevisionIDSpec):
886
887
    prefix = 'annotate:'
888
889
    help_txt = """Select the revision that last modified the specified line.
890
891
    Select the revision that last modified the specified line.  Line is
892
    specified as path:number.  Path is a relative path to the file.  Numbers
893
    start at 1, and are relative to the current version, not the last-
894
    committed version of the file.
895
    """
896
897
    def _raise_invalid(self, numstring, context_branch):
898
        raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
899
            'No such line: %s' % numstring)
900
901
    def _as_revision_id(self, context_branch):
902
        path, numstring = self.spec.rsplit(':', 1)
903
        try:
904
            index = int(numstring) - 1
905
        except ValueError:
906
            self._raise_invalid(numstring, context_branch)
907
        tree, file_path = workingtree.WorkingTree.open_containing(path)
908
        tree.lock_read()
909
        try:
910
            file_id = tree.path2id(file_path)
911
            if file_id is None:
912
                raise errors.InvalidRevisionSpec(self.user_spec,
913
                    context_branch, "File '%s' is not versioned." %
914
                    file_path)
915
            revision_ids = [r for (r, l) in tree.annotate_iter(file_id)]
916
        finally:
917
            tree.unlock()
918
        try:
919
            revision_id = revision_ids[index]
920
        except IndexError:
921
            self._raise_invalid(numstring, context_branch)
922
        if revision_id == revision.CURRENT_REVISION:
923
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
924
                'Line %s has not been committed.' % numstring)
925
        return revision_id
926
927
5365.6.4 by Aaron Bentley
Implement mainline revision spec.
928
class RevisionSpec_mainline(RevisionIDSpec):
929
930
    help_txt = """Select mainline revision that merged the specified revision.
931
932
    Select the revision that merged the specified revision into mainline.
933
    """
934
935
    prefix = 'mainline:'
936
937
    def _as_revision_id(self, context_branch):
938
        revspec = RevisionSpec.from_string(self.spec)
939
        if revspec.get_branch() is None:
940
            spec_branch = context_branch
941
        else:
942
            spec_branch = _mod_branch.Branch.open(revspec.get_branch())
943
        revision_id = revspec.as_revision_id(spec_branch)
944
        graph = context_branch.repository.get_graph()
945
        result = graph.find_lefthand_merger(revision_id,
946
                                            context_branch.last_revision())
947
        if result is None:
948
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch)
949
        return result
950
951
4569.2.18 by Vincent Ladeuil
Small refactoring to unblock the submission.
952
# The order in which we want to DWIM a revision spec without any prefix.
953
# revno is always tried first and isn't listed here, this is used by
954
# RevisionSpec_dwim._match_on
5671.5.1 by Jelmer Vernooij
Allow lazily registering possible DWIM revspecs.
955
RevisionSpec_dwim.append_possible_revspec(RevisionSpec_tag)
956
RevisionSpec_dwim.append_possible_revspec(RevisionSpec_revid)
957
RevisionSpec_dwim.append_possible_revspec(RevisionSpec_date)
958
RevisionSpec_dwim.append_possible_revspec(RevisionSpec_branch)
4569.2.18 by Vincent Ladeuil
Small refactoring to unblock the submission.
959
3966.2.1 by Jelmer Vernooij
Register revision specifiers in a registry.
960
revspec_registry = registry.Registry()
961
def _register_revspec(revspec):
962
    revspec_registry.register(revspec.prefix, revspec)
963
964
_register_revspec(RevisionSpec_revno)
965
_register_revspec(RevisionSpec_revid)
966
_register_revspec(RevisionSpec_last)
967
_register_revspec(RevisionSpec_before)
968
_register_revspec(RevisionSpec_tag)
969
_register_revspec(RevisionSpec_date)
970
_register_revspec(RevisionSpec_ancestor)
971
_register_revspec(RevisionSpec_branch)
972
_register_revspec(RevisionSpec_submit)
5365.6.6 by Aaron Bentley
Implement 'annotate' revision-id.
973
_register_revspec(RevisionSpec_annotate)
5365.6.4 by Aaron Bentley
Implement mainline revision spec.
974
_register_revspec(RevisionSpec_mainline)