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)