|  | 
| 1 | 1 | from rpg.plugin import Plugin | 
|  | 2 | +import re | 
|  | 3 | +import rpm | 
|  | 4 | +import os | 
|  | 5 | +import sys | 
|  | 6 | +import tempfile | 
|  | 7 | +import io | 
|  | 8 | +import locale | 
|  | 9 | + | 
|  | 10 | + | 
|  | 11 | +# This has been copied from: | 
|  | 12 | +#   https://github.com/phracek/rebase-helper | 
|  | 13 | +def _dump(): | 
|  | 14 | +    """ | 
|  | 15 | +    Captures output of %dump macro | 
|  | 16 | +    :return: Raw %dump macro output as a list of lines | 
|  | 17 | +    """ | 
|  | 18 | +    # %dump macro prints results to stderr | 
|  | 19 | +    # we cannot use sys.stderr because it can be modified by pytest | 
|  | 20 | +    err = sys.__stderr__.fileno() | 
|  | 21 | +    defenc = locale.getpreferredencoding() | 
|  | 22 | +    defenc = 'utf-8' if defenc == 'ascii' else defenc | 
|  | 23 | +    with tempfile.TemporaryFile(mode='w+b') as tmp: | 
|  | 24 | +        with os.fdopen(os.dup(err), 'wb') as copied: | 
|  | 25 | +            try: | 
|  | 26 | +                sys.stderr.flush() | 
|  | 27 | +                os.dup2(tmp.fileno(), err) | 
|  | 28 | +                try: | 
|  | 29 | +                    rpm.expandMacro('%dump') | 
|  | 30 | +                finally: | 
|  | 31 | +                    sys.stderr.flush() | 
|  | 32 | +                    os.dup2(copied.fileno(), err) | 
|  | 33 | +            finally: | 
|  | 34 | +                tmp.flush() | 
|  | 35 | +                tmp.seek(0, io.SEEK_SET) | 
|  | 36 | +                for macro in re.finditer( | 
|  | 37 | +                        "-14\: (\w+).*(?=\n-14)", tmp.read().decode(defenc)): | 
|  | 38 | +                    expanded = rpm.expandMacro("%" + macro.group(1)) | 
|  | 39 | +                    if os.path.isdir(expanded) and expanded != '': | 
|  | 40 | +                        yield (expanded, "%{" + macro.group(1) + "}") | 
|  | 41 | + | 
|  | 42 | +# priority list - here are all default directory paths | 
|  | 43 | +PRIO = [ | 
|  | 44 | +    "%{_mandir}", | 
|  | 45 | +    "%{_defaultdocdir}", | 
|  | 46 | +    "%{_defaultlicencedir}", | 
|  | 47 | +    "%{_fileattrsdir}", | 
|  | 48 | +    "%{fmoddir}", | 
|  | 49 | +    "%{_includedir}", | 
|  | 50 | +    "%{_sbindir}", | 
|  | 51 | +    "%{_bindir}", | 
|  | 52 | +    "%{_libdir}", | 
|  | 53 | +    "%{_libexecdir}", | 
|  | 54 | +    "%{_infodir}", | 
|  | 55 | +    "%{_datadir}", | 
|  | 56 | +    "%{_sharedstatedir}", | 
|  | 57 | +    "%{_localstatedir}", | 
|  | 58 | +    "%{_sysconfdir}", | 
|  | 59 | +] | 
| 2 | 60 | 
 | 
| 3 | 61 | 
 | 
| 4 | 62 | class FindFilePlugin(Plugin): | 
| 5 | 63 | 
 | 
|  | 64 | +    # expand %dump, gets dir macros and sort them by len and by prio | 
|  | 65 | +    # (priority is for duplicates like _kde4_dir and _libdir where defaultly | 
|  | 66 | +    #  _libdir should be picked) | 
|  | 67 | +    MACROS = sorted(_dump(), reverse=True, | 
|  | 68 | +                    key=lambda x: len(x[0]) * 2 + (1 if x[1] in PRIO else 0)) | 
|  | 69 | + | 
| 6 | 70 |     def installed(self, project_dir, spec, sack): | 
| 7 | 71 |         """ Finds files that will be installed and | 
| 8 |  | -            appends them to files macro """ | 
| 9 |  | -        for item in list(project_dir.glob('**/*')): | 
| 10 |  | -            if item.is_file(): | 
| 11 |  | -                spec.files.add(("/" + str(item.relative_to(project_dir)), | 
| 12 |  | -                                None, None)) | 
|  | 72 | +            replaces prefix with rpm macro """ | 
|  | 73 | + | 
|  | 74 | +        def relative(_file, _relative): | 
|  | 75 | +            return "/" + str(_file.relative_to(_relative)) | 
|  | 76 | + | 
|  | 77 | +        def append(_file, _spec): | 
|  | 78 | +            _spec.files.add((_file, None, None)) | 
|  | 79 | + | 
|  | 80 | +        def find_n_replace(_file, f, *r): | 
|  | 81 | +            match = re.search("^" + f[0], _file) | 
|  | 82 | +            if match: | 
|  | 83 | +                return f[1] + _file[len(match.group(0)):] | 
|  | 84 | +            else: | 
|  | 85 | +                return find_n_replace(_file, *r) if r else _file | 
|  | 86 | + | 
|  | 87 | +        def ite(_spec, _proj_dir, f, *r): | 
|  | 88 | +            if f.is_file(): | 
|  | 89 | +                append(find_n_replace(relative(f, _proj_dir), *self.MACROS), | 
|  | 90 | +                       _spec) | 
|  | 91 | +            if r: | 
|  | 92 | +                ite(_spec, _proj_dir, *r) | 
|  | 93 | + | 
|  | 94 | +        def iterate(_spec, _proj_dir, _glob): | 
|  | 95 | +            if _glob: | 
|  | 96 | +                ite(_spec, _proj_dir, *_glob) | 
|  | 97 | + | 
|  | 98 | +        iterate(spec, project_dir, list(project_dir.glob('**/*'))) | 
0 commit comments