def dump_gv_depgraph(root, workdir, tpaths=_TEMPLATE_PATHS, engine=_GV_ENGINE, html=True): """ Generate dependency graph with graphviz. TODO: Utilize graph, DAG and trees generated w/ ``dump_graphs``. :param root: Root dir where 'var/lib/rpm' exists :param workdir: Working dir to dump the result :param tpaths: Template path list :param engine: Graphviz rendering engine to choose, e.g. neato :param html: Generate HTML graph files if True """ reqs = RU.make_requires_dict(root) # Set virtual root for root rpms: for p, rs in reqs.iteritems(): if not rs: # This is a root RPM: reqs[p] = ["<rpmlibs>"] # Set virtual root for this root rpm. # Remove self dependency refs: ctx = dict(dependencies=[(r, [p for p in ps if p != r]) for r, ps in reqs.iteritems()]) depgraph_s = RT.render("rpmdep_graph_gv.j2", ctx, tpaths, ask=True) src = os.path.join(workdir, "rpmdep_graph.dot") U.copen(src, "w").write(depgraph_s) output = src + ".svg" SH.run("%s -Tsvg -o %s %s" % (engine, output, src), workdir=workdir) if html: logging.info("Generate HTML files for graphviz outputs") for t in ("js/graphviz-svg.js.j2", "js/jquery.js.j2", "rpmdep_graph_gv.html.j2"): _renderfile(workdir, t, ctx={}, tpaths=tpaths)
def dump_graphs(root, workdir, tpaths=_TEMPLATE_PATHS, html=True): """ Make and dump RPM dependency graphs. :param root: RPM Database root dir :param workdir: Working directory to dump results :param tpaths: Template path list :param html: Generate HTML graph files if True """ g = make_dependency_graph(root) dag = make_dependencies_dag(root) trees = make_dependencies_trees(root, True) if os.path.exists(workdir): assert os.path.isdir(workdir) else: os.makedirs(workdir) # see also: http://bl.ocks.org/mbostock/4062045. logging.info("Make dependency graph and dump it") g_data = dict() g_data["name"] = "RPM Dependency graph: root=%s" % root g_data["nodes"] = [dict(name=n, group=1) for n in g] nodeids = dict((n["name"], i) for i, n in enumerate(g_data["nodes"])) g_data["links"] = [ dict(source=nodeids[e[0]], target=nodeids[e[1]], value=1) for e in g.edges_iter() ] U.json_dump(g_data, os.path.join(workdir, "rpmdep_graph.json")) # Likewise. logging.info("Make dependency DAG and dump it") dag_data = dict() dag_data["name"] = "RPM Dependency DAG: root=%s" % root dag_data["nodes"] = [dict(name=n, group=1) for n in dag] nodeids = dict((n["name"], i) for i, n in enumerate(dag_data["nodes"])) dag_data["links"] = [ dict(source=nodeids[e[0]], target=nodeids[e[1]], value=1) for e in dag.edges_iter() ] U.json_dump(dag_data, os.path.join(workdir, "rpmdep_dag.json")) # see also: http://bl.ocks.org/mbostock/4063550 (flare.json) logging.info("Make dependency trees and dump them") for tree in trees: f = os.path.join(workdir, "rpmdep_tree_%(name)s.json" % tree) U.copen(f, 'w').write(str(tree)) # Render dependency graph w/ d3.js (force directed layout). # see also: https://github.com/mbostock/d3/wiki/Force-Layout if html: logging.info("Generate HTML graph files") t = "rpmdep_graph_d3_force_directed_graph.html.j2" _renderfile(workdir, t, dict(root=root, graph_type="graph"), tpaths) _renderfile(workdir, t, dict(root=root, graph_type="daga"), tpaths)
def _renderfile(workdir, tmpl, ctx={}, tpaths=_TEMPLATE_PATHS): if os.path.sep in tmpl: subdir = os.path.dirname(tmpl) d = os.path.join(workdir, subdir) tpaths = [os.path.join(t, subdir) for t in tpaths] if not os.path.exists(d): os.makedirs(d) s = RT.render(tmpl, ctx, tpaths, ask=True) U.copen(os.path.join(workdir, tmpl[:-3]), "w").write(s)
def _renderfile(workdir, tmpl, ctx={}, tpaths=_TEMPLATE_PATHS): if os.path.sep in tmpl: subdir = os.path.dirname(tmpl) d = os.path.join(workdir, subdir) tpaths = [os.path.join(t, subdir) for t in tpaths] if not os.path.exists(d): os.makedirs(d) s = RT.render(tmpl, ctx, tpaths, ask=True) U.copen(os.path.join(workdir, tmpl[:-3]), 'w').write(s)
def dump_graphs(root, workdir, tpaths=_TEMPLATE_PATHS, html=True): """ Make and dump RPM dependency graphs. :param root: RPM Database root dir :param workdir: Working directory to dump results :param tpaths: Template path list :param html: Generate HTML graph files if True """ g = make_dependency_graph(root) dag = make_dependencies_dag(root) trees = make_dependencies_trees(root, True) if os.path.exists(workdir): assert os.path.isdir(workdir) else: os.makedirs(workdir) # see also: http://bl.ocks.org/mbostock/4062045. logging.info("Make dependency graph and dump it") g_data = dict() g_data["name"] = "RPM Dependency graph: root=%s" % root g_data["nodes"] = [dict(name=n, group=1) for n in g] nodeids = dict((n["name"], i) for i, n in enumerate(g_data["nodes"])) g_data["links"] = [dict(source=nodeids[e[0]], target=nodeids[e[1]], value=1) for e in g.edges_iter()] U.json_dump(g_data, os.path.join(workdir, "rpmdep_graph.json")) # Likewise. logging.info("Make dependency DAG and dump it") dag_data = dict() dag_data["name"] = "RPM Dependency DAG: root=%s" % root dag_data["nodes"] = [dict(name=n, group=1) for n in dag] nodeids = dict((n["name"], i) for i, n in enumerate(dag_data["nodes"])) dag_data["links"] = [dict(source=nodeids[e[0]], target=nodeids[e[1]], value=1) for e in dag.edges_iter()] U.json_dump(dag_data, os.path.join(workdir, "rpmdep_dag.json")) # see also: http://bl.ocks.org/mbostock/4063550 (flare.json) logging.info("Make dependency trees and dump them") for tree in trees: f = os.path.join(workdir, "rpmdep_tree_%(name)s.json" % tree) U.copen(f, "w").write(str(tree)) # Render dependency graph w/ d3.js (force directed layout). # see also: https://github.com/mbostock/d3/wiki/Force-Layout if html: logging.info("Generate HTML graph files") t = "rpmdep_graph_d3_force_directed_graph.html.j2" _renderfile(workdir, t, dict(root=root, graph_type="graph"), tpaths) _renderfile(workdir, t, dict(root=root, graph_type="daga"), tpaths)
def dump_gv_depgraph(root, workdir, tpaths=_TEMPLATE_PATHS, engine=_GV_ENGINE, html=True): """ Generate dependency graph with graphviz. TODO: Utilize graph, DAG and trees generated w/ ``dump_graphs``. :param root: Root dir where 'var/lib/rpm' exists :param workdir: Working dir to dump the result :param tpaths: Template path list :param engine: Graphviz rendering engine to choose, e.g. neato :param html: Generate HTML graph files if True """ reqs = RU.make_requires_dict(root) # Set virtual root for root rpms: for p, rs in reqs.iteritems(): if not rs: # This is a root RPM: reqs[p] = ["<rpmlibs>"] # Set virtual root for this root rpm. # Remove self dependency refs: ctx = dict(dependencies=[(r, [p for p in ps if p != r]) for r, ps in reqs.iteritems()]) depgraph_s = RT.render("rpmdep_graph_gv.j2", ctx, tpaths, ask=True) src = os.path.join(workdir, "rpmdep_graph.dot") U.copen(src, 'w').write(depgraph_s) output = src + ".svg" SH.run("%s -Tsvg -o %s %s" % (engine, output, src), workdir=workdir) if html: logging.info("Generate HTML files for graphviz outputs") for t in ("js/graphviz-svg.js.j2", "js/jquery.js.j2", "rpmdep_graph_gv.html.j2"): _renderfile(workdir, t, ctx={}, tpaths=tpaths)