# vim:fileencoding=utf-8 # (c) 2011 Michał Górny # Released under the terms of the 2-clause BSD license. import os, os.path class EbuildRepository(object): """ A universal class to handle an ebuild repository in a PM-agnostic manner. >>> r = EbuildRepository('/usr/portage') # XXX: do not depend on path >>> r.repo_name # doctest: +ELLIPSIS '...' """ def __init__(self, path): """ Instantiate a new EbuildRepository. Read the repository name. @param path: path to the repository @type path: string @raise EnvironmentError: for repo_name file operations @raise ValueError: if repo_name contents are invalid """ self.path = path rnpath = os.path.join(path, 'profiles', 'repo_name') f = open(rnpath, 'r') self.repo_name = f.readline().strip() f.close() catspath = os.path.join(path, 'profiles', 'categories') try: f = open(catspath, 'r'); self.categories = [l.strip() for l in f.readlines()] f.close() except EnvironmentError: self.categories = [] if not self.repo_name: raise ValueError('Repository %s has invalid name.' % path) def get_category_from_path(self, fn): head = fn while head: head, tail = os.path.split(head) if tail in ('eclass', 'licenses', 'metadata', 'profiles'): return None return tail def write_files(self, files): """ Write files to the repository. @param files: a dict, as returned by L{library.case.TestCase.get_output_files()} @type files: dict(string -> stringifiable) """ newcats = set() for fn in files: cat = self.get_category_from_path(fn) if cat and cat not in self.categories: newcats.add(cat) self.add_categories(newcats, files) for fn, c in files.items(): fp = os.path.join(self.path, fn) if not os.path.exists(os.path.dirname(fp)): os.makedirs(os.path.dirname(fp)) f = open(fp, 'w') f.write(bytes(c)) f.close() def remanifest(self, files, pm): """ Remanifest files in repository. @param files: filenames in the repository @type files: iterable(string) @param pm: the package manager instance @type pm: L{PackageManager} """ dirs = set() for fn in files: cat = self.get_category_from_path(fn) if cat: dirs.add(os.path.join(self.path, os.path.dirname(fn))) pm.remanifest(dirs) def add_categories(self, cats, files): """ Add categories in to profiles/categories. Update the profiles/categories file in C{files}. @param cats: categories to add @type cats: list(string) @param files: the files dict @type files: dict(string -> stringifiable) """ # XXX: profiles/categories can contain new categories already # and they may not be in self.categories self.categories.extend(cats) newcats = '\n'.join(self.categories) files[os.path.join('profiles', 'categories')] = newcats class NewEbuildRepository(EbuildRepository): """ A subclass of EbuildRepository supporting creating a new repository for the test suite (i.e. not requiring repo_name to exist). """ def __init__(self, path, repo_name): """ Create a new ebuild repository in C{path}. Name it C{repo_name}. @param path: path to the repository @type path: string @param repo_name: the new repository name @type repo_name: string """ rnpath = os.path.join(path, 'profiles', 'repo_name') dirpath = os.path.dirname(rnpath) if not os.path.isdir(dirpath): # XXX: poor os.makedirs(dirpath) f = open(rnpath, 'w') f.write(repo_name) f.close() EbuildRepository.__init__(self, path)