6 # GNU General Public License version 2 or any later version. |
6 # GNU General Public License version 2 or any later version. |
7 |
7 |
8 from __future__ import absolute_import |
8 from __future__ import absolute_import |
9 |
9 |
10 from . import ( |
10 from . import ( |
|
11 encoding, |
11 error, |
12 error, |
|
13 pycompat, |
12 util, |
14 util, |
13 ) |
15 ) |
14 |
16 |
15 def _formatsetrepr(r): |
17 def _formatsetrepr(r): |
16 """Format an optional printable representation of a set |
18 """Format an optional printable representation of a set |
17 |
19 |
18 ======== ================================= |
20 ======== ================================= |
19 type(r) example |
21 type(r) example |
20 ======== ================================= |
22 ======== ================================= |
21 tuple ('<not %r>', other) |
23 tuple ('<not %r>', other) |
22 str '<branch closed>' |
24 bytes '<branch closed>' |
23 callable lambda: '<branch %r>' % sorted(b) |
25 callable lambda: '<branch %r>' % sorted(b) |
24 object other |
26 object other |
25 ======== ================================= |
27 ======== ================================= |
26 """ |
28 """ |
27 if r is None: |
29 if r is None: |
28 return '' |
30 return '' |
29 elif isinstance(r, tuple): |
31 elif isinstance(r, tuple): |
30 return r[0] % r[1:] |
32 return r[0] % r[1:] |
31 elif isinstance(r, str): |
33 elif isinstance(r, bytes): |
32 return r |
34 return r |
33 elif callable(r): |
35 elif callable(r): |
34 return r() |
36 return r() |
35 else: |
37 else: |
36 return repr(r) |
38 return pycompat.sysbytes(repr(r)) |
|
39 |
|
40 def _typename(o): |
|
41 return pycompat.sysbytes(type(o).__name__).lstrip('_') |
37 |
42 |
38 class abstractsmartset(object): |
43 class abstractsmartset(object): |
39 |
44 |
40 def __nonzero__(self): |
45 def __nonzero__(self): |
41 """True if the smartset is not empty""" |
46 """True if the smartset is not empty""" |
382 start, stop = max(len(data) - stop, 0), max(len(data) - start, 0) |
387 start, stop = max(len(data) - stop, 0), max(len(data) - start, 0) |
383 s = baseset(data[start:stop], istopo=self._istopo) |
388 s = baseset(data[start:stop], istopo=self._istopo) |
384 s._ascending = self._ascending |
389 s._ascending = self._ascending |
385 return s |
390 return s |
386 |
391 |
|
392 @encoding.strmethod |
387 def __repr__(self): |
393 def __repr__(self): |
388 d = {None: '', False: '-', True: '+'}[self._ascending] |
394 d = {None: '', False: '-', True: '+'}[self._ascending] |
389 s = _formatsetrepr(self._datarepr) |
395 s = _formatsetrepr(self._datarepr) |
390 if not s: |
396 if not s: |
391 l = self._list |
397 l = self._list |
392 # if _list has been built from a set, it might have a different |
398 # if _list has been built from a set, it might have a different |
393 # order from one python implementation to another. |
399 # order from one python implementation to another. |
394 # We fallback to the sorted version for a stable output. |
400 # We fallback to the sorted version for a stable output. |
395 if self._ascending is not None: |
401 if self._ascending is not None: |
396 l = self._asclist |
402 l = self._asclist |
397 s = repr(l) |
403 s = pycompat.sysbytes(repr(l)) |
398 return '<%s%s %s>' % (type(self).__name__, d, s) |
404 return '<%s%s %s>' % (_typename(self), d, s) |
399 |
405 |
400 class filteredset(abstractsmartset): |
406 class filteredset(abstractsmartset): |
401 """Duck type for baseset class which iterates lazily over the revisions in |
407 """Duck type for baseset class which iterates lazily over the revisions in |
402 the subset and contains a function which tests for membership in the |
408 the subset and contains a function which tests for membership in the |
403 revset |
409 revset |
503 x = None |
509 x = None |
504 for x in self: |
510 for x in self: |
505 pass |
511 pass |
506 return x |
512 return x |
507 |
513 |
|
514 @encoding.strmethod |
508 def __repr__(self): |
515 def __repr__(self): |
509 xs = [repr(self._subset)] |
516 xs = [pycompat.sysbytes(repr(self._subset))] |
510 s = _formatsetrepr(self._condrepr) |
517 s = _formatsetrepr(self._condrepr) |
511 if s: |
518 if s: |
512 xs.append(s) |
519 xs.append(s) |
513 return '<%s %s>' % (type(self).__name__, ', '.join(xs)) |
520 return '<%s %s>' % (_typename(self), ', '.join(xs)) |
514 |
521 |
515 def _iterordered(ascending, iter1, iter2): |
522 def _iterordered(ascending, iter1, iter2): |
516 """produce an ordered iteration from two iterators with the same order |
523 """produce an ordered iteration from two iterators with the same order |
517 |
524 |
518 The ascending is used to indicated the iteration direction. |
525 The ascending is used to indicated the iteration direction. |
753 self.reverse() |
760 self.reverse() |
754 val = self.first() |
761 val = self.first() |
755 self.reverse() |
762 self.reverse() |
756 return val |
763 return val |
757 |
764 |
|
765 @encoding.strmethod |
758 def __repr__(self): |
766 def __repr__(self): |
759 d = {None: '', False: '-', True: '+'}[self._ascending] |
767 d = {None: '', False: '-', True: '+'}[self._ascending] |
760 return '<%s%s %r, %r>' % (type(self).__name__, d, self._r1, self._r2) |
768 return '<%s%s %r, %r>' % (_typename(self), d, self._r1, self._r2) |
761 |
769 |
762 class generatorset(abstractsmartset): |
770 class generatorset(abstractsmartset): |
763 """Wrap a generator for lazy iteration |
771 """Wrap a generator for lazy iteration |
764 |
772 |
765 Wrapper structure for generators that provides lazy membership and can |
773 Wrapper structure for generators that provides lazy membership and can |
916 for x in self._consumegen(): |
924 for x in self._consumegen(): |
917 pass |
925 pass |
918 return self.last() |
926 return self.last() |
919 return next(it(), None) |
927 return next(it(), None) |
920 |
928 |
|
929 @encoding.strmethod |
921 def __repr__(self): |
930 def __repr__(self): |
922 d = {False: '-', True: '+'}[self._ascending] |
931 d = {False: '-', True: '+'}[self._ascending] |
923 return '<%s%s>' % (type(self).__name__.lstrip('_'), d) |
932 return '<%s%s>' % (_typename(self), d) |
924 |
933 |
925 class _generatorsetasc(generatorset): |
934 class _generatorsetasc(generatorset): |
926 """Special case of generatorset optimized for ascending generators.""" |
935 """Special case of generatorset optimized for ascending generators.""" |
927 |
936 |
928 fastasc = generatorset._iterator |
937 fastasc = generatorset._iterator |
1085 else: |
1094 else: |
1086 x = max(self._end - stop, self._start) |
1095 x = max(self._end - stop, self._start) |
1087 y = max(self._end - start, self._start) |
1096 y = max(self._end - start, self._start) |
1088 return _spanset(x, y, self._ascending, self._hiddenrevs) |
1097 return _spanset(x, y, self._ascending, self._hiddenrevs) |
1089 |
1098 |
|
1099 @encoding.strmethod |
1090 def __repr__(self): |
1100 def __repr__(self): |
1091 d = {False: '-', True: '+'}[self._ascending] |
1101 d = {False: '-', True: '+'}[self._ascending] |
1092 return '<%s%s %d:%d>' % (type(self).__name__.lstrip('_'), d, |
1102 return '<%s%s %d:%d>' % (_typename(self), d, self._start, self._end) |
1093 self._start, self._end) |
|
1094 |
1103 |
1095 class fullreposet(_spanset): |
1104 class fullreposet(_spanset): |
1096 """a set containing all revisions in the repo |
1105 """a set containing all revisions in the repo |
1097 |
1106 |
1098 This class exists to host special optimization and magic to handle virtual |
1107 This class exists to host special optimization and magic to handle virtual |