def __init__(self, name): self.name = name if name[-7:] == '-native': self._basename = name[:-7] self._native = True else: self._basename = name self._native = False self.mk = self._get_mk() if not self.mk: Blog.fatal("unable to find mk for package: %s" % name) mk_full_path = os.path.join(Bos.topdir, self.mk) Blog.debug('start to parse .mk: %s' % self.mk) config = ConfigParser() meta = self._preprocess_mk() try: config.read(meta) except ParsingError as e: Blog.error(e.message) Blog.fatal("failed to parse .mk: %s <%s>" % (name, self.mk)) os.remove(meta) Blog.debug('parsing package .mk: %s' % self.mk) ## package description is required try: self._description = config.get('BOSMK', 'DESCRIPTION') except NoOptionError: Blog.fatal("package description missing: %s <%s>" % (name, self.mk)) ## everything else if optional Blog.debug('parsing package .mk: %s optional fields.' % self.mk) self.require = [] self._patch = [] self._patched = None self._src = None self._files = {} for fld in dict(config.items('BOSMK')): if 'require' == fld: require = dict(config.items('BOSMK'))[ 'require'].replace('\n', ' ').split(' ') for dep in require: if self._native: if dep[-7:] != '-native': self.require.append(dep + '-native') continue self.require.append(dep) elif 'source' == fld: sources = dict(config.items('BOSMK'))[ 'source'].replace('\n', ' ').split(' ') for s in sources: if os.path.splitext(s)[1] == '.patch': self._patch.append(s) self._src = sources[0] elif fld[:5] == 'files': self._files.update({fld: dict(config.items('BOSMK'))[fld]}) ## package misc if self._patch: self._patched = os.path.join(Bos.topdir, self._src, '.bos-patch-applied') self._mtime = os.path.getmtime(mk_full_path) self._gitdir = self._get_gitdir() ## installed contents directory: ## {package-name: [[mode ownership size path]]} self._contents = {} ## version info is available only after a successful install. self._version = None ## put it on shelf db = shelve.open(_get_shelf_name(name)) db['obj'] = self db.close()
def _install(self): """ install package from staging area to output area and populate DB examine contents in staging area to make sure that, - all package specified contents must exist, unless optional - all installed contents must associate with given package return: 0 if successful, error code otherwise """ ## walk through package and sub-package definitions if any for kn in self._files: if kn == 'files': pn = self._basename else: pn = self._basename + kn[5:] Blog.debug('processing package: %s' % pn) ctx = BosInstallContext(pn, self) try: for itm in self._files[kn].split('\n'): if '' == itm.strip(): continue ownership, pattern, optional = _parse_install_item(itm) Blog.debug('processing pattern: %s' % pattern) flist = glob.glob(os.path.join(self._get_stagingdir(), pattern[1:])) if (not flist) and (not optional): Blog.fatal('<%s> unable to find: %s' % (self.name, pattern)) for ff in flist: _install_files(ff, ownership, ctx) for ctnt in ctx.contents: ff = ctnt[3] path = os.path.join(ctx.indexdir, ff[1:]) if not os.path.exists(os.path.dirname(path)): os.makedirs(os.path.dirname(path)) #with open(path, 'w') as f: f.write(ctx.name) os.symlink(ctx.name, path) except: Blog.error("%s unable to install." % self.name) self._put_info({ctx.name:ctx.contents}) self._uninstall() return -1 Blog.debug('%s writing package info' % ctx.name) self._put_info({ctx.name:ctx.contents}) ## post process: walk the stagingdir to make sure there's no files left try: for r, d, f in os.walk(self._get_stagingdir()): if f: Blog.fatal('installed but unpackaged contents found: %s\n%s' % (self.name, _list_dir(self._get_stagingdir()))) except: Blog.error('%s unable to walk staging dir: %s' % (self.name, self._get_stagingdir())) self._uninstall() return -2 return 0