[gnome-ostree] build: Improve web frontend with diff, list view
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-ostree] build: Improve web frontend with diff, list view
- Date: Mon, 22 Oct 2012 00:12:22 +0000 (UTC)
commit eb7eb54866ab333ad7178d0657d7235de47f1a78
Author: Colin Walters <walters verbum org>
Date: Sun Oct 21 20:09:37 2012 -0400
build: Improve web frontend with diff, list view
Makefile-ostbuild.am | 1 +
qa/repoweb/index.html | 7 +-
qa/repoweb/repoweb.js | 129 +++++++++++++++++-------
src/ostbuild/pyostbuild/builtin_autobuilder.py | 28 ++++-
src/ostbuild/pyostbuild/builtin_build.py | 10 ++
src/ostbuild/pyostbuild/jsondb.py | 16 +++
src/ostbuild/pyostbuild/snapshot.py | 50 +++++++++
7 files changed, 196 insertions(+), 45 deletions(-)
---
diff --git a/Makefile-ostbuild.am b/Makefile-ostbuild.am
index 2b3b6aa..d93a760 100644
--- a/Makefile-ostbuild.am
+++ b/Makefile-ostbuild.am
@@ -63,6 +63,7 @@ pyostbuild_PYTHON = \
src/ostbuild/pyostbuild/ostbuildrc.py \
src/ostbuild/pyostbuild/privileged_subproc.py \
src/ostbuild/pyostbuild/warningfilter.py \
+ src/ostbuild/pyostbuild/snapshot.py \
src/ostbuild/pyostbuild/subprocess_helpers.py \
src/ostbuild/pyostbuild/vcs.py \
$(NULL)
diff --git a/qa/repoweb/index.html b/qa/repoweb/index.html
index 424d272..cb2e3fa 100644
--- a/qa/repoweb/index.html
+++ b/qa/repoweb/index.html
@@ -24,11 +24,10 @@
the <a href="http://git.gnome.org/browse/gnome-ostree">gnome-ostree</a>
git module.</p>
- <h3>Resolve</h3>
- <div id="resolve-summary">Loading...</div>
+ <h3>Builds</h3>
+ <ul id="build-summary" data-role="listview" data-theme="d" data-divider-theme="d">
+ </ul>
- <h3>Build</h3>
- <div id="build-summary">Loading...</div>
</div>
<div class="content-secondary">
<ul data-role="listview" data-theme="c" data-dividertheme="d">
diff --git a/qa/repoweb/repoweb.js b/qa/repoweb/repoweb.js
index 1ef195d..5476a8c 100644
--- a/qa/repoweb/repoweb.js
+++ b/qa/repoweb/repoweb.js
@@ -61,57 +61,114 @@ function timeago(d, now) {
}
}
+function buildDiffComponentAppend(container, description, a) {
+ var additional = 0;
+ if (a.length > 10) {
+ a = a.slice(0, 10);
+ additional = a.length - 10;
+ }
+ var p = document.createElement('p');
+ container.appendChild(p);
+ p.appendChild(document.createTextNode(description + ": " + a.join(", ")));
+ if (additional > 0) {
+ var b = document.createElement('b');
+ p.appendChild(b);
+ b.appendChild.document.createTextNode(" and " + additional + " more");
+ }
+}
+
+function buildDiffAppend(container, buildDiff) {
+ if (!buildDiff)
+ return document.createTextNode("No changes or new build");
+ var added = buildDiff[0];
+ var modified = buildDiff[1];
+ var removed = buildDiff[2];
+
+ if (added.length > 0)
+ buildDiffComponentAppend(container, 'Added', added);
+ if (modified.length > 0)
+ buildDiffComponentAppend(container, 'Updated', modified);
+ if (removed.length > 0)
+ buildDiffComponentAppend(container, 'removed', removed);
+}
+
function renderBuild(container, build) {
var now = new Date();
- var div = document.createElement('div');
- container.appendChild(div);
var version = build['meta']['version'];
- var endTimestamp = null;
- if (build['timestamp'])
- endTimestamp = new Date(build['timestamp'] * 1000);
+
+ var divider = document.createElement('li');
+ container.appendChild(divider);
+ divider.setAttribute('data-role', 'list-divider');
+ divider.appendChild(document.createTextNode(version));
+
+ var li = document.createElement('li');
+ container.appendChild(li);
var a = document.createElement('a');
- div.appendChild(a);
+ li.appendChild(a);
a.setAttribute('href', 'work/tasks/' + prefix + '-build/' + build['v'] + '/log');
a.setAttribute('rel', 'external');
- a.appendChild(document.createTextNode("Build " + version));
- div.appendChild(document.createTextNode(": "));
- var stateSpan = document.createElement('span');
- div.appendChild(stateSpan);
- var state = document.createTextNode(build['state']);
- stateSpan.appendChild(state);
- if (build['state'] == 'success')
- $(stateSpan).addClass("repoweb-build-success");
- else
- $(stateSpan).addClass("repoweb-build-failed");
- var status = build['build-status'];
- if (status)
- div.appendChild(document.createTextNode(" " + status['description']));
- else if (endTimestamp)
- div.appendChild(document.createTextNode(" " + timeago(endTimestamp, now)));
+
+ var state = build['state'];
+
+ if (state == 'running') {
+ var p = document.createElement('p');
+ a.appendChild(p);
+ var text = "Build " + version + " running";
+ var status = build['build-status'];
+ if (status)
+ text += ": " + status['description'];
+ p.appendChild(document.createTextNode(text));
+ p = document.createElement('p');
+ p.appendChild(document.createTextNode(text));
+ } else {
+ var p = document.createElement('p');
+ a.appendChild(p);
+ p.appendChild(document.createTextNode("Build " + version + ": "));
+ var stateSpan = document.createElement('span');
+ p.appendChild(stateSpan);
+ stateSpan.appendChild(document.createTextNode(build['state']));
+ if (state == 'success')
+ $(stateSpan).addClass("repoweb-build-success");
+ else if (state == 'failed')
+ $(stateSpan).addClass("repoweb-build-failed");
+ }
+
+ buildDiffAppend(a, build['diff']);
+
+ if (build['timestamp']) {
+ var endTimestamp = new Date(build['timestamp'] * 1000);
+ var p = document.createElement('p');
+ a.appendChild(p);
+ $(p).addClass("ui-li-aside");
+ p.appendChild(document.createTextNode(timeago(endTimestamp, now)));
+ }
+}
+
+function updateResolve() {
+ $("#resolve-summary").empty();
+ var summary = $("#resolve-summary").get(0);
+
+ var div = document.createElement('div');
+ summary.appendChild(div);
+ div.appendChild(document.createTextNode("Current version: "));
+ var a = document.createElement('a');
+ div.appendChild(a);
+ a.setAttribute('href', 'work/snapshots/' + repoData['version-path']);
+ a.setAttribute('rel', 'external');
+ a.appendChild(document.createTextNode(repoData['version']));
}
function repoweb_index_init() {
repoweb_init();
$(repoDataSignal).on("loaded", function () {
- $("#resolve-summary").empty();
- var summary = $("#resolve-summary").get(0);
-
- var div = document.createElement('div');
- summary.appendChild(div);
- div.appendChild(document.createTextNode("Current version: "));
- var a = document.createElement('a');
- div.appendChild(a);
- a.setAttribute('href', 'work/snapshots/' + repoData['version-path']);
- a.setAttribute('rel', 'external');
- a.appendChild(document.createTextNode(repoData['version']));
-
- $("#build-summary").empty();
- summary = $("#build-summary").get(0);
+
+ var buildSummary = $("#build-summary").get(0);
var buildData = repoData.build;
for (var i = buildData.length - 1; i >= 0; i--) {
var build = buildData[i];
- renderBuild(summary, build);
+ renderBuild(buildSummary, build);
}
+ $(buildSummary).listview('refresh');
});
}
diff --git a/src/ostbuild/pyostbuild/builtin_autobuilder.py b/src/ostbuild/pyostbuild/builtin_autobuilder.py
index 0d71675..d84a1a4 100755
--- a/src/ostbuild/pyostbuild/builtin_autobuilder.py
+++ b/src/ostbuild/pyostbuild/builtin_autobuilder.py
@@ -35,6 +35,7 @@ from . import kvfile
from . import filemonitor
from . import jsondb
from . import odict
+from . import snapshot
from . import vcs
from . import task
@@ -51,10 +52,27 @@ class OstbuildAutobuilder(builtins.Builtin):
self.source_snapshot_path = None
self.build_needed = True
self.last_build_succeeded = True
+ self._build_diff_cache = {}
def _status_is_success(self, estatus):
return os.WIFEXITED(estatus) and os.WEXITSTATUS(estatus) == 0
+ def _get_build_diff_for_task(self, task):
+ if hasattr(task, 'build_diff'):
+ return task.build_diff
+ db = self.get_src_snapshot_db()
+ meta_path = os.path.join(task.path, 'meta.json')
+ f = open(meta_path)
+ meta = json.load(f)
+ f.close()
+ snapshot_path = meta['version-path']
+ prev_snapshot_path = db.get_previous_path(snapshot_path)
+ if prev_snapshot_path is None:
+ task.build_diff = None
+ else:
+ task.build_diff = snapshot.snapshot_diff(db.load_from_path(snapshot_path),
+ db.load_from_path(prev_snapshot_path))
+
def _on_resolve_exited(self, pid, status):
self.resolve_proc = None
success = self._status_is_success(status)
@@ -131,7 +149,8 @@ class OstbuildAutobuilder(builtins.Builtin):
self.loop.watch_pid(self.build_proc.pid, self._on_build_exited)
self._write_status()
- def _taskhistory_to_json(self, history):
+ def _buildhistory_to_json(self):
+ history = self._build_taskset.get_history()
MAXITEMS = 5
entries = []
for item in history[-MAXITEMS:]:
@@ -144,6 +163,7 @@ class OstbuildAutobuilder(builtins.Builtin):
f = open(meta_path)
data['meta'] = json.load(f)
f.close()
+ data['diff'] = self._get_build_diff_for_task(item)
return entries
def _write_status(self):
@@ -156,12 +176,10 @@ class OstbuildAutobuilder(builtins.Builtin):
else:
status['version'] = ''
- status['resolve'] = self._taskhistory_to_json(self._resolve_taskset.get_history())
- build_history = self._build_taskset.get_history()
- status['build'] = self._taskhistory_to_json(build_history)
+ status['build'] = self._buildhistory_to_json()
if self.build_proc is not None:
- active_build = build_history[-1]
+ active_build = self._build_taskset.get_history()[-1]
active_build_json = status['build'][-1]
status_path = os.path.join(active_build.path, 'status.json')
if os.path.isfile(status_path):
diff --git a/src/ostbuild/pyostbuild/builtin_build.py b/src/ostbuild/pyostbuild/builtin_build.py
index b2c8077..234841f 100755
--- a/src/ostbuild/pyostbuild/builtin_build.py
+++ b/src/ostbuild/pyostbuild/builtin_build.py
@@ -32,6 +32,7 @@ from . import buildutil
from . import task
from . import fileutil
from . import kvfile
+from . import snapshot
from . import odict
from . import vcs
@@ -509,6 +510,15 @@ and the manifest input."""
log("Using source snapshot: %s" % (os.path.basename(self.snapshot_path), ))
+ db = self.get_src_snapshot_db()
+ prev_snapshot = db.get_previous_path(self.snapshot_path)
+ if prev_snapshot is not None:
+ (removed, modified, added) = snapshot.snapshot_diff(db.load_from_path(self.snapshot_path),
+ db.load_from_path(prev_snapshot))
+ log("Removed components: %r" % (removed, ))
+ log("Modified components: %r" % (modified, ))
+ log("Added components: %r" % (added, ))
+
self._write_status('Starting')
self.buildopts = BuildOptions()
diff --git a/src/ostbuild/pyostbuild/jsondb.py b/src/ostbuild/pyostbuild/jsondb.py
index 5a1500d..3ff2930 100644
--- a/src/ostbuild/pyostbuild/jsondb.py
+++ b/src/ostbuild/pyostbuild/jsondb.py
@@ -64,12 +64,28 @@ class JsonDB(object):
return None
return json.load(open(path))
+ def load_from_path(self, path):
+ return json.load(open(os.path.join(self._dirpath, os.path.basename(path))))
+
def get_latest_path(self):
files = self._get_all()
if len(files) == 0:
return None
return os.path.join(self._dirpath, files[0][3])
+ def get_previous_path(self, path):
+ name = os.path.basename(path)
+ match = self._version_csum_re.search(name)
+ assert match is not None
+ (target_major, target_minor) = (int(match.group(1)), int(match.group(2)))
+ files = self._get_all()
+ prev = None
+ for (major, minor, csum, fname) in reversed(files):
+ if target_major == major and target_minor == minor:
+ break
+ prev = fname
+ return prev
+
def parse_version(self, name):
match = self._version_csum_re.search(name)
assert match is not None
diff --git a/src/ostbuild/pyostbuild/snapshot.py b/src/ostbuild/pyostbuild/snapshot.py
new file mode 100644
index 0000000..b706ebf
--- /dev/null
+++ b/src/ostbuild/pyostbuild/snapshot.py
@@ -0,0 +1,50 @@
+#
+# Copyright (C) 2012 Colin Walters <walters verbum org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+import os,sys
+
+def _component_dict(snapshot):
+ r = {}
+ for component in snapshot['components']:
+ r[component['name']] = component
+ patches = snapshot['patches']
+ r[patches['name']] = patches
+ base = snapshot['base']
+ r[base['name']] = base
+ return r
+
+def snapshot_diff(a, b):
+ a_components = _component_dict(a)
+ b_components = _component_dict(b)
+
+ added = []
+ modified = []
+ removed = []
+
+ for name in a_components:
+ c_a = a_components[name]
+ c_b = b_components.get(name)
+ if c_b is None:
+ removed.append(name)
+ elif c_a['revision'] != c_b['revision']:
+ modified.append(name)
+ for name in b_components:
+ if name not in a_components:
+ added.append(name)
+ return (added, modified, removed)
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]