source: rtems-source-builder/source-builder/sb/path.py @ 3ddbd79

5
Last change on this file since 3ddbd79 was 3ddbd79, checked in by Chris Johns <chrisj@…>, on 01/18/18 at 02:16:47

sb: Add an orphan check to sb-check.

The orphans check lets you see which configuration and build set
files in the RSB are not referernced. You can audit the list and
remove any configuration files not being used. Top level
build set files are included so you need to becareful not to
remove something that is valid and useful. To run:

$ ./source-builder/sb-check --check-orphans

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