429
def glob_one(possible_glob):
430
"""Same as glob.glob().
432
work around bugs in glob.glob()
433
- Python bug #1001604 ("glob doesn't return unicode with ...")
434
- failing expansion for */* with non-iso-8859-* chars
436
corrected_glob, corrected = _ensure_with_dir(possible_glob)
437
glob_files = glob.glob(corrected_glob)
440
# special case to let the normal code path handle
441
# files that do not exist, etc.
442
glob_files = [possible_glob]
444
glob_files = [_undo_ensure_with_dir(elem, corrected)
445
for elem in glob_files]
446
return [elem.replace(u'\\', u'/') for elem in glob_files]
424
449
def glob_expand(file_list):
425
450
"""Replacement for glob expansion by the shell.
435
460
if not file_list:
438
462
expanded_file_list = []
439
463
for possible_glob in file_list:
440
# work around bugs in glob.glob()
441
# - Python bug #1001604 ("glob doesn't return unicode with ...")
442
# - failing expansion for */* with non-iso-8859-* chars
443
possible_glob, corrected = _ensure_with_dir(possible_glob)
444
glob_files = glob.glob(possible_glob)
447
# special case to let the normal code path handle
448
# files that do not exists
449
expanded_file_list.append(
450
_undo_ensure_with_dir(possible_glob, corrected))
452
glob_files = [_undo_ensure_with_dir(elem, corrected) for elem in glob_files]
453
expanded_file_list += glob_files
455
return [elem.replace(u'\\', u'/') for elem in expanded_file_list]
464
expanded_file_list.extend(glob_one(possible_glob))
465
return expanded_file_list
458
468
def get_app_path(appname):
499
509
def set_file_attr_hidden(path):
500
510
"""Set file attributes to hidden if possible"""
501
511
if has_win32file:
502
win32file.SetFileAttributes(path, win32file.FILE_ATTRIBUTE_HIDDEN)
512
if winver != 'Windows 98':
513
SetFileAttributes = win32file.SetFileAttributesW
515
SetFileAttributes = win32file.SetFileAttributes
517
SetFileAttributes(path, win32file.FILE_ATTRIBUTE_HIDDEN)
518
except pywintypes.error, e:
519
from bzrlib import trace
520
trace.mutter('Unable to set hidden attribute on %r: %s', path, e)
524
class UnicodeShlex(object):
525
"""This is a very simplified version of shlex.shlex.
527
The main change is that it supports non-ascii input streams. The internal
528
structure is quite simplified relative to shlex.shlex, since we aren't
529
trying to handle multiple input streams, etc. In fact, we don't use a
530
file-like api either.
533
def __init__(self, uni_string):
534
self._input = uni_string
535
self._input_iter = iter(self._input)
536
self._whitespace_match = re.compile(u'\s').match
537
self._word_match = re.compile(u'\S').match
538
self._quote_chars = u'"'
539
# self._quote_match = re.compile(u'[\'"]').match
540
self._escape_match = lambda x: None # Never matches
543
# ' ' - after whitespace, starting a new token
544
# 'a' - after text, currently working on a token
545
# '"' - after ", currently in a "-delimited quoted section
546
# "\" - after '\', checking the next char
548
self._token = [] # Current token being parsed
550
def _get_token(self):
551
# Were there quote chars as part of this token?
554
for nextchar in self._input_iter:
555
if self._state == ' ':
556
if self._whitespace_match(nextchar):
557
# if self._token: return token
559
elif nextchar in self._quote_chars:
560
self._state = nextchar # quoted state
561
elif self._word_match(nextchar):
562
self._token.append(nextchar)
565
raise AssertionError('wtttf?')
566
elif self._state in self._quote_chars:
568
if nextchar == self._state: # End of quote
569
self._state = 'a' # posix allows 'foo'bar to translate to
571
elif self._state == '"' and nextchar == self._escape:
572
quoted_state = self._state
573
self._state = nextchar
575
self._token.append(nextchar)
576
elif self._state == self._escape:
578
self._token.append('\\')
579
elif nextchar == '"':
580
self._token.append(nextchar)
582
self._token.append('\\' + nextchar)
583
self._state = quoted_state
584
elif self._state == 'a':
585
if self._whitespace_match(nextchar):
587
break # emit this token
589
continue # no token to emit
590
elif nextchar in self._quote_chars:
591
# Start a new quoted section
592
self._state = nextchar
594
elif (self._word_match(nextchar)
595
or nextchar in self._quote_chars
596
# or whitespace_split?
598
self._token.append(nextchar)
600
raise AssertionError('state == "a", char: %r'
603
raise AssertionError('unknown state: %r' % (self._state,))
604
result = ''.join(self._token)
606
if not quoted and result == '':
608
return quoted, result
614
quoted, token = self._get_token()
620
def _command_line_to_argv(command_line):
621
"""Convert a Unicode command line into a set of argv arguments.
623
This does wildcard expansion, etc. It is intended to make wildcards act
624
closer to how they work in posix shells, versus how they work by default on
627
s = UnicodeShlex(command_line)
628
# Now that we've split the content, expand globs
629
# TODO: Use 'globbing' instead of 'glob.glob', this gives us stuff like
632
for is_quoted, arg in s:
633
if is_quoted or not glob.has_magic(arg):
636
args.extend(glob_one(arg))
505
640
if has_ctypes and winver != 'Windows 98':
511
646
GetCommandLine = prototype(("GetCommandLineW",
512
647
ctypes.windll.kernel32))
513
648
prototype = ctypes.WINFUNCTYPE(POINTER(LPCWSTR), LPCWSTR, POINTER(INT))
514
CommandLineToArgv = prototype(("CommandLineToArgvW",
515
ctypes.windll.shell32))
517
pargv = CommandLineToArgv(GetCommandLine(), ctypes.byref(c))
649
command_line = GetCommandLine()
518
650
# Skip the first argument, since we only care about parameters
519
argv = [pargv[i] for i in range(1, c.value)]
651
argv = _command_line_to_argv(GetCommandLine())[1:]
520
652
if getattr(sys, 'frozen', None) is None:
521
653
# Invoked via 'python.exe' which takes the form:
522
654
# python.exe [PYTHON_OPTIONS] C:\Path\bzr [BZR_OPTIONS]
523
655
# we need to get only BZR_OPTIONS part,
524
# so let's using sys.argv[1:] as reference to get the tail
526
tail_len = len(sys.argv[1:])
527
ix = len(argv) - tail_len
656
# We already removed 'python.exe' so we remove everything up to and
657
# including the first non-option ('-') argument.
658
for idx in xrange(len(argv)):
659
if argv[idx][:1] != '-':
531
664
get_unicode_argv = None