553 >>> _quote(1) |
553 >>> _quote(1) |
554 "'1'" |
554 "'1'" |
555 """ |
555 """ |
556 return "'%s'" % util.escapestr(pycompat.bytestr(s)) |
556 return "'%s'" % util.escapestr(pycompat.bytestr(s)) |
557 |
557 |
|
558 def _formatargtype(c, arg): |
|
559 if c == 'd': |
|
560 return '%d' % int(arg) |
|
561 elif c == 's': |
|
562 return _quote(arg) |
|
563 elif c == 'r': |
|
564 parse(arg) # make sure syntax errors are confined |
|
565 return '(%s)' % arg |
|
566 elif c == 'n': |
|
567 return _quote(node.hex(arg)) |
|
568 elif c == 'b': |
|
569 try: |
|
570 return _quote(arg.branch()) |
|
571 except AttributeError: |
|
572 raise TypeError |
|
573 raise error.ParseError(_('unexpected revspec format character %s') % c) |
|
574 |
|
575 def _formatlistexp(s, t): |
|
576 l = len(s) |
|
577 if l == 0: |
|
578 return "_list('')" |
|
579 elif l == 1: |
|
580 return _formatargtype(t, s[0]) |
|
581 elif t == 'd': |
|
582 return "_intlist('%s')" % "\0".join('%d' % int(a) for a in s) |
|
583 elif t == 's': |
|
584 return "_list(%s)" % _quote("\0".join(s)) |
|
585 elif t == 'n': |
|
586 return "_hexlist('%s')" % "\0".join(node.hex(a) for a in s) |
|
587 elif t == 'b': |
|
588 try: |
|
589 return "_list('%s')" % "\0".join(a.branch() for a in s) |
|
590 except AttributeError: |
|
591 raise TypeError |
|
592 |
|
593 m = l // 2 |
|
594 return '(%s or %s)' % (_formatlistexp(s[:m], t), _formatlistexp(s[m:], t)) |
|
595 |
558 def formatspec(expr, *args): |
596 def formatspec(expr, *args): |
559 ''' |
597 ''' |
560 This is a convenience function for using revsets internally, and |
598 This is a convenience function for using revsets internally, and |
561 escapes arguments appropriately. Aliases are intentionally ignored |
599 escapes arguments appropriately. Aliases are intentionally ignored |
562 so that intended expression behavior isn't accidentally subverted. |
600 so that intended expression behavior isn't accidentally subverted. |
587 >>> formatspec(b'root(%ls)', [b'a', b'b', b'c', b'd']) |
625 >>> formatspec(b'root(%ls)', [b'a', b'b', b'c', b'd']) |
588 "root(_list('a\\\\x00b\\\\x00c\\\\x00d'))" |
626 "root(_list('a\\\\x00b\\\\x00c\\\\x00d'))" |
589 >>> formatspec('%ls', ['a', "'"]) |
627 >>> formatspec('%ls', ['a', "'"]) |
590 "_list('a\\\\x00\\\\'')" |
628 "_list('a\\\\x00\\\\'')" |
591 ''' |
629 ''' |
592 |
|
593 def argtype(c, arg): |
|
594 if c == 'd': |
|
595 return '%d' % int(arg) |
|
596 elif c == 's': |
|
597 return _quote(arg) |
|
598 elif c == 'r': |
|
599 parse(arg) # make sure syntax errors are confined |
|
600 return '(%s)' % arg |
|
601 elif c == 'n': |
|
602 return _quote(node.hex(arg)) |
|
603 elif c == 'b': |
|
604 try: |
|
605 return _quote(arg.branch()) |
|
606 except AttributeError: |
|
607 raise TypeError |
|
608 raise error.ParseError(_('unexpected revspec format character %s') % c) |
|
609 |
|
610 def listexp(s, t): |
|
611 l = len(s) |
|
612 if l == 0: |
|
613 return "_list('')" |
|
614 elif l == 1: |
|
615 return argtype(t, s[0]) |
|
616 elif t == 'd': |
|
617 return "_intlist('%s')" % "\0".join('%d' % int(a) for a in s) |
|
618 elif t == 's': |
|
619 return "_list(%s)" % _quote("\0".join(s)) |
|
620 elif t == 'n': |
|
621 return "_hexlist('%s')" % "\0".join(node.hex(a) for a in s) |
|
622 elif t == 'b': |
|
623 try: |
|
624 return "_list('%s')" % "\0".join(a.branch() for a in s) |
|
625 except AttributeError: |
|
626 raise TypeError |
|
627 |
|
628 m = l // 2 |
|
629 return '(%s or %s)' % (listexp(s[:m], t), listexp(s[m:], t)) |
|
630 |
|
631 expr = pycompat.bytestr(expr) |
630 expr = pycompat.bytestr(expr) |
632 argiter = iter(args) |
631 argiter = iter(args) |
633 ret = [] |
632 ret = [] |
634 pos = 0 |
633 pos = 0 |
635 while pos < len(expr): |
634 while pos < len(expr): |
658 try: |
657 try: |
659 d = expr[pos] |
658 d = expr[pos] |
660 except IndexError: |
659 except IndexError: |
661 raise error.ParseError(_('incomplete revspec format character')) |
660 raise error.ParseError(_('incomplete revspec format character')) |
662 try: |
661 try: |
663 ret.append(listexp(list(arg), d)) |
662 ret.append(_formatlistexp(list(arg), d)) |
664 except (TypeError, ValueError): |
663 except (TypeError, ValueError): |
665 raise error.ParseError(_('invalid argument for revspec')) |
664 raise error.ParseError(_('invalid argument for revspec')) |
666 else: |
665 else: |
667 try: |
666 try: |
668 ret.append(argtype(d, arg)) |
667 ret.append(_formatargtype(d, arg)) |
669 except (TypeError, ValueError): |
668 except (TypeError, ValueError): |
670 raise error.ParseError(_('invalid argument for revspec')) |
669 raise error.ParseError(_('invalid argument for revspec')) |
671 pos += 1 |
670 pos += 1 |
672 |
671 |
673 try: |
672 try: |