aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'portage_with_autodep/integration_with_portage.patch')
-rw-r--r--portage_with_autodep/integration_with_portage.patch920
1 files changed, 0 insertions, 920 deletions
diff --git a/portage_with_autodep/integration_with_portage.patch b/portage_with_autodep/integration_with_portage.patch
deleted file mode 100644
index 794c156..0000000
--- a/portage_with_autodep/integration_with_portage.patch
+++ /dev/null
@@ -1,920 +0,0 @@
-diff -urN /usr/lib/portage/pym/_emerge/EbuildBuild.py ./pym/_emerge/EbuildBuild.py
---- /usr/lib/portage/pym/_emerge/EbuildBuild.py 2012-05-28 16:20:40.737712559 +0600
-+++ ./pym/_emerge/EbuildBuild.py 2012-06-01 21:37:22.799844102 +0600
-@@ -9,6 +9,8 @@
- from _emerge.EbuildMerge import EbuildMerge
- from _emerge.EbuildFetchonly import EbuildFetchonly
- from _emerge.EbuildBuildDir import EbuildBuildDir
-+from _emerge.EventsAnalyser import EventsAnalyser, FilterProcGenerator
-+from _emerge.EventsLogger import EventsLogger
- from _emerge.MiscFunctionsProcess import MiscFunctionsProcess
- from portage.util import writemsg
- import portage
-@@ -21,7 +23,7 @@
- class EbuildBuild(CompositeTask):
-
- __slots__ = ("args_set", "config_pool", "find_blockers",
-- "ldpath_mtimes", "logger", "opts", "pkg", "pkg_count",
-+ "ldpath_mtimes", "logger", "logserver", "opts", "pkg", "pkg_count",
- "prefetcher", "settings", "world_atom") + \
- ("_build_dir", "_buildpkg", "_ebuild_path", "_issyspkg", "_tree")
-
-@@ -251,8 +253,54 @@
-
- build = EbuildExecuter(background=self.background, pkg=pkg,
- scheduler=scheduler, settings=settings)
-+
-+ build.addStartListener(self._build_start)
-+ build.addExitListener(self._build_stop)
-+
- self._start_task(build, self._build_exit)
-
-+ def _build_start(self,phase):
-+ if "depcheck" in self.settings["FEATURES"] or \
-+ "depcheckstrict" in self.settings["FEATURES"]:
-+ # Lets start a log listening server
-+ temp_path=self.settings.get("T",self.settings["PORTAGE_TMPDIR"])
-+
-+ if "depcheckstrict" not in self.settings["FEATURES"]:
-+ # use default filter_proc
-+ self.logserver=EventsLogger(socket_dir=temp_path)
-+ else:
-+ portage.util.writemsg("Getting list of allowed files..." + \
-+ "This may take some time\n")
-+ filter_gen=FilterProcGenerator(self.pkg.cpv, self.settings)
-+ filter_proc=filter_gen.get_filter_proc()
-+ self.logserver=EventsLogger(socket_dir=temp_path,
-+ filter_proc=filter_proc)
-+
-+ self.logserver.start()
-+
-+ # Copy socket path to LOG_SOCKET environment variable
-+ env=self.settings.configdict["pkg"]
-+ env['LOG_SOCKET'] = self.logserver.socket_name
-+
-+ #import pdb; pdb.set_trace()
-+
-+ def _build_stop(self,phase):
-+ if "depcheck" in self.settings["FEATURES"] or \
-+ "depcheckstrict" in self.settings["FEATURES"]:
-+ # Delete LOG_SOCKET from environment
-+ env=self.settings.configdict["pkg"]
-+ if 'LOG_SOCKET' in env:
-+ del env['LOG_SOCKET']
-+
-+ events=self.logserver.stop()
-+ self.logserver=None
-+ analyser=EventsAnalyser(self.pkg.cpv, events, self.settings)
-+ analyser.display() # show the analyse
-+
-+ #import pdb; pdb.set_trace()
-+
-+
-+
- def _fetch_failed(self):
- # We only call the pkg_nofetch phase if either RESTRICT=fetch
- # is set or the package has explicitly overridden the default
-diff -urN /usr/lib/portage/pym/_emerge/EbuildPhase.py ./pym/_emerge/EbuildPhase.py
---- /usr/lib/portage/pym/_emerge/EbuildPhase.py 2012-05-28 16:20:40.738712559 +0600
-+++ ./pym/_emerge/EbuildPhase.py 2012-06-01 21:38:11.935842036 +0600
-@@ -34,7 +34,8 @@
-
- # FEATURES displayed prior to setup phase
- _features_display = (
-- "ccache", "compressdebug", "distcc", "distcc-pump", "fakeroot",
-+ "ccache", "compressdebug", "depcheck", "depcheckstrict",
-+ "distcc", "distcc-pump", "fakeroot",
- "installsources", "keeptemp", "keepwork", "nostrip",
- "preserve-libs", "sandbox", "selinux", "sesandbox",
- "splitdebug", "suidctl", "test", "userpriv",
-diff -urN /usr/lib/portage/pym/_emerge/EbuildPhase.py.rej ./pym/_emerge/EbuildPhase.py.rej
---- /usr/lib/portage/pym/_emerge/EbuildPhase.py.rej 1970-01-01 05:00:00.000000000 +0500
-+++ ./pym/_emerge/EbuildPhase.py.rej 2012-06-01 21:37:22.800844102 +0600
-@@ -0,0 +1,12 @@
-+--- pym/_emerge/EbuildPhase.py
-++++ pym/_emerge/EbuildPhase.py
-+@@ -33,7 +33,8 @@
-+ ("_ebuild_lock",)
-+
-+ # FEATURES displayed prior to setup phase
-+- _features_display = ("ccache", "distcc", "distcc-pump", "fakeroot",
-++ _features_display = ("ccache", "depcheck", "depcheckstrict" "distcc",
-++ "distcc-pump", "fakeroot",
-+ "installsources", "keeptemp", "keepwork", "nostrip",
-+ "preserve-libs", "sandbox", "selinux", "sesandbox",
-+ "splitdebug", "suidctl", "test", "userpriv",
-diff -urN /usr/lib/portage/pym/_emerge/EventsAnalyser.py ./pym/_emerge/EventsAnalyser.py
---- /usr/lib/portage/pym/_emerge/EventsAnalyser.py 1970-01-01 05:00:00.000000000 +0500
-+++ ./pym/_emerge/EventsAnalyser.py 2012-06-01 21:37:22.802844102 +0600
-@@ -0,0 +1,511 @@
-+# Distributed under the terms of the GNU General Public License v2
-+
-+import portage
-+from portage.dbapi._expand_new_virt import expand_new_virt
-+from portage import os
-+
-+import subprocess
-+import re
-+
-+class PortageUtils:
-+ """ class for accessing the portage api """
-+ def __init__(self, settings):
-+ """ test """
-+ self.settings=settings
-+ self.vartree=portage.vartree(settings=settings)
-+ self.vardbapi=portage.vardbapi(settings=settings, vartree=self.vartree)
-+ self.portdbapi=portage.portdbapi(mysettings=settings)
-+ self.metadata_keys = [k for k in portage.auxdbkeys if not k.startswith("UNUSED_")]
-+ self.use=self.settings["USE"]
-+
-+ def get_best_visible_pkg(self,pkg):
-+ """
-+ Gets best candidate on installing. Returns empty string if no found
-+
-+ :param pkg: package name
-+
-+ """
-+ try:
-+ return self.portdbapi.xmatch("bestmatch-visible", pkg)
-+ except:
-+ return ''
-+
-+ # non-recursive dependency getter
-+ def get_dep(self,pkg,dep_type=["RDEPEND","DEPEND"]):
-+ """
-+ Gets current dependencies of a package. Looks in portage db
-+
-+ :param pkg: name of package
-+ :param dep_type: type of dependencies to recurse. Can be ["DEPEND"] or
-+ ["RDEPEND", "DEPEND"]
-+ :returns: **set** of packages names
-+ """
-+ ret=set()
-+
-+ pkg = self.get_best_visible_pkg(pkg)
-+ if not pkg:
-+ return ret
-+
-+ # we found the best visible match in common tree
-+
-+
-+ metadata = dict(zip(self.metadata_keys,
-+ self.portdbapi.aux_get(pkg, self.metadata_keys)))
-+ dep_str = " ".join(metadata[k] for k in dep_type)
-+
-+ # the IUSE default are very important for us
-+ iuse_defaults=[
-+ u[1:] for u in metadata.get("IUSE",'').split() if u.startswith("+")]
-+
-+ use=self.use.split()
-+
-+ for u in iuse_defaults:
-+ if u not in use:
-+ use.append(u)
-+
-+ success, atoms = portage.dep_check(dep_str, None, self.settings,
-+ myuse=use, myroot=self.settings["ROOT"],
-+ trees={self.settings["ROOT"]:{"vartree":self.vartree, "porttree": self.vartree}})
-+ if not success:
-+ return ret
-+
-+ for atom in atoms:
-+ atomname = self.vartree.dep_bestmatch(atom)
-+
-+ if not atomname:
-+ continue
-+
-+ for unvirt_pkg in expand_new_virt(self.vardbapi,'='+atomname):
-+ for pkg in self.vartree.dep_match(unvirt_pkg):
-+ ret.add(pkg)
-+
-+ return ret
-+
-+ # recursive dependency getter
-+ def get_deps(self,pkg,dep_type=["RDEPEND","DEPEND"]):
-+ """
-+ Gets current dependencies of a package on any depth
-+ All dependencies **must** be installed
-+
-+ :param pkg: name of package
-+ :param dep_type: type of dependencies to recurse. Can be ["DEPEND"] or
-+ ["RDEPEND", "DEPEND"]
-+ :returns: **set** of packages names
-+ """
-+ ret=set()
-+
-+
-+ # get porttree dependencies on the first package
-+
-+ pkg = self.portdbapi.xmatch("bestmatch-visible", pkg)
-+ if not pkg:
-+ return ret
-+
-+ known_packages=set()
-+ unknown_packages=self.get_dep(pkg,dep_type)
-+ ret=ret.union(unknown_packages)
-+
-+ while unknown_packages:
-+ p=unknown_packages.pop()
-+ if p in known_packages:
-+ continue
-+ known_packages.add(p)
-+
-+ metadata = dict(zip(self.metadata_keys, self.vardbapi.aux_get(p, self.metadata_keys)))
-+
-+ dep_str = " ".join(metadata[k] for k in dep_type)
-+
-+ # the IUSE default are very important for us
-+ iuse_defaults=[
-+ u[1:] for u in metadata.get("IUSE",'').split() if u.startswith("+")]
-+
-+ use=self.use.split()
-+
-+ for u in iuse_defaults:
-+ if u not in use:
-+ use.append(u)
-+
-+ success, atoms = portage.dep_check(dep_str, None, self.settings,
-+ myuse=use, myroot=self.settings["ROOT"],
-+ trees={self.settings["ROOT"]:{"vartree":self.vartree,"porttree": self.vartree}})
-+
-+ if not success:
-+ continue
-+
-+ for atom in atoms:
-+ atomname = self.vartree.dep_bestmatch(atom)
-+ if not atomname:
-+ continue
-+
-+ for unvirt_pkg in expand_new_virt(self.vardbapi,'='+atomname):
-+ for pkg in self.vartree.dep_match(unvirt_pkg):
-+ ret.add(pkg)
-+ unknown_packages.add(pkg)
-+ return ret
-+
-+ def get_deps_for_package_building(self, pkg):
-+ """
-+ returns buildtime dependencies of current package and
-+ all runtime dependencies of that buildtime dependencies
-+ """
-+ buildtime_deps=self.get_dep(pkg, ["DEPEND"])
-+ runtime_deps=set()
-+ for dep in buildtime_deps:
-+ runtime_deps=runtime_deps.union(self.get_deps(dep,["RDEPEND"]))
-+
-+ ret=buildtime_deps.union(runtime_deps)
-+ return ret
-+
-+ def get_system_packages_list(self):
-+ """
-+ returns all packages from system set. They are always implicit dependencies
-+
-+ :returns: **list** of package names
-+ """
-+ ret=[]
-+ for atom in self.settings.packages:
-+ for pre_pkg in self.vartree.dep_match(atom):
-+ for unvirt_pkg in expand_new_virt(self.vardbapi,'='+pre_pkg):
-+ for pkg in self.vartree.dep_match(unvirt_pkg):
-+ ret.append(pkg)
-+ return ret
-+
-+
-+class GentoolkitUtils:
-+ """
-+ Interface with qfile and qlist utils. They are much faster than
-+ internals.
-+ """
-+
-+ def getpackagesbyfiles(files):
-+ """
-+ :param files: list of filenames
-+ :returns: **dictionary** file->package, if file doesn't belong to any
-+ package it not returned as key of this dictionary
-+ """
-+ ret={}
-+ listtocheck=[]
-+ for f in files:
-+ if os.path.isdir(f):
-+ ret[f]="directory"
-+ else:
-+ listtocheck.append(f)
-+
-+ try:
-+ proc=subprocess.Popen(['qfile']+['--nocolor','--exact','','--from','-'],
-+ stdin=subprocess.PIPE, stdout=subprocess.PIPE,stderr=subprocess.PIPE,
-+ bufsize=4096)
-+
-+ out,err=proc.communicate("\n".join(listtocheck).encode("utf8"))
-+
-+ lines=out.decode("utf8").split("\n")
-+ #print lines
-+ line_re=re.compile(r"^([^ ]+)\s+\(([^)]+)\)$")
-+ for line in lines:
-+ if len(line)==0:
-+ continue
-+ match=line_re.match(line)
-+ if match:
-+ ret[match.group(2)]=match.group(1)
-+ else:
-+ portage.util.writemsg("Util qfile returned unparsable string: %s\n" % line)
-+
-+ except OSError as e:
-+ portage.util.writemsg("Error while launching qfile: %s\n" % e)
-+
-+
-+ return ret
-+
-+ def getfilesbypackages(packagenames):
-+ """
-+
-+ :param packagename: name of package
-+ :returns: **list** of files in package with name *packagename*
-+ """
-+ ret=[]
-+ try:
-+ proc=subprocess.Popen(['qlist']+['--nocolor',"--obj"]+packagenames,
-+ stdout=subprocess.PIPE,stderr=subprocess.PIPE,
-+ bufsize=4096)
-+
-+ out,err=proc.communicate()
-+
-+ ret=out.decode("utf8").split("\n")
-+ if ret==['']:
-+ ret=[]
-+ except OSError as e:
-+ portage.util.writemsg("Error while launching qfile: %s\n" % e)
-+
-+ return ret
-+
-+ def get_all_packages_files():
-+ """
-+ Memory-hungry operation
-+
-+ :returns: **set** of all files that belongs to package
-+ """
-+ ret=[]
-+ try:
-+ proc=subprocess.Popen(['qlist']+['--all',"--obj"],
-+ stdout=subprocess.PIPE,stderr=subprocess.PIPE,
-+ bufsize=4096)
-+
-+ out,err=proc.communicate()
-+
-+ ret=out.decode("utf8").split("\n")
-+ except OSError as e:
-+ portage.util.writemsg("Error while launching qfile: %s\n" % e)
-+
-+ return set(ret)
-+
-+class FilterProcGenerator:
-+ def __init__(self, pkgname, settings):
-+ portageutils=PortageUtils(settings=settings)
-+
-+ deps_all=portageutils.get_deps_for_package_building(pkgname)
-+ deps_portage=portageutils.get_dep('portage',["RDEPEND"])
-+
-+ system_packages=portageutils.get_system_packages_list()
-+
-+ allfiles=GentoolkitUtils.get_all_packages_files()
-+ portage.util.writemsg("All files list recieved, waiting for " \
-+ "a list of allowed files\n")
-+
-+
-+ allowedpkgs=system_packages+list(deps_portage)+list(deps_all)
-+
-+ allowedfiles=GentoolkitUtils.getfilesbypackages(allowedpkgs)
-+ #for pkg in allowedpkgs:
-+ # allowedfiles+=GentoolkitUtils.getfilesbypackage(pkg)
-+
-+ #import pdb; pdb.set_trace()
-+
-+ # manually add all python interpreters to this list
-+ allowedfiles+=GentoolkitUtils.getfilesbypackages(['python'])
-+ allowedfiles=set(allowedfiles)
-+
-+ deniedfiles=allfiles-allowedfiles
-+
-+ def filter_proc(eventname,filename,stage):
-+ if filename in deniedfiles:
-+ return False
-+ return True
-+
-+ self.filter_proc=filter_proc
-+ def get_filter_proc(self):
-+ return self.filter_proc
-+
-+class EventsAnalyser:
-+ def __init__(self, pkgname, events, settings):
-+ self.pkgname=pkgname
-+ self.events=events
-+ self.settings=settings
-+ self.portageutils=PortageUtils(settings=settings)
-+
-+ self.deps_all=self.portageutils.get_deps_for_package_building(pkgname)
-+ self.deps_direct=self.portageutils.get_dep(pkgname,["DEPEND"])
-+ self.deps_portage=self.portageutils.get_dep('portage',["RDEPEND"])
-+
-+ self.system_packages=self.portageutils.get_system_packages_list()
-+ # All analyse work is here
-+
-+ # get unique filenames
-+ filenames=set()
-+ for stage in events:
-+ succ_events=set(events[stage][0])
-+ fail_events=set(events[stage][1])
-+ filenames=filenames.union(succ_events)
-+ filenames=filenames.union(fail_events)
-+ filenames=list(filenames)
-+
-+ file_to_package=GentoolkitUtils.getpackagesbyfiles(filenames)
-+ # This part is completly unreadable.
-+ # It converting one complex struct(returned by getfsevents) to another complex
-+ # struct which good for generating output.
-+ #
-+ # Old struct is also used during output
-+
-+ packagesinfo={}
-+
-+ for stage in sorted(events):
-+ succ_events=events[stage][0]
-+ fail_events=events[stage][1]
-+
-+ for filename in succ_events:
-+ if filename in file_to_package:
-+ package=file_to_package[filename]
-+ else:
-+ package="unknown"
-+
-+ if not package in packagesinfo:
-+ packagesinfo[package]={}
-+ stageinfo=packagesinfo[package]
-+ if not stage in stageinfo:
-+ stageinfo[stage]={}
-+
-+ filesinfo=stageinfo[stage]
-+ if not filename in filesinfo:
-+ filesinfo[filename]={"found":[],"notfound":[]}
-+ filesinfo[filename]["found"]=succ_events[filename]
-+
-+ for filename in fail_events:
-+ if filename in file_to_package:
-+ package=file_to_package[filename]
-+ else:
-+ package="unknown"
-+ if not package in packagesinfo:
-+ packagesinfo[package]={}
-+ stageinfo=packagesinfo[package]
-+ if not stage in stageinfo:
-+ stageinfo[stage]={}
-+
-+ filesinfo=stageinfo[stage]
-+ if not filename in filesinfo:
-+ filesinfo[filename]={"found":[],"notfound":[]}
-+ filesinfo[filename]["notfound"]=fail_events[filename]
-+ self.packagesinfo=packagesinfo
-+
-+ def display(self):
-+ portage.util.writemsg(
-+ portage.output.colorize(
-+ "WARN", "\nFile access report for %s:\n" % self.pkgname))
-+
-+ stagesorder={"clean":1,"setup":2,"unpack":3,"prepare":4,"configure":5,"compile":6,"test":7,
-+ "install":8,"preinst":9,"postinst":10,"prerm":11,"postrm":12,"unknown":13}
-+ packagesinfo=self.packagesinfo
-+ # print information grouped by package
-+ for package in sorted(packagesinfo):
-+ # not showing special directory package
-+ if package=="directory":
-+ continue
-+
-+ if package=="unknown":
-+ continue
-+
-+
-+ is_pkg_in_dep=package in self.deps_all
-+ is_pkg_in_portage_dep=package in self.deps_portage
-+ is_pkg_in_system=package in self.system_packages
-+ is_pkg_python="dev-lang/python" in package
-+
-+ stages=[]
-+ for stage in sorted(packagesinfo[package].keys(), key=stagesorder.get):
-+ if stage!="unknown":
-+ stages.append(stage)
-+
-+ if len(stages)==0:
-+ continue
-+
-+ filenames={}
-+ for stage in stages:
-+ for filename in packagesinfo[package][stage]:
-+ if len(packagesinfo[package][stage][filename]["found"])!=0:
-+ was_readed,was_writed=packagesinfo[package][stage][filename]["found"]
-+ if not filename in filenames:
-+ filenames[filename]=['ok',was_readed,was_writed]
-+ else:
-+ status, old_was_readed, old_was_writed=filenames[filename]
-+ filenames[filename]=[
-+ 'ok',old_was_readed | was_readed, old_was_writed | was_writed
-+ ]
-+ if len(packagesinfo[package][stage][filename]["notfound"])!=0:
-+ was_notfound,was_blocked=packagesinfo[package][stage][filename]["notfound"]
-+ if not filename in filenames:
-+ filenames[filename]=['err',was_notfound,was_blocked]
-+ else:
-+ status, old_was_notfound, old_was_blocked=filenames[filename]
-+ filenames[filename]=[
-+ 'err',old_was_notfound | was_notfound, old_was_blocked | was_blocked
-+ ]
-+
-+
-+ if is_pkg_in_dep:
-+ portage.util.writemsg("[OK]")
-+ elif is_pkg_in_system:
-+ portage.util.writemsg("[SYSTEM]")
-+ elif is_pkg_in_portage_dep:
-+ portage.util.writemsg("[PORTAGE DEP]")
-+ elif is_pkg_python:
-+ portage.util.writemsg("[INTERPRETER]")
-+ elif not self.is_package_useful(package,stages,filenames.keys()):
-+ portage.util.writemsg("[LIKELY OK]")
-+ else:
-+ portage.util.writemsg(portage.output.colorize("BAD", "[NOT IN DEPS]"))
-+ # show information about accessed files
-+
-+ portage.util.writemsg(" %-40s: %s\n" % (package,stages))
-+
-+ # this is here for readability
-+ action={
-+ ('ok',False,False):"accessed",
-+ ('ok',True,False):"readed",
-+ ('ok',False,True):"writed",
-+ ('ok',True,True):"readed and writed",
-+ ('err',False,False):"other error",
-+ ('err',True,False):"not found",
-+ ('err',False,True):"blocked",
-+ ('err',True,True):"not found and blocked"
-+ }
-+
-+ filescounter=0
-+
-+ for filename in filenames:
-+ event_info=tuple(filenames[filename])
-+ portage.util.writemsg(" %-56s %-21s\n" % (filename,action[event_info]))
-+ filescounter+=1
-+ if filescounter>10:
-+ portage.util.writemsg(" ... and %d more ...\n" % (len(filenames)-10))
-+ break
-+ # ... and one more check. Making sure that direct build time
-+ # dependencies were accessed
-+ #import pdb; pdb.set_trace()
-+ not_accessed_deps=set(self.deps_direct)-set(self.packagesinfo.keys())
-+ if not_accessed_deps:
-+ portage.util.writemsg(portage.output.colorize("WARN", "!!! "))
-+ portage.util.writemsg("Warning! Some build time dependencies " + \
-+ "of packages were not accessed: " + \
-+ " ".join(not_accessed_deps) + "\n")
-+
-+ def is_package_useful(self,pkg,stages,files):
-+ """ some basic heuristics here to cut part of packages """
-+
-+ excluded_paths=set(
-+ ['/etc/sandbox.d/']
-+ )
-+
-+ excluded_packages=set(
-+ # autodep shows these two packages every time
-+ ['net-zope/zope-fixers', 'net-zope/zope-interface']
-+ )
-+
-+
-+ def is_pkg_excluded(p):
-+ for pkg in excluded_packages:
-+ if p.startswith(pkg): # if package is excluded
-+ return True
-+ return False
-+
-+
-+ def is_file_excluded(f):
-+ for path in excluded_paths:
-+ if f.startswith(path): # if path is excluded
-+ return True
-+ return False
-+
-+
-+ if is_pkg_excluded(pkg):
-+ return False
-+
-+ for f in files:
-+ if is_file_excluded(f):
-+ continue
-+
-+ # test 1: package is not useful if all files are *.desktop or *.xml or *.m4
-+ if not (f.endswith(".desktop") or f.endswith(".xml") or f.endswith(".m4") or f.endswith(".pc")):
-+ break
-+ else:
-+ return False # we get here if cycle ends not with break
-+
-+ return True
-+
-+
-\ No newline at end of file
-diff -urN /usr/lib/portage/pym/_emerge/EventsLogger.py ./pym/_emerge/EventsLogger.py
---- /usr/lib/portage/pym/_emerge/EventsLogger.py 1970-01-01 05:00:00.000000000 +0500
-+++ ./pym/_emerge/EventsLogger.py 2012-06-01 21:37:22.803844102 +0600
-@@ -0,0 +1,180 @@
-+# Distributed under the terms of the GNU General Public License v2
-+
-+import io
-+import sys
-+import stat
-+import socket
-+import select
-+import tempfile
-+
-+import threading
-+
-+from portage import os
-+
-+class EventsLogger(threading.Thread):
-+ def default_filter(eventname, filename, stage):
-+ return True
-+
-+ def __init__(self, socket_dir="/tmp/", filter_proc=default_filter):
-+ threading.Thread.__init__(self) # init the Thread
-+
-+ self.alive=False
-+
-+ self.main_thread=threading.currentThread()
-+
-+ self.socket_dir=socket_dir
-+ self.filter_proc=filter_proc
-+
-+ self.socket_name=None
-+ self.socket_logger=None
-+
-+ self.events={}
-+
-+ try:
-+ socket_dir_name = tempfile.mkdtemp(dir=self.socket_dir,
-+ prefix="log_socket_")
-+
-+ socket_name = os.path.join(socket_dir_name, 'socket')
-+
-+ except OSError as e:
-+ return
-+
-+ self.socket_name=socket_name
-+
-+ #print(self.socket_name)
-+
-+ try:
-+ socket_logger=socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
-+ socket_logger.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-+
-+ socket_logger.bind(self.socket_name)
-+ socket_logger.listen(64)
-+
-+ except socket.error as e:
-+ return
-+
-+ self.socket_logger=socket_logger
-+
-+ try:
-+ # Allow connecting to socket for anyone
-+ os.chmod(socket_dir_name,
-+ stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR|
-+ stat.S_IROTH|stat.S_IWOTH|stat.S_IXOTH)
-+ os.chmod(socket_name,
-+ stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR|
-+ stat.S_IROTH|stat.S_IWOTH|stat.S_IXOTH)
-+ except OSError as e:
-+ return
-+
-+ def run(self):
-+ """ Starts the log server """
-+
-+ self.alive=True
-+ self.listen_thread=threading.currentThread()
-+ clients={}
-+
-+ epoll=select.epoll()
-+ epoll.register(self.socket_logger.fileno(), select.EPOLLIN)
-+
-+ while self.alive:
-+ try:
-+ sock_events = epoll.poll(3)
-+
-+ for fileno, sock_event in sock_events:
-+ if fileno == self.socket_logger.fileno():
-+ ret = self.socket_logger.accept()
-+ if ret is None:
-+ pass
-+ else:
-+ (client,addr)=ret
-+ epoll.register(client.fileno(), select.EPOLLIN)
-+ clients[client.fileno()]=client
-+ elif sock_event & select.EPOLLIN:
-+ s=clients[fileno]
-+ record=s.recv(8192)
-+
-+ if not record: # if connection was closed
-+ epoll.unregister(fileno)
-+ clients[fileno].close()
-+ del clients[fileno]
-+ continue
-+
-+ #import pdb; pdb.set_trace()
-+ try:
-+ message=record.decode("utf8").split("\0")
-+ except UnicodeDecodeError:
-+ print("Bad message %s" % record)
-+ continue
-+
-+ # continue
-+
-+ #print(message)
-+
-+ try:
-+ if message[4]=="ASKING":
-+ if self.filter_proc(message[1],message[2],message[3]):
-+ s.sendall(b"ALLOW\0")
-+ else:
-+ # TODO: log through portage infrastructure
-+ #print("Blocking an access to %s" % message[2])
-+ s.sendall(b"DENY\0")
-+ else:
-+ eventname,filename,stage,result=message[1:5]
-+
-+ if not stage in self.events:
-+ self.events[stage]=[{},{}]
-+
-+ hashofsucesses=self.events[stage][0]
-+ hashoffailures=self.events[stage][1]
-+
-+ if result=="DENIED":
-+ print("Blocking an access to %s" % filename)
-+
-+ if result=="OK":
-+ if not filename in hashofsucesses:
-+ hashofsucesses[filename]=[False,False]
-+
-+ readed_or_writed=hashofsucesses[filename]
-+
-+ if eventname=="read":
-+ readed_or_writed[0]=True
-+ elif eventname=="write":
-+ readed_or_writed[1]=True
-+
-+ elif result[0:3]=="ERR" or result=="DENIED":
-+ if not filename in hashoffailures:
-+ hashoffailures[filename]=[False,False]
-+ notfound_or_blocked=hashoffailures[filename]
-+
-+ if result=="ERR/2":
-+ notfound_or_blocked[0]=True
-+ elif result=="DENIED":
-+ notfound_or_blocked[1]=True
-+
-+ else:
-+ print("Error in logger module<->analyser protocol")
-+
-+ except IndexError:
-+ print("IndexError while parsing %s" % record)
-+ except IOError as e:
-+ if e.errno!=4: # handling "Interrupted system call" errors
-+ raise
-+
-+ # if main thread doesnt exists then exit
-+ if not self.main_thread.is_alive():
-+ break
-+ epoll.unregister(self.socket_logger.fileno())
-+ epoll.close()
-+ self.socket_logger.close()
-+
-+ def stop(self):
-+ """ Stops the log server. Returns all events """
-+
-+ self.alive=False
-+
-+ # Block the main thread until listener exists
-+ self.listen_thread.join()
-+
-+ # We assume portage clears tmp folder, so no deleting a socket file
-+ # We assume that no new socket data will arrive after this moment
-+ return self.events
-diff -urN /usr/lib/portage/pym/portage/const.py ./pym/portage/const.py
---- /usr/lib/portage/pym/portage/const.py 2012-05-28 16:20:40.766712558 +0600
-+++ ./pym/portage/const.py 2012-06-01 21:39:51.363837853 +0600
-@@ -67,6 +67,8 @@
- BASH_BINARY = "/bin/bash"
- MOVE_BINARY = "/bin/mv"
- PRELINK_BINARY = "/usr/sbin/prelink"
-+AUTODEP_LIBRARY = "/usr/lib/file_hook.so"
-+
-
- INVALID_ENV_FILE = "/etc/spork/is/not/valid/profile.env"
- REPO_NAME_FILE = "repo_name"
-@@ -89,7 +91,7 @@
- "assume-digests", "binpkg-logs", "buildpkg", "buildsyspkg", "candy",
- "ccache", "chflags", "clean-logs",
- "collision-protect", "compress-build-logs", "compressdebug",
-- "config-protect-if-modified",
-+ "config-protect-if-modified", "depcheck", "depcheckstrict",
- "digest", "distcc", "distcc-pump", "distlocks", "ebuild-locks", "fakeroot",
- "fail-clean", "force-mirror", "force-prefix", "getbinpkg",
- "installsources", "keeptemp", "keepwork", "fixlafiles", "lmirror",
-diff -urN /usr/lib/portage/pym/portage/const.py.rej ./pym/portage/const.py.rej
---- /usr/lib/portage/pym/portage/const.py.rej 1970-01-01 05:00:00.000000000 +0500
-+++ ./pym/portage/const.py.rej 2012-06-01 21:37:22.803844102 +0600
-@@ -0,0 +1,12 @@
-+--- pym/portage/const.py
-++++ pym/portage/const.py
-+@@ -90,7 +92,8 @@
-+ SUPPORTED_FEATURES = frozenset([
-+ "allow-missing-manifests",
-+ "assume-digests", "binpkg-logs", "buildpkg", "buildsyspkg", "candy",
-+- "ccache", "chflags", "collision-protect", "compress-build-logs",
-++ "ccache", "chflags", "collision-protect", "compress-build-logs",
-++ "depcheck", "depcheckstrict",
-+ "digest", "distcc", "distcc-pump", "distlocks", "ebuild-locks", "fakeroot",
-+ "fail-clean", "fixpackages", "force-mirror", "getbinpkg",
-+ "installsources", "keeptemp", "keepwork", "fixlafiles", "lmirror",
-diff -urN /usr/lib/portage/pym/portage/package/ebuild/_config/special_env_vars.py ./pym/portage/package/ebuild/_config/special_env_vars.py
---- /usr/lib/portage/pym/portage/package/ebuild/_config/special_env_vars.py 2012-05-28 16:20:40.870712551 +0600
-+++ ./pym/portage/package/ebuild/_config/special_env_vars.py 2012-06-01 21:37:22.804844102 +0600
-@@ -101,8 +101,8 @@
- # other variables inherited from the calling environment
- environ_whitelist += [
- "CVS_RSH", "ECHANGELOG_USER",
-- "GPG_AGENT_INFO",
-- "SSH_AGENT_PID", "SSH_AUTH_SOCK",
-+ "GPG_AGENT_INFO", "LOG_SOCKET",
-+ "SSH_AGENT_PID", "SSH_AUTH_SOCK"
- "STY", "WINDOW", "XAUTHORITY",
- ]
-
-diff -urN /usr/lib/portage/pym/portage/package/ebuild/doebuild.py ./pym/portage/package/ebuild/doebuild.py
---- /usr/lib/portage/pym/portage/package/ebuild/doebuild.py 2012-05-28 16:20:40.860712554 +0600
-+++ ./pym/portage/package/ebuild/doebuild.py 2012-06-01 21:37:22.805844102 +0600
-@@ -1222,6 +1222,9 @@
- nosandbox = ("sandbox" not in features and \
- "usersandbox" not in features)
-
-+ if "depcheck" in features or "depcheckstrict" in features:
-+ nosandbox = True
-+
- if not portage.process.sandbox_capable:
- nosandbox = True
-
-@@ -1401,7 +1404,10 @@
- keywords["opt_name"] = "[%s/%s]" % \
- (mysettings.get("CATEGORY",""), mysettings.get("PF",""))
-
-- if free or "SANDBOX_ACTIVE" in os.environ:
-+ if "depcheck" in features or "depcheckstrict" in features:
-+ keywords["opt_name"] += " bash"
-+ spawn_func = portage.process.spawn_autodep
-+ elif free or "SANDBOX_ACTIVE" in os.environ:
- keywords["opt_name"] += " bash"
- spawn_func = portage.process.spawn_bash
- elif fakeroot:
-diff -urN /usr/lib/portage/pym/portage/process.py ./pym/portage/process.py
---- /usr/lib/portage/pym/portage/process.py 2012-05-28 16:20:40.768712558 +0600
-+++ ./pym/portage/process.py 2012-06-01 21:37:22.806844102 +0600
-@@ -18,7 +18,7 @@
- 'portage.util:dump_traceback',
- )
-
--from portage.const import BASH_BINARY, SANDBOX_BINARY, FAKEROOT_BINARY
-+from portage.const import BASH_BINARY, SANDBOX_BINARY, FAKEROOT_BINARY, AUTODEP_LIBRARY
- from portage.exception import CommandNotFound
-
- try:
-@@ -53,6 +53,9 @@
- sandbox_capable = (os.path.isfile(SANDBOX_BINARY) and
- os.access(SANDBOX_BINARY, os.X_OK))
-
-+autodep_capable = (os.path.isfile(AUTODEP_LIBRARY) and
-+ os.access(AUTODEP_LIBRARY, os.X_OK))
-+
- fakeroot_capable = (os.path.isfile(FAKEROOT_BINARY) and
- os.access(FAKEROOT_BINARY, os.X_OK))
-
-@@ -80,6 +83,16 @@
- args.append(mycommand)
- return spawn(args, opt_name=opt_name, **keywords)
-
-+def spawn_autodep(mycommand, opt_name=None, **keywords):
-+ if not autodep_capable:
-+ return spawn_bash(mycommand, opt_name=opt_name, **keywords)
-+ if "env" not in keywords or "LOG_SOCKET" not in keywords["env"]:
-+ return spawn_bash(mycommand, opt_name=opt_name, **keywords)
-+
-+ # Core part: tell the loader to preload logging library
-+ keywords["env"]["LD_PRELOAD"]=AUTODEP_LIBRARY
-+ return spawn_bash(mycommand, opt_name=opt_name, **keywords)
-+
- def spawn_sandbox(mycommand, opt_name=None, **keywords):
- if not sandbox_capable:
- return spawn_bash(mycommand, opt_name=opt_name, **keywords)