core updated.
This commit is contained in:
Executable
+193
@@ -0,0 +1,193 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2008, TUBITAK/UEKAE
|
||||
#
|
||||
# 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; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# Please read the COPYING file.
|
||||
#
|
||||
|
||||
import sys
|
||||
import multiprocessing
|
||||
|
||||
import urllib2
|
||||
import bz2
|
||||
import lzma
|
||||
|
||||
import piksemel
|
||||
|
||||
import pisi
|
||||
import pisi.dependency as dependency
|
||||
from pisi.graph import CycleException
|
||||
|
||||
|
||||
class SourceDB:
|
||||
def __init__(self, index):
|
||||
|
||||
self.__source_nodes = {}
|
||||
self.__pkgstosrc = {}
|
||||
|
||||
doc = piksemel.parseString(index)
|
||||
self.__source_nodes, self.__pkgstosrc = self.__generate_sources(doc)
|
||||
|
||||
def __generate_sources(self, doc):
|
||||
sources = {}
|
||||
pkgstosrc = {}
|
||||
|
||||
for spec in doc.tags("SpecFile"):
|
||||
src_name = spec.getTag("Source").getTagData("Name")
|
||||
sources[src_name] = spec.toString()
|
||||
for package in spec.tags("Package"):
|
||||
pkgstosrc[package.getTagData("Name")] = src_name
|
||||
|
||||
return sources, pkgstosrc
|
||||
|
||||
def has_spec(self, name):
|
||||
return self.__source_nodes.has_key(name)
|
||||
|
||||
def get_spec(self, name):
|
||||
src = self.__source_nodes[name]
|
||||
spec = pisi.specfile.SpecFile()
|
||||
spec.parse(src)
|
||||
return spec
|
||||
|
||||
def list_specs(self):
|
||||
return self.__source_nodes.keys()
|
||||
|
||||
def pkgtosrc(self, name):
|
||||
return self.__pkgstosrc[name]
|
||||
|
||||
def find_circle(sourcedb, A):
|
||||
|
||||
G_f = pisi.graph.Digraph()
|
||||
|
||||
def get_spec(name):
|
||||
if sourcedb.has_spec(name):
|
||||
return sourcedb.get_spec(name)
|
||||
else:
|
||||
raise Exception('Cannot find source package: %s' % name)
|
||||
|
||||
def get_src(name):
|
||||
return get_spec(name).source
|
||||
|
||||
def add_src(src):
|
||||
if not str(src.name) in G_f.vertices():
|
||||
G_f.add_vertex(str(src.name), (src.version, src.release))
|
||||
|
||||
def pkgtosrc(pkg):
|
||||
try:
|
||||
tmp = sourcedb.pkgtosrc(pkg)
|
||||
except KeyError, e:
|
||||
# this is a bad hack but after we hit a problem we need to continue
|
||||
tmp = "e3"
|
||||
print "---> borks in ", e
|
||||
|
||||
return tmp
|
||||
|
||||
B = A
|
||||
|
||||
install_list = set()
|
||||
|
||||
while len(B) > 0:
|
||||
Bp = set()
|
||||
for x in B:
|
||||
sf = get_spec(x)
|
||||
src = sf.source
|
||||
add_src(src)
|
||||
|
||||
# add dependencies
|
||||
|
||||
def process_dep(dep):
|
||||
srcdep = pkgtosrc(dep.package)
|
||||
if not srcdep in G_f.vertices():
|
||||
Bp.add(srcdep)
|
||||
add_src(get_src(srcdep))
|
||||
if not src.name == srcdep: # firefox - firefox-devel thing
|
||||
G_f.add_edge(src.name, srcdep)
|
||||
|
||||
for builddep in src.buildDependencies:
|
||||
process_dep(builddep)
|
||||
|
||||
for pkg in sf.packages:
|
||||
for rtdep in pkg.packageDependencies:
|
||||
process_dep(rtdep)
|
||||
B = Bp
|
||||
|
||||
try:
|
||||
order_build = G_f.topological_sort()
|
||||
order_build.reverse()
|
||||
except CycleException, cycle:
|
||||
return str(cycle)
|
||||
|
||||
return ""
|
||||
|
||||
def getIndex(uri):
|
||||
try:
|
||||
if "://" in uri:
|
||||
rawdata = urllib2.urlopen(uri).read()
|
||||
else:
|
||||
rawdata = open(uri, "r").read()
|
||||
except IOError:
|
||||
print "could not fetch %s" % uri
|
||||
return None
|
||||
|
||||
if uri.endswith("bz2"):
|
||||
data = bz2.decompress(rawdata)
|
||||
elif uri.endswith("xz") or uri.endswith("lzma"):
|
||||
data = lzma.decompress(rawdata)
|
||||
else:
|
||||
data = rawdata
|
||||
|
||||
return data
|
||||
|
||||
def processPackage(pkg, sourcesLength, counter):
|
||||
global sourcedb
|
||||
|
||||
sys.stdout.write("\r(%04d/%d) Calculating build dep of %s " % (counter, sourcesLength, pkg))
|
||||
sys.stdout.flush()
|
||||
|
||||
return find_circle(sourcedb, [pkg])
|
||||
|
||||
def updateStatus(circleResult):
|
||||
global cycles
|
||||
cycles.add(circleResult)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print "Usage: circlefinder.py <source repo pisi-index.xml file>"
|
||||
sys.exit(1)
|
||||
|
||||
rawIndex = getIndex(sys.argv[1])
|
||||
sourcedb = SourceDB(rawIndex)
|
||||
sources = sourcedb.list_specs()
|
||||
|
||||
sourcesLength = len(sources)
|
||||
counter = 0
|
||||
|
||||
global cycles
|
||||
cycles = set()
|
||||
|
||||
pool = multiprocessing.Pool()
|
||||
|
||||
for pkg in sources:
|
||||
counter += 1
|
||||
pool.apply_async(processPackage, (pkg, sourcesLength, counter), callback=updateStatus)
|
||||
|
||||
pool.close()
|
||||
pool.join()
|
||||
|
||||
if len(cycles):
|
||||
print
|
||||
for cycle in cycles:
|
||||
print cycle
|
||||
else:
|
||||
print "No circular dep found"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user