]> git.decadent.org.uk Git - dak.git/blob - claire.py
two bug fixes in source_exists changes
[dak.git] / claire.py
1 #!/usr/bin/env python
2
3 # 'Fix' stable to make debian-cd and dpkg -BORGiE users happy
4 # Copyright (C) 2000, 2001, 2002  James Troup <james@nocrew.org>
5 # $Id: claire.py,v 1.18 2002-10-16 02:47:32 troup Exp $
6
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
21 ################################################################################
22
23 # "Look around... leaves are brown... and the sky's a hazy shade of winter,
24 #  Look around... leaves are brown... there's a patch of snow on the ground."
25 #                                         -- Simon & Garfunkel / 'A Hazy Shade'
26
27 ################################################################################
28
29 import os, pg, re, sys;
30 import utils, db_access;
31 import apt_pkg;
32
33 ################################################################################
34
35 re_strip_section_prefix = re.compile(r'.*/');
36
37 Cnf = None;
38 projectB = None;
39
40 ################################################################################
41
42 def usage (exit_code=0):
43     print """Usage: claire [OPTIONS]
44 Create compatibility symlinks from legacy locations to the pool.
45
46   -v, --verbose              explain what is being done
47   -h, --help                 show this help and exit"""
48
49     sys.exit(exit_code)
50
51 ################################################################################
52
53 # Relativize an absolute symlink from 'src' -> 'dest' relative to 'root'.
54 # Returns fixed 'src'
55 def clean_symlink (src, dest, root):
56     src = src.replace(root, '', 1);
57     dest = dest.replace(root, '', 1);
58     dest = os.path.dirname(dest);
59     new_src = '../' * len(dest.split('/'));
60     return new_src + src;
61
62 ################################################################################
63
64 def fix_component_section (component, section):
65     if component == "":
66         component = utils.extract_component_from_section(section)[1];
67
68     # FIXME: ugly hacks to work around override brain damage
69     section = re_strip_section_prefix.sub('', section);
70     section = section.lower().replace('non-us', '');
71     if section == "main" or section == "contrib" or section == "non-free":
72         section = '';
73     if section != '':
74         section += '/';
75
76     return (component, section);
77
78 ################################################################################
79
80 def find_dislocated_stable(Cnf, projectB):
81     dislocated_files = {}
82
83     codename = Cnf["Suite::Stable::Codename"];
84
85     # Source
86     q = projectB.query("""
87 SELECT DISTINCT ON (f.id) c.name, sec.section, l.path, f.filename, f.id
88     FROM component c, override o, section sec, source s, files f, location l,
89          dsc_files df, suite su, src_associations sa, files f2, location l2
90     WHERE su.suite_name = 'stable' AND sa.suite = su.id AND sa.source = s.id
91       AND f2.id = s.file AND f2.location = l2.id AND df.source = s.id
92       AND f.id = df.file AND f.location = l.id AND o.package = s.source
93       AND sec.id = o.section AND NOT (f.filename ~ '^%s/')
94       AND l.component = c.id AND o.suite = su.id
95 """ % (codename));
96 # Only needed if you have files in legacy-mixed locations
97 #  UNION SELECT DISTINCT ON (f.id) null, sec.section, l.path, f.filename, f.id
98 #      FROM component c, override o, section sec, source s, files f, location l,
99 #           dsc_files df, suite su, src_associations sa, files f2, location l2
100 #      WHERE su.suite_name = 'stable' AND sa.suite = su.id AND sa.source = s.id
101 #        AND f2.id = s.file AND f2.location = l2.id AND df.source = s.id
102 #        AND f.id = df.file AND f.location = l.id AND o.package = s.source
103 #        AND sec.id = o.section AND NOT (f.filename ~ '^%s/') AND o.suite = su.id
104 #        AND NOT EXISTS (SELECT l.path FROM location l WHERE l.component IS NOT NULL AND f.location = l.id);
105     for i in q.getresult():
106         (component, section) = fix_component_section(i[0], i[1]);
107         if Cnf.FindB("Dinstall::LegacyStableHasNoSections"):
108             section="";
109         dest = "%sdists/%s/%s/source/%s%s" % (Cnf["Dir::Root"], codename, component, section, os.path.basename(i[3]));
110         if not os.path.exists(dest):
111             src = i[2]+i[3];
112             src = clean_symlink(src, dest, Cnf["Dir::Root"]);
113             if Cnf.Find("Claire::Options::Verbose"):
114                 print src+' -> '+dest
115             os.symlink(src, dest);
116         dislocated_files[i[4]] = dest;
117
118     # Binary
119     architectures = filter(utils.real_arch, Cnf.ValueList("Suite::Stable::Architectures"));
120     q = projectB.query("""
121 SELECT DISTINCT ON (f.id) c.name, a.arch_string, sec.section, b.package,
122                           b.version, l.path, f.filename, f.id
123     FROM architecture a, bin_associations ba, binaries b, component c, files f,
124          location l, override o, section sec, suite su
125     WHERE su.suite_name = 'stable' AND ba.suite = su.id AND ba.bin = b.id
126       AND f.id = b.file AND f.location = l.id AND o.package = b.package
127       AND sec.id = o.section AND NOT (f.filename ~ '^%s/')
128       AND b.architecture = a.id AND l.component = c.id AND o.suite = su.id""" %
129                        (codename));
130 # Only needed if you have files in legacy-mixed locations
131 #  UNION SELECT DISTINCT ON (f.id) null, a.arch_string, sec.section, b.package,
132 #                            b.version, l.path, f.filename, f.id
133 #      FROM architecture a, bin_associations ba, binaries b, component c, files f,
134 #           location l, override o, section sec, suite su
135 #      WHERE su.suite_name = 'stable' AND ba.suite = su.id AND ba.bin = b.id
136 #        AND f.id = b.file AND f.location = l.id AND o.package = b.package
137 #        AND sec.id = o.section AND NOT (f.filename ~ '^%s/')
138 #        AND b.architecture = a.id AND o.suite = su.id AND NOT EXISTS
139 #          (SELECT l.path FROM location l WHERE l.component IS NOT NULL AND f.location = l.id);
140     for i in q.getresult():
141         (component, section) = fix_component_section(i[0], i[2]);
142         if Cnf.FindB("Dinstall::LegacyStableHasNoSections"):
143             section="";
144         architecture = i[1];
145         package = i[3];
146         version = utils.re_no_epoch.sub('', i[4]);
147         src = i[5]+i[6];
148
149         dest = "%sdists/%s/%s/binary-%s/%s%s_%s.deb" % (Cnf["Dir::Root"], codename, component, architecture, section, package, version);
150         src = clean_symlink(src, dest, Cnf["Dir::Root"]);
151         if not os.path.exists(dest):
152             if Cnf.Find("Claire::Options::Verbose"):
153                 print src+' -> '+dest;
154             os.symlink(src, dest);
155         dislocated_files[i[7]] = dest;
156         # Add per-arch symlinks for arch: all debs
157         if architecture == "all":
158             for arch in architectures:
159                 dest = "%sdists/%s/%s/binary-%s/%s%s_%s.deb" % (Cnf["Dir::Root"], codename, component, arch, section, package, version);
160                 if not os.path.exists(dest):
161                     if Cnf.Find("Claire::Options::Verbose"):
162                         print src+' -> '+dest
163                     os.symlink(src, dest);
164
165     return dislocated_files
166
167 ################################################################################
168
169 def main ():
170     global Cnf, projectB;
171
172     Cnf = utils.get_conf()
173
174     Arguments = [('h',"help","Claire::Options::Help"),
175                  ('v',"verbose","Claire::Options::Verbose")];
176     for i in ["help", "verbose" ]:
177         if not Cnf.has_key("Claire::Options::%s" % (i)):
178             Cnf["Claire::Options::%s" % (i)] = "";
179
180     apt_pkg.ParseCommandLine(Cnf,Arguments,sys.argv);
181     Options = Cnf.SubTree("Claire::Options")
182
183     if Options["Help"]:
184         usage();
185
186     projectB = pg.connect(Cnf["DB::Name"], Cnf["DB::Host"], int(Cnf["DB::Port"]));
187
188     db_access.init(Cnf, projectB);
189
190     find_dislocated_stable(Cnf, projectB);
191
192 #######################################################################################
193
194 if __name__ == '__main__':
195     main();
196