/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
1
# Copyright (C) 2005 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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
1948.4.1 by John Arbash Meinel
Update number parsers to raise InvalidRevisionSpec. Update revno: itself so it supports negative numbers
18
import bisect
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
19
import datetime
20
import re
1948.4.1 by John Arbash Meinel
Update number parsers to raise InvalidRevisionSpec. Update revno: itself so it supports negative numbers
21
22
from bzrlib import (
23
    errors,
1948.4.18 by John Arbash Meinel
Update branch: spec and tests
24
    revision,
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
25
    symbol_versioning,
26
    trace,
1948.4.1 by John Arbash Meinel
Update number parsers to raise InvalidRevisionSpec. Update revno: itself so it supports negative numbers
27
    )
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
28
1948.4.16 by John Arbash Meinel
Move the tests into the associated tester, remove redundant tests, some small PEP8 changes
29
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
30
_marker = []
31
1948.4.16 by John Arbash Meinel
Move the tests into the associated tester, remove redundant tests, some small PEP8 changes
32
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
33
class RevisionInfo(object):
34
    """The results of applying a revision specification to a branch.
35
36
    An instance has two useful attributes: revno, and rev_id.
37
38
    They can also be accessed as spec[0] and spec[1] respectively,
39
    so that you can write code like:
40
    revno, rev_id = RevisionSpec(branch, spec)
41
    although this is probably going to be deprecated later.
42
43
    This class exists mostly to be the return value of a RevisionSpec,
44
    so that you can access the member you're interested in (number or id)
45
    or treat the result as a tuple.
46
    """
47
48
    def __init__(self, branch, revno, rev_id=_marker):
49
        self.branch = branch
50
        self.revno = revno
51
        if rev_id is _marker:
52
            # allow caller to be lazy
53
            if self.revno is None:
54
                self.rev_id = None
55
            else:
56
                self.rev_id = branch.get_rev_id(self.revno)
57
        else:
58
            self.rev_id = rev_id
59
60
    def __nonzero__(self):
61
        # first the easy ones...
62
        if self.rev_id is None:
63
            return False
64
        if self.revno is not None:
65
            return True
66
        # TODO: otherwise, it should depend on how I was built -
67
        # if it's in_history(branch), then check revision_history(),
68
        # if it's in_store(branch), do the check below
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
69
        return self.branch.repository.has_revision(self.rev_id)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
70
71
    def __len__(self):
72
        return 2
73
74
    def __getitem__(self, index):
75
        if index == 0: return self.revno
76
        if index == 1: return self.rev_id
77
        raise IndexError(index)
78
79
    def get(self):
1185.67.2 by Aaron Bentley
Renamed Branch.storage to Branch.repository
80
        return self.branch.repository.get_revision(self.rev_id)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
81
82
    def __eq__(self, other):
83
        if type(other) not in (tuple, list, type(self)):
84
            return False
85
        if type(other) is type(self) and self.branch is not other.branch:
86
            return False
87
        return tuple(self) == tuple(other)
88
89
    def __repr__(self):
90
        return '<bzrlib.revisionspec.RevisionInfo object %s, %s for %r>' % (
91
            self.revno, self.rev_id, self.branch)
92
1948.4.16 by John Arbash Meinel
Move the tests into the associated tester, remove redundant tests, some small PEP8 changes
93
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
94
# classes in this list should have a "prefix" attribute, against which
95
# string specs are matched
96
SPEC_TYPES = []
97
1948.4.16 by John Arbash Meinel
Move the tests into the associated tester, remove redundant tests, some small PEP8 changes
98
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
99
class RevisionSpec(object):
100
    """A parsed revision specification.
101
102
    A revision specification can be an integer, in which case it is
103
    assumed to be a revno (though this will translate negative values
104
    into positive ones); or it can be a string, in which case it is
105
    parsed for something like 'date:' or 'revid:' etc.
106
107
    Revision specs are an UI element, and they have been moved out
108
    of the branch class to leave "back-end" classes unaware of such
109
    details.  Code that gets a revno or rev_id from other code should
110
    not be using revision specs - revnos and revision ids are the
111
    accepted ways to refer to revisions internally.
112
113
    (Equivalent to the old Branch method get_revision_info())
114
    """
115
116
    prefix = None
117
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
118
    def __new__(cls, spec, _internal=False):
119
        if _internal:
120
            return object.__new__(cls, spec, _internal=_internal)
121
122
        symbol_versioning.warn('Creating a RevisionSpec directly has'
123
                               ' been deprecated in version 0.11. Use'
124
                               ' bzrlib.revisionspec.get_revision_spec()'
125
                               ' instead.',
126
                               DeprecationWarning, stacklevel=2)
127
        return get_revision_spec(spec)
128
129
    def __init__(self, spec, _internal=False):
130
        """Create a RevisionSpec referring to the Null revision.
131
132
        :param spec: The original spec supplied by the user
133
        :param _internal: Used to ensure that RevisionSpec is not being
134
            called directly. Only from get_revision_spec()
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
135
        """
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
136
        if not _internal:
137
            # XXX: Update this after 0.10 is released
138
            symbol_versioning.warn('Creating a RevisionSpec directly has'
139
                                   ' been deprecated in version 0.11. Use'
140
                                   ' bzrlib.revisionspec.get_revision_spec()'
141
                                   ' instead.',
142
                                   DeprecationWarning, stacklevel=2)
143
        self.user_spec = spec
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
144
        if self.prefix and spec.startswith(self.prefix):
145
            spec = spec[len(self.prefix):]
146
        self.spec = spec
147
148
    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
149
        trace.mutter('Returning RevisionSpec._match_on: None')
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
150
        return RevisionInfo(branch, 0, None)
151
152
    def _match_on_and_check(self, branch, revs):
153
        info = self._match_on(branch, revs)
154
        if info:
155
            return info
156
        elif info == (0, None):
157
            # special case - the empty tree
158
            return info
159
        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
160
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
161
        else:
1948.4.2 by John Arbash Meinel
Update _match_on_and_check to raise the right error
162
            raise errors.InvalidRevisionSpec(self.spec, branch)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
163
164
    def in_history(self, branch):
1732.3.1 by Matthieu Moy
Implementation of -r revno:N:/path/to/branch
165
        if branch:
166
            revs = branch.revision_history()
167
        else:
168
            revs = None
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
169
        return self._match_on_and_check(branch, revs)
170
1432 by Robert Collins
branch: namespace
171
        # FIXME: in_history is somewhat broken,
172
        # it will return non-history revisions in many
173
        # circumstances. The expected facility is that
174
        # in_history only returns revision-history revs,
175
        # in_store returns any rev. RBC 20051010
176
    # aliases for now, when we fix the core logic, then they
177
    # will do what you expect.
178
    in_store = in_history
179
    in_branch = in_store
180
        
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
181
    def __repr__(self):
182
        # this is mostly for helping with testing
183
        return '<%s %s%s>' % (self.__class__.__name__,
184
                              self.prefix or '',
185
                              self.spec)
1881.1.1 by Matthieu Moy
Fixed and tested "bzr diff" outside a working tree.
186
    
1881.1.4 by Matthieu Moy
needs_tree -> needs_branch
187
    def needs_branch(self):
188
        """Whether this revision spec needs a branch.
189
1711.2.99 by John Arbash Meinel
minor typo fix
190
        Set this to False the branch argument of _match_on is not used.
191
        """
1881.1.1 by Matthieu Moy
Fixed and tested "bzr diff" outside a working tree.
192
        return True
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
193
1948.4.22 by John Arbash Meinel
Refactor common code from integer revno handlers
194
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
195
_revno_regex = None
196
197
def get_revision_spec(spec):
198
    """Parse a revision spec into a RevisionSpec object.
199
200
    :param spec: A string specified by the user
201
    :return: A RevisionSpec object that understands how to parse the
202
        supplied notation.
203
    """
204
    if not isinstance(spec, (type(None), basestring)):
205
        raise TypeError('error')
206
207
    if spec is None:
208
        return RevisionSpec(None, _internal=True)
209
210
    assert isinstance(spec, basestring), \
211
        "You should only supply strings not %s" % (type(spec),)
212
213
    for spectype in SPEC_TYPES:
214
        if spec.startswith(spectype.prefix):
215
            trace.mutter('Returning RevisionSpec %s for %s',
216
                         spectype.__name__, spec)
217
            return spectype(spec, _internal=True)
218
    else:
219
        # RevisionSpec_revno is special cased, because it is the only
220
        # one that directly handles plain integers
221
        global _revno_regex
222
        if _revno_regex is None:
223
            _revno_regex = re.compile(r'-?\d+(:.*)?')
224
        if _revno_regex.match(spec) is not None:
225
            return RevisionSpec_revno(spec, _internal=True)
226
227
        raise errors.NoSuchRevisionSpec(spec)
228
        
229
        
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
230
# private API
231
232
233
class RevisionSpec_revno(RevisionSpec):
234
    prefix = 'revno:'
235
236
    def _match_on(self, branch, revs):
237
        """Lookup a revision by revision number"""
1948.4.1 by John Arbash Meinel
Update number parsers to raise InvalidRevisionSpec. Update revno: itself so it supports negative numbers
238
        loc = self.spec.find(':')
239
        if loc == -1:
240
            revno_spec = self.spec
241
            branch_spec = None
242
        else:
243
            revno_spec = self.spec[:loc]
244
            branch_spec = self.spec[loc+1:]
245
246
        if revno_spec == '':
1948.4.6 by John Arbash Meinel
A small bugfix, and more tests for revno:
247
            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
248
                raise errors.InvalidRevisionSpec(self.user_spec,
1948.4.5 by John Arbash Meinel
Fix tests for negative entries, and add tests for revno:
249
                        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
250
            revno = None
251
        else:
252
            try:
253
                revno = int(revno_spec)
254
            except ValueError, e:
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
255
                raise errors.InvalidRevisionSpec(self.user_spec,
1948.4.5 by John Arbash Meinel
Fix tests for negative entries, and add tests for revno:
256
                                                 branch, e)
1948.4.1 by John Arbash Meinel
Update number parsers to raise InvalidRevisionSpec. Update revno: itself so it supports negative numbers
257
1948.4.6 by John Arbash Meinel
A small bugfix, and more tests for revno:
258
        if branch_spec:
1948.4.1 by John Arbash Meinel
Update number parsers to raise InvalidRevisionSpec. Update revno: itself so it supports negative numbers
259
            from bzrlib.branch import Branch
260
            branch = Branch.open(branch_spec)
1948.4.22 by John Arbash Meinel
Refactor common code from integer revno handlers
261
            # Need to use a new revision history
262
            # because we are using a specific branch
263
            revs = branch.revision_history()
264
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
265
        if revno < 0:
266
            if (-revno) >= len(revs):
267
                revno = 1
268
            else:
269
                revno = len(revs) + revno + 1
270
        try:
271
            revision_id = branch.get_rev_id(revno, revs)
272
        except errors.NoSuchRevision:
273
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
274
        return RevisionInfo(branch, revno, revision_id)
1881.1.1 by Matthieu Moy
Fixed and tested "bzr diff" outside a working tree.
275
        
1881.1.4 by Matthieu Moy
needs_tree -> needs_branch
276
    def needs_branch(self):
1881.1.1 by Matthieu Moy
Fixed and tested "bzr diff" outside a working tree.
277
        return self.spec.find(':') == -1
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
278
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
279
# Old compatibility 
280
RevisionSpec_int = RevisionSpec_revno
281
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
282
SPEC_TYPES.append(RevisionSpec_revno)
283
284
285
class RevisionSpec_revid(RevisionSpec):
286
    prefix = 'revid:'
287
288
    def _match_on(self, branch, revs):
289
        try:
1948.4.2 by John Arbash Meinel
Update _match_on_and_check to raise the right error
290
            revno = revs.index(self.spec) + 1
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
291
        except ValueError:
1948.4.2 by John Arbash Meinel
Update _match_on_and_check to raise the right error
292
            revno = None
293
        return RevisionInfo(branch, revno, self.spec)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
294
295
SPEC_TYPES.append(RevisionSpec_revid)
296
297
298
class RevisionSpec_last(RevisionSpec):
1185.1.39 by Robert Collins
Robey Pointers before: namespace to clear up usage of dates in revision parameters
299
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
300
    prefix = 'last:'
301
302
    def _match_on(self, branch, revs):
1948.4.9 by John Arbash Meinel
Cleanup and test last:
303
        if self.spec == '':
304
            if not revs:
1948.4.26 by John Arbash Meinel
Get rid of direct imports of exceptions
305
                raise errors.NoCommits(branch)
1948.4.9 by John Arbash Meinel
Cleanup and test last:
306
            return RevisionInfo(branch, len(revs), revs[-1])
307
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
308
        try:
309
            offset = int(self.spec)
1948.4.9 by John Arbash Meinel
Cleanup and test last:
310
        except ValueError, e:
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
311
            raise errors.InvalidRevisionSpec(self.user_spec, branch, e)
1948.4.9 by John Arbash Meinel
Cleanup and test last:
312
313
        if offset <= 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
314
            raise errors.InvalidRevisionSpec(self.user_spec, branch,
1948.4.9 by John Arbash Meinel
Cleanup and test last:
315
                                             'you must supply a positive value')
316
        revno = len(revs) - offset + 1
317
        try:
318
            revision_id = branch.get_rev_id(revno, revs)
319
        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
320
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
1948.4.9 by John Arbash Meinel
Cleanup and test last:
321
        return RevisionInfo(branch, revno, revision_id)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
322
323
SPEC_TYPES.append(RevisionSpec_last)
324
325
1185.1.39 by Robert Collins
Robey Pointers before: namespace to clear up usage of dates in revision parameters
326
class RevisionSpec_before(RevisionSpec):
327
328
    prefix = 'before:'
329
    
330
    def _match_on(self, branch, revs):
1948.4.28 by John Arbash Meinel
Remove some places that were directly instantiating a RevisionSpec object. Also get rid of support for --revision 1:2, it has been deprecated for a long time
331
        r = get_revision_spec(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
332
        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
333
            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
334
                                         'cannot go before the null: revision')
335
        if r.revno is None:
336
            # We need to use the repository history here
337
            rev = branch.repository.get_revision(r.rev_id)
338
            if not rev.parent_ids:
339
                revno = 0
340
                revision_id = None
341
            else:
342
                revision_id = rev.parent_ids[0]
343
                try:
344
                    revno = revs.index(revision_id) + 1
345
                except ValueError:
346
                    revno = None
347
        else:
348
            revno = r.revno - 1
349
            try:
350
                revision_id = branch.get_rev_id(revno, revs)
1948.4.26 by John Arbash Meinel
Get rid of direct imports of exceptions
351
            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
352
                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
353
                                                 branch)
354
        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
355
356
SPEC_TYPES.append(RevisionSpec_before)
357
358
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
359
class RevisionSpec_tag(RevisionSpec):
360
    prefix = 'tag:'
361
362
    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
363
        raise errors.InvalidRevisionSpec(self.user_spec, branch,
1948.4.11 by John Arbash Meinel
Update and test the tag: spec
364
                                         'tag: namespace registered,'
365
                                         ' but not implemented')
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
366
367
SPEC_TYPES.append(RevisionSpec_tag)
368
369
1948.4.12 by John Arbash Meinel
Some tests for the date: spec
370
class _RevListToTimestamps(object):
371
    """This takes a list of revisions, and allows you to bisect by date"""
372
373
    __slots__ = ['revs', 'branch']
374
1688.2.2 by Guillaume Pinot
Binary search for 'date:' revision.
375
    def __init__(self, revs, branch):
376
        self.revs = revs
377
        self.branch = branch
1948.4.12 by John Arbash Meinel
Some tests for the date: spec
378
1688.2.2 by Guillaume Pinot
Binary search for 'date:' revision.
379
    def __getitem__(self, index):
1948.4.12 by John Arbash Meinel
Some tests for the date: spec
380
        """Get the date of the index'd item"""
1688.2.2 by Guillaume Pinot
Binary search for 'date:' revision.
381
        r = self.branch.repository.get_revision(self.revs[index])
382
        # TODO: Handle timezone.
383
        return datetime.datetime.fromtimestamp(r.timestamp)
1948.4.12 by John Arbash Meinel
Some tests for the date: spec
384
1688.2.2 by Guillaume Pinot
Binary search for 'date:' revision.
385
    def __len__(self):
386
        return len(self.revs)
387
388
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
389
class RevisionSpec_date(RevisionSpec):
390
    prefix = 'date:'
391
    _date_re = re.compile(
392
            r'(?P<date>(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d))?'
393
            r'(,|T)?\s*'
394
            r'(?P<time>(?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d))?)?'
395
        )
396
397
    def _match_on(self, branch, revs):
398
        """
399
        Spec for date revisions:
400
          date:value
401
          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
402
          matches the first entry after a given date (either at midnight or
403
          at a specified time).
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
404
405
          So the proper way of saying 'give me all entries for today' is:
1711.2.90 by John Arbash Meinel
Fix the docstring of RevisionSpec_date (bug #31276)
406
              -r date:yesterday..date:today
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
407
        """
1185.1.39 by Robert Collins
Robey Pointers before: namespace to clear up usage of dates in revision parameters
408
        today = datetime.datetime.fromordinal(datetime.date.today().toordinal())
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
409
        if self.spec.lower() == 'yesterday':
410
            dt = today - datetime.timedelta(days=1)
411
        elif self.spec.lower() == 'today':
412
            dt = today
413
        elif self.spec.lower() == 'tomorrow':
414
            dt = today + datetime.timedelta(days=1)
415
        else:
416
            m = self._date_re.match(self.spec)
417
            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
418
                raise errors.InvalidRevisionSpec(self.user_spec,
1948.4.12 by John Arbash Meinel
Some tests for the date: spec
419
                                                 branch, 'invalid date')
420
421
            try:
422
                if m.group('date'):
423
                    year = int(m.group('year'))
424
                    month = int(m.group('month'))
425
                    day = int(m.group('day'))
426
                else:
427
                    year = today.year
428
                    month = today.month
429
                    day = today.day
430
431
                if m.group('time'):
432
                    hour = int(m.group('hour'))
433
                    minute = int(m.group('minute'))
434
                    if m.group('second'):
435
                        second = int(m.group('second'))
436
                    else:
437
                        second = 0
438
                else:
439
                    hour, minute, second = 0,0,0
440
            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
441
                raise errors.InvalidRevisionSpec(self.user_spec,
1948.4.12 by John Arbash Meinel
Some tests for the date: spec
442
                                                 branch, 'invalid date')
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
443
444
            dt = datetime.datetime(year=year, month=month, day=day,
445
                    hour=hour, minute=minute, second=second)
1704.2.27 by Martin Pool
Run bisection search for revision date with lock held. (Robert Widhopf-Frenk)
446
        branch.lock_read()
447
        try:
1948.4.12 by John Arbash Meinel
Some tests for the date: spec
448
            rev = bisect.bisect(_RevListToTimestamps(revs, branch), dt)
1704.2.27 by Martin Pool
Run bisection search for revision date with lock held. (Robert Widhopf-Frenk)
449
        finally:
450
            branch.unlock()
1688.2.2 by Guillaume Pinot
Binary search for 'date:' revision.
451
        if rev == len(revs):
452
            return RevisionInfo(branch, None)
453
        else:
454
            return RevisionInfo(branch, rev + 1)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
455
456
SPEC_TYPES.append(RevisionSpec_date)
457
458
459
class RevisionSpec_ancestor(RevisionSpec):
460
    prefix = 'ancestor:'
461
462
    def _match_on(self, branch, revs):
1948.4.16 by John Arbash Meinel
Move the tests into the associated tester, remove redundant tests, some small PEP8 changes
463
        from bzrlib.branch import Branch
1948.4.18 by John Arbash Meinel
Update branch: spec and tests
464
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
465
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
1948.4.17 by John Arbash Meinel
Update tests for ancestor: spec
466
        other_branch = Branch.open(self.spec)
1390 by Robert Collins
pair programming worx... merge integration and weave
467
        revision_a = branch.last_revision()
468
        revision_b = other_branch.last_revision()
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
469
        for r, b in ((revision_a, branch), (revision_b, other_branch)):
1948.4.18 by John Arbash Meinel
Update branch: spec and tests
470
            if r in (None, revision.NULL_REVISION):
1948.4.26 by John Arbash Meinel
Get rid of direct imports of exceptions
471
                raise errors.NoCommits(b)
1948.4.18 by John Arbash Meinel
Update branch: spec and tests
472
        revision_source = revision.MultipleRevisionSources(
473
                branch.repository, other_branch.repository)
474
        rev_id = revision.common_ancestor(revision_a, revision_b,
475
                                          revision_source)
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
476
        try:
477
            revno = branch.revision_id_to_revno(rev_id)
1948.4.26 by John Arbash Meinel
Get rid of direct imports of exceptions
478
        except errors.NoSuchRevision:
1185.11.5 by John Arbash Meinel
Merged up-to-date against mainline, still broken.
479
            revno = None
480
        return RevisionInfo(branch, revno, rev_id)
481
        
482
SPEC_TYPES.append(RevisionSpec_ancestor)
1432 by Robert Collins
branch: namespace
483
1948.4.16 by John Arbash Meinel
Move the tests into the associated tester, remove redundant tests, some small PEP8 changes
484
1432 by Robert Collins
branch: namespace
485
class RevisionSpec_branch(RevisionSpec):
486
    """A branch: revision specifier.
487
488
    This takes the path to a branch and returns its tip revision id.
489
    """
490
    prefix = 'branch:'
491
492
    def _match_on(self, branch, revs):
1948.4.18 by John Arbash Meinel
Update branch: spec and tests
493
        from bzrlib.branch import Branch
494
        other_branch = Branch.open(self.spec)
1432 by Robert Collins
branch: namespace
495
        revision_b = other_branch.last_revision()
1948.4.18 by John Arbash Meinel
Update branch: spec and tests
496
        if revision_b in (None, revision.NULL_REVISION):
1948.4.26 by John Arbash Meinel
Get rid of direct imports of exceptions
497
            raise errors.NoCommits(other_branch)
1432 by Robert Collins
branch: namespace
498
        # pull in the remote revisions so we can diff
1534.1.31 by Robert Collins
Deprecated fetch.fetch and fetch.greedy_fetch for branch.fetch, and move the Repository.fetch internals to InterRepo and InterWeaveRepo.
499
        branch.fetch(other_branch, revision_b)
1432 by Robert Collins
branch: namespace
500
        try:
501
            revno = branch.revision_id_to_revno(revision_b)
1948.4.26 by John Arbash Meinel
Get rid of direct imports of exceptions
502
        except errors.NoSuchRevision:
1432 by Robert Collins
branch: namespace
503
            revno = None
504
        return RevisionInfo(branch, revno, revision_b)
505
        
506
SPEC_TYPES.append(RevisionSpec_branch)