- wrong-file-owner-uid-or-gid
- install-info-used-in-maintainer-script
- missing-pre-dependency-on-multiarch-support
+ - bad-perm-for-file-in-etc-sudoers.d
fatal:
- debian-control-file-uses-obsolete-national-encoding
- malformed-deb-archive
- dir-or-file-in-mnt
- dir-or-file-in-opt
- dir-or-file-in-srv
+ - udeb-uses-non-gzip-data-tarball
FROM binaries b, bin_associations ba, architecture a
WHERE ba.suite = :suiteid
AND ba.bin = b.id AND b.architecture = a.id""", {'suiteid': suite_id})
- for i in q.fetchall():
- key = " ".join(i[:3])
+ for i in q:
+ key = i[:3]
current[key] = i[3]
- q = session.execute("""SELECT s.source, s.version, sa.id
+ q = session.execute("""SELECT s.source, s.version, 'source', sa.id
FROM source s, src_associations sa
WHERE sa.suite = :suiteid
AND sa.source = s.id""", {'suiteid': suite_id})
- for i in q.fetchall():
- key = " ".join(i[:2]) + " source"
- current[key] = i[2]
+ for i in q:
+ key = i[:3]
+ current[key] = i[3]
# Build up a dictionary of what should be in the suite
- desired = {}
+ desired = set()
for line in lines:
split_line = line.strip().split()
if len(split_line) != 3:
utils.warn("'%s' does not break into 'package version architecture'." % (line[:-1]))
continue
- key = " ".join(split_line)
- desired[key] = ""
+ desired.add(tuple(split_line))
# Check to see which packages need added and add them
- for key in sorted(desired.keys(), cmp=cmp_package_version):
- if not current.has_key(key):
- (package, version, architecture) = key.split()
+ for key in sorted(desired, cmp=cmp_package_version):
+ if key not in current:
+ (package, version, architecture) = key
version_checks(package, architecture, suite.suite_name, version, session, force)
pkid = get_id (package, version, architecture, session)
if not pkid:
else:
session.execute("""INSERT INTO bin_associations (suite, bin)
VALUES (:suiteid, :pkid)""", {'suiteid': suite_id, 'pkid': pkid})
- Logger.log(["added", key, pkid])
+ Logger.log(["added", " ".join(key), pkid])
# Check to see which packages need removed and remove them
- for key in current.keys():
- if not desired.has_key(key):
- (package, version, architecture) = key.split()
- pkid = current[key]
+ for key, pkid in current.iteritems():
+ if key not in desired:
+ (package, version, architecture) = key
if architecture == "source":
session.execute("""DELETE FROM src_associations WHERE id = :pkid""", {'pkid': pkid})
else:
session.execute("""DELETE FROM bin_associations WHERE id = :pkid""", {'pkid': pkid})
- Logger.log(["removed", key, pkid])
+ Logger.log(["removed", " ".join(key), pkid])
session.commit()
# coding=utf8
"""
-Add suite options for overrides and control-suite to DB
+Add support for Description-md5
@contact: Debian FTP Master <ftpmaster@debian.org>
-@copyright: 2011 Mark Hymers <mhy@debian.org>
+@copyright: 2011 Ansgar Burchardt <ansgar@debian.org>
@license: GNU General Public License version 2 or later
"""
################################################################################
def do_update(self):
"""
- Add suite options for overrides and control-suite to DB
+ Add support for Description-md5
"""
print __doc__
try:
c = self.db.cursor()
- c.execute("ALTER TABLE suite ADD COLUMN overrideprocess BOOLEAN NOT NULL DEFAULT FALSE")
- c.execute("COMMENT ON COLUMN suite.overrideprocess IS %s", ['If true, check-overrides will process the suite by default'])
- c.execute("ALTER TABLE suite ADD COLUMN overrideorigin TEXT DEFAULT NULL")
- c.execute("COMMENT ON COLUMN suite.overrideprocess IS %s", ['If NOT NULL, check-overrides will take missing overrides from the named suite'])
-
- # Migrate config file values into database
- if cnf.has_key("Check-Overrides::OverrideSuites"):
- for suitename in cnf.SubTree("Check-Overrides::OverrideSuites").List():
- if cnf.get("Check-Overrides::OverrideSuites::%s::Process" % suitename, "0") == "1":
- print "Marking %s to have overrides processed automatically" % suitename.lower()
- c.execute("UPDATE suite SET overrideprocess = TRUE WHERE suite_name = %s", [suitename.lower()])
-
- originsuite = cnf.get("Check-Overrides::OverrideSuites::%s::OriginSuite" % suitename, '')
- if originsuite != '':
- print "Setting %s to use %s as origin for overrides" % (suitename.lower(), originsuite.lower())
- c.execute("UPDATE suite SET overrideorigin = %s WHERE suite_name = %s", [originsuite.lower(), suitename.lower()])
-
- c.execute("ALTER TABLE suite ADD COLUMN allowcsset BOOLEAN NOT NULL DEFAULT FALSE")
- c.execute("COMMENT ON COLUMN suite.allowcsset IS %s", ['Allow control-suite to be used with the --set option without forcing'])
-
- # Import historical hard-coded values
- c.execute("UPDATE suite SET allowcsset = TRUE WHERE suite_name IN ('testing', 'squeeze-updates')")
+ c.execute("""CREATE OR REPLACE FUNCTION public.add_missing_description_md5()
+ RETURNS VOID
+ VOLATILE
+ LANGUAGE plpgsql
+AS $function$
+DECLARE
+ description_key_id metadata_keys.key_id%TYPE;
+ description_md5_key_id metadata_keys.key_id%TYPE;
+ BEGIN
+ SELECT key_id INTO STRICT description_key_id FROM metadata_keys WHERE key='Description';
+ SELECT key_id INTO description_md5_key_id FROM metadata_keys WHERE key='Description-md5';
+ IF NOT FOUND THEN
+ INSERT INTO metadata_keys (key) VALUES ('Description-md5') RETURNING key_id INTO description_md5_key_id;
+ END IF;
+
+ INSERT INTO binaries_metadata
+ (bin_id, key_id, value)
+ SELECT
+ bm.bin_id AS bin_id,
+ description_md5_key_id AS key_id,
+ MD5(bm.value || E'\n') AS value
+ FROM binaries_metadata AS bm
+ WHERE
+ bm.key_id = description_key_id
+ AND
+ NOT EXISTS (SELECT 1 FROM binaries_metadata AS bm2 WHERE bm.bin_id = bm2.bin_id AND bm2.key_id = description_md5_key_id);
+END;
+$function$""")
+
+ c.execute("ALTER TABLE suite ADD COLUMN include_long_description BOOLEAN NOT NULL DEFAULT 't'")
c.execute("UPDATE config SET value = '69' WHERE name = 'db_revision'")
self.db.commit()
- except psycopg2.ProgrammingError as msg:
+ except psycopg2.ProgrammingError, msg:
self.db.rollback()
raise DBUpdateError('Unable to apply sick update 69, rollback issued. Error message : %s' % (str(msg)))
--- /dev/null
+#!/usr/bin/env python
+# coding=utf8
+
+"""
+Add suite options for overrides and control-suite to DB
+
+@contact: Debian FTP Master <ftpmaster@debian.org>
+@copyright: 2011 Mark Hymers <mhy@debian.org>
+@license: GNU General Public License version 2 or later
+"""
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+################################################################################
+
+import psycopg2
+from daklib.dak_exceptions import DBUpdateError
+from daklib.config import Config
+
+################################################################################
+def do_update(self):
+ """
+ Add suite options for overrides and control-suite to DB
+ """
+ print __doc__
+ try:
+ cnf = Config()
+
+ c = self.db.cursor()
+
+ c.execute("ALTER TABLE suite ADD COLUMN overrideprocess BOOLEAN NOT NULL DEFAULT FALSE")
+ c.execute("COMMENT ON COLUMN suite.overrideprocess IS %s", ['If true, check-overrides will process the suite by default'])
+ c.execute("ALTER TABLE suite ADD COLUMN overrideorigin TEXT DEFAULT NULL")
+ c.execute("COMMENT ON COLUMN suite.overrideprocess IS %s", ['If NOT NULL, check-overrides will take missing overrides from the named suite'])
+
+ # Migrate config file values into database
+ if cnf.has_key("Check-Overrides::OverrideSuites"):
+ for suitename in cnf.SubTree("Check-Overrides::OverrideSuites").List():
+ if cnf.get("Check-Overrides::OverrideSuites::%s::Process" % suitename, "0") == "1":
+ print "Marking %s to have overrides processed automatically" % suitename.lower()
+ c.execute("UPDATE suite SET overrideprocess = TRUE WHERE suite_name = %s", [suitename.lower()])
+
+ originsuite = cnf.get("Check-Overrides::OverrideSuites::%s::OriginSuite" % suitename, '')
+ if originsuite != '':
+ print "Setting %s to use %s as origin for overrides" % (suitename.lower(), originsuite.lower())
+ c.execute("UPDATE suite SET overrideorigin = %s WHERE suite_name = %s", [originsuite.lower(), suitename.lower()])
+
+ c.execute("ALTER TABLE suite ADD COLUMN allowcsset BOOLEAN NOT NULL DEFAULT FALSE")
+ c.execute("COMMENT ON COLUMN suite.allowcsset IS %s", ['Allow control-suite to be used with the --set option without forcing'])
+
+ # Import historical hard-coded values
+ c.execute("UPDATE suite SET allowcsset = TRUE WHERE suite_name IN ('testing', 'squeeze-updates')")
+
+ c.execute("UPDATE config SET value = '70' WHERE name = 'db_revision'")
+ self.db.commit()
+
+ except psycopg2.ProgrammingError as msg:
+ self.db.rollback()
+ raise DBUpdateError('Unable to apply sick update 70, rollback issued. Error message : %s' % (str(msg)))
Default: All suites not marked 'untouchable'
-f, --force Allow processing of untouchable suites
CAREFUL: Only to be used at point release time!
+ -5, --description-md5 Allow to use Description-md5 instead of
+ Description for Packages index and generate
+ Translation-en
+ NOTE: suite.include_long_descriptions needs to
+ be set to false for this.
-h, --help show this help and exit
SUITE can be a space seperated list, e.g.
#############################################################################
-# We currently filter out the "Tag" line. They are set by external overrides and
-# NOT by the maintainer. And actually having it set by maintainer means we output
-# it twice at the moment -> which breaks dselect.
# Here be large dragons.
_packages_query = R"""
WITH
JOIN metadata_keys mk ON mk.key_id = bm.key_id
WHERE
bm.bin_id = tmp.binary_id
- AND key != 'Section' AND key != 'Priority' AND key != 'Tag'
+ AND key != ALL (:metadata_skip)
)
|| COALESCE(E'\n' || (SELECT
STRING_AGG(key || '\: ' || value, E'\n' ORDER BY key)
ORDER BY tmp.source, tmp.package, tmp.version
"""
-def generate_packages(suite_id, component_id, architecture_id, type_name):
+def generate_packages(suite_id, component_id, architecture_id, type_name, use_description_md5):
global _packages_query
from daklib.filewriter import PackagesFileWriter
from daklib.dbconn import Architecture, Component, DBConn, OverrideType, Suite
overridesuite_id = suite.get_overridesuite().suite_id
+ # We currently filter out the "Tag" line. They are set by external
+ # overrides and NOT by the maintainer. And actually having it set by
+ # maintainer means we output it twice at the moment -> which breaks
+ # dselect.
+ metadata_skip = ["Section", "Priority", "Tag"]
+ if suite.include_long_description or not use_description_md5:
+ metadata_skip.append("Description-md5")
+ else:
+ metadata_skip.append("Description")
+
writer = PackagesFileWriter(suite=suite.suite_name, component=component.component_name,
architecture=architecture.arch_string, debtype=type_name)
output = writer.open()
r = session.execute(_packages_query, {"suite": suite_id, "component": component_id,
"arch": architecture_id, "type_id": type_id, "type_name": type_name, "arch_all": arch_all_id,
- "overridesuite": overridesuite_id})
+ "overridesuite": overridesuite_id, "metadata_skip": metadata_skip})
for (stanza,) in r:
print >>output, stanza
print >>output, ""
#############################################################################
+_translations_query = """
+SELECT
+ 'Package\: ' || b.package
+ || E'\nDescription-md5\: ' || bm_description_md5.value
+ || E'\nDescription-en\: ' || bm_description.value
+ || E'\n'
+FROM binaries b
+ -- join tables for suite and component
+ JOIN bin_associations ba ON b.id = ba.bin
+ JOIN override o ON b.package = o.package AND o.suite = :suite AND o.type = (SELECT id FROM override_type WHERE type = 'deb')
+
+ -- join tables for Description and Description-md5
+ JOIN binaries_metadata bm_description ON b.id = bm_description.bin_id AND bm_description.key_id = (SELECT key_id FROM metadata_keys WHERE key = 'Description')
+ JOIN binaries_metadata bm_description_md5 ON b.id = bm_description_md5.bin_id AND bm_description_md5.key_id = (SELECT key_id FROM metadata_keys WHERE key = 'Description-md5')
+
+ -- we want to sort by source name
+ JOIN source s ON b.source = s.id
+
+WHERE ba.suite = :suite AND o.component = :component
+GROUP BY s.source, b.package, bm_description_md5.value, bm_description.value
+ORDER BY s.source, b.package, bm_description_md5.value
+"""
+
+def generate_translations(suite_id, component_id):
+ global _translations_query
+ from daklib.filewriter import TranslationFileWriter
+ from daklib.dbconn import DBConn, Suite, Component
+ from daklib.dakmultiprocessing import PROC_STATUS_SUCCESS
+
+ session = DBConn().session()
+ suite = session.query(Suite).get(suite_id)
+ component = session.query(Component).get(component_id)
+
+ writer = TranslationFileWriter(suite=suite.suite_name, component=component.component_name, language="en")
+ output = writer.open()
+
+ r = session.execute(_translations_query, {"suite": suite_id, "component": component_id})
+ for (stanza,) in r:
+ print >>output, stanza
+
+ writer.close()
+
+ message = ["generate-translations", suite.suite_name, component.component_name]
+ session.rollback()
+ return (PROC_STATUS_SUCCESS, message)
+
+#############################################################################
+
def main():
from daklib.dakmultiprocessing import DakProcessPool, PROC_STATUS_SUCCESS, PROC_STATUS_SIGNALRAISED
pool = DakProcessPool()
cnf = Config()
Arguments = [('h',"help","Generate-Packages-Sources::Options::Help"),
+ ('5','description-md5',"Generate-Packages-Sources::Options::Description-md5"),
('s',"suite","Generate-Packages-Sources::Options::Suite"),
('f',"force","Generate-Packages-Sources::Options::Force")]
logger = daklog.Logger('generate-packages-sources2')
session = DBConn().session()
+ session.execute("SELECT add_missing_description_md5()")
+ session.commit()
if Options.has_key("Suite"):
suites = []
else:
suites = session.query(Suite).filter(Suite.untouchable == False).all()
+ use_description_md5 = Options.has_key("Description-md5") and Options["Description-md5"]
force = Options.has_key("Force") and Options["Force"]
component_ids = [ c.component_id for c in session.query(Component).all() ]
utils.fubar("Refusing to touch %s (untouchable and not forced)" % s.suite_name)
for c in component_ids:
pool.apply_async(generate_sources, [s.suite_id, c], callback=parse_results)
+ if use_description_md5 and not s.include_long_description:
+ pool.apply_async(generate_translations, [s.suite_id, c], callback=parse_results)
for a in s.architectures:
if a == 'source':
continue
- pool.apply_async(generate_packages, [s.suite_id, c, a.arch_id, 'deb'], callback=parse_results)
- pool.apply_async(generate_packages, [s.suite_id, c, a.arch_id, 'udeb'], callback=parse_results)
+ pool.apply_async(generate_packages, [s.suite_id, c, a.arch_id, 'deb', use_description_md5], callback=parse_results)
+ pool.apply_async(generate_packages, [s.suite_id, c, a.arch_id, 'udeb', use_description_md5], callback=parse_results)
pool.close()
pool.join()
'suite_id': dbsuite.suite_id,
'metakey_d_id': metakey_d.key_id,
'metakey_p_id': metakey_p.key_id,
- 'arch_all_id' : get_architecture('all', session).arch_id,
}
- for architecture in all_arches:
+ for architecture in all_arches | set(['all']):
deps = {}
sources = {}
virtual_packages = {}
params['arch_id'] = get_architecture(architecture, session).arch_id
statement = '''
- WITH suite_binaries AS
- (select b.id, b.package, b.source, b.file
- from binaries b WHERE b.id in
- (SELECT bin FROM bin_associations WHERE suite = :suite_id)
- AND b.architecture in (:arch_id, :arch_all_id))
SELECT b.id, b.package, s.source, c.name as component,
- bmd.value as depends, bmp.value as provides
- FROM suite_binaries b
- LEFT OUTER JOIN binaries_metadata bmd
- ON b.id = bmd.bin_id AND bmd.key_id = :metakey_d_id
- LEFT OUTER JOIN binaries_metadata bmp
- ON b.id = bmp.bin_id AND bmp.key_id = :metakey_p_id
+ (SELECT bmd.value FROM binaries_metadata bmd WHERE bmd.bin_id = b.id AND bmd.key_id = :metakey_d_id) AS depends,
+ (SELECT bmp.value FROM binaries_metadata bmp WHERE bmp.bin_id = b.id AND bmp.key_id = :metakey_p_id) AS provides
+ FROM binaries b
+ JOIN bin_associations ba ON b.id = ba.bin AND ba.suite = :suite_id
JOIN source s ON b.source = s.id
JOIN files f ON b.file = f.id
JOIN location l ON f.location = l.id
- JOIN component c ON l.component = c.id'''
- session.rollback()
+ JOIN component c ON l.component = c.id
+ WHERE b.architecture = :arch_id'''
query = session.query('id', 'package', 'source', 'component', 'depends', 'provides'). \
from_statement(statement).params(params)
for binary_id, package, source, component, depends, provides in query:
for source, bindict in sorted(all_broken.items()):
lines = []
for binary, arches in sorted(bindict.items()):
- if arches == all_arches:
+ if arches == all_arches or 'all' in arches:
lines.append(binary)
else:
lines.append('%s [%s]' % (binary, ' '.join(sorted(arches))))
flags.update(keywords)
template = "dists/%(suite)s/%(component)s/source/Sources"
BaseFileWriter.__init__(self, template, **flags)
+
+class TranslationFileWriter(BaseFileWriter):
+ def __init__(self, **keywords):
+ '''
+ The value of the keywords suite, component and language are strings.
+ Output files are bzip2 compressed only.
+ '''
+ flags = {
+ 'uncompressed': False,
+ 'gzip': False,
+ 'bzip2': True,
+ 'language': 'en',
+ }
+ flags.update(keywords)
+ template = "dists/%(suite)s/%(component)s/i18n/Translation-%(language)s"
+ super(TranslationFileWriter, self).__init__(template, **flags)