Commits

Moises Henriquez committed e66aea1

Main application workflow acheived.

Comments (0)

Files changed (5)

src/vpackager/bot.py

         if descuri is None:
             return
         if descuri.startswith('/'):
+            self.print_to_log(
+                "\n +++ Copying package description from %s\n"% descuri)
             return shutil.copy2(descuri, workdir)
         else:
+            self.print_to_log(
+                "\n +++ Downloading package description from %s\n"% descuri)
             _prevdir = os.getcwd()
             os.chdir(workdir)
             urllib.urlretrieve(descuri, 'slack-desc')
 
     def process_patches(self, patchlist, workdir):
         """ copy or download any patches into the source tree"""
-        if not patchlist:
-            return
-        if patchlist is None:
-            return
-        if patchlist is "None":
+        if patchlist in (None,"","None"):
             return
         _prevdir = os.getcwd()
         patchesdir = os.path.join(workdir, 'patches')
         return self.view.PlayOutput(data)
 
     def run(self):
+        """ Actual build sequence"""
         while self.view.RUN_BOT:
             time.sleep(1)
             job_id = self.model.GetNextJob()
-            job_info = self.model.GetJobDetails(job_id)
+            if job_id is None:
+                self.print_to_log(
+                    "\n   *** No more jobs in queue. Stopping bot ***")
+                return self.view.StopBot()
+            #clear the textview()
+            self.clear_textview()
+            job_info = self.model.GetJobDetails(str(job_id))
+            # Show the progress on the GUI
+            self.view.IndicateBotRunning(app = job_info['app'],
+                                         ver = job_info['ver'])
+            # Log the job start
+            self.model.LogJobStart(job_id)
+            # Create the appropriate build object
+            srcob = self.get_builder(job_info['srcURI'], job_info['id'])
 
-        # get the job id from the queue
-        _id = self.model.GetNextJob()
-        if _id is None:
-            self.print_to_log(
-                "\n   *** No more jobs in queue. Stopping bot ***")
-            return self.view.StopBot()
+            # Create the build script
+            sbpath = srcob.makeSlackBuild(
+                buildno = job_info['release'])
+            workdir = os.path.dirname(sbpath)
+            # cd to the right place to perform operations
+            os.chdir(os.path.dirname(sbpath))
+            # Process the source code
+            self.process_source(job_info['srcURI'], workdir)
+            # Process the package description
+            self.process_description(job_info['descURI'], workdir)
+            # Process any patches added to the build
+            self.process_patches(job_info['patches'], workdir)
+            # cd back to the original workdir (just in case)
+            os.chdir(os.path.dirname(sbpath))
+            # Create build job object
+            job = srcob.buildSlackBuild()
+            # Connect the observer so we can watch the matrix.
+            job.observer.add_callback(self.view.PlayOutput)
+            # start the job
+            job.run()
+            while job._popen_running:
+                time.sleep(1)
+            retval = job.popen.returncode
+            if retval > 0:
+                result = 'Fail'
+            else:
+                result = 'Success'
 
-        # Clear the textview for the previous build log
-        self.clear_textview()
-        # Get the vpackager job
-        details = self.model.GetJobDetails(_id)
-        # Show the bot status in the view GUI...
-        self.view.IndicateBotRunning(app = details['app'],
-                                     ver = details['ver'])
-        # begin the build job
-        self.model.LogJobStart(_id)
-        # Do something to update the bot status UI notifications
-        # FIXME: ^^
-
-        srcob = self.get_builder()
-        # create the build script
-        sbpath = srcob.makeSlackBuild(buildno = details['release'])
-        # cd to the right place to perform operations
-        os.chdir(os.path.dirname(sbpath))
-        # Process the source
-        self.process_source(details['srcURI'], sbpath)
-        # process the description
-        self.process_description(details['descuri'], sbpath)
-        # Process patches
-        self.process_patches(details['patches'], sbpath)
-        # change back to the original work path
-        os.chdir(os.path.dirname(sbpath))
-        job = srcob.buildSlackBuild()
-        # Add a callback to play the output to the GUI
-        job.observer.add_callback(self.view.PlayOutput)
-        job.run()
-        while job._popen_running:
-            time.sleep(1)
-        retval = job.popen.returncode
-        if retval > 0:
-            result = 'Fail'
-        else:
-            result = 'Success'
-
-        # Log the output to a file
-        logpath = os.path.join(os.path.dirname(srcob.srclocation),
-                               '%s.build_log'% details['app'])
-        # Log the job end to the database
-        self.log_output_to_file(logpath)
-        self.model.LogJobEnd(_id, logpath, result)
-        if result == 'Success' and details['install'] == "1":
-            # install the package
-            self.print_to_log("\n + Installing package per user request")
-            try:
+            # Install the package if it was requested
+            if result == 'Success' and job_info['install'] == 1:
+                self.print_to_log(
+                    "\n   + Installing package per user request +")
                 proc = srcob.install_pkg()
-                # again, pass the observer to se can see the output
+                # again, play the output on the GUI
                 proc.observer.add_callback(self.view.PlayOutput)
                 proc.run()
                 while proc._popen_running:
                     time.sleep(1)
-                retval = proc.popen.returncode
-            except:
-                pass
+                retval = proc._popen.returncode
+
+            # Log the output to a file
+            logpath = os.path.join(os.path.dirname(srcob.srclocation),
+                                   '%s.build_log'% job_info['app'])
+            self.log_output_to_file(logpath)
+
+            # Log the end of the job on the database:
+            self.model.LogJobEnd(job_id, logpath, result)
+        return
 
 class StatusTab(gtk.VBox):
     """ Content of the status tab packed in a vbox that can be
             self.dispatcher.start()
         except:
             del self.dispatcher
-            self.dispatcher = Dispatcher(model = self.mode, view = self)
+            self.dispatcher = Dispatcher(model = self.model, view = self)
             self.dispatcher.start()
         return
 
         self.scrl = gtk.ScrolledWindow()
         self.scrl.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
         self.textview = gtk.TextView()
+        self.textview.set_editable(False)
         for edge in (gtk.TEXT_WINDOW_LEFT, gtk.TEXT_WINDOW_RIGHT,
                      gtk.TEXT_WINDOW_TOP, gtk.TEXT_WINDOW_BOTTOM):
             self.textview.set_border_window_size(edge, 4)
         gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
         self.dbase_model = dbase_model
         self.body = gtk.VBox()
+        datadir = os.path.dirname(os.path.abspath(__file__))
+        datadir = os.path.join(datadir, 'data')
+        self.set_icon_from_file(os.path.join(datadir, 'vpackager.png'))
         self.set_title('vpackager')
         self.set_position(gtk.WIN_POS_CENTER)
-        self.body.pack_start(gtk.Label('Menu goes here'), False, True, 2)
+        self.body.pack_start(self._get_menubar(), False, True, 2)
         self.tabstrip = guitools.TabStrip()
         self.bot_tab = StatusTab(model = self.dbase_model)
         #self.bot_tab = StatusTab()
         self.add(self.body)
         self.show_all()
         self.connect('destroy', gtk.main_quit)
-        self.set_size_request(600,400)
+        self.set_size_request(700,400)
 
         # Force initial display of the queue and history
         self.dbase_model.RefreshQueue()
         self.dbase_model.RefreshHistory()
 
+    def _get_menubar(self):
+        mb = gtk.MenuBar()
+        filemenu = gtk.Menu()
+        filem = gtk.MenuItem("File")
+        filem.set_submenu(filemenu)
 
+        exit = gtk.MenuItem("Exit")
+        exit.connect("activate", self._exit)
+        filemenu.append(exit)
+
+        mb.append(filem)
+
+        editm = gtk.MenuItem("Edit")
+        editmenu = gtk.Menu()
+        editm.set_submenu(editmenu)
+        mb.append(editm)
+        editprefs = gtk.MenuItem("Preferences")
+        editmenu.append(editprefs)
+        editprefs.connect('activate', self.ShowPrefsWindow)
+
+        helpm = gtk.MenuItem("Help")
+        helpmenu = gtk.Menu()
+        helpm.set_submenu(helpmenu)
+
+        about = gtk.MenuItem("About")
+        about.connect("activate", self._show_about)
+        helpmenu.append(about)
+        mb.append(helpm)
+        return mb
+
+    def ShowPrefsWindow(self, widget=None):
+        dia = guitools.message.Error(
+            text = "No preferences available yet",
+            parent = self)
+        if dia.run():
+            return dia.destroy()
+
+    def _exit(self, widget=None):
+        self.bot_tab.RUN_BOT = False
+        time.sleep(0.25)
+        self.dbase_model.close()
+        return gtk.main_quit()
+
+    def _show_about(self, widget=None):
+        """Display the about window"""
+        dia = guitools.About()
+        if dia.run():
+            dia.destroy()
 
 
 

src/vpackager/dbutils.py

     def close(self):
         """ Completely close the database to save all data """
         try:
+            self.cursor.close()
             self.db.commit()
             self.db.close()
         except:
     def verify_tables(self):
         """Verify that the essential tables for the vpackages environemtn
         actually exist"""
-        self.cursor.execute('''select name from sqlite_master where
+        db, cursor = self._open()
+        cursor.execute('''select name from sqlite_master where
                 type="table" and name != "sqlite_sequence"''')
-        res = self.cursor.fetchall()
+        res = cursor.fetchall()
         if len(res) > 0:
             return False
         return True
         cursor.execute('''
         select id, app, ver, srcURI, descURI, release, type from queue where
         id=?''',t)
-        res = self.cursor.next()
+        res = cursor.next()
         cursor.execute('''
         insert into history (id, app, ver, srcURI, descURI, release, type,
         buildstart, result) values (?,?,?,?,?,?,?,CURRENT_TIMESTAMP,
         'Running')''', res)
         cursor.execute('delete from queue where id=?', t)
         db.commit()
+        # Notify the observers of the changes.
         self.notify(data = self.GetHistory(), group='history')
+        self.notify(data = self.GetQueue(), group='queue')
         return self.close()
 
     def LogJobEnd(self, job_id, stdoutpath, result):
         update history set stdout=? where id=?''',t)
         t = (result, job_id)
         cursor.execute('''
-        update history set result=? where id=''',t)
+        update history set result=? where id=?''',t)
 
         db.commit()
         self.notify(data = self.GetHistory(), group='history')
+        self.notify(data = self.GetQueue(), group='queue')
         return self.close()
 
     def GetJobProp(self, job_id, prop):
         form of a dictionary"""
         db,cursor = self._open()
         retval = {}
-        t = (job_id,)
+        t = (str(job_id),)
         cursor.execute('select * from queue where id=?',t)
         try:
             ret = cursor.next()
         Returns the jobid for the next job"""
         db, cursor = self._open()
         cursor.execute('select id from queue')
+        retval = None
         try:
             ret = cursor.next()
+            retval = ret[0]
         except StopIteration:
             ret = None
         self.close()
-        return ret
+        return retval
+
 
     def RefreshQueue(self):
         """ Forces the GUI to refresh the queue list"""

src/vpackager/dbviews.py

     def __init__(self):
         QueueView.__init__(self)
         self.banner_label.set_label('Manager job history')
-        self.rc_menu = RCMenu(items=['About Job', 'Rebuild Job'])
+        self.rc_menu = RCMenu(items=['About Job', 'Rebuild Job',
+                                     'View Build Log'])
 
     def tree_click_event(self, tree, event, data=None):
         """ Events triggered with the treeview is clicked """

src/vpackager/guitools.py

     def GetRowCount(self):
         return len(self.get_model())
 
-
 class AboutJob(gtk.Dialog):
     '''Dialog used to display detailed information about a build job. The user
     interface will not display every detail about the job, but this dialog
         self.body = body
         body.show_all()
 
+    def set_app(self, data):
+        self.app = data
+        self.appEntry.set_text((data or ""))
+
+    def set_src(self, data):
+        self.SrcURI = data
+        self.srcentry.set_text((data or ""))
+
+    def set_desc(self, data):
+        self.DescURI = data
+        self.descEntry.set_text((data or ""))
+
+    def set_version(self, data):
+        self.ver = data
+        self.verEntry.set_text((data or ""))
+
+    def add_patches(self, data):
+        for patch in data:
+            self.patches.append(patch)
+        self.__refresh_patches_tree()
+
     def _del_patch_event(self, widget=None):
         sel = self.patchestree.get_selection().get_selected()[0][0][0]
         if sel:

src/vpackager/viewcontrollers.py

         self.view.connect_item('wipe_history', self._wipe_history_event)
         # Connect menu items.
         self.view.rc_menu.connect_item('about_job', self._about_task_event)
+        self.view.rc_menu.connect_item('rebuild_job', self._rebuild_job_event)
+        self.view.rc_menu.connect_item('view_build_log',
+                                       self._view_build_log_event)
+
+    def _view_build_log_event(self, widget=None):
+        """ Display the build log if it is still present"""
+        dia = guitools.message.Error(
+            text = "Feature not yet available",
+            parent = self._parentwindow)
+        if dia.run():
+            return dia.destroy()
 
     def _about_task_event(self, widget=None):
-        pass
+        """ Show build details about the selected job"""
+        about = guitools.AboutTask(
+            jobid=self.view._selectedjob, dbase = self.model,
+            parent = self._parentwindow)
+        if about.run():
+            about.destroy()
 
     def _wipe_history_event(self, widget=None):
-        pass
+        """ Ask if the user is sure about wiping the history, and then do it"""
+        question = guitools.message.Question(
+            text="Are you sure you want to delete the job history?",
+            parent = self._parentwindow)
+        response = question.run()
+        question.destroy()
+        if response == gtk.RESPONSE_YES:
+            return self.model.WipeHistory()
+        return
 
+    def _rebuild_job_event(self, widget=None):
+        """ Present a form to make a few changes to the job and
+        add it back to the queue"""
+        info = self.model.GetTaskDetails(self.view._selectedjob)
+        dia = guitools.JobAddDialog(
+            title = 'Rebuild %s'% info['app'],
+            parent = self._parentwindow)
+        dia.set_app(info['app'])
+        dia.set_version(info['ver'])
+        dia.set_src(info['srcURI'])
+        dia.set_desc(info['descURI'])
+        if info['patches'] not in (
+            '', None, 'None'):
+            dia.set_patches(info['patches'].split(','))
+        response = dia.run()
+        dia.hide()
+        if response == gtk.RESPONSE_OK:
+            ret = self.model.NewJob(
+                app = dia.app,
+                ver = dia.ver,
+                srcURI = dia.SrcURI,
+                descURI = dia.DescURI,
+                release = dia.release,
+                _type = dia.srctype,
+                install = dia.install,
+                patches = ','.join(dia.patches))
+        else:
+            ret = None
+        dia.destroy()
 
-
+        return ret
 
 if __name__ == "__main__":
     model = dbutils.dbase()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.