-
Notifications
You must be signed in to change notification settings - Fork 0
/
repository.py
170 lines (110 loc) · 4.82 KB
/
repository.py
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
# 1st-party
import logging
# 2nd-party
from metadatawriter import MetadataWriter
from projects import Projects
class Repository:
'''Keep state on the repository, e.g. keys, projects (their keys and
packages), delegations of projects.'''
def __init__(self, changelog_reader):
# Administrator keyids.
# Return a *deterministic* "keyid" for the snapshot administrator.
# WARNING: Do *NOT* reuse this value anywhere else!
# It just so happens that a SHA-256 hex digest is as long as our keyid.
self.__snapshot_administrator_keyid = \
MetadataWriter.get_sha256('snapshot'.encode('utf-8'))
self.__projects_administrator_keyid = MetadataWriter.get_random_keyid()
self.__projects_subordinates_keyid = self.__projects_administrator_keyid
# Administrator keyvals.
self.__keyid_to_keyval = {
self.__snapshot_administrator_keyid:
MetadataWriter.get_random_ed25519_keyval(),
self.__projects_administrator_keyid:
MetadataWriter.get_random_ed25519_keyval()
}
# Administrator versions.
self.__snapshot_administrator_version = 0
self.__projects_administrator_version = 0
# A map of which projects subordinates are responsible for which projects.
# str (role name): {str} (set of project names)
self._projects_subordinates_to_projects = {}
# str (role name): int (version number > 0)
self._projects_subordinates_to_version = {}
# This object takes care of projects and their packages, keys, etc.
self.__projects = Projects(changelog_reader)
# Custom setup routine here.
self._setup()
def get_projects_subordinate_version(self, projects_subordinate):
assert self._projects_subordinates_to_projects.keys() == \
self._projects_subordinates_to_version.keys()
assert projects_subordinate in self._projects_subordinates_to_version
return self._projects_subordinates_to_version[projects_subordinate]
def inc_projects_administrator_version(self):
self.__projects_administrator_version += 1
def inc_projects_subordinate_version(self, projects_subordinate):
assert self._projects_subordinates_to_projects.keys() == \
self._projects_subordinates_to_version.keys()
assert projects_subordinate in self._projects_subordinates_to_version
self._projects_subordinates_to_version[projects_subordinate] += 1
def inc_snapshot_administrator_version(self):
self.__snapshot_administrator_version += 1
@property
def keyid_to_keyval(self):
return self.__keyid_to_keyval.copy()
@property
def projects(self):
return self.__projects
@property
def projects_administrator_keyids(self):
return (self.__projects_administrator_keyid,)
@property
def projects_administrator_version(self):
assert self.__projects_administrator_version > 0
return self.__projects_administrator_version
@property
def projects_subordinates(self):
return sorted(self.projects_subordinates_to_projects.keys())
@property
def projects_subordinates_keyids(self):
return (self.__projects_subordinates_keyid,)
@property
def projects_subordinates_to_keyids(self):
assert self._projects_subordinates_to_projects.keys() == \
self._projects_subordinates_to_version.keys()
return {
role: self.projects_subordinates_keyids \
for role in self._projects_subordinates_to_projects
}
@property
def projects_subordinates_to_projects(self):
assert self._projects_subordinates_to_projects.keys() == \
self._projects_subordinates_to_version.keys()
# TODO: assert that projects are mutex between subordinates
return self._projects_subordinates_to_projects.copy()
def release(self):
if len(self.projects.dirty) > 0:
#self.inc_projects_administrator_version()
self.inc_snapshot_administrator_version()
else:
logging.debug('No repository release, '\
'because there is no dirty project metadata.')
def _setup(self):
raise NotImplementedError()
@property
def snapshot_administrator_keyids(self):
return (self.__snapshot_administrator_keyid,)
@property
def snapshot_administrator_version(self):
assert self.__snapshot_administrator_version > 0
return self.__snapshot_administrator_version
def update(self, change):
self.__projects.update(change)
class TUFAlphabeticalRepository(Repository):
def _setup(self):
for project_name in self.projects.names:
role = project_name[0]
projects = self._projects_subordinates_to_projects.setdefault(role,
set())
projects.add(project_name)
self._projects_subordinates_to_version[role] = 1
class MercuryAlphabeticalRepository(TUFAlphabeticalRepository): pass