source: rtems-source-builder/source-builder/sb/path.py @ f88fcf3

4.11
Last change on this file since f88fcf3 was f88fcf3, checked in by Chris Johns <chrisj@…>, on Mar 7, 2016 at 12:56:02 AM

sb: Update code base to support Python3 and Python2.

Fix Windows support to allow MSYS2 Python to be used.

Updates #2619.

  • Property mode set to 100644
File size: 8.3 KB
Line 
1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2010-2016 Chris Johns (chrisj@rtems.org)
4# All rights reserved.
5#
6# This file is part of the RTEMS Tools package in 'rtems-tools'.
7#
8# Permission to use, copy, modify, and/or distribute this software for any
9# purpose with or without fee is hereby granted, provided that the above
10# copyright notice and this permission notice appear in all copies.
11#
12# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20#
21# Manage paths locally. The internally the path is in Unix or shell format and
22# we convert to the native format when performing operations at the Python
23# level. This allows macro expansion to work.
24#
25
26from __future__ import print_function
27
28import log
29import os
30import shutil
31import stat
32import string
33
34import error
35
36windows = os.name == 'nt'
37
38def host(path):
39    if path is not None:
40        while '//' in path:
41            path = path.replace('//', '/')
42        if windows:
43            if len(path) > 2 and \
44               path[0] == '/' and path[2] == '/' and \
45               (path[1] in string.ascii_lowercase or \
46                path[1] in string.ascii_uppercase):
47                path = '%s:%s' % (path[1], path[2:])
48            path = path.replace('/', '\\')
49            if not path.startswith('\\\\?\\') and len(path) > 254:
50                path = '\\\\?\\' + path
51    return path
52
53def shell(path):
54    if path is not None:
55        if windows:
56            if path.startswith('\\\\?\\'):
57                path = path[4:]
58            if len(path) > 1 and path[1] == ':':
59                path = '/%s%s' % (path[0], path[2:])
60            path = path.replace('\\', '/')
61        while '//' in path:
62            path = path.replace('//', '/')
63    return path
64
65def basename(path):
66    return shell(os.path.basename(path))
67
68def dirname(path):
69    return shell(os.path.dirname(path))
70
71def join(path, *args):
72    path = shell(path)
73    for arg in args:
74        if len(path):
75            path += '/' + shell(arg)
76        else:
77            path = shell(arg)
78    return shell(path)
79
80def abspath(path):
81    return shell(os.path.abspath(host(path)))
82
83def splitext(path):
84    root, ext = os.path.splitext(host(path))
85    return shell(root), ext
86
87def exists(paths):
88    if type(paths) == list:
89        results = []
90        for p in paths:
91            results += [os.path.exists(host(p))]
92        return results
93    return os.path.exists(host(paths))
94
95def isdir(path):
96    return os.path.isdir(host(path))
97
98def isfile(path):
99    return os.path.isfile(host(path))
100
101def isabspath(path):
102    return path[0] == '/'
103
104def iswritable(path):
105    return os.access(host(path), os.W_OK)
106
107def ispathwritable(path):
108    path = host(path)
109    while len(path) != 0:
110        if os.path.exists(path):
111            return iswritable(path)
112        path = os.path.dirname(path)
113    return False
114
115def mkdir(path):
116    path = host(path)
117    if exists(path):
118        if not isdir(path):
119            raise error.general('path exists and is not a directory: %s' % (path))
120    else:
121        if windows:
122            try:
123                os.makedirs(host(path))
124            except IOError as err:
125                raise error.general('cannot make directory: %s' % (path))
126            except OSError as err:
127                raise error.general('cannot make directory: %s' % (path))
128            except WindowsError as err:
129                raise error.general('cannot make directory: %s' % (path))
130        else:
131            try:
132                os.makedirs(host(path))
133            except IOError as err:
134                raise error.general('cannot make directory: %s' % (path))
135            except OSError as err:
136                raise error.general('cannot make directory: %s' % (path))
137
138def removeall(path):
139    #
140    # Perform the removal of the directory tree manually so we can
141    # make sure on Windows the files and correctly encoded to avoid
142    # the size limit.
143    #
144    path = host(path)
145    for root, dirs, files in os.walk(path, topdown = False):
146        for name in files:
147            file = host(os.path.join(root, name))
148            if not os.path.islink(file) and not os.access(file, os.W_OK):
149                os.chmod(file, stat.S_IWUSR)
150            os.unlink(file)
151        for name in dirs:
152            dir = host(os.path.join(root, name))
153            if os.path.islink(dir):
154                os.unlink(dir)
155            else:
156                if not os.access(dir, os.W_OK):
157                    os.chmod(dir, stat.S_IWUSR)
158                os.rmdir(dir)
159    if not os.path.islink(path) and not os.access(path, os.W_OK):
160        os.chmod(path, stat.S_IWUSR)
161    if os.path.islink(path):
162        os.unlink(path)
163    else:
164        os.rmdir(path)
165
166def expand(name, paths):
167    l = []
168    for p in paths:
169        l += [join(p, name)]
170    return l
171
172def copy(src, dst):
173    hsrc = host(src)
174    hdst = host(dst)
175    try:
176        shutil.copy(hsrc, hdst)
177    except OSError as why:
178        if windows:
179            if WindowsError is not None and isinstance(why, WindowsError):
180                pass
181        else:
182            raise error.general('copying tree: %s -> %s: %s' % (hsrc, hdst, str(why)))
183
184def copy_tree(src, dst):
185    trace = False
186
187    hsrc = host(src)
188    hdst = host(dst)
189
190    if os.path.exists(hsrc):
191        names = os.listdir(hsrc)
192    else:
193        names = []
194
195    if trace:
196        print('path.copy_tree:')
197        print('   src: %s' % (src))
198        print('  hsrc: %s' % (hsrc))
199        print('   dst: %s' % (dst))
200        print('  hdst: %s' % (hdst))
201        print(' names: %r' % (names))
202
203    if not os.path.isdir(hdst):
204        if trace:
205            print(' mkdir: %s' % (hdst))
206        try:
207            os.makedirs(hdst)
208        except OSError as why:
209            raise error.general('copying tree: cannot create target directory %s: %s' % \
210                                (hdst, str(why)))
211
212    for name in names:
213        srcname = host(os.path.join(hsrc, name))
214        dstname = host(os.path.join(hdst, name))
215        try:
216            if os.path.islink(srcname):
217                linkto = os.readlink(srcname)
218                if os.path.exists(dstname):
219                    if os.path.islink(dstname):
220                        dstlinkto = os.readlink(dstname)
221                        if linkto != dstlinkto:
222                            log.warning('copying tree: link does not match: %s -> %s' % \
223                                            (dstname, dstlinkto))
224                            os.remove(dstname)
225                    else:
226                        log.warning('copying tree: destination is not a link: %s' % \
227                                        (dstname))
228                        os.remove(dstname)
229                else:
230                    os.symlink(linkto, dstname)
231            elif os.path.isdir(srcname):
232                copy_tree(srcname, dstname)
233            else:
234                    shutil.copy2(host(srcname), host(dstname))
235        except shutil.Error as err:
236            raise error.general('copying tree: %s -> %s: %s' % \
237                                (hsrc, hdst, str(err)))
238        except EnvironmentError as why:
239            raise error.general('copying tree: %s -> %s: %s' % \
240                                (srcname, dstname, str(why)))
241    try:
242        shutil.copystat(hsrc, hdst)
243    except OSError as why:
244        if windows:
245            if WindowsError is not None and isinstance(why, WindowsError):
246                pass
247        else:
248            raise error.general('copying tree: %s -> %s: %s' % (hsrc, hdst, str(why)))
249
250if __name__ == '__main__':
251    print(host('/a/b/c/d-e-f'))
252    print(host('//a/b//c/d-e-f'))
253    print(shell('/w/x/y/z'))
254    print(basename('/as/sd/df/fg/me.txt'))
255    print(dirname('/as/sd/df/fg/me.txt'))
256    print(join('/d', 'g', '/tyty/fgfg'))
257    windows = True
258    print(host('/a/b/c/d-e-f'))
259    print(host('//a/b//c/d-e-f'))
260    print(shell('/w/x/y/z'))
261    print(shell('w:/x/y/z'))
262    print(basename('x:/sd/df/fg/me.txt'))
263    print(dirname('x:/sd/df/fg/me.txt'))
264    print(join('s:/d/e\\f/g', '/h', '/tyty/zxzx', '\\mm\\nn/p'))
Note: See TracBrowser for help on using the repository browser.