Changeset af9b561 in rtems-tools


Ignore:
Timestamp:
May 30, 2019, 10:26:55 AM (3 weeks ago)
Author:
Chris Johns <chrisj@…>
Branches:
master
Children:
89dcdbc
Parents:
5dd75b0
git-author:
Chris Johns <chrisj@…> (05/30/19 10:26:55)
git-committer:
Chris Johns <chrisj@…> (06/11/19 01:00:30)
Message:

rtemstoolkit/path: Merge RSB changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • rtemstoolkit/path.py

    r5dd75b0 raf9b561  
    4141import shutil
    4242import string
     43import sys
    4344
    4445from rtemstoolkit import error
    4546from rtemstoolkit import log
    46 
     47windows_posix = sys.platform == 'msys'
    4748windows = os.name == 'nt'
     49
     50win_maxpath = 254
    4851
    4952def host(path):
     
    5154        while '//' in path:
    5255            path = path.replace('//', '/')
    53         if windows and len(path) > 2:
    54             if path[0] == '/' and path[2] == '/' and \
    55                     (path[1] in string.ascii_lowercase or \
    56                          path[1] in string.ascii_uppercase):
    57                 path = ('%s:%s' % (path[1], path[2:])).replace('/', '\\')
     56        if windows:
     57            if len(path) > 2 and \
     58               path[0] == '/' and path[2] == '/' and \
     59               (path[1] in string.ascii_lowercase or \
     60                path[1] in string.ascii_uppercase):
     61                path = '%s:%s' % (path[1], path[2:])
     62            path = path.replace('/', '\\')
     63            if len(path) > win_maxpath:
     64                if path.startswith('\\\\?\\'):
     65                    path = path[4:]
     66                path = u'\\'.join([u'\\\\?', path])
    5867    return path
    5968
    6069def shell(path):
     70    if isinstance(path, bytes):
     71        path = path.decode('ascii')
    6172    if path is not None:
    62         if windows and len(path) > 1 and path[1] == ':':
    63             path = ('/%s%s' % (path[0], path[2:])).replace('\\', '/')
     73        if windows or windows_posix:
     74            path = path.encode('ascii', 'ignore').decode('ascii')
     75            if path.startswith('\\\\?\\'):
     76                path = path[4:]
     77            if len(path) > 1 and path[1] == ':':
     78                path = '/%s%s' % (path[0].lower(), path[2:])
     79            path = path.replace('\\', '/')
    6480        while '//' in path:
    6581            path = path.replace('//', '/')
     
    6783
    6884def basename(path):
     85    path = shell(path)
    6986    return shell(os.path.basename(path))
    7087
    7188def dirname(path):
     89    path = shell(path)
    7290    return shell(os.path.dirname(path))
     91
     92def is_abspath(path):
     93    if path is not None and len(path) > 0:
     94        return '/' == path[0]
     95    return False
    7396
    7497def join(path, *args):
     
    82105
    83106def abspath(path):
     107    path = shell(path)
    84108    return shell(os.path.abspath(host(path)))
    85109
     110def relpath(path, start = None):
     111    path = shell(path)
     112    if start is None:
     113        path = os.path.relpath(host(path))
     114    else:
     115        path = os.path.relpath(host(path), start)
     116    return shell(path)
     117
    86118def splitext(path):
     119    path = shell(path)
    87120    root, ext = os.path.splitext(host(path))
    88121    return shell(root), ext
    89122
     123def listdir(path, error = True):
     124    path = host(path)
     125    files = []
     126    if not os.path.exists(path):
     127        if error:
     128            raise error.general('path does not exist : %s' % (path))
     129    elif not isdir(path):
     130        if error:
     131            raise error.general('path is not a directory: %s' % (path))
     132    else:
     133        if windows:
     134            try:
     135                files = os.listdir(host(path))
     136            except IOError:
     137                raise error.general('Could not list files: %s' % (path))
     138            except OSError as e:
     139                raise error.general('Could not list files: %s: %s' % (path, str(e)))
     140            except WindowsError as e:
     141                raise error.general('Could not list files: %s: %s' % (path, str(e)))
     142        else:
     143            try:
     144                files = os.listdir(host(path))
     145            except IOError:
     146                raise error.general('Could not list files: %s' % (path))
     147            except OSError as e:
     148                raise error.general('Could not list files: %s: %s' % (path, str(e)))
     149    return files
     150
    90151def exists(paths):
     152    def _exists(p):
     153        if not is_abspath(p):
     154            p = shell(join(os.getcwd(), host(p)))
     155        return basename(p) in ['.'] + listdir(dirname(p), error = False)
     156
    91157    if type(paths) == list:
    92158        results = []
    93159        for p in paths:
    94             results += [os.path.exists(host(p))]
     160            results += [_exists(shell(p))]
    95161        return results
    96     return os.path.exists(host(paths))
     162    return _exists(shell(paths))
    97163
    98164def isdir(path):
     165    path = shell(path)
    99166    return os.path.isdir(host(path))
    100167
    101168def isfile(path):
     169    path = shell(path)
    102170    return os.path.isfile(host(path))
    103171
    104172def isabspath(path):
     173    path = shell(path)
    105174    return path[0] == '/'
    106175
     176def isreadable(path):
     177    path = shell(path)
     178    return os.access(host(path), os.R_OK)
     179
    107180def iswritable(path):
     181    path = shell(path)
    108182    return os.access(host(path), os.W_OK)
     183
     184def isreadwritable(path):
     185    path = shell(path)
     186    return isreadable(path) and iswritable(path)
    109187
    110188def ispathwritable(path):
    111189    path = host(path)
    112190    while len(path) != 0:
    113         if os.path.exists(path):
     191        if exists(path):
    114192            return iswritable(path)
    115193        path = os.path.dirname(path)
     
    139217                raise error.general('cannot make directory: %s: %s' % (path, str(e)))
    140218
     219def chdir(path):
     220    path = shell(path)
     221    os.chdir(host(path))
     222
    141223def removeall(path):
    142 
    143     def _onerror(function, path, excinfo):
    144         print('removeall error: (%s) %s' % (excinfo, path))
    145 
    146     path = host(path)
    147     shutil.rmtree(path, onerror = _onerror)
     224    #
     225    # Perform the removal of the directory tree manually so we can
     226    # make sure on Windows the files are correctly encoded to avoid
     227    # the file name size limit. On Windows the os.walk fails once we
     228    # get to the max path length.
     229    #
     230    def _isdir(path):
     231        hpath = host(path)
     232        return os.path.isdir(hpath) and not os.path.islink(hpath)
     233
     234    def _remove_node(path):
     235        hpath = host(path)
     236        if not os.path.islink(hpath) and not os.access(hpath, os.W_OK):
     237            os.chmod(hpath, stat.S_IWUSR)
     238        if _isdir(path):
     239            os.rmdir(hpath)
     240        else:
     241            os.unlink(hpath)
     242
     243    def _remove(path):
     244        dirs = []
     245        for name in listdir(path):
     246            path_ = join(path, name)
     247            hname = host(path_)
     248            if _isdir(path_):
     249                dirs += [name]
     250            else:
     251                _remove_node(path_)
     252        for name in dirs:
     253            dir = join(path, name)
     254            _remove(dir)
     255            _remove_node(dir)
     256
     257    path = shell(path)
     258    hpath = host(path)
     259
     260    if os.path.exists(hpath):
     261        _remove(path)
     262        _remove_node(path)
    148263
    149264def expand(name, paths):
    150265    l = []
    151266    for p in paths:
    152         l += [join(p, name)]
     267        l += [join(shell(p), name)]
    153268    return l
    154269
     
    157272    path = os.path.expanduser(path)
    158273    return shell(path)
    159 
    160 def listdir(path):
    161     path = host(path)
    162     files = []
    163     if not exists(path):
    164         raise error.general('path does not exist : %s' % (path))
    165     elif not isdir(path):
    166         raise error.general('path is not a directory: %s' % (path))
    167     else:
    168         if windows:
    169             try:
    170                 files = os.listdir(host(path))
    171             except IOError:
    172                 raise error.general('Could not list files: %s' % (path))
    173             except OSError as e:
    174                 raise error.general('Could not list files: %s: %s' % (path, str(e)))
    175             except WindowsError as e:
    176                 raise error.general('Could not list files: %s: %s' % (path, str(e)))
    177         else:
    178             try:
    179                 files = os.listdir(host(path))
    180             except IOError:
    181                 raise error.general('Could not list files: %s' % (path))
    182             except OSError as e:
    183                 raise error.general('Could not list files: %s: %s' % (path, str(e)))
    184 
    185     return files
    186274
    187275def collect_files(path_):
     
    207295    return sorted(files)
    208296
    209 def copy_tree(src, dst):
     297def copy(src, dst):
     298    src = shell(src)
     299    dst = shell(dst)
    210300    hsrc = host(src)
    211301    hdst = host(dst)
    212 
    213     if os.path.exists(src) and os.path.isdir(src):
     302    try:
     303        shutil.copy(hsrc, hdst)
     304    except OSError as why:
     305        if windows:
     306            if WindowsError is not None and isinstance(why, WindowsError):
     307                pass
     308        else:
     309            raise error.general('copying tree (1): %s -> %s: %s' % (hsrc, hdst, str(why)))
     310
     311def copy_tree(src, dst):
     312    trace = False
     313
     314    hsrc = host(src)
     315    hdst = host(dst)
     316
     317    if exists(src):
    214318        names = listdir(src)
    215319    else:
    216         names = [basename(src)]
    217         src = dirname(src)
    218 
    219     if not os.path.isdir(dst):
    220         os.makedirs(dst)
     320        names = []
     321
     322    if trace:
     323        print('path.copy_tree:')
     324        print('   src: "%s"' % (src))
     325        print('  hsrc: "%s"' % (hsrc))
     326        print('   dst: "%s"' % (dst))
     327        print('  hdst: "%s"' % (hdst))
     328        print(' names: %r' % (names))
     329
     330    if not os.path.isdir(hdst):
     331        if trace:
     332            print(' mkdir: %s' % (hdst))
     333        try:
     334            os.makedirs(hdst)
     335        except OSError as why:
     336            raise error.general('copying tree: cannot create target directory %s: %s' % \
     337                                (hdst, str(why)))
    221338
    222339    for name in names:
    223         srcname = os.path.join(src, name)
    224         dstname = os.path.join(dst, name)
     340        srcname = host(os.path.join(hsrc, name))
     341        dstname = host(os.path.join(hdst, name))
    225342        try:
    226343            if os.path.islink(srcname):
    227344                linkto = os.readlink(srcname)
    228                 if os.path.exists(dstname):
     345                if exists(shell(dstname)):
    229346                    if os.path.islink(dstname):
    230347                        dstlinkto = os.readlink(dstname)
    231348                        if linkto != dstlinkto:
    232                             log.warning('copying tree: update of link does not match: %s -> %s' % \
     349                            log.warning('copying tree: link does not match: %s -> %s' % \
    233350                                            (dstname, dstlinkto))
    234351                            os.remove(dstname)
     
    242359                copy_tree(srcname, dstname)
    243360            else:
    244                 shutil.copy2(srcname, dstname)
     361                shutil.copyfile(host(srcname), host(dstname))
     362                shutil.copystat(host(srcname), host(dstname))
    245363        except shutil.Error as err:
    246             raise error.general('copying tree: %s -> %s: %s' % (src, dst, str(err)))
     364            raise error.general('copying tree (2): %s -> %s: %s' % \
     365                                (hsrc, hdst, str(err)))
    247366        except EnvironmentError as why:
    248             raise error.general('copying tree: %s -> %s: %s' % (srcname, dstname, str(why)))
     367            raise error.general('copying tree (3): %s -> %s: %s' % \
     368                                (srcname, dstname, str(why)))
    249369    try:
    250         shutil.copystat(src, dst)
     370        shutil.copystat(hsrc, hdst)
    251371    except OSError as why:
    252         ok = False
    253372        if windows:
    254373            if WindowsError is not None and isinstance(why, WindowsError):
    255                 ok = True
    256         if not ok:
    257             raise error.general('copying tree: %s -> %s: %s' % (src, dst, str(why)))
     374                pass
     375        else:
     376            raise error.general('copying tree (4): %s -> %s: %s' % (hsrc, hdst, str(why)))
     377
     378def get_size(path, depth = -1):
     379    #
     380    # Get the size the directory tree manually to the required depth.
     381    # This makes sure on Windows the files are correctly encoded to avoid
     382    # the file name size limit. On Windows the os.walk fails once we
     383    # get to the max path length on Windows.
     384    #
     385    def _isdir(path):
     386        hpath = host(path)
     387        return os.path.isdir(hpath) and not os.path.islink(hpath)
     388
     389    def _node_size(path):
     390        hpath = host(path)
     391        size = 0
     392        if not os.path.islink(hpath):
     393            size = os.path.getsize(hpath)
     394        return size
     395
     396    def _get_size(path, depth, level = 0):
     397        level += 1
     398        dirs = []
     399        size = 0
     400        for name in listdir(path):
     401            path_ = join(path, shell(name))
     402            hname = host(path_)
     403            if _isdir(path_):
     404                dirs += [shell(name)]
     405            else:
     406                size += _node_size(path_)
     407        if depth < 0 or level < depth:
     408            for name in dirs:
     409                dir = join(path, name)
     410                size += _get_size(dir, depth, level)
     411        return size
     412
     413    path = shell(path)
     414    hpath = host(path)
     415    size = 0
     416
     417    if os.path.exists(hpath):
     418        size = _get_size(path, depth)
     419
     420    return size
     421
     422def get_humanize_size(path, depth = -1):
     423    size = get_size(path, depth)
     424    for unit in ['','K','M','G','T','P','E','Z']:
     425        if abs(size) < 1024.0:
     426            return "%5.3f%sB" % (size, unit)
     427        size /= 1024.0
     428    return "%.3f%sB" % (size, 'Y')
    258429
    259430if __name__ == '__main__':
     
    272443    print(dirname('x:/sd/df/fg/me.txt'))
    273444    print(join('s:/d/', '/g', '/tyty/fgfg'))
     445    print(join('s:/d/e\\f/g', '/h', '/tyty/zxzx', '\\mm\\nn/p'))
Note: See TracChangeset for help on using the changeset viewer.