summaryrefslogtreecommitdiff
path: root/patchtracker/DB.py
blob: 3a5be5ce786af6c7a77e23d5268d75aa7113ada6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
from pysqlite2 import dbapi2 as sqlite
import Conf
import os
import errno

import patchtracker.SourceArchive as SourceArchive

def srcpkg_factory(cursor, row):
  d = {}
  for idx, col in enumerate(cursor.description):
    d[col[0]] = row[idx]

  info = {}
  info['Files'] = []
  if d['diffgz_name']:
    diffgz = {'name':d['diffgz_name'], 'size':d['diffgz_size'], 
              'md5sum':d['diffgz_md5sum'] }
    info['Files'].append(diffgz)

  colmap = {'name':'Package','version':'Version','format':'Format',
            'loc':'Directory','maintainer':'Maintainer','uploaders':'Uploaders'}
            
  for col,field in colmap.iteritems():
    info[field] = d[col]
  return SourceArchive.SourcePackage(info)

def srcpkg_collection_factory(cursor, row):
  d = {}
  rest = {}
  for idx, col in enumerate(cursor.description):
    if not d.has_key(col[0]):
      d[col[0]] = row[idx]
    else:
      rest[col[0]] = row[idx]

  info = {}
  info['Files'] = []
  if d['diffgz_name']:
    diffgz = {'name':d['diffgz_name'], 'size':d['diffgz_size'], 
              'md5sum':d['diffgz_md5sum'] }
    info['Files'].append(diffgz)

  colmap = {'name':'Package','version':'Version','format':'Format',
            'loc':'Directory','maintainer':'Maintainer','uploaders':'Uploaders'}
            
  for col,field in colmap.iteritems():
    info[field] = d[col]
  return (SourceArchive.SourcePackage(info), rest)


class PatchTrackerDB:
  def __init__(self, dbname=Conf.database):
    self.db = sqlite.connect(dbname)
    cursor = self.db.cursor()
    cursor.execute("SELECT * FROM sqlite_master WHERE name='packages'")
    if not cursor.fetchone():
      print "repopulating empty database..."
      nextcmd = ""
      for l in file(Conf.sqlschema).readlines():
        if len(l.strip()):
          nextcmd += " " + l.strip()
        else:
          cursor.execute(nextcmd)
          nextcmd = ""

  def setFactory(self, factory):
    self.db.row_factory = factory

  def saveSourcePackage(self, srcpkg):
    cursor = self.db.cursor()
    #print "creating new record for",srcpkg
    q = "INSERT OR IGNORE INTO packages \
           (name,format,loc,version,diffgz_name,diffgz_size,diffgz_md5sum,maintainer,uploaders) \
           VALUES (?,?,?,?,?,?,?,?,?)"
    cursor.execute(q, (srcpkg.name,srcpkg.format,srcpkg.loc,
                       srcpkg.version,srcpkg.diffgz_name,srcpkg.diffgz_size,
                       srcpkg.diffgz_md5sum,srcpkg.maintainer,srcpkg.uploaders))

  def saveSuite(self, suite):
    q = "INSERT INTO suites (name) VALUES (?)"
    cursor = self.db.cursor()
    cursor.execute(q, (suite,))

  def saveComponent(self, component):
    q = "INSERT INTO components (name) VALUES (?)"
    cursor = self.db.cursor()
    cursor.execute(q, (component,))

  def findCollection(self, package="%", version=None, email=None):
    oldfactory = self.db.row_factory
    self.db.row_factory = srcpkg_collection_factory
    cursor = self.db.cursor()
    toc = SourceArchive.SourcePackageIndex()
    q = "SELECT * FROM packages AS p,package_rel_map AS m,suites AS s \
           WHERE p.name LIKE ? AND p.id = m.package_id AND m.suite_id = s.id"
    qargs = (package,)
    if version:
      q += " AND p.version = ?"
      qargs += (version,)
    if email:
      q += " AND ( p.maintainer like ? OR p.uploaders like ? )"
      qargs += (email,email)

    cursor.execute(q, qargs)
    # use srcpkg_factory to fetch sourcepackages, once per suite
    for srcpkg,rest in cursor.fetchall():
      toc.ins(srcpkg, rest["name"])
    self.db.row_factory = oldfactory
    return toc

  def findLetterToc(self, letter):
    return self.findCollection(package=letter+"%").getletter(letter)

  def findIndices(self):
    indices = []
    cursor = self.db.cursor()
    q1 = "SELECT DISTINCT SUBSTR(name,1,1) FROM packages \
            WHERE name NOT LIKE 'lib%'"
    q2 = "SELECT DISTINCT SUBSTR(name,1,4) FROM packages \
            WHERE name LIKE 'lib%'"

    for q in [q1, q2]:
      cursor.execute(q)
      for idx in cursor.fetchall():
        indices.append(idx[0])
    
    indices.sort()
    return indices
     
  def relateSourcePackage(self, name, version, suite, component):
    q = "INSERT INTO package_rel_map \
           (package_id,suite_id,component_id,marked) \
           VALUES ((SELECT id FROM packages WHERE name=? AND version=?), \
                  (SELECT id FROM suites WHERE name=?), \
                  (SELECT id FROM components WHERE name=?), 1)"
    cursor = self.db.cursor()
    cursor.execute(q, (name, version, suite, component))

  def findDiffGz(self, pkgname, version):
    q = "SELECT diffgz_name,loc FROM packages WHERE name=? AND version=?"
    cursor = self.db.cursor()
    cursor.execute(q, (pkgname, version))
    try:
      diffgz,loc = cursor.fetchone()
      return os.sep.join([Conf.archive_root, loc, diffgz])
    except:
      return None

  def prune(self):
    q = "DELETE FROM package_rel_map WHERE marked != 1"
    cursor = self.db.cursor()
    cursor.execute(q)

  def unmark(self):
    q = "UPDATE package_rel_map SET marked=0"
    cursor = self.db.cursor()
    cursor.execute(q)

  def finalize(self):
    self.db.commit()

  def __del__(self):
    self.finalize()
    

if __name__ == "__main__":
  print "patch tracker db testing"
  d = PatchTrackerDB(dbname="foo.db")
  sp = SourceArchive.SourcePackage({'Package':'foo','Format':'blah','Directory':'/foo','Version':'1.2.3.4','Files':[]})
  d.saveSourcePackage(sp)
  d.finalize()