Commit cdb086a5 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 21bad144
......@@ -28,28 +28,43 @@ from __future__ import print_function
import sys, configparser, re
from os.path import basename
from glob import glob
from collections import namedtuple
# PkgInfo represents information about a package
PkgInfo = namedtuple('PkgInfo', [
'name',
'version',
'kind'])
# bom_software retrieves BOM from .installed.cfg generated by buildout along the build.
def bom_software(installed_software_path): # -> {} name -> version + XXX
bom = {} # name -> ver + ... XXX
def bom_software(installed_software_path): # -> {} name -> PkgInfo
bom = {}
def addbom(urlpath, kind):
name, ver = namever(urlpath) # XXX strip egg and py2.7-linux-x86_64
info = PkgInfo(name, ver, kind)
if name in bom:
assert bom[name] == info, (bom[name], info)
else:
bom[name] = info
idb = configparser.ConfigParser()
idb.read('%s/.installed.cfg' % installed_software_path)
eggs_todo = set() # eggs listed in zc.recipe.egg - XXX
for s in idb.sections():
if s == 'buildout':
continue # [buildout] is used internally
#print(s)
part = idb[s]
recipe = part['recipe']
if recipe == 'slapos.recipe.cmmi':
name, ver = namever(part['url'])
addbom(part['url'], '') # XXX detect kind?
elif recipe == 'slapos.recipe.build':
# slapos.recipe.build is often used in creative ways to actually
......@@ -66,7 +81,7 @@ def bom_software(installed_software_path): # -> {} name -> version + XXX
raise NotImplementedError('%s uses %s without url' % (s, recipe))
else:
name, ver = namever(url)
addbom(url, '') # XXX detect kind?
elif recipe == 'slapos.recipe.build:download':
# slapos.recipe.build:download is often used to download .conf files, but sometimes it is used to download e.g. binaries
......@@ -94,26 +109,30 @@ def bom_software(installed_software_path): # -> {} name -> version + XXX
elif recipe == 'zc.recipe.egg:custom':
eggpath = part['__buildout_installed__']
assert len(eggpath.split()) == 1, eggpath # no spaces inside - just one item
name, ver = namever(eggpath) # XXX strip egg and py2.7-linux-x86_64
addbom(eggpath, 'egg')
elif recipe == 'zc.recipe.egg':
# XXX sadly zc.recipe.egg neither saves in .installed.cfg information about where the eggs are installed,
# nor there are [versions] save.
# -> look the egg on the filesystem
# TODO it is better to fix zc.recipe.egg to save the full information, so that we can build BOM just from .installed.cfg
eggdir = part['_e']
eggdev = part['_d']
eggs = part['eggs'].split()
for _ in eggs:
eggs_todo.add(_)
for eggname in eggs:
eggv = glob('%s/%s-*.egg' % (eggdir, eggname))
eggv += glob('%s/%s-*.egg' % (eggdev, eggname))
if len(eggv) == 0:
raise ValueError('egg %s not found' % egg)
if len(eggv) > 1:
raise ValueError('egg %s is present multiple times: %s' % (egg, eggv))
addbom(eggv[0], 'egg')
else:
raise NotImplementedError('TODO: add support for recipe %s' % recipe)
# XXX patches
print('%s\t%s' % (name, ver))
bom[name] = ver
# verify that every egg listed in zc.recipe.egg was actally insalled one way or another
for egg in eggs_todo:
assert egg in bom, (egg, bom)
return bom
def bom_node(XXX):
......@@ -143,7 +162,7 @@ def _namever(url):
return m.group('name'), m.group('rev')
filename = basename(url)
name, ver = filename.split('-', 1)
name, ver = filename.rsplit('-', 1)
return name, ver
......@@ -181,11 +200,23 @@ def main():
print(__doc__, file=sys.stderr)
sys.exit(2)
kind, arg = sys.argv[1:]
if kind == 'software':
bom_software(arg)
elif kind == 'node':
bom_node(arg)
what, arg = sys.argv[1:]
if what == 'software':
bom = bom_software(arg)
elif what == 'node':
bom = bom_node(arg)
kinds = set()
for info in bom.values():
kinds.add(info.kind)
for kind in sorted(kinds):
if kind is not None:
print('\n\n>>> %ss:' % kind)
for name in sorted(bom):
info = bom[name]
if info.kind == kind:
print('%s\t%s' % (name, info))
if __name__ == '__main__':
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment