source: rtems-source-builder/source-builder/sb/path.py @ 4021c28

5
Last change on this file since 4021c28 was 4021c28, checked in by Chris Johns <chrisj@…>, on 10/14/17 at 14:18:44

sb: Fix the interface to all path function to be shell paths.

  • Add an is_abspath call.
  • Convert the path or paths to shell paths on entry to all path calls. This is safe to do for a path that is already a shell path.
  • Fix exists to use shell paths.
  • Property mode set to 100644
File size: 9.4 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'
37win_maxpath = 254
38
39def host(path):
40    if path is not None:
41        while '//' in path:
42            path = path.replace('//', '/')
43        if windows:
44            if len(path) > 2 and \
45               path[0] == '/' and path[2] == '/' and \
46               (path[1] in string.ascii_lowercase or \
47                path[1] in string.ascii_uppercase):
48                path = '%s:%s' % (path[1], path[2:])
49            path = path.replace('/', '\\')
50            if len(path) > win_maxpath:
51                if path.startswith('\\\\?\\'):
52                    path = path[4:]
53                path = u'\\'.join([u'\\\\?', path])
54    return path
55
56def is_abspath(path):
57    if path is not None:
58        return '/' == path[0]
59    return False
60
61def shell(path):
62    if path is not None:
63        if windows:
64            path = path.encode('ascii', 'ignore')
65            if path.startswith('\\\\?\\'):
66                path = path[4:]
67            if len(path) > 1 and path[1] == ':':
68                path = '/%s%s' % (path[0], path[2:])
69            path = path.replace('\\', '/')
70        while '//' in path:
71            path = path.replace('//', '/')
72    return path
73
74def basename(path):
75    path = shell(path)
76    return shell(os.path.basename(host(path)))
77
78def dirname(path):
79    path = shell(path)
80    return shell(os.path.dirname(path))
81
82def join(path, *args):
83    path = shell(path)
84    for arg in args:
85        if len(path):
86            path += '/' + shell(arg)
87        else:
88            path = shell(arg)
89    return shell(path)
90
91def abspath(path):
92    path = shell(path)
93    return shell(os.path.abspath(host(path)))
94
95def splitext(path):
96    path = shell(path)
97    root, ext = os.path.splitext(host(path))
98    return shell(root), ext
99
100def listdir(path):
101    path = shell(path)
102    hp = host(path)
103    if not os.path.exists(hp):
104        return []
105    return os.listdir(hp)
106
107def exists(paths):
108    def _exists(p):
109        if not is_abspath(p):
110            p = shell(join(os.getcwd(), host(p)))
111        return basename(p) in ['.'] + listdir(dirname(p))
112
113    if type(paths) == list:
114        results = []
115        for p in paths:
116            results += [_exists(shell(p))]
117        return results
118    return _exists(shell(paths))
119
120def isdir(path):
121    path = shell(path)
122    return os.path.isdir(host(path))
123
124def isfile(path):
125    path = shell(path)
126    return os.path.isfile(host(path))
127
128def isabspath(path):
129    path = shell(path)
130    return path[0] == '/'
131
132def iswritable(path):
133    path = shell(path)
134    return os.access(host(path), os.W_OK)
135
136def ispathwritable(path):
137    path = shell(path)
138    while len(path) != 0:
139        if exists(path):
140            return iswritable(path)
141        path = dirname(path)
142    return False
143
144def mkdir(path):
145    path = shell(path)
146    if exists(path):
147        if not isdir(path):
148            raise error.general('path exists and is not a directory: %s' % (path))
149    else:
150        if windows:
151            try:
152                os.makedirs(host(path))
153            except IOError as err:
154                raise error.general('cannot make directory: %s' % (path))
155            except OSError as err:
156                raise error.general('cannot make directory: %s' % (path))
157            except WindowsError as err:
158                raise error.general('cannot make directory: %s' % (path))
159        else:
160            try:
161                os.makedirs(host(path))
162            except IOError as err:
163                raise error.general('cannot make directory: %s' % (path))
164            except OSError as err:
165                raise error.general('cannot make directory: %s' % (path))
166
167def chdir(path):
168    path = shell(path)
169    os.chdir(host(path))
170
171def removeall(path):
172    #
173    # Perform the removal of the directory tree manually so we can
174    # make sure on Windows the files are correctly encoded to avoid
175    # the file name size limit. On Windows the os.walk fails once we
176    # get to the max path length on Windows.
177    #
178    def _isdir(path):
179        hpath = host(path)
180        return os.path.isdir(hpath) and not os.path.islink(hpath)
181
182    def _remove_node(path):
183        hpath = host(path)
184        if not os.path.islink(hpath) and not os.access(hpath, os.W_OK):
185            os.chmod(hpath, stat.S_IWUSR)
186        if _isdir(path):
187            os.rmdir(hpath)
188        else:
189            os.unlink(hpath)
190
191    def _remove(path):
192        dirs = []
193        for name in listdir(path):
194            path_ = join(path, name)
195            hname = host(path_)
196            if _isdir(path_):
197                dirs += [name]
198            else:
199                _remove_node(path_)
200        for name in dirs:
201            dir = join(path, name)
202            _remove(dir)
203            _remove_node(dir)
204
205    path = shell(path)
206    hpath = host(path)
207
208    if os.path.exists(hpath):
209        _remove(path)
210        _remove_node(path)
211
212def expand(name, paths):
213    path = shell(path)
214    l = []
215    for p in paths:
216        l += [join(shell(p), name)]
217    return l
218
219def copy(src, dst):
220    src = shell(src)
221    dst = shell(dst)
222    hsrc = host(src)
223    hdst = host(dst)
224    try:
225        shutil.copy(hsrc, hdst)
226    except OSError as why:
227        if windows:
228            if WindowsError is not None and isinstance(why, WindowsError):
229                pass
230        else:
231            raise error.general('copying tree (1): %s -> %s: %s' % (hsrc, hdst, str(why)))
232
233def copy_tree(src, dst):
234    trace = False
235
236    hsrc = host(src)
237    hdst = host(dst)
238
239    if exists(src):
240        names = listdir(src)
241    else:
242        names = []
243
244    if trace:
245        print('path.copy_tree:')
246        print('   src: "%s"' % (src))
247        print('  hsrc: "%s"' % (hsrc))
248        print('   dst: "%s"' % (dst))
249        print('  hdst: "%s"' % (hdst))
250        print(' names: %r' % (names))
251
252    if not os.path.isdir(hdst):
253        if trace:
254            print(' mkdir: %s' % (hdst))
255        try:
256            os.makedirs(hdst)
257        except OSError as why:
258            raise error.general('copying tree: cannot create target directory %s: %s' % \
259                                (hdst, str(why)))
260
261    for name in names:
262        srcname = host(os.path.join(hsrc, name))
263        dstname = host(os.path.join(hdst, name))
264        try:
265            if os.path.islink(srcname):
266                linkto = os.readlink(srcname)
267                if exists(shell(dstname)):
268                    if os.path.islink(dstname):
269                        dstlinkto = os.readlink(dstname)
270                        if linkto != dstlinkto:
271                            log.warning('copying tree: link does not match: %s -> %s' % \
272                                            (dstname, dstlinkto))
273                            os.remove(dstname)
274                    else:
275                        log.warning('copying tree: destination is not a link: %s' % \
276                                        (dstname))
277                        os.remove(dstname)
278                else:
279                    os.symlink(linkto, dstname)
280            elif os.path.isdir(srcname):
281                copy_tree(srcname, dstname)
282            else:
283                shutil.copyfile(host(srcname), host(dstname))
284                shutil.copystat(host(srcname), host(dstname))
285        except shutil.Error as err:
286            raise error.general('copying tree (2): %s -> %s: %s' % \
287                                (hsrc, hdst, str(err)))
288        except EnvironmentError as why:
289            raise error.general('copying tree (3): %s -> %s: %s' % \
290                                (srcname, dstname, str(why)))
291    try:
292        shutil.copystat(hsrc, hdst)
293    except OSError as why:
294        if windows:
295            if WindowsError is not None and isinstance(why, WindowsError):
296                pass
297        else:
298            raise error.general('copying tree (4): %s -> %s: %s' % (hsrc, hdst, str(why)))
299
300if __name__ == '__main__':
301    print(host('/a/b/c/d-e-f'))
302    print(host('//a/b//c/d-e-f'))
303    print(shell('/w/x/y/z'))
304    print(basename('/as/sd/df/fg/me.txt'))
305    print(dirname('/as/sd/df/fg/me.txt'))
306    print(join('/d', 'g', '/tyty/fgfg'))
307    windows = True
308    print(host('/a/b/c/d-e-f'))
309    print(host('//a/b//c/d-e-f'))
310    print(shell('/w/x/y/z'))
311    print(shell('w:/x/y/z'))
312    print(basename('x:/sd/df/fg/me.txt'))
313    print(dirname('x:/sd/df/fg/me.txt'))
314    print(join('s:/d/e\\f/g', '/h', '/tyty/zxzx', '\\mm\\nn/p'))
Note: See TracBrowser for help on using the repository browser.