# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+from buildfarm.sqldb import distinct_builds, Cast, StormBuild, setup_schema, StormHostDatabase
+from buildfarm.tree import Tree
+from storm.database import create_database
+from storm.expr import Desc
+from storm.store import Store
+
import ConfigParser
import os
import re
-GIT_ROOT = "/data/git"
-
-
-class Tree(object):
- """A tree to build."""
-
- def __init__(self, name, scm, repo, branch, subdir="", srcdir=""):
- self.name = name
- self.repo = repo
- self.scm = scm
- self.branch = branch
- self.subdir = subdir
- self.srcdir = srcdir
- self.scm = scm
-
- def get_branch(self):
- if self.scm == "git":
- from buildfarm.history import GitBranch
- return GitBranch(os.path.join(GIT_ROOT, self.repo), self.branch)
- else:
- raise NotImplementedError(self.scm)
-
- def __repr__(self):
- return "<%s %r>" % (self.__class__.__name__, self.name)
-
-
def read_trees_from_conf(path):
"""Read trees from a configuration file.
return ret
-def lcov_extract_percentage(text):
+def lcov_extract_percentage(f):
"""Extract the coverage percentage from the lcov file."""
- m = re.search('\<td class="headerItem".*?\>Code\ \;covered\:\<\/td\>.*?\n.*?\<td class="headerValue".*?\>([0-9.]+) \%', text)
+ m = re.search('\<td class="headerItem".*?\>Code\ \;covered\:\<\/td\>.*?\n.*?\<td class="headerValue".*?\>([0-9.]+) \%', f.read())
if m:
return m.group(1)
else:
class BuildFarm(object):
- LCOVHOST = "magni"
+ LCOVHOST = "coverage"
OLDAGE = 60*60*4,
DEADAGE = 60*60*24*4
- def __init__(self, path=None):
+ def __init__(self, path=None, store=None, timeout=0.5):
+ self.timeout = timeout
+ self.store = store
if path is None:
path = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
self.path = path
return "%s(%r)" % (self.__class__.__name__, self.path)
def _open_build_results(self):
- from buildfarm import data
- return data.BuildResultStore(os.path.join(self.path, "data", "oldrevs"))
+ path = os.path.join(self.path, "data", "oldrevs")
+ from buildfarm.build import BuildResultStore
+ return BuildResultStore(path, self._get_store())
def _open_upload_build_results(self):
- from buildfarm import data
- return data.UploadBuildResultStore(os.path.join(self.path, "data", "upload"))
+ from buildfarm.build import UploadBuildResultStore
+ path = os.path.join(self.path, "data", "upload")
+ return UploadBuildResultStore(path)
def _open_hostdb(self):
- from buildfarm import hostdb
- return hostdb.PlainTextHostDatabase.from_file(os.path.join(self.webdir, "hosts.list"))
+ return StormHostDatabase(self._get_store())
def _load_compilers(self):
from buildfarm import util
return set(util.load_list(os.path.join(self.webdir, "compilers.list")))
def commit(self):
- pass
+ if self.store is not None:
+ self.store.commit()
def lcov_status(self, tree):
"""get status of build"""
- from buildfarm import data, util
+ from buildfarm.build import NoSuchBuildError
file = os.path.join(self.lcovdir, self.LCOVHOST, tree, "index.html")
try:
- lcov_html = util.FileLoad(file)
+ lcov_html = open(file, 'r')
except (OSError, IOError):
# File does not exist
- raise data.NoSuchBuildError(tree, self.LCOVHOST, "lcov")
+ raise NoSuchBuildError(tree, self.LCOVHOST, "lcov")
+ try:
+ return lcov_extract_percentage(lcov_html)
+ finally:
+ lcov_html.close()
- perc = lcov_extract_percentage(lcov_html)
- if perc is None:
- ret = ""
- else:
- ret = perc
- return perc
+ def unused_fns(self, tree):
+ """get status of build"""
+ from buildfarm.build import NoSuchBuildError
+ file = os.path.join(self.lcovdir, self.LCOVHOST, tree, "unused-fns.txt")
+ try:
+ unused_fns_file = open(file, 'r')
+ except (OSError, IOError):
+ # File does not exist
+ raise NoSuchBuildError(tree, self.LCOVHOST, "unused_fns")
+ try:
+ return "unused-fns.txt"
+ finally:
+ unused_fns_file.close()
- def get_build(self, tree, host, compiler, rev=None):
+ def get_build(self, tree, host, compiler, rev=None, checksum=None):
if rev is not None:
- return self.builds.get_build(tree, host, compiler, rev)
+ return self.builds.get_build(tree, host, compiler, rev,
+ checksum=checksum)
else:
return self.upload_builds.get_build(tree, host, compiler)
def get_new_builds(self):
hostnames = set([host.name for host in self.hostdb.hosts()])
- for build in self.upload_builds.get_new_builds():
- if build.tree in self.trees and build.compiler in self.compilers and build.host in hostnames:
+ for build in self.upload_builds.get_all_builds():
+ if (build.tree in self.trees and
+ build.compiler in self.compilers and
+ build.host in hostnames):
yield build
- def get_host_builds(self, host):
- from buildfarm import data
- for compiler in self.compilers:
- for tree in sorted(self.trees.keys()):
- try:
- yield self.get_build(tree, host, compiler)
- except data.NoSuchBuildError:
- pass
+ def get_last_builds(self):
+ result = self._get_store().find(StormBuild)
+ return distinct_builds(result.order_by(Desc(StormBuild.upload_time)))
+ def get_tree_builds(self, tree):
+ result = self._get_store().find(StormBuild,
+ Cast(StormBuild.tree, "TEXT") == Cast(tree, "TEXT"))
+ return distinct_builds(result.order_by(Desc(StormBuild.upload_time)))
+ def host_last_build(self, host):
+ return max([build.upload_time for build in self.get_host_builds(host)])
+
+ def get_host_builds(self, host):
+ result = self._get_store().find(StormBuild, StormBuild.host == host)
+ return distinct_builds(result.order_by(Desc(StormBuild.upload_time)))
+
+ def _get_store(self):
+ if self.store is not None:
+ return self.store
+ db_path = os.path.join(self.path, "db", "hostdb.sqlite")
+ db = create_database("sqlite:%s?timeout=%f" % (db_path, self.timeout))
+ self.store = Store(db)
+ setup_schema(self.store)
+ return self.store
+
+ def get_revision_builds(self, tree, revision=None):
+ return self._get_store().find(StormBuild,
+ Cast(StormBuild.tree, "TEXT") == Cast(tree, "TEXT"),
+ Cast(StormBuild.revision, "TEXT") == Cast(revision, "TEXT"))