[SCM] build.samba.org - branch master updated
Jelmer Vernooij
jelmer at samba.org
Tue Nov 2 02:48:41 MDT 2010
The branch, master has been updated
via 0c4399c Move build_status onto Build.
via 846f498 Move revision_details onto Build.
via 8f5f5f6 Move read_log and read_err onto Build.
via 5b5e222 Move age_mtime/age_ctime onto Build.
via 29cee7a Add Build object.
from 9e71906 Raise NoSuchBuildError rather than silently pretending files are empty.
http://gitweb.samba.org/?p=build-farm.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 0c4399c4712a8d7eb8407b654270c3f080063f6d
Author: Jelmer Vernooij <jelmer at samba.org>
Date: Tue Nov 2 09:48:57 2010 +0100
Move build_status onto Build.
commit 846f498b80e05b3031bd9724121a6bd90c1d54d3
Author: Jelmer Vernooij <jelmer at samba.org>
Date: Tue Nov 2 09:46:07 2010 +0100
Move revision_details onto Build.
commit 8f5f5f676389096345def353a1c0f14cba56447b
Author: Jelmer Vernooij <jelmer at samba.org>
Date: Tue Nov 2 09:35:20 2010 +0100
Move read_log and read_err onto Build.
commit 5b5e2224772636e45f785c3cca88c6a2816e0d14
Author: Jelmer Vernooij <jelmer at samba.org>
Date: Tue Nov 2 09:32:48 2010 +0100
Move age_mtime/age_ctime onto Build.
commit 29cee7a9abac3c8fc2c59831438d393af0c69220
Author: Jelmer Vernooij <jelmer at samba.org>
Date: Tue Nov 2 09:31:01 2010 +0100
Add Build object.
-----------------------------------------------------------------------
Summary of changes:
buildfarm/data.py | 282 +++++++++++++++++++++---------------------
buildfarm/tests/test_data.py | 23 ++--
web/build.py | 30 +++--
3 files changed, 170 insertions(+), 165 deletions(-)
Changeset truncated at 500 lines:
diff --git a/buildfarm/data.py b/buildfarm/data.py
index d083698..426f50a 100644
--- a/buildfarm/data.py
+++ b/buildfarm/data.py
@@ -82,6 +82,131 @@ class Tree(object):
return "<%s %r>" % (self.__class__.__name__, self.name)
+class Build(object):
+ """A single build of a tree on a particular host using a particular compiler.
+ """
+
+ def __init__(self, store, tree, host, compiler, rev=None):
+ self._store = store
+ self.tree = tree
+ self.host = host
+ self.compiler = compiler
+ self.rev = rev
+
+ ###################
+ # the mtime age is used to determine if builds are still happening
+ # on a host.
+ # the ctime age is used to determine when the last real build happened
+
+ def age_mtime(self):
+ """get the age of build from mtime"""
+ file = self._store.build_fname(self.tree, self.host, self.compiler, self.rev)
+
+ st = os.stat("%s.log" % file)
+ return time.time() - st.st_mtime
+
+ def age_ctime(self):
+ """get the age of build from ctime"""
+ file = self._store.build_fname(self.tree, self.host, self.compiler, self.rev)
+
+ st = os.stat("%s.log" % file)
+ return time.time() - st.st_ctime
+
+ def read_log(self):
+ """read full log file"""
+ f = open(self._store.build_fname(self.tree, self.host, self.compiler, self.rev)+".log", "r")
+ try:
+ return f.read()
+ finally:
+ f.close()
+
+ def read_err(self):
+ """read full err file"""
+ return util.FileLoad(self._store.build_fname(self.tree, self.host, self.compiler, self.rev)+".err")
+
+ def build_revision_details(self):
+ """get the revision of build
+
+ :return: Tuple with revision id and timestamp (if available)
+ """
+ file = self._store.build_fname(self.tree, self.host, self.compiler, self.rev)
+ cachef = self._store.cache_fname(self.tree, self.host, self.compiler, self.rev)
+
+ # don't fast-path for trees with git repository:
+ # we get the timestamp as rev and want the details
+ if self.rev:
+ if self.tree not in self._store.trees:
+ return self.rev
+ if self.trees[self.tree].scm != "git":
+ return self.rev
+
+ st1 = os.stat("%s.log" % file)
+
+ try:
+ st2 = os.stat("%s.revision" % cachef)
+ except OSError:
+ # File does not exist
+ st2 = None
+
+ # the ctime/mtime asymmetry is needed so we don't get fooled by
+ # the mtime update from rsync
+ if st2 and st1.st_ctime <= st2.st_mtime:
+ (revid, timestamp) = util.FileLoad("%s.revision" % cachef).split(":", 1)
+ if timestamp == "":
+ return (revid, None)
+ else:
+ return (revid, timestamp)
+
+ revid = None
+ timestamp = None
+ f = open("%s.log" % file, 'r')
+ try:
+ for l in f.readlines():
+ if l.startswith("BUILD COMMIT REVISION: "):
+ revid = l.split(":", 1)[1].strip()
+ elif l.startswith("BUILD REVISION: "):
+ revid = l.split(":", 1)[1].strip()
+ elif l.startswith("BUILD COMMIT TIME"):
+ timestamp = l.split(":", 1)[1].strip()
+ finally:
+ f.close()
+
+ if not self.readonly:
+ util.FileSave("%s.revision" % cachef, "%s:%s" % (revid, timestamp or ""))
+
+ return (revid, timestamp)
+
+ def status(self):
+ """get status of build
+
+ :return: string with build status
+ """
+ # FIXME: This should return a tuple
+
+ file = self._store.build_fname(self.tree, self.host, self.compiler, self.rev)
+ cachefile = self._store.cache_fname(self.tree, self.host, self.compiler, self.rev)+".status"
+ st1 = os.stat("%s.log" % file)
+
+ try:
+ st2 = os.stat(cachefile)
+ except OSError:
+ # No such file
+ st2 = None
+
+ if st2 and st1.st_ctime <= st2.st_mtime:
+ return util.FileLoad(cachefile)
+
+ log = self.read_log()
+ err = self.read_err()
+
+ ret = self._store.build_status_from_logs(log, err)
+
+ if not self.readonly:
+ util.FileSave(cachefile, ret)
+
+ return ret
+
+
def read_trees_from_conf(path):
"""Read trees from a configuration file."""
ret = {}
@@ -126,6 +251,12 @@ class BuildResultStore(object):
self.trees = read_trees_from_conf(os.path.join(self.webdir, "trees.conf"))
+ def get_build(self, tree, host, compiler, rev=None):
+ logf = self.build_fname(tree, host, compiler, rev) + ".log"
+ if not os.path.exists(logf):
+ raise NoSuchBuildError(tree, host, compiler, rev)
+ return Build(self, tree, host, compiler, rev)
+
def cache_fname(self, tree, host, compiler, rev=None):
if rev is not None:
return os.path.join(self.cachedir, "build.%s.%s.%s-%s" % (tree,host,compiler,rev))
@@ -138,92 +269,14 @@ class BuildResultStore(object):
return os.path.join(self.datadir, "oldrevs/build.%s.%s.%s-%s" % (tree, host, compiler, rev))
return os.path.join(self.datadir, "upload/build.%s.%s.%s" % (tree, host, compiler))
- ###################
- # the mtime age is used to determine if builds are still happening
- # on a host.
- # the ctime age is used to determine when the last real build happened
-
- def build_age_mtime(self, tree, host, compiler, rev=None):
- """get the age of build from mtime"""
- file = self.build_fname(tree, host, compiler, rev=rev)
-
- try:
- st = os.stat("%s.log" % file)
- except OSError:
- # File does not exist
- raise NoSuchBuildError(tree, host, compiler, rev)
- else:
- return time.time() - st.st_mtime
-
- def build_age_ctime(self, tree, host, compiler, rev=None):
- """get the age of build from ctime"""
- file = self.build_fname(tree, host, compiler, rev=rev)
-
- try:
- st = os.stat("%s.log" % file)
- except OSError:
- raise NoSuchBuildError(tree, host, compiler, rev)
- else:
- return time.time() - st.st_ctime
-
- def build_revision_details(self, tree, host, compiler, rev=None):
- """get the revision of build"""
- file = self.build_fname(tree, host, compiler, rev)
- cachef = self.cache_fname(tree, host, compiler, rev)
-
- # don't fast-path for trees with git repository:
- # we get the timestamp as rev and want the details
- if rev:
- if tree not in self.trees:
- return rev
- if self.trees[tree].scm != "git":
- return rev
-
- try:
- st1 = os.stat("%s.log" % file)
- except OSError:
- # File does not exist
- raise NoSuchBuildError(tree, host, compiler, rev)
-
- try:
- st2 = os.stat("%s.revision" % cachef)
- except OSError:
- # File does not exist
- st2 = None
-
- # the ctime/mtime asymmetry is needed so we don't get fooled by
- # the mtime update from rsync
- if st2 and st1.st_ctime <= st2.st_mtime:
- return util.FileLoad("%s.revision" % cachef)
-
- log = util.FileLoad("%s.log" % file)
-
- m = re.search("BUILD COMMIT REVISION: (.*)", log)
- if m:
- ret = m.group(1)
- else:
- m = re.search("BUILD REVISION: (.*)", log)
- if m:
- ret = m.group(1)
- else:
- ret = ""
-
- m = re.search("BUILD COMMIT TIME: (.*)", log)
- if m:
- ret += ":" + m.group(1)
-
- if not self.readonly:
- util.FileSave("%s.revision" % cachef, ret)
-
- return ret
def build_revision(self, tree, host, compiler, rev=None):
- r = self.build_revision_details(tree, host, compiler, rev=rev)
- return r.split(":")[0]
+ build = self.get_build(tree, host, compiler, rev)
+ return build.revision_details()[0]
def build_revision_time(self, tree, host, compiler, rev=None):
- r = self.build_revision_details(tree, host, compiler, rev)
- return r.split(":", 1)[1]
+ build = self.get_build(tree, host, compiler, rev)
+ return build.revision_details()[1]
def build_status_from_logs(self, log, err):
"""get status of build"""
@@ -289,48 +342,6 @@ class BuildResultStore(object):
return "%s/%s/%s/%s%s%s%s" % (
cstatus, bstatus, istatus, tstatus, sstatus, dstatus, tostatus)
- def build_status(self, tree, host, compiler, rev=None):
- """get status of build
-
- :param tree: Tree name
- :param host: Host name
- :param compiler: Compiler name
- :param rev: Revision
- :return: string with build status
- """
- # FIXME: This should return a tuple
-
- file = self.build_fname(tree, host, compiler, rev)
- cachefile = self.cache_fname(tree, host, compiler, rev)+".status"
- try:
- st1 = os.stat("%s.log" % file)
- except OSError:
- # No such file
- raise NoSuchBuildError(tree, host, compiler, rev)
-
- try:
- st2 = os.stat(cachefile)
- except OSError:
- # No such file
- st2 = None
-
- if st2 and st1.st_ctime <= st2.st_mtime:
- return util.FileLoad(cachefile)
-
- log = util.FileLoad("%s.log" % file)
- try:
- err = util.FileLoad("%s.err" % file)
- except OSError:
- # No such file
- err = ""
-
- ret = self.build_status_from_logs(log, err)
-
- if not self.readonly:
- util.FileSave(cachefile, ret)
-
- return ret
-
def build_status_info_from_string(self, rev_seq, rev, status_raw):
"""find the build status as an perl object
@@ -381,8 +392,9 @@ class BuildResultStore(object):
the 'value' gets one point for passing each stage
"""
- rev = self.build_revision(tree, host, compiler, rev_seq)
- status_html = self.build_status(tree, host, compiler, rev_seq)
+ build = self.get_build(tree, host, compiler, rev_seq)
+ rev, rev_time = build.revision_details()
+ status_html = build.status()
return self.build_status_info_from_html(rev_seq, rev, status_html)
def lcov_status(self, tree):
@@ -446,18 +458,6 @@ class BuildResultStore(object):
return ret
- def read_log(self, tree, host, compiler, rev=None):
- """read full log file"""
- f = open(self.build_fname(tree, host, compiler, rev)+".log", "r")
- try:
- return f.read()
- finally:
- f.close()
-
- def read_err(self, tree, host, compiler, rev=None):
- """read full err file"""
- return util.FileLoad(self.build_fname(tree, host, compiler, rev)+".err")
-
def get_old_revs(self, tree, host, compiler):
"""get a list of old builds and their status."""
ret = []
@@ -471,8 +471,9 @@ class BuildResultStore(object):
# skip the current build
if stat.st_nlink == 2:
continue
+ build = self.get_build(tree, host, compiler, rev)
r = {
- "STATUS": self.build_status(tree, host, compiler, rev),
+ "STATUS": build.status(),
"REVISION": rev,
"TIMESTAMP": stat.st_ctime
}
@@ -491,7 +492,8 @@ class BuildResultStore(object):
for compiler in self.compilers:
for tree in self.trees:
try:
- age = self.db.build_age_mtime(tree, host, compiler)
+ build = self.get_build(tree, host, compiler)
+ age = build.age_mtime()
except NoSuchBuildError:
pass
else:
diff --git a/buildfarm/tests/test_data.py b/buildfarm/tests/test_data.py
index d265125..d54206e 100755
--- a/buildfarm/tests/test_data.py
+++ b/buildfarm/tests/test_data.py
@@ -62,32 +62,31 @@ class BuildResultStoreTests(BuildFarmTestCase):
path = self.create_mock_logfile("tdb", "charis", "cc")
# Set mtime to something in the past
os.utime(path, (time.time(), time.time() - 990))
- age = self.x.build_age_mtime("tdb", "charis", "cc")
+ build = self.x.get_build("tdb", "charis", "cc")
+ age = build.age_mtime()
self.assertTrue(age >= 990 and age <= 1000, "age was %d" % age)
- def test_build_age_mtime_nonexistant(self):
- self.assertRaises(data.NoSuchBuildError, self.x.build_age_mtime, "tdb",
+ def test_get_build_nonexistant(self):
+ self.assertRaises(data.NoSuchBuildError, self.x.get_build, "tdb",
"charis", "cc")
def test_build_age_ctime(self):
path = self.create_mock_logfile("tdb", "charis", "cc")
# Set mtime to something in the past
- age = self.x.build_age_ctime("tdb", "charis", "cc")
+ build = self.x.get_build("tdb", "charis", "cc")
+ age = build.age_ctime()
self.assertTrue(age >= 0 and age <= 10, "age was %d" % age)
- def test_build_age_ctime_nonexistant(self):
- self.assertRaises(data.NoSuchBuildError, self.x.build_age_ctime, "tdb",
- "charis", "cc")
-
def test_read_log(self):
path = self.create_mock_logfile("tdb", "charis", "cc",
contents="This is what a log file looks like.")
- log = self.x.read_log("tdb", "charis", "cc")
- self.assertEquals("This is what a log file looks like.", log)
+ build = self.x.get_build("tdb", "charis", "cc")
+ self.assertEquals("This is what a log file looks like.", build.read_log())
def test_read_err(self):
+ self.create_mock_logfile("tdb", "charis", "cc")
path = self.create_mock_logfile("tdb", "charis", "cc",
kind="stderr",
contents="This is what an stderr file looks like.")
- log = self.x.read_err("tdb", "charis", "cc")
- self.assertEquals("This is what an stderr file looks like.", log)
+ build = self.x.get_build("tdb", "charis", "cc")
+ self.assertEquals("This is what an stderr file looks like.", build.read_err())
diff --git a/web/build.py b/web/build.py
index df583aa..71d4bae 100755
--- a/web/build.py
+++ b/web/build.py
@@ -79,7 +79,8 @@ def build_link(myself, tree, host, compiler, rev, status):
def build_status(myself, tree, host, compiler, rev):
- status = db.build_status(tree, host, compiler, rev)
+ build = db.get_build(tree, host, compiler, rev)
+ status = build.build_status()
return build_link(myself, tree, host, compiler, rev, status)
@@ -130,10 +131,11 @@ def view_summary(myself, output_type):
for compiler in compilers:
for tree in trees:
try:
+ build = db.get_build(tree, host, compiler)
status = build_status(myself, tree, host, compiler)
except data.NoSuchBuildError:
continue
- age_mtime = db.build_age_mtime(tree, host, compiler)
+ age_mtime = build.age_mtime()
host_count[tree]+=1
if "status failed" in status:
@@ -243,13 +245,13 @@ def view_recent_builds(myself, tree, sort_by):
for compiler in compilers:
try:
status = build_status(myself, tree, host, compiler)
+ build = db.get_build(tree, host, compiler)
except data.NoSuchBuildError:
pass
else:
- age_mtime = db.build_age_mtime(tree, host, compiler)
- age_ctime = db.build_age_ctime(tree, host, compiler)
- revision = db.build_revision(tree, host, compiler)
- revision_time = db.build_revision_time(tree, host, compiler)
+ age_mtime = build.age_mtime()
+ age_ctime = build.age_ctime()
+ (revision, revision_time) = build.revision_details()
all_builds.append([age_ctime, hosts[host], "<a href='%s?function=View+Host;host=%s;tree=%s;compiler=%s#%s'>%s</a>" % (myself, host, tree, compiler, host, host), compiler, tree, status, revision_link(myself, revision, tree), revision_time])
all_builds.sort(cmp_funcs[sort_by])
@@ -347,14 +349,15 @@ def view_build(myself, tree, host, compiler, rev, plain_logs=False):
uname = ""
cflags = ""
config = ""
- age_mtime = db.build_age_mtime(tree, host, compiler, rev)
- revision = db.build_revision(tree, host, compiler, rev)
+ build = db.get_build(tree, host, compiler, rev)
+ age_mtime = build.age_mtime()
+ (revision, revision_time) = build.revision_details()
status = build_status(myself, tree, host, compiler, rev)
assert re.match("^[0-9a-fA-F]*$", rev)
- log = db.read_log(tree, host, compiler, rev)
- err = db.read_err(tree, host, compiler, rev)
+ log = build.read_log()
+ err = build.read_err()
if log:
log = cgi.escape(log)
@@ -455,13 +458,14 @@ def view_host(myself, output_type, *requested_hosts):
for compiler in compilers:
for tree in sorted(trees.keys()):
- revision = db.build_revision(tree, host, compiler)
try:
- age_mtime = db.build_age_mtime(tree, host, compiler)
+ build = db.get_build(tree, host, compiler)
except data.NoSuchBuildError:
pass
else:
- age_ctime = db.build_age_ctime(tree, host, compiler)
+ revision, revision_time = build.revision_details()
+ age_mtime = build.age_mtime()
+ age_ctime = build.age_ctime()
warnings = db.err_count(tree, host, compiler)
status = build_status(myself, tree, host, compiler)
if row == 0:
--
build.samba.org
More information about the samba-cvs
mailing list