summaryrefslogtreecommitdiff
path: root/morphlib/morphset.py
diff options
context:
space:
mode:
Diffstat (limited to 'morphlib/morphset.py')
-rw-r--r--morphlib/morphset.py158
1 files changed, 158 insertions, 0 deletions
diff --git a/morphlib/morphset.py b/morphlib/morphset.py
new file mode 100644
index 00000000..98a4b8f9
--- /dev/null
+++ b/morphlib/morphset.py
@@ -0,0 +1,158 @@
+# Copyright (C) 2013 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.
+#
+# =*= License: GPL-2 =*=
+
+
+import morphlib
+
+
+class StratumNotInSystemError(morphlib.Error):
+
+ def __init__(self, system_name, stratum_name):
+ self.msg = (
+ 'System %s does not contain %s' % (system_name, stratum_name))
+
+
+class StratumNotInSetError(morphlib.Error):
+
+ def __init__(self, stratum_name):
+ self.msg = 'Stratum %s is not in MorphologySet' % stratum_name
+
+
+class ChunkNotInStratumError(morphlib.Error):
+
+ def __init__(self, stratum_name, chunk_name):
+ self.msg = (
+ 'Stratum %s does not contain %s' % (stratum_name, chunk_name))
+
+
+class MorphologySet(object):
+
+ '''Store and manipulate a set of Morphology objects.'''
+
+ def __init__(self):
+ self.morphologies = []
+
+ def add_morphology(self, morphology):
+ '''Add a morphology object to the set, unless it's there already.'''
+
+ triplet = (
+ morphology.repo_url,
+ morphology.ref,
+ morphology.filename
+ )
+ for existing in self.morphologies:
+ existing_triplet = (
+ existing.repo_url,
+ existing.ref,
+ existing.filename
+ )
+ if existing_triplet == triplet:
+ return
+
+ self.morphologies.append(morphology)
+
+ def has(self, repo_url, ref, filename):
+ '''Does the set have a morphology for the given triplet?'''
+ return self._get_morphology(repo_url, ref, filename) is not None
+
+ def _get_morphology(self, repo_url, ref, filename):
+ for m in self.morphologies:
+ if (m.repo_url == repo_url and
+ m.ref == ref and
+ m.filename == filename):
+ return m
+ return None
+
+ def _find_spec(self, specs, wanted_name):
+ for spec in specs:
+ name = spec.get('morph', spec.get('name'))
+ if name == wanted_name:
+ return spec['repo'], spec['ref'], name
+ return None, None, None
+
+ def get_stratum_in_system(self, system_morph, stratum_name):
+ '''Return morphology for a stratum that is in a system.
+
+ If the stratum is not in the system, raise StratumNotInSystemError.
+ If the stratum morphology has not been added to the set,
+ raise StratumNotInSetError.
+
+ '''
+
+ repo_url, ref, morph = self._find_spec(
+ system_morph['strata'], stratum_name)
+ if repo_url is None:
+ raise StratumNotInSystemError(system_morph['name'], stratum_name)
+ m = self._get_morphology(repo_url, ref, '%s.morph' % morph)
+ if m is None:
+ raise StratumNotInSetError(stratum_name)
+ return m
+
+ def get_chunk_triplet(self, stratum_morph, chunk_name):
+ '''Return the repo url, ref, morph name triplet for a chunk.
+
+ Given a stratum morphology, find the triplet used to refer to
+ a given chunk. Note that because of how the chunk may be
+ referred to using either name or morph fields in the morphology,
+ the morph field (or its computed value) is always returned.
+ Note also that the morph field, not the filename, is returned.
+
+ Raise ChunkNotInStratumError if the chunk is not found in the
+ stratum.
+
+ '''
+
+ repo_url, ref, morph = self._find_spec(
+ stratum_morph['chunks'], chunk_name)
+ if repo_url is None:
+ raise ChunkNotInStratumError(stratum_morph['name'], chunk_name)
+ return repo_url, ref, morph
+
+ def change_ref(self, repo_url, orig_ref, morph_filename, new_ref):
+ '''Change a triplet's ref to a new one in all morphologies in a ref.
+
+ Change orig_ref to new_ref in any morphology that references the
+ original triplet. This includes stratum build-dependencies.
+
+ '''
+
+ def wanted_spec(spec):
+ return (spec['repo'] == repo_url and
+ spec['ref'] == orig_ref and
+ spec['morph'] + '.morph' == morph_filename)
+
+ def change_specs(specs):
+ for spec in specs:
+ if wanted_spec(spec):
+ spec['ref'] = new_ref
+ m.dirty = True
+
+ def change(m):
+ if m['kind'] == 'system':
+ change_specs(m['strata'])
+ elif m['kind'] == 'stratum':
+ change_specs(m['chunks'])
+ change_specs(m['build-depends'])
+
+ for m in self.morphologies:
+ change(m)
+
+ m = self._get_morphology(repo_url, orig_ref, morph_filename)
+ if m and m.ref != new_ref:
+ m.ref = new_ref
+ m.dirty = True
+