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
|
# Copyright (C) 2012-2015 Codethink Limited
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import morphlib
class Source(object):
'''Represent the source to be built.
Has the following properties:
* ``repo`` -- the git repository which contains the source
* ``repo_name`` -- name of the git repository which contains the source
* ``original_ref`` -- the git ref provided by the user or a morphology
* ``sha1`` -- the absolute git commit id for the revision we use
* ``tree`` -- the SHA1 of the tree corresponding to the commit
* ``morphology`` -- the in-memory representation of the morphology we use
* ``filename`` -- basename of the morphology filename
* ``cache_id`` -- a dict describing the components of the cache key
* ``cache_key`` -- a cache key to uniquely identify the artifact
* ``dependencies`` -- list of Artifacts that need to be built beforehand
* ``split_rules`` -- rules for splitting the source's produced artifacts
* ``artifacts`` -- the set of artifacts this source produces.
'''
def __init__(self, name, repo_name, original_ref, sha1, tree, morphology,
filename, split_rules):
self.name = name
self.repo = None
self.repo_name = repo_name
self.original_ref = original_ref
self.sha1 = sha1
self.tree = tree
self.morphology = morphology
self.filename = filename
self.cache_id = None
self.cache_key = None
self.dependencies = []
self.split_rules = split_rules
self.artifacts = None
def __str__(self): # pragma: no cover
return '%s|%s|%s|%s' % (self.repo_name,
self.original_ref,
self.filename,
self.name)
def __repr__(self): # pragma: no cover
return 'Source(%s)' % str(self)
def basename(self):
return '%s.%s' % (self.cache_key, str(self.morphology['kind']))
def metadata_basename(self):
return '%s.meta' % (self.cache_key)
def build_log_basename(self):
return '%s.build-log' % (self.cache_key)
def files(self):
'''Return the name of all built artifacts of this source.
This includes every artifact and all associated metadata.
It's usually a bad idea to have only some of the files for a given
source available. Transfer all of them if you transfer any of them.
'''
files = {self.metadata_basename()}
if self.morphology['kind'] == 'chunk':
files.add(self.build_log_basename())
for artifact in self.artifacts.values():
files.add(artifact.basename())
if self.morphology.needs_artifact_metadata_cached:
files.add(artifact.metadata_basename())
return files
def add_dependency(self, artifact): # pragma: no cover
if artifact not in self.dependencies:
self.dependencies.append(artifact)
if self not in artifact.dependents:
artifact.dependents.append(self)
def depends_on(self, artifact): # pragma: no cover
'''Do we depend on ``artifact``?'''
return artifact in self.dependencies
def make_sources(reponame, ref, filename, absref, tree, morphology):
kind = morphology['kind']
if kind in ('system', 'chunk'):
unifier = getattr(morphlib.artifactsplitrule,
'unify_%s_matches' % kind)
split_rules = unifier(morphology)
# chunk and system sources are named after the morphology
source_name = morphology['name']
source = morphlib.source.Source(source_name, reponame, ref,
absref, tree, morphology,
filename, split_rules)
source.artifacts = {name: morphlib.artifact.Artifact(source, name)
for name in split_rules.artifacts}
yield source
elif kind == 'stratum': # pragma: no cover
unifier = morphlib.artifactsplitrule.unify_stratum_matches
split_rules = unifier(morphology)
for name in split_rules.artifacts:
source = morphlib.source.Source(
name, # stratum source name is artifact name
reponame, ref, absref, tree, morphology, filename,
# stratum sources need to match the unified
# split rules, so they know to yield the match
# to a different source
split_rules)
source.artifacts = {name: morphlib.artifact.Artifact(source, name)}
yield source
else:
# cluster morphologies don't have sources
pass
|