/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/win32utils.py

  • Committer: Gordon Tyler
  • Date: 2010-02-02 04:37:56 UTC
  • mto: (5037.3.1 integration)
  • mto: This revision was merged to the branch mainline in revision 5046.
  • Revision ID: gordon@doxxx.net-20100202043756-nkub38sw5v80zx7o
Moved UnicodeShlex, etc. to a new module, bzrlib.cmdline, and renamed it to Parser.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
import struct
26
26
import sys
27
27
 
 
28
from bzrlib import cmdline
28
29
 
29
30
# Windows version
30
31
if sys.platform == 'win32':
517
518
            trace.mutter('Unable to set hidden attribute on %r: %s', path, e)
518
519
 
519
520
 
520
 
_whitespace_match = re.compile(u'\s', re.UNICODE).match
521
 
 
522
 
 
523
 
class _PushbackSequence(object):
524
 
    def __init__(self, orig):
525
 
        self._iter = iter(orig)
526
 
        self._pushback_buffer = []
527
 
        
528
 
    def next(self):
529
 
        if len(self._pushback_buffer) > 0:
530
 
            return self._pushback_buffer.pop()
531
 
        else:
532
 
            return self._iter.next()
533
 
    
534
 
    def pushback(self, char):
535
 
        self._pushback_buffer.append(char)
536
 
        
537
 
    def __iter__(self):
538
 
        return self
539
 
 
540
 
 
541
 
class _Whitespace(object):
542
 
    def process(self, next_char, seq, context):
543
 
        if _whitespace_match(next_char):
544
 
            if len(context.token) > 0:
545
 
                return None
546
 
            else:
547
 
                return self
548
 
        elif (next_char == u'"'
549
 
              or (context.single_quotes_allowed and next_char == u"'")):
550
 
            context.quoted = True
551
 
            return _Quotes(next_char, self)
552
 
        elif next_char == u'\\':
553
 
            return _Backslash(self)
554
 
        else:
555
 
            context.token.append(next_char)
556
 
            return _Word()
557
 
 
558
 
 
559
 
class _Quotes(object):
560
 
    def __init__(self, quote_char, exit_state):
561
 
        self.quote_char = quote_char
562
 
        self.exit_state = exit_state
563
 
 
564
 
    def process(self, next_char, seq, context):
565
 
        if next_char == u'\\':
566
 
            return _Backslash(self)
567
 
        elif next_char == self.quote_char:
568
 
            return self.exit_state
569
 
        else:
570
 
            context.token.append(next_char)
571
 
            return self
572
 
 
573
 
 
574
 
class _Backslash(object):
575
 
    # See http://msdn.microsoft.com/en-us/library/bb776391(VS.85).aspx
576
 
    def __init__(self, exit_state):
577
 
        self.exit_state = exit_state
578
 
        self.count = 1
579
 
        
580
 
    def process(self, next_char, seq, context):
581
 
        if next_char == u'\\':
582
 
            self.count += 1
583
 
            return self
584
 
        elif next_char == u'"':
585
 
            # 2N backslashes followed by '"' are N backslashes
586
 
            context.token.append(u'\\' * (self.count/2))
587
 
            # 2N+1 backslashes follwed by '"' are N backslashes followed by '"'
588
 
            # which should not be processed as the start or end of quoted arg
589
 
            if self.count % 2 == 1:
590
 
                context.token.append(next_char) # odd number of '\' escapes the '"'
591
 
            else:
592
 
                seq.pushback(next_char) # let exit_state handle next_char
593
 
            self.count = 0
594
 
            return self.exit_state
595
 
        else:
596
 
            # N backslashes not followed by '"' are just N backslashes
597
 
            if self.count > 0:
598
 
                context.token.append(u'\\' * self.count)
599
 
                self.count = 0
600
 
            seq.pushback(next_char) # let exit_state handle next_char
601
 
            return self.exit_state
602
 
    
603
 
    def finish(self, context):
604
 
        if self.count > 0:
605
 
            context.token.append(u'\\' * self.count)
606
 
 
607
 
 
608
 
class _Word(object):
609
 
    def process(self, next_char, seq, context):
610
 
        if _whitespace_match(next_char):
611
 
            return None
612
 
        elif (next_char == u'"'
613
 
              or (context.single_quotes_allowed and next_char == u"'")):
614
 
            return _Quotes(next_char, self)
615
 
        elif next_char == u'\\':
616
 
            return _Backslash(self)
617
 
        else:
618
 
            context.token.append(next_char)
619
 
            return self
620
 
 
621
 
 
622
 
class UnicodeShlex(object):
623
 
    def __init__(self, command_line, single_quotes_allowed=False):
624
 
        self._seq = _PushbackSequence(command_line)
625
 
        self.single_quotes_allowed = single_quotes_allowed
626
 
    
627
 
    def __iter__(self):
628
 
        return self
629
 
    
630
 
    def next(self):
631
 
        quoted, token = self._get_token()
632
 
        if token is None:
633
 
            raise StopIteration
634
 
        return quoted, token
635
 
    
636
 
    def _get_token(self):
637
 
        self.quoted = False
638
 
        self.token = []
639
 
        state = _Whitespace()
640
 
        for next_char in self._seq:
641
 
            state = state.process(next_char, self._seq, self)
642
 
            if state is None:
643
 
                break
644
 
        if not state is None and not getattr(state, 'finish', None) is None:
645
 
            state.finish(self)
646
 
        result = u''.join(self.token)
647
 
        if not self.quoted and result == '':
648
 
            result = None
649
 
        return self.quoted, result
650
 
 
651
 
 
652
521
def command_line_to_argv(command_line, wildcard_expansion=True,
653
522
                         single_quotes_allowed=False):
654
523
    """Convert a Unicode command line into a list of argv arguments.
665
534
                                  default.
666
535
    :return: A list of unicode strings.
667
536
    """
668
 
    s = UnicodeShlex(command_line, single_quotes_allowed=single_quotes_allowed)
 
537
    s = cmdline.Parser(command_line, single_quotes_allowed=single_quotes_allowed)
669
538
    # Now that we've split the content, expand globs if necessary
670
539
    # TODO: Use 'globbing' instead of 'glob.glob', this gives us stuff like
671
540
    #       '**/' style globs