(file_source, install_target)
| 41 | DIRECTORIES = set() |
| 42 | |
| 43 | def main(file_source, install_target): |
| 44 | with open(file_source, 'r', newline='') as f: |
| 45 | files = list(csv.reader(f)) |
| 46 | |
| 47 | assert len(files) == len(set(make_id(f[1]) for f in files)), "Duplicate file IDs exist" |
| 48 | |
| 49 | directories = defaultdict(set) |
| 50 | cache_directories = defaultdict(set) |
| 51 | groups = defaultdict(list) |
| 52 | for source, target, group, disk_id, condition in files: |
| 53 | target = PureWindowsPath(target) |
| 54 | groups[group].append((source, target, disk_id, condition)) |
| 55 | |
| 56 | if target.suffix.lower() in {".py", ".pyw"}: |
| 57 | cache_directories[group].add(target.parent) |
| 58 | |
| 59 | for dirname in target.parents: |
| 60 | parent = make_id(dirname.parent) |
| 61 | if parent and parent != '.': |
| 62 | directories[parent].add(dirname.name) |
| 63 | |
| 64 | lines = [ |
| 65 | '<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">', |
| 66 | ' <Fragment>', |
| 67 | ] |
| 68 | for dir_parent in sorted(directories): |
| 69 | lines.append(' <DirectoryRef Id="{}">'.format(dir_parent)) |
| 70 | for dir_name in sorted(directories[dir_parent]): |
| 71 | lines.append(' <Directory Id="{}_{}" Name="{}" />'.format(dir_parent, make_id(dir_name), dir_name)) |
| 72 | lines.append(' </DirectoryRef>') |
| 73 | for dir_parent in (make_id(d) for group in cache_directories.values() for d in group): |
| 74 | lines.append(' <DirectoryRef Id="{}">'.format(dir_parent)) |
| 75 | lines.append(' <Directory Id="{}___pycache__" Name="__pycache__" />'.format(dir_parent)) |
| 76 | lines.append(' </DirectoryRef>') |
| 77 | lines.append(' </Fragment>') |
| 78 | |
| 79 | for group in sorted(groups): |
| 80 | lines.extend([ |
| 81 | ' <Fragment>', |
| 82 | ' <ComponentGroup Id="{}">'.format(group), |
| 83 | ]) |
| 84 | for source, target, disk_id, condition in groups[group]: |
| 85 | lines.append(' <Component Id="{}" Directory="{}" Guid="*">'.format(make_id(target), make_id(target.parent))) |
| 86 | if condition: |
| 87 | lines.append(' <Condition>{}</Condition>'.format(condition)) |
| 88 | |
| 89 | if disk_id: |
| 90 | lines.append(' <File Id="{}" Name="{}" Source="{}" DiskId="{}" />'.format(make_id(target), target.name, source, disk_id)) |
| 91 | else: |
| 92 | lines.append(' <File Id="{}" Name="{}" Source="{}" />'.format(make_id(target), target.name, source)) |
| 93 | lines.append(' </Component>') |
| 94 | |
| 95 | create_folders = {make_id(p) + "___pycache__" for p in cache_directories[group]} |
| 96 | remove_folders = {make_id(p2) for p1 in cache_directories[group] for p2 in chain((p1,), p1.parents)} |
| 97 | create_folders.discard(".") |
| 98 | remove_folders.discard(".") |
| 99 | if create_folders or remove_folders: |
| 100 | lines.append(' <Component Id="{}__pycache__folders" Directory="TARGETDIR" Guid="{}">'.format(group, uuid1())) |
no test coverage detected
searching dependent graphs…