# HG changeset patch # User cmlenz # Date 1124646560 0 # Node ID 395b67aa072e4f502c9cb46a1ea6ca326b712a94 # Parent affd91b4c6fb7764862c26acc6a153e521812695 Build recipes are now stored in the database with the build configuration. This means that it is no longer necessary to store the recipe in the repository. Closes #41. At some point, there'll need to be a real user interface for creating/updating the recipe. diff --git a/bitten/master.py b/bitten/master.py --- a/bitten/master.py +++ b/bitten/master.py @@ -285,11 +285,11 @@ return self.send_snapshot(build, type, encoding) - xml = xmlio.Element('build', recipe='recipe.xml') - self.channel.send_msg(beep.Payload(xml), handle_reply=handle_reply) + config = BuildConfig.fetch(self.env, build.config) + self.channel.send_msg(beep.Payload(config.recipe), + handle_reply=handle_reply) def send_snapshot(self, build, type, encoding): - timestamp_delta = 0 if self.master.adjust_timestamps: d = datetime.now() - timedelta(seconds=self.master.check_interval) \ diff --git a/bitten/model.py b/bitten/model.py --- a/bitten/model.py +++ b/bitten/model.py @@ -26,19 +26,23 @@ _schema = [ Table('bitten_config', key='name')[ - Column('name'), Column('path'), Column('label'), - Column('active', type='int'), Column('description') + Column('name'), Column('path'), Column('active', type='int'), + Column('recipe'), Column('min_rev'), Column('max_rev'), + Column('label'), Column('description') ] ] - def __init__(self, env, name=None, path=None, label=None, active=False, - description=None): + def __init__(self, env, name=None, path=None, active=False, recipe=None, + min_rev=None, max_rev=None, label=None, description=None): self.env = env self._old_name = None self.name = name self.path = path or '' + self.active = bool(active) + self.recipe = recipe or '' + self.min_rev = min_rev or None + self.max_rev = max_rev or None self.label = label or '' - self.active = bool(active) self.description = description or '' exists = property(fget=lambda self: self._old_name is not None) @@ -53,14 +57,16 @@ handle_ta = False cursor = db.cursor() - cursor.execute("INSERT INTO bitten_config " - "(name,path,label,active,description) " - "VALUES (%s,%s,%s,%s,%s)", - (self.name, self.path, self.label or '', - int(self.active or 0), self.description or '')) + cursor.execute("INSERT INTO bitten_config (name,path,active," + "recipe,min_rev,max_rev,label,description) " + "VALUES (%s,%s,%s,%s,%s,%s,%s,%s)", + (self.name, self.path, int(self.active or 0), + self.recipe or '', self.min_rev, self.max_rev, + self.label or '', self.description or '')) if handle_ta: db.commit() + self._old_name = self.name def update(self, db=None): assert self.exists, 'Cannot update a non-existing configuration' @@ -72,21 +78,24 @@ handle_ta = False cursor = db.cursor() - cursor.execute("UPDATE bitten_config SET name=%s,path=%s,label=%s," - "active=%s,description=%s WHERE name=%s", - (self.name, self.path, self.label, int(self.active or 0), - self.description, self._old_name)) + cursor.execute("UPDATE bitten_config SET name=%s,path=%s,active=%s," + "recipe=%s,min_rev=%s,max_rev=%s,label=%s," + "description=%s WHERE name=%s", + (self.name, self.path, int(self.active or 0), + self.recipe, self.min_rev, self.max_rev, + self.label, self.description, self._old_name)) if handle_ta: db.commit() + self._old_name = self.name def fetch(cls, env, name, db=None): if not db: db = env.get_db_cnx() cursor = db.cursor() - cursor.execute("SELECT path,label,active,description " - "FROM bitten_config WHERE name=%s", (name,)) + cursor.execute("SELECT path,active,recipe,min_rev,max_rev,label," + "description FROM bitten_config WHERE name=%s", (name,)) row = cursor.fetchone() if not row: return None @@ -94,9 +103,12 @@ config = BuildConfig(env) config.name = config._old_name = name config.path = row[0] or '' - config.label = row[1] or '' - config.active = row[2] and True or False - config.description = row[3] or '' + config.active = row[1] and True or False + config.recipe = row[2] or '' + config.min_rev = row[3] or '' + config.max_rev = row[4] or '' + config.label = row[5] or '' + config.description = row[6] or '' return config fetch = classmethod(fetch) @@ -104,18 +116,21 @@ def select(cls, env, include_inactive=False, db=None): if not db: db = env.get_db_cnx() - where = '' + cursor = db.cursor() if include_inactive: - cursor.execute("SELECT name,path,label,active,description " - "FROM bitten_config ORDER BY name") + cursor.execute("SELECT name,path,active,recipe,min_rev,max_rev," + "label,description FROM bitten_config ORDER BY name") else: - cursor.execute("SELECT name,path,label,active,description " - "FROM bitten_config WHERE active=1 " - "ORDER BY name") - for name, path, label, active, description in cursor: + cursor.execute("SELECT name,path,active,recipe,min_rev,max_rev," + "label,description FROM bitten_config " + "WHERE active=1 ORDER BY name") + for name, path, active, recipe, min_rev, max_rev, label, description \ + in cursor: config = BuildConfig(env, name=name, path=path or '', - label=label or '', active=bool(active), + active=bool(active), recipe=recipe or '', + min_rev=min_rev or None, + max_rev=max_rev or None, label=label or '', description=description or '') config._old_name = name yield config @@ -643,4 +658,4 @@ schema = BuildConfig._schema + TargetPlatform._schema + Build._schema + \ BuildStep._schema + BuildLog._schema -schema_version = 2 +schema_version = 3 diff --git a/bitten/recipe.py b/bitten/recipe.py --- a/bitten/recipe.py +++ b/bitten/recipe.py @@ -113,7 +113,7 @@ func_name = self._translate_name(elem.name) try: module = __import__(elem.namespace[7:], globals(), locals(), - func_name) + [func_name]) func = getattr(module, func_name) return func except (ImportError, AttributeError), e: @@ -137,13 +137,17 @@ LOG = 'log' REPORT = 'report' - def __init__(self, filename='recipe.xml', basedir=os.getcwd()): + def __init__(self, filename='recipe.xml', basedir=os.getcwd(), + xml_elem=None): self.ctxt = Context(basedir) - fd = file(self.ctxt.resolve(filename), 'r') - try: - self._root = xmlio.parse(fd) - finally: - fd.close() + if filename: + fd = file(self.ctxt.resolve(filename), 'r') + try: + self._root = xmlio.parse(fd) + finally: + fd.close() + elif xml_elem: + self._root = xml_elem self.description = self._root.attr.get('description') def __iter__(self): diff --git a/bitten/slave.py b/bitten/slave.py --- a/bitten/slave.py +++ b/bitten/slave.py @@ -58,7 +58,6 @@ def handle_connect(self): """Register with the build master.""" - self.recipe_path = None def handle_reply(cmd, msgno, ansno, payload): if cmd == 'ERR': @@ -105,12 +104,12 @@ self.channel.send_msg(beep.Payload(xml), handle_reply) def handle_msg(self, msgno, payload): + recipe_xml = None if payload.content_type == beep.BEEP_XML: elem = xmlio.parse(payload.body) if elem.name == 'build': + recipe_xml = elem # Received a build request - self.recipe_path = elem.attr['recipe'] - xml = xmlio.Element('proceed')[ xmlio.Element('accept', type='application/tar', encoding='bzip2'), @@ -157,15 +156,12 @@ for filename in files: os.chmod(os.path.join(root, filename), 0400) - self.execute_build(msgno, path, self.recipe_path) + self.execute_build(msgno, Recipe(basedir=path, xml_elem=recipe_xml)) - def execute_build(self, msgno, basedir, recipe_path): + def execute_build(self, msgno, recipe): global log - log.info('Building in directory %s using recipe %s', basedir, - recipe_path) + log.info('Building in directory %s', recipe.ctxt.basedir) try: - recipe = Recipe(recipe_path, basedir) - xml = xmlio.Element('started', time=datetime.utcnow().isoformat()) self.channel.send_ans(msgno, beep.Payload(xml)) diff --git a/bitten/trac_ext/htdocs/bitten.css b/bitten/trac_ext/htdocs/bitten.css --- a/bitten/trac_ext/htdocs/bitten.css +++ b/bitten/trac_ext/htdocs/bitten.css @@ -4,7 +4,10 @@ background-image: url(bitten_build.png) !important } -#content.build form.config td.active { vertical-align: bottom; } +#content.build #prefs { line-height: 1.4em; } + +#content.build form.config th { text-align: left; } +#content.build form.config fieldset { margin-bottom: 1em; } #content.build form.platforms ul { list-style: none; padding-left: 1em; } #content.build #builds { margin-top: 2em; } diff --git a/bitten/trac_ext/templates/bitten_config.cs b/bitten/trac_ext/templates/bitten_config.cs --- a/bitten/trac_ext/templates/bitten_config.cs +++ b/bitten/trac_ext/templates/bitten_config.cs @@ -19,7 +19,7 @@ elif:page.mode == 'edit_config' ?>