Project

General

Profile

Download (4.23 KB) Statistics
| Branch: | Tag: | Revision:

hydrilla-builder / src / hydrilla / builder / piggybacking.py @ 61f0aa75

1
# SPDX-License-Identifier: AGPL-3.0-or-later
2

    
3
# Handling of software packaged for other distribution systems.
4
#
5
# This file is part of Hydrilla
6
#
7
# Copyright (C) 2022 Wojtek Kosior
8
#
9
# This program is free software: you can redistribute it and/or modify
10
# it under the terms of the GNU Affero General Public License as
11
# published by the Free Software Foundation, either version 3 of the
12
# License, or (at your option) any later version.
13
#
14
# This program is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
# GNU Affero General Public License for more details.
18
#
19
# You should have received a copy of the GNU Affero General Public License
20
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
21
#
22
#
23
# I, Wojtek Kosior, thereby promise not to sue for violation of this
24
# file's license. Although I request that you do not make use this code
25
# in a proprietary program, I am not going to enforce this in court.
26

    
27
"""
28
This module contains definitions that may be reused by multiple piggybacked
29
software system backends.
30
"""
31

    
32
# Enable using with Python 3.7.
33
from __future__ import annotations
34

    
35
from pathlib import Path, PurePosixPath
36
from typing import Optional, Iterable
37

    
38
from .. import util
39
from .common_errors import *
40

    
41
here = Path(__file__).resolve().parent
42

    
43
_ = util.translation(here / 'locales').gettext
44

    
45
class Piggybacked:
46
    """
47
    Store information about foreign resources in use.
48

    
49
    Public attributes:
50
        'package_must_depend' (read-only)
51
        'package_license_files' (read-only)
52
    """
53
    def __init__(self, archives: dict[str, Path]={}, roots: dict[str, Path]={},
54
                 package_license_files: list[PurePosixPath]=[],
55
                 package_must_depend: list[dict]=[]):
56
        """
57
        Initialize this Piggybacked object.
58

    
59
        'archives' maps piggybacked system names to directories that contain
60
        package(s)' archive files. An 'archives' object may look like
61
        {'apt': PosixPath('/path/to/dir/with/debs/and/tarballs')}.
62

    
63
        'roots' associates directory names to be virtually inserted under
64
        Hydrilla source package directory with paths to real filesystem
65
        directories that hold their desired contents, i.e. unpacked foreign
66
        packages.
67

    
68
        'package_license_files' lists paths to license files that should be
69
        included with the Haketilo package that will be produced. The paths are
70
        to be resolved using 'roots' dictionary.
71

    
72
        'package_must_depend' lists names of Haketilo packages that the produced
73
        package will additionally depend on. This is meant to help distribute
74
        common licenses with a separate Haketilo package.
75
        """
76
        self.archives              = archives
77
        self.roots                 = roots
78
        self.package_license_files = package_license_files
79
        self.package_must_depend   = package_must_depend
80

    
81
    def resolve_file(self, file_ref_name: PurePosixPath) -> Optional[Path]:
82
        """
83
        'file_ref_name' is a path as may appear in an index.json file. Check if
84
        the file belongs to one of the roots we have and return either a path
85
        to the relevant file under this root or None.
86

    
87
        It is not being checked whether the file actually exists in the
88
        filesystem.
89
        """
90
        parts = file_ref_name.parts
91
        root_path = self.roots.get(parts and parts[0])
92
        path = root_path
93
        if path is None:
94
            return None
95

    
96
        for part in parts[1:]:
97
            path = path / part
98

    
99
        path = path.resolve()
100

    
101
        if not path.is_relative_to(root_path):
102
            raise FileReferenceError(_('loading_{}_outside_piggybacked_dir')
103
                                     .format(file_ref_name))
104

    
105
        return path
106

    
107
    def archive_files(self) -> Iterable[tuple[PurePosixPath, Path]]:
108
        """
109
        Yield all archive files in use. Each yielded tuple holds file's desired
110
        path relative to the piggybacked archives directory to be created and
111
        its current real path.
112
        """
113
        for system, real_dir in self.archives.items():
114
            for path in real_dir.rglob('*'):
115
                yield PurePosixPath(system) / path.relative_to(real_dir), path
(6-6/6)