summaryrefslogtreecommitdiff
path: root/buildstream/_artifactcache/artifactcache.py
blob: 246a7691df4b2283ae6a6efd54661e6fb4fb4935 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/usr/bin/env python3
#
#  Copyright (C) 2017 Codethink Limited
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public
#  License as published by the Free Software Foundation; either
#  version 2 of the License, or (at your option) any later version.
#
#  This library is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
#  Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public
#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
#
#  Authors:
#        Tristan Maat <tristan.maat@codethink.co.uk>

import os
from collections import Mapping

from .. import utils, ImplError
from .. import _yaml


# An ArtifactCache manages artifacts
#
# Args:
#     context (Context): The BuildStream context
#     project (Project): The BuildStream project
#
class ArtifactCache():
    def __init__(self, context, project):

        self.context = context

        os.makedirs(context.artifactdir, exist_ok=True)
        self.extractdir = os.path.join(context.artifactdir, 'extract')

        self._pull_local = False
        self._push_local = False

        project_overrides = context._get_overrides(project.name)
        artifact_overrides = _yaml.node_get(project_overrides, Mapping, 'artifacts', default_value={})
        override_pull = _yaml.node_get(artifact_overrides, str, 'pull-url', default_value='') or None
        override_push = _yaml.node_get(artifact_overrides, str, 'push-url', default_value='') or None
        override_push_port = _yaml.node_get(artifact_overrides, int, 'push-port', default_value=22)

        _yaml.node_validate(artifact_overrides, ['pull-url', 'push-url', 'push-port'])

        if override_pull or override_push:
            self.artifact_pull = override_pull
            self.artifact_push = override_push
            self.artifact_push_port = override_push_port

        elif any((project.artifact_pull, project.artifact_push)):
            self.artifact_pull = project.artifact_pull
            self.artifact_push = project.artifact_push
            self.artifact_push_port = project.artifact_push_port

        else:
            self.artifact_pull = context.artifact_pull
            self.artifact_push = context.artifact_push
            self.artifact_push_port = context.artifact_push_port

        if self.artifact_push:
            if self.artifact_push.startswith("/") or \
               self.artifact_push.startswith("file://"):
                self._push_local = True

        if self.artifact_pull:
            if self.artifact_pull.startswith("/") or \
               self.artifact_pull.startswith("file://"):
                self._pull_local = True

            self.remote = utils.url_directory_name(self.artifact_pull)
        else:
            self.remote = None

        self._offline = False

    # contains():
    #
    # Check whether the artifact for the specified Element is already available
    # in the local artifact cache.
    #
    # Args:
    #     element (Element): The Element to check
    #     strength (_KeyStrength): Either STRONG or WEAK key strength, or None
    #
    # Returns: True if the artifact is in the cache, False otherwise
    #
    def contains(self, element, strength=None):
        raise ImplError("Cache '{kind}' does not implement contains()"
                        .format(kind=type(self).__name__))

    # extract():
    #
    # Extract cached artifact for the specified Element if it hasn't
    # already been extracted.
    #
    # Assumes artifact has previously been fetched or committed.
    #
    # Args:
    #     element (Element): The Element to extract
    #
    # Raises:
    #     _ArtifactError: In cases there was an OSError, or if the artifact
    #                    did not exist.
    #
    # Returns: path to extracted artifact
    #
    def extract(self, element):
        raise ImplError("Cache '{kind}' does not implement extract()"
                        .format(kind=type(self).__name__))

    # commit():
    #
    # Commit built artifact to cache.
    #
    # Args:
    #     element (Element): The Element commit an artifact for
    #     content (str): The element's content directory
    #
    def commit(self, element, content):
        raise ImplError("Cache '{kind}' does not implement commit()"
                        .format(kind=type(self).__name__))

    # set_offline()
    #
    # Do not attempt to pull or push artifacts.
    #
    def set_offline(self):
        self._offline = True

    # can_fetch():
    #
    # Check whether remote repository is available for fetching.
    #
    # Returns: True if remote repository is available, False otherwise
    #
    def can_fetch(self):
        return (not self._offline or self._pull_local) and \
            self.remote is not None

    # can_push():
    #
    # Check whether remote repository is available for pushing.
    #
    # Returns: True if remote repository is available, False otherwise
    #
    def can_push(self):
        return (not self._offline or self._push_local) and \
            self.artifact_push is not None

    # remote_contains_key():
    #
    # Check whether the artifact for the specified Element is already available
    # in the remote artifact cache.
    #
    # Args:
    #     element (Element): The Element to check
    #     strength (_KeyStrength): Either STRONG or WEAK key strength, or None
    #
    # Returns: True if the artifact is in the cache, False otherwise
    #
    def remote_contains(self, element, strength=None):
        return False

    def fetch_remote_refs(self):
        pass