Merge lp:~lifeless/launchpad/bug-618406 into lp:launchpad

Proposed by Robert Collins
Status: Rejected
Rejected by: Robert Collins
Proposed branch: lp:~lifeless/launchpad/bug-618406
Merge into: lp:launchpad
Diff against target: 5399 lines (+2369/-742)
98 files modified
configs/development/launchpad-lazr.conf (+0/-4)
configs/testrunner/launchpad-lazr.conf (+0/-3)
database/sampledata/current-dev.sql (+149/-113)
database/sampledata/current.sql (+144/-109)
database/schema/comments.sql (+4/-3)
database/schema/launchpad_session.sql (+25/-0)
database/schema/patch-2208-51-0.sql (+18/-0)
database/schema/patch-2208-52-0.sql (+14/-0)
database/schema/patch-2208-53-0.sql (+20/-0)
database/schema/patch-2208-54-0.sql (+6/-0)
database/schema/patch-2208-55-0.sql (+24/-0)
database/schema/patch-2208-56-0.sql (+33/-0)
database/schema/patch-2208-57-1.sql (+14/-0)
database/schema/patch-2208-59-0.sql (+38/-0)
database/schema/security.cfg (+6/-0)
database/schema/security.py (+182/-99)
database/schema/trusted.sql (+14/-0)
lib/canonical/config/schema-lazr.conf (+5/-8)
lib/canonical/launchpad/database/message.py (+2/-0)
lib/canonical/launchpad/interfaces/message.py (+2/-0)
lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt (+1/-1)
lib/canonical/launchpad/pagetests/webservice/xx-hide-comments.txt (+2/-2)
lib/canonical/launchpad/security.py (+23/-8)
lib/canonical/launchpad/zcml/message.zcml (+4/-3)
lib/lp/app/stories/launchpad-root/site-search.txt (+5/-3)
lib/lp/archivepublisher/config.py (+8/-7)
lib/lp/archivepublisher/deathrow.py (+2/-7)
lib/lp/archivepublisher/interfaces/publisherconfig.py (+58/-0)
lib/lp/archivepublisher/model/publisherconfig.py (+68/-0)
lib/lp/archivepublisher/publishing.py (+1/-6)
lib/lp/archivepublisher/tests/test_publisherconfig.py (+92/-0)
lib/lp/archivepublisher/zcml/configure.zcml (+25/-1)
lib/lp/bugs/browser/bugcomment.py (+1/-1)
lib/lp/bugs/configure.zcml (+5/-1)
lib/lp/bugs/doc/bugmessage-visibility.txt (+9/-8)
lib/lp/bugs/doc/bugnotification-sending.txt (+9/-3)
lib/lp/bugs/enum.py (+4/-4)
lib/lp/bugs/interfaces/bug.py (+1/-1)
lib/lp/bugs/interfaces/bugmessage.py (+0/-2)
lib/lp/bugs/mail/bugnotificationrecipients.py (+11/-0)
lib/lp/bugs/model/bug.py (+1/-1)
lib/lp/bugs/model/bugmessage.py (+0/-1)
lib/lp/bugs/model/bugnotification.py (+11/-0)
lib/lp/bugs/model/structuralsubscription.py (+4/-3)
lib/lp/bugs/security.py (+2/-7)
lib/lp/bugs/stories/bugs/xx-bug-hidden-comments.txt (+1/-1)
lib/lp/bugs/tests/test_bug_messages_webservice.py (+1/-1)
lib/lp/code/model/tests/test_recipebuilder.py (+2/-2)
lib/lp/registry/adapters.py (+10/-0)
lib/lp/registry/browser/configure.zcml (+8/-8)
lib/lp/registry/browser/distribution.py (+75/-2)
lib/lp/registry/browser/distroseries.py (+70/-28)
lib/lp/registry/browser/tests/test_distribution_views.py (+167/-0)
lib/lp/registry/browser/tests/test_series_views.py (+127/-8)
lib/lp/registry/configure.zcml (+8/-1)
lib/lp/registry/doc/distroseries.txt (+8/-4)
lib/lp/registry/interfaces/distribution.py (+7/-2)
lib/lp/registry/interfaces/distroseries.py (+7/-2)
lib/lp/registry/interfaces/distroseriesdifference.py (+7/-3)
lib/lp/registry/model/distribution.py (+10/-5)
lib/lp/registry/model/distroseries.py (+8/-3)
lib/lp/registry/model/distroseriesdifference.py (+13/-7)
lib/lp/registry/stories/distribution/xx-distribution-launchpad-usage.txt (+24/-1)
lib/lp/registry/stories/distribution/xx-distribution-overview.txt (+3/-1)
lib/lp/registry/stories/distroseries/xx-distroseries-index.txt (+3/-1)
lib/lp/registry/stories/distroseries/xx-reassign-distroseries.txt (+0/-72)
lib/lp/registry/stories/webservice/xx-distribution.txt (+1/-0)
lib/lp/registry/stories/webservice/xx-distroseries.txt (+2/-1)
lib/lp/registry/templates/distribution-index.pt (+2/-2)
lib/lp/registry/templates/distroseries-index.pt (+2/-5)
lib/lp/registry/templates/distroseries-localdifferences.pt (+9/-0)
lib/lp/registry/templates/packagesearch-macros.pt (+3/-6)
lib/lp/registry/tests/test_distribution.py (+111/-3)
lib/lp/registry/tests/test_distributionsourcepackage.py (+2/-1)
lib/lp/registry/tests/test_distroseries.py (+9/-0)
lib/lp/registry/tests/test_pillarname_triggers.py (+10/-7)
lib/lp/scripts/garbo.py (+86/-8)
lib/lp/scripts/tests/test_garbo.py (+161/-4)
lib/lp/scripts/utilities/sanitizedb.py (+16/-3)
lib/lp/services/configure.zcml (+1/-0)
lib/lp/services/session/adapters.py (+40/-0)
lib/lp/services/session/configure.zcml (+12/-0)
lib/lp/services/session/interfaces.py (+15/-0)
lib/lp/services/session/model.py (+47/-0)
lib/lp/services/session/tests/test_session.py (+32/-0)
lib/lp/soyuz/doc/archive-dependencies.txt (+73/-73)
lib/lp/soyuz/doc/archive.txt (+8/-5)
lib/lp/soyuz/doc/distroseriesqueue-translations.txt (+30/-30)
lib/lp/soyuz/doc/publishing.txt (+5/-2)
lib/lp/soyuz/interfaces/distroarchseries.py (+3/-1)
lib/lp/soyuz/model/archive.py (+5/-4)
lib/lp/soyuz/scripts/tests/test_publishdistro.py (+8/-3)
lib/lp/soyuz/stories/distroseries/add-architecture.txt (+10/-0)
lib/lp/soyuz/tests/test_packageupload.py (+16/-8)
lib/lp/testing/factory.py (+31/-5)
lib/lp/testing/tests/test_standard_test_template.py (+5/-4)
lib/lp/translations/browser/tests/test_sharing_information.py (+6/-4)
utilities/soyuz-sampledata-setup.py (+2/-2)
To merge this branch: bzr merge lp:~lifeless/launchpad/bug-618406
Reviewer Review Type Date Requested Status
Launchpad code reviewers Pending
Review via email: mp+55303@code.launchpad.net

Commit message

Add a bugtask heat column which mirrors bug.heat allowing in-bugtask sorting of heat based queries.

Description of the change

Add a bugtask heat column which mirrors bug.heat allowing in-bugtask sorting of heat based queries.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configs/development/launchpad-lazr.conf'
2--- configs/development/launchpad-lazr.conf 2011-03-18 01:17:42 +0000
3+++ configs/development/launchpad-lazr.conf 2011-03-29 10:32:58 +0000
4@@ -5,10 +5,6 @@
5 [meta]
6 extends: ../../lib/canonical/config/schema-lazr.conf
7
8-[archivepublisher]
9-root: /var/tmp/archive
10-base_url: http://archive.launchpad.dev/
11-
12 [branchscanner]
13 oops_prefix: BS
14 error_dir: /var/tmp/codehosting.test
15
16=== modified file 'configs/testrunner/launchpad-lazr.conf'
17--- configs/testrunner/launchpad-lazr.conf 2011-02-25 19:27:05 +0000
18+++ configs/testrunner/launchpad-lazr.conf 2011-03-29 10:32:58 +0000
19@@ -8,9 +8,6 @@
20 [canonical]
21 cron_control_url: file:lib/lp/services/scripts/tests/cronscripts.ini
22
23-[archivepublisher]
24-base_url: http://ftpmaster.internal/
25-
26 [branchscanner]
27 oops_prefix: TSMS
28 error_dir: /var/tmp/lperr.test
29
30=== modified file 'database/sampledata/current-dev.sql'
31--- database/sampledata/current-dev.sql 2011-03-29 00:11:57 +0000
32+++ database/sampledata/current-dev.sql 2011-03-29 10:32:58 +0000
33@@ -837,6 +837,12 @@
34
35
36
37+
38+
39+
40+
41+
42+
43 SET SESSION AUTHORIZATION DEFAULT;
44
45 ALTER TABLE account DISABLE TRIGGER ALL;
46@@ -1879,21 +1885,21 @@
47
48 ALTER TABLE distroseries DISABLE TRIGGER ALL;
49
50-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (1, 1, 'warty', 'The Warty Warthog Release', 'Warty was the first stable release of Ubuntu. Key feature goals included releasing on time, with the latest version of the Gnome Desktop Environment, and the creation of all the infrastructure required to manage Ubuntu itself. Warty includes excellent support for Python, with most of the widely used Python libraries installed by default.', '4.10', 4, '2004-08-20 00:00:00', NULL, 17, 'Warty is the first release of Ubuntu, with a planned release date of October 2004.', 'Warty', NULL, 0, 1, 'warty-changes@ubuntu.com', 4, 3, NULL, '2006-10-16 18:31:43.475428', false, false, NULL, NULL, NULL, false);
51-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (2, 2, 'six', 'Six Six Six', 'some text to describe the whole 666 release of RH', '6.0.1', 4, '2004-03-21 00:00:00', NULL, 8, 'some text to describe the whole 666 release of RH', 'Six', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.482603', false, false, NULL, NULL, NULL, false);
52-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (3, 1, 'hoary', 'The Hoary Hedgehog Release', 'Hoary is the second release of Ubuntu. Key feature goals include the integration of Hoary with the Launchpad for bugs and translation information, as well as Gnome 2.10 and the X.org window system.', '5.04', 2, NULL, 1, 1, 'Hoary is the second released of Ubuntu, with release planned for April 2005.', 'Hoary', NULL, 96, 6, 'hoary-changes@ubuntu.com', 1, 4, NULL, '2006-10-16 18:31:43.483559', false, false, NULL, NULL, NULL, false);
53-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (4, 2, '7.0', 'Seven', 'The release that we would not expect', '7.0.1', 3, NULL, 2, 7, 'The release that we would not expect', '7.0', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.484426', false, false, NULL, NULL, NULL, false);
54-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (5, 1, 'grumpy', 'The Grumpy Groundhog Release', 'Grumpy, the third release of Ubuntu Linux, is not yet in active development. This information is purely a placeholder.', '5.10', 1, NULL, 1, 1, 'Grumpy is the third release of Ubuntu, planned for October 2005.', 'Grumpy', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.485233', false, false, NULL, NULL, NULL, false);
55-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (6, 3, 'woody', 'WOODY', 'WOODY is the current stable verison of Debian GNU/Linux', '3.0', 4, '2003-01-01 00:00:00', NULL, 2, 'WOODY is the current stable verison of Debian GNU/Linux', 'Woody', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.486054', false, false, NULL, NULL, NULL, false);
56-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (7, 3, 'sarge', 'Sarge', 'Sarge is the FROZEN unstable version of Debian GNU/Linux.', '3.1', 3, NULL, 6, 5, 'Sarge is the FROZEN unstable version of Debian GNU/Linux.', 'Sarge', NULL, 0, NULL, NULL, 0, 0, 6, '2006-10-16 18:31:43.486972', false, false, NULL, NULL, NULL, false);
57-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (8, 3, 'sid', 'Sid', 'Sid is the CRAZY unstable version of Debian GNU/Linux.', '3.2', 1, NULL, 6, 6, 'Sid is the CRAZY unstable version of Debian GNU/Linux.', 'Sid', NULL, 0, NULL, NULL, 0, 1, NULL, '2006-10-16 18:31:43.487779', false, false, NULL, NULL, NULL, false);
58-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (9, 7, '2k5', 'Guada 2005', 'This release places extra emphasis on usability and installability. The installer is adapted from Ubuntu to assume your country, language, keyboard and time zone preference, thus ensuring that installs ask the minimum number of questions possible.', '2005', 2, NULL, 3, 4, 'Guada 2005 is a rapid-install version of
59-Ubuntu Hoary for the Andalucian marketplace.', 'Guada2005', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.488598', false, false, NULL, NULL, NULL, false);
60-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (10, 1, 'breezy-autotest', 'Breezy Badger Autotest', 'Autotest version of Breezy', '6.6.6', 1, NULL, 3, 1, 'Autosync uploader test', 'Breezy Badger Autotest', NULL, 0, 8, 'autotest_changes@ubuntu.com', 0, 0, NULL, '2006-10-16 18:31:43.489468', false, false, NULL, NULL, NULL, false);
61-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (11, 8, 'breezy-autotest', 'Breezy Badger Autotest', 'Autotest version of Breezy', '6.6.6', 1, NULL, 1, 1, 'Autosync uploader test', 'Breezy Badger Autotest', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.490333', false, false, NULL, NULL, NULL, false);
62-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (12, 5, 'krunch', 'The Krunchy Kangaroo', 'The archive split allows us to use different kernel settings for Kubuntu, as well as make other pervasive low-level fixes, and release on our own schedule.', '8.06', 1, NULL, 3, 1, 'This is the first experimental release of Kubuntu that uses a separate archive from the main Ubuntu release.', 'Krunch', NULL, 0, NULL, NULL, 0, 0, 33, '2006-10-16 18:31:43.491929', false, false, NULL, NULL, NULL, false);
63-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (13, 8, 'hoary-test', 'Mock Hoary', 'nothing special', '9.9.9', 1, NULL, 1, 1, 'summmmmmmary', 'Hoary Mock', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.492845', false, false, NULL, NULL, NULL, false);
64-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (14, 9, 'deriwarty', 'Deriwarty', 'Deriwarty', '1', 1, NULL, 1, 16, 'Deriwarty', 'Deriwarty', NULL, 0, NULL, NULL, 0, 0, NULL, '2011-03-17 14:29:23.190835', true, true, NULL, NULL, NULL, false);
65+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (1, 1, 'warty', 'The Warty Warthog Release', 'Warty was the first stable release of Ubuntu. Key feature goals included releasing on time, with the latest version of the Gnome Desktop Environment, and the creation of all the infrastructure required to manage Ubuntu itself. Warty includes excellent support for Python, with most of the widely used Python libraries installed by default.', '4.10', 4, '2004-08-20 00:00:00', NULL, 'Warty is the first release of Ubuntu, with a planned release date of October 2004.', 'Warty', NULL, 0, 1, 'warty-changes@ubuntu.com', 4, 3, NULL, '2006-10-16 18:31:43.475428', false, false, NULL, NULL, NULL, false, 17);
66+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (2, 2, 'six', 'Six Six Six', 'some text to describe the whole 666 release of RH', '6.0.1', 4, '2004-03-21 00:00:00', NULL, 'some text to describe the whole 666 release of RH', 'Six', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.482603', false, false, NULL, NULL, NULL, false, 8);
67+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (3, 1, 'hoary', 'The Hoary Hedgehog Release', 'Hoary is the second release of Ubuntu. Key feature goals include the integration of Hoary with the Launchpad for bugs and translation information, as well as Gnome 2.10 and the X.org window system.', '5.04', 2, NULL, 1, 'Hoary is the second released of Ubuntu, with release planned for April 2005.', 'Hoary', NULL, 96, 6, 'hoary-changes@ubuntu.com', 1, 4, NULL, '2006-10-16 18:31:43.483559', false, false, NULL, NULL, NULL, false, 1);
68+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (4, 2, '7.0', 'Seven', 'The release that we would not expect', '7.0.1', 3, NULL, 2, 'The release that we would not expect', '7.0', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.484426', false, false, NULL, NULL, NULL, false, 7);
69+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (5, 1, 'grumpy', 'The Grumpy Groundhog Release', 'Grumpy, the third release of Ubuntu Linux, is not yet in active development. This information is purely a placeholder.', '5.10', 1, NULL, 1, 'Grumpy is the third release of Ubuntu, planned for October 2005.', 'Grumpy', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.485233', false, false, NULL, NULL, NULL, false, 1);
70+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (6, 3, 'woody', 'WOODY', 'WOODY is the current stable verison of Debian GNU/Linux', '3.0', 4, '2003-01-01 00:00:00', NULL, 'WOODY is the current stable verison of Debian GNU/Linux', 'Woody', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.486054', false, false, NULL, NULL, NULL, false, 2);
71+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (7, 3, 'sarge', 'Sarge', 'Sarge is the FROZEN unstable version of Debian GNU/Linux.', '3.1', 3, NULL, 6, 'Sarge is the FROZEN unstable version of Debian GNU/Linux.', 'Sarge', NULL, 0, NULL, NULL, 0, 0, 6, '2006-10-16 18:31:43.486972', false, false, NULL, NULL, NULL, false, 5);
72+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (8, 3, 'sid', 'Sid', 'Sid is the CRAZY unstable version of Debian GNU/Linux.', '3.2', 1, NULL, 6, 'Sid is the CRAZY unstable version of Debian GNU/Linux.', 'Sid', NULL, 0, NULL, NULL, 0, 1, NULL, '2006-10-16 18:31:43.487779', false, false, NULL, NULL, NULL, false, 6);
73+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (9, 7, '2k5', 'Guada 2005', 'This release places extra emphasis on usability and installability. The installer is adapted from Ubuntu to assume your country, language, keyboard and time zone preference, thus ensuring that installs ask the minimum number of questions possible.', '2005', 2, NULL, 3, 'Guada 2005 is a rapid-install version of
74+Ubuntu Hoary for the Andalucian marketplace.', 'Guada2005', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.488598', false, false, NULL, NULL, NULL, false, 4);
75+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (10, 1, 'breezy-autotest', 'Breezy Badger Autotest', 'Autotest version of Breezy', '6.6.6', 1, NULL, 3, 'Autosync uploader test', 'Breezy Badger Autotest', NULL, 0, 8, 'autotest_changes@ubuntu.com', 0, 0, NULL, '2006-10-16 18:31:43.489468', false, false, NULL, NULL, NULL, false, 1);
76+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (11, 8, 'breezy-autotest', 'Breezy Badger Autotest', 'Autotest version of Breezy', '6.6.6', 1, NULL, 1, 'Autosync uploader test', 'Breezy Badger Autotest', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.490333', false, false, NULL, NULL, NULL, false, 1);
77+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (12, 5, 'krunch', 'The Krunchy Kangaroo', 'The archive split allows us to use different kernel settings for Kubuntu, as well as make other pervasive low-level fixes, and release on our own schedule.', '8.06', 1, NULL, 3, 'This is the first experimental release of Kubuntu that uses a separate archive from the main Ubuntu release.', 'Krunch', NULL, 0, NULL, NULL, 0, 0, 33, '2006-10-16 18:31:43.491929', false, false, NULL, NULL, NULL, false, 1);
78+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (13, 8, 'hoary-test', 'Mock Hoary', 'nothing special', '9.9.9', 1, NULL, 1, 'summmmmmmary', 'Hoary Mock', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.492845', false, false, NULL, NULL, NULL, false, 1);
79+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (14, 9, 'deriwarty', 'Deriwarty', 'Deriwarty', '1', 1, NULL, 1, 'Deriwarty', 'Deriwarty', NULL, 0, NULL, NULL, 0, 0, NULL, '2011-03-17 14:29:23.190835', true, true, NULL, NULL, NULL, false, 16);
80
81
82 ALTER TABLE distroseries ENABLE TRIGGER ALL;
83@@ -1909,22 +1915,22 @@
84
85 ALTER TABLE distribution DISABLE TRIGGER ALL;
86
87-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (1, 'ubuntu', 'Ubuntu Linux', 'Ubuntu is a new approach to Linux Distribution that includes regular releases, and a simplified single-CD installation system.', 'ubuntulinux.org', 17, 'Ubuntu', 'Ubuntu is a new approach to Linux Distribution that includes regular releases, and a simplified single-CD installation system.', 17, NULL, 1, NULL, true, true, NULL, NULL, 3, 59, NULL, NULL, '2006-10-16 18:31:43.415195', NULL, NULL, NULL, NULL, NULL, true, NULL, true, true, NULL, NULL, NULL, NULL, 20, 20, 20);
88-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (2, 'redhat', 'Redhat Advanced Server', 'Red Hat is a commercial distribution of the GNU/Linux Operating System.', 'redhat.com', 1, 'Red Hat', 'Red Hat is a commercial distribution of the GNU/Linux Operating System.', 1, NULL, 1, NULL, false, false, NULL, 8, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.417928', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10);
89-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (3, 'debian', 'Debian GNU/Linux', 'Debian GNU/Linux is
90+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (1, 'ubuntu', 'Ubuntu Linux', 'Ubuntu is a new approach to Linux Distribution that includes regular releases, and a simplified single-CD installation system.', 'ubuntulinux.org', 17, 'Ubuntu', 'Ubuntu is a new approach to Linux Distribution that includes regular releases, and a simplified single-CD installation system.', 17, NULL, 1, NULL, true, true, NULL, NULL, 3, 59, NULL, NULL, '2006-10-16 18:31:43.415195', NULL, NULL, NULL, NULL, NULL, true, NULL, true, true, NULL, NULL, NULL, NULL, 20, 20, 20, 60);
91+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (2, 'redhat', 'Redhat Advanced Server', 'Red Hat is a commercial distribution of the GNU/Linux Operating System.', 'redhat.com', 1, 'Red Hat', 'Red Hat is a commercial distribution of the GNU/Linux Operating System.', 1, NULL, 1, NULL, false, false, NULL, 8, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.417928', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10, 60);
92+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (3, 'debian', 'Debian GNU/Linux', 'Debian GNU/Linux is
93 a non commercial distribution of a GNU/Linux Operating System for many
94 platforms.', 'debian.org', 1, 'Debian', 'Debian GNU/Linux is
95 a non commercial distribution of a GNU/Linux Operating System for many
96-platforms.', 1, NULL, 1, NULL, false, false, NULL, NULL, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.418942', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10);
97-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (4, 'gentoo', 'The Gentoo Linux', 'Gentoo is a very
98+platforms.', 1, NULL, 1, NULL, false, false, NULL, NULL, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.418942', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10, 60);
99+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (4, 'gentoo', 'The Gentoo Linux', 'Gentoo is a very
100 customizeable GNU/Linux Distribution that is designed to let you build every
101-single package yourself, with your own preferences.', 'gentoo.org', 1, 'Gentoo', 'Gentoo is a very customizeable GNU/Linux Distribution that is designed to let you build every single package yourself, with your own preferences.', 1, NULL, 1, NULL, true, false, NULL, NULL, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.41974', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10);
102-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (5, 'kubuntu', 'Kubuntu - Free KDE-based Linux', 'Kubuntu is an entirely free Linux distribution that uses the K Desktop
103+single package yourself, with your own preferences.', 'gentoo.org', 1, 'Gentoo', 'Gentoo is a very customizeable GNU/Linux Distribution that is designed to let you build every single package yourself, with your own preferences.', 1, NULL, 1, NULL, true, false, NULL, NULL, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.41974', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10, 60);
104+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (5, 'kubuntu', 'Kubuntu - Free KDE-based Linux', 'Kubuntu is an entirely free Linux distribution that uses the K Desktop
105 Environment as its default desktop after install.', 'kubuntu.org', 1, 'Kubuntu', 'Kubuntu is an entirely free Linux distribution that uses the K Desktop
106-Environment as its default desktop after install.', 1, NULL, 1, NULL, false, false, NULL, 8, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.420551', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10);
107-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (7, 'guadalinex', 'GuadaLinex: Linux for Andalucia', 'GuadaLinex is based on Ubuntu and adds full support for applications specific to the local environment in Andalucia.', 'guadalinex.es', 4, 'GuadaLinex', 'The GuadaLinex team produces a high quality linux for the Andalucian marketplace.', 32, NULL, 1, NULL, false, false, NULL, NULL, NULL, 4, NULL, NULL, '2006-10-16 18:31:43.421329', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10);
108-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (8, 'ubuntutest', 'Ubuntu Test', 'Ubuntu Test', 'ubuntulinux.org', 17, 'ubuntutest', 'Ubuntu Test summary', 17, NULL, 1, NULL, false, false, NULL, NULL, NULL, 17, NULL, NULL, '2006-10-16 18:31:43.422162', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10);
109-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (9, 'deribuntu', 'Deribuntu', 'Deribuntu', 'deribuntu', 16, 'Deribuntu', 'Deribuntu', 16, NULL, 1, NULL, false, false, NULL, NULL, NULL, 16, NULL, NULL, '2011-03-17 14:28:54.354337', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10);
110+Environment as its default desktop after install.', 1, NULL, 1, NULL, false, false, NULL, 8, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.420551', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10, 60);
111+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (7, 'guadalinex', 'GuadaLinex: Linux for Andalucia', 'GuadaLinex is based on Ubuntu and adds full support for applications specific to the local environment in Andalucia.', 'guadalinex.es', 4, 'GuadaLinex', 'The GuadaLinex team produces a high quality linux for the Andalucian marketplace.', 32, NULL, 1, NULL, false, false, NULL, NULL, NULL, 4, NULL, NULL, '2006-10-16 18:31:43.421329', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10, 60);
112+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (8, 'ubuntutest', 'Ubuntu Test', 'Ubuntu Test', 'ubuntulinux.org', 17, 'ubuntutest', 'Ubuntu Test summary', 17, NULL, 1, NULL, false, false, NULL, NULL, NULL, 17, NULL, NULL, '2006-10-16 18:31:43.422162', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10, 60);
113+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (9, 'deribuntu', 'Deribuntu', 'Deribuntu', 'deribuntu', 16, 'Deribuntu', 'Deribuntu', 16, NULL, 1, NULL, false, false, NULL, NULL, NULL, 16, NULL, NULL, '2011-03-17 14:28:54.354337', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10, 60);
114
115
116 ALTER TABLE distribution ENABLE TRIGGER ALL;
117@@ -2944,57 +2950,57 @@
118
119 ALTER TABLE message DISABLE TRIGGER ALL;
120
121-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (1, '2004-09-24 20:58:04.684057', 'PEBCAK', 16, NULL, NULL, 'foo@example.com-332342--1231', NULL, NULL);
122-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (3, '2004-09-24 21:17:17.153792', 'Reproduced on AIX', 12, NULL, NULL, 'sdsdfsfd', NULL, NULL);
123-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (4, '2004-09-24 21:24:03.922564', 'Re: Reproduced on AIX', 12, NULL, NULL, 'sdfssfdfsd', NULL, NULL);
124-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (5, '2004-09-24 21:29:27.407354', 'Fantastic idea, I''d really like to see this', 12, NULL, NULL, 'dxssdfsdgf', NULL, NULL);
125-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (6, '2004-09-24 21:35:20.125564', 'Strange bug with duplicate messages.', 12, NULL, NULL, 'sdfsfwew', NULL, NULL);
126-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (7, '2005-01-14 17:20:12.820778', 'Reflow problems with complex page layouts', 12, NULL, NULL, '<20050114172012.6687.51124.malonedeb@localhost.localdomain>', NULL, NULL);
127-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (8, '2005-01-14 17:27:03.702622', 'Firefox install instructions should be complete', 12, NULL, NULL, '<20050114172703.6687.71983.malonedeb@localhost.localdomain>', NULL, NULL);
128-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (9, '2005-01-14 17:35:39.548665', 'Firefox crashes when Save As dialog for a nonexistent window is closed', 12, NULL, NULL, '<20050114173539.6687.81610.malonedeb@localhost.localdomain>', NULL, NULL);
129-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (10, '2004-10-05 00:00:00', 'Re: Bug Title Test', 12, NULL, NULL, '<20050831114528.7616.78129.malone@localhost.localdomain>', NULL, NULL);
130-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (11, '2005-10-14 15:12:29.602117', 'A test bug', 16, NULL, NULL, '<20051014151229.28962.1536.malonedeb@localhost.localdomain>', NULL, NULL);
131-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (12, '2005-10-14 12:25:21.508923', 'Re: Newly installed plug-in doesn''t seem to be used', 16, NULL, NULL, '<20051014122521.14276.39260.lptickets@localhost.localdomain>', NULL, NULL);
132-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (13, '2005-10-14 13:28:11.554476', 'Re: Slow system', 12, NULL, NULL, '<20051014132811.14276.65873.lptickets@localhost.localdomain>', NULL, NULL);
133-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (14, '2005-10-28 09:10:17.13237', 'Printing doesn''t work', 12, NULL, 3, '<20051028091017.6690.9505.malonedeb@localhost.localdomain>', NULL, NULL);
134-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (15, '2006-02-23 16:42:14.080227', 'Thunderbird crashes', 16, NULL, 1, '<20060223164214.9126.7558.malonedeb@localhost.localdomain>', NULL, NULL);
135-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (16, '2006-06-16 17:12:54', 'Unicode™', 16, NULL, NULL, '<20060616141252.22134.71562@localhost.localdomain>', NULL, 51);
136-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (17, '2006-02-22 19:42:21.890299', 'another test bug', 16, NULL, 1, '<20060222194221.25842.69665.malonedeb@banzai.async.com.br>', NULL, NULL);
137-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (18, '2006-07-20 20:48:24.975495', 'Re: Continue playing after shutdown', 16, NULL, NULL, '<20060720204825.13277.37433.lptickets@Bourdieu.Contre.COM>', NULL, NULL);
138-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (19, '2006-07-20 20:49:47.551344', 'Re: mailto: problem in webpage', 16, NULL, NULL, '<20060720204947.13277.79684.lptickets@Bourdieu.Contre.COM>', NULL, NULL);
139-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (20, '2006-07-20 20:52:07.054216', 'Re: Installation of Java Runtime Environment for Mozilla', 16, NULL, NULL, '<20060720205207.13277.68582.lptickets@Bourdieu.Contre.COM>', NULL, NULL);
140-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (21, '2006-07-20 20:53:53.684848', 'Re: Play DVDs in Totem', 16, NULL, NULL, '<20060720205354.13277.37000.lptickets@Bourdieu.Contre.COM>', NULL, NULL);
141-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (22, '2006-07-20 20:56:35.442839', 'Re: mailto: problem in webpage', 12, NULL, NULL, '<20060720205635.13277.87295.lptickets@Bourdieu.Contre.COM>', NULL, NULL);
142-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (23, '2006-07-20 23:11:24.975495', 'Re: Continue playing after shutdown', 12, NULL, NULL, '<20061201222020.597.97888.lptickets@Huxley.Contre.COM>', NULL, NULL);
143-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (24, '2007-03-15 20:33:56.67893', 'Make Jokosher use autoaudiosink', 26, NULL, NULL, '<20070315203356.12919.76581.malonedeb@localhost>', NULL, NULL);
144-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (25, '2007-03-15 20:34:26.518114', 'Re: Make Jokosher use autoaudiosink', 50, NULL, NULL, '<20070315203426.12919.54628.malone@localhost>', NULL, NULL);
145-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (26, '2007-03-15 20:35:10.133383', 'Re: Make Jokosher use autoaudiosink', 66, NULL, NULL, '<20070315203510.12919.22697.malone@localhost>', NULL, NULL);
146-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (27, '2007-03-15 20:36:01.779544', 'Autoaudiosink is no longer under development', 63, NULL, NULL, '<20070315203601.12919.29640.malone@localhost>', NULL, NULL);
147-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (28, '2007-03-15 20:36:57.133832', 'Re: Autoaudiosink is no longer under development', 27, NULL, NULL, '<20070315203657.12919.48585.malone@localhost>', NULL, NULL);
148-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (29, '2007-03-15 20:37:27.991571', 'This is a really new title', 33, NULL, NULL, '<20070315203728.12919.76787.malone@localhost>', NULL, NULL);
149-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (30, '2007-03-15 20:37:51.544376', 'Re: Make Jokosher use autoaudiosink', 3, NULL, NULL, '<20070315203751.12919.49072.malone@localhost>', NULL, NULL);
150-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (31, '2007-03-15 20:41:18.635493', 'Copy, Cut and Delete operations should work on selections', 8, NULL, NULL, '<20070315204118.14326.61124.malonedeb@localhost>', NULL, NULL);
151-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (32, '2007-03-15 20:41:42.154264', 'Re: Copy, Cut and Delete operations should work on selections', 16, NULL, NULL, '<20070315204142.14326.82988.launchpad@localhost>', NULL, NULL);
152-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (33, '2007-03-15 20:43:14.981111', 'Re: Copy, Cut and Delete operations should work on selections', 45, NULL, NULL, '<20070315204315.14326.75272.malone@localhost>', NULL, NULL);
153-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (34, '2007-03-15 20:45:15.852052', 'Re: Copy, Cut and Delete operations should work on selections', 13, NULL, NULL, '<20070315204515.14326.38817.malone@localhost>', NULL, NULL);
154-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (35, '2007-03-15 20:45:51.817826', 'Re: Copy, Cut and Delete operations should work on selections', 9, NULL, NULL, '<20070315204551.14326.36994.malone@localhost>', NULL, NULL);
155-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (36, '2007-03-15 20:46:49.83307', 'Re: Copy, Cut and Delete operations should work on selections', 6, NULL, NULL, '<20070315204649.14326.69581.malone@localhost>', NULL, NULL);
156-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (37, '2007-07-27 20:00:58.299796', 'Launchpad CSS and JS is not testible', 12, NULL, NULL, '<20070727200058.25131.76173.malonedeb@autumn.annrky-sinzui.local>', NULL, NULL);
157-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (38, '2007-07-27 20:29:46.25854', 'Re: Launchpad CSS and JS is not testible', 12, NULL, NULL, '<20070727202946.25131.16206.malone@autumn.annrky-sinzui.local>', NULL, NULL);
158-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (39, '2007-08-09 11:39:16.836856', 'jokosher exposes personal details in its actions portlet', 63, NULL, NULL, '<20070809113916.26819.83859.malonedeb@localhost.localdomain>', NULL, NULL);
159-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (40, '2004-12-18 16:30:19.103679', 'Nonsensical bugs are useless', 16, NULL, NULL, '<20071218163019.18924.87555.malonedeb@localhost>', NULL, NULL);
160-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (41, '2007-12-18 16:30:47.889614', 'Re: Nonsensical bugs are useless', 16, NULL, NULL, '<20071218163048.18924.13348.launchpad@localhost>', NULL, NULL);
161-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (42, '2007-12-18 16:30:47.889614', 'Re: Nonsensical bugs are useless', 16, NULL, NULL, '<20071218163048.18924.86681.launchpad@localhost>', NULL, NULL);
162-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (43, '2007-12-18 16:31:34.790641', 'Re: Nonsensical bugs are useless', 62, NULL, NULL, '<20071218163134.18996.53651.launchpad@localhost>', NULL, NULL);
163-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (44, '2005-05-13 16:37:37', 'gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243614, NULL, NULL, '<4284D7D1.6010208@gmx.de>', NULL, 75);
164-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (45, '2005-05-17 18:54:29', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243615, 44, NULL, '<20050517185429.GB20786@spring.luon.net>', NULL, 76);
165-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (46, '2005-05-17 19:24:25', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243614, 45, NULL, '<428A44E9.6090802@gmx.de>', NULL, 77);
166-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (47, '2005-05-17 20:20:44', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243615, 46, NULL, '<20050517202044.GA23231@spring.luon.net>', NULL, 78);
167-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (48, '2005-06-17 14:00:11', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243616, 46, NULL, '<20050617140011.GA15638@piware.de>', NULL, 79);
168-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (49, '2005-06-25 10:13:10', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243614, NULL, NULL, '<42BD2E36.9090809@gmx.de>', NULL, 81);
169-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (50, '2010-06-25 10:13:10', 'Sample comment 1', 1, NULL, NULL, '<42BD2E36.9090810@zz.de>', NULL, 81);
170-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (51, '2010-06-26 10:13:10', 'Sample comment 2', 1, NULL, NULL, '<42BD2E36.9090810@zz.de>', NULL, 81);
171-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (52, '2010-06-27 10:13:10', 'Sample comment 3', 1, NULL, NULL, '<42BD2E36.9090810@zz.de>', NULL, 81);
172+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (1, '2004-09-24 20:58:04.684057', 'PEBCAK', 16, NULL, NULL, 'foo@example.com-332342--1231', NULL, NULL, true);
173+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (3, '2004-09-24 21:17:17.153792', 'Reproduced on AIX', 12, NULL, NULL, 'sdsdfsfd', NULL, NULL, true);
174+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (4, '2004-09-24 21:24:03.922564', 'Re: Reproduced on AIX', 12, NULL, NULL, 'sdfssfdfsd', NULL, NULL, true);
175+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (5, '2004-09-24 21:29:27.407354', 'Fantastic idea, I''d really like to see this', 12, NULL, NULL, 'dxssdfsdgf', NULL, NULL, true);
176+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (6, '2004-09-24 21:35:20.125564', 'Strange bug with duplicate messages.', 12, NULL, NULL, 'sdfsfwew', NULL, NULL, true);
177+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (7, '2005-01-14 17:20:12.820778', 'Reflow problems with complex page layouts', 12, NULL, NULL, '<20050114172012.6687.51124.malonedeb@localhost.localdomain>', NULL, NULL, true);
178+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (8, '2005-01-14 17:27:03.702622', 'Firefox install instructions should be complete', 12, NULL, NULL, '<20050114172703.6687.71983.malonedeb@localhost.localdomain>', NULL, NULL, true);
179+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (9, '2005-01-14 17:35:39.548665', 'Firefox crashes when Save As dialog for a nonexistent window is closed', 12, NULL, NULL, '<20050114173539.6687.81610.malonedeb@localhost.localdomain>', NULL, NULL, true);
180+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (10, '2004-10-05 00:00:00', 'Re: Bug Title Test', 12, NULL, NULL, '<20050831114528.7616.78129.malone@localhost.localdomain>', NULL, NULL, true);
181+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (11, '2005-10-14 15:12:29.602117', 'A test bug', 16, NULL, NULL, '<20051014151229.28962.1536.malonedeb@localhost.localdomain>', NULL, NULL, true);
182+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (12, '2005-10-14 12:25:21.508923', 'Re: Newly installed plug-in doesn''t seem to be used', 16, NULL, NULL, '<20051014122521.14276.39260.lptickets@localhost.localdomain>', NULL, NULL, true);
183+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (13, '2005-10-14 13:28:11.554476', 'Re: Slow system', 12, NULL, NULL, '<20051014132811.14276.65873.lptickets@localhost.localdomain>', NULL, NULL, true);
184+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (14, '2005-10-28 09:10:17.13237', 'Printing doesn''t work', 12, NULL, 3, '<20051028091017.6690.9505.malonedeb@localhost.localdomain>', NULL, NULL, true);
185+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (15, '2006-02-23 16:42:14.080227', 'Thunderbird crashes', 16, NULL, 1, '<20060223164214.9126.7558.malonedeb@localhost.localdomain>', NULL, NULL, true);
186+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (16, '2006-06-16 17:12:54', 'Unicode™', 16, NULL, NULL, '<20060616141252.22134.71562@localhost.localdomain>', NULL, 51, true);
187+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (17, '2006-02-22 19:42:21.890299', 'another test bug', 16, NULL, 1, '<20060222194221.25842.69665.malonedeb@banzai.async.com.br>', NULL, NULL, true);
188+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (18, '2006-07-20 20:48:24.975495', 'Re: Continue playing after shutdown', 16, NULL, NULL, '<20060720204825.13277.37433.lptickets@Bourdieu.Contre.COM>', NULL, NULL, true);
189+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (19, '2006-07-20 20:49:47.551344', 'Re: mailto: problem in webpage', 16, NULL, NULL, '<20060720204947.13277.79684.lptickets@Bourdieu.Contre.COM>', NULL, NULL, true);
190+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (20, '2006-07-20 20:52:07.054216', 'Re: Installation of Java Runtime Environment for Mozilla', 16, NULL, NULL, '<20060720205207.13277.68582.lptickets@Bourdieu.Contre.COM>', NULL, NULL, true);
191+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (21, '2006-07-20 20:53:53.684848', 'Re: Play DVDs in Totem', 16, NULL, NULL, '<20060720205354.13277.37000.lptickets@Bourdieu.Contre.COM>', NULL, NULL, true);
192+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (22, '2006-07-20 20:56:35.442839', 'Re: mailto: problem in webpage', 12, NULL, NULL, '<20060720205635.13277.87295.lptickets@Bourdieu.Contre.COM>', NULL, NULL, true);
193+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (23, '2006-07-20 23:11:24.975495', 'Re: Continue playing after shutdown', 12, NULL, NULL, '<20061201222020.597.97888.lptickets@Huxley.Contre.COM>', NULL, NULL, true);
194+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (24, '2007-03-15 20:33:56.67893', 'Make Jokosher use autoaudiosink', 26, NULL, NULL, '<20070315203356.12919.76581.malonedeb@localhost>', NULL, NULL, true);
195+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (25, '2007-03-15 20:34:26.518114', 'Re: Make Jokosher use autoaudiosink', 50, NULL, NULL, '<20070315203426.12919.54628.malone@localhost>', NULL, NULL, true);
196+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (26, '2007-03-15 20:35:10.133383', 'Re: Make Jokosher use autoaudiosink', 66, NULL, NULL, '<20070315203510.12919.22697.malone@localhost>', NULL, NULL, true);
197+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (27, '2007-03-15 20:36:01.779544', 'Autoaudiosink is no longer under development', 63, NULL, NULL, '<20070315203601.12919.29640.malone@localhost>', NULL, NULL, true);
198+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (28, '2007-03-15 20:36:57.133832', 'Re: Autoaudiosink is no longer under development', 27, NULL, NULL, '<20070315203657.12919.48585.malone@localhost>', NULL, NULL, true);
199+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (29, '2007-03-15 20:37:27.991571', 'This is a really new title', 33, NULL, NULL, '<20070315203728.12919.76787.malone@localhost>', NULL, NULL, true);
200+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (30, '2007-03-15 20:37:51.544376', 'Re: Make Jokosher use autoaudiosink', 3, NULL, NULL, '<20070315203751.12919.49072.malone@localhost>', NULL, NULL, true);
201+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (31, '2007-03-15 20:41:18.635493', 'Copy, Cut and Delete operations should work on selections', 8, NULL, NULL, '<20070315204118.14326.61124.malonedeb@localhost>', NULL, NULL, true);
202+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (32, '2007-03-15 20:41:42.154264', 'Re: Copy, Cut and Delete operations should work on selections', 16, NULL, NULL, '<20070315204142.14326.82988.launchpad@localhost>', NULL, NULL, true);
203+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (33, '2007-03-15 20:43:14.981111', 'Re: Copy, Cut and Delete operations should work on selections', 45, NULL, NULL, '<20070315204315.14326.75272.malone@localhost>', NULL, NULL, true);
204+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (34, '2007-03-15 20:45:15.852052', 'Re: Copy, Cut and Delete operations should work on selections', 13, NULL, NULL, '<20070315204515.14326.38817.malone@localhost>', NULL, NULL, true);
205+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (35, '2007-03-15 20:45:51.817826', 'Re: Copy, Cut and Delete operations should work on selections', 9, NULL, NULL, '<20070315204551.14326.36994.malone@localhost>', NULL, NULL, true);
206+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (36, '2007-03-15 20:46:49.83307', 'Re: Copy, Cut and Delete operations should work on selections', 6, NULL, NULL, '<20070315204649.14326.69581.malone@localhost>', NULL, NULL, true);
207+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (37, '2007-07-27 20:00:58.299796', 'Launchpad CSS and JS is not testible', 12, NULL, NULL, '<20070727200058.25131.76173.malonedeb@autumn.annrky-sinzui.local>', NULL, NULL, true);
208+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (38, '2007-07-27 20:29:46.25854', 'Re: Launchpad CSS and JS is not testible', 12, NULL, NULL, '<20070727202946.25131.16206.malone@autumn.annrky-sinzui.local>', NULL, NULL, true);
209+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (39, '2007-08-09 11:39:16.836856', 'jokosher exposes personal details in its actions portlet', 63, NULL, NULL, '<20070809113916.26819.83859.malonedeb@localhost.localdomain>', NULL, NULL, true);
210+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (40, '2004-12-18 16:30:19.103679', 'Nonsensical bugs are useless', 16, NULL, NULL, '<20071218163019.18924.87555.malonedeb@localhost>', NULL, NULL, true);
211+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (41, '2007-12-18 16:30:47.889614', 'Re: Nonsensical bugs are useless', 16, NULL, NULL, '<20071218163048.18924.13348.launchpad@localhost>', NULL, NULL, true);
212+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (42, '2007-12-18 16:30:47.889614', 'Re: Nonsensical bugs are useless', 16, NULL, NULL, '<20071218163048.18924.86681.launchpad@localhost>', NULL, NULL, true);
213+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (43, '2007-12-18 16:31:34.790641', 'Re: Nonsensical bugs are useless', 62, NULL, NULL, '<20071218163134.18996.53651.launchpad@localhost>', NULL, NULL, true);
214+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (44, '2005-05-13 16:37:37', 'gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243614, NULL, NULL, '<4284D7D1.6010208@gmx.de>', NULL, 75, true);
215+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (45, '2005-05-17 18:54:29', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243615, 44, NULL, '<20050517185429.GB20786@spring.luon.net>', NULL, 76, true);
216+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (46, '2005-05-17 19:24:25', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243614, 45, NULL, '<428A44E9.6090802@gmx.de>', NULL, 77, true);
217+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (47, '2005-05-17 20:20:44', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243615, 46, NULL, '<20050517202044.GA23231@spring.luon.net>', NULL, 78, true);
218+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (48, '2005-06-17 14:00:11', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243616, 46, NULL, '<20050617140011.GA15638@piware.de>', NULL, 79, true);
219+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (49, '2005-06-25 10:13:10', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243614, NULL, NULL, '<42BD2E36.9090809@gmx.de>', NULL, 81, true);
220+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (50, '2010-06-25 10:13:10', 'Sample comment 1', 1, NULL, NULL, '<42BD2E36.9090810@zz.de>', NULL, 81, true);
221+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (51, '2010-06-26 10:13:10', 'Sample comment 2', 1, NULL, NULL, '<42BD2E36.9090810@zz.de>', NULL, 81, true);
222+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (52, '2010-06-27 10:13:10', 'Sample comment 3', 1, NULL, NULL, '<42BD2E36.9090810@zz.de>', NULL, 81, true);
223
224
225 ALTER TABLE message ENABLE TRIGGER ALL;
226@@ -3392,42 +3398,42 @@
227
228 ALTER TABLE bugmessage DISABLE TRIGGER ALL;
229
230-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (1, 2, 1, NULL, NULL, true, 0);
231-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (2, 1, 3, NULL, NULL, true, 0);
232-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (3, 1, 4, NULL, NULL, true, 1);
233-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (4, 2, 5, NULL, NULL, true, 1);
234-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (5, 2, 6, NULL, NULL, true, 2);
235-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (6, 4, 7, NULL, NULL, true, 0);
236-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (7, 5, 8, NULL, NULL, true, 0);
237-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (8, 6, 9, NULL, NULL, true, 0);
238-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (9, 3, 10, NULL, NULL, true, 0);
239-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (10, 7, 11, NULL, NULL, true, 0);
240-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (11, 8, 14, NULL, NULL, true, 0);
241-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (12, 9, 15, NULL, NULL, true, 0);
242-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (13, 10, 17, NULL, NULL, true, 0);
243-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (14, 10, 16, NULL, NULL, true, 1);
244-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (15, 11, 24, NULL, NULL, true, 0);
245-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (16, 11, 25, NULL, NULL, true, 1);
246-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (17, 11, 26, NULL, NULL, true, 2);
247-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (18, 11, 27, NULL, NULL, true, 3);
248-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (19, 11, 28, NULL, NULL, true, 4);
249-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (20, 11, 29, NULL, NULL, true, 5);
250-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (21, 11, 30, NULL, NULL, true, 6);
251-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (22, 12, 31, NULL, NULL, true, 0);
252-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (23, 12, 33, NULL, NULL, true, 1);
253-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (24, 12, 34, NULL, NULL, true, 2);
254-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (25, 12, 35, NULL, NULL, true, 3);
255-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (26, 12, 36, NULL, NULL, true, 4);
256-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (27, 13, 37, NULL, NULL, true, 0);
257-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (28, 13, 38, NULL, NULL, true, 1);
258-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (29, 14, 39, NULL, NULL, true, 0);
259-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (30, 15, 40, NULL, NULL, true, 0);
260-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (31, 15, 44, 11, '<4284D7D1.6010208@gmx.de>', true, 1);
261-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (32, 15, 45, 11, '<20050517185429.GB20786@spring.luon.net>', true, 2);
262-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (33, 15, 46, 11, '<428A44E9.6090802@gmx.de>', true, 3);
263-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (34, 15, 47, 11, '<20050517202044.GA23231@spring.luon.net>', true, 4);
264-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (35, 15, 48, 11, '<20050617140011.GA15638@piware.de>', true, 5);
265-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (36, 15, 49, 11, '<42BD2E36.9090809@gmx.de>', true, 6);
266+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (1, 2, 1, NULL, NULL, 0);
267+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (2, 1, 3, NULL, NULL, 0);
268+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (3, 1, 4, NULL, NULL, 1);
269+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (4, 2, 5, NULL, NULL, 1);
270+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (5, 2, 6, NULL, NULL, 2);
271+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (6, 4, 7, NULL, NULL, 0);
272+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (7, 5, 8, NULL, NULL, 0);
273+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (8, 6, 9, NULL, NULL, 0);
274+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (9, 3, 10, NULL, NULL, 0);
275+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (10, 7, 11, NULL, NULL, 0);
276+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (11, 8, 14, NULL, NULL, 0);
277+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (12, 9, 15, NULL, NULL, 0);
278+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (13, 10, 17, NULL, NULL, 0);
279+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (14, 10, 16, NULL, NULL, 1);
280+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (15, 11, 24, NULL, NULL, 0);
281+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (16, 11, 25, NULL, NULL, 1);
282+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (17, 11, 26, NULL, NULL, 2);
283+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (18, 11, 27, NULL, NULL, 3);
284+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (19, 11, 28, NULL, NULL, 4);
285+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (20, 11, 29, NULL, NULL, 5);
286+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (21, 11, 30, NULL, NULL, 6);
287+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (22, 12, 31, NULL, NULL, 0);
288+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (23, 12, 33, NULL, NULL, 1);
289+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (24, 12, 34, NULL, NULL, 2);
290+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (25, 12, 35, NULL, NULL, 3);
291+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (26, 12, 36, NULL, NULL, 4);
292+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (27, 13, 37, NULL, NULL, 0);
293+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (28, 13, 38, NULL, NULL, 1);
294+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (29, 14, 39, NULL, NULL, 0);
295+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (30, 15, 40, NULL, NULL, 0);
296+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (31, 15, 44, 11, '<4284D7D1.6010208@gmx.de>', 1);
297+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (32, 15, 45, 11, '<20050517185429.GB20786@spring.luon.net>', 2);
298+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (33, 15, 46, 11, '<428A44E9.6090802@gmx.de>', 3);
299+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (34, 15, 47, 11, '<20050517202044.GA23231@spring.luon.net>', 4);
300+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (35, 15, 48, 11, '<20050617140011.GA15638@piware.de>', 5);
301+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (36, 15, 49, 11, '<42BD2E36.9090809@gmx.de>', 6);
302
303
304 ALTER TABLE bugmessage ENABLE TRIGGER ALL;
305@@ -4051,6 +4057,13 @@
306 ALTER TABLE databasecpustats ENABLE TRIGGER ALL;
307
308
309+ALTER TABLE databasediskutilization DISABLE TRIGGER ALL;
310+
311+
312+
313+ALTER TABLE databasediskutilization ENABLE TRIGGER ALL;
314+
315+
316 ALTER TABLE databasereplicationlag DISABLE TRIGGER ALL;
317
318
319@@ -4447,6 +4460,20 @@
320 ALTER TABLE featureflag ENABLE TRIGGER ALL;
321
322
323+ALTER TABLE featureflagchangelogentry DISABLE TRIGGER ALL;
324+
325+
326+
327+ALTER TABLE featureflagchangelogentry ENABLE TRIGGER ALL;
328+
329+
330+ALTER TABLE featureflagchangelogentry DISABLE TRIGGER ALL;
331+
332+
333+
334+ALTER TABLE featureflagchangelogentry ENABLE TRIGGER ALL;
335+
336+
337 ALTER TABLE flatpackagesetinclusion DISABLE TRIGGER ALL;
338
339
340@@ -9961,6 +9988,15 @@
341 ALTER TABLE projectrelationship ENABLE TRIGGER ALL;
342
343
344+ALTER TABLE publisherconfig DISABLE TRIGGER ALL;
345+
346+INSERT INTO publisherconfig (id, distribution, root_dir, base_url, copy_base_url) VALUES (1, 1, '/var/tmp/archive', 'http://archive.launchpad.dev/', 'http://rebuild-test.internal/');
347+INSERT INTO publisherconfig (id, distribution, root_dir, base_url, copy_base_url) VALUES (2, 8, '/var/tmp/archive', 'http://archive.launchpad.dev/', 'http://rebuild-test.internal/');
348+
349+
350+ALTER TABLE publisherconfig ENABLE TRIGGER ALL;
351+
352+
353 ALTER TABLE pushmirroraccess DISABLE TRIGGER ALL;
354
355
356
357=== modified file 'database/sampledata/current.sql'
358--- database/sampledata/current.sql 2011-02-25 17:46:17 +0000
359+++ database/sampledata/current.sql 2011-03-29 10:32:58 +0000
360@@ -837,6 +837,12 @@
361
362
363
364+
365+
366+
367+
368+
369+
370 SET SESSION AUTHORIZATION DEFAULT;
371
372 ALTER TABLE account DISABLE TRIGGER ALL;
373@@ -1879,20 +1885,20 @@
374
375 ALTER TABLE distroseries DISABLE TRIGGER ALL;
376
377-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (1, 1, 'warty', 'The Warty Warthog Release', 'Warty was the first stable release of Ubuntu. Key feature goals included releasing on time, with the latest version of the Gnome Desktop Environment, and the creation of all the infrastructure required to manage Ubuntu itself. Warty includes excellent support for Python, with most of the widely used Python libraries installed by default.', '4.10', 4, '2004-08-20 00:00:00', NULL, 17, 'Warty is the first release of Ubuntu, with a planned release date of October 2004.', 'Warty', NULL, 0, 1, 'warty-changes@ubuntu.com', 4, 3, NULL, '2006-10-16 18:31:43.475428', false, false, NULL, NULL, NULL, false);
378-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (2, 2, 'six', 'Six Six Six', 'some text to describe the whole 666 release of RH', '6.0.1', 4, '2004-03-21 00:00:00', NULL, 8, 'some text to describe the whole 666 release of RH', 'Six', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.482603', false, false, NULL, NULL, NULL, false);
379-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (3, 1, 'hoary', 'The Hoary Hedgehog Release', 'Hoary is the second release of Ubuntu. Key feature goals include the integration of Hoary with the Launchpad for bugs and translation information, as well as Gnome 2.10 and the X.org window system.', '5.04', 2, NULL, 1, 1, 'Hoary is the second released of Ubuntu, with release planned for April 2005.', 'Hoary', NULL, 96, 6, 'hoary-changes@ubuntu.com', 1, 4, NULL, '2006-10-16 18:31:43.483559', false, false, NULL, NULL, NULL, false);
380-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (4, 2, '7.0', 'Seven', 'The release that we would not expect', '7.0.1', 3, NULL, 2, 7, 'The release that we would not expect', '7.0', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.484426', false, false, NULL, NULL, NULL, false);
381-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (5, 1, 'grumpy', 'The Grumpy Groundhog Release', 'Grumpy, the third release of Ubuntu Linux, is not yet in active development. This information is purely a placeholder.', '5.10', 1, NULL, 1, 1, 'Grumpy is the third release of Ubuntu, planned for October 2005.', 'Grumpy', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.485233', false, false, NULL, NULL, NULL, false);
382-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (6, 3, 'woody', 'WOODY', 'WOODY is the current stable verison of Debian GNU/Linux', '3.0', 4, '2003-01-01 00:00:00', NULL, 2, 'WOODY is the current stable verison of Debian GNU/Linux', 'Woody', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.486054', false, false, NULL, NULL, NULL, false);
383-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (7, 3, 'sarge', 'Sarge', 'Sarge is the FROZEN unstable version of Debian GNU/Linux.', '3.1', 3, NULL, 6, 5, 'Sarge is the FROZEN unstable version of Debian GNU/Linux.', 'Sarge', NULL, 0, NULL, NULL, 0, 0, 6, '2006-10-16 18:31:43.486972', false, false, NULL, NULL, NULL, false);
384-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (8, 3, 'sid', 'Sid', 'Sid is the CRAZY unstable version of Debian GNU/Linux.', '3.2', 1, NULL, 6, 6, 'Sid is the CRAZY unstable version of Debian GNU/Linux.', 'Sid', NULL, 0, NULL, NULL, 0, 1, NULL, '2006-10-16 18:31:43.487779', false, false, NULL, NULL, NULL, false);
385-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (9, 7, '2k5', 'Guada 2005', 'This release places extra emphasis on usability and installability. The installer is adapted from Ubuntu to assume your country, language, keyboard and time zone preference, thus ensuring that installs ask the minimum number of questions possible.', '2005', 2, NULL, 3, 4, 'Guada 2005 is a rapid-install version of
386-Ubuntu Hoary for the Andalucian marketplace.', 'Guada2005', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.488598', false, false, NULL, NULL, NULL, false);
387-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (10, 1, 'breezy-autotest', 'Breezy Badger Autotest', 'Autotest version of Breezy', '6.6.6', 1, NULL, 3, 1, 'Autosync uploader test', 'Breezy Badger Autotest', NULL, 0, 8, 'autotest_changes@ubuntu.com', 0, 0, NULL, '2006-10-16 18:31:43.489468', false, false, NULL, NULL, NULL, false);
388-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (11, 8, 'breezy-autotest', 'Breezy Badger Autotest', 'Autotest version of Breezy', '6.6.6', 1, NULL, 1, 1, 'Autosync uploader test', 'Breezy Badger Autotest', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.490333', false, false, NULL, NULL, NULL, false);
389-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (12, 5, 'krunch', 'The Krunchy Kangaroo', 'The archive split allows us to use different kernel settings for Kubuntu, as well as make other pervasive low-level fixes, and release on our own schedule.', '8.06', 1, NULL, 3, 1, 'This is the first experimental release of Kubuntu that uses a separate archive from the main Ubuntu release.', 'Krunch', NULL, 0, NULL, NULL, 0, 0, 33, '2006-10-16 18:31:43.491929', false, false, NULL, NULL, NULL, false);
390-INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, owner, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested) VALUES (13, 8, 'hoary-test', 'Mock Hoary', 'nothing special', '9.9.9', 1, NULL, 1, 1, 'summmmmmmary', 'Hoary Mock', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.492845', false, false, NULL, NULL, NULL, false);
391+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (1, 1, 'warty', 'The Warty Warthog Release', 'Warty was the first stable release of Ubuntu. Key feature goals included releasing on time, with the latest version of the Gnome Desktop Environment, and the creation of all the infrastructure required to manage Ubuntu itself. Warty includes excellent support for Python, with most of the widely used Python libraries installed by default.', '4.10', 4, '2004-08-20 00:00:00', NULL, 'Warty is the first release of Ubuntu, with a planned release date of October 2004.', 'Warty', NULL, 0, 1, 'warty-changes@ubuntu.com', 4, 3, NULL, '2006-10-16 18:31:43.475428', false, false, NULL, NULL, NULL, false, 17);
392+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (2, 2, 'six', 'Six Six Six', 'some text to describe the whole 666 release of RH', '6.0.1', 4, '2004-03-21 00:00:00', NULL, 'some text to describe the whole 666 release of RH', 'Six', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.482603', false, false, NULL, NULL, NULL, false, 8);
393+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (3, 1, 'hoary', 'The Hoary Hedgehog Release', 'Hoary is the second release of Ubuntu. Key feature goals include the integration of Hoary with the Launchpad for bugs and translation information, as well as Gnome 2.10 and the X.org window system.', '5.04', 2, NULL, 1, 'Hoary is the second released of Ubuntu, with release planned for April 2005.', 'Hoary', NULL, 96, 6, 'hoary-changes@ubuntu.com', 1, 4, NULL, '2006-10-16 18:31:43.483559', false, false, NULL, NULL, NULL, false, 1);
394+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (4, 2, '7.0', 'Seven', 'The release that we would not expect', '7.0.1', 3, NULL, 2, 'The release that we would not expect', '7.0', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.484426', false, false, NULL, NULL, NULL, false, 7);
395+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (5, 1, 'grumpy', 'The Grumpy Groundhog Release', 'Grumpy, the third release of Ubuntu Linux, is not yet in active development. This information is purely a placeholder.', '5.10', 1, NULL, 1, 'Grumpy is the third release of Ubuntu, planned for October 2005.', 'Grumpy', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.485233', false, false, NULL, NULL, NULL, false, 1);
396+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (6, 3, 'woody', 'WOODY', 'WOODY is the current stable verison of Debian GNU/Linux', '3.0', 4, '2003-01-01 00:00:00', NULL, 'WOODY is the current stable verison of Debian GNU/Linux', 'Woody', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.486054', false, false, NULL, NULL, NULL, false, 2);
397+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (7, 3, 'sarge', 'Sarge', 'Sarge is the FROZEN unstable version of Debian GNU/Linux.', '3.1', 3, NULL, 6, 'Sarge is the FROZEN unstable version of Debian GNU/Linux.', 'Sarge', NULL, 0, NULL, NULL, 0, 0, 6, '2006-10-16 18:31:43.486972', false, false, NULL, NULL, NULL, false, 5);
398+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (8, 3, 'sid', 'Sid', 'Sid is the CRAZY unstable version of Debian GNU/Linux.', '3.2', 1, NULL, 6, 'Sid is the CRAZY unstable version of Debian GNU/Linux.', 'Sid', NULL, 0, NULL, NULL, 0, 1, NULL, '2006-10-16 18:31:43.487779', false, false, NULL, NULL, NULL, false, 6);
399+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (9, 7, '2k5', 'Guada 2005', 'This release places extra emphasis on usability and installability. The installer is adapted from Ubuntu to assume your country, language, keyboard and time zone preference, thus ensuring that installs ask the minimum number of questions possible.', '2005', 2, NULL, 3, 'Guada 2005 is a rapid-install version of
400+Ubuntu Hoary for the Andalucian marketplace.', 'Guada2005', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.488598', false, false, NULL, NULL, NULL, false, 4);
401+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (10, 1, 'breezy-autotest', 'Breezy Badger Autotest', 'Autotest version of Breezy', '6.6.6', 1, NULL, 3, 'Autosync uploader test', 'Breezy Badger Autotest', NULL, 0, 8, 'autotest_changes@ubuntu.com', 0, 0, NULL, '2006-10-16 18:31:43.489468', false, false, NULL, NULL, NULL, false, 1);
402+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (11, 8, 'breezy-autotest', 'Breezy Badger Autotest', 'Autotest version of Breezy', '6.6.6', 1, NULL, 1, 'Autosync uploader test', 'Breezy Badger Autotest', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.490333', false, false, NULL, NULL, NULL, false, 1);
403+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (12, 5, 'krunch', 'The Krunchy Kangaroo', 'The archive split allows us to use different kernel settings for Kubuntu, as well as make other pervasive low-level fixes, and release on our own schedule.', '8.06', 1, NULL, 3, 'This is the first experimental release of Kubuntu that uses a separate archive from the main Ubuntu release.', 'Krunch', NULL, 0, NULL, NULL, 0, 0, 33, '2006-10-16 18:31:43.491929', false, false, NULL, NULL, NULL, false, 1);
404+INSERT INTO distroseries (id, distribution, name, title, description, version, releasestatus, datereleased, parent_series, summary, displayname, datelastlangpack, messagecount, nominatedarchindep, changeslist, binarycount, sourcecount, driver, date_created, hide_all_translations, defer_translation_imports, language_pack_base, language_pack_delta, language_pack_proposed, language_pack_full_export_requested, registrant) VALUES (13, 8, 'hoary-test', 'Mock Hoary', 'nothing special', '9.9.9', 1, NULL, 1, 'summmmmmmary', 'Hoary Mock', NULL, 0, NULL, NULL, 0, 0, NULL, '2006-10-16 18:31:43.492845', false, false, NULL, NULL, NULL, false, 1);
405
406
407 ALTER TABLE distroseries ENABLE TRIGGER ALL;
408@@ -1908,21 +1914,21 @@
409
410 ALTER TABLE distribution DISABLE TRIGGER ALL;
411
412-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (1, 'ubuntu', 'Ubuntu Linux', 'Ubuntu is a new approach to Linux Distribution that includes regular releases, and a simplified single-CD installation system.', 'ubuntulinux.org', 17, 'Ubuntu', 'Ubuntu is a new approach to Linux Distribution that includes regular releases, and a simplified single-CD installation system.', 17, NULL, 1, NULL, true, true, NULL, NULL, 3, 59, NULL, NULL, '2006-10-16 18:31:43.415195', NULL, NULL, NULL, NULL, NULL, true, NULL, true, true, NULL, NULL, NULL, NULL, 10, 10, 10);
413-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (2, 'redhat', 'Redhat Advanced Server', 'Red Hat is a commercial distribution of the GNU/Linux Operating System.', 'redhat.com', 1, 'Red Hat', 'Red Hat is a commercial distribution of the GNU/Linux Operating System.', 1, NULL, 1, NULL, false, false, NULL, 8, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.417928', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10);
414-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (3, 'debian', 'Debian GNU/Linux', 'Debian GNU/Linux is
415+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (1, 'ubuntu', 'Ubuntu Linux', 'Ubuntu is a new approach to Linux Distribution that includes regular releases, and a simplified single-CD installation system.', 'ubuntulinux.org', 17, 'Ubuntu', 'Ubuntu is a new approach to Linux Distribution that includes regular releases, and a simplified single-CD installation system.', 17, NULL, 1, NULL, true, true, NULL, NULL, 3, 59, NULL, NULL, '2006-10-16 18:31:43.415195', NULL, NULL, NULL, NULL, NULL, true, NULL, true, true, NULL, NULL, NULL, NULL, 10, 10, 10, 60);
416+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (2, 'redhat', 'Redhat Advanced Server', 'Red Hat is a commercial distribution of the GNU/Linux Operating System.', 'redhat.com', 1, 'Red Hat', 'Red Hat is a commercial distribution of the GNU/Linux Operating System.', 1, NULL, 1, NULL, false, false, NULL, 8, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.417928', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10, 60);
417+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (3, 'debian', 'Debian GNU/Linux', 'Debian GNU/Linux is
418 a non commercial distribution of a GNU/Linux Operating System for many
419 platforms.', 'debian.org', 1, 'Debian', 'Debian GNU/Linux is
420 a non commercial distribution of a GNU/Linux Operating System for many
421-platforms.', 1, NULL, 1, NULL, false, false, NULL, NULL, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.418942', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10);
422-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (4, 'gentoo', 'The Gentoo Linux', 'Gentoo is a very
423+platforms.', 1, NULL, 1, NULL, false, false, NULL, NULL, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.418942', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10, 60);
424+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (4, 'gentoo', 'The Gentoo Linux', 'Gentoo is a very
425 customizeable GNU/Linux Distribution that is designed to let you build every
426-single package yourself, with your own preferences.', 'gentoo.org', 1, 'Gentoo', 'Gentoo is a very customizeable GNU/Linux Distribution that is designed to let you build every single package yourself, with your own preferences.', 1, NULL, 1, NULL, true, false, NULL, NULL, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.41974', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10);
427-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (5, 'kubuntu', 'Kubuntu - Free KDE-based Linux', 'Kubuntu is an entirely free Linux distribution that uses the K Desktop
428+single package yourself, with your own preferences.', 'gentoo.org', 1, 'Gentoo', 'Gentoo is a very customizeable GNU/Linux Distribution that is designed to let you build every single package yourself, with your own preferences.', 1, NULL, 1, NULL, true, false, NULL, NULL, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.41974', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10, 60);
429+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (5, 'kubuntu', 'Kubuntu - Free KDE-based Linux', 'Kubuntu is an entirely free Linux distribution that uses the K Desktop
430 Environment as its default desktop after install.', 'kubuntu.org', 1, 'Kubuntu', 'Kubuntu is an entirely free Linux distribution that uses the K Desktop
431-Environment as its default desktop after install.', 1, NULL, 1, NULL, false, false, NULL, 8, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.420551', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10);
432-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (7, 'guadalinex', 'GuadaLinex: Linux for Andalucia', 'GuadaLinex is based on Ubuntu and adds full support for applications specific to the local environment in Andalucia.', 'guadalinex.es', 4, 'GuadaLinex', 'The GuadaLinex team produces a high quality linux for the Andalucian marketplace.', 32, NULL, 1, NULL, false, false, NULL, NULL, NULL, 4, NULL, NULL, '2006-10-16 18:31:43.421329', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10);
433-INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage) VALUES (8, 'ubuntutest', 'Ubuntu Test', 'Ubuntu Test', 'ubuntulinux.org', 17, 'ubuntutest', 'Ubuntu Test summary', 17, NULL, 1, NULL, false, false, NULL, NULL, NULL, 17, NULL, NULL, '2006-10-16 18:31:43.422162', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10);
434+Environment as its default desktop after install.', 1, NULL, 1, NULL, false, false, NULL, 8, NULL, 1, NULL, NULL, '2006-10-16 18:31:43.420551', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10, 60);
435+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (7, 'guadalinex', 'GuadaLinex: Linux for Andalucia', 'GuadaLinex is based on Ubuntu and adds full support for applications specific to the local environment in Andalucia.', 'guadalinex.es', 4, 'GuadaLinex', 'The GuadaLinex team produces a high quality linux for the Andalucian marketplace.', 32, NULL, 1, NULL, false, false, NULL, NULL, NULL, 4, NULL, NULL, '2006-10-16 18:31:43.421329', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10, 60);
436+INSERT INTO distribution (id, name, title, description, domainname, owner, displayname, summary, members, translationgroup, translationpermission, bug_supervisor, official_malone, official_rosetta, security_contact, driver, translation_focus, mirror_admin, upload_admin, upload_sender, date_created, homepage_content, icon, mugshot, logo, fti, official_answers, language_pack_admin, official_blueprints, enable_bug_expiration, bug_reporting_guidelines, reviewer_whiteboard, max_bug_heat, bug_reported_acknowledgement, answers_usage, blueprints_usage, translations_usage, registrant) VALUES (8, 'ubuntutest', 'Ubuntu Test', 'Ubuntu Test', 'ubuntulinux.org', 17, 'ubuntutest', 'Ubuntu Test summary', 17, NULL, 1, NULL, false, false, NULL, NULL, NULL, 17, NULL, NULL, '2006-10-16 18:31:43.422162', NULL, NULL, NULL, NULL, NULL, false, NULL, false, false, NULL, NULL, NULL, NULL, 10, 10, 10, 60);
437
438
439 ALTER TABLE distribution ENABLE TRIGGER ALL;
440@@ -2891,54 +2897,54 @@
441
442 ALTER TABLE message DISABLE TRIGGER ALL;
443
444-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (1, '2004-09-24 20:58:04.684057', 'PEBCAK', 16, NULL, NULL, 'foo@example.com-332342--1231', NULL, NULL);
445-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (3, '2004-09-24 21:17:17.153792', 'Reproduced on AIX', 12, NULL, NULL, 'sdsdfsfd', NULL, NULL);
446-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (4, '2004-09-24 21:24:03.922564', 'Re: Reproduced on AIX', 12, NULL, NULL, 'sdfssfdfsd', NULL, NULL);
447-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (5, '2004-09-24 21:29:27.407354', 'Fantastic idea, I''d really like to see this', 12, NULL, NULL, 'dxssdfsdgf', NULL, NULL);
448-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (6, '2004-09-24 21:35:20.125564', 'Strange bug with duplicate messages.', 12, NULL, NULL, 'sdfsfwew', NULL, NULL);
449-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (7, '2005-01-14 17:20:12.820778', 'Reflow problems with complex page layouts', 12, NULL, NULL, '<20050114172012.6687.51124.malonedeb@localhost.localdomain>', NULL, NULL);
450-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (8, '2005-01-14 17:27:03.702622', 'Firefox install instructions should be complete', 12, NULL, NULL, '<20050114172703.6687.71983.malonedeb@localhost.localdomain>', NULL, NULL);
451-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (9, '2005-01-14 17:35:39.548665', 'Firefox crashes when Save As dialog for a nonexistent window is closed', 12, NULL, NULL, '<20050114173539.6687.81610.malonedeb@localhost.localdomain>', NULL, NULL);
452-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (10, '2004-10-05 00:00:00', 'Re: Bug Title Test', 12, NULL, NULL, '<20050831114528.7616.78129.malone@localhost.localdomain>', NULL, NULL);
453-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (11, '2005-10-14 15:12:29.602117', 'A test bug', 16, NULL, NULL, '<20051014151229.28962.1536.malonedeb@localhost.localdomain>', NULL, NULL);
454-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (12, '2005-10-14 12:25:21.508923', 'Re: Newly installed plug-in doesn''t seem to be used', 16, NULL, NULL, '<20051014122521.14276.39260.lptickets@localhost.localdomain>', NULL, NULL);
455-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (13, '2005-10-14 13:28:11.554476', 'Re: Slow system', 12, NULL, NULL, '<20051014132811.14276.65873.lptickets@localhost.localdomain>', NULL, NULL);
456-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (14, '2005-10-28 09:10:17.13237', 'Printing doesn''t work', 12, NULL, 3, '<20051028091017.6690.9505.malonedeb@localhost.localdomain>', NULL, NULL);
457-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (15, '2006-02-23 16:42:14.080227', 'Thunderbird crashes', 16, NULL, 1, '<20060223164214.9126.7558.malonedeb@localhost.localdomain>', NULL, NULL);
458-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (16, '2006-06-16 17:12:54', 'Unicode™', 16, NULL, NULL, '<20060616141252.22134.71562@localhost.localdomain>', NULL, 51);
459-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (17, '2006-02-22 19:42:21.890299', 'another test bug', 16, NULL, 1, '<20060222194221.25842.69665.malonedeb@banzai.async.com.br>', NULL, NULL);
460-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (18, '2006-07-20 20:48:24.975495', 'Re: Continue playing after shutdown', 16, NULL, NULL, '<20060720204825.13277.37433.lptickets@Bourdieu.Contre.COM>', NULL, NULL);
461-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (19, '2006-07-20 20:49:47.551344', 'Re: mailto: problem in webpage', 16, NULL, NULL, '<20060720204947.13277.79684.lptickets@Bourdieu.Contre.COM>', NULL, NULL);
462-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (20, '2006-07-20 20:52:07.054216', 'Re: Installation of Java Runtime Environment for Mozilla', 16, NULL, NULL, '<20060720205207.13277.68582.lptickets@Bourdieu.Contre.COM>', NULL, NULL);
463-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (21, '2006-07-20 20:53:53.684848', 'Re: Play DVDs in Totem', 16, NULL, NULL, '<20060720205354.13277.37000.lptickets@Bourdieu.Contre.COM>', NULL, NULL);
464-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (22, '2006-07-20 20:56:35.442839', 'Re: mailto: problem in webpage', 12, NULL, NULL, '<20060720205635.13277.87295.lptickets@Bourdieu.Contre.COM>', NULL, NULL);
465-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (23, '2006-07-20 23:11:24.975495', 'Re: Continue playing after shutdown', 12, NULL, NULL, '<20061201222020.597.97888.lptickets@Huxley.Contre.COM>', NULL, NULL);
466-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (24, '2007-03-15 20:33:56.67893', 'Make Jokosher use autoaudiosink', 26, NULL, NULL, '<20070315203356.12919.76581.malonedeb@localhost>', NULL, NULL);
467-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (25, '2007-03-15 20:34:26.518114', 'Re: Make Jokosher use autoaudiosink', 50, NULL, NULL, '<20070315203426.12919.54628.malone@localhost>', NULL, NULL);
468-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (26, '2007-03-15 20:35:10.133383', 'Re: Make Jokosher use autoaudiosink', 66, NULL, NULL, '<20070315203510.12919.22697.malone@localhost>', NULL, NULL);
469-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (27, '2007-03-15 20:36:01.779544', 'Autoaudiosink is no longer under development', 63, NULL, NULL, '<20070315203601.12919.29640.malone@localhost>', NULL, NULL);
470-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (28, '2007-03-15 20:36:57.133832', 'Re: Autoaudiosink is no longer under development', 27, NULL, NULL, '<20070315203657.12919.48585.malone@localhost>', NULL, NULL);
471-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (29, '2007-03-15 20:37:27.991571', 'This is a really new title', 33, NULL, NULL, '<20070315203728.12919.76787.malone@localhost>', NULL, NULL);
472-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (30, '2007-03-15 20:37:51.544376', 'Re: Make Jokosher use autoaudiosink', 3, NULL, NULL, '<20070315203751.12919.49072.malone@localhost>', NULL, NULL);
473-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (31, '2007-03-15 20:41:18.635493', 'Copy, Cut and Delete operations should work on selections', 8, NULL, NULL, '<20070315204118.14326.61124.malonedeb@localhost>', NULL, NULL);
474-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (32, '2007-03-15 20:41:42.154264', 'Re: Copy, Cut and Delete operations should work on selections', 16, NULL, NULL, '<20070315204142.14326.82988.launchpad@localhost>', NULL, NULL);
475-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (33, '2007-03-15 20:43:14.981111', 'Re: Copy, Cut and Delete operations should work on selections', 45, NULL, NULL, '<20070315204315.14326.75272.malone@localhost>', NULL, NULL);
476-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (34, '2007-03-15 20:45:15.852052', 'Re: Copy, Cut and Delete operations should work on selections', 13, NULL, NULL, '<20070315204515.14326.38817.malone@localhost>', NULL, NULL);
477-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (35, '2007-03-15 20:45:51.817826', 'Re: Copy, Cut and Delete operations should work on selections', 9, NULL, NULL, '<20070315204551.14326.36994.malone@localhost>', NULL, NULL);
478-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (36, '2007-03-15 20:46:49.83307', 'Re: Copy, Cut and Delete operations should work on selections', 6, NULL, NULL, '<20070315204649.14326.69581.malone@localhost>', NULL, NULL);
479-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (37, '2007-07-27 20:00:58.299796', 'Launchpad CSS and JS is not testible', 12, NULL, NULL, '<20070727200058.25131.76173.malonedeb@autumn.annrky-sinzui.local>', NULL, NULL);
480-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (38, '2007-07-27 20:29:46.25854', 'Re: Launchpad CSS and JS is not testible', 12, NULL, NULL, '<20070727202946.25131.16206.malone@autumn.annrky-sinzui.local>', NULL, NULL);
481-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (39, '2007-08-09 11:39:16.836856', 'jokosher exposes personal details in its actions portlet', 63, NULL, NULL, '<20070809113916.26819.83859.malonedeb@localhost.localdomain>', NULL, NULL);
482-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (40, '2004-12-18 16:30:19.103679', 'Nonsensical bugs are useless', 16, NULL, NULL, '<20071218163019.18924.87555.malonedeb@localhost>', NULL, NULL);
483-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (41, '2007-12-18 16:30:47.889614', 'Re: Nonsensical bugs are useless', 16, NULL, NULL, '<20071218163048.18924.13348.launchpad@localhost>', NULL, NULL);
484-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (42, '2007-12-18 16:30:47.889614', 'Re: Nonsensical bugs are useless', 16, NULL, NULL, '<20071218163048.18924.86681.launchpad@localhost>', NULL, NULL);
485-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (43, '2007-12-18 16:31:34.790641', 'Re: Nonsensical bugs are useless', 62, NULL, NULL, '<20071218163134.18996.53651.launchpad@localhost>', NULL, NULL);
486-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (44, '2005-05-13 16:37:37', 'gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243614, NULL, NULL, '<4284D7D1.6010208@gmx.de>', NULL, 75);
487-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (45, '2005-05-17 18:54:29', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243615, 44, NULL, '<20050517185429.GB20786@spring.luon.net>', NULL, 76);
488-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (46, '2005-05-17 19:24:25', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243614, 45, NULL, '<428A44E9.6090802@gmx.de>', NULL, 77);
489-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (47, '2005-05-17 20:20:44', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243615, 46, NULL, '<20050517202044.GA23231@spring.luon.net>', NULL, 78);
490-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (48, '2005-06-17 14:00:11', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243616, 46, NULL, '<20050617140011.GA15638@piware.de>', NULL, 79);
491-INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw) VALUES (49, '2005-06-25 10:13:10', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243614, NULL, NULL, '<42BD2E36.9090809@gmx.de>', NULL, 81);
492+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (1, '2004-09-24 20:58:04.684057', 'PEBCAK', 16, NULL, NULL, 'foo@example.com-332342--1231', NULL, NULL, true);
493+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (3, '2004-09-24 21:17:17.153792', 'Reproduced on AIX', 12, NULL, NULL, 'sdsdfsfd', NULL, NULL, true);
494+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (4, '2004-09-24 21:24:03.922564', 'Re: Reproduced on AIX', 12, NULL, NULL, 'sdfssfdfsd', NULL, NULL, true);
495+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (5, '2004-09-24 21:29:27.407354', 'Fantastic idea, I''d really like to see this', 12, NULL, NULL, 'dxssdfsdgf', NULL, NULL, true);
496+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (6, '2004-09-24 21:35:20.125564', 'Strange bug with duplicate messages.', 12, NULL, NULL, 'sdfsfwew', NULL, NULL, true);
497+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (7, '2005-01-14 17:20:12.820778', 'Reflow problems with complex page layouts', 12, NULL, NULL, '<20050114172012.6687.51124.malonedeb@localhost.localdomain>', NULL, NULL, true);
498+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (8, '2005-01-14 17:27:03.702622', 'Firefox install instructions should be complete', 12, NULL, NULL, '<20050114172703.6687.71983.malonedeb@localhost.localdomain>', NULL, NULL, true);
499+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (9, '2005-01-14 17:35:39.548665', 'Firefox crashes when Save As dialog for a nonexistent window is closed', 12, NULL, NULL, '<20050114173539.6687.81610.malonedeb@localhost.localdomain>', NULL, NULL, true);
500+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (10, '2004-10-05 00:00:00', 'Re: Bug Title Test', 12, NULL, NULL, '<20050831114528.7616.78129.malone@localhost.localdomain>', NULL, NULL, true);
501+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (11, '2005-10-14 15:12:29.602117', 'A test bug', 16, NULL, NULL, '<20051014151229.28962.1536.malonedeb@localhost.localdomain>', NULL, NULL, true);
502+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (12, '2005-10-14 12:25:21.508923', 'Re: Newly installed plug-in doesn''t seem to be used', 16, NULL, NULL, '<20051014122521.14276.39260.lptickets@localhost.localdomain>', NULL, NULL, true);
503+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (13, '2005-10-14 13:28:11.554476', 'Re: Slow system', 12, NULL, NULL, '<20051014132811.14276.65873.lptickets@localhost.localdomain>', NULL, NULL, true);
504+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (14, '2005-10-28 09:10:17.13237', 'Printing doesn''t work', 12, NULL, 3, '<20051028091017.6690.9505.malonedeb@localhost.localdomain>', NULL, NULL, true);
505+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (15, '2006-02-23 16:42:14.080227', 'Thunderbird crashes', 16, NULL, 1, '<20060223164214.9126.7558.malonedeb@localhost.localdomain>', NULL, NULL, true);
506+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (16, '2006-06-16 17:12:54', 'Unicode™', 16, NULL, NULL, '<20060616141252.22134.71562@localhost.localdomain>', NULL, 51, true);
507+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (17, '2006-02-22 19:42:21.890299', 'another test bug', 16, NULL, 1, '<20060222194221.25842.69665.malonedeb@banzai.async.com.br>', NULL, NULL, true);
508+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (18, '2006-07-20 20:48:24.975495', 'Re: Continue playing after shutdown', 16, NULL, NULL, '<20060720204825.13277.37433.lptickets@Bourdieu.Contre.COM>', NULL, NULL, true);
509+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (19, '2006-07-20 20:49:47.551344', 'Re: mailto: problem in webpage', 16, NULL, NULL, '<20060720204947.13277.79684.lptickets@Bourdieu.Contre.COM>', NULL, NULL, true);
510+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (20, '2006-07-20 20:52:07.054216', 'Re: Installation of Java Runtime Environment for Mozilla', 16, NULL, NULL, '<20060720205207.13277.68582.lptickets@Bourdieu.Contre.COM>', NULL, NULL, true);
511+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (21, '2006-07-20 20:53:53.684848', 'Re: Play DVDs in Totem', 16, NULL, NULL, '<20060720205354.13277.37000.lptickets@Bourdieu.Contre.COM>', NULL, NULL, true);
512+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (22, '2006-07-20 20:56:35.442839', 'Re: mailto: problem in webpage', 12, NULL, NULL, '<20060720205635.13277.87295.lptickets@Bourdieu.Contre.COM>', NULL, NULL, true);
513+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (23, '2006-07-20 23:11:24.975495', 'Re: Continue playing after shutdown', 12, NULL, NULL, '<20061201222020.597.97888.lptickets@Huxley.Contre.COM>', NULL, NULL, true);
514+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (24, '2007-03-15 20:33:56.67893', 'Make Jokosher use autoaudiosink', 26, NULL, NULL, '<20070315203356.12919.76581.malonedeb@localhost>', NULL, NULL, true);
515+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (25, '2007-03-15 20:34:26.518114', 'Re: Make Jokosher use autoaudiosink', 50, NULL, NULL, '<20070315203426.12919.54628.malone@localhost>', NULL, NULL, true);
516+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (26, '2007-03-15 20:35:10.133383', 'Re: Make Jokosher use autoaudiosink', 66, NULL, NULL, '<20070315203510.12919.22697.malone@localhost>', NULL, NULL, true);
517+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (27, '2007-03-15 20:36:01.779544', 'Autoaudiosink is no longer under development', 63, NULL, NULL, '<20070315203601.12919.29640.malone@localhost>', NULL, NULL, true);
518+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (28, '2007-03-15 20:36:57.133832', 'Re: Autoaudiosink is no longer under development', 27, NULL, NULL, '<20070315203657.12919.48585.malone@localhost>', NULL, NULL, true);
519+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (29, '2007-03-15 20:37:27.991571', 'This is a really new title', 33, NULL, NULL, '<20070315203728.12919.76787.malone@localhost>', NULL, NULL, true);
520+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (30, '2007-03-15 20:37:51.544376', 'Re: Make Jokosher use autoaudiosink', 3, NULL, NULL, '<20070315203751.12919.49072.malone@localhost>', NULL, NULL, true);
521+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (31, '2007-03-15 20:41:18.635493', 'Copy, Cut and Delete operations should work on selections', 8, NULL, NULL, '<20070315204118.14326.61124.malonedeb@localhost>', NULL, NULL, true);
522+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (32, '2007-03-15 20:41:42.154264', 'Re: Copy, Cut and Delete operations should work on selections', 16, NULL, NULL, '<20070315204142.14326.82988.launchpad@localhost>', NULL, NULL, true);
523+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (33, '2007-03-15 20:43:14.981111', 'Re: Copy, Cut and Delete operations should work on selections', 45, NULL, NULL, '<20070315204315.14326.75272.malone@localhost>', NULL, NULL, true);
524+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (34, '2007-03-15 20:45:15.852052', 'Re: Copy, Cut and Delete operations should work on selections', 13, NULL, NULL, '<20070315204515.14326.38817.malone@localhost>', NULL, NULL, true);
525+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (35, '2007-03-15 20:45:51.817826', 'Re: Copy, Cut and Delete operations should work on selections', 9, NULL, NULL, '<20070315204551.14326.36994.malone@localhost>', NULL, NULL, true);
526+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (36, '2007-03-15 20:46:49.83307', 'Re: Copy, Cut and Delete operations should work on selections', 6, NULL, NULL, '<20070315204649.14326.69581.malone@localhost>', NULL, NULL, true);
527+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (37, '2007-07-27 20:00:58.299796', 'Launchpad CSS and JS is not testible', 12, NULL, NULL, '<20070727200058.25131.76173.malonedeb@autumn.annrky-sinzui.local>', NULL, NULL, true);
528+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (38, '2007-07-27 20:29:46.25854', 'Re: Launchpad CSS and JS is not testible', 12, NULL, NULL, '<20070727202946.25131.16206.malone@autumn.annrky-sinzui.local>', NULL, NULL, true);
529+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (39, '2007-08-09 11:39:16.836856', 'jokosher exposes personal details in its actions portlet', 63, NULL, NULL, '<20070809113916.26819.83859.malonedeb@localhost.localdomain>', NULL, NULL, true);
530+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (40, '2004-12-18 16:30:19.103679', 'Nonsensical bugs are useless', 16, NULL, NULL, '<20071218163019.18924.87555.malonedeb@localhost>', NULL, NULL, true);
531+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (41, '2007-12-18 16:30:47.889614', 'Re: Nonsensical bugs are useless', 16, NULL, NULL, '<20071218163048.18924.13348.launchpad@localhost>', NULL, NULL, true);
532+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (42, '2007-12-18 16:30:47.889614', 'Re: Nonsensical bugs are useless', 16, NULL, NULL, '<20071218163048.18924.86681.launchpad@localhost>', NULL, NULL, true);
533+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (43, '2007-12-18 16:31:34.790641', 'Re: Nonsensical bugs are useless', 62, NULL, NULL, '<20071218163134.18996.53651.launchpad@localhost>', NULL, NULL, true);
534+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (44, '2005-05-13 16:37:37', 'gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243614, NULL, NULL, '<4284D7D1.6010208@gmx.de>', NULL, 75, true);
535+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (45, '2005-05-17 18:54:29', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243615, 44, NULL, '<20050517185429.GB20786@spring.luon.net>', NULL, 76, true);
536+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (46, '2005-05-17 19:24:25', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243614, 45, NULL, '<428A44E9.6090802@gmx.de>', NULL, 77, true);
537+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (47, '2005-05-17 20:20:44', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243615, 46, NULL, '<20050517202044.GA23231@spring.luon.net>', NULL, 78, true);
538+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (48, '2005-06-17 14:00:11', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243616, 46, NULL, '<20050617140011.GA15638@piware.de>', NULL, 79, true);
539+INSERT INTO message (id, datecreated, subject, owner, parent, distribution, rfc822msgid, fti, raw, visible) VALUES (49, '2005-06-25 10:13:10', 'Re: Bug#308994: gnome-volume-manager: dvd+rw unreadable when automounted in burner because mounted read/write', 243614, NULL, NULL, '<42BD2E36.9090809@gmx.de>', NULL, 81, true);
540
541
542 ALTER TABLE message ENABLE TRIGGER ALL;
543@@ -3336,42 +3342,42 @@
544
545 ALTER TABLE bugmessage DISABLE TRIGGER ALL;
546
547-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (1, 2, 1, NULL, NULL, true, 0);
548-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (2, 1, 3, NULL, NULL, true, 0);
549-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (3, 1, 4, NULL, NULL, true, 1);
550-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (4, 2, 5, NULL, NULL, true, 1);
551-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (5, 2, 6, NULL, NULL, true, 2);
552-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (6, 4, 7, NULL, NULL, true, 0);
553-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (7, 5, 8, NULL, NULL, true, 0);
554-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (8, 6, 9, NULL, NULL, true, 0);
555-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (9, 3, 10, NULL, NULL, true, 0);
556-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (10, 7, 11, NULL, NULL, true, 0);
557-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (11, 8, 14, NULL, NULL, true, 0);
558-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (12, 9, 15, NULL, NULL, true, 0);
559-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (13, 10, 17, NULL, NULL, true, 0);
560-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (14, 10, 16, NULL, NULL, true, 1);
561-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (15, 11, 24, NULL, NULL, true, 0);
562-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (16, 11, 25, NULL, NULL, true, 1);
563-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (17, 11, 26, NULL, NULL, true, 2);
564-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (18, 11, 27, NULL, NULL, true, 3);
565-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (19, 11, 28, NULL, NULL, true, 4);
566-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (20, 11, 29, NULL, NULL, true, 5);
567-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (21, 11, 30, NULL, NULL, true, 6);
568-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (22, 12, 31, NULL, NULL, true, 0);
569-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (23, 12, 33, NULL, NULL, true, 1);
570-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (24, 12, 34, NULL, NULL, true, 2);
571-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (25, 12, 35, NULL, NULL, true, 3);
572-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (26, 12, 36, NULL, NULL, true, 4);
573-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (27, 13, 37, NULL, NULL, true, 0);
574-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (28, 13, 38, NULL, NULL, true, 1);
575-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (29, 14, 39, NULL, NULL, true, 0);
576-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (30, 15, 40, NULL, NULL, true, 0);
577-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (31, 15, 44, 11, '<4284D7D1.6010208@gmx.de>', true, 1);
578-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (32, 15, 45, 11, '<20050517185429.GB20786@spring.luon.net>', true, 2);
579-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (33, 15, 46, 11, '<428A44E9.6090802@gmx.de>', true, 3);
580-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (34, 15, 47, 11, '<20050517202044.GA23231@spring.luon.net>', true, 4);
581-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (35, 15, 48, 11, '<20050617140011.GA15638@piware.de>', true, 5);
582-INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (36, 15, 49, 11, '<42BD2E36.9090809@gmx.de>', true, 6);
583+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (1, 2, 1, NULL, NULL, 0);
584+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (2, 1, 3, NULL, NULL, 0);
585+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (3, 1, 4, NULL, NULL, 1);
586+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (4, 2, 5, NULL, NULL, 1);
587+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (5, 2, 6, NULL, NULL, 2);
588+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (6, 4, 7, NULL, NULL, 0);
589+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (7, 5, 8, NULL, NULL, 0);
590+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (8, 6, 9, NULL, NULL, 0);
591+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (9, 3, 10, NULL, NULL, 0);
592+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (10, 7, 11, NULL, NULL, 0);
593+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (11, 8, 14, NULL, NULL, 0);
594+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (12, 9, 15, NULL, NULL, 0);
595+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (13, 10, 17, NULL, NULL, 0);
596+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (14, 10, 16, NULL, NULL, 1);
597+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (15, 11, 24, NULL, NULL, 0);
598+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (16, 11, 25, NULL, NULL, 1);
599+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (17, 11, 26, NULL, NULL, 2);
600+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (18, 11, 27, NULL, NULL, 3);
601+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (19, 11, 28, NULL, NULL, 4);
602+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (20, 11, 29, NULL, NULL, 5);
603+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (21, 11, 30, NULL, NULL, 6);
604+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (22, 12, 31, NULL, NULL, 0);
605+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (23, 12, 33, NULL, NULL, 1);
606+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (24, 12, 34, NULL, NULL, 2);
607+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (25, 12, 35, NULL, NULL, 3);
608+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (26, 12, 36, NULL, NULL, 4);
609+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (27, 13, 37, NULL, NULL, 0);
610+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (28, 13, 38, NULL, NULL, 1);
611+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (29, 14, 39, NULL, NULL, 0);
612+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (30, 15, 40, NULL, NULL, 0);
613+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (31, 15, 44, 11, '<4284D7D1.6010208@gmx.de>', 1);
614+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (32, 15, 45, 11, '<20050517185429.GB20786@spring.luon.net>', 2);
615+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (33, 15, 46, 11, '<428A44E9.6090802@gmx.de>', 3);
616+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (34, 15, 47, 11, '<20050517202044.GA23231@spring.luon.net>', 4);
617+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (35, 15, 48, 11, '<20050617140011.GA15638@piware.de>', 5);
618+INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, index) VALUES (36, 15, 49, 11, '<42BD2E36.9090809@gmx.de>', 6);
619
620
621 ALTER TABLE bugmessage ENABLE TRIGGER ALL;
622@@ -4000,6 +4006,13 @@
623 ALTER TABLE databasecpustats ENABLE TRIGGER ALL;
624
625
626+ALTER TABLE databasediskutilization DISABLE TRIGGER ALL;
627+
628+
629+
630+ALTER TABLE databasediskutilization ENABLE TRIGGER ALL;
631+
632+
633 ALTER TABLE databasereplicationlag DISABLE TRIGGER ALL;
634
635
636@@ -4389,6 +4402,20 @@
637 ALTER TABLE featureflag ENABLE TRIGGER ALL;
638
639
640+ALTER TABLE featureflagchangelogentry DISABLE TRIGGER ALL;
641+
642+
643+
644+ALTER TABLE featureflagchangelogentry ENABLE TRIGGER ALL;
645+
646+
647+ALTER TABLE featureflagchangelogentry DISABLE TRIGGER ALL;
648+
649+
650+
651+ALTER TABLE featureflagchangelogentry ENABLE TRIGGER ALL;
652+
653+
654 ALTER TABLE flatpackagesetinclusion DISABLE TRIGGER ALL;
655
656
657@@ -9903,10 +9930,18 @@
658 ALTER TABLE projectrelationship ENABLE TRIGGER ALL;
659
660
661+ALTER TABLE publisherconfig DISABLE TRIGGER ALL;
662+
663+INSERT INTO publisherconfig (id, distribution, root_dir, base_url, copy_base_url) VALUES (1, 1, '/var/tmp/archive', 'http://archive.launchpad.dev/', 'http://rebuild-test.internal/');
664+INSERT INTO publisherconfig (id, distribution, root_dir, base_url, copy_base_url) VALUES (2, 8, '/var/tmp/archive', 'http://archive.launchpad.dev/', 'http://rebuild-test.internal/');
665+
666+
667+ALTER TABLE publisherconfig ENABLE TRIGGER ALL;
668+
669+
670 ALTER TABLE pushmirroraccess DISABLE TRIGGER ALL;
671
672
673-
674 ALTER TABLE pushmirroraccess ENABLE TRIGGER ALL;
675
676
677
678=== modified file 'database/schema/comments.sql'
679--- database/schema/comments.sql 2011-02-28 15:51:56 +0000
680+++ database/schema/comments.sql 2011-03-29 10:32:58 +0000
681@@ -271,6 +271,7 @@
682 COMMENT ON COLUMN BugTask.date_left_closed IS 'The date when this bug last transitioned out of a CLOSED status.';
683 COMMENT ON COLUMN BugTask.date_milestone_set IS 'The date when this bug was targed to the milestone that is currently set.';
684 COMMENT ON COLUMN BugTask.heat_rank IS 'The heat bin in which this bugtask appears, as a value from the BugTaskHeatRank enumeration.';
685+COMMENT ON COLUMN BugTask.heat IS 'The relevance of this bug. This value is computed periodically using bug_affects_person and other bug values.';
686
687
688 -- BugNotification
689@@ -1098,7 +1099,7 @@
690 COMMENT ON COLUMN Distribution.reviewer_whiteboard IS 'A whiteboard for Launchpad admins, registry experts and the project owners to capture the state of current issues with the project.';
691 COMMENT ON COLUMN Distribution.max_bug_heat IS 'The highest heat value across bugs for this distribution.';
692 COMMENT ON COLUMN Distribution.bug_reported_acknowledgement IS 'A message of acknowledgement to display to a bug reporter after they\'ve reported a new bug.';
693-
694+COMMENT ON COLUMN Distribution.registrant IS 'The person in launchpad who registered this distribution.';
695
696 -- DistroSeries
697
698@@ -1352,7 +1353,6 @@
699 COMMENT ON TABLE BugMessage IS 'This table maps a message to a bug. In other words, it shows that a particular message is associated with a particular bug.';
700 COMMENT ON COLUMN BugMessage.bugwatch IS 'The external bug this bug comment was imported from.';
701 COMMENT ON COLUMN BugMessage.remote_comment_id IS 'The id this bug comment has in the external bug tracker, if it is an imported comment. If it is NULL while having a bugwatch set, this comment was added in Launchpad and needs to be pushed to the external bug tracker.';
702-COMMENT ON COLUMN BugMessage.visible IS 'If false, the bug comment is hidden and should not be shown in any UI.';
703 COMMENT ON COLUMN BugMessage.index IS 'The index (used in urls) of the message in a particular bug.';
704
705 -- Messaging subsytem
706@@ -1361,6 +1361,7 @@
707 COMMENT ON COLUMN Message.subject IS 'The title text of the message, or the subject if it was an email.';
708 COMMENT ON COLUMN Message.distribution IS 'The distribution in which this message originated, if we know it.';
709 COMMENT ON COLUMN Message.raw IS 'The original unadulterated message if it arrived via email. This is required to provide access to the original, undecoded message.';
710+COMMENT ON COLUMN Message.visible IS 'If false, the message is hidden and should not be shown in any UI.';
711
712 COMMENT ON TABLE MessageChunk IS 'This table stores a single chunk of a possibly multipart message. There will be at least one row in this table for each message. text/* parts are stored in the content column. All other parts are stored in the Librarian and referenced via the blob column. If both content and blob are NULL, then this chunk has been removed (eg. offensive, legal reasons, virus etc.)';
713 COMMENT ON COLUMN MessageChunk.content IS 'Text content for this chunk of the message. This content is full text searchable.';
714@@ -1621,7 +1622,7 @@
715 COMMENT ON COLUMN DistroSeries.releasestatus IS 'The current release status of this distroseries. E.g. "pre-release freeze" or "released"';
716 COMMENT ON COLUMN DistroSeries.datereleased IS 'The date on which this distroseries was released. (obviously only valid for released distributions)';
717 COMMENT ON COLUMN DistroSeries.parent_series IS 'The parent distroseries on which this distribution is based. This is related to the inheritance stuff.';
718-COMMENT ON COLUMN DistroSeries.owner IS 'The ultimate owner of this distroseries.';
719+COMMENT ON COLUMN DistroSeries.registrant IS 'The user who registered this distroseries.';
720 COMMENT ON COLUMN DistroSeries.driver IS 'This is a person or team who can act as a driver for this specific release - note that the distribution drivers can also set goals for any release.';
721 COMMENT ON COLUMN DistroSeries.changeslist IS 'The email address (name name) of the changes announcement list for this distroseries. If NULL, no announcement mail will be sent.';
722 COMMENT ON COLUMN DistroSeries.defer_translation_imports IS 'Don''t accept PO imports for this release just now.';
723
724=== modified file 'database/schema/launchpad_session.sql'
725--- database/schema/launchpad_session.sql 2010-09-10 09:45:45 +0000
726+++ database/schema/launchpad_session.sql 2011-03-29 10:32:58 +0000
727@@ -29,3 +29,28 @@
728 GRANT SELECT, INSERT, UPDATE, DELETE ON TimeLimitedToken TO session;
729 -- And the garbo needs to run on it too.
730 GRANT SELECT, DELETE ON TimeLimitedToken TO session;
731+
732+
733+-- This helper needs to exist in the session database so the BulkPruner
734+-- can clean up unwanted sessions.
735+CREATE OR REPLACE FUNCTION cursor_fetch(cur refcursor, n integer)
736+RETURNS SETOF record LANGUAGE plpgsql AS
737+$$
738+DECLARE
739+ r record;
740+ count integer;
741+BEGIN
742+ FOR count IN 1..n LOOP
743+ FETCH FORWARD FROM cur INTO r;
744+ IF NOT FOUND THEN
745+ RETURN;
746+ END IF;
747+ RETURN NEXT r;
748+ END LOOP;
749+END;
750+$$;
751+
752+COMMENT ON FUNCTION cursor_fetch(refcursor, integer) IS
753+'Fetch the next n items from a cursor. Work around for not being able to use FETCH inside a SELECT statement.';
754+
755+GRANT EXECUTE ON FUNCTION cursor_fetch(refcursor, integer) TO session;
756
757=== added file 'database/schema/patch-2208-51-0.sql'
758--- database/schema/patch-2208-51-0.sql 1970-01-01 00:00:00 +0000
759+++ database/schema/patch-2208-51-0.sql 2011-03-29 10:32:58 +0000
760@@ -0,0 +1,18 @@
761+SET client_min_messages=ERROR;
762+
763+--Create new visible column on message.
764+ALTER TABLE Message
765+ ADD COLUMN visible BOOLEAN NOT NULL DEFAULT TRUE;
766+
767+--Migrate the data, rebuilding indexes afterwards.
768+UPDATE Message SET visible = FALSE
769+ FROM BugMessage
770+ WHERE BugMessage.message = Message.id AND BugMessage.visible IS FALSE;
771+CLUSTER Message USING message_pkey;
772+
773+--And kill the old column
774+ALTER TABLE BugMessage
775+ DROP COLUMN visible;
776+
777+--Per patch adding reqs
778+INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 51, 0);
779
780=== added file 'database/schema/patch-2208-52-0.sql'
781--- database/schema/patch-2208-52-0.sql 1970-01-01 00:00:00 +0000
782+++ database/schema/patch-2208-52-0.sql 2011-03-29 10:32:58 +0000
783@@ -0,0 +1,14 @@
784+SET client_min_messages=ERROR;
785+
786+CREATE TABLE PublisherConfig (
787+ id serial PRIMARY KEY,
788+ distribution integer NOT NULL CONSTRAINT publisherconfig__distribution__fk REFERENCES distribution,
789+ root_dir text NOT NULL,
790+ base_url text NOT NULL,
791+ copy_base_url text NOT NULL
792+);
793+
794+CREATE UNIQUE INDEX publisherconfig__distribution__idx
795+ ON PublisherConfig(distribution);
796+
797+INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 52, 0);
798
799=== added file 'database/schema/patch-2208-53-0.sql'
800--- database/schema/patch-2208-53-0.sql 1970-01-01 00:00:00 +0000
801+++ database/schema/patch-2208-53-0.sql 2011-03-29 10:32:58 +0000
802@@ -0,0 +1,20 @@
803+-- Copyright 2009 Canonical Ltd. This software is licensed under the
804+-- GNU Affero General Public License version 3 (see the file LICENSE).
805+
806+SET client_min_messages=ERROR;
807+
808+-- Add a registrant column to distributions.
809+ALTER TABLE Distribution
810+ ADD COLUMN registrant integer REFERENCES Person;
811+
812+-- Set registrant to owner for existing distros.
813+update Distribution
814+ SET registrant = owner;
815+
816+-- Add NOT NULL constraint to registrant column.
817+ALTER TABLE Distribution ALTER COLUMN registrant SET NOT NULL;
818+
819+-- Add index to registrant column.
820+CREATE INDEX distribution__registrant__idx ON Distribution(registrant);
821+
822+INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 53, 0);
823
824=== added file 'database/schema/patch-2208-54-0.sql'
825--- database/schema/patch-2208-54-0.sql 1970-01-01 00:00:00 +0000
826+++ database/schema/patch-2208-54-0.sql 2011-03-29 10:32:58 +0000
827@@ -0,0 +1,6 @@
828+SET client_min_messages=ERROR;
829+
830+ALTER TABLE distroarchseries
831+ ADD CONSTRAINT valid_architecturetag CHECK (valid_name(architecturetag));
832+
833+INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 54, 0);
834
835=== added file 'database/schema/patch-2208-55-0.sql'
836--- database/schema/patch-2208-55-0.sql 1970-01-01 00:00:00 +0000
837+++ database/schema/patch-2208-55-0.sql 2011-03-29 10:32:58 +0000
838@@ -0,0 +1,24 @@
839+-- Copyright 2011 Canonical Ltd. This software is licensed under the
840+-- GNU Affero General Public License version 3 (see the file LICENSE).
841+
842+SET client_min_messages=ERROR;
843+
844+-- Convert DistroSeriesDifference source_version, parent_source_version,
845+-- and base_version types to debversion.
846+
847+-- Change types.
848+ALTER TABLE DistroSeriesDifference
849+ ALTER COLUMN source_version TYPE debversion,
850+ ALTER COLUMN parent_source_version TYPE debversion,
851+ ALTER COLUMN base_version TYPE debversion;
852+
853+-- Create indexes.
854+CREATE INDEX distroseriesdifference__source_version__idx
855+ ON DistroSeriesDifference(source_version);
856+CREATE INDEX distroseriesdifference__parent_source_version__idx
857+ ON DistroSeriesDifference(parent_source_version);
858+CREATE INDEX distroseriesdifference__base_version__idx
859+ ON DistroSeriesDifference(base_version);
860+
861+INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 55, 0);
862+
863
864=== added file 'database/schema/patch-2208-56-0.sql'
865--- database/schema/patch-2208-56-0.sql 1970-01-01 00:00:00 +0000
866+++ database/schema/patch-2208-56-0.sql 2011-03-29 10:32:58 +0000
867@@ -0,0 +1,33 @@
868+-- Copyright 2009 Canonical Ltd. This software is licensed under the
869+-- GNU Affero General Public License version 3 (see the file LICENSE).
870+
871+SET client_min_messages=ERROR;
872+
873+-- Renaming owner to registrant for DistroSeries
874+
875+-- Rename owner into registrant.
876+ALTER TABLE distroseries
877+ RENAME COLUMN owner TO registrant;
878+
879+-- 'Rename' constraint.
880+ALTER TABLE distroseries
881+ ADD CONSTRAINT distroseries__registrant__fk
882+ FOREIGN KEY (registrant) REFERENCES Person(id);
883+ALTER TABLE distroseries
884+ DROP CONSTRAINT distroseries__owner__fk;
885+
886+-- Rename index.
887+ALTER INDEX distroseries__owner__idx
888+ RENAME TO distroseries__registrant__idx;
889+
890+-- Rename old misnamed indexes.
891+-- Don't rename primary key indexes though, as this causes Slony-I to explode.
892+--ALTER INDEX distrorelease_pkey
893+-- RENAME TO distroseries_pkey;
894+ALTER INDEX distrorelease_distribution_key
895+ RENAME TO distrorelease__distribution__name__key;
896+ALTER INDEX distrorelease_distro_release_unique
897+ RENAME TO distroseries__distribution__id__key;
898+
899+
900+INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 56, 0);
901
902=== added file 'database/schema/patch-2208-57-1.sql'
903--- database/schema/patch-2208-57-1.sql 1970-01-01 00:00:00 +0000
904+++ database/schema/patch-2208-57-1.sql 2011-03-29 10:32:58 +0000
905@@ -0,0 +1,14 @@
906+-- Copyright 2011 Canonical Ltd. This software is licensed under the
907+-- GNU Affero General Public License version 3 (see the file LICENSE).
908+
909+SET client_min_messages=ERROR;
910+
911+-- Partial index for queue processing view : the lopsided data makes this
912+-- necessary (millions of rows matching the archive, 100's of rows match the
913+-- query).
914+
915+
916+CREATE INDEX packageupload__id_distroseries__archive__idx ON
917+ packageupload(id, distroseries, archive) WHERE status IN (0,1);
918+
919+INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 57, 1);
920
921=== added file 'database/schema/patch-2208-59-0.sql'
922--- database/schema/patch-2208-59-0.sql 1970-01-01 00:00:00 +0000
923+++ database/schema/patch-2208-59-0.sql 2011-03-29 10:32:58 +0000
924@@ -0,0 +1,38 @@
925+-- Copyright 2009 Canonical Ltd. This software is licensed under the
926+-- GNU Affero General Public License version 3 (see the file LICENSE).
927+
928+SET client_min_messages=ERROR;
929+
930+-- Add bugtask heat denormalisation for sort efficiency. We will enforce non-null subsequently;
931+
932+ALTER TABLE bugtask ADD COLUMN heat integer;
933+
934+UPDATE bugtask SET heat=bug.heat FROM bug WHERE bug.id=bugtask.bug;
935+
936+ALTER TABLE bugtask ALTER COLUMN heat SET NOT NULL;
937+ALTER TABLE bugtask ALTER COLUMN heat SET DEFAULT 0;
938+
939+-- Primary use case is 'sort by heat in a context'; for no context we can use
940+-- the bug.heat column & index.
941+
942+-- contexts - product, productseries, distro sourcepackage, distroseries sourcepackage, distro and distroseries.
943+-- product context
944+CREATE INDEX bugtask__product__heat__idx ON bugtask USING btree (product, heat) WHERE product IS NOT NULL;
945+-- productseries context
946+CREATE INDEX bugtask__productseries__heat__idx ON bugtask USING btree (productseries, heat) WHERE productseries IS NOT NULL;
947+-- distribution context (handles distribution and distribution source package queries)
948+CREATE INDEX bugtask__distribution_sourcepackage__heat__idx ON bugtask USING btree (distribution, sourcepackagename, heat) WHERE distribution IS NOT NULL;
949+-- distroseries context (handles series and series source package queries)
950+CREATE INDEX bugtask__distroseries_sourcepackage__heat__idx ON bugtask USING btree (distroseries, sourcepackagename, heat) WHERE distroseries IS NOT NULL;
951+
952+-- may wish to drop these indices as superceded by the above; if so should
953+-- CLUSTER the distribution_sourcepackagename index.
954+-- DROP INDEX bugtask__distribution__sourcepackagename__idx
955+-- DROP INDEX bugtask__distroseries__sourcepackagename__idx
956+
957+-- When a bug is changed we copy the heat; brand new bugs will not have their
958+-- heat copied until they are recalculated (but equally brand new bugs have 0
959+-- heat).
960+CREATE TRIGGER bug_to_bugtask_heat AFTER UPDATE ON bug FOR EACH ROW EXECUTE PROCEDURE bug_update_heat_copy_to_bugtask();
961+
962+INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 59, 0);
963
964=== modified file 'database/schema/security.cfg'
965--- database/schema/security.cfg 2011-03-29 03:35:23 +0000
966+++ database/schema/security.cfg 2011-03-29 10:32:58 +0000
967@@ -260,6 +260,7 @@
968 public.productrelease = SELECT, INSERT, UPDATE, DELETE
969 public.productreleasefile = SELECT, INSERT, DELETE
970 public.productseriescodeimport = SELECT, INSERT, UPDATE
971+public.publisherconfig = SELECT, INSERT, UPDATE, DELETE
972 public.project = SELECT
973 public.projectbounty = SELECT, INSERT, UPDATE
974 public.questionbug = SELECT, INSERT, DELETE
975@@ -860,6 +861,8 @@
976 public.packagesetgroup = SELECT
977 public.packagesetsources = SELECT, INSERT, UPDATE, DELETE
978 public.packagesetinclusion = SELECT, INSERT, UPDATE, DELETE
979+# INSERT for publisherconfig only required for the test suite.
980+public.publisherconfig = SELECT, INSERT
981 public.flatpackagesetinclusion = SELECT, INSERT, UPDATE, DELETE
982 public.binarypackagepublishinghistory = SELECT, INSERT, UPDATE, DELETE
983 public.sourcepackagepublishinghistory = SELECT, INSERT, UPDATE, DELETE
984@@ -962,6 +965,7 @@
985 public.teamparticipation = SELECT
986 public.translationimportqueueentry = SELECT, INSERT, UPDATE
987 public.translationtemplatesbuild = SELECT, INSERT
988+public.publisherconfig = SELECT
989
990 [ppa-apache-log-parser]
991 type=user
992@@ -1431,6 +1435,7 @@
993 public.componentselection = SELECT
994 public.sectionselection = SELECT
995 public.packagediff = SELECT, UPDATE
996+public.publisherconfig = SELECT
997
998 # Librarian stuff
999 public.libraryfilealias = SELECT, INSERT
1000@@ -2276,6 +2281,7 @@
1001 public.distroseries = SELECT
1002 public.emailaddress = SELECT
1003 public.person = SELECT
1004+public.publisherconfig = SELECT
1005 public.teammembership = SELECT
1006 public.teamparticipation = SELECT
1007
1008
1009=== modified file 'database/schema/security.py'
1010--- database/schema/security.py 2010-11-11 14:13:19 +0000
1011+++ database/schema/security.py 2011-03-29 10:32:58 +0000
1012@@ -19,7 +19,6 @@
1013
1014 from canonical.database.sqlbase import connect
1015 from canonical.launchpad.scripts import logger_options, logger, db_options
1016-from lp.services.log.loglevels import DEBUG2
1017 from fti import quote_identifier
1018 import replication.helpers
1019
1020@@ -36,6 +35,7 @@
1021
1022
1023 class DbObject(object):
1024+
1025 def __init__(
1026 self, schema, name, type_, owner, arguments=None, language=None):
1027 self.schema = schema
1028@@ -50,9 +50,7 @@
1029
1030 @property
1031 def fullname(self):
1032- fn = "%s.%s" % (
1033- self.schema, self.name
1034- )
1035+ fn = "%s.%s" % (self.schema, self.name)
1036 if self.type == 'function':
1037 fn = "%s(%s)" % (fn, self.arguments)
1038 return fn
1039@@ -67,6 +65,7 @@
1040 class DbSchema(dict):
1041 groups = None # List of groups defined in the db
1042 users = None # List of users defined in the db
1043+
1044 def __init__(self, con):
1045 super(DbSchema, self).__init__()
1046 cur = con.cursor()
1047@@ -113,8 +112,7 @@
1048 """)
1049 for schema, name, arguments, owner, language in cur.fetchall():
1050 self['%s.%s(%s)' % (schema, name, arguments)] = DbObject(
1051- schema, name, 'function', owner, arguments, language
1052- )
1053+ schema, name, 'function', owner, arguments, language)
1054 # Pull a list of groups
1055 cur.execute("SELECT groname FROM pg_group")
1056 self.groups = [r[0] for r in cur.fetchall()]
1057@@ -129,6 +127,7 @@
1058
1059
1060 class CursorWrapper(object):
1061+
1062 def __init__(self, cursor):
1063 self.__dict__['_cursor'] = cursor
1064
1065@@ -149,7 +148,7 @@
1066
1067
1068 CONFIG_DEFAULTS = {
1069- 'groups': ''
1070+ 'groups': '',
1071 }
1072
1073
1074@@ -192,6 +191,120 @@
1075 quote_identifier(identifier) for identifier in identifiers])
1076
1077
1078+class PermissionGatherer:
1079+ """Gather permissions for bulk granting or revocation.
1080+
1081+ Processing such statements in bulk (with multiple users, tables,
1082+ or permissions in one statement) is faster than issuing very large
1083+ numbers of individual statements.
1084+ """
1085+
1086+ def __init__(self, entity_keyword):
1087+ """Gather for SQL entities of one kind (TABLE, FUNCTION, SEQUENCE).
1088+
1089+ :param entity_keyword: The SQL keyword for the kind of entity
1090+ that permissions will be gathered for.
1091+ """
1092+ self.entity_keyword = entity_keyword
1093+ self.permissions = defaultdict(dict)
1094+
1095+ def add(self, permission, entity, principal, is_group=False):
1096+ """Add a permission.
1097+
1098+ Add all privileges you want to grant or revoke first, then use
1099+ `grant` or `revoke` to process them in bulk.
1100+
1101+ :param permission: A permission: SELECT, INSERT, EXECUTE, etc.
1102+ :param entity: Table, function, or sequence on which to grant
1103+ or revoke a privilege.
1104+ :param principal: User or group to which the privilege should
1105+ apply.
1106+ :param is_group: Is `principal` a group?
1107+ """
1108+ if is_group:
1109+ full_principal = "GROUP " + principal
1110+ else:
1111+ full_principal = principal
1112+ self.permissions[permission].setdefault(entity, set()).add(
1113+ full_principal)
1114+
1115+ def tabulate(self):
1116+ """Group privileges into single-statement work items.
1117+
1118+ Each entry returned by this method represents a batch of
1119+ privileges that can be granted or revoked in a single SQL
1120+ statement.
1121+
1122+ :return: A sequence of tuples of strings: permission(s) to
1123+ grant/revoke, entity or entities to act on, and principal(s)
1124+ to grant or revoke for. Each is a string.
1125+ """
1126+ result = []
1127+ for permission, parties in self.permissions.iteritems():
1128+ for entity, principals in parties.iteritems():
1129+ result.append(
1130+ (permission, entity, ", ".join(principals)))
1131+ return result
1132+
1133+ def countPermissions(self):
1134+ """Count the number of different permissions."""
1135+ return len(self.permissions)
1136+
1137+ def countEntities(self):
1138+ """Count the number of different entities."""
1139+ return len(set(sum([
1140+ entities.keys()
1141+ for entities in self.permissions.itervalues()], [])))
1142+
1143+ def countPrincipals(self):
1144+ """Count the number of different principals."""
1145+ principals = set()
1146+ for entities_and_principals in self.permissions.itervalues():
1147+ for extra_principals in entities_and_principals.itervalues():
1148+ principals.update(extra_principals)
1149+ return len(principals)
1150+
1151+ def grant(self, cur):
1152+ """Grant all gathered permissions.
1153+
1154+ :param cur: A cursor to operate on.
1155+ """
1156+ log.debug(
1157+ "Granting %d permission(s) on %d %s(s) for %d user(s)/group(s).",
1158+ self.countPermissions(),
1159+ self.countEntities(),
1160+ self.entity_keyword,
1161+ self.countPrincipals())
1162+ grant_count = 0
1163+ for permissions, entities, principals in self.tabulate():
1164+ grant = "GRANT %s ON %s %s TO %s" % (
1165+ permissions, self.entity_keyword, entities, principals)
1166+ log.debug2(grant)
1167+ cur.execute(grant)
1168+ grant_count += 1
1169+ log.debug("Issued %d GRANT statement(s).", grant_count)
1170+
1171+ def revoke(self, cur):
1172+ """Revoke all gathered permissions.
1173+
1174+ :param cur: A cursor to operate on.
1175+ """
1176+ log.debug(
1177+ "Revoking %d permission(s) on %d %s(s) for %d user(s)/group(s).",
1178+ self.countPermissions(),
1179+ self.countEntities(),
1180+ self.entity_keyword,
1181+ self.countPrincipals())
1182+ revoke_count = 0
1183+ for permissions, entities, principals in self.tabulate():
1184+ revoke = "REVOKE %s ON %s %s FROM %s" % (
1185+ permissions, self.entity_keyword, entities, principals)
1186+ log.debug2(revoke)
1187+ cur.execute(revoke)
1188+ revoke_count += 1
1189+ log.debug("Issued %d REVOKE statement(s).", revoke_count)
1190+
1191+
1192 def reset_permissions(con, config, options):
1193 schema = DbSchema(con)
1194 all_users = list_identifiers(schema.users)
1195@@ -264,8 +377,7 @@
1196 continue
1197 groups = [
1198 g.strip() for g in config.get(user, 'groups', '').split(',')
1199- if g.strip()
1200- ]
1201+ if g.strip()]
1202 # Read-Only users get added to Read-Only groups.
1203 if user.endswith('_ro'):
1204 groups = ['%s_ro' % group for group in groups]
1205@@ -287,36 +399,37 @@
1206 cur.execute("ALTER TABLE %s OWNER TO %s" % (
1207 obj.fullname, quote_identifier(options.owner)))
1208
1209- # Revoke all privs from known groups. Don't revoke anything for
1210- # users or groups not defined in our security.cfg.
1211- revocations = defaultdict(list)
1212- # Gather all revocations.
1213- for section_name in config.sections():
1214- for obj in schema.values():
1215- if obj.type == 'function':
1216- t = 'FUNCTION'
1217- else:
1218- t = 'TABLE'
1219-
1220- item = "%s %s" % (t, obj.fullname)
1221-
1222- roles = [section_name]
1223- if section_name != 'public':
1224- roles.append(section_name + '_ro')
1225-
1226- revocations[item] += roles
1227-
1228- if schema.has_key(obj.seqname):
1229- revocations["SEQUENCE %s" % obj.seqname] += roles
1230-
1231- # Now batch up and execute all revocations.
1232 if options.revoke:
1233- for item, roles in revocations.iteritems():
1234- if roles:
1235- log.debug("Revoking permissions on %s", item)
1236- cur.execute(
1237- "REVOKE ALL ON %s FROM %s"
1238- % (item, list_identifiers(roles)))
1239+ # Revoke all privs from known groups. Don't revoke anything for
1240+ # users or groups not defined in our security.cfg.
1241+ table_revocations = PermissionGatherer("TABLE")
1242+ function_revocations = PermissionGatherer("FUNCTION")
1243+ sequence_revocations = PermissionGatherer("SEQUENCE")
1244+
1245+ # Gather all revocations.
1246+ for section_name in config.sections():
1247+ role = quote_identifier(section_name)
1248+ if section_name == 'public':
1249+ ro_role = None
1250+ else:
1251+ ro_role = quote_identifier(section_name + "_ro")
1252+
1253+ for obj in schema.values():
1254+ if obj.type == 'function':
1255+ gatherer = function_revocations
1256+ else:
1257+ gatherer = table_revocations
1258+
1259+ gatherer.add("ALL", obj.fullname, role)
1260+
1261+ if obj.seqname in schema:
1262+ sequence_revocations.add("ALL", obj.seqname, role)
1263+ if ro_role is not None:
1264+ sequence_revocations.add("ALL", obj.seqname, ro_role)
1265+
1266+ table_revocations.revoke(cur)
1267+ function_revocations.revoke(cur)
1268+ sequence_revocations.revoke(cur)
1269 else:
1270 log.info("Not revoking permissions on database objects")
1271
1272@@ -327,8 +440,9 @@
1273
1274 # Set permissions as per config file
1275
1276- functions = set()
1277- tables = set()
1278+ table_permissions = PermissionGatherer("TABLE")
1279+ function_permissions = PermissionGatherer("FUNCTION")
1280+ sequence_permissions = PermissionGatherer("SEQUENCE")
1281
1282 for username in config.sections():
1283 for obj_name, perm in config.items(username):
1284@@ -355,73 +469,42 @@
1285 log.debug(
1286 "Granting %s on %s to %s", perm, obj.fullname, who)
1287 if obj.type == 'function':
1288- functions.add(obj.fullname)
1289- cur.execute(
1290- 'GRANT %s ON FUNCTION %s TO %s'
1291- % (perm, obj.fullname, who))
1292- cur.execute(
1293- 'GRANT EXECUTE ON FUNCTION %s TO GROUP %s'
1294- % (obj.fullname, who_ro))
1295+ function_permissions.add(perm, obj.fullname, who)
1296+ function_permissions.add("EXECUTE", obj.fullname, who_ro)
1297+ function_permissions.add(
1298+ "EXECUTE", obj.fullname, "read", is_group=True)
1299+ function_permissions.add(
1300+ "ALL", obj.fullname, "admin", is_group=True)
1301 else:
1302- tables.add(obj.fullname)
1303- cur.execute(
1304- 'GRANT %s ON TABLE %s TO %s'
1305- % (perm, obj.fullname, who))
1306- cur.execute(
1307- 'GRANT SELECT ON TABLE %s TO %s'
1308- % (obj.fullname, who_ro))
1309- if schema.has_key(obj.seqname):
1310+ table_permissions.add(
1311+ "ALL", obj.fullname, "admin", is_group=True)
1312+ table_permissions.add(perm, obj.fullname, who)
1313+ table_permissions.add("SELECT", obj.fullname, who_ro)
1314+ is_secure = (obj.fullname in SECURE_TABLES)
1315+ if not is_secure:
1316+ table_permissions.add(
1317+ "SELECT", obj.fullname, "read", is_group=True)
1318+ if obj.seqname in schema:
1319 if 'INSERT' in perm:
1320 seqperm = 'USAGE'
1321 elif 'SELECT' in perm:
1322 seqperm = 'SELECT'
1323- log.debug(
1324- "Granting %s on %s to %s", seqperm, obj.seqname, who)
1325- cur.execute(
1326- 'GRANT %s ON %s TO %s'
1327- % (seqperm, obj.seqname, who))
1328- if obj.fullname not in SECURE_TABLES:
1329- cur.execute(
1330- 'GRANT SELECT ON %s TO GROUP read'
1331- % obj.seqname)
1332- cur.execute(
1333- 'GRANT ALL ON %s TO GROUP admin'
1334- % obj.seqname)
1335- cur.execute(
1336- 'GRANT SELECT ON %s TO %s'
1337- % (obj.seqname, who_ro))
1338+ sequence_permissions.add(seqperm, obj.seqname, who)
1339+ if not is_secure:
1340+ sequence_permissions.add(
1341+ "SELECT", obj.seqname, "read", is_group=True)
1342+ sequence_permissions.add("SELECT", obj.seqname, who_ro)
1343+ sequence_permissions.add(
1344+ "ALL", obj.seqname, "admin", is_group=True)
1345
1346- # A few groups get special rights to every function or table. Batch
1347- # the schema manipulations to save time.
1348- log.debug(
1349- "Granting permissions to %d functions to magic roles",
1350- len(functions))
1351- if functions:
1352- functions_text = ', '.join(functions)
1353- cur.execute(
1354- "GRANT EXECUTE ON FUNCTION %s TO GROUP read" % functions_text)
1355- cur.execute(
1356- "GRANT ALL ON FUNCTION %s TO GROUP admin" % functions_text)
1357- log.debug(
1358- "Granting permissions to %d tables to admin role",
1359- len(tables))
1360- if tables:
1361- tables_text = ', '.join(tables)
1362- cur.execute("GRANT ALL ON TABLE %s TO GROUP admin" % tables_text)
1363- nonsecure_tables = tables - set(SECURE_TABLES)
1364- log.debug(
1365- "Granting permissions to %d nonsecure tables to read role",
1366- len(nonsecure_tables))
1367- if nonsecure_tables:
1368- nonsecure_tables_text = ', '.join(nonsecure_tables)
1369- cur.execute(
1370- "GRANT SELECT ON TABLE %s TO GROUP read" % nonsecure_tables_text)
1371+ function_permissions.grant(cur)
1372+ table_permissions.grant(cur)
1373+ sequence_permissions.grant(cur)
1374
1375 # Set permissions on public schemas
1376 public_schemas = [
1377- s.strip() for s in config.get('DEFAULT','public_schemas').split(',')
1378- if s.strip()
1379- ]
1380+ s.strip() for s in config.get('DEFAULT', 'public_schemas').split(',')
1381+ if s.strip()]
1382 log.debug("Granting access to %d public schemas", len(public_schemas))
1383 for schema_name in public_schemas:
1384 cur.execute("GRANT USAGE ON SCHEMA %s TO PUBLIC" % (
1385@@ -444,7 +527,7 @@
1386 if obj not in found:
1387 forgotten.add(obj)
1388 forgotten = [obj.fullname for obj in forgotten
1389- if obj.type in ['table','function','view']]
1390+ if obj.type in ['table', 'function', 'view']]
1391 if forgotten:
1392 log.warn('No permissions specified for %r', forgotten)
1393
1394
1395=== modified file 'database/schema/trusted.sql'
1396--- database/schema/trusted.sql 2011-03-01 17:07:13 +0000
1397+++ database/schema/trusted.sql 2011-03-29 10:32:58 +0000
1398@@ -1954,6 +1954,20 @@
1399 return int(total_heat)
1400 $$;
1401
1402+CREATE OR REPLACE FUNCTION bug_update_heat_copy_to_bugtask()
1403+RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path TO public AS
1404+$$
1405+BEGIN
1406+ IF NEW.heat != OLD.heat THEN
1407+ UPDATE bugtask SET heat=NEW.heat WHERE bugtask.bug=NEW.id;
1408+ END IF;
1409+ RETURN NULL; -- Ignored - this is an AFTER trigger
1410+END;
1411+$$;
1412+
1413+COMMENT ON FUNCTION bug_update_heat_copy_to_bugtask() IS
1414+'Copies bug heat to bugtasks when the bug is changed. Runs on UPDATE only because INSERTs do not have bugtasks at the point of insertion.';
1415+
1416 -- This function is not STRICT, since it needs to handle
1417 -- dateexpected when it is NULL.
1418 CREATE OR REPLACE FUNCTION milestone_sort_key(
1419
1420=== modified file 'lib/canonical/config/schema-lazr.conf'
1421--- lib/canonical/config/schema-lazr.conf 2011-03-18 01:17:42 +0000
1422+++ lib/canonical/config/schema-lazr.conf 2011-03-29 10:32:58 +0000
1423@@ -24,14 +24,11 @@
1424 # datatype: string
1425 dbuser: archivepublisher
1426
1427-# Base directory for distribution archives.
1428-# datatype: string
1429-root: /var/tmp/archive/
1430-
1431-# External base URL for distribution archives.
1432-# datatype: string
1433-base_url: http://ftpmaster.internal/
1434-copy_base_url: http://rebuild-test.internal/
1435+# XXX: wgrant 2011-03-22 bug=739992: These three keys are obsolete and
1436+# should be removed after 11.04 is released.
1437+root: none
1438+base_url: none
1439+copy_base_url: none
1440
1441
1442 [binaryfile_expire]
1443
1444=== modified file 'lib/canonical/launchpad/database/message.py'
1445--- lib/canonical/launchpad/database/message.py 2011-03-04 03:48:11 +0000
1446+++ lib/canonical/launchpad/database/message.py 2011-03-29 10:32:58 +0000
1447@@ -37,6 +37,7 @@
1448 )
1449 import pytz
1450 from sqlobject import (
1451+ BoolCol,
1452 ForeignKey,
1453 IntCol,
1454 SQLMultipleJoin,
1455@@ -131,6 +132,7 @@
1456 raw = ForeignKey(foreignKey='LibraryFileAlias', dbName='raw',
1457 default=None)
1458 bugattachments = SQLMultipleJoin('BugAttachment', joinColumn='_message')
1459+ visible = BoolCol(notNull=True, default=True)
1460
1461 def __repr__(self):
1462 return "<Message at 0x%x id=%s>" % (id(self), self.id)
1463
1464=== modified file 'lib/canonical/launchpad/interfaces/message.py'
1465--- lib/canonical/launchpad/interfaces/message.py 2010-10-03 15:30:06 +0000
1466+++ lib/canonical/launchpad/interfaces/message.py 2011-03-29 10:32:58 +0000
1467@@ -104,6 +104,8 @@
1468 title=_("Whether or not the title of this message "
1469 "is different to that of its parent."),
1470 readonly=True)
1471+ visible = Bool(title=u"This message is visible or not.", required=False,
1472+ default=True)
1473
1474 bugattachments = exported(
1475 CollectionField(
1476
1477=== modified file 'lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt'
1478--- lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt 2011-03-23 16:28:51 +0000
1479+++ lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt 2011-03-29 10:32:58 +0000
1480@@ -222,7 +222,7 @@
1481 >>> check("/ubuntu/hoary")
1482 >>> check("/ubuntu/hoary/+edit", auth=True)
1483 >>> check("/ubuntu/hoary/+specs")
1484->>> check("/ubuntu/hoary/+reassign", auth=True)
1485+>>> check_not_found("/ubuntu/hoary/+reassign")
1486 >>> check("/ubuntu/hoary/+packaging")
1487 >>> check("/ubuntu/hoary/+bugs")
1488
1489
1490=== modified file 'lib/canonical/launchpad/pagetests/webservice/xx-hide-comments.txt'
1491--- lib/canonical/launchpad/pagetests/webservice/xx-hide-comments.txt 2010-10-11 16:17:45 +0000
1492+++ lib/canonical/launchpad/pagetests/webservice/xx-hide-comments.txt 2011-03-29 10:32:58 +0000
1493@@ -27,7 +27,7 @@
1494 >>> bug_11 = getUtility(IBugSet).get(11)
1495 >>> bug_message = getUtility(IBugMessageSet).getByBugAndMessage(
1496 ... bug_11, bug_11.messages[2])
1497- >>> bug_message.visible
1498+ >>> bug_message.message.visible
1499 False
1500 >>> logout()
1501
1502@@ -46,7 +46,7 @@
1503 >>> bug_11 = getUtility(IBugSet).get(11)
1504 >>> bug_message = getUtility(IBugMessageSet).getByBugAndMessage(
1505 ... bug_11, bug_11.messages[2])
1506- >>> bug_message.visible
1507+ >>> bug_message.message.visible
1508 True
1509 >>> logout()
1510
1511
1512=== modified file 'lib/canonical/launchpad/security.py'
1513--- lib/canonical/launchpad/security.py 2011-02-21 15:22:33 +0000
1514+++ lib/canonical/launchpad/security.py 2011-03-29 10:32:58 +0000
1515@@ -35,6 +35,7 @@
1516 IOAuthAccessToken,
1517 IOAuthRequestToken,
1518 )
1519+from canonical.launchpad.interfaces.message import IMessage
1520 from canonical.launchpad.webapp.authorization import check_permission
1521 from canonical.launchpad.webapp.interfaces import (
1522 IAuthorization,
1523@@ -45,6 +46,7 @@
1524 from lp.answers.interfaces.question import IQuestion
1525 from lp.answers.interfaces.questionsperson import IQuestionsPerson
1526 from lp.answers.interfaces.questiontarget import IQuestionTarget
1527+from lp.archivepublisher.interfaces.publisherconfig import IPublisherConfig
1528 from lp.blueprints.interfaces.specification import (
1529 ISpecification,
1530 ISpecificationPublic,
1531@@ -985,9 +987,10 @@
1532 usedfor = IDistroSeries
1533
1534
1535-class EditDistroSeriesByOwnersOrDistroOwnersOrAdmins(AuthorizationBase):
1536- """The owner of the distro series should be able to modify some of the
1537- fields on the IDistroSeries
1538+class EditDistroSeriesByReleaseManagerOrDistroOwnersOrAdmins(
1539+ AuthorizationBase):
1540+ """The owner of the distro series (i.e. the owner of the distribution)
1541+ should be able to modify some of the fields on the IDistroSeries
1542
1543 NB: there is potential for a great mess if this is not done correctly so
1544 please consult with Kiko and MDZ on the mailing list before modifying
1545@@ -1002,8 +1005,7 @@
1546 # The series driver (release manager) may edit a series if the
1547 # distribution is an `IDerivativeDistribution`
1548 return True
1549- return (user.inTeam(self.obj.owner) or
1550- user.inTeam(self.obj.distribution.owner) or
1551+ return (user.inTeam(self.obj.distribution.owner) or
1552 user.in_admin)
1553
1554
1555@@ -2052,7 +2054,7 @@
1556
1557 class AdminDistroSeriesLanguagePacks(
1558 OnlyRosettaExpertsAndAdmins,
1559- EditDistroSeriesByOwnersOrDistroOwnersOrAdmins):
1560+ EditDistroSeriesByReleaseManagerOrDistroOwnersOrAdmins):
1561 permission = 'launchpad.LanguagePacksAdmin'
1562 usedfor = IDistroSeries
1563
1564@@ -2063,10 +2065,10 @@
1565 edit distroseries or members of IDistribution.language_pack_admin team
1566 are able to change the language packs available.
1567 """
1568+ EditDS = EditDistroSeriesByReleaseManagerOrDistroOwnersOrAdmins
1569 return (
1570 OnlyRosettaExpertsAndAdmins.checkAuthenticated(self, user) or
1571- EditDistroSeriesByOwnersOrDistroOwnersOrAdmins.checkAuthenticated(
1572- self, user) or
1573+ EditDS.checkAuthenticated(self, user) or
1574 user.inTeam(self.obj.distribution.language_pack_admin))
1575
1576
1577@@ -2587,3 +2589,16 @@
1578 if parent is None:
1579 return False
1580 return check_permission(self.permission, parent)
1581+
1582+
1583+class SetMessageVisibility(AuthorizationBase):
1584+ permission = 'launchpad.Admin'
1585+ usedfor = IMessage
1586+
1587+ def checkAuthenticated(self, user):
1588+ """Admins and registry admins can set bug comment visibility."""
1589+ return (user.in_admin or user.in_registry_experts)
1590+
1591+
1592+class ViewPublisherConfig(AdminByAdminsTeam):
1593+ usedfor = IPublisherConfig
1594
1595=== modified file 'lib/canonical/launchpad/zcml/message.zcml'
1596--- lib/canonical/launchpad/zcml/message.zcml 2010-10-03 15:30:06 +0000
1597+++ lib/canonical/launchpad/zcml/message.zcml 2011-03-29 10:32:58 +0000
1598@@ -9,11 +9,12 @@
1599 i18n_domain="launchpad">
1600
1601 <!-- Message -->
1602- <class class="canonical.launchpad.database.message.Message">
1603+ <class
1604+ class="canonical.launchpad.database.message.Message">
1605 <allow interface="canonical.launchpad.interfaces.message.IMessage" />
1606 <require
1607- permission="zope.Public"
1608- set_schema="canonical.launchpad.interfaces.message.IMessage" />
1609+ permission="launchpad.Admin"
1610+ set_attributes="visible"/>
1611 </class>
1612
1613 <class class="canonical.launchpad.interfaces.message.IndexedMessage">
1614
1615=== modified file 'lib/lp/app/stories/launchpad-root/site-search.txt'
1616--- lib/lp/app/stories/launchpad-root/site-search.txt 2011-02-17 17:02:54 +0000
1617+++ lib/lp/app/stories/launchpad-root/site-search.txt 2011-03-29 10:32:58 +0000
1618@@ -181,9 +181,11 @@
1619 >>> print_search_results()
1620 Exact matches
1621 Ubuntu
1622- Ubuntu is a new approach to Linux Distribution that includes regular
1623- releases, and a simplified single-CD installation system.
1624- Registered on 2006-10-16
1625+ Ubuntu is a new approach to Linux Distribution that includes ...
1626+ Registered
1627+ by
1628+ Registry Administrators
1629+ on 2006-10-16
1630
1631 The user enters the number 1, and he sees a bug and a question in the
1632 "Exact matches" section.
1633
1634=== modified file 'lib/lp/archivepublisher/config.py'
1635--- lib/lp/archivepublisher/config.py 2010-10-17 13:35:20 +0000
1636+++ lib/lp/archivepublisher/config.py 2011-03-29 10:32:58 +0000
1637@@ -8,7 +8,10 @@
1638
1639 import os
1640
1641+from zope.component import getUtility
1642+
1643 from canonical.config import config
1644+from lp.archivepublisher.interfaces.publisherconfig import IPublisherConfigSet
1645 from lp.soyuz.enums import ArchivePurpose
1646
1647
1648@@ -24,9 +27,11 @@
1649 """
1650 pubconf = Config()
1651 ppa_config = config.personalpackagearchive
1652+ db_pubconf = getUtility(
1653+ IPublisherConfigSet).getByDistribution(archive.distribution)
1654
1655 pubconf.temproot = os.path.join(
1656- config.archivepublisher.root, '%s-temp' % archive.distribution.name)
1657+ db_pubconf.root_dir, '%s-temp' % archive.distribution.name)
1658
1659 if archive.is_ppa:
1660 if archive.private:
1661@@ -40,7 +45,7 @@
1662 pubconf.distroroot, archive.owner.name, archive.name,
1663 archive.distribution.name)
1664 elif archive.is_main:
1665- pubconf.distroroot = config.archivepublisher.root
1666+ pubconf.distroroot = db_pubconf.root_dir
1667 pubconf.archiveroot = os.path.join(
1668 pubconf.distroroot, archive.distribution.name)
1669 if archive.purpose == ArchivePurpose.PARTNER:
1670@@ -48,7 +53,7 @@
1671 elif archive.purpose == ArchivePurpose.DEBUG:
1672 pubconf.archiveroot += '-debug'
1673 elif archive.is_copy:
1674- pubconf.distroroot = config.archivepublisher.root
1675+ pubconf.distroroot = db_pubconf.root_dir
1676 pubconf.archiveroot = os.path.join(
1677 pubconf.distroroot,
1678 archive.distribution.name + '-' + archive.name,
1679@@ -83,10 +88,6 @@
1680 return pubconf
1681
1682
1683-class LucilleConfigError(Exception):
1684- """Lucille configuration was not present."""
1685-
1686-
1687 class Config(object):
1688 """Manage a publisher configuration from the database. (Read Only)
1689 This class provides a useful abstraction so that if we change
1690
1691=== modified file 'lib/lp/archivepublisher/deathrow.py'
1692--- lib/lp/archivepublisher/deathrow.py 2010-10-17 13:35:20 +0000
1693+++ lib/lp/archivepublisher/deathrow.py 2011-03-29 10:32:58 +0000
1694@@ -17,7 +17,6 @@
1695 from lp.archivepublisher import ELIGIBLE_DOMINATION_STATES
1696 from lp.archivepublisher.config import (
1697 getPubConfig,
1698- LucilleConfigError,
1699 )
1700 from lp.archivepublisher.diskpool import DiskPool
1701 from lp.archivepublisher.utils import process_in_batches
1702@@ -40,12 +39,8 @@
1703 the one provided by the publishing-configuration, it will be only
1704 used for PRIMARY archives.
1705 """
1706- log.debug("Grab Lucille config.")
1707- try:
1708- pubconf = getPubConfig(archive)
1709- except LucilleConfigError, info:
1710- log.error(info)
1711- raise
1712+ log.debug("Grab publisher config.")
1713+ pubconf = getPubConfig(archive)
1714
1715 if (pool_root_override is not None and
1716 archive.purpose == ArchivePurpose.PRIMARY):
1717
1718=== added file 'lib/lp/archivepublisher/interfaces/publisherconfig.py'
1719--- lib/lp/archivepublisher/interfaces/publisherconfig.py 1970-01-01 00:00:00 +0000
1720+++ lib/lp/archivepublisher/interfaces/publisherconfig.py 2011-03-29 10:32:58 +0000
1721@@ -0,0 +1,58 @@
1722+# Copyright 2011 Canonical Ltd. This software is licensed under the
1723+# GNU Affero General Public License version 3 (see the file LICENSE).
1724+
1725+# pylint: disable-msg=E0211,E0213
1726+
1727+"""PublisherConfig interface."""
1728+
1729+__metaclass__ = type
1730+
1731+__all__ = [
1732+ 'IPublisherConfig',
1733+ 'IPublisherConfigSet',
1734+ ]
1735+
1736+from lazr.restful.fields import Reference
1737+from zope.interface import Interface
1738+from zope.schema import (
1739+ Int,
1740+ TextLine,
1741+ )
1742+
1743+from canonical.launchpad import _
1744+from lp.registry.interfaces.distribution import IDistribution
1745+
1746+
1747+class IPublisherConfig(Interface):
1748+ """`PublisherConfig` interface."""
1749+
1750+ id = Int(title=_('ID'), required=True, readonly=True)
1751+
1752+ distribution = Reference(
1753+ IDistribution, title=_("Distribution"), required=True,
1754+ description=_("The Distribution for this configuration."))
1755+
1756+ root_dir = TextLine(
1757+ title=_("Root Directory"), required=True,
1758+ description=_("The root directory for published archives."))
1759+
1760+ base_url = TextLine(
1761+ title=_("Base URL"), required=True,
1762+ description=_("The base URL for published archives"))
1763+
1764+ copy_base_url = TextLine(
1765+ title=_("Copy Base URL"), required=True,
1766+ description=_("The base URL for published copy archives"))
1767+
1768+
1769+class IPublisherConfigSet(Interface):
1770+ """`PublisherConfigSet` interface."""
1771+
1772+ def new(distribution, root_dir, base_url, copy_base_url):
1773+ """Create a new `PublisherConfig`."""
1774+
1775+ def getByDistribution(distribution):
1776+ """Get the config for a a distribution.
1777+
1778+ :param distribution: An `IDistribution`
1779+ """
1780
1781=== added file 'lib/lp/archivepublisher/model/publisherconfig.py'
1782--- lib/lp/archivepublisher/model/publisherconfig.py 1970-01-01 00:00:00 +0000
1783+++ lib/lp/archivepublisher/model/publisherconfig.py 2011-03-29 10:32:58 +0000
1784@@ -0,0 +1,68 @@
1785+# Copyright 2011 Canonical Ltd. This software is licensed under the
1786+# GNU Affero General Public License version 3 (see the file LICENSE).
1787+
1788+"""Database class for table PublisherConfig."""
1789+
1790+__metaclass__ = type
1791+
1792+__all__ = [
1793+ 'PublisherConfig',
1794+ 'PublisherConfigSet',
1795+ ]
1796+
1797+from storm.locals import (
1798+ Int,
1799+ Reference,
1800+ Storm,
1801+ Unicode,
1802+ )
1803+from zope.interface import implements
1804+
1805+from canonical.launchpad.interfaces.lpstorm import (
1806+ IMasterStore,
1807+ )
1808+from lp.archivepublisher.interfaces.publisherconfig import (
1809+ IPublisherConfig,
1810+ IPublisherConfigSet,
1811+ )
1812+
1813+
1814+class PublisherConfig(Storm):
1815+ """See `IArchiveAuthToken`."""
1816+ implements(IPublisherConfig)
1817+ __storm_table__ = 'PublisherConfig'
1818+
1819+ id = Int(primary=True)
1820+
1821+ distribution_id = Int(name='distribution', allow_none=False)
1822+ distribution = Reference(distribution_id, 'Distribution.id')
1823+
1824+ root_dir = Unicode(name='root_dir', allow_none=False)
1825+
1826+ base_url = Unicode(name='base_url', allow_none=False)
1827+
1828+ copy_base_url = Unicode(name='copy_base_url', allow_none=False)
1829+
1830+
1831+class PublisherConfigSet:
1832+ """See `IPublisherConfigSet`."""
1833+ implements(IPublisherConfigSet)
1834+ title = "Soyuz Publisher Configurations"
1835+
1836+ def new(self, distribution, root_dir, base_url, copy_base_url):
1837+ """Make and return a new `PublisherConfig`."""
1838+ store = IMasterStore(PublisherConfig)
1839+ pubconf = PublisherConfig()
1840+ pubconf.distribution = distribution
1841+ pubconf.root_dir = root_dir
1842+ pubconf.base_url = base_url
1843+ pubconf.copy_base_url = copy_base_url
1844+ store.add(pubconf)
1845+ return pubconf
1846+
1847+ def getByDistribution(self, distribution):
1848+ """See `IArchiveAuthTokenSet`."""
1849+ store = IMasterStore(PublisherConfig)
1850+ return store.find(
1851+ PublisherConfig,
1852+ PublisherConfig.distribution_id == distribution.id).one()
1853
1854=== modified file 'lib/lp/archivepublisher/publishing.py'
1855--- lib/lp/archivepublisher/publishing.py 2011-02-04 09:07:36 +0000
1856+++ lib/lp/archivepublisher/publishing.py 2011-03-29 10:32:58 +0000
1857@@ -21,7 +21,6 @@
1858 from lp.archivepublisher import HARDCODED_COMPONENT_ORDER
1859 from lp.archivepublisher.config import (
1860 getPubConfig,
1861- LucilleConfigError,
1862 )
1863 from lp.archivepublisher.diskpool import DiskPool
1864 from lp.archivepublisher.domination import Dominator
1865@@ -120,11 +119,7 @@
1866 else:
1867 log.debug("Finding configuration for '%s' PPA."
1868 % archive.owner.name)
1869- try:
1870- pubconf = getPubConfig(archive)
1871- except LucilleConfigError, info:
1872- log.error(info)
1873- raise
1874+ pubconf = getPubConfig(archive)
1875
1876 disk_pool = _getDiskPool(pubconf, log)
1877
1878
1879=== added file 'lib/lp/archivepublisher/tests/test_publisherconfig.py'
1880--- lib/lp/archivepublisher/tests/test_publisherconfig.py 1970-01-01 00:00:00 +0000
1881+++ lib/lp/archivepublisher/tests/test_publisherconfig.py 2011-03-29 10:32:58 +0000
1882@@ -0,0 +1,92 @@
1883+# Copyright 2011 Canonical Ltd. This software is licensed under the
1884+# GNU Affero General Public License version 3 (see the file LICENSE).
1885+
1886+"""Tests for publisherConfig model class."""
1887+
1888+__metaclass__ = type
1889+
1890+
1891+from storm.store import Store
1892+from storm.exceptions import IntegrityError
1893+from zope.component import getUtility
1894+from zope.interface.verify import verifyObject
1895+from zope.security.interfaces import Unauthorized
1896+
1897+from canonical.launchpad.ftests import login
1898+from canonical.testing.layers import (
1899+ DatabaseFunctionalLayer,
1900+ ZopelessDatabaseLayer,
1901+ )
1902+from lp.archivepublisher.interfaces.publisherconfig import (
1903+ IPublisherConfig,
1904+ IPublisherConfigSet,
1905+ )
1906+from lp.testing import (
1907+ ANONYMOUS,
1908+ TestCaseWithFactory,
1909+ )
1910+from lp.testing.sampledata import LAUNCHPAD_ADMIN
1911+
1912+
1913+class TestPublisherConfig(TestCaseWithFactory):
1914+ """Test the `PublisherConfig` model."""
1915+ layer = ZopelessDatabaseLayer
1916+
1917+ def setUp(self):
1918+ TestCaseWithFactory.setUp(self)
1919+ self.distribution = self.factory.makeDistribution(name='conftest')
1920+
1921+ def test_verify_interface(self):
1922+ # Test the interface for the model.
1923+ pubconf = self.factory.makePublisherConfig()
1924+ verified = verifyObject(IPublisherConfig, pubconf)
1925+ self.assertTrue(verified)
1926+
1927+ def test_properties(self):
1928+ # Test the model properties.
1929+ ROOT_DIR = u"rootdir/test"
1930+ BASE_URL = u"http://base.url"
1931+ COPY_BASE_URL = u"http://base.url"
1932+ pubconf = self.factory.makePublisherConfig(
1933+ distribution=self.distribution,
1934+ root_dir=ROOT_DIR,
1935+ base_url=BASE_URL,
1936+ copy_base_url=COPY_BASE_URL,
1937+ )
1938+
1939+ self.assertEqual(self.distribution.name, pubconf.distribution.name)
1940+ self.assertEqual(ROOT_DIR, pubconf.root_dir)
1941+ self.assertEqual(BASE_URL, pubconf.base_url)
1942+ self.assertEqual(COPY_BASE_URL, pubconf.copy_base_url)
1943+
1944+ def test_one_config_per_distro(self):
1945+ # Only one config for each distro is allowed.
1946+ pubconf = self.factory.makePublisherConfig(self.distribution)
1947+ pubconf2 = self.factory.makePublisherConfig(self.distribution)
1948+ store = Store.of(pubconf)
1949+ self.assertRaises(IntegrityError, store.flush)
1950+
1951+ def test_getByDistribution(self):
1952+ # Test that IPublisherConfigSet.getByDistribution works.
1953+ pubconf = getUtility(IPublisherConfigSet).getByDistribution(
1954+ self.distribution)
1955+ self.assertEqual(self.distribution.name, pubconf.distribution.name)
1956+
1957+
1958+class TestPublisherConfigSecurity(TestCaseWithFactory):
1959+
1960+ layer = DatabaseFunctionalLayer
1961+
1962+ def test_only_admin(self):
1963+ # Only admins can see and change the config.
1964+ distro = self.factory.makeDistribution(publish_root_dir=u"foo")
1965+ config = getUtility(IPublisherConfigSet).getByDistribution(distro)
1966+
1967+ login(ANONYMOUS)
1968+ self.assertRaises(Unauthorized, getattr, config, "root_dir")
1969+ self.assertRaises(Unauthorized, setattr, config, "root_dir", "test")
1970+
1971+ login(LAUNCHPAD_ADMIN)
1972+ self.assertEqual(u"foo", config.root_dir)
1973+ config.root_dir = u"bar"
1974+ self.assertEqual(u"bar", config.root_dir)
1975
1976=== modified file 'lib/lp/archivepublisher/zcml/configure.zcml'
1977--- lib/lp/archivepublisher/zcml/configure.zcml 2009-07-13 18:15:02 +0000
1978+++ lib/lp/archivepublisher/zcml/configure.zcml 2011-03-29 10:32:58 +0000
1979@@ -2,8 +2,32 @@
1980 GNU Affero General Public License version 3 (see the file LICENSE).
1981 -->
1982
1983-<configure xmlns="http://namespaces.zope.org/zope">
1984+<configure
1985+ xmlns="http://namespaces.zope.org/zope"
1986+ xmlns:browser="http://namespaces.zope.org/browser"
1987+ xmlns:i18n="http://namespaces.zope.org/i18n"
1988+ xmlns:webservice="http://namespaces.canonical.com/webservice"
1989+ xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
1990+ i18n_domain="launchpad">
1991+
1992 <include package="lp.archivepublisher.zcml"
1993 file="archivesigningkey.zcml" />
1994+
1995+ <securedutility
1996+ class="lp.archivepublisher.model.publisherconfig.PublisherConfigSet"
1997+ provides="lp.archivepublisher.interfaces.publisherconfig.IPublisherConfigSet">
1998+ <allow
1999+ interface="lp.archivepublisher.interfaces.publisherconfig.IPublisherConfigSet"/>
2000+ </securedutility>
2001+
2002+ <class
2003+ class="lp.archivepublisher.model.publisherconfig.PublisherConfig">
2004+ <require
2005+ permission="launchpad.Admin"
2006+ interface="lp.archivepublisher.interfaces.publisherconfig.IPublisherConfig"
2007+ set_schema="lp.archivepublisher.interfaces.publisherconfig.IPublisherConfig"/>
2008+ </class>
2009+
2010+
2011 </configure>
2012
2013
2014=== modified file 'lib/lp/bugs/browser/bugcomment.py'
2015--- lib/lp/bugs/browser/bugcomment.py 2011-02-16 20:06:40 +0000
2016+++ lib/lp/bugs/browser/bugcomment.py 2011-03-29 10:32:58 +0000
2017@@ -68,7 +68,7 @@
2018 bug_comment = comments.get(message.id)
2019 if bug_comment is None:
2020 bug_comment = BugComment(bugmessage.index, message, bugtask,
2021- visible=bugmessage.visible)
2022+ visible=message.visible)
2023 comments[message.id] = bug_comment
2024 # This code path is currently only used from BugTask view which
2025 # have already loaded all the bug watches. If we start lazy loading
2026
2027=== modified file 'lib/lp/bugs/configure.zcml'
2028--- lib/lp/bugs/configure.zcml 2011-03-29 00:11:57 +0000
2029+++ lib/lp/bugs/configure.zcml 2011-03-29 10:32:58 +0000
2030@@ -869,7 +869,7 @@
2031 interface="lp.bugs.interfaces.bugmessage.IBugMessage"/>
2032 <require
2033 permission="launchpad.Admin"
2034- set_attributes="remote_comment_id bugwatch visible index"/>
2035+ set_attributes="remote_comment_id bugwatch index"/>
2036 </class>
2037
2038 <!-- BugMessageSet -->
2039@@ -1060,6 +1060,10 @@
2040 class="lp.bugs.mail.bugnotificationrecipients.BugNotificationRecipients">
2041 <allow
2042 interface="canonical.launchpad.interfaces.launchpad.INotificationRecipientSet"/>
2043+ <!-- BugNotificationRecipients provides the following
2044+ attributes/methods in addition. -->
2045+ <allow
2046+ attributes="subscription_filters addFilter"/>
2047 </class>
2048 <securedutility
2049 provides="lp.bugs.interfaces.bugnotification.IBugNotificationSet"
2050
2051=== modified file 'lib/lp/bugs/doc/bugmessage-visibility.txt'
2052--- lib/lp/bugs/doc/bugmessage-visibility.txt 2010-10-18 22:24:59 +0000
2053+++ lib/lp/bugs/doc/bugmessage-visibility.txt 2011-03-29 10:32:58 +0000
2054@@ -20,27 +20,28 @@
2055 ... content="new message for visibility test",
2056 ... owner=sample_person,
2057 ... bug=bug_one)
2058- >>> new_message.visible
2059+ >>> new_message.message.visible
2060 True
2061
2062-Only Admins can hide bug messages using the visible field.
2063+Only Admins and registry experts can hide bug messages using the visible
2064+field.
2065
2066 # Login an Admin user and set visible to False.
2067 >>> login('foo.bar@canonical.com')
2068 >>> abugmessage = bugmessageset.get(1)
2069- >>> abugmessage.visible
2070+ >>> abugmessage.message.visible
2071 True
2072- >>> abugmessage.visible = False
2073- >>> abugmessage.visible
2074+ >>> abugmessage.message.visible = False
2075+ >>> abugmessage.message.visible
2076 False
2077
2078 # Non-privileged users should not be able to
2079 # make comments visible again.
2080 >>> login('no-priv@canonical.com')
2081 >>> abugmessage = bugmessageset.get(1)
2082- >>> abugmessage.visible
2083+ >>> abugmessage.message.visible
2084 False
2085- >>> abugmessage.visible = True
2086+ >>> abugmessage.message.visible = True
2087 Traceback (most recent call last):
2088 ...
2089- Unauthorized: (<BugMessage at ...>, 'visible', 'launchpad.Admin')
2090+ Unauthorized: (<Message at ...>, 'visible', 'launchpad.Admin')
2091
2092=== modified file 'lib/lp/bugs/doc/bugnotification-sending.txt'
2093--- lib/lp/bugs/doc/bugnotification-sending.txt 2011-03-23 16:28:51 +0000
2094+++ lib/lp/bugs/doc/bugnotification-sending.txt 2011-03-29 10:32:58 +0000
2095@@ -21,8 +21,10 @@
2096
2097 >>> def print_notification_headers(email_notification):
2098 ... for header in ['To', 'From', 'Subject',
2099- ... 'X-Launchpad-Message-Rationale']:
2100- ... print "%s: %s" % (header, email_notification[header])
2101+ ... 'X-Launchpad-Message-Rationale',
2102+ ... 'X-Launchpad-Subscription']:
2103+ ... if email_notification[header]:
2104+ ... print "%s: %s" % (header, email_notification[header])
2105
2106 >>> def print_notification(email_notification):
2107 ... print_notification_headers(email_notification)
2108@@ -676,7 +678,6 @@
2109 been set properly.
2110
2111 >>> from lp.bugs.model.bugnotification import BugNotification
2112- >>> from lp.bugs.enum import BugNotificationStatus
2113 >>> for notification in BugNotification.select(orderBy='id')[-8:]:
2114 ... if notification.is_comment:
2115 ... identifier = 'comment'
2116@@ -1247,6 +1248,7 @@
2117 >>> with lp_dbuser():
2118 ... filter = subscription_no_priv.newBugFilter()
2119 ... filter.bug_notification_level = BugNotificationLevel.COMMENTS
2120+ ... filter.description = u"Allow-comments filter"
2121
2122 >>> comment = getUtility(IMessageSet).fromText(
2123 ... 'subject', 'another comment.', sample_person,
2124@@ -1279,12 +1281,14 @@
2125 From: Sample Person <...@bugs.launchpad.net>
2126 Subject: [Bug 1] subject
2127 X-Launchpad-Message-Rationale: Subscriber (Mozilla Firefox)
2128+ X-Launchpad-Subscription: Allow-comments filter
2129 <BLANKLINE>
2130 another comment.
2131 <BLANKLINE>
2132 --
2133 You received this bug notification because you are subscribed to Mozilla
2134 Firefox.
2135+ Matching subscriptions: Allow-comments filter
2136 ...
2137 ----------------------------------------------------------------------
2138 To: support@ubuntu.com
2139@@ -1390,6 +1394,7 @@
2140 From: Sample Person <...@bugs.launchpad.net>
2141 Subject: [Bug 1] subject
2142 X-Launchpad-Message-Rationale: Subscriber (Mozilla Firefox)
2143+ X-Launchpad-Subscription: Allow-comments filter
2144 <BLANKLINE>
2145 no comment for no-priv.
2146 <BLANKLINE>
2147@@ -1400,6 +1405,7 @@
2148 --
2149 You received this bug notification because you are subscribed to Mozilla
2150 Firefox.
2151+ Matching subscriptions: Allow-comments filter
2152 ...
2153 ----------------------------------------------------------------------
2154 To: support@ubuntu.com
2155
2156=== modified file 'lib/lp/bugs/enum.py'
2157--- lib/lp/bugs/enum.py 2011-03-05 00:06:26 +0000
2158+++ lib/lp/bugs/enum.py 2011-03-29 10:32:58 +0000
2159@@ -57,18 +57,18 @@
2160
2161 class BugNotificationStatus(DBEnumeratedType):
2162 """The status of a bug notification.
2163-
2164+
2165 A notification may be pending, sent, or omitted."""
2166
2167 PENDING = DBItem(10, """
2168 Pending
2169-
2170+
2171 The notification has not yet been sent.
2172 """)
2173
2174 OMITTED = DBItem(20, """
2175 Omitted
2176-
2177+
2178 The system considered sending the notification, but omitted it.
2179 This is generally because the action reported by the notification
2180 was immediately undone.
2181@@ -76,6 +76,6 @@
2182
2183 SENT = DBItem(30, """
2184 Sent
2185-
2186+
2187 The notification has been sent.
2188 """)
2189
2190=== modified file 'lib/lp/bugs/interfaces/bug.py'
2191--- lib/lp/bugs/interfaces/bug.py 2011-03-29 00:11:57 +0000
2192+++ lib/lp/bugs/interfaces/bug.py 2011-03-29 10:32:58 +0000
2193@@ -382,7 +382,7 @@
2194 title=_('Heat Last Updated'), required=False, readonly=True)
2195
2196 # Adding related BugMessages provides a hook for getting at
2197- # BugMessage.visible when building bug comments.
2198+ # BugMessage.message.visible when building bug comments.
2199 bug_messages = Attribute('The bug messages related to this object.')
2200 comment_count = Attribute(
2201 "The number of comments on this bug, not including the initial "
2202
2203=== modified file 'lib/lp/bugs/interfaces/bugmessage.py'
2204--- lib/lp/bugs/interfaces/bugmessage.py 2011-02-24 15:30:54 +0000
2205+++ lib/lp/bugs/interfaces/bugmessage.py 2011-03-29 10:32:58 +0000
2206@@ -52,8 +52,6 @@
2207 bugwatchID = Int(title=u'The bugwatch id.', readonly=True)
2208 remote_comment_id = TextLine(
2209 title=u"The id this comment has in the bugwatch's bug tracker.")
2210- visible = Bool(title=u"This message is visible or not.", required=False,
2211- default=True)
2212
2213
2214 class IBugMessageSet(Interface):
2215
2216=== modified file 'lib/lp/bugs/mail/bugnotificationrecipients.py'
2217--- lib/lp/bugs/mail/bugnotificationrecipients.py 2011-03-02 14:07:23 +0000
2218+++ lib/lp/bugs/mail/bugnotificationrecipients.py 2011-03-29 10:32:58 +0000
2219@@ -58,6 +58,7 @@
2220 """
2221 NotificationRecipientSet.__init__(self)
2222 self.duplicateof = duplicateof
2223+ self.subscription_filters = set()
2224
2225 def _addReason(self, person, reason, header):
2226 """Adds a reason (text and header) for a person.
2227@@ -127,3 +128,13 @@
2228 else:
2229 text = "are the registrant for %s" % upstream.displayname
2230 self._addReason(person, text, reason)
2231+
2232+ def update(self, recipient_set):
2233+ """See `INotificationRecipientSet`."""
2234+ super(BugNotificationRecipients, self).update(recipient_set)
2235+ self.subscription_filters.update(
2236+ recipient_set.subscription_filters)
2237+
2238+ def addFilter(self, subscription_filter):
2239+ if subscription_filter is not None:
2240+ self.subscription_filters.add(subscription_filter)
2241
2242=== modified file 'lib/lp/bugs/model/bug.py'
2243--- lib/lp/bugs/model/bug.py 2011-03-29 00:11:57 +0000
2244+++ lib/lp/bugs/model/bug.py 2011-03-29 10:32:58 +0000
2245@@ -1784,7 +1784,7 @@
2246 bug_message_set = getUtility(IBugMessageSet)
2247 bug_message = bug_message_set.getByBugAndMessage(
2248 self, self.messages[comment_number])
2249- bug_message.visible = visible
2250+ bug_message.message.visible = visible
2251
2252 @cachedproperty
2253 def _known_viewers(self):
2254
2255=== modified file 'lib/lp/bugs/model/bugmessage.py'
2256--- lib/lp/bugs/model/bugmessage.py 2011-02-16 03:35:46 +0000
2257+++ lib/lp/bugs/model/bugmessage.py 2011-03-29 10:32:58 +0000
2258@@ -44,7 +44,6 @@
2259 bugwatch = ForeignKey(dbName='bugwatch', foreignKey='BugWatch',
2260 notNull=False, default=None)
2261 remote_comment_id = StringCol(notNull=False, default=None)
2262- visible = BoolCol(notNull=True, default=True)
2263 # -- The index of the message is cached in the DB.
2264 index = IntCol(notNull=True)
2265
2266
2267=== modified file 'lib/lp/bugs/model/bugnotification.py'
2268--- lib/lp/bugs/model/bugnotification.py 2011-02-25 16:19:58 +0000
2269+++ lib/lp/bugs/model/bugnotification.py 2011-03-29 10:32:58 +0000
2270@@ -150,12 +150,23 @@
2271 reason_body, reason_header = recipients.getReason(recipient)
2272 sql_values.append('(%s, %s, %s, %s)' % sqlvalues(
2273 bug_notification, recipient, reason_header, reason_body))
2274+
2275 # We add all the recipients in a single SQL statement to make
2276 # this a bit more efficient for bugs with many subscribers.
2277 store.execute("""
2278 INSERT INTO BugNotificationRecipient
2279 (bug_notification, person, reason_header, reason_body)
2280 VALUES %s;""" % ', '.join(sql_values))
2281+
2282+ if len(recipients.subscription_filters) > 0:
2283+ filter_link_sql = [
2284+ "(%s, %s)" % sqlvalues(bug_notification, filter.id)
2285+ for filter in recipients.subscription_filters]
2286+ store.execute("""
2287+ INSERT INTO BugNotificationFilter
2288+ (bug_notification, bug_subscription_filter)
2289+ VALUES %s;""" % ", ".join(filter_link_sql))
2290+
2291 return bug_notification
2292
2293
2294
2295=== modified file 'lib/lp/bugs/model/structuralsubscription.py'
2296--- lib/lp/bugs/model/structuralsubscription.py 2011-03-23 15:55:44 +0000
2297+++ lib/lp/bugs/model/structuralsubscription.py 2011-03-29 10:32:58 +0000
2298@@ -641,14 +641,15 @@
2299 else:
2300 subscribers = []
2301 query_results = source.find(
2302- (Person, StructuralSubscription),
2303- *constraints).config(distinct=True)
2304- for person, subscription in query_results:
2305+ (Person, StructuralSubscription, BugSubscriptionFilter),
2306+ *constraints)
2307+ for person, subscription, filter in query_results:
2308 # Set up results.
2309 if person not in recipients:
2310 subscribers.append(person)
2311 recipients.addStructuralSubscriber(
2312 person, subscription.target)
2313+ recipients.addFilter(filter)
2314 return subscribers
2315
2316
2317
2318=== modified file 'lib/lp/bugs/security.py'
2319--- lib/lp/bugs/security.py 2011-02-28 22:09:39 +0000
2320+++ lib/lp/bugs/security.py 2011-03-29 10:32:58 +0000
2321@@ -161,20 +161,15 @@
2322 usedfor = IMessage
2323
2324
2325-class SetMessageVisibility(AuthorizationBase):
2326+class SetBugCommentVisibility(AuthorizationBase):
2327 permission = 'launchpad.Admin'
2328- usedfor = IBugMessage
2329+ usedfor = IBug
2330
2331 def checkAuthenticated(self, user):
2332 """Admins and registry admins can set bug comment visibility."""
2333 return (user.in_admin or user.in_registry_experts)
2334
2335
2336-class SetBugCommentVisibility(SetMessageVisibility):
2337-
2338- usedfor = IBug
2339-
2340-
2341 class ViewBugTracker(AnonymousAuthorization):
2342 """Anyone can view a bug tracker."""
2343 usedfor = IBugTracker
2344
2345=== modified file 'lib/lp/bugs/stories/bugs/xx-bug-hidden-comments.txt'
2346--- lib/lp/bugs/stories/bugs/xx-bug-hidden-comments.txt 2010-10-11 16:17:45 +0000
2347+++ lib/lp/bugs/stories/bugs/xx-bug-hidden-comments.txt 2011-03-29 10:32:58 +0000
2348@@ -30,7 +30,7 @@
2349 This comment will not be visible when the test completes.
2350 >>> bug_message = getUtility(IBugMessageSet).getByBugAndMessage(
2351 ... bug_11, message)
2352- >>> bug_message.visible = False
2353+ >>> bug_message.message.visible = False
2354 >>> transaction.commit()
2355 >>> logout()
2356
2357
2358=== modified file 'lib/lp/bugs/tests/test_bug_messages_webservice.py'
2359--- lib/lp/bugs/tests/test_bug_messages_webservice.py 2011-03-23 16:28:51 +0000
2360+++ lib/lp/bugs/tests/test_bug_messages_webservice.py 2011-03-29 10:32:58 +0000
2361@@ -61,7 +61,7 @@
2362 with person_logged_in(self.admin):
2363 bug_message = bug_msg_set.getByBugAndMessage(
2364 self.bug, self.message)
2365- self.assertFalse(bug_message.visible)
2366+ self.assertFalse(bug_message.message.visible)
2367
2368 def test_random_user_cannot_set_visible(self):
2369 # Logged in users without privs can't set bug comment
2370
2371=== modified file 'lib/lp/code/model/tests/test_recipebuilder.py'
2372--- lib/lp/code/model/tests/test_recipebuilder.py 2010-12-23 01:02:00 +0000
2373+++ lib/lp/code/model/tests/test_recipebuilder.py 2011-03-29 10:32:58 +0000
2374@@ -21,7 +21,7 @@
2375 from zope.security.proxy import removeSecurityProxy
2376
2377 from canonical.testing.layers import (
2378- LaunchpadFunctionalLayer,
2379+ LaunchpadZopelessLayer,
2380 )
2381 from lp.buildmaster.enums import BuildFarmJobType
2382 from lp.buildmaster.interfaces.builder import CannotBuild
2383@@ -50,7 +50,7 @@
2384
2385 class TestRecipeBuilder(TestCaseWithFactory):
2386
2387- layer = LaunchpadFunctionalLayer
2388+ layer = LaunchpadZopelessLayer
2389
2390 def makeJob(self, recipe_registrant=None, recipe_owner=None):
2391 """Create a sample `ISourcePackageRecipeBuildJob`."""
2392
2393=== modified file 'lib/lp/registry/adapters.py'
2394--- lib/lp/registry/adapters.py 2011-01-04 16:08:57 +0000
2395+++ lib/lp/registry/adapters.py 2011-03-29 10:32:58 +0000
2396@@ -18,6 +18,9 @@
2397 from zope.interface import implements
2398
2399 from canonical.launchpad.webapp.interfaces import ILaunchpadPrincipal
2400+from lp.archivepublisher.interfaces.publisherconfig import (
2401+ IPublisherConfigSet,
2402+ )
2403 from lp.registry.interfaces.poll import (
2404 IPollSet,
2405 IPollSubset,
2406@@ -112,3 +115,10 @@
2407 or `ILaunchpadUsage`.
2408 """
2409 return productseries.product
2410+
2411+
2412+def distribution_to_publisherconfig(distro):
2413+ """Adapts `IDistribution` to `IPublisherConfig`."""
2414+ # Used for traversal from distro to +pubconf.
2415+ config = getUtility(IPublisherConfigSet).getByDistribution(distro)
2416+ return config
2417
2418=== modified file 'lib/lp/registry/browser/configure.zcml'
2419--- lib/lp/registry/browser/configure.zcml 2011-03-28 02:54:53 +0000
2420+++ lib/lp/registry/browser/configure.zcml 2011-03-29 10:32:58 +0000
2421@@ -129,13 +129,6 @@
2422 template="../templates/distroseries-needs-packaging.pt"/>
2423 <browser:page
2424 for="lp.registry.interfaces.distroseries.IDistroSeries"
2425- permission="launchpad.Admin"
2426- facet="overview"
2427- class="canonical.launchpad.browser.ObjectReassignmentView"
2428- name="+reassign"
2429- template="../../../canonical/launchpad/templates/object-reassignment.pt"/>
2430- <browser:page
2431- for="lp.registry.interfaces.distroseries.IDistroSeries"
2432 permission="launchpad.Edit"
2433 name="+edit"
2434 class="lp.registry.browser.distroseries.DistroSeriesEditView"
2435@@ -1951,7 +1944,7 @@
2436 for="lp.registry.interfaces.distribution.IDistribution"
2437 permission="launchpad.Edit"
2438 facet="overview"
2439- class="canonical.launchpad.browser.ObjectReassignmentView">
2440+ class="lp.registry.browser.distribution.DistributionReassignmentView">
2441 <browser:page
2442 name="+reassign"
2443 template="../../../canonical/launchpad/templates/object-reassignment.pt"/>
2444@@ -1995,6 +1988,13 @@
2445 facet="overview"
2446 permission="launchpad.Edit"
2447 template="../../app/templates/generic-edit.pt"/>
2448+ <browser:page
2449+ name="+pubconf"
2450+ for="lp.registry.interfaces.distribution.IDistribution"
2451+ class="lp.registry.browser.distribution.DistributionPublisherConfigView"
2452+ template="../../app/templates/generic-edit.pt"
2453+ facet="overview"
2454+ permission="launchpad.Admin"/>
2455 <browser:defaultView
2456 for="lp.registry.interfaces.distribution.IDistributionSet"
2457 name="+index"/>
2458
2459=== modified file 'lib/lp/registry/browser/distribution.py'
2460--- lib/lp/registry/browser/distribution.py 2011-03-04 09:55:17 +0000
2461+++ lib/lp/registry/browser/distribution.py 2011-03-29 10:32:58 +0000
2462@@ -21,6 +21,8 @@
2463 'DistributionPPASearchView',
2464 'DistributionPackageSearchView',
2465 'DistributionPendingReviewMirrorsView',
2466+ 'DistributionPublisherConfigView',
2467+ 'DistributionReassignmentView',
2468 'DistributionSeriesView',
2469 'DistributionSeriesMirrorsRSSView',
2470 'DistributionSeriesMirrorsView',
2471@@ -40,6 +42,7 @@
2472
2473 from zope.component import getUtility
2474 from zope.event import notify
2475+from zope.formlib import form
2476 from zope.interface import implements
2477 from zope.lifecycleevent import ObjectCreatedEvent
2478 from zope.security.interfaces import Unauthorized
2479@@ -78,6 +81,10 @@
2480 )
2481 from lp.app.errors import NotFoundError
2482 from lp.app.widgets.image import ImageChangeWidget
2483+from lp.archivepublisher.interfaces.publisherconfig import (
2484+ IPublisherConfig,
2485+ IPublisherConfigSet,
2486+ )
2487 from lp.blueprints.browser.specificationtarget import (
2488 HasSpecificationsMenuMixin,
2489 )
2490@@ -92,6 +99,7 @@
2491 RegistryCollectionActionMenuBase,
2492 )
2493 from lp.registry.browser.pillar import PillarBugsMenu
2494+from lp.registry.browser.objectreassignment import ObjectReassignmentView
2495 from lp.registry.interfaces.distribution import (
2496 IDerivativeDistribution,
2497 IDistribution,
2498@@ -278,7 +286,12 @@
2499 """A menu of context actions."""
2500 usedfor = IDistribution
2501 facet = 'overview'
2502- links = ['edit']
2503+ links = ['edit', 'pubconf']
2504+
2505+ @enabled_with_permission("launchpad.Admin")
2506+ def pubconf(self):
2507+ text = "Configure publisher"
2508+ return Link("+pubconf", text, icon="edit")
2509
2510
2511 class DistributionOverviewMenu(ApplicationMenu, DistributionLinksMixin):
2512@@ -325,7 +338,7 @@
2513
2514 @enabled_with_permission('launchpad.Edit')
2515 def reassign(self):
2516- text = 'Change registrant'
2517+ text = 'Change maintainer'
2518 return Link('+reassign', text, icon='edit')
2519
2520 def newmirror(self):
2521@@ -770,6 +783,7 @@
2522 domainname=data['domainname'],
2523 members=data['members'],
2524 owner=self.user,
2525+ registrant=self.user,
2526 )
2527 notify(ObjectCreatedEvent(distribution))
2528 self.next_url = canonical_url(distribution)
2529@@ -1081,3 +1095,62 @@
2530 @cachedproperty
2531 def mirrors(self):
2532 return self.context.disabled_mirrors
2533+
2534+
2535+class DistributionReassignmentView(ObjectReassignmentView):
2536+ """View class for changing distribution maintainer."""
2537+ ownerOrMaintainerName = 'maintainer'
2538+
2539+
2540+class DistributionPublisherConfigView(LaunchpadFormView):
2541+ """View class for configuring publisher options for a DistroSeries.
2542+
2543+ It redirects to the main distroseries page after a successful edit.
2544+ """
2545+ schema = IPublisherConfig
2546+ field_names = ['root_dir', 'base_url', 'copy_base_url']
2547+
2548+ @property
2549+ def label(self):
2550+ """See `LaunchpadFormView`."""
2551+ return 'Publisher configuration for %s' % self.context.title
2552+
2553+ @property
2554+ def page_title(self):
2555+ """The page title."""
2556+ return self.label
2557+
2558+ @property
2559+ def cancel_url(self):
2560+ """See `LaunchpadFormView`."""
2561+ return canonical_url(self.context)
2562+
2563+ @property
2564+ def initial_values(self):
2565+ """If the config already exists, set up the fields with data."""
2566+ config = getUtility(
2567+ IPublisherConfigSet).getByDistribution(self.context)
2568+ values = {}
2569+ if config is not None:
2570+ for name in self.field_names:
2571+ values[name] = getattr(config, name)
2572+
2573+ return values
2574+
2575+ @action("Save")
2576+ def save_action(self, action, data):
2577+ """Update the context and redirect to its overview page."""
2578+ config = getUtility(IPublisherConfigSet).getByDistribution(
2579+ self.context)
2580+ if config is None:
2581+ config = getUtility(IPublisherConfigSet).new(
2582+ distribution=self.context,
2583+ root_dir=data['root_dir'],
2584+ base_url=data['base_url'],
2585+ copy_base_url=data['copy_base_url'])
2586+ else:
2587+ form.applyChanges(config, self.form_fields, data, self.adapters)
2588+
2589+ self.request.response.addInfoNotification(
2590+ 'Your changes have been applied.')
2591+ self.next_url = canonical_url(self.context)
2592
2593=== modified file 'lib/lp/registry/browser/distroseries.py'
2594--- lib/lp/registry/browser/distroseries.py 2011-03-24 14:13:45 +0000
2595+++ lib/lp/registry/browser/distroseries.py 2011-03-29 10:32:58 +0000
2596@@ -24,7 +24,6 @@
2597 from zope.interface import Interface
2598 from zope.lifecycleevent import ObjectCreatedEvent
2599 from zope.schema import (
2600- Bool,
2601 Choice,
2602 List,
2603 TextLine,
2604@@ -69,6 +68,7 @@
2605 from lp.app.widgets.itemswidgets import (
2606 LabeledMultiCheckBoxWidget,
2607 LaunchpadDropdownWidget,
2608+ LaunchpadRadioWidget,
2609 )
2610 from lp.blueprints.browser.specificationtarget import (
2611 HasSpecificationsMenuMixin,
2612@@ -187,7 +187,7 @@
2613
2614 usedfor = IDistroSeries
2615 facet = 'overview'
2616- links = ['edit', 'reassign', 'driver', 'answers',
2617+ links = ['edit', 'driver', 'answers',
2618 'packaging', 'needs_packaging', 'builds', 'queue',
2619 'add_port', 'create_milestone', 'subscribe', 'admin']
2620
2621@@ -202,11 +202,6 @@
2622 summary = 'Someone with permission to set goals for this series'
2623 return Link('+driver', text, summary, icon='edit')
2624
2625- @enabled_with_permission('launchpad.Admin')
2626- def reassign(self):
2627- text = 'Change registrant'
2628- return Link('+reassign', text, icon='edit')
2629-
2630 @enabled_with_permission('launchpad.Edit')
2631 def create_milestone(self):
2632 text = 'Create milestone'
2633@@ -499,9 +494,9 @@
2634 @action(_('Create Series'), name='create')
2635 def createAndAdd(self, action, data):
2636 """Create and add a new Distribution Series"""
2637- owner = getUtility(ILaunchBag).user
2638+ registrant = getUtility(ILaunchBag).user
2639
2640- assert owner is not None
2641+ assert registrant is not None
2642 distroseries = self.context.newSeries(
2643 name=data['name'],
2644 displayname=data['displayname'],
2645@@ -510,7 +505,7 @@
2646 description=data['description'],
2647 version=data['version'],
2648 parent_series=data['parent_series'],
2649- owner=owner)
2650+ registrant=registrant)
2651 notify(ObjectCreatedEvent(distroseries))
2652 self.next_url = canonical_url(distroseries)
2653 return distroseries
2654@@ -535,6 +530,32 @@
2655 return navigator
2656
2657
2658+# A simple vocabulary for package filtering on the source package
2659+# differences page
2660+NON_BLACKLISTED = 'non-blacklisted'
2661+BLACKLISTED = 'blacklisted'
2662+HIGHER_VERSION_THAN_PARENT = 'higher-than-parent'
2663+RESOLVED = 'resolved'
2664+
2665+DEFAULT_PACKAGE_TYPE = NON_BLACKLISTED
2666+
2667+
2668+def make_package_type_vocabulary(parent_name):
2669+ return SimpleVocabulary((
2670+ SimpleTerm(
2671+ NON_BLACKLISTED, NON_BLACKLISTED, 'Non blacklisted packages'),
2672+ SimpleTerm(BLACKLISTED, BLACKLISTED, 'Blacklisted packages'),
2673+ SimpleTerm(
2674+ HIGHER_VERSION_THAN_PARENT,
2675+ HIGHER_VERSION_THAN_PARENT,
2676+ "Blacklisted packages with a higher version than in '%s'"
2677+ % parent_name),
2678+ SimpleTerm(
2679+ RESOLVED,
2680+ RESOLVED,
2681+ "Resolved packages")))
2682+
2683+
2684 class DistroSeriesNeedsPackagesView(LaunchpadView):
2685 """A View to show series package to upstream package relationships."""
2686
2687@@ -554,10 +575,6 @@
2688 name_filter = TextLine(
2689 title=_("Package name contains"), required=False)
2690
2691- include_blacklisted_filter = Bool(
2692- title=_("include blacklisted packages"),
2693- required=False, default=False)
2694-
2695 selected_differences = List(
2696 title=_('Selected differences'),
2697 value_type=Choice(vocabulary=SimpleVocabulary([])),
2698@@ -570,6 +587,7 @@
2699 schema = IDifferencesFormSchema
2700 field_names = ['selected_differences']
2701 custom_widget('selected_differences', LabeledMultiCheckBoxWidget)
2702+ custom_widget('package_type', LaunchpadRadioWidget)
2703
2704 page_title = 'Local package differences'
2705
2706@@ -585,6 +603,7 @@
2707 self.context.parent_series.displayname,
2708 self.context.displayname,
2709 ))
2710+
2711 super(DistroSeriesLocalDifferences, self).initialize()
2712
2713 @property
2714@@ -596,6 +615,14 @@
2715 self.context.parent_series.displayname,
2716 ))
2717
2718+ def setupPackageFilterRadio(self):
2719+ return form.Fields(Choice(
2720+ __name__='package_type',
2721+ vocabulary=make_package_type_vocabulary(
2722+ self.context.parent_series.displayname),
2723+ default=DEFAULT_PACKAGE_TYPE,
2724+ required=True))
2725+
2726 def setUpFields(self):
2727 """Add the selected differences field.
2728
2729@@ -603,6 +630,10 @@
2730 for its own vocabulary, we set it up after all the others.
2731 """
2732 super(DistroSeriesLocalDifferences, self).setUpFields()
2733+ self.form_fields = (
2734+ self.setupPackageFilterRadio() +
2735+ self.form_fields)
2736+
2737 has_edit = check_permission('launchpad.Edit', self.context)
2738
2739 terms = [
2740@@ -673,33 +704,44 @@
2741 return None
2742
2743 @property
2744- def specified_include_blacklisted_filter(self):
2745- """If specified, return the 'blacklisted' filter from the GET form
2746+ def specified_package_type(self):
2747+ """If specified, return the package type filter from the GET form
2748 data.
2749 """
2750- include_blacklisted_filter = self.request.query_string_params.get(
2751- 'field.include_blacklisted_filter')
2752-
2753- if include_blacklisted_filter and include_blacklisted_filter[0]:
2754- return include_blacklisted_filter[0]
2755+ package_type = self.request.query_string_params.get(
2756+ 'field.package_type')
2757+ if package_type and package_type[0]:
2758+ return package_type[0]
2759 else:
2760- return None
2761+ return DEFAULT_PACKAGE_TYPE
2762
2763 @cachedproperty
2764 def cached_differences(self):
2765 """Return a batch navigator of filtered results."""
2766- if self.specified_include_blacklisted_filter:
2767- status=(
2768- DistroSeriesDifferenceStatus.NEEDS_ATTENTION,
2769- DistroSeriesDifferenceStatus.BLACKLISTED_CURRENT)
2770- else:
2771+ if self.specified_package_type == NON_BLACKLISTED:
2772 status=(
2773 DistroSeriesDifferenceStatus.NEEDS_ATTENTION,)
2774+ child_version_higher = False
2775+ elif self.specified_package_type == BLACKLISTED:
2776+ status=(
2777+ DistroSeriesDifferenceStatus.BLACKLISTED_CURRENT)
2778+ child_version_higher = False
2779+ elif self.specified_package_type == HIGHER_VERSION_THAN_PARENT:
2780+ status=(
2781+ DistroSeriesDifferenceStatus.BLACKLISTED_CURRENT)
2782+ child_version_higher = True
2783+ elif self.specified_package_type == RESOLVED:
2784+ status=DistroSeriesDifferenceStatus.RESOLVED
2785+ child_version_higher = False
2786+ else:
2787+ raise AssertionError('specified_package_type unknown')
2788+
2789 differences = getUtility(
2790 IDistroSeriesDifferenceSource).getForDistroSeries(
2791 self.context,
2792 source_package_name_filter=self.specified_name_filter,
2793- status=status)
2794+ status=status,
2795+ child_version_higher=child_version_higher)
2796 return BatchNavigator(differences, self.request)
2797
2798 @cachedproperty
2799
2800=== added file 'lib/lp/registry/browser/tests/test_distribution_views.py'
2801--- lib/lp/registry/browser/tests/test_distribution_views.py 1970-01-01 00:00:00 +0000
2802+++ lib/lp/registry/browser/tests/test_distribution_views.py 2011-03-29 10:32:58 +0000
2803@@ -0,0 +1,167 @@
2804+# Copyright 2009 Canonical Ltd. This software is licensed under the
2805+# GNU Affero General Public License version 3 (see the file LICENSE).
2806+
2807+__metaclass__ = type
2808+
2809+import soupmatchers
2810+from zope.component import getUtility
2811+
2812+from canonical.launchpad.ftests import login
2813+from canonical.launchpad.webapp.servers import LaunchpadTestRequest
2814+from canonical.testing.layers import DatabaseFunctionalLayer
2815+from lp.archivepublisher.interfaces.publisherconfig import IPublisherConfigSet
2816+from lp.registry.browser.distribution import DistributionPublisherConfigView
2817+from lp.registry.interfaces.distribution import IDistributionSet
2818+from lp.testing import (
2819+ login_celebrity,
2820+ TestCaseWithFactory,
2821+ )
2822+from lp.testing.sampledata import LAUNCHPAD_ADMIN
2823+from lp.testing.views import create_initialized_view
2824+
2825+
2826+class TestDistributionPublisherConfigView(TestCaseWithFactory):
2827+ """Test `DistributionPublisherConfigView`."""
2828+
2829+ layer = DatabaseFunctionalLayer
2830+
2831+ def setUp(self):
2832+ # Create a test distribution.
2833+ super(TestDistributionPublisherConfigView, self).setUp()
2834+ self.distro = self.factory.makeDistribution(no_pubconf=True)
2835+ login(LAUNCHPAD_ADMIN)
2836+
2837+ self.ROOT_DIR = u"rootdir/test"
2838+ self.BASE_URL = u"http://base.url"
2839+ self.COPY_BASE_URL = u"http://copybase.url"
2840+
2841+ def test_empty_initial_values(self):
2842+ # Test that the page will display empty field values with no
2843+ # existing config set up.
2844+ view = DistributionPublisherConfigView(
2845+ self.distro, LaunchpadTestRequest())
2846+
2847+ for value in view.initial_values:
2848+ self.assertEqual(u"", value)
2849+
2850+ def test_previous_initial_values(self):
2851+ # Test that the initial values are the same as the ones in the
2852+ # existing database record.
2853+ pubconf = self.factory.makePublisherConfig(
2854+ distribution=self.distro)
2855+
2856+ view = DistributionPublisherConfigView(
2857+ self.distro, LaunchpadTestRequest())
2858+
2859+ self.assertEqual(pubconf.root_dir, view.initial_values["root_dir"])
2860+ self.assertEqual(pubconf.base_url, view.initial_values["base_url"])
2861+ self.assertEqual(
2862+ pubconf.copy_base_url, view.initial_values["copy_base_url"])
2863+
2864+ def _change_and_test_config(self):
2865+ form = {
2866+ 'field.actions.save': 'save',
2867+ 'field.root_dir': self.ROOT_DIR,
2868+ 'field.base_url': self.BASE_URL,
2869+ 'field.copy_base_url': self.COPY_BASE_URL,
2870+ }
2871+
2872+ view = DistributionPublisherConfigView(
2873+ self.distro, LaunchpadTestRequest(method='POST', form=form))
2874+ view.initialize()
2875+
2876+ config = getUtility(
2877+ IPublisherConfigSet).getByDistribution(self.distro)
2878+
2879+ self.assertEqual(self.ROOT_DIR, config.root_dir)
2880+ self.assertEqual(self.BASE_URL, config.base_url)
2881+ self.assertEqual(self.COPY_BASE_URL, config.copy_base_url)
2882+
2883+ def test_add_new_config(self):
2884+ # Test POSTing a new config.
2885+ self._change_and_test_config()
2886+
2887+ def test_change_existing_config(self):
2888+ # Test POSTing to change existing config.
2889+ pubconf = self.factory.makePublisherConfig(
2890+ distribution=self.distro,
2891+ root_dir=u"random",
2892+ base_url=u"blah",
2893+ copy_base_url=u"foo",
2894+ )
2895+ self._change_and_test_config()
2896+
2897+
2898+class TestDistroAddView(TestCaseWithFactory):
2899+ """Test the +add page for a new distribution."""
2900+
2901+ layer = DatabaseFunctionalLayer
2902+
2903+ def setUp(self):
2904+ super(TestDistroAddView, self).setUp()
2905+ self.owner = self.factory.makePerson()
2906+ self.registrant = self.factory.makePerson()
2907+ self.simple_user = self.factory.makePerson()
2908+
2909+ def test_registrant_set_by_creation(self):
2910+ # The registrant field should be set to the Person creating
2911+ # the distribution.
2912+ admin = login_celebrity('admin')
2913+ distributionset = getUtility(IDistributionSet)
2914+ creation_form = {
2915+ 'field.name': 'newbuntu',
2916+ 'field.displayname': 'newbuntu',
2917+ 'field.title': 'newbuntu',
2918+ 'field.summary': 'newbuntu',
2919+ 'field.description': 'newbuntu',
2920+ 'field.domainname': 'newbuntu',
2921+ 'field.members': self.simple_user.name,
2922+ 'field.actions.save': 'Save',
2923+ }
2924+ view = create_initialized_view(
2925+ distributionset, '+add', principal=admin,
2926+ method='POST', form=creation_form)
2927+ distribution = distributionset.getByName('newbuntu')
2928+ self.assertEqual(distribution.owner, admin)
2929+ self.assertEqual(distribution.registrant, admin)
2930+
2931+
2932+class TestDistroReassignView(TestCaseWithFactory):
2933+ """Test the +reassign page for a new distribution."""
2934+
2935+ layer = DatabaseFunctionalLayer
2936+
2937+ def setUp(self):
2938+ super(TestDistroReassignView, self).setUp()
2939+ self.owner = self.factory.makePerson()
2940+ self.registrant = self.factory.makePerson()
2941+ self.simple_user = self.factory.makePerson()
2942+
2943+ def test_reassign_distro_change_owner_not_registrant(self):
2944+ # Reassigning a distribution should not change the registrant.
2945+ admin = login_celebrity('admin')
2946+ distribution = self.factory.makeDistribution(
2947+ name="boobuntu", owner=self.owner, registrant=self.registrant)
2948+ reassign_form = {
2949+ 'field.owner': self.simple_user.name,
2950+ 'field.existing': 'existing',
2951+ 'field.actions.change': 'Change',
2952+ }
2953+ view = create_initialized_view(
2954+ distribution, '+reassign', principal=admin,
2955+ method='POST', form=reassign_form)
2956+ self.assertEqual(distribution.owner, self.simple_user)
2957+ self.assertEqual(distribution.registrant, self.registrant)
2958+
2959+ def test_reassign_distro_page_title(self):
2960+ # Reassign should say maintainer instead of owner.
2961+ admin = login_celebrity('admin')
2962+ distribution = self.factory.makeDistribution(
2963+ name="boobuntu", owner=self.owner, registrant=self.registrant)
2964+ view = create_initialized_view(
2965+ distribution, '+reassign', principal=admin, method='GET')
2966+ header_match = soupmatchers.HTMLContains(
2967+ soupmatchers.Tag(
2968+ 'Header should say maintainer (not owner)', 'h1',
2969+ text='Change the maintainer of Boobuntu'))
2970+ self.assertThat(view.render(), header_match)
2971
2972=== modified file 'lib/lp/registry/browser/tests/test_series_views.py'
2973--- lib/lp/registry/browser/tests/test_series_views.py 2011-03-29 00:11:57 +0000
2974+++ lib/lp/registry/browser/tests/test_series_views.py 2011-03-29 10:32:58 +0000
2975@@ -3,13 +3,14 @@
2976
2977 __metaclass__ = type
2978
2979+import unittest
2980+
2981 from BeautifulSoup import BeautifulSoup
2982+import soupmatchers
2983 from storm.zope.interfaces import IResultSet
2984 from zope.component import getUtility
2985 from zope.security.proxy import removeSecurityProxy
2986
2987-import unittest
2988-
2989 from canonical.config import config
2990 from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
2991 from canonical.launchpad.testing.pages import find_tag_by_id
2992@@ -17,13 +18,23 @@
2993 from canonical.launchpad.webapp.publisher import canonical_url
2994 from canonical.testing.layers import (
2995 DatabaseFunctionalLayer,
2996+ LaunchpadFunctionalLayer,
2997 LaunchpadZopelessLayer,
2998- LaunchpadFunctionalLayer,
2999+ )
3000+from lp.registry.browser.distroseries import (
3001+ BLACKLISTED,
3002+ HIGHER_VERSION_THAN_PARENT,
3003+ NON_BLACKLISTED,
3004+ RESOLVED,
3005 )
3006 from lp.registry.enum import (
3007 DistroSeriesDifferenceStatus,
3008 DistroSeriesDifferenceType,
3009 )
3010+from lp.services.features import (
3011+ getFeatureFlag,
3012+ install_feature_controller,
3013+ )
3014 from lp.services.features.flags import FeatureController
3015 from lp.services.features.model import (
3016 FeatureFlag,
3017@@ -40,9 +51,9 @@
3018 SourcePackageFormat,
3019 )
3020 from lp.testing import (
3021- TestCaseWithFactory,
3022 login_person,
3023 person_logged_in,
3024+ TestCaseWithFactory,
3025 )
3026 from lp.testing.views import create_initialized_view
3027
3028@@ -273,6 +284,29 @@
3029
3030 layer = LaunchpadFunctionalLayer
3031
3032+
3033+ def test_higher_radio_mentions_parent(self):
3034+ set_derived_series_ui_feature_flag(self)
3035+ parent_series = self.factory.makeDistroSeries(
3036+ name='lucid', displayname='Lucid')
3037+ derived_series = self.factory.makeDistroSeries(
3038+ name='derilucid', parent_series=parent_series)
3039+ diff1 = self.factory.makeDistroSeriesDifference(
3040+ derived_series=derived_series,
3041+ source_package_name_str="my-src-package")
3042+ view = create_initialized_view(
3043+ derived_series,
3044+ '+localpackagediffs')
3045+
3046+ radio_title = \
3047+ "&nbsp;Blacklisted packages with a higher version than in 'Lucid'"
3048+ radio_option_matches = soupmatchers.HTMLContains(
3049+ soupmatchers.Tag(
3050+ "radio displays parent's name", 'label',
3051+ text=radio_title),
3052+ )
3053+ self.assertThat(view.render(), radio_option_matches)
3054+
3055 def _set_source_selection(self, series):
3056 # Set up source package format selection so that copying will
3057 # work with the default dsc_format used in
3058@@ -306,9 +340,38 @@
3059 self.assertContentEqual(
3060 [diff2, diff1], unfiltered_view.cached_differences.batch)
3061
3062- def test_batch_blacklisted(self):
3063- # The include_blacklisted_filter parameter allows to list
3064- # blacklisted packages.
3065+ def test_batch_non_blacklisted(self):
3066+ # The default filter is all non blacklisted differences.
3067+ set_derived_series_ui_feature_flag(self)
3068+ derived_series = self.factory.makeDistroSeries(
3069+ name='derilucid', parent_series=self.factory.makeDistroSeries(
3070+ name='lucid'))
3071+ diff1 = self.factory.makeDistroSeriesDifference(
3072+ derived_series=derived_series,
3073+ source_package_name_str="my-src-package")
3074+ diff2 = self.factory.makeDistroSeriesDifference(
3075+ derived_series=derived_series,
3076+ source_package_name_str="my-second-src-package")
3077+ blacklisted_diff = self.factory.makeDistroSeriesDifference(
3078+ derived_series=derived_series,
3079+ status=DistroSeriesDifferenceStatus.BLACKLISTED_CURRENT)
3080+
3081+ filtered_view = create_initialized_view(
3082+ derived_series,
3083+ '+localpackagediffs',
3084+ query_string='field.package_type=%s' % NON_BLACKLISTED)
3085+ filtered_view2 = create_initialized_view(
3086+ derived_series,
3087+ '+localpackagediffs')
3088+
3089+ self.assertContentEqual(
3090+ [diff2, diff1], filtered_view.cached_differences.batch)
3091+ self.assertContentEqual(
3092+ [diff2, diff1], filtered_view2.cached_differences.batch)
3093+
3094+ def test_batch_differences_packages(self):
3095+ # field.package_type parameter allows to list only
3096+ # blacklisted differences.
3097 set_derived_series_ui_feature_flag(self)
3098 derived_series = self.factory.makeDistroSeries(
3099 name='derilucid', parent_series=self.factory.makeDistroSeries(
3100@@ -320,7 +383,7 @@
3101 blacklisted_view = create_initialized_view(
3102 derived_series,
3103 '+localpackagediffs',
3104- query_string='field.include_blacklisted_filter=on')
3105+ query_string='field.package_type=%s' % BLACKLISTED)
3106 unblacklisted_view = create_initialized_view(
3107 derived_series,
3108 '+localpackagediffs')
3109@@ -330,6 +393,62 @@
3110 self.assertContentEqual(
3111 [], unblacklisted_view.cached_differences.batch)
3112
3113+ def test_batch_blacklisted_differences_with_higher_version(self):
3114+ # field.package_type parameter allows to list only
3115+ # blacklisted differences with a child's version higher than parent's.
3116+ set_derived_series_ui_feature_flag(self)
3117+ derived_series = self.factory.makeDistroSeries(
3118+ name='derilucid', parent_series=self.factory.makeDistroSeries(
3119+ name='lucid'))
3120+ blacklisted_diff_higher = self.factory.makeDistroSeriesDifference(
3121+ derived_series=derived_series,
3122+ status=DistroSeriesDifferenceStatus.BLACKLISTED_CURRENT,
3123+ versions={'base': '1.1', 'parent': '1.3', 'derived': '1.10'})
3124+ blacklisted_diff_not_higher = self.factory.makeDistroSeriesDifference(
3125+ derived_series=derived_series,
3126+ status=DistroSeriesDifferenceStatus.BLACKLISTED_CURRENT,
3127+ versions={'base': '1.1', 'parent': '1.12', 'derived': '1.10'})
3128+
3129+ blacklisted_view = create_initialized_view(
3130+ derived_series,
3131+ '+localpackagediffs',
3132+ query_string='field.package_type=%s' % HIGHER_VERSION_THAN_PARENT)
3133+ unblacklisted_view = create_initialized_view(
3134+ derived_series,
3135+ '+localpackagediffs')
3136+
3137+ self.assertContentEqual(
3138+ [blacklisted_diff_higher],
3139+ blacklisted_view.cached_differences.batch)
3140+ self.assertContentEqual(
3141+ [], unblacklisted_view.cached_differences.batch)
3142+
3143+ def test_batch_resolved_differences(self):
3144+ # Test that we can search for differences that we marked
3145+ # resolved.
3146+ set_derived_series_ui_feature_flag(self)
3147+ derived_series = self.factory.makeDistroSeries(
3148+ name='derilucid', parent_series=self.factory.makeDistroSeries(
3149+ name='lucid'))
3150+
3151+ diff1 = self.factory.makeDistroSeriesDifference(
3152+ derived_series=derived_series,
3153+ source_package_name_str="my-src-package")
3154+ diff2 = self.factory.makeDistroSeriesDifference(
3155+ derived_series=derived_series,
3156+ source_package_name_str="my-second-src-package")
3157+ resolved_diff = self.factory.makeDistroSeriesDifference(
3158+ derived_series=derived_series,
3159+ status=DistroSeriesDifferenceStatus.RESOLVED)
3160+
3161+ filtered_view = create_initialized_view(
3162+ derived_series,
3163+ '+localpackagediffs',
3164+ query_string='field.package_type=%s' % RESOLVED)
3165+
3166+ self.assertContentEqual(
3167+ [resolved_diff], filtered_view.cached_differences.batch)
3168+
3169 def test_canPerformSync_non_editor(self):
3170 # Non-editors do not see options to sync.
3171 derived_series = self.factory.makeDistroSeries(
3172
3173=== modified file 'lib/lp/registry/configure.zcml'
3174--- lib/lp/registry/configure.zcml 2011-03-23 16:28:51 +0000
3175+++ lib/lp/registry/configure.zcml 2011-03-29 10:32:58 +0000
3176@@ -215,7 +215,7 @@
3177
3178 <require
3179 permission="launchpad.Moderate"
3180- set_attributes="version name status owner nominatedarchindep changeslist datereleased"/>
3181+ set_attributes="version name status nominatedarchindep changeslist datereleased"/>
3182
3183 <!-- IStructuralSubscriptionTarget -->
3184
3185@@ -1532,6 +1532,7 @@
3186 addAnswerContact
3187 removeAnswerContact"/>
3188
3189+
3190 <!-- IFAQTarget -->
3191
3192 <allow
3193@@ -1575,6 +1576,12 @@
3194 for="lp.registry.interfaces.distribution.IDistributionSet"
3195 factory="lp.registry.browser.distribution.DistributionSetBreadcrumb"
3196 permission="zope.Public"/>
3197+ <adapter
3198+ provides="lp.archivepublisher.interfaces.publisherconfig.IPublisherConfig"
3199+ for="lp.registry.interfaces.distribution.IDistribution"
3200+ factory="lp.registry.adapters.distribution_to_publisherconfig"
3201+ permission="zope.Public"/>
3202+
3203
3204 <!-- DistributionSet -->
3205
3206
3207=== modified file 'lib/lp/registry/doc/distroseries.txt'
3208--- lib/lp/registry/doc/distroseries.txt 2010-11-02 05:48:54 +0000
3209+++ lib/lp/registry/doc/distroseries.txt 2011-03-29 10:32:58 +0000
3210@@ -842,9 +842,11 @@
3211 >>> yo_series = youbuntu.newSeries(
3212 ... name='island', displayname='Island', title='YouBuntu Island',
3213 ... summary='summary', description='description', version='09.07',
3214- ... parent_series=warty, owner=yo_driver)
3215+ ... parent_series=warty, registrant=yo_driver)
3216 >>> print yo_series.name
3217 island
3218+ >>> print yo_series.registrant.name
3219+ yo-driver
3220 >>> print yo_series.driver.name
3221 yo-driver
3222
3223@@ -856,7 +858,7 @@
3224 >>> yo_series = youbuntu.newSeries(
3225 ... name='forest', displayname='Forest', title='YouBuntu Forest',
3226 ... summary='summary', description='description', version='09.07',
3227- ... parent_series=warty, owner=youbuntu.owner)
3228+ ... parent_series=warty, registrant=youbuntu.owner)
3229 >>> print yo_series.name
3230 forest
3231 >>> print yo_series.driver
3232@@ -884,9 +886,11 @@
3233 >>> u_series = ubuntu.newSeries(
3234 ... name='finch', displayname='Finch', title='Ubuntu Finch',
3235 ... summary='summary', description='description', version='9.06',
3236- ... parent_series=warty, owner=ubuntu.owner)
3237+ ... parent_series=warty, registrant=ubuntu.owner)
3238 >>> print u_series.name
3239 finch
3240+ >>> print u_series.registrant.name
3241+ ubuntu-team
3242 >>> print u_series.driver
3243 None
3244
3245@@ -1056,7 +1060,7 @@
3246 mark
3247 >>> print sid.driver
3248 None
3249- >>> print sid.owner.name
3250+ >>> print sid.registrant.name
3251 jdub
3252
3253 >>> for d in sid.drivers:
3254
3255=== modified file 'lib/lp/registry/interfaces/distribution.py'
3256--- lib/lp/registry/interfaces/distribution.py 2011-03-22 16:04:10 +0000
3257+++ lib/lp/registry/interfaces/distribution.py 2011-03-29 10:32:58 +0000
3258@@ -123,7 +123,7 @@
3259 """IDistribution properties requiring launchpad.Driver permission."""
3260
3261 def newSeries(name, displayname, title, summary, description,
3262- version, parent_series, owner):
3263+ version, parent_series, registrant):
3264 """Creates a new distroseries."""
3265
3266
3267@@ -209,6 +209,11 @@
3268 PublicPersonChoice(
3269 title=_("Owner"), vocabulary='ValidOwner',
3270 description=_("The distro's owner."), required=True))
3271+ registrant = exported(
3272+ PublicPersonChoice(
3273+ title=_("Registrant"), vocabulary='ValidPersonOrTeam',
3274+ description=_("The distro's registrant."), required=True,
3275+ readonly=True))
3276 date_created = exported(
3277 Datetime(title=_('Date created'),
3278 description=_("The date this distribution was registered.")))
3279@@ -689,7 +694,7 @@
3280 """Return the IDistribution with the given name or None."""
3281
3282 def new(name, displayname, title, description, summary, domainname,
3283- members, owner, mugshot=None, logo=None, icon=None):
3284+ members, owner, registrant, mugshot=None, logo=None, icon=None):
3285 """Create a new distribution."""
3286
3287 def getCurrentSourceReleases(distro_to_source_packagenames):
3288
3289=== modified file 'lib/lp/registry/interfaces/distroseries.py'
3290--- lib/lp/registry/interfaces/distroseries.py 2011-03-16 00:23:20 +0000
3291+++ lib/lp/registry/interfaces/distroseries.py 2011-03-29 10:32:58 +0000
3292@@ -242,8 +242,13 @@
3293 description=_("The series from which this one was branched."),
3294 required=True, schema=Interface, # Really IDistroSeries, see below
3295 vocabulary='DistroSeries'))
3296- owner = exported(
3297- PublicPersonChoice(title=_("Owner"), vocabulary='ValidOwner'))
3298+ registrant = exported(
3299+ PublicPersonChoice(
3300+ title=_("Registrant"), vocabulary='ValidPersonOrTeam'))
3301+ owner = exported(Reference(
3302+ IPerson, title=_("Owning team of the derived series"), readonly=True,
3303+ description=_(
3304+ "This attribute mirrors the owner of the distribution.")))
3305 date_created = exported(
3306 Datetime(title=_("The date this series was registered.")))
3307 driver = exported(
3308
3309=== modified file 'lib/lp/registry/interfaces/distroseriesdifference.py'
3310--- lib/lp/registry/interfaces/distroseriesdifference.py 2011-03-23 16:28:51 +0000
3311+++ lib/lp/registry/interfaces/distroseriesdifference.py 2011-03-29 10:32:58 +0000
3312@@ -1,4 +1,4 @@
3313-# Copyright 2010 Canonical Ltd. This software is licensed under the
3314+# Copyright 2010-2011 Canonical Ltd. This software is licensed under the
3315 # GNU Affero General Public License version 3 (see the file LICENSE).
3316
3317 """Interface classes for a difference between two distribution series."""
3318@@ -38,8 +38,8 @@
3319 )
3320 from lp.registry.interfaces.distroseries import IDistroSeries
3321 from lp.registry.interfaces.person import IPerson
3322+from lp.registry.interfaces.role import IHasOwner
3323 from lp.registry.interfaces.sourcepackagename import ISourcePackageName
3324-from lp.registry.interfaces.role import IHasOwner
3325 from lp.soyuz.interfaces.packagediff import IPackageDiff
3326 from lp.soyuz.interfaces.publishing import ISourcePackagePublishingHistory
3327
3328@@ -224,7 +224,8 @@
3329 distro_series,
3330 difference_type=DistroSeriesDifferenceType.DIFFERENT_VERSIONS,
3331 source_package_name_filter=None,
3332- status=None):
3333+ status=None,
3334+ child_version_higher=False):
3335 """Return differences for the derived distro series.
3336
3337 :param distro_series: The derived distribution series which is to be
3338@@ -238,6 +239,9 @@
3339 :param status: Only differences matching the status(es) will be
3340 included.
3341 :type status: `DistroSeriesDifferenceStatus`.
3342+ :param child_version_higher: Only differences for which the child's
3343+ version is higher than the parent's version will be included.
3344+ :type child_version_higher: bool.
3345 :return: A result set of differences.
3346 """
3347
3348
3349=== modified file 'lib/lp/registry/model/distribution.py'
3350--- lib/lp/registry/model/distribution.py 2011-03-28 20:54:50 +0000
3351+++ lib/lp/registry/model/distribution.py 2011-03-29 10:32:58 +0000
3352@@ -241,6 +241,9 @@
3353 owner = ForeignKey(
3354 dbName='owner', foreignKey='Person',
3355 storm_validator=validate_public_person, notNull=True)
3356+ registrant = ForeignKey(
3357+ dbName='registrant', foreignKey='Person',
3358+ storm_validator=validate_public_person, notNull=True)
3359 bug_supervisor = ForeignKey(
3360 dbName='bug_supervisor', foreignKey='Person',
3361 storm_validator=validate_person,
3362@@ -1775,7 +1778,7 @@
3363 return user.inTeam(self.owner) or user.inTeam(admins)
3364
3365 def newSeries(self, name, displayname, title, summary,
3366- description, version, parent_series, owner):
3367+ description, version, parent_series, registrant):
3368 """See `IDistribution`."""
3369 series = DistroSeries(
3370 distribution=self,
3371@@ -1787,10 +1790,11 @@
3372 version=version,
3373 status=SeriesStatus.EXPERIMENTAL,
3374 parent_series=parent_series,
3375- owner=owner)
3376- if owner.inTeam(self.driver) and not owner.inTeam(self.owner):
3377+ registrant=registrant)
3378+ if (registrant.inTeam(self.driver)
3379+ and not registrant.inTeam(self.owner)):
3380 # This driver is a release manager.
3381- series.driver = owner
3382+ series.driver = registrant
3383
3384 # May wish to add this to the series rather than clearing the cache --
3385 # RBC 20100816.
3386@@ -1897,7 +1901,7 @@
3387 return pillar
3388
3389 def new(self, name, displayname, title, description, summary, domainname,
3390- members, owner, mugshot=None, logo=None, icon=None):
3391+ members, owner, registrant, mugshot=None, logo=None, icon=None):
3392 """See `IDistributionSet`."""
3393 distro = Distribution(
3394 name=name,
3395@@ -1909,6 +1913,7 @@
3396 members=members,
3397 mirror_admin=owner,
3398 owner=owner,
3399+ registrant=registrant,
3400 mugshot=mugshot,
3401 logo=logo,
3402 icon=icon)
3403
3404=== modified file 'lib/lp/registry/model/distroseries.py'
3405--- lib/lp/registry/model/distroseries.py 2011-03-28 20:54:50 +0000
3406+++ lib/lp/registry/model/distroseries.py 2011-03-29 10:32:58 +0000
3407@@ -227,8 +227,8 @@
3408 datereleased = UtcDateTimeCol(notNull=False, default=None)
3409 parent_series = ForeignKey(
3410 dbName='parent_series', foreignKey='DistroSeries', notNull=False)
3411- owner = ForeignKey(
3412- dbName='owner', foreignKey='Person',
3413+ registrant = ForeignKey(
3414+ dbName='registrant', foreignKey='Person',
3415 storm_validator=validate_public_person, notNull=True)
3416 driver = ForeignKey(
3417 dbName="driver", foreignKey="Person",
3418@@ -396,6 +396,11 @@
3419 return self.distribution
3420
3421 @property
3422+ def owner(self):
3423+ """See `IDistroSeries`."""
3424+ return self.distribution.owner
3425+
3426+ @property
3427 def sortkey(self):
3428 """A string to be used for sorting distro seriess.
3429
3430@@ -1963,7 +1968,7 @@
3431 child = distribution.newSeries(
3432 name=name, displayname=displayname, title=title,
3433 summary=summary, description=description,
3434- version=version, parent_series=self, owner=user)
3435+ version=version, parent_series=self, registrant=user)
3436 IStore(self).add(child)
3437 else:
3438 if child.parent_series is not self:
3439
3440=== modified file 'lib/lp/registry/model/distroseriesdifference.py'
3441--- lib/lp/registry/model/distroseriesdifference.py 2011-03-28 07:01:41 +0000
3442+++ lib/lp/registry/model/distroseriesdifference.py 2011-03-29 10:32:58 +0000
3443@@ -11,14 +11,13 @@
3444
3445 from debian.changelog import Changelog
3446 from lazr.enum import DBItem
3447+from sqlobject import StringCol
3448 from storm.expr import Desc
3449-
3450 from storm.locals import (
3451 And,
3452 Int,
3453 Reference,
3454 Storm,
3455- Unicode,
3456 )
3457 from zope.component import getUtility
3458 from zope.interface import (
3459@@ -88,10 +87,10 @@
3460 enum=DistroSeriesDifferenceStatus)
3461 difference_type = DBEnum(name='difference_type', allow_none=False,
3462 enum=DistroSeriesDifferenceType)
3463- source_version = Unicode(name='source_version', allow_none=True)
3464- parent_source_version = Unicode(name='parent_source_version',
3465- allow_none=True)
3466- base_version = Unicode(name='base_version', allow_none=True)
3467+ source_version = StringCol(dbName='source_version', notNull=False)
3468+ parent_source_version = StringCol(dbName='parent_source_version',
3469+ notNull=False)
3470+ base_version = StringCol(dbName='base_version', notNull=False)
3471
3472 @staticmethod
3473 def new(derived_series, source_package_name):
3474@@ -117,7 +116,8 @@
3475 distro_series,
3476 difference_type=DistroSeriesDifferenceType.DIFFERENT_VERSIONS,
3477 source_package_name_filter=None,
3478- status=None):
3479+ status=None,
3480+ child_version_higher=False):
3481 """See `IDistroSeriesDifferenceSource`."""
3482 if status is None:
3483 status = (
3484@@ -131,12 +131,18 @@
3485 DistroSeriesDifference.difference_type == difference_type,
3486 DistroSeriesDifference.status.is_in(status),
3487 ]
3488+
3489 if source_package_name_filter:
3490 conditions.extend([
3491 DistroSeriesDifference.source_package_name ==
3492 SourcePackageName.id,
3493 SourcePackageName.name == source_package_name_filter])
3494
3495+ if child_version_higher:
3496+ conditions.extend([
3497+ DistroSeriesDifference.source_version >
3498+ DistroSeriesDifference.parent_source_version])
3499+
3500 return IStore(DistroSeriesDifference).find(
3501 DistroSeriesDifference,
3502 And(*conditions))
3503
3504=== modified file 'lib/lp/registry/stories/distribution/xx-distribution-launchpad-usage.txt'
3505--- lib/lp/registry/stories/distribution/xx-distribution-launchpad-usage.txt 2010-11-30 15:11:48 +0000
3506+++ lib/lp/registry/stories/distribution/xx-distribution-launchpad-usage.txt 2011-03-29 10:32:58 +0000
3507@@ -12,6 +12,10 @@
3508 Traceback (most recent call last):
3509 ...
3510 LinkNotFound...
3511+ >>> user_browser.getLink('Configure publisher')
3512+ Traceback (most recent call last):
3513+ ...
3514+ LinkNotFound...
3515 >>> user_browser.open('http://launchpad.dev/ubuntu/+edit')
3516 Traceback (most recent call last):
3517 ...
3518@@ -62,12 +66,31 @@
3519 >>> admin_browser.getControl(name='field.official_malone').value = False
3520 >>> admin_browser.getControl(name='field.blueprints_usage').value = (
3521 ... ['UNKNOWN'])
3522- >>> admin_browser.getControl(name='field.answers_usage').value = ['UNKNOWN']
3523+ >>> admin_browser.getControl(
3524+ ... name='field.answers_usage').value = ['UNKNOWN']
3525 >>> admin_browser.getControl('Change', index=3).click()
3526
3527 >>> print admin_browser.url
3528 http://launchpad.dev/ubuntu
3529
3530+Only administators can configure the publisher for the distribution:
3531+
3532+ >>> admin_browser.getLink('Configure publisher').click()
3533+ >>> print admin_browser.title
3534+ Publisher configuration for...
3535+
3536+ >>> admin_browser.getControl(
3537+ ... name='field.root_dir').value = "/tmp/root_dir"
3538+ >>> admin_browser.getControl(
3539+ ... name='field.base_url').value = "http://base.url/"
3540+ >>> admin_browser.getControl(
3541+ ... name='field.copy_base_url').value = "http://copy.base.url/"
3542+ >>> admin_browser.getControl('Save').click()
3543+
3544+ >>> print admin_browser.url
3545+ http://launchpad.dev/ubuntu
3546+
3547+
3548 enable_bug_expiration and JavaScript
3549 ====================================
3550
3551
3552=== modified file 'lib/lp/registry/stories/distribution/xx-distribution-overview.txt'
3553--- lib/lp/registry/stories/distribution/xx-distribution-overview.txt 2010-05-17 20:09:03 +0000
3554+++ lib/lp/registry/stories/distribution/xx-distribution-overview.txt 2011-03-29 10:32:58 +0000
3555@@ -89,7 +89,9 @@
3556
3557 >>> print extract_text(
3558 ... find_tag_by_id(anon_browser.contents, 'registration'))
3559- registered by Ubuntu Team on 2006-10-16
3560+ Registered by
3561+ Registry Administrators
3562+ on 2006-10-16
3563
3564 >>> print extract_text(find_main_content(anon_browser.contents))
3565 Ubuntu Linux
3566
3567=== modified file 'lib/lp/registry/stories/distroseries/xx-distroseries-index.txt'
3568--- lib/lp/registry/stories/distroseries/xx-distroseries-index.txt 2010-08-05 20:17:40 +0000
3569+++ lib/lp/registry/stories/distroseries/xx-distroseries-index.txt 2011-03-29 10:32:58 +0000
3570@@ -20,7 +20,9 @@
3571
3572 >>> print extract_text(
3573 ... find_tag_by_id(anon_browser.contents, 'registration'))
3574- registered by Ubuntu Team on 2006-10-16
3575+ Registered by
3576+ Ubuntu Team on
3577+ 2006-10-16
3578
3579 >>> print extract_text(find_main_content(anon_browser.contents))
3580 Warty
3581
3582=== removed file 'lib/lp/registry/stories/distroseries/xx-reassign-distroseries.txt'
3583--- lib/lp/registry/stories/distroseries/xx-reassign-distroseries.txt 2009-11-22 15:43:16 +0000
3584+++ lib/lp/registry/stories/distroseries/xx-reassign-distroseries.txt 1970-01-01 00:00:00 +0000
3585@@ -1,72 +0,0 @@
3586- Change the owner of the grumpy distroseries.
3587-
3588-
3589- Logged in as Sample Person we don't have permission to do that, because he's
3590- not the owner nor a member of the admins team.
3591-
3592- >>> print http(r"""
3593- ... GET /ubuntu/grumpy/+reassign HTTP/1.1
3594- ... Authorization: Basic test@canonical.com:test
3595- ... """)
3596- HTTP/1.1 403 Forbidden
3597- Content-Length: ...
3598- Content-Type: text/html;charset=utf-8
3599- ...
3600-
3601-
3602- Now we're logged in as Mark Shutleworth and reassign grumpy to Foo Bar.
3603-
3604- >>> print http(r"""
3605- ... POST /ubuntu/grumpy/+reassign HTTP/1.1
3606- ... Authorization: Basic mark@example.com:test
3607- ... field.owner=name16&field.existing=existing"""
3608- ... r"""&field.actions.change=Change""")
3609- HTTP/1.1 303 See Other
3610- ...
3611- Location: http://localhost/ubuntu/grumpy
3612- ...
3613-
3614-
3615- Foo Bar is the owner here
3616-
3617- >>> print http(r"""
3618- ... GET /ubuntu/grumpy/ HTTP/1.1
3619- ... Authorization: Basic mark@example.com:test
3620- ... """)
3621- HTTP/1.1 200 Ok
3622- Content-Length: ...
3623- Content-Type: text/html;charset=utf-8
3624- ...
3625- ...registered by...
3626- ...
3627- ...Foo Bar...
3628- ...
3629-
3630-
3631- Now we reassign it to a newly create team: ubuntu2
3632-
3633- >>> print http(r"""
3634- ... POST /ubuntu/grumpy/+reassign HTTP/1.1
3635- ... Authorization: Basic mark@example.com:test
3636- ... field.owner=ubuntu2&field.existing=new&field.actions.change=Change""")
3637- HTTP/1.1 303 See Other
3638- ...
3639- Location: http://localhost/ubuntu/grumpy
3640- ...
3641-
3642-
3643- And the new team can be seen as the owner.
3644-
3645- >>> print http(r"""
3646- ... GET /ubuntu/grumpy/ HTTP/1.1
3647- ... Authorization: Basic mark@example.com:test
3648- ... """)
3649- HTTP/1.1 200 Ok
3650- Content-Length: ...
3651- Content-Type: text/html;charset=utf-8
3652- ...
3653- ...registered by...
3654- ...
3655- ...ubuntu2...
3656- ...
3657-
3658
3659=== modified file 'lib/lp/registry/stories/webservice/xx-distribution.txt'
3660--- lib/lp/registry/stories/webservice/xx-distribution.txt 2011-02-13 22:54:48 +0000
3661+++ lib/lp/registry/stories/webservice/xx-distribution.txt 2011-03-29 10:32:58 +0000
3662@@ -43,6 +43,7 @@
3663 name: u'ubuntu'
3664 official_bug_tags: []
3665 owner_link: u'http://.../~ubuntu-team'
3666+ registrant_link: u'http://.../~registry'
3667 resource_type_link: u'http://.../#distribution'
3668 security_contact_link: None
3669 self_link: u'http://.../ubuntu'
3670
3671=== modified file 'lib/lp/registry/stories/webservice/xx-distroseries.txt'
3672--- lib/lp/registry/stories/webservice/xx-distroseries.txt 2011-01-26 19:35:17 +0000
3673+++ lib/lp/registry/stories/webservice/xx-distroseries.txt 2011-03-29 10:32:58 +0000
3674@@ -75,8 +75,9 @@
3675 main_archive_link: u'http://.../ubuntu/+archive/primary'
3676 name: u'hoary'
3677 official_bug_tags: []
3678- owner_link: u'http://.../~mark'
3679+ owner_link: u'http://.../~ubuntu-team'
3680 parent_series_link: u'http://.../ubuntu/warty'
3681+ registrant_link: u'http://.../~mark'
3682 resource_type_link: ...
3683 self_link: u'http://.../ubuntu/hoary'
3684 status: u'Active Development'
3685
3686=== modified file 'lib/lp/registry/templates/distribution-index.pt'
3687--- lib/lp/registry/templates/distribution-index.pt 2010-10-10 21:54:16 +0000
3688+++ lib/lp/registry/templates/distribution-index.pt 2011-03-29 10:32:58 +0000
3689@@ -11,8 +11,8 @@
3690 </tal:heading>
3691
3692 <tal:registering metal:fill-slot="registering">
3693- registered by
3694- <a tal:replace="structure context/owner/fmt:link" />
3695+ Registered by
3696+ <a tal:replace="structure context/registrant/fmt:link" />
3697 <span tal:content="context/date_created/fmt:displaydate"
3698 tal:attributes="title context/date_created/fmt:datetime"
3699 >on 2005-01-01</span>
3700
3701=== modified file 'lib/lp/registry/templates/distroseries-index.pt'
3702--- lib/lp/registry/templates/distroseries-index.pt 2010-10-10 21:54:16 +0000
3703+++ lib/lp/registry/templates/distroseries-index.pt 2011-03-29 10:32:58 +0000
3704@@ -19,8 +19,8 @@
3705 </tal:heading>
3706
3707 <tal:registering metal:fill-slot="registering">
3708- registered by
3709- <a tal:replace="structure context/owner/fmt:link" />
3710+ Registered by
3711+ <a tal:replace="structure context/registrant/fmt:link" />
3712 <span tal:content="context/date_created/fmt:displaydate"
3713 tal:attributes="title context/date_created/fmt:datetime"
3714 >on 2005-01-01</span>
3715@@ -121,9 +121,6 @@
3716 <li tal:condition="overview_menu/admin/enabled">
3717 <a tal:replace="structure overview_menu/admin/fmt:link" />
3718 </li>
3719- <li tal:condition="overview_menu/reassign/enabled">
3720- <a tal:replace="structure overview_menu/reassign/fmt:link" />
3721- </li>
3722 <li>
3723 <a tal:replace="structure overview_menu/subscribe/fmt:link" />
3724 </li>
3725
3726=== modified file 'lib/lp/registry/templates/distroseries-localdifferences.pt'
3727--- lib/lp/registry/templates/distroseries-localdifferences.pt 2011-03-23 16:28:51 +0000
3728+++ lib/lp/registry/templates/distroseries-localdifferences.pt 2011-03-29 10:32:58 +0000
3729@@ -6,6 +6,15 @@
3730 metal:use-macro="view/macro:page/main_only"
3731 i18n:domain="launchpad">
3732 <body>
3733+
3734+ <metal:block fill-slot="head_epilogue">
3735+ <style type="text/css">
3736+ .distroseries-localdiff-search-filter input[type="radio"] {
3737+ margin-left: 0;
3738+ }
3739+ </style>
3740+ </metal:block>
3741+
3742 <tal:heading metal:fill-slot="heading">
3743 <h1 tal:content="view/label">Package differences between ...</h1>
3744 </tal:heading>
3745
3746=== modified file 'lib/lp/registry/templates/packagesearch-macros.pt'
3747--- lib/lp/registry/templates/packagesearch-macros.pt 2011-03-23 16:28:51 +0000
3748+++ lib/lp/registry/templates/packagesearch-macros.pt 2011-03-29 10:32:58 +0000
3749@@ -71,12 +71,9 @@
3750 type="text" name="field.name_filter"
3751 tal:attributes="value request/field.name_filter|nothing"/>
3752 <input type="submit" value="Filter" />
3753- <br />
3754- <input
3755- id="field.include_blacklisted_filter"
3756- type="checkbox" name="field.include_blacklisted_filter"
3757- tal:attributes="checked request/field.include_blacklisted_filter|nothing"/>
3758- <label for="field.include_blacklisted_filter">include blacklisted packages</label>
3759+ <br />
3760+ <tal:package_type
3761+ replace="structure view/widgets/package_type" />
3762 </div>
3763 <div class="clearfix"></div>
3764 </form>
3765
3766=== modified file 'lib/lp/registry/tests/test_distribution.py'
3767--- lib/lp/registry/tests/test_distribution.py 2011-03-14 12:22:17 +0000
3768+++ lib/lp/registry/tests/test_distribution.py 2011-03-29 10:32:58 +0000
3769@@ -1,4 +1,4 @@
3770-# Copyright 2009 Canonical Ltd. This software is licensed under the
3771+# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
3772 # GNU Affero General Public License version 3 (see the file LICENSE).
3773
3774 """Tests for Distribution."""
3775@@ -6,14 +6,22 @@
3776 __metaclass__ = type
3777
3778 from lazr.lifecycle.snapshot import Snapshot
3779+import soupmatchers
3780+from testtools.matchers import (
3781+ MatchesAny,
3782+ Not,
3783+ )
3784+from zope.component import getUtility
3785 from zope.security.proxy import removeSecurityProxy
3786
3787+from canonical.launchpad.webapp import canonical_url
3788 from canonical.testing.layers import (
3789 DatabaseFunctionalLayer,
3790 LaunchpadFunctionalLayer,
3791 )
3792 from lp.registry.errors import NoSuchDistroSeries
3793 from lp.registry.interfaces.distribution import IDistribution
3794+from lp.registry.interfaces.person import IPersonSet
3795 from lp.registry.interfaces.series import SeriesStatus
3796 from lp.registry.tests.test_distroseries import (
3797 TestDistroSeriesCurrentSourceReleases,
3798@@ -22,7 +30,11 @@
3799 from lp.soyuz.interfaces.distributionsourcepackagerelease import (
3800 IDistributionSourcePackageRelease,
3801 )
3802-from lp.testing import TestCaseWithFactory
3803+from lp.testing import (
3804+ login_person,
3805+ TestCaseWithFactory,
3806+ )
3807+from lp.testing.views import create_initialized_view
3808
3809
3810 class TestDistribution(TestCaseWithFactory):
3811@@ -97,7 +109,7 @@
3812 distribution.newSeries(
3813 name='bar', displayname='Bar', title='Bar', summary='',
3814 description='', version='1', parent_series=None,
3815- owner=self.factory.makePerson())
3816+ registrant=self.factory.makePerson())
3817 self.assertNotIn("series", cache)
3818
3819 # New cached value.
3820@@ -174,3 +186,99 @@
3821 self.assertFalse(
3822 hasattr(snapshot, attribute),
3823 "Snapshot should not include %s." % attribute)
3824+
3825+
3826+class TestDistributionPage(TestCaseWithFactory):
3827+ """A TestCase for the distribution page."""
3828+
3829+ layer = DatabaseFunctionalLayer
3830+
3831+ def setUp(self):
3832+ super(TestDistributionPage, self).setUp('foo.bar@canonical.com')
3833+ self.distro = self.factory.makeDistribution(
3834+ name="distro", displayname=u'distro')
3835+ self.admin = getUtility(IPersonSet).getByEmail(
3836+ 'admin@canonical.com')
3837+ self.simple_user = self.factory.makePerson()
3838+
3839+ def test_distributionpage_addseries_link(self):
3840+ """ Verify that an admin sees the +addseries link."""
3841+ login_person(self.admin)
3842+ view = create_initialized_view(
3843+ self.distro, '+index', principal=self.admin)
3844+ series_matches = soupmatchers.HTMLContains(
3845+ soupmatchers.Tag(
3846+ 'link to add a series', 'a',
3847+ attrs={'href':
3848+ canonical_url(self.distro, view_name='+addseries')},
3849+ text='Add series'),
3850+ soupmatchers.Tag(
3851+ 'Series and milestones widget', 'h2',
3852+ text='Series and milestones'),
3853+ )
3854+ self.assertThat(view.render(), series_matches)
3855+
3856+ def test_distributionpage_addseries_link_noadmin(self):
3857+ """Verify that a non-admin does not see the +addseries link
3858+ nor the series header (since there is no series yet).
3859+ """
3860+ login_person(self.simple_user)
3861+ view = create_initialized_view(
3862+ self.distro, '+index', principal=self.simple_user)
3863+ add_series_match = soupmatchers.HTMLContains(
3864+ soupmatchers.Tag(
3865+ 'link to add a series', 'a',
3866+ attrs={'href':
3867+ canonical_url(self.distro, view_name='+addseries')},
3868+ text='Add series'))
3869+ series_header_match = soupmatchers.HTMLContains(
3870+ soupmatchers.Tag(
3871+ 'Series and milestones widget', 'h2',
3872+ text='Series and milestones'))
3873+ self.assertThat(
3874+ view.render(),
3875+ Not(MatchesAny(add_series_match, series_header_match)))
3876+
3877+ def test_distributionpage_series_list_noadmin(self):
3878+ """Verify that a non-admin does see the series list
3879+ when there is a series.
3880+ """
3881+ self.factory.makeDistroSeries(distribution=self.distro,
3882+ status=SeriesStatus.CURRENT)
3883+ login_person(self.simple_user)
3884+ view = create_initialized_view(
3885+ self.distro, '+index', principal=self.simple_user)
3886+ add_series_match = soupmatchers.HTMLContains(
3887+ soupmatchers.Tag(
3888+ 'link to add a series', 'a',
3889+ attrs={'href':
3890+ canonical_url(self.distro, view_name='+addseries')},
3891+ text='Add series'))
3892+ series_header_match = soupmatchers.HTMLContains(
3893+ soupmatchers.Tag(
3894+ 'Series and milestones widget', 'h2',
3895+ text='Series and milestones'))
3896+ self.assertThat(view.render(), series_header_match)
3897+ self.assertThat(view.render(), Not(add_series_match))
3898+
3899+
3900+class DistroRegistrantTestCase(TestCaseWithFactory):
3901+ """A TestCase for registrants and owners of a distribution.
3902+
3903+ The registrant is the creator of the distribution (read-only field).
3904+ The owner is really the maintainer.
3905+ """
3906+
3907+ layer = DatabaseFunctionalLayer
3908+
3909+ def setUp(self):
3910+ super(DistroRegistrantTestCase, self).setUp()
3911+ self.owner = self.factory.makePerson()
3912+ self.registrant = self.factory.makePerson()
3913+
3914+ def test_distro_registrant_owner_differ(self):
3915+ distribution = self.factory.makeDistribution(
3916+ name="boobuntu", owner=self.owner, registrant=self.registrant)
3917+ self.assertNotEqual(distribution.owner, distribution.registrant)
3918+ self.assertEqual(distribution.owner, self.owner)
3919+ self.assertEqual(distribution.registrant, self.registrant)
3920
3921=== modified file 'lib/lp/registry/tests/test_distributionsourcepackage.py'
3922--- lib/lp/registry/tests/test_distributionsourcepackage.py 2010-10-04 19:50:45 +0000
3923+++ lib/lp/registry/tests/test_distributionsourcepackage.py 2011-03-29 10:32:58 +0000
3924@@ -32,7 +32,8 @@
3925 distribution = distribution_set.new(name='wart',
3926 displayname='wart', title='wart', description='lots of warts',
3927 summary='lots of warts', domainname='wart.dumb',
3928- members=self.factory.makeTeam(), owner=self.factory.makePerson())
3929+ members=self.factory.makeTeam(), owner=self.factory.makePerson(),
3930+ registrant=self.factory.makePerson())
3931 naked_distribution = removeSecurityProxy(distribution)
3932 self.factory.makeSourcePackage(distroseries=distribution)
3933 dsp = naked_distribution.getSourcePackage(name='pmount')
3934
3935=== modified file 'lib/lp/registry/tests/test_distroseries.py'
3936--- lib/lp/registry/tests/test_distroseries.py 2011-03-10 14:05:51 +0000
3937+++ lib/lp/registry/tests/test_distroseries.py 2011-03-29 10:32:58 +0000
3938@@ -211,6 +211,15 @@
3939 self.assertContentEqual(
3940 [distroseries], distroseries.parent_series.getDerivedSeries())
3941
3942+ def test_registrant_owner_differ(self):
3943+ # The registrant is the creator whereas the owner is the distribution's
3944+ # owner
3945+ registrant = self.factory.makePerson()
3946+ distroseries = self.factory.makeDistroRelease(registrant=registrant)
3947+ self.assertEquals(distroseries.distribution.owner, distroseries.owner)
3948+ self.assertEquals(registrant, distroseries.registrant)
3949+ self.assertNotEqual(distroseries.registrant, distroseries.owner)
3950+
3951
3952 class TestDistroSeriesPackaging(TestCaseWithFactory):
3953
3954
3955=== modified file 'lib/lp/registry/tests/test_pillarname_triggers.py'
3956--- lib/lp/registry/tests/test_pillarname_triggers.py 2010-10-04 19:50:45 +0000
3957+++ lib/lp/registry/tests/test_pillarname_triggers.py 2011-03-29 10:32:58 +0000
3958@@ -46,12 +46,12 @@
3959 # Inserting a new Distribution will populate PillarName
3960 cur.execute("""
3961 INSERT INTO Distribution (
3962- name, description, domainname, owner, displayname,
3963- summary, title, members, mirror_admin
3964+ name, description, domainname, owner, registrant,
3965+ displayname, summary, title, members, mirror_admin
3966 )
3967 VALUES (
3968- 'whatever', 'whatever', 'whatever', 1, 'whatever',
3969- 'whatever', 'whatever', 1, 1
3970+ 'whatever', 'whatever', 'whatever', 1, 1,
3971+ 'whatever', 'whatever', 'whatever', 1, 1
3972 )
3973 """)
3974 self.failUnless(is_in_sync('whatever'))
3975@@ -69,7 +69,8 @@
3976 """)
3977 self.failUnless(is_in_sync('whatever2'))
3978
3979- # Deleting a Distribution removes the corresponding entry in PillarName
3980+ # Deleting a Distribution removes the corresponding entry in
3981+ # PillarName
3982 cur.execute("DELETE FROM Distribution WHERE name='whatever2'")
3983 cur.execute("SELECT COUNT(*) FROM PillarName WHERE name='whatever2'")
3984 self.failUnlessEqual(cur.fetchone()[0], 0)
3985@@ -101,7 +102,8 @@
3986
3987 # Inserting a new Product will populate PillarName
3988 cur.execute("""
3989- INSERT INTO Product (owner, registrant, name, displayname, title, summary)
3990+ INSERT INTO Product (
3991+ owner, registrant, name, displayname, title, summary)
3992 VALUES (
3993 1, 1, 'whatever', 'whatever', 'whatever', 'whatever'
3994 )
3995@@ -154,7 +156,8 @@
3996 # Inserting a new ProjectGroup will populate PillarName
3997 cur.execute("""
3998 INSERT INTO Project (
3999- name, owner, registrant, displayname, title, summary, description
4000+ name, owner, registrant, displayname, title, summary,
4001+ description
4002 )
4003 VALUES (
4004 'whatever', 1, 1, 'whatever', 'whatever',
4005
4006=== modified file 'lib/lp/scripts/garbo.py'
4007--- lib/lp/scripts/garbo.py 2011-03-09 23:43:02 +0000
4008+++ lib/lp/scripts/garbo.py 2011-03-29 10:32:58 +0000
4009@@ -86,6 +86,7 @@
4010 LaunchpadCronScript,
4011 SilentLaunchpadScriptFailure,
4012 )
4013+from lp.services.session.model import SessionData
4014 from lp.soyuz.model.files import SourcePackageReleaseFile
4015 from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
4016 from lp.translations.interfaces.potemplate import IPOTemplateSet
4017@@ -125,10 +126,14 @@
4018 # from. Must be overridden.
4019 target_table_class = None
4020
4021- # The column name in target_table we use as the integer key. May be
4022- # overridden.
4023+ # The column name in target_table we use as the key. The type must
4024+ # match that returned by the ids_to_prune_query and the
4025+ # target_table_key_type. May be overridden.
4026 target_table_key = 'id'
4027
4028+ # SQL type of the target_table_key. May be overridden.
4029+ target_table_key_type = 'integer'
4030+
4031 # An SQL query returning a list of ids to remove from target_table.
4032 # The query must return a single column named 'id' and should not
4033 # contain duplicates. Must be overridden.
4034@@ -137,10 +142,17 @@
4035 # See `TunableLoop`. May be overridden.
4036 maximum_chunk_size = 10000
4037
4038+ def getStore(self):
4039+ """The master Store for the table we are pruning.
4040+
4041+ May be overridden.
4042+ """
4043+ return IMasterStore(self.target_table_class)
4044+
4045 def __init__(self, log, abort_time=None):
4046 super(BulkPruner, self).__init__(log, abort_time)
4047
4048- self.store = IMasterStore(self.target_table_class)
4049+ self.store = self.getStore()
4050 self.target_table_name = self.target_table_class.__storm_table__
4051
4052 # Open the cursor.
4053@@ -157,11 +169,14 @@
4054 def __call__(self, chunk_size):
4055 """See `ITunableLoop`."""
4056 result = self.store.execute("""
4057- DELETE FROM %s WHERE %s IN (
4058+ DELETE FROM %s
4059+ WHERE %s IN (
4060 SELECT id FROM
4061- cursor_fetch('bulkprunerid', %d) AS f(id integer))
4062+ cursor_fetch('bulkprunerid', %d) AS f(id %s))
4063 """
4064- % (self.target_table_name, self.target_table_key, chunk_size))
4065+ % (
4066+ self.target_table_name, self.target_table_key,
4067+ chunk_size, self.target_table_key_type))
4068 self._num_removed = result.rowcount
4069 transaction.commit()
4070
4071@@ -175,9 +190,7 @@
4072
4073 XXX bug=723596 StuartBishop: This job only needs to run once per month.
4074 """
4075-
4076 target_table_class = POTranslation
4077-
4078 ids_to_prune_query = """
4079 SELECT POTranslation.id AS id FROM POTranslation
4080 EXCEPT (
4081@@ -204,6 +217,68 @@
4082 """
4083
4084
4085+class SessionPruner(BulkPruner):
4086+ """Base class for session removal."""
4087+
4088+ target_table_class = SessionData
4089+ target_table_key = 'client_id'
4090+ target_table_key_type = 'text'
4091+
4092+
4093+class AntiqueSessionPruner(SessionPruner):
4094+ """Remove sessions not accessed for 60 days"""
4095+
4096+ ids_to_prune_query = """
4097+ SELECT client_id AS id FROM SessionData
4098+ WHERE last_accessed < CURRENT_TIMESTAMP - CAST('60 days' AS interval)
4099+ """
4100+
4101+
4102+class UnusedSessionPruner(SessionPruner):
4103+ """Remove sessions older than 1 day with no authentication credentials."""
4104+
4105+ ids_to_prune_query = """
4106+ SELECT client_id AS id FROM SessionData
4107+ WHERE
4108+ last_accessed < CURRENT_TIMESTAMP - CAST('1 day' AS interval)
4109+ AND client_id NOT IN (
4110+ SELECT client_id
4111+ FROM SessionPkgData
4112+ WHERE
4113+ product_id = 'launchpad.authenticateduser'
4114+ AND key='logintime')
4115+ """
4116+
4117+
4118+class DuplicateSessionPruner(SessionPruner):
4119+ """Remove all but the most recent 6 authenticated sessions for a user.
4120+
4121+ We sometimes see users with dozens or thousands of authenticated
4122+ sessions. To limit exposure to replay attacks, we remove all but
4123+ the most recent 6 of them for a given user.
4124+ """
4125+
4126+ ids_to_prune_query = """
4127+ SELECT client_id AS id
4128+ FROM (
4129+ SELECT
4130+ sessiondata.client_id,
4131+ last_accessed,
4132+ rank() OVER pickle AS rank
4133+ FROM SessionData, SessionPkgData
4134+ WHERE
4135+ SessionData.client_id = SessionPkgData.client_id
4136+ AND product_id = 'launchpad.authenticateduser'
4137+ AND key='accountid'
4138+ WINDOW pickle AS (PARTITION BY pickle ORDER BY last_accessed DESC)
4139+ ) AS whatever
4140+ WHERE
4141+ rank > 6
4142+ AND last_accessed < CURRENT_TIMESTAMP AT TIME ZONE 'UTC'
4143+ - CAST('1 hour' AS interval)
4144+ """
4145+
4146+
4147 class OAuthNoncePruner(TunableLoop):
4148 """An ITunableLoop to prune old OAuthNonce records.
4149
4150@@ -1113,6 +1188,9 @@
4151 RevisionCachePruner,
4152 BugHeatUpdater,
4153 BugWatchScheduler,
4154+ AntiqueSessionPruner,
4155+ UnusedSessionPruner,
4156+ DuplicateSessionPruner,
4157 PopulateSPRChangelogs,
4158 ]
4159 experimental_tunable_loops = []
4160
4161=== modified file 'lib/lp/scripts/tests/test_garbo.py'
4162--- lib/lp/scripts/tests/test_garbo.py 2011-03-09 23:43:02 +0000
4163+++ lib/lp/scripts/tests/test_garbo.py 2011-03-29 10:32:58 +0000
4164@@ -20,7 +20,10 @@
4165 Min,
4166 SQL,
4167 )
4168-from storm.locals import Storm, Int
4169+from storm.locals import (
4170+ Int,
4171+ Storm,
4172+ )
4173 from storm.store import Store
4174 import transaction
4175 from zope.component import getUtility
4176@@ -74,13 +77,20 @@
4177 PersonCreationRationale,
4178 )
4179 from lp.scripts.garbo import (
4180+ AntiqueSessionPruner,
4181 BulkPruner,
4182 DailyDatabaseGarbageCollector,
4183+ DuplicateSessionPruner,
4184 HourlyDatabaseGarbageCollector,
4185 OpenIDConsumerAssociationPruner,
4186+ UnusedSessionPruner,
4187 )
4188 from lp.services.job.model.job import Job
4189 from lp.services.log.logger import BufferLogger
4190+from lp.services.session.model import (
4191+ SessionData,
4192+ SessionPkgData,
4193+ )
4194 from lp.soyuz.enums import PackagePublishingStatus
4195 from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
4196 from lp.testing import (
4197@@ -195,6 +205,153 @@
4198 pruner(chunk_size)
4199
4200
4201+class TestSessionPruner(TestCase):
4202+ layer = ZopelessDatabaseLayer
4203+
4204+ def setUp(self):
4205+ super(TestCase, self).setUp()
4206+
4207+ # Session database isn't reset between tests. We need to do this
4208+ # manually.
4209+ nuke_all_sessions = IMasterStore(SessionData).find(SessionData).remove
4210+ nuke_all_sessions()
4211+ self.addCleanup(nuke_all_sessions)
4212+
4213+ recent = datetime.now(UTC)
4214+ yesterday = recent - timedelta(days=1)
4215+ ancient = recent - timedelta(days=61)
4216+
4217+ self.make_session(u'recent_auth', recent, 'auth1')
4218+ self.make_session(u'recent_unauth', recent, False)
4219+ self.make_session(u'yesterday_auth', yesterday, 'auth2')
4220+ self.make_session(u'yesterday_unauth', yesterday, False)
4221+ self.make_session(u'ancient_auth', ancient, 'auth3')
4222+ self.make_session(u'ancient_unauth', ancient, False)
4223+
4224+ def make_session(self, client_id, accessed, authenticated=None):
4225+ session_data = SessionData()
4226+ session_data.client_id = client_id
4227+ session_data.last_accessed = accessed
4228+ IMasterStore(SessionData).add(session_data)
4229+
4230+ if authenticated:
4231+ # Add login time information.
4232+ session_pkg_data = SessionPkgData()
4233+ session_pkg_data.client_id = client_id
4234+ session_pkg_data.product_id = u'launchpad.authenticateduser'
4235+ session_pkg_data.key = u'logintime'
4236+ session_pkg_data.pickle = 'value is ignored'
4237+ IMasterStore(SessionPkgData).add(session_pkg_data)
4238+
4239+ # Add authenticated as information.
4240+ session_pkg_data = SessionPkgData()
4241+ session_pkg_data.client_id = client_id
4242+ session_pkg_data.product_id = u'launchpad.authenticateduser'
4243+ session_pkg_data.key = u'accountid'
4244+ # Normally Account.id, but the session pruning works
4245+ # at the SQL level and doesn't unpickle anything.
4246+ session_pkg_data.pickle = authenticated
4247+ IMasterStore(SessionPkgData).add(session_pkg_data)
4248+
4249+ def sessionExists(self, client_id):
4250+ store = IMasterStore(SessionData)
4251+ return not store.find(
4252+ SessionData, SessionData.client_id == client_id).is_empty()
4253+
4254+ def test_antique_session_pruner(self):
4255+ chunk_size = 2
4256+ log = BufferLogger()
4257+ pruner = AntiqueSessionPruner(log)
4258+ try:
4259+ while not pruner.isDone():
4260+ pruner(chunk_size)
4261+ finally:
4262+ pruner.cleanUp()
4263+
4264+ expected_sessions = set([
4265+ u'recent_auth',
4266+ u'recent_unauth',
4267+ u'yesterday_auth',
4268+ u'yesterday_unauth',
4269+ # u'ancient_auth',
4270+ # u'ancient_unauth',
4271+ ])
4272+
4273+ found_sessions = set(
4274+ IMasterStore(SessionData).find(SessionData.client_id))
4275+
4276+ self.assertEqual(expected_sessions, found_sessions)
4277+
4278+ def test_unused_session_pruner(self):
4279+ chunk_size = 2
4280+ log = BufferLogger()
4281+ pruner = UnusedSessionPruner(log)
4282+ try:
4283+ while not pruner.isDone():
4284+ pruner(chunk_size)
4285+ finally:
4286+ pruner.cleanUp()
4287+
4288+ expected_sessions = set([
4289+ u'recent_auth',
4290+ u'recent_unauth',
4291+ u'yesterday_auth',
4292+ # u'yesterday_unauth',
4293+ u'ancient_auth',
4294+ # u'ancient_unauth',
4295+ ])
4296+
4297+ found_sessions = set(
4298+ IMasterStore(SessionData).find(SessionData.client_id))
4299+
4300+ self.assertEqual(expected_sessions, found_sessions)
4301+
4302+ def test_duplicate_session_pruner(self):
4303+ # None of the sessions created in setUp() are duplicates, so
4304+ # they will all survive the pruning.
4305+ expected_sessions = set([
4306+ u'recent_auth',
4307+ u'recent_unauth',
4308+ u'yesterday_auth',
4309+ u'yesterday_unauth',
4310+ u'ancient_auth',
4311+ u'ancient_unauth',
4312+ ])
4313+
4314+ now = datetime.now(UTC)
4315+
4316+ # Make some duplicate logins from a few days ago.
4317+ # Only the most recent 6 will be kept. Oldest is 'old dupe 9',
4318+ # most recent 'old dupe 1'.
4319+ for count in range(1, 10):
4320+ self.make_session(
4321+ u'old dupe %d' % count,
4322+ now - timedelta(days=2, seconds=count),
4323+ 'old dupe')
4324+ for count in range(1, 7):
4325+ expected_sessions.add(u'old dupe %d' % count)
4326+
4327+ # Make some other duplicate logins less than an hour old.
4328+ # All of these will be kept.
4329+ for count in range(1, 10):
4330+ self.make_session(u'new dupe %d' % count, now, 'new dupe')
4331+ expected_sessions.add(u'new dupe %d' % count)
4332+
4333+ chunk_size = 2
4334+ log = BufferLogger()
4335+ pruner = DuplicateSessionPruner(log)
4336+ try:
4337+ while not pruner.isDone():
4338+ pruner(chunk_size)
4339+ finally:
4340+ pruner.cleanUp()
4341+
4342+ found_sessions = set(
4343+ IMasterStore(SessionData).find(SessionData.client_id))
4344+
4345+ self.assertEqual(expected_sessions, found_sessions)
4346+
4347+
4348 class TestGarbo(TestCaseWithFactory):
4349 layer = LaunchpadZopelessLayer
4350
4351@@ -223,7 +380,7 @@
4352 return collector
4353
4354 def test_OAuthNoncePruner(self):
4355- now = datetime.utcnow().replace(tzinfo=UTC)
4356+ now = datetime.now(UTC)
4357 timestamps = [
4358 now - timedelta(days=2), # Garbage
4359 now - timedelta(days=1) - timedelta(seconds=60), # Garbage
4360@@ -301,7 +458,7 @@
4361 self.failUnless(earliest >= now - 24*60*60, 'Still have old nonces')
4362
4363 def test_CodeImportResultPruner(self):
4364- now = datetime.utcnow().replace(tzinfo=UTC)
4365+ now = datetime.now(UTC)
4366 store = IMasterStore(CodeImportResult)
4367
4368 results_to_keep_count = (
4369@@ -358,7 +515,7 @@
4370 >= now - timedelta(days=30))
4371
4372 def test_CodeImportEventPruner(self):
4373- now = datetime.utcnow().replace(tzinfo=UTC)
4374+ now = datetime.now(UTC)
4375 store = IMasterStore(CodeImportResult)
4376
4377 LaunchpadZopelessLayer.switchDbUser('testadmin')
4378
4379=== modified file 'lib/lp/scripts/utilities/sanitizedb.py'
4380--- lib/lp/scripts/utilities/sanitizedb.py 2011-02-21 00:06:55 +0000
4381+++ lib/lp/scripts/utilities/sanitizedb.py 2011-03-29 10:32:58 +0000
4382@@ -13,7 +13,10 @@
4383 import subprocess
4384 import sys
4385
4386-from storm.locals import Or
4387+from storm.expr import (
4388+ Join,
4389+ Or,
4390+ )
4391 import transaction
4392 from zope.component import getUtility
4393
4394@@ -254,8 +257,14 @@
4395 def removePrivateBugMessages(self):
4396 """Remove all hidden bug messages."""
4397 from lp.bugs.model.bugmessage import BugMessage
4398+ from canonical.launchpad.database.message import Message
4399+ message_ids = list(self.store.using(*[
4400+ BugMessage,
4401+ Join(Message, BugMessage.messageID == Message.id),
4402+ ]).find(BugMessage.id, Message.visible == False))
4403+ self.store.flush()
4404 count = self.store.find(
4405- BugMessage, BugMessage.visible == False).remove()
4406+ BugMessage, BugMessage.id.is_in(message_ids)).remove()
4407 self.store.flush()
4408 self.logger.info("Removed %d private bug messages.", count)
4409
4410@@ -578,7 +587,11 @@
4411 # deletes because they fail (attempting to change a mutating table).
4412 # We can repair these caches by forcing the triggers to run for
4413 # every row.
4414- self.store.execute("UPDATE BugMessage SET visible=visible")
4415+ self.store.execute("""
4416+ UPDATE Message SET visible=visible
4417+ FROM BugMessage
4418+ WHERE BugMessage.message = Message.id
4419+ """)
4420
4421 def _fail(self, error_message):
4422 self.logger.fatal(error_message)
4423
4424=== modified file 'lib/lp/services/configure.zcml'
4425--- lib/lp/services/configure.zcml 2011-03-07 16:32:12 +0000
4426+++ lib/lp/services/configure.zcml 2011-03-29 10:32:58 +0000
4427@@ -16,5 +16,6 @@
4428 <include package=".profile" />
4429 <include package=".salesforce" />
4430 <include package=".scripts" />
4431+ <include package=".session" />
4432 <include package=".worlddata" />
4433 </configure>
4434
4435=== added directory 'lib/lp/services/session'
4436=== added file 'lib/lp/services/session/__init__.py'
4437=== added file 'lib/lp/services/session/adapters.py'
4438--- lib/lp/services/session/adapters.py 1970-01-01 00:00:00 +0000
4439+++ lib/lp/services/session/adapters.py 2011-03-29 10:32:58 +0000
4440@@ -0,0 +1,40 @@
4441+# Copyright 2011 Canonical Ltd. This software is licensed under the
4442+# GNU Affero General Public License version 3 (see the file LICENSE).
4443+
4444+"""Session adapters."""
4445+
4446+__metaclass__ = type
4447+__all__ = []
4448+
4449+
4450+from zope.component import adapter
4451+from zope.interface import implementer
4452+
4453+from canonical.database.sqlbase import session_store
4454+from canonical.launchpad.interfaces.lpstorm import (
4455+ IMasterStore,
4456+ ISlaveStore,
4457+ IStore,
4458+ )
4459+from lp.services.session.interfaces import IUseSessionStore
4460+
4461+
4462+@adapter(IUseSessionStore)
4463+@implementer(IMasterStore)
4464+def session_master_store(cls):
4465+ """Adapt a Session database object to an `IMasterStore`."""
4466+ return session_store()
4467+
4468+
4469+@adapter(IUseSessionStore)
4470+@implementer(ISlaveStore)
4471+def session_slave_store(cls):
4472+ """Adapt a Session database object to an `ISlaveStore`."""
4473+ return session_store()
4474+
4475+
4476+@adapter(IUseSessionStore)
4477+@implementer(IStore)
4478+def session_default_store(cls):
4479+ """Adapt an Session database object to an `IStore`."""
4480+ return session_store()
4481
4482=== added file 'lib/lp/services/session/configure.zcml'
4483--- lib/lp/services/session/configure.zcml 1970-01-01 00:00:00 +0000
4484+++ lib/lp/services/session/configure.zcml 2011-03-29 10:32:58 +0000
4485@@ -0,0 +1,12 @@
4486+<!-- Copyright 2011 Canonical Ltd. This software is licensed under the
4487+ GNU Affero General Public License version 3 (see the file LICENSE).
4488+-->
4489+<configure
4490+ xmlns="http://namespaces.zope.org/zope"
4491+ xmlns:browser="http://namespaces.zope.org/browser"
4492+ xmlns:i18n="http://namespaces.zope.org/i18n"
4493+ i18n_domain="launchpad">
4494+ <adapter factory=".adapters.session_master_store" />
4495+ <adapter factory=".adapters.session_slave_store" />
4496+ <adapter factory=".adapters.session_default_store" />
4497+</configure>
4498
4499=== added file 'lib/lp/services/session/interfaces.py'
4500--- lib/lp/services/session/interfaces.py 1970-01-01 00:00:00 +0000
4501+++ lib/lp/services/session/interfaces.py 2011-03-29 10:32:58 +0000
4502@@ -0,0 +1,15 @@
4503+# Copyright 2011 Canonical Ltd. This software is licensed under the
4504+# GNU Affero General Public License version 3 (see the file LICENSE).
4505+
4506+"""Session interfaces."""
4507+
4508+__metaclass__ = type
4509+__all__ = ['IUseSessionStore']
4510+
4511+
4512+from zope.interface import Interface
4513+
4514+
4515+class IUseSessionStore(Interface):
4516+ """Marker interface for Session Storm database classes and instances."""
4517+ pass
4518
4519=== added file 'lib/lp/services/session/model.py'
4520--- lib/lp/services/session/model.py 1970-01-01 00:00:00 +0000
4521+++ lib/lp/services/session/model.py 2011-03-29 10:32:58 +0000
4522@@ -0,0 +1,47 @@
4523+# Copyright 2011 Canonical Ltd. This software is licensed under the
4524+# GNU Affero General Public License version 3 (see the file LICENSE).
4525+
4526+"""Session Storm database classes"""
4527+
4528+__metaclass__ = type
4529+__all__ = ['SessionData', 'SessionPkgData']
4530+
4531+from storm.locals import (
4532+ Pickle,
4533+ Storm,
4534+ Unicode,
4535+ )
4536+from zope.interface import (
4537+ classProvides,
4538+ implements,
4539+ )
4540+
4541+from canonical.database.datetimecol import UtcDateTimeCol
4542+from lp.services.session.interfaces import IUseSessionStore
4543+
4544+
4545+class SessionData(Storm):
4546+ """A user's Session."""
4547+
4548+ classProvides(IUseSessionStore)
4549+ implements(IUseSessionStore)
4550+
4551+ __storm_table__ = 'SessionData'
4552+ client_id = Unicode(primary=True)
4553+ created = UtcDateTimeCol()
4554+ last_accessed = UtcDateTimeCol()
4555+
4556+
4557+class SessionPkgData(Storm):
4558+ """Data storage for a Session."""
4559+
4560+ classProvides(IUseSessionStore)
4561+ implements(IUseSessionStore)
4562+
4563+ __storm_table__ = 'SessionPkgData'
4564+ __storm_primary__ = 'client_id', 'product_id', 'key'
4565+
4566+ client_id = Unicode()
4567+ product_id = Unicode()
4568+ key = Unicode()
4569+ pickle = Pickle()
4570
4571=== added directory 'lib/lp/services/session/tests'
4572=== added file 'lib/lp/services/session/tests/__init__.py'
4573=== added file 'lib/lp/services/session/tests/test_session.py'
4574--- lib/lp/services/session/tests/test_session.py 1970-01-01 00:00:00 +0000
4575+++ lib/lp/services/session/tests/test_session.py 2011-03-29 10:32:58 +0000
4576@@ -0,0 +1,32 @@
4577+# Copyright 2011 Canonical Ltd. This software is licensed under the
4578+# GNU Affero General Public License version 3 (see the file LICENSE).
4579+
4580+"""Session tests."""
4581+
4582+__metaclass__ = type
4583+
4584+from canonical.launchpad.interfaces.lpstorm import (
4585+ IMasterStore,
4586+ ISlaveStore,
4587+ IStore,
4588+ )
4589+from canonical.testing.layers import DatabaseFunctionalLayer
4590+from lp.services.session.model import (
4591+ SessionData,
4592+ SessionPkgData,
4593+ )
4594+from lp.testing import TestCase
4595+
4596+
4597+class TestSessionModelAdapters(TestCase):
4598+ layer = DatabaseFunctionalLayer
4599+
4600+ def test_adapters(self):
4601+ for adapter in [IMasterStore, ISlaveStore, IStore]:
4602+ for cls in [SessionData, SessionPkgData]:
4603+ for obj in [cls, cls()]:
4604+ store = adapter(obj)
4605+ self.assert_(
4606+ 'session' in store.get_database()._dsn,
4607+ 'Unknown store returned adapting %r to %r'
4608+ % (obj, adapter))
4609
4610=== modified file 'lib/lp/soyuz/doc/archive-dependencies.txt'
4611--- lib/lp/soyuz/doc/archive-dependencies.txt 2010-10-18 12:35:41 +0000
4612+++ lib/lp/soyuz/doc/archive-dependencies.txt 2011-03-29 10:32:58 +0000
4613@@ -226,11 +226,11 @@
4614 0
4615
4616 >>> print_building_sources_list(a_build)
4617- deb http://ftpmaster.internal/ubuntu hoary
4618- main restricted universe multiverse
4619- deb http://ftpmaster.internal/ubuntu hoary-security
4620- main restricted universe multiverse
4621- deb http://ftpmaster.internal/ubuntu hoary-updates
4622+ deb http://archive.launchpad.dev/ubuntu hoary
4623+ main restricted universe multiverse
4624+ deb http://archive.launchpad.dev/ubuntu hoary-security
4625+ main restricted universe multiverse
4626+ deb http://archive.launchpad.dev/ubuntu hoary-updates
4627 main restricted universe multiverse
4628
4629 Once we publish a test binary in Celso's PPA hoary/i386,
4630@@ -243,11 +243,11 @@
4631
4632 >>> print_building_sources_list(a_build)
4633 deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
4634- deb http://ftpmaster.internal/ubuntu hoary
4635- main restricted universe multiverse
4636- deb http://ftpmaster.internal/ubuntu hoary-security
4637- main restricted universe multiverse
4638- deb http://ftpmaster.internal/ubuntu hoary-updates
4639+ deb http://archive.launchpad.dev/ubuntu hoary
4640+ main restricted universe multiverse
4641+ deb http://archive.launchpad.dev/ubuntu hoary-security
4642+ main restricted universe multiverse
4643+ deb http://archive.launchpad.dev/ubuntu hoary-updates
4644 main restricted universe multiverse
4645
4646 Similarly, unpopulated PPA dependencies are *not* listed in the building
4647@@ -259,11 +259,11 @@
4648 ... getUtility(IComponentSet)['main'])
4649 >>> print_building_sources_list(a_build)
4650 deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
4651- deb http://ftpmaster.internal/ubuntu hoary
4652- main restricted universe multiverse
4653- deb http://ftpmaster.internal/ubuntu hoary-security
4654- main restricted universe multiverse
4655- deb http://ftpmaster.internal/ubuntu hoary-updates
4656+ deb http://archive.launchpad.dev/ubuntu hoary
4657+ main restricted universe multiverse
4658+ deb http://archive.launchpad.dev/ubuntu hoary-security
4659+ main restricted universe multiverse
4660+ deb http://archive.launchpad.dev/ubuntu hoary-updates
4661 main restricted universe multiverse
4662
4663 But *populated* PPA dependencies *are* listed in the building 'sources_list'.
4664@@ -274,11 +274,11 @@
4665 >>> print_building_sources_list(a_build)
4666 deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
4667 deb http://ppa.launchpad.dev/mark/ppa/ubuntu hoary main
4668- deb http://ftpmaster.internal/ubuntu hoary
4669- main restricted universe multiverse
4670- deb http://ftpmaster.internal/ubuntu hoary-security
4671- main restricted universe multiverse
4672- deb http://ftpmaster.internal/ubuntu hoary-updates
4673+ deb http://archive.launchpad.dev/ubuntu hoary
4674+ main restricted universe multiverse
4675+ deb http://archive.launchpad.dev/ubuntu hoary-security
4676+ main restricted universe multiverse
4677+ deb http://archive.launchpad.dev/ubuntu hoary-updates
4678 main restricted universe multiverse
4679
4680 The authentication information gets added for private PPA
4681@@ -300,11 +300,11 @@
4682 deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
4683 deb http://buildd:sekrit@private-ppa.launchpad.dev/mark/p3a/ubuntu
4684 hoary main
4685- deb http://ftpmaster.internal/ubuntu hoary
4686- main restricted universe multiverse
4687- deb http://ftpmaster.internal/ubuntu hoary-security
4688- main restricted universe multiverse
4689- deb http://ftpmaster.internal/ubuntu hoary-updates
4690+ deb http://archive.launchpad.dev/ubuntu hoary
4691+ main restricted universe multiverse
4692+ deb http://archive.launchpad.dev/ubuntu hoary-security
4693+ main restricted universe multiverse
4694+ deb http://archive.launchpad.dev/ubuntu hoary-updates
4695 main restricted universe multiverse
4696
4697 Remove the private PPA dependency before continuing.
4698@@ -332,11 +332,11 @@
4699 ValueError: incomplete format
4700 <BLANKLINE>
4701 deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
4702- deb http://ftpmaster.internal/ubuntu hoary
4703- main restricted universe multiverse
4704- deb http://ftpmaster.internal/ubuntu hoary-security
4705- main restricted universe multiverse
4706- deb http://ftpmaster.internal/ubuntu hoary-updates
4707+ deb http://archive.launchpad.dev/ubuntu hoary
4708+ main restricted universe multiverse
4709+ deb http://archive.launchpad.dev/ubuntu hoary-security
4710+ main restricted universe multiverse
4711+ deb http://archive.launchpad.dev/ubuntu hoary-updates
4712 main restricted universe multiverse
4713
4714 However, in order to avoid the problem going forward (and to allow the PPA
4715@@ -372,11 +372,11 @@
4716 ValueError: incomplete format
4717 <BLANKLINE>
4718 deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
4719- deb http://ftpmaster.internal/ubuntu hoary
4720- main restricted universe multiverse
4721- deb http://ftpmaster.internal/ubuntu hoary-security
4722- main restricted universe multiverse
4723- deb http://ftpmaster.internal/ubuntu hoary-updates
4724+ deb http://archive.launchpad.dev/ubuntu hoary
4725+ main restricted universe multiverse
4726+ deb http://archive.launchpad.dev/ubuntu hoary-security
4727+ main restricted universe multiverse
4728+ deb http://archive.launchpad.dev/ubuntu hoary-updates
4729 main restricted universe multiverse
4730
4731 However, in order to avoid the problem going forward (and to allow the PPA
4732@@ -407,11 +407,11 @@
4733
4734 >>> print_building_sources_list(a_build)
4735 deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
4736- deb http://ftpmaster.internal/ubuntu hoary
4737- main restricted universe multiverse
4738- deb http://ftpmaster.internal/ubuntu hoary-security
4739- main restricted universe multiverse
4740- deb http://ftpmaster.internal/ubuntu hoary-updates
4741+ deb http://archive.launchpad.dev/ubuntu hoary
4742+ main restricted universe multiverse
4743+ deb http://archive.launchpad.dev/ubuntu hoary-security
4744+ main restricted universe multiverse
4745+ deb http://archive.launchpad.dev/ubuntu hoary-updates
4746 main restricted universe multiverse
4747
4748 The default build behaviour will remain unchanged when we override the
4749@@ -423,11 +423,11 @@
4750
4751 >>> print_building_sources_list(a_build)
4752 deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
4753- deb http://ftpmaster.internal/ubuntu hoary
4754- main restricted universe multiverse
4755- deb http://ftpmaster.internal/ubuntu hoary-security
4756- main restricted universe multiverse
4757- deb http://ftpmaster.internal/ubuntu hoary-updates
4758+ deb http://archive.launchpad.dev/ubuntu hoary
4759+ main restricted universe multiverse
4760+ deb http://archive.launchpad.dev/ubuntu hoary-security
4761+ main restricted universe multiverse
4762+ deb http://archive.launchpad.dev/ubuntu hoary-updates
4763 main restricted universe multiverse
4764
4765 >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive)
4766@@ -450,9 +450,9 @@
4767
4768 >>> print_building_sources_list(a_build)
4769 deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
4770- deb http://ftpmaster.internal/ubuntu hoary
4771+ deb http://archive.launchpad.dev/ubuntu hoary
4772 main universe
4773- deb http://ftpmaster.internal/ubuntu hoary-security
4774+ deb http://archive.launchpad.dev/ubuntu hoary-security
4775 main universe
4776
4777 >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive)
4778@@ -467,7 +467,7 @@
4779
4780 >>> print_building_sources_list(a_build)
4781 deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
4782- deb http://ftpmaster.internal/ubuntu hoary main restricted
4783+ deb http://archive.launchpad.dev/ubuntu hoary main restricted
4784
4785 >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive)
4786
4787@@ -480,13 +480,13 @@
4788
4789 >>> print_building_sources_list(a_build)
4790 deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
4791- deb http://ftpmaster.internal/ubuntu hoary
4792- main restricted universe multiverse
4793- deb http://ftpmaster.internal/ubuntu hoary-security
4794- main restricted universe multiverse
4795- deb http://ftpmaster.internal/ubuntu hoary-updates
4796- main restricted universe multiverse
4797- deb http://ftpmaster.internal/ubuntu hoary-proposed
4798+ deb http://archive.launchpad.dev/ubuntu hoary
4799+ main restricted universe multiverse
4800+ deb http://archive.launchpad.dev/ubuntu hoary-security
4801+ main restricted universe multiverse
4802+ deb http://archive.launchpad.dev/ubuntu hoary-updates
4803+ main restricted universe multiverse
4804+ deb http://archive.launchpad.dev/ubuntu hoary-proposed
4805 main restricted universe multiverse
4806
4807 >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive)
4808@@ -499,13 +499,13 @@
4809
4810 >>> print_building_sources_list(a_build)
4811 deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main
4812- deb http://ftpmaster.internal/ubuntu hoary
4813- main restricted universe multiverse
4814- deb http://ftpmaster.internal/ubuntu hoary-security
4815- main restricted universe multiverse
4816- deb http://ftpmaster.internal/ubuntu hoary-updates
4817- main restricted universe multiverse
4818- deb http://ftpmaster.internal/ubuntu hoary-backports
4819+ deb http://archive.launchpad.dev/ubuntu hoary
4820+ main restricted universe multiverse
4821+ deb http://archive.launchpad.dev/ubuntu hoary-security
4822+ main restricted universe multiverse
4823+ deb http://archive.launchpad.dev/ubuntu hoary-updates
4824+ main restricted universe multiverse
4825+ deb http://archive.launchpad.dev/ubuntu hoary-backports
4826 main restricted universe multiverse
4827
4828 >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive)
4829@@ -532,12 +532,12 @@
4830 >>> [partner_build] = pub_source.createMissingBuilds()
4831
4832 >>> print_building_sources_list(partner_build)
4833- deb http://ftpmaster.internal/ubuntu-partner hoary partner
4834- deb http://ftpmaster.internal/ubuntu hoary
4835- main restricted universe multiverse
4836- deb http://ftpmaster.internal/ubuntu hoary-security
4837- main restricted universe multiverse
4838- deb http://ftpmaster.internal/ubuntu hoary-updates
4839+ deb http://archive.launchpad.dev/ubuntu-partner hoary partner
4840+ deb http://archive.launchpad.dev/ubuntu hoary
4841+ main restricted universe multiverse
4842+ deb http://archive.launchpad.dev/ubuntu hoary-security
4843+ main restricted universe multiverse
4844+ deb http://archive.launchpad.dev/ubuntu hoary-updates
4845 main restricted universe multiverse
4846
4847
4848@@ -570,9 +570,9 @@
4849 deb http://user:pass@repository zoing everything
4850 deb http://user:pass@repository hoary public private
4851 deb http://user:pass@repository hoary-extra public
4852- deb http://ftpmaster.internal/ubuntu hoary
4853- main restricted universe multiverse
4854- deb http://ftpmaster.internal/ubuntu hoary-security
4855- main restricted universe multiverse
4856- deb http://ftpmaster.internal/ubuntu hoary-updates
4857+ deb http://archive.launchpad.dev/ubuntu hoary
4858+ main restricted universe multiverse
4859+ deb http://archive.launchpad.dev/ubuntu hoary-security
4860+ main restricted universe multiverse
4861+ deb http://archive.launchpad.dev/ubuntu hoary-updates
4862 main restricted universe multiverse
4863
4864=== modified file 'lib/lp/soyuz/doc/archive.txt'
4865--- lib/lp/soyuz/doc/archive.txt 2011-03-03 00:43:44 +0000
4866+++ lib/lp/soyuz/doc/archive.txt 2011-03-29 10:32:58 +0000
4867@@ -1284,21 +1284,23 @@
4868 None
4869
4870 IArchive.archive_url will return a URL for the archive that the builder can
4871-use to retrieve files from it.
4872+use to retrieve files from it. Internal paths and urls supplied via the
4873+PunlisherConfig require us to log in as an admin:
4874
4875+ >>> login('admin@canonical.com')
4876 >>> print partner_archive.archive_url
4877- http://ftpmaster.internal/ubuntutest-partner
4878+ http://archive.launchpad.dev/ubuntutest-partner
4879
4880 >>> print sandbox_archive.archive_url
4881 http://ppa.launchpad.dev/name16/ppa/ubuntu
4882
4883 >>> print getUtility(IArchiveSet).getByDistroPurpose(
4884 ... ubuntutest, ArchivePurpose.PRIMARY).archive_url
4885- http://ftpmaster.internal/ubuntutest
4886+ http://archive.launchpad.dev/ubuntutest
4887
4888 >>> print getUtility(IArchiveSet).getByDistroPurpose(
4889 ... ubuntu, ArchivePurpose.DEBUG).archive_url
4890- http://ftpmaster.internal/ubuntu-debug
4891+ http://archive.launchpad.dev/ubuntu-debug
4892
4893 COPY archives use a URL format of <distro-name>-<archive-name>:
4894
4895@@ -1310,6 +1312,7 @@
4896 If the archive is private, the url may be different as private PPAs
4897 are published to a secure location.
4898
4899+ >>> login("celso.providelo@canonical.com")
4900 >>> print cprov_archive.archive_url
4901 http://ppa.launchpad.dev/cprov/ppa/ubuntu
4902
4903@@ -2460,7 +2463,7 @@
4904 >>> uber = getUtility(IDistributionSet).new(
4905 ... 'uberdistro', 'The uberdistro', 'The mother of all distros',
4906 ... 'All you would want from a distro', 'zero', 'uberdistro.org',
4907- ... mark, cprov)
4908+ ... mark, cprov, cprov)
4909
4910 The primary archive for the Überdistro was created by the
4911 IDistributionSet.new() method. Let's check its publish flag.
4912
4913=== modified file 'lib/lp/soyuz/doc/distroseriesqueue-translations.txt'
4914--- lib/lp/soyuz/doc/distroseriesqueue-translations.txt 2011-03-22 14:27:50 +0000
4915+++ lib/lp/soyuz/doc/distroseriesqueue-translations.txt 2011-03-29 10:32:58 +0000
4916@@ -158,16 +158,16 @@
4917 ... print '%s/%s by %s: %s' % (
4918 ... entry.distroseries.name, entry.sourcepackagename.name,
4919 ... entry.importer.name, entry.path)
4920- dapper/pmount by mark: po/es_ES.po
4921- dapper/pmount by mark: po/ca.po
4922- dapper/pmount by mark: po/de.po
4923- dapper/pmount by mark: po/cs.po
4924- dapper/pmount by mark: po/es.po
4925- dapper/pmount by mark: po/fr.po
4926- dapper/pmount by mark: po/hr.po
4927- dapper/pmount by mark: po/nb.po
4928- dapper/pmount by mark: po/pmount.pot
4929- dapper/pmount by mark: po/it_IT.po
4930+ dapper/pmount by ubuntu-team: po/es_ES.po
4931+ dapper/pmount by ubuntu-team: po/ca.po
4932+ dapper/pmount by ubuntu-team: po/de.po
4933+ dapper/pmount by ubuntu-team: po/cs.po
4934+ dapper/pmount by ubuntu-team: po/es.po
4935+ dapper/pmount by ubuntu-team: po/fr.po
4936+ dapper/pmount by ubuntu-team: po/hr.po
4937+ dapper/pmount by ubuntu-team: po/nb.po
4938+ dapper/pmount by ubuntu-team: po/pmount.pot
4939+ dapper/pmount by ubuntu-team: po/it_IT.po
4940
4941 # Abort the transaction so we can check the same upload in a different
4942 # pocket.
4943@@ -208,16 +208,16 @@
4944 ... print '%s/%s by %s: %s' % (
4945 ... entry.distroseries.name, entry.sourcepackagename.name,
4946 ... entry.importer.name, entry.path)
4947- dapper/pmount by mark: po/es_ES.po
4948- dapper/pmount by mark: po/ca.po
4949- dapper/pmount by mark: po/de.po
4950- dapper/pmount by mark: po/cs.po
4951- dapper/pmount by mark: po/es.po
4952- dapper/pmount by mark: po/fr.po
4953- dapper/pmount by mark: po/hr.po
4954- dapper/pmount by mark: po/nb.po
4955- dapper/pmount by mark: po/pmount.pot
4956- dapper/pmount by mark: po/it_IT.po
4957+ dapper/pmount by ubuntu-team: po/es_ES.po
4958+ dapper/pmount by ubuntu-team: po/ca.po
4959+ dapper/pmount by ubuntu-team: po/de.po
4960+ dapper/pmount by ubuntu-team: po/cs.po
4961+ dapper/pmount by ubuntu-team: po/es.po
4962+ dapper/pmount by ubuntu-team: po/fr.po
4963+ dapper/pmount by ubuntu-team: po/hr.po
4964+ dapper/pmount by ubuntu-team: po/nb.po
4965+ dapper/pmount by ubuntu-team: po/pmount.pot
4966+ dapper/pmount by ubuntu-team: po/it_IT.po
4967
4968 # Let's abort the transaction so we can check the same upload in a different
4969 # pocket.
4970@@ -241,16 +241,16 @@
4971 ... print '%s/%s by %s: %s' % (
4972 ... entry.distroseries.name, entry.sourcepackagename.name,
4973 ... entry.importer.name, entry.path)
4974- dapper/pmount by mark: po/es_ES.po
4975- dapper/pmount by mark: po/ca.po
4976- dapper/pmount by mark: po/de.po
4977- dapper/pmount by mark: po/cs.po
4978- dapper/pmount by mark: po/es.po
4979- dapper/pmount by mark: po/fr.po
4980- dapper/pmount by mark: po/hr.po
4981- dapper/pmount by mark: po/nb.po
4982- dapper/pmount by mark: po/pmount.pot
4983- dapper/pmount by mark: po/it_IT.po
4984+ dapper/pmount by ubuntu-team: po/es_ES.po
4985+ dapper/pmount by ubuntu-team: po/ca.po
4986+ dapper/pmount by ubuntu-team: po/de.po
4987+ dapper/pmount by ubuntu-team: po/cs.po
4988+ dapper/pmount by ubuntu-team: po/es.po
4989+ dapper/pmount by ubuntu-team: po/fr.po
4990+ dapper/pmount by ubuntu-team: po/hr.po
4991+ dapper/pmount by ubuntu-team: po/nb.po
4992+ dapper/pmount by ubuntu-team: po/pmount.pot
4993+ dapper/pmount by ubuntu-team: po/it_IT.po
4994
4995 # Let's abort the transaction so we can check the same upload in a different
4996 # component.
4997
4998=== modified file 'lib/lp/soyuz/doc/publishing.txt'
4999--- lib/lp/soyuz/doc/publishing.txt 2011-03-29 00:11:57 +0000
5000+++ lib/lp/soyuz/doc/publishing.txt 2011-03-29 10:32:58 +0000
The diff has been truncated for viewing.