]> git.decadent.org.uk Git - dak.git/blob - daklib/ls.py
Add by-hash support
[dak.git] / daklib / ls.py
1 """List packages according to various criteria
2
3 @copyright: 2014, Ansgar Burchardt <ansgar@debian.org>
4 @license: GPL-2+
5 """
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 import sqlalchemy.sql as sql
22 import daklib.daksql as daksql
23
24 from daklib.dbconn import DBConn
25 from collections import defaultdict
26
27 def list_packages(packages, suites=None, components=None, architectures=None, binary_types=None,
28                   source_and_binary=False, regex=False,
29                   format=None, highest=None):
30     session = DBConn().session()
31     try:
32         t = DBConn().view_package_list
33
34         comparison_operator = "~" if regex else "="
35
36         where = sql.false()
37         for package in packages:
38             where = where | t.c.package.op(comparison_operator)(package)
39             if source_and_binary:
40                 where = where | t.c.source.op(comparison_operator)(package)
41
42         if suites is not None:
43             where = where & (t.c.suite.in_(suites) | t.c.codename.in_(suites))
44         if components is not None:
45             where = where & t.c.component.in_(components)
46         if architectures is not None:
47             where = where & t.c.architecture.in_(architectures)
48         if binary_types is not None:
49             where = where & t.c.type.in_(binary_types)
50
51         if format is None:
52             c_architectures = daksql.string_agg(t.c.architecture, ', ', order_by=[t.c.architecture_is_source.desc(), t.c.architecture])
53             query = sql.select([t.c.package, t.c.version, t.c.display_suite, c_architectures]) \
54                        .where(where) \
55                        .group_by(t.c.package, t.c.version, t.c.display_suite) \
56                        .order_by(t.c.package, t.c.version, t.c.display_suite)
57             result = session.execute(query).fetchall()
58
59             if len(result) == 0:
60                 raise StopIteration
61
62             lengths = {
63                 'package': max(10, max(len(row[t.c.package]) for row in result)),
64                 'version': max(13, max(len(row[t.c.version]) for row in result)),
65                 'suite':   max(10, max(len(row[t.c.display_suite]) for row in result))
66             }
67             format = "{0:{lengths[package]}} | {1:{lengths[version]}} | {2:{lengths[suite]}} | {3}"
68
69             for row in result:
70                 yield format.format(row[t.c.package], row[t.c.version], row[t.c.display_suite], row[c_architectures], lengths=lengths)
71         elif format in ('control-suite', 'heidi'):
72             query = sql.select([t.c.package, t.c.version, t.c.architecture]).where(where)
73             result = session.execute(query)
74             for row in result:
75                 yield "{0} {1} {2}".format(row[t.c.package], row[t.c.version], row[t.c.architecture])
76         elif format == "python":
77             c_architectures = daksql.string_agg(t.c.architecture, ',', order_by=[t.c.architecture_is_source.desc(), t.c.architecture])
78             query = sql.select([t.c.package,
79                                 t.c.version,
80                                 t.c.display_suite,
81                                 c_architectures,
82                                 t.c.source,
83                                 t.c.source_version,
84                                 t.c.component]) \
85                 .where(where) \
86                 .group_by(t.c.package,
87                           t.c.version,
88                           t.c.display_suite,
89                           t.c.source,
90                           t.c.component,
91                           t.c.source_version)
92             result = session.execute(query).fetchall()
93
94             if len(result) == 0:
95                 raise StopIteration
96
97             val = lambda: defaultdict(val)
98             ret = val()
99             for row in result:
100                 ret[row[t.c.package]] \
101                    [row[t.c.display_suite]] \
102                    [row[t.c.version]]={'component':      row[t.c.component],
103                                        'architectures':  row[c_architectures].split(','),
104                                        'source':         row[t.c.source],
105                                        'source_version': row[t.c.source_version]
106                                    }
107
108             yield ret
109             return
110         else:
111             raise ValueError("Unknown output format requested.")
112
113         if highest is not None:
114             query = sql.select([t.c.package, sql.func.max(t.c.version)]).where(where) \
115                        .group_by(t.c.package).order_by(t.c.package)
116             result = session.execute(query)
117             yield ""
118             for row in result:
119                 yield "{0} ({1} {2})".format(row[0], highest, row[1])
120     finally:
121         session.close()