Source

Portfolio / trike / src / main.py

import logging
import os
import re
import subprocess
import sys

from os.path import isfile
from time import gmtime, strftime
from shlex import split

from loader.gccxml import process

from scanner.run import detect
from scanner.tools import record

from util.xml import generate
from util.database import Connection
from util.options import TrikeOptions

if __name__ == "__main__":
    ## Get and Set Options
    options = TrikeOptions( )
    configure = options.configure
    excludeddirs = options.excludes
    extensions = options.extensions
    gccxml = options.gccxml
    includes = options.includes
    logfile = options.logfile
    logname = options.logname
    overwrite = options.overwrite
    project = options.project
    sqlfile = options.sqlfile

    ## We close this after running checks.
    database = Connection( )
    conn = database.get( )
    db = conn.cursor( )

    if overwrite == '1':
        ## Clean out the database
        print "Setting up database..."
        db.execute("drop database if exists " + options.db)
        ## Setup database
        schema = open(options.sqlfile, 'r')
        for ddlstatement in schema:
            db.execute(ddlstatement)
        print "Finished database setup."

    ## Double check database exists before continuing.
    check = "select schema_name from information_schema.schemata where " + \
            "schema_name='" + options.db + "';"
    db.execute(check)
    status = db.fetchone( )

    if status[0] != options.db:
        print "ERROR: Database not setup properly. Does " + options.db + " exist?"
        from sys import exit as fail
        fail(-1)

    ## Setup Logging
    logging.basicConfig(filename=logfile, level=logging.INFO)
    scannerlog = logging.getLogger(logname)

    ## Get program id
    db.execute("select id from program where name = '" + options.name + "'")
    program_name = db.fetchone()
    if program_name == None:
        ## Add project - right now we only support a single project at a time
        db.execute("insert into program (name) values ('" + options.name + "');")
        program_name = options.name
        conn.commit( )

    db.execute("select id from program where name = '" + options.name + "'")
    program_id = db.fetchone( )[0]
      
    start_time = strftime("%a, %d %b %Y %H:%M:%S -0500", gmtime())
    print "Starting run at " + start_time
    print "This can take a while so please be patient."
    scannerlog.info("Started run at " + start_time)

    ## Is autoconf supported and requested?
    if configure == '1':
        if not isfile(project + "/configure"):
            scannerlog.info("Asked to run configure without a configure file?")
            scannerlog.info("Does the project source code exists?")
            print "You wanted to run ./configure but this project doesn't" + \
                   " seem to use autoconf. Did you unpack the source?"
            exit(-1)

        ## Try to run configure
        try:
            scannerlog.info("Running ./configure ... " + \
                            strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()))
            print "Running ./configure ..."
            scandir = os.getcwd()
            os.chdir(project)
            command = "./configure"
            args = split(command)
            config = subprocess.Popen(
                args, stdout=subprocess.PIPE, stderr=subprocess.PIPE
            ) 

            while True:
                stdout = config.stdout.readline()
                stderr = config.stderr.readline()
                if stdout == '' and config.poll() != None:
                    break
                
                if stderr != '':
                    if stderr.startswith("configure: error"):
                        raise Exception(stderr);

            ## REMOVE ME

            ## change back
            os.chdir(scandir)
        except Exception, configException:
            scannerlog.error("Error running ./configure.") 
            print "Error running ./configure."
            print configException 
            exit(-1)

    ## Get Source Files and Record Associated Data
    print "Detecting source files..."
    scannerlog.info("Detecting source file...")
    sourcefilelist = detect(project, extensions, excludeddirs)
    record(sourcefilelist, program_id, database, 'source')

    ## Get Existing XML Files
    print "Detecting existing xml files..."
    scannerlog.info("Detecting existing xml files...")
    existingxmllist = detect(project, ["xml"], excludeddirs)
    print "Discovered " + str(len(existingxmllist)) + " existing xml files."
    scannerlog.info("Discovered " + str(len(existingxmllist)) +
                    " existing xml files.")

    ## Generate XML using GCC-XML?
    ## NOTE: We originally intended to do auto-discovery of new xml files but
    ##       it makes more sense to enable developers to run the tool using a
    ##       small script that will use these routines.
    ##
    ## TODO: We need to write this tool.
    ##

    print includes

    ## Generate XML Files
    scannerlog.info("Entering GCC-XML xml generation phase...")
    print "Entering GCC-XML xml generation phase..."
    xmlfilelist = generate(gccxml, project, includes, existingxmllist, program_id, sourcefilelist)
    conn.commit( )

    ## Parse and Record XML
    if len(xmlfilelist) == 0:
        scannerlog.info("NOTICE: No new xml files exist. Did you clean up?")
        print "NOTICE: No new xml files exist. Did you clean up?"
        from sys import exit as fail
        fail(-1)
    else:
        scannerlog.info("Attempting to process and record generated XML...")
        print "Attempting to process and record generated XML..."
        process(scannerlog, db, conn, xmlfilelist)

    ## Close Database Connection
    db.close( )

    print "Finished." 
    scannerlog.info("Finished run at " + \
        strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()))