]> git.decadent.org.uk Git - dak.git/blobdiff - daklib/dbconn.py
miscellaneous fixups from testing
[dak.git] / daklib / dbconn.py
index b993d43fa1e2ead90c072ef318f06d8f163191d5..f32a94bb91d550fa82886943a80c83d620ec613e 100755 (executable)
@@ -417,6 +417,9 @@ def get_or_set_contents_file_id(filename, session=None):
             session.add(cf)
             if privatetrans:
                 session.commit()
+                session.close()
+            else:
+                session.flush()
             return cf.cafilename_id
         else:
             return q.one().cafilename_id
@@ -491,7 +494,7 @@ class ContentFilepath(object):
 
 __all__.append('ContentFilepath')
 
-def get_or_set_contents_path_id(filepath, session):
+def get_or_set_contents_path_id(filepath, session=None):
     """
     Returns database id for given path.
 
@@ -520,6 +523,9 @@ def get_or_set_contents_path_id(filepath, session):
             session.add(cf)
             if privatetrans:
                 session.commit()
+                session.close()
+            else:
+                session.flush()
             return cf.cafilepath_id
         else:
             return q.one().cafilepath_id
@@ -566,27 +572,40 @@ def insert_content_paths(binary_id, fullpaths, session=None):
         privatetrans = True
 
     try:
+        # Insert paths
+        pathcache = {}
         for fullpath in fullpaths:
+            # Get the necessary IDs ...
             (path, file) = os.path.split(fullpath)
 
-            # Get the necessary IDs ...
+            filepath_id = get_or_set_contents_path_id(path, session)
+            filename_id = get_or_set_contents_file_id(file, session)
+
+            pathcache[fullpath] = (filepath_id, filename_id)
+
+        for fullpath, dat in pathcache.items():
             ca = ContentAssociation()
             ca.binary_id = binary_id
-            ca.filename_id = get_or_set_contents_file_id(file)
-            ca.filepath_id = get_or_set_contents_path_id(path)
+            ca.filepath_id = dat[0]
+            ca.filename_id = dat[1]
             session.add(ca)
 
         # Only commit if we set up the session ourself
         if privatetrans:
             session.commit()
+            session.close()
+        else:
+            session.flush()
 
         return True
+
     except:
         traceback.print_exc()
 
         # Only rollback if we set up the session ourself
         if privatetrans:
             session.rollback()
+            session.close()
 
         return False
 
@@ -603,6 +622,41 @@ class DSCFile(object):
 
 __all__.append('DSCFile')
 
+def get_dscfiles(dscfile_id=None, source_id=None, poolfile_id=None, session=None):
+    """
+    Returns a list of DSCFiles which may be empty
+
+    @type dscfile_id: int (optional)
+    @param dscfile_id: the dscfile_id of the DSCFiles to find
+
+    @type source_id: int (optional)
+    @param source_id: the source id related to the DSCFiles to find
+
+    @type poolfile_id: int (optional)
+    @param poolfile_id: the poolfile id related to the DSCFiles to find
+
+    @rtype: list
+    @return: Possibly empty list of DSCFiles
+    """
+
+    if session is None:
+        session = DBConn().session()
+
+    q = session.query(DSCFile)
+
+    if dscfile_id is not None:
+        q = q.filter_by(dscfile_id=dscfile_id)
+
+    if source_id is not None:
+        q = q.filter_by(source_id=source_id)
+
+    if poolfile_id is not None:
+        q = q.filter_by(poolfile_id=poolfile_id)
+
+    return q.all()
+
+__all__.append('get_dscfiles')
+
 ################################################################################
 
 class PoolFile(object):
@@ -614,6 +668,76 @@ class PoolFile(object):
 
 __all__.append('PoolFile')
 
+def check_poolfile(filename, filesize, md5sum, location_id, session=None):
+    """
+    Returns a tuple:
+     (ValidFileFound [boolean or None], PoolFile object or None)
+
+    @type filename: string
+    @param filename: the filename of the file to check against the DB
+
+    @type filesize: int
+    @param filesize: the size of the file to check against the DB
+
+    @type md5sum: string
+    @param md5sum: the md5sum of the file to check against the DB
+
+    @type location_id: int
+    @param location_id: the id of the location to look in
+
+    @rtype: tuple
+    @return: Tuple of length 2.
+             If more than one file found with that name:
+                    (None,  None)
+             If valid pool file found: (True, PoolFile object)
+             If valid pool file not found:
+                    (False, None) if no file found
+                    (False, PoolFile object) if file found with size/md5sum mismatch
+    """
+
+    if session is None:
+        session = DBConn().session()
+
+    q = session.query(PoolFile).filter_by(filename=filename)
+    q = q.join(Location).filter_by(location_id=location_id)
+
+    if q.count() > 1:
+        return (None, None)
+    if q.count() < 1:
+        return (False, None)
+
+    obj = q.one()
+    if obj.md5sum != md5sum or obj.filesize != filesize:
+        return (False, obj)
+
+    return (True, obj)
+
+__all__.append('check_poolfile')
+
+def get_poolfile_by_id(file_id, session=None):
+    """
+    Returns a PoolFile objects or None for the given id
+
+    @type file_id: int
+    @param file_id: the id of the file to look for
+
+    @rtype: PoolFile or None
+    @return: either the PoolFile object or None
+    """
+
+    if session is None:
+        session = DBConn().session()
+
+    q = session.query(PoolFile).filter_by(file_id=file_id)
+
+    if q.count() > 0:
+        return q.one()
+
+    return None
+
+__all__.append('get_poolfile_by_id')
+
+
 def get_poolfile_by_name(filename, location_id=None, session=None):
     """
     Returns an array of PoolFile objects for the given filename and
@@ -629,7 +753,7 @@ def get_poolfile_by_name(filename, location_id=None, session=None):
     @return: array of PoolFile objects
     """
 
-    if session is not None:
+    if session is None:
         session = DBConn().session()
 
     q = session.query(PoolFile).filter_by(filename=filename)
@@ -652,7 +776,7 @@ def get_poolfile_like_name(filename, session=None):
     @return: array of PoolFile objects
     """
 
-    if session is not None:
+    if session is None:
         session = DBConn().session()
 
     # TODO: There must be a way of properly using bind parameters with %FOO%
@@ -673,6 +797,49 @@ class Fingerprint(object):
 
 __all__.append('Fingerprint')
 
+def get_or_set_fingerprint(fpr, session=None):
+    """
+    Returns Fingerprint object for given fpr.
+
+    If no matching fpr is found, a row is inserted.
+
+    @type fpr: string
+    @param fpr: The fpr to find / add
+
+    @type session: SQLAlchemy
+    @param session: Optional SQL session object (a temporary one will be
+    generated if not supplied).  If not passed, a commit will be performed at
+    the end of the function, otherwise the caller is responsible for commiting.
+    A flush will be performed either way.
+
+    @rtype: Fingerprint
+    @return: the Fingerprint object for the given fpr
+    """
+    privatetrans = False
+    if session is None:
+        session = DBConn().session()
+        privatetrans = True
+
+    try:
+        q = session.query(Fingerprint).filter_by(fingerprint=fpr)
+        if q.count() < 1:
+            fingerprint = Fingerprint()
+            fingerprint.fingerprint = fpr
+            session.add(fingerprint)
+            if privatetrans:
+                session.commit()
+            else:
+                session.flush()
+            return fingerprint
+        else:
+            return q.one()
+
+    except:
+        traceback.print_exc()
+        raise
+
+__all__.append('get_or_set_fingerprint')
+
 ################################################################################
 
 class Keyring(object):
@@ -748,6 +915,49 @@ class Maintainer(object):
 
 __all__.append('Maintainer')
 
+def get_or_set_maintainer(name, session=None):
+    """
+    Returns Maintainer object for given maintainer name.
+
+    If no matching maintainer name is found, a row is inserted.
+
+    @type name: string
+    @param name: The maintainer name to add
+
+    @type session: SQLAlchemy
+    @param session: Optional SQL session object (a temporary one will be
+    generated if not supplied).  If not passed, a commit will be performed at
+    the end of the function, otherwise the caller is responsible for commiting.
+    A flush will be performed either way.
+
+    @rtype: Maintainer
+    @return: the Maintainer object for the given maintainer
+    """
+    privatetrans = False
+    if session is None:
+        session = DBConn().session()
+        privatetrans = True
+
+    try:
+        q = session.query(Maintainer).filter_by(name=name)
+        if q.count() < 1:
+            maintainer = Maintainer()
+            maintainer.name = name
+            session.add(maintainer)
+            if privatetrans:
+                session.commit()
+            else:
+                session.flush()
+            return maintainer
+        else:
+            return q.one()
+
+    except:
+        traceback.print_exc()
+        raise
+
+__all__.append('get_or_set_maintainer')
+
 ################################################################################
 
 class NewComment(object):
@@ -965,23 +1175,32 @@ def insert_pending_content_paths(package, fullpaths, session=None):
         q.delete()
 
         # Insert paths
+        pathcache = {}
         for fullpath in fullpaths:
             (path, file) = os.path.split(fullpath)
 
             if path.startswith( "./" ):
                 path = path[2:]
 
+            filepath_id = get_or_set_contents_path_id(path, session)
+            filename_id = get_or_set_contents_file_id(file, session)
+
+            pathcache[fullpath] = (filepath_id, filename_id)
+
+        for fullpath, dat in pathcache.items():
             pca = PendingContentAssociation()
             pca.package = package['Package']
             pca.version = package['Version']
-            pca.filename_id = get_or_set_contents_file_id(file, session)
-            pca.filepath_id = get_or_set_contents_path_id(path, session)
+            pca.filepath_id = dat[0]
+            pca.filename_id = dat[1]
             pca.architecture = arch_id
             session.add(pca)
 
         # Only commit if we set up the session ourself
         if privatetrans:
             session.commit()
+        else:
+            session.flush()
 
         return True
     except:
@@ -1042,6 +1261,29 @@ def get_priority(priority, session=None):
 
 __all__.append('get_priority')
 
+def get_priorities(session=None):
+    """
+    Returns dictionary of priority names -> id mappings
+
+    @type session: Session
+    @param session: Optional SQL session object (a temporary one will be
+    generated if not supplied)
+
+    @rtype: dictionary
+    @return: dictionary of priority names -> id mappings
+    """
+    if session is None:
+        session = DBConn().session()
+
+    ret = {}
+    q = session.query(Priority)
+    for x in q.all():
+        ret[x.priority] = x.priority_id
+
+    return ret
+
+__all__.append('get_priorities')
+
 ################################################################################
 
 class Queue(object):
@@ -1105,7 +1347,7 @@ class Queue(object):
                 dest = os.path.join(dest_dir, file_entry)
 
                 # TODO: Move into database as above
-                if Cnf.FindB("Dinstall::SecurityQueueBuild"):
+                if conf.FindB("Dinstall::SecurityQueueBuild"):
                     # Copy it since the original won't be readable by www-data
                     utils.copy(src, dest)
                 else:
@@ -1199,15 +1441,15 @@ class QueueBuild(object):
 
 __all__.append('QueueBuild')
 
-def get_queue_build(filename, suite_id, session=None):
+def get_queue_build(filename, suite, session=None):
     """
-    Returns QueueBuild object for given C{filename} and C{suite id}.
+    Returns QueueBuild object for given C{filename} and C{suite}.
 
     @type filename: string
     @param filename: The name of the file
 
-    @type suiteid: int
-    @param suiteid: Suite ID
+    @type suiteid: int or str
+    @param suiteid: Suite name or ID
 
     @type session: Session
     @param session: Optional SQLA session object (a temporary one will be
@@ -1219,7 +1461,12 @@ def get_queue_build(filename, suite_id, session=None):
     """
     if session is None:
         session = DBConn().session()
-    q = session.query(QueueBuild).filter_by(filename=filename).filter_by(suite_id=suite_id)
+    if isinstance(suite, int):
+        q = session.query(QueueBuild).filter_by(filename=filename).filter_by(suite_id=suite)
+    else:
+        q = session.query(QueueBuild).filter_by(filename=filename)
+        q = q.join(Suite).filter_by(suite_name=suite)
+
     if q.count() == 0:
         return None
     return q.one()
@@ -1273,6 +1520,29 @@ def get_section(section, session=None):
 
 __all__.append('get_section')
 
+def get_sections(session=None):
+    """
+    Returns dictionary of section names -> id mappings
+
+    @type session: Session
+    @param session: Optional SQL session object (a temporary one will be
+    generated if not supplied)
+
+    @rtype: dictionary
+    @return: dictionary of section names -> id mappings
+    """
+    if session is None:
+        session = DBConn().session()
+
+    ret = {}
+    q = session.query(Section)
+    for x in q.all():
+        ret[x.section] = x.section_id
+
+    return ret
+
+__all__.append('get_sections')
+
 ################################################################################
 
 class DBSource(object):
@@ -1698,6 +1968,8 @@ def get_or_set_uid(uidname, session=None):
             session.add(uid)
             if privatetrans:
                 session.commit()
+            else:
+                session.flush()
             return uid
         else:
             return q.one()