]> git.decadent.org.uk Git - dak.git/blob - dak/import_contents.py
Added content import, merged master, added update2 script,
[dak.git] / dak / import_contents.py
1 #!/usr/bin/env python
2 # Import contents files
3
4 # Copyright (C) 2008, 2009 Michael Casadevall <mcasadevall@debian.org>
5
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 ################################################################################
21 ################################################################################
22
23 ################################################################################
24
25 import sys, os, popen2, tempfile, stat, time, pg
26 import re, gzip, apt_pkg
27 from daklib import database, utils
28 from daklib.dak_exceptions import *
29
30 ################################################################################
31
32 Cnf = None
33 projectB = None
34 out = None
35 AptCnf = None
36
37 ################################################################################
38
39 def usage (exit_code=0):
40     print """Usage: dak import-contents
41 Import Contents files
42
43  -h, --help                 show this help and exit
44  -s, --suite=SUITE         only write file lists for this suite
45 """
46     sys.exit(exit_code)
47
48 ################################################################################
49
50 def import_contents(suites):
51     global projectB, Cnf
52
53     # Start transaction
54     projectB.query("BEGIN WORK")
55
56     # Needed to make sure postgreSQL doesn't freak out on some of the data
57     projectB.query("SET CLIENT_ENCODING TO 'LATIN1'")
58
59     # Get our suites, and the architectures
60     for s in suites:
61         suite_id = database.get_suite_id(s)
62
63         q = projectB.query("SELECT s.architecture, a.arch_string FROM suite_architectures s JOIN architecture a ON (s.architecture=a.id) WHERE suite = '%d'" % suite_id)
64
65         arch_list = [ ]
66         for r in q.getresult():
67             if r[1] != "source" and r[1] != "all":
68                 arch_list.append((r[0], r[1]))
69
70         arch_all_id = database.get_architecture_id("all")
71
72         for arch in arch_list:
73             print "Processing %s/%s" % (s, arch[1])
74             arch_id = database.get_architecture_id(arch[1])
75             f = gzip.open(Cnf["Dir::Root"] + "dists/%s/Contents-%s.gz" % (s, arch[1]), "r")
76
77             # Get line count
78             lines = f.readlines()
79             num_of_lines = len(lines)
80
81             # Ok, the file cursor is at the first entry, now comes the fun 'lets parse' bit
82             lines_processed = 0
83             found_header = False
84
85             for line in lines:
86                 if found_header == False:
87                     if not line:
88                         print "Unable to find end of Contents-%s.gz header!" % ( arch[1])
89                         sys.exit(255)
90
91                     lines_processed += 1
92                     p = re.compile('^FILE')
93                     if p.match(line):
94                         found_header = True
95                     continue
96
97                 # The format is simple enough, *filename*, *section/package1,section/package2,etc*
98                 # Each file appears once per Contents file, so first, use some regex match
99                 # to split the two bits
100
101                 # Print out progress bar
102                 print "\rProcessed %d lines of %d (%%%.2f)" % (lines_processed, num_of_lines, (float(lines_processed)/num_of_lines)),
103
104                 # regex lifted from packages.d.o code
105                 p = re.compile('^(.+?)\s+(\S+)$')
106                 matchs = p.findall(line)
107                 filename = matchs[0][0]
108                 packages = matchs[0][1].split(',')
109
110                 # Iterate through each file's packages
111                 for package in packages:
112                     p = re.compile('(\S+)/(\S+)$')
113                     matchs = p.findall(package)
114
115                     # Needed since the DB is unicode, and these files
116                     # are ASCII
117                     section_name = matchs[0][0]
118                     package_name = matchs[0][1]
119
120                     section_id = database.get_section_id(section_name)
121                     package_id = database.get_latest_binary_version_id(package_name, section_id, suite_id, arch_id)
122
123                     if package_id == None:
124                         # Likely got an arch all package
125                         package_id = database.get_latest_binary_version_id(package_name, section_id, suite_id, arch_all_id)
126
127                     database.insert_content_path(package_id, filename)
128
129                 lines_processed += 1
130             f.close()
131
132     # Commit work
133     print "Committing to database ..."
134     projectB.query("COMMIT")
135
136 ################################################################################
137
138 def main ():
139     global Cnf, projectB, out
140     out = sys.stdout
141
142     Cnf = utils.get_conf()
143
144     Arguments = [('h',"help","Import-Contents::Options::Help"),
145                  ('s',"suite","Import-Contents::Options::Suite","HasArg"),
146                 ]
147
148     for i in [ "help", "suite" ]:
149         if not Cnf.has_key("Import-Contents::Options::%s" % (i)):
150             Cnf["Import-Contents::Options::%s" % (i)] = ""
151
152     suites = apt_pkg.ParseCommandLine(Cnf,Arguments,sys.argv)
153     Options = Cnf.SubTree("Import-Contents::Options")
154
155     if Options["Help"]:
156         usage()
157
158     if Options["Suite"]:
159         suites = utils.split_args(Options["Suite"])
160     else:
161         suites = Cnf.SubTree("Suite").List()
162
163     projectB = pg.connect(Cnf["DB::Name"], Cnf["DB::Host"], int(Cnf["DB::Port"]))
164     database.init(Cnf, projectB)
165
166     import_contents(suites)
167
168 #######################################################################################
169
170 if __name__ == '__main__':
171     main()