Commits

Moises Henriquez  committed 1bc4fb0

adding patching support for builds and reducing information displayed on the screen

  • Participants
  • Parent commits 5b469ee

Comments (0)

Files changed (7)

+########################
+vpackager
+########################
+
+vpackager is a tool for building and installing software from
+source code.  Relies on sbbuilder to keep things standard to
+some point.  Designed with 2 goals in mind:
+1.) Make it easy for new linux users to install software.
+2.) Help project contributors (packagers) by providing a centralized
+    workplace and build packages that are up to standard for the online
+    repositories.  Because it relies on sbbuilder, vpackager creates
+    a valid source tree complete with package descriptions and dependency
+    information.
+
+#########################
+WARNING: Project Testers
+#########################
+If you are currently testing this project, please make sure you
+delete your /tmp/vpackager.db if you have one. The database structure
+is udergoing changes throughout the development process, and will
+conflict with previous versions of the database. You just need to delete it
+and vpackager will create the new one as necessary.
+

File src/vpackager/bot.py

 import os
 import sqlite3
 import urllib2
+import urllib
 import shutil
 import glib
 
         self.parent.historyman._refresh_history_display()
         self.parent.queueman._update_queue()
 
+    def _download_file(self, url):
+        '''download a remote file to the local directory'''
+        urllib.urlretrieve(url)
+
     def run(self):
         while self.parent._bot_run:
             time.sleep(0.25)
             # clear the textview
             buf = self.parent.outputplayer.get_buffer()
             buf.delete(buf.get_bounds()[0], buf.get_bounds()[1])
-
-            (_id,pkg,ver,src,desc,rel,_type,toinstall) = njob
+            _id = njob[0]
+            pkg = dbutils.GetJobProp(_id,'app')
+            ver = dbutils.GetJobProp(_id,'ver')
+            src = dbutils.GetJobProp(_id,'srcURI')
+            desc = dbutils.GetJobProp(_id, 'descURI')
+            rel = dbutils.GetJobProp(_id,'release')
+            _type = dbutils.GetJobProp(_id, 'install')
+            patches = dbutils.GetJobProp(_id, 'patches')
+            patchlist = []
+            if patches:
+                patchlist = patches.split(',')
             # Log the build start time
             self._log_job_start(_id)
             # Update GUI displays for queue and history
                     f.write(u.read())
                     f.close()
                     u.close()
+            if patchlist:
+                os.chdir(os.path.join(
+                    os.path.dirname(sbpath), 'patches'))
+                for patch in patchlist:
+                    if patch.startswith('/'):
+                        self.parent._play_output('\
+                                Adding patch %s to source tree \n'% patch)
+                        shutil.copy2(patch, os.path.join(
+                                    os.path.dirname(sbpath), 'patches',patch))
+                    else:
+                        self.parent._play_output('\
+                                Downloading patch %s \n'% patch)
+                        self._download_file(patch)
+            os.chdir(os.path.dirname(sbpath))
             job = srcob.buildSlackBuild()
             job.observer.add_callback(self.parent._play_output)
             job.run()

File src/vpackager/buildutils.py

 
     def __init__(self, path):
         self.path = path
+        self.builder = None
         filename = os.path.split(path)[1]
         if '-' in filename:
             fnsplit = filename.rsplit('-', 1)

File src/vpackager/dbutils.py

 #    along with vpackager.  If not, see <http://www.gnu.org/licenses/>.
 
 import sqlite3
+import os
 
 __author__ = 'M0E-lnx'
 __author_email__ = 'moc.liamg@xnl.E0M'[::-1]
 def __verify_tables():
     ''' Verify that the essential tables for the vpackager environment
     exist'''
+    if os.path.exists(dbpath):
+        os.remove(dbpath)
+    return True
+    # FIXME: ^^^ Remove this before final release ^^
+
     db = sqlite3.connect(dbpath)
     c = db.cursor()
     c.execute('select name from sqlite_master where type="table"')
     c.execute("""create table queue
     (id integer primary key autoincrement,
     app text, ver text, srcURI text, descURI text, release text, type text,
-    install text)""")
+    install text, patches text)""")
     db.commit()
     c.close()
     db.close()
 
     return
 
-def NewJob(app, ver, srcURI, descURI, release, _type, install):
+def NewJob(app, ver, srcURI, descURI, release, _type, install,
+        patches):
 
     """ Add a job to the job queue"""
     db = sqlite3.connect(dbpath)
-    t = (app, ver, srcURI, descURI, release, _type, install)
+    t = (app, ver, srcURI, descURI, release, _type, install, patches)
     c = db.cursor()
     c.execute("""insert into queue (app, ver, srcURI, descURI, release, Type,
-    install) values (?,?,?,?,?,?,?)""", t)
+    install, patches) values (?,?,?,?,?,?,?,?)""", t)
 
     db.commit()
     c.close()
     db.commit()
     db.close()
 
+def GetJobPatches(jobID):
+    t = (jobID,)
+    db = sqlite3.connect(dbpath)
+    c = db.cursor()
+    c.execute('select patches from queue where id=?',t)
+    try:
+        ret = c.next()
+    except StopIteration:
+        ret = None
+    c.close()
+    db.close()
+    return ret
+
+def GetJobProp(jobid, prop):
+    ''' Returns jobid's propperty (prop) '''
+    t = (prop,jobid)
+    db = sqlite3.connect(dbpath)
+    c = db.cursor()
+    c.execute('select %s from queue where id=%s'%(prop, jobid))
+    try:
+        ret = c.next()
+    except StopIteration:
+        ret = None
+    c.close()
+    db.close()
+    if ret:
+        return ret[0]
+    return None
+
 def GetNextJob():
     """ Find the next job in line to be built"""
     db = sqlite3.connect(dbpath)
     c = db.cursor()
-    c.execute('select * from queue')
+    c.execute('select id from queue')
     try:
         ret = c.next()
     except StopIteration:
     """ Return a list of all pending jobs"""
     db = sqlite3.connect(dbpath)
     c = db.cursor()
-    ret = c.execute('select * from queue').fetchall()
+    ret = c.execute('select id,app,ver,release from queue').fetchall()
+    #ret = c.execute('select * from queue').fetchall()
     c.close()
     db.close()
     return ret
     """ Return a list of all processed jobs"""
     db = sqlite3.connect(dbpath)
     c = db.cursor()
-    ret = c.execute('select * from history').fetchall()
+    ret = c.execute('\
+            select id,app,ver,buildstart,buildend,result \
+            from history').fetchall()
+    #ret = c.execute('select * from history').fetchall()
     c.close()
     db.close()
     return ret

File src/vpackager/guitools.py

 
         self.set_label(label)
 
+class AddPatchBox(gtk.Dialog):
+    ''' Dialog used to add a patch to a build job'''
+    def __init__(self, title='Add Patch', parent=None):
+        gtk.Dialog.__init__(self,parent=parent)
+        self.set_title('Add patch')
+        self.URI = None
+        body = self.get_content_area()
+        self.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
+        self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
+        hb = gtk.HBox()
+        lb = gtk.Label('\
+                Enter patch URL or browse for local files')
+        body.pack_start(lb, False, False, 2)
+        body.pack_start(hb, False, True, 2)
+        uriEntry = gtk.Entry()
+        self.uriEntry = uriEntry
+        uriEntry.connect('changed', self._uriEntry_changed)
+        btBrowse = vButton(stock=gtk.STOCK_OPEN,
+                label='Browse')
+        btBrowse.connect('clicked', self._btBrowse_clicked)
+        hb.pack_start(uriEntry, True, True, 2)
+        hb.pack_start(btBrowse, False, False, 2)
+        self.set_size_request(600,100)
+
+        self.show_all()
+
+    def _uriEntry_changed(self, widget=None):
+        ''' Set the dialog's URI property'''
+        self.URI = widget.get_text()
+        return
+
+    def _btBrowse_clicked(self, widget=None):
+        ''' Launch a filechooser dialog to select a patch file '''
+        dia = FilePicker(title='Select patch file')
+        res = dia.run()
+        dia.hide()
+        if res == gtk.RESPONSE_OK:
+            self.uriEntry.set_text(dia.get_filename())
+            self.URI=self.uriEntry.get_text()
+        return
+
+class FilePicker(gtk.FileChooserDialog):
+    ''' File chooser used in vpackager. Based on the gtk.FileChooserDialog but
+    has some extra convinience methods.'''
+    def __init__(self, title=None, forsrc=False, plaintxt=False):
+        _buttons = (gtk.STOCK_OK, gtk.RESPONSE_OK,
+                gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
+        _filter_src = gtk.FileFilter()
+        _filter_src.add_pattern('*.[bgx]z*')
+        _filter_src.set_name('Compressed Files')
+        _filter_txt = gtk.FileFilter()
+        _filter_txt.add_mime_type('text/plain')
+        _filter_txt.set_name('Text files')
+        _filter_all = gtk.FileFilter()
+        _filter_all.set_name('All Files')
+        _filter_all.add_pattern('*.*')
+
+        gtk.FileChooserDialog.__init__(self,
+                buttons=_buttons)
+        self.set_title(title)
+        if forsrc:
+            self.add_filter(_filter_src)
+        elif plaintxt:
+            self.add_filter(_filter_txt)
+        else:
+            self.add_filter(_filter_all)
+
+        self.set_current_folder('/home')
+
 class JobAddDialog(gtk.Dialog):
     '''Dialog window used to add a job to the queue'''
     def __init__(self, title='Add Job', parent=None):
         self.DescURI = None
         self.app = None
         self.ver = None
+        self.patches = []
         self.release = 1
         self.install = False
         self.patchesbox = self._patchesbox()
         self.set_default_response(gtk.RESPONSE_OK)
         body = self.get_content_area()
         self.set_title('Add New Job')
-        self.set_size_request(500,300)
+        self.set_size_request(500,320)
         frmSrc = gtk.Frame('Source Archive')
         body.pack_start(frmSrc, False, True, 8)
         hsrc = gtk.HBox()
         self.body = body
         body.show_all()
 
+    def _del_patch_event(self, widget=None):
+        sel = self.patchestree.get_selection().get_selected()[0][0][0]
+        if sel:
+            self.patches.remove(sel)
+        # Refresh the GUI that shows the patches
+        self.__refresh_patches_tree()
+
+    def _add_patch_event(self, widget=None):
+        dia = AddPatchBox(parent=self)
+        res = dia.run()
+        if res == gtk.RESPONSE_OK:
+            self.patches.append(dia.URI)
+        dia.destroy()
+        # Refresh the GUI list that shows the patches
+        self.__refresh_patches_tree()
+
+    def __refresh_patches_tree(self, widget=None):
+        model = self.patchestree.get_model()
+        model.clear()
+        for patch in self.patches:
+            model.append([patch])
+        return
+
     def _patchesbox(self):
         box = gtk.HBox()
         rbox = gtk.VBox()
         col.pack_start(cr)
         col.add_attribute(cr, 'text', 0)
         tree.append_column(col)
+        self.patchestree = tree
         tree.set_headers_visible(False)
-        box.pack_start(tree, True, True, 2)
+        scrollw = gtk.ScrolledWindow()
+        scrollw.set_policy(gtk.POLICY_AUTOMATIC,
+                gtk.POLICY_AUTOMATIC)
+        scrollw.add(tree)
+        box.pack_start(scrollw, True, True, 2)
         box.pack_start(rbox, False, False, 2)
         btAddPatch = vButton(stock=gtk.STOCK_ADD,
                 label='Add')
+        btAddPatch.connect('clicked', self._add_patch_event)
         btDelPatch = vButton(stock=gtk.STOCK_REMOVE,
                 label='Remove')
+        btDelPatch.connect('clicked', self._del_patch_event)
         rbox.pack_start(btAddPatch, False ,False, 2)
         rbox.pack_start(btDelPatch, False ,False, 2)
         return box
         self.DescURI = widget.get_text()
 
     def _desc_browse(self, widget=None):
-        dia = gtk.FileChooserDialog(buttons=(gtk.STOCK_OK,
-            gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
-        dia.set_title('Select description file')
-        flt = gtk.FileFilter()
-        flt.add_mime_type('text/plain')
-        flt.set_name('Text files')
-        dia.add_filter(flt)
+        dia = FilePicker(
+                title='Select description file',
+                plaintxt = True)
         res = dia.run()
         dia.hide()
         if res == gtk.RESPONSE_OK:
 
     def _browse(self, widget=None):
         """ Browse for source archive """
-        dia = gtk.FileChooserDialog(buttons=(gtk.STOCK_OK,
-            gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
-        dia.set_title('Choose source archive')
-        flt = gtk.FileFilter()
-        flt.add_pattern('*.[bgx]z*')
-        flt.set_name('Compressed Files')
-        dia.add_filter(flt)
-        dia.set_current_folder('/home')
+        dia = FilePicker(title='Choose source archive',
+                forsrc = True)
         res = dia.run()
         dia.hide()
         if res == gtk.RESPONSE_OK:
             self.SrcURI = dia.get_filename()
+            self.srcentry.set_text(self.SrcURI)
             try:
                 s = buildutils.Source(self.SrcURI)
                 self.appEntry.set_text(s.app)
                 if dia.run():
                     dia.destroy()
 
-        self.srcentry.set_text(self.SrcURI)
         return
 
 

File src/vpackager/historymanager.py

     def __init__(self):
         gtk.VBox.__init__(self)
         self.model = gtk.ListStore(
-                int, str, str, str, str, str, str, str, str, str, str)
+                int, str, str, str, str, str)
         self.pack_start(gtk.Label('Job History'), False, True, 2)
         scroll = gtk.ScrolledWindow()
         scroll.set_policy(gtk.POLICY_AUTOMATIC,
                 gtk.POLICY_AUTOMATIC)
         self.pack_start(scroll, True, True, 2)
         scroll.add(self._get_tree())
-#        self.pack_start(self._get_tree())
+        #self.pack_start(self._get_tree())
         self.show_all()
         self._refresh_history_display()
 
     def _get_tree(self):
         self.tree = gtk.TreeView(model = self.model)
         i = 0
-        for field in ('ID', 'Package', 'Version', 'Source URI', 'Description',
-                'Release','Type', 'Build Start', 'Build End', 'Output', 'Result'):
+        for field in ('ID','Application', 'Version',
+                'Build Start', 'Build End', 'Result'):
+        #for field in ('ID', 'Package', 'Version', 'Source URI', 'Description',
+        #   'Release','Type', 'Build Start', 'Build End', 'Output', 'Result'):
             col = gtk.TreeViewColumn(field)
             col.set_resizable(True)
             crt = gtk.CellRendererText()
 
     def _refresh_history_display(self):
         self.tree.set_model(
-                gtk.ListStore(int,str, str, str, str, str, str, str, str, str,str))
+                gtk.ListStore(int,str, str, str, str, str))
         lst = dbutils.GetHistory()
         for entry in lst:
             self.tree.get_model().append(entry)

File src/vpackager/jobmanage.py

             rel = dia.release
             srctype = dia.srctype
             toinstall = dia.install
+            patches = ','.join(dia.patches)
             dia.destroy()
-            dbutils.NewJob(app, ver, srcuri, desc, rel, srctype, toinstall)
+            dbutils.NewJob(app, ver, srcuri, desc,
+                    rel, srctype, toinstall, patches)
             return self._update_queue()
 
     def _btDeleteClick(self, widget=None):
             self._update_queue()
 
     def _update_queue(self):
-        self.tree.set_model(
-                gtk.ListStore(int,str, str, str, str, str, str,str))
+        self.tree.set_model(gtk.ListStore(int,str, str, str))
         lst = dbutils.GetQueue()
         for entry in lst:
             self.tree.get_model().append(entry)
 
     def _get_tree(self):
-        mod = gtk.ListStore(int, str, str, str, str, str, str, str)
+        mod = gtk.ListStore(int, str, str, str)
         self.tree = gtk.TreeView(model = mod)
         self.tree.connect('cursor-changed', self._tree_click_event)
 
         i = 0
         for field in ('ID', 'Application', 'Version',
-                'Source URI', 'Description', 'Release','Type', 'Install'):
+                'Release'):
             col = gtk.TreeViewColumn(field)
             col.set_resizable(True)
             cr = gtk.CellRendererText()