This email list is read-only.  Emails sent to this list will be discarded
----------------------------------
 bitbake-dev/lib/bb/ui/crumbs/__init__.py     |   18 +
 bitbake-dev/lib/bb/ui/crumbs/buildmanager.py |  459 +++++++++++++++++++
 bitbake-dev/lib/bb/ui/crumbs/puccho.glade    |  606 ++++++++++++++++++++++++++
 bitbake-dev/lib/bb/ui/crumbs/runningbuild.py |  181 ++++++++
 bitbake-dev/lib/bb/ui/goggle.py              |  146 +------
 bitbake-dev/lib/bb/ui/puccho.py              |  426 ++++++++++++++++++
 meta/conf/bitbake.conf                       |    4 +-
 7 files changed, 1693 insertions(+), 147 deletions(-)

New commits:
commit d6740d45e56fce0feef261b4e5633816a76540ea
Author: Rob Bradford <[EMAIL PROTECTED]>
Date:   Fri Nov 14 14:14:08 2008 +0000

    bitbake-dev: Add basics of "puccho" image builder UI

commit b7b2fb2d708c30aed9441aaa0e3d2b67c5a425a7
Author: Rob Bradford <[EMAIL PROTECTED]>
Date:   Fri Nov 14 11:38:10 2008 +0000

    bitbake-dev: Refactor goggle to pull out useful components.
    
    Separate the GTK components and abstractions to a separate module where they
    can be used by other user interfaces. This module includes the model, the 
view
    and abstraction that populates the model.

commit 7e0aac98b0d9539f0589816f415f661194a012fd
Author: Rob Bradford <[EMAIL PROTECTED]>
Date:   Fri Nov 14 10:45:49 2008 +0000

    bitbake.conf: Allow TMPDIR and DEPLOY_DIR_IMAGE to be overridden


Diff in this email is a maximum of 400 lines.
diff --git a/bitbake-dev/lib/bb/ui/crumbs/__init__.py 
b/bitbake-dev/lib/bb/ui/crumbs/__init__.py
new file mode 100644
index 0000000..c6a377a
--- /dev/null
+++ b/bitbake-dev/lib/bb/ui/crumbs/__init__.py
@@ -0,0 +1,18 @@
+#
+# BitBake UI Implementation
+#
+# Copyright (C) 2006-2007 Richard Purdie
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
diff --git a/bitbake-dev/lib/bb/ui/crumbs/buildmanager.py 
b/bitbake-dev/lib/bb/ui/crumbs/buildmanager.py
new file mode 100644
index 0000000..572cc4c
--- /dev/null
+++ b/bitbake-dev/lib/bb/ui/crumbs/buildmanager.py
@@ -0,0 +1,459 @@
+#
+# BitBake Graphical GTK User Interface
+#
+# Copyright (C) 2008        Intel Corporation
+#
+# Authored by Rob Bradford <[EMAIL PROTECTED]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import gtk
+import gobject
+import gtk.glade
+import threading
+import urllib2
+import os
+import datetime
+import time
+
+class BuildConfiguration:
+    """ Represents a potential *or* historic *or* concrete build. It
+    encompasses all the things that we need to tell bitbake to do to make it
+    build what we want it to build. 
+
+    It also stored the metadata URL and the set of possible machines (and the
+    distros / images / uris for these. Apart from the metdata URL these are
+    not serialised to file (since they may be transient). In some ways this
+    functionality might be shifted to the loader class."""
+
+    def __init__ (self):
+        self.metadata_url = None
+
+        # Tuple of (distros, image, urls)
+        self.machine_options = {}
+
+        self.machine = None
+        self.distro = None
+        self.image = None
+        self.urls = []
+        self.extra_urls = []
+        self.extra_pkgs = []
+
+    def get_machines_model (self):
+        model = gtk.ListStore (gobject.TYPE_STRING)
+        for machine in self.machine_options.keys():
+            model.append ([machine])
+
+        return model
+
+    def get_distro_and_images_models (self, machine):
+        distro_model = gtk.ListStore (gobject.TYPE_STRING)
+
+        for distro in self.machine_options[machine][0]:
+            distro_model.append ([distro])
+
+        image_model = gtk.ListStore (gobject.TYPE_STRING)
+
+        for image in self.machine_options[machine][1]:
+            image_model.append ([image])
+
+        return (distro_model, image_model)
+
+    def get_repos (self):
+        self.urls = self.machine_options[self.machine][2]
+        return self.urls
+
+    # It might be a lot lot better if we stored these in like, bitbake conf
+    # file format. 
+    @staticmethod 
+    def load_from_file (filename):
+        f = open (filename, "r")
+
+        conf = BuildConfiguration()
+        for line in f.readlines():
+            data = line.split (";")[1]
+            if (line.startswith ("metadata-url;")):
+                conf.metadata_url = data.strip()
+                continue
+            if (line.startswith ("url;")):
+                conf.urls += [data.strip()]
+                continue
+            if (line.startswith ("extra-url;")):
+                conf.extra_urls += [data.strip()]
+                continue
+            if (line.startswith ("machine;")):
+                conf.machine = data.strip()
+                continue
+            if (line.startswith ("distribution;")):
+                conf.distro = data.strip()
+                continue
+            if (line.startswith ("image;")):
+                conf.image = data.strip()
+                continue
+
+        f.close ()
+        return conf
+
+    # Serialise to a file. This is part of the build process and we use this
+    # to be able to repeat a given build (using the same set of parameters)
+    # but also so that we can include the details of the image / machine /
+    # distro in the build manager tree view.
+    def write_to_file (self, filename):
+        f = open (filename, "w")
+
+        lines = []
+
+        if (self.metadata_url):
+            lines += ["metadata-url;%s\n" % (self.metadata_url)]
+
+        for url in self.urls:
+            lines += ["url;%s\n" % (url)]
+
+        for url in self.extra_urls:
+            lines += ["extra-url;%s\n" % (url)]
+
+        if (self.machine):
+            lines += ["machine;%s\n" % (self.machine)]
+
+        if (self.distro):
+            lines += ["distribution;%s\n" % (self.distro)]
+
+        if (self.image):
+            lines += ["image;%s\n" % (self.image)]
+
+        f.writelines (lines)
+        f.close ()
+
+class BuildResult(gobject.GObject):
+    """ Represents an historic build. Perhaps not successful. But it includes
+    things such as the files that are in the directory (the output from the
+    build) as well as a deserialised BuildConfiguration file that is stored in
+    ".conf" in the directory for the build.
+
+    This is GObject so that it can be included in the TreeStore."""
+    
+    (STATE_COMPLETE, STATE_FAILED, STATE_ONGOING) = \
+        (0, 1, 2)
+
+    def __init__ (self, parent, identifier):
+        gobject.GObject.__init__ (self)
+        self.date = None 
+
+        self.files = []
+        self.status = None
+        self.identifier = identifier
+        self.path = os.path.join (parent, identifier)
+
+        # Extract the date, since the directory name is of the
+        # format build-<year><month><day>-<ordinal> we can easily
+        # pull it out.
+        # TODO: Better to stat a file?
+        (_ , date, revision) = identifier.split ("-")
+        print date
+
+        year = int (date[0:4])
+        month = int (date[4:6])
+        day = int (date[6:8])
+
+        self.date = datetime.date (year, month, day)
+
+        self.conf = None
+
+        # By default builds are STATE_FAILED unless we find a "complete" file
+        # in which case they are STATE_COMPLETE
+        self.state = BuildResult.STATE_FAILED
+        for file in os.listdir (self.path):
+            if (file.startswith (".conf")):
+                conffile = os.path.join (self.path, file)
+                self.conf = BuildConfiguration.load_from_file (conffile)
+            elif (file.startswith ("complete")):
+                self.state = BuildResult.STATE_COMPLETE
+            else:
+                self.add_file (file)
+
+    def add_file (self, file):
+        # Just add the file for now. Don't care about the type. 
+        self.files += [(file, None)]
+
+class BuildManagerModel (gtk.TreeStore):
+    """ Model for the BuildManagerTreeView. This derives from gtk.TreeStore
+    but it abstracts nicely what the columns mean and the setup of the columns
+    in the model. """
+
+    (COL_IDENT, COL_DESC, COL_MACHINE, COL_DISTRO, COL_BUILD_RESULT, COL_DATE, 
COL_STATE) = \
+        (0, 1, 2, 3, 4, 5, 6)
+
+    def __init__ (self):
+        gtk.TreeStore.__init__ (self,
+            gobject.TYPE_STRING, 
+            gobject.TYPE_STRING,
+            gobject.TYPE_STRING,
+            gobject.TYPE_STRING,
+            gobject.TYPE_OBJECT,
+            gobject.TYPE_INT64,
+            gobject.TYPE_INT)
+
+class BuildManager (gobject.GObject):
+    """ This class manages the historic builds that have been found in the
+    "results" directory but is also used for starting a new build."""
+
+    __gsignals__ = {
+        'population-finished' : (gobject.SIGNAL_RUN_LAST, 
+                                 gobject.TYPE_NONE,
+                                 ()),
+        'populate-error' : (gobject.SIGNAL_RUN_LAST,
+                            gobject.TYPE_NONE,
+                            ())
+    }
+
+    def update_build_result (self, result, iter):
+        # Convert the date into something we can sort by.
+        date = long (time.mktime (result.date.timetuple()))
+
+        # Add a top level entry for the build
+        
+        self.model.set (iter, 
+            BuildManagerModel.COL_IDENT, result.identifier,
+            BuildManagerModel.COL_DESC, result.conf.image,
+            BuildManagerModel.COL_MACHINE, result.conf.machine, 
+            BuildManagerModel.COL_DISTRO, result.conf.distro, 
+            BuildManagerModel.COL_BUILD_RESULT, result, 
+            BuildManagerModel.COL_DATE, date,
+            BuildManagerModel.COL_STATE, result.state)
+
+        # And then we use the files in the directory as the children for the
+        # top level iter.
+        for file in result.files:
+            self.model.append (iter, (None, file[0], None, None, None, date, 
-1))
+
+    # This function is called as an idle by the BuildManagerPopulaterThread
+    def add_build_result (self, result):
+        gtk.gdk.threads_enter()
+        self.known_builds += [result]
+
+        self.update_build_result (result, self.model.append (None))
+
+        gtk.gdk.threads_leave()
+
+    def notify_build_finished (self):
+        # This is a bit of a hack. If we have a running build running then we
+        # will have a row in the model in STATE_ONGOING. Find it and make it
+        # as if it was a proper historic build (well, it is completed now....)
+
+        # We need to use the iters here rather than the Python iterator
+        # interface to the model since we need to pass it into
+        # update_build_result
+
+        iter = self.model.get_iter_first()
+
+        while (iter):
+            (ident, state) = self.model.get(iter,
+                BuildManagerModel.COL_IDENT, 
+                BuildManagerModel.COL_STATE)
+
+            if state == BuildResult.STATE_ONGOING:
+                result = BuildResult (self.results_directory, ident)
+                self.update_build_result (result, iter)
+            iter = self.model.iter_next(iter)
+
+    def notify_build_succeeded (self):
+        # Write the "complete" file so that when we create the BuildResult
+        # object we put into the model
+
+        complete_file_path = os.path.join (self.cur_build_directory, 
"complete")
+        f = file (complete_file_path, "w")
+        f.close()
+        self.notify_build_finished()
+
+    def notify_build_failed (self):
+        # Without a "complete" file then this will mark the build as failed:
+        self.notify_build_finished()
+
+    # This function is called as an idle
+    def emit_population_finished_signal (self):
+        gtk.gdk.threads_enter()
+        self.emit ("population-finished")
+        gtk.gdk.threads_leave()
+
+    class BuildManagerPopulaterThread (threading.Thread):
+        def __init__ (self, manager, directory):
+            threading.Thread.__init__ (self)
+            self.manager = manager
+            self.directory = directory
+
+        def run (self):
+            # For each of the "build-<...>" directories ..
+
+            if os.path.exists (self.directory):
+                for directory in os.listdir (self.directory):
+
+                    if not directory.startswith ("build-"):
+                        continue
+
+                    build_result = BuildResult (self.directory, directory)
+                    self.manager.add_build_result (build_result)
+
+            gobject.idle_add (BuildManager.emit_population_finished_signal,
+                self.manager)
+
+    def __init__ (self, server, results_directory):
+        gobject.GObject.__init__ (self)
+
+        # The builds that we've found from walking the result directory
+        self.known_builds = []
+
+        # Save out the bitbake server, we need this for issuing commands to
+        # the cooker:
+        self.server = server
+
+        # The TreeStore that we use
+        self.model = BuildManagerModel ()
+
+        # The results directory is where we create (and look for) the
+        # build-<xyz>-<n> directories. We need to populate ourselves from
+        # directory
+        self.results_directory = results_directory
+        self.populate_from_directory (self.results_directory)
+
+    def populate_from_directory (self, directory):
+        thread = BuildManager.BuildManagerPopulaterThread (self, directory)
+        thread.start()
+
+    # Come up with the name for the next build ident by combining "build-"
+    # with the date formatted as yyyymmdd and then an ordinal. We do this by
+    # an optimistic algorithm incrementing the ordinal if we find that it
+    # already exists.
+    def get_next_build_ident (self):
+        today = datetime.date.today ()
+        datestr = str (today.year) + str (today.month) + str (today.day)
+
+        revision = 0
+        test_name = "build-%s-%d" % (datestr, revision)
+        test_path = os.path.join (self.results_directory, test_name)
+
+        while (os.path.exists (test_path)):
+            revision += 1
+            test_name = "build-%s-%d" % (datestr, revision)
+            test_path = os.path.join (self.results_directory, test_name)
+
+        return test_name
+
+    # Take a BuildConfiguration and then try and build it based on the
+    # parameters of that configuration. S
+    def do_build (self, conf):
+        server = self.server
+
+        # Work out the build directory. Note we actually create the
+        # directories here since we need to write the ".conf" file. Otherwise
+        # we could have relied on bitbake's builder thread to actually make
+        # the directories as it proceeds with the build.
+        ident = self.get_next_build_ident ()
+        build_directory = os.path.join (self.results_directory,
+            ident)
+        self.cur_build_directory = build_directory
+        os.makedirs (build_directory)
+
+        conffile = os.path.join (build_directory, ".conf")
+        conf.write_to_file (conffile)
+
+        # Add a row to the model representing this ongoing build. It's kinda a
_______________________________________________
Commits mailing list
[email protected]
https://lists.moblin.org/mailman/listinfo/commits

Reply via email to