Merge lp:~bac/launchpad/bug-574142 into lp:~bac/launchpad/db-devel

Proposed by Brad Crittenden
Status: Merged
Merge reported by: Brad Crittenden
Merged at revision: not available
Proposed branch: lp:~bac/launchpad/bug-574142
Merge into: lp:~bac/launchpad/db-devel
Diff against target: 327555 lines (+141781/-82341)
2700 files modified
.bzrignore (+17/-2)
.ctags (+1/-0)
.testr.conf (+3/-0)
Makefile (+154/-60)
bootstrap.py (+149/-113)
buildmailman.py (+29/-2)
buildout-templates/_pythonpath.py.in (+31/-12)
buildout-templates/bin/combine-css.in (+51/-0)
buildout-templates/bin/jstest.in (+5/-4)
buildout-templates/bin/kill-test-services.in (+42/-0)
buildout-templates/bin/lint.sh.in (+16/-8)
buildout-templates/bin/py.in (+0/-2)
buildout-templates/bin/retest.in (+2/-1)
buildout-templates/bin/sprite-util.in (+47/-0)
buildout-templates/bin/test.in (+43/-35)
buildout-templates/bin/update-download-cache.in (+3/-1)
buildout.cfg (+18/-21)
bzrplugins/lpserve.py (+13/-9)
configs/development/build-from-branch.zcml (+119/-0)
configs/development/launchpad-lazr.conf (+53/-11)
configs/development/local-launchpad-apache (+13/-0)
configs/replicated-development/launchpad-lazr.conf (+4/-5)
configs/test-playground/launchpad-lazr.conf (+4/-4)
configs/testrunner-appserver/launchpad-lazr.conf (+4/-1)
configs/testrunner-appserver/yui-unittest.zcml (+16/-0)
configs/testrunner/launchpad-lazr.conf (+44/-14)
cronscripts/allocate-revision-karma.py (+1/-1)
cronscripts/branch-scanner.py (+0/-36)
cronscripts/buildd-queue-builder.py (+1/-1)
cronscripts/buildd-retry-depwait.py (+1/-1)
cronscripts/buildd-slave-scanner.py (+1/-1)
cronscripts/calculate-bug-heat.py (+33/-0)
cronscripts/check-teamparticipation.py (+3/-3)
cronscripts/checkwatches.py (+1/-1)
cronscripts/code-import-dispatcher.py (+9/-2)
cronscripts/create-debwatches.py (+2/-2)
cronscripts/create_merge_proposals.py (+1/-1)
cronscripts/distributionmirror-prober.py (+1/-1)
cronscripts/expire-archive-files.py (+4/-4)
cronscripts/expire-bugtasks.py (+1/-1)
cronscripts/expire-questions.py (+1/-1)
cronscripts/flag-expired-memberships.py (+1/-1)
cronscripts/foaf-update-karma-cache.py (+21/-16)
cronscripts/garbo-daily.py (+1/-1)
cronscripts/garbo-hourly.py (+1/-1)
cronscripts/generate-ppa-htaccess.py (+1/-1)
cronscripts/language-pack-exporter.py (+1/-1)
cronscripts/librarian-gc.py (+9/-8)
cronscripts/merge-proposal-jobs.py (+23/-31)
cronscripts/mirror-prober.sh (+2/-2)
cronscripts/nightly.sh (+14/-14)
cronscripts/oops-prune.py (+1/-1)
cronscripts/parse-librarian-apache-access-logs.py (+1/-1)
cronscripts/parse-ppa-apache-access-logs.py (+61/-0)
cronscripts/ppa-generate-keys.py (+1/-1)
cronscripts/process-apport-blobs.py (+33/-0)
cronscripts/process-hwdb-submissions.py (+2/-2)
cronscripts/process-mail.py (+1/-1)
cronscripts/process-pending-packagediffs.py (+1/-1)
cronscripts/product-release-finder.py (+1/-1)
cronscripts/publishing/cron.germinate (+14/-4)
cronscripts/publishing/cron.publish-copy-archives (+83/-0)
cronscripts/publishing/cron.publish-ftpmaster (+44/-18)
cronscripts/publishing/maintenance-check.py (+382/-0)
cronscripts/reclaimbranchspace.py (+1/-1)
cronscripts/rosetta-approve-imports.py (+1/-1)
cronscripts/rosetta-branches.py (+5/-5)
cronscripts/rosetta-export-queue.py (+1/-1)
cronscripts/rosetta-pofile-stats-daily.py (+1/-1)
cronscripts/rosetta-pofile-stats.py (+1/-1)
cronscripts/rosetta-poimport.py (+1/-1)
cronscripts/scan_branches.py (+25/-0)
cronscripts/send-bug-notifications.py (+1/-1)
cronscripts/send-person-notifications.py (+6/-40)
cronscripts/sendbranchmail.py (+5/-5)
cronscripts/supermirror-pull.py (+6/-4)
cronscripts/translations-export-to-branch.py (+1/-1)
cronscripts/update-bugtask-targetnamecaches.py (+1/-1)
cronscripts/update-cve.py (+1/-1)
cronscripts/update-debwatches.py (+2/-2)
cronscripts/update-pkgcache.py (+3/-3)
cronscripts/update-remote-product.py (+4/-4)
cronscripts/update-sourceforge-remote-products.py (+4/-4)
cronscripts/update-standing.py (+1/-1)
cronscripts/update-stats.py (+2/-2)
cronscripts/update_preview_diffs.py (+0/-34)
cronscripts/upgrade_branches.py (+25/-0)
daemons/buildd-sequencer.tac (+0/-31)
daemons/buildd-slave.tac (+12/-4)
daemons/cache-database-replication-lag.py (+53/-0)
daemons/librarian.tac (+11/-0)
daemons/poppy-upload.py (+2/-49)
daemons/sftp.tac (+21/-6)
database/replication/Makefile (+43/-17)
database/replication/helpers.py (+59/-35)
database/replication/initialize.py (+10/-56)
database/replication/new-slave.py (+78/-12)
database/replication/populate_auth_replication_set.py (+0/-177)
database/replication/preamble.py (+1/-1)
database/replication/repair-restored-db.py (+44/-25)
database/replication/report.py (+1/-1)
database/replication/slon_ctl.py (+1/-1)
database/replication/sync.py (+26/-0)
database/sampledata/current-dev.sql (+5161/-4546)
database/sampledata/current.sql (+5057/-4497)
database/schema/Makefile (+6/-4)
database/schema/README (+1/-131)
database/schema/comments.sql (+168/-64)
database/schema/diagram.py (+3/-4)
database/schema/emptytables.py (+1/-1)
database/schema/fti.py (+9/-13)
database/schema/online_fti_updater.py (+1/-1)
database/schema/patch-2207-06-0.sql (+122/-0)
database/schema/patch-2207-08-0.sql (+20/-0)
database/schema/patch-2207-09-0.sql (+10/-0)
database/schema/patch-2207-10-0.sql (+8/-0)
database/schema/patch-2207-11-0.sql (+87/-0)
database/schema/patch-2207-12-0.sql (+7/-0)
database/schema/patch-2207-14-0.sql (+32/-0)
database/schema/patch-2207-15-0.sql (+15/-0)
database/schema/patch-2207-15-1.sql (+28/-0)
database/schema/patch-2207-16-0.sql (+50/-0)
database/schema/patch-2207-17-0.sql (+13/-0)
database/schema/patch-2207-18-0.sql (+7/-0)
database/schema/patch-2207-19-0.sql (+103/-0)
database/schema/patch-2207-19-1.sql (+35/-0)
database/schema/patch-2207-20-0.sql (+13/-0)
database/schema/patch-2207-21-0.sql (+9/-0)
database/schema/patch-2207-23-0.sql (+19/-0)
database/schema/patch-2207-24-0.sql (+30/-0)
database/schema/patch-2207-25-0.sql (+149/-0)
database/schema/patch-2207-26-0.sql (+28/-0)
database/schema/patch-2207-27-0.sql (+13/-0)
database/schema/patch-2207-28-0.sql (+11/-0)
database/schema/patch-2207-28-1.sql (+9/-0)
database/schema/patch-2207-29-0.sql (+34/-0)
database/schema/patch-2207-30-0.sql (+14/-0)
database/schema/patch-2207-31-0.sql (+27/-0)
database/schema/patch-2207-32-0.sql (+24/-0)
database/schema/patch-2207-33-0.sql (+9/-0)
database/schema/patch-2207-34-0.sql (+11/-0)
database/schema/patch-2207-35-0.sql (+8/-0)
database/schema/patch-2207-35-1.sql (+7/-0)
database/schema/patch-2207-35-2.sql (+12/-0)
database/schema/patch-2207-36-0.sql (+15/-0)
database/schema/patch-2207-37-0.sql (+9/-0)
database/schema/patch-2207-38-0.sql (+17/-0)
database/schema/patch-2207-39-0.sql (+16/-0)
database/schema/patch-2207-40-0.sql (+19/-0)
database/schema/patch-2207-41-0.sql (+95/-0)
database/schema/patch-2207-42-0.sql (+7/-0)
database/schema/patch-2207-43-0.sql (+4/-0)
database/schema/patch-2207-44-0.sql (+37/-0)
database/schema/patch-2207-45-0.sql (+12/-0)
database/schema/patch-2207-47-0.sql (+6/-0)
database/schema/patch-2207-48-0.sql (+27/-0)
database/schema/patch-2207-52-0.sql (+11/-0)
database/schema/patch-2207-53-0.sql (+11/-0)
database/schema/patch-2207-54-0.sql (+11/-0)
database/schema/pending/add-mailing-list-experts.py (+1/-1)
database/schema/pending/create-openid-rp-configs.py (+1/-1)
database/schema/pending/delete-unused-team-addresses.sql (+30/-0)
database/schema/pending/fix-rosetta-data.py (+1/-1)
database/schema/pending/gnu-savannah-celebrity.py (+1/-1)
database/schema/pending/import_language_packs.py (+1/-1)
database/schema/pending/migrate_kde_potemplates.py (+1/-1)
database/schema/pending/new-person-columns.py (+1/-1)
database/schema/pending/patch-2207-13-0.sql (+33/-0)
database/schema/pending/patch-2207-49-0.sql (+16/-0)
database/schema/pending/prune-nonce.py (+1/-1)
database/schema/pending/update-shippingrequest-types.py (+1/-1)
database/schema/pending/update-translation-credits.py (+3/-3)
database/schema/reset_sequences.py (+1/-1)
database/schema/security.cfg (+222/-154)
database/schema/security.py (+23/-11)
database/schema/sort_sql.py (+1/-1)
database/schema/trusted.sql (+230/-8)
database/schema/unautovacuumable.py (+26/-8)
database/schema/upgrade.py (+5/-4)
doc/bazaar/Makefile (+0/-39)
doc/bazaar/README (+0/-47)
doc/bazaar/bazaar.tmml (+0/-2722)
doc/bazaar/html.xsl (+0/-230)
doc/bazaar/large-dia/sizes (+0/-5)
doc/bazaar/texmacs.css (+0/-25)
doc/bazaar/write-sizes (+0/-17)
doc/webapp-process.txt (+1/-1)
ez_setup.py (+11/-3)
lib/canonical/Makefile (+0/-5)
lib/canonical/__init__.py (+5/-0)
lib/canonical/base.py (+3/-3)
lib/canonical/buildd/README (+1/-0)
lib/canonical/buildd/binarypackage.py (+143/-0)
lib/canonical/buildd/buildd-config.py (+1/-1)
lib/canonical/buildd/buildrecipe (+133/-0)
lib/canonical/buildd/check-implicit-pointer-functions (+112/-0)
lib/canonical/buildd/debian.py (+44/-128)
lib/canonical/buildd/debian/changelog (+70/-0)
lib/canonical/buildd/debian/control (+1/-1)
lib/canonical/buildd/debian/launchpad-buildd.init (+11/-1)
lib/canonical/buildd/debian/postinst (+1/-3)
lib/canonical/buildd/debian/rules (+22/-10)
lib/canonical/buildd/debian/upgrade-config (+51/-1)
lib/canonical/buildd/example.chroot (+2/-2)
lib/canonical/buildd/generate-translation-templates (+57/-0)
lib/canonical/buildd/mount-chroot (+1/-2)
lib/canonical/buildd/pottery/generate_translation_templates.py (+87/-0)
lib/canonical/buildd/pottery/intltool.py (+254/-0)
lib/canonical/buildd/sbuild (+39/-5)
lib/canonical/buildd/sbuild-notes.txt (+2/-2)
lib/canonical/buildd/sbuild-package (+25/-6)
lib/canonical/buildd/sequencer.py (+0/-157)
lib/canonical/buildd/slave.py (+22/-7)
lib/canonical/buildd/sourcepackagerecipe.py (+155/-0)
lib/canonical/buildd/template-buildd-slave.conf (+11/-2)
lib/canonical/buildd/test_buildd_generatetranslationtemplates (+33/-0)
lib/canonical/buildd/test_buildd_recipe (+30/-0)
lib/canonical/buildd/tests/harness.py (+19/-12)
lib/canonical/buildd/tests/test_generate_translation_templates.py (+117/-0)
lib/canonical/buildd/tests/test_translationtemplatesbuildmanager.py (+176/-0)
lib/canonical/buildd/translationtemplates.py (+97/-0)
lib/canonical/buildd/update-debian-chroot (+1/-1)
lib/canonical/buildd/utils.py (+0/-53)
lib/canonical/cachedproperty.py (+1/-0)
lib/canonical/config/__init__.py (+35/-53)
lib/canonical/config/schema-lazr.conf (+164/-43)
lib/canonical/config/tests/test_config_lookup.py (+7/-7)
lib/canonical/config/tests/test_database_config.py (+61/-0)
lib/canonical/configure.zcml (+12/-22)
lib/canonical/database/ftests/script_isolation.py (+8/-0)
lib/canonical/database/ftests/test_zopelesstransactionmanager.txt (+26/-0)
lib/canonical/database/harness.py (+2/-5)
lib/canonical/database/revision.py (+5/-6)
lib/canonical/database/sqlbase.py (+76/-51)
lib/canonical/database/tests/test_zopeless_transaction_manager.py (+31/-0)
lib/canonical/doap/__init__.py (+0/-8)
lib/canonical/doap/forage.py (+0/-283)
lib/canonical/ftests/pgsql.py (+11/-0)
lib/canonical/launchpad/apidoc/wadl-testrunner.xml (+0/-10)
lib/canonical/launchpad/blocked.html (+26/-0)
lib/canonical/launchpad/browser/__init__.py (+2/-7)
lib/canonical/launchpad/browser/feeds.py (+3/-14)
lib/canonical/launchpad/browser/ftests/logintoken-corner-cases.txt (+10/-11)
lib/canonical/launchpad/browser/launchpad.py (+64/-52)
lib/canonical/launchpad/browser/librarian.py (+26/-15)
lib/canonical/launchpad/browser/logintoken.py (+69/-387)
lib/canonical/launchpad/browser/oauth.py (+25/-13)
lib/canonical/launchpad/browser/packaging.py (+0/-48)
lib/canonical/launchpad/browser/temporaryblobstorage.py (+48/-4)
lib/canonical/launchpad/browser/tests/registration.py (+2/-0)
lib/canonical/launchpad/browser/tests/test_branchtraversal.py (+2/-2)
lib/canonical/launchpad/browser/tests/test_launchpad.py (+97/-15)
lib/canonical/launchpad/browser/tests/test_librarian.py (+31/-0)
lib/canonical/launchpad/browser/tests/test_logintoken.py (+67/-0)
lib/canonical/launchpad/browser/tests/test_registration.py (+0/-61)
lib/canonical/launchpad/browser/vocabulary.py (+6/-2)
lib/canonical/launchpad/components/apihelpers.py (+15/-0)
lib/canonical/launchpad/components/cal.py (+0/-89)
lib/canonical/launchpad/components/crowd.py (+0/-80)
lib/canonical/launchpad/configure.zcml (+7/-13)
lib/canonical/launchpad/daemons/tachandler.py (+133/-70)
lib/canonical/launchpad/database/__init__.py (+3/-6)
lib/canonical/launchpad/database/account.py (+11/-8)
lib/canonical/launchpad/database/baseopenidstore.py (+1/-1)
lib/canonical/launchpad/database/emailaddress.py (+3/-2)
lib/canonical/launchpad/database/librarian.py (+4/-3)
lib/canonical/launchpad/database/logintoken.py (+70/-17)
lib/canonical/launchpad/database/oauth.py (+6/-4)
lib/canonical/launchpad/database/temporaryblobstorage.py (+28/-6)
lib/canonical/launchpad/database/tests/test_baseopenidstore.py (+5/-0)
lib/canonical/launchpad/database/tests/test_oauth.py (+1/-1)
lib/canonical/launchpad/doc/account.txt (+74/-83)
lib/canonical/launchpad/doc/badges.txt (+1/-0)
lib/canonical/launchpad/doc/canonical-config.txt (+1/-1)
lib/canonical/launchpad/doc/canonical_url.txt (+9/-0)
lib/canonical/launchpad/doc/canonical_url_examples.txt (+34/-18)
lib/canonical/launchpad/doc/celebrities.txt (+49/-1)
lib/canonical/launchpad/doc/crowd.txt (+0/-124)
lib/canonical/launchpad/doc/db-policy.txt (+126/-0)
lib/canonical/launchpad/doc/displaying-numbers.txt (+1/-1)
lib/canonical/launchpad/doc/emailauthentication.txt (+6/-5)
lib/canonical/launchpad/doc/google-searchservice.txt (+2/-2)
lib/canonical/launchpad/doc/gpg-encryption.txt (+3/-3)
lib/canonical/launchpad/doc/gpghandler.txt (+7/-7)
lib/canonical/launchpad/doc/hasowner-authorization.txt (+5/-5)
lib/canonical/launchpad/doc/hierarchical-menu.txt (+17/-5)
lib/canonical/launchpad/doc/incomingmail.txt (+8/-25)
lib/canonical/launchpad/doc/launchpad-radio-widget.txt (+48/-0)
lib/canonical/launchpad/doc/launchpadlib.txt (+1/-1)
lib/canonical/launchpad/doc/launchpadview.txt (+5/-14)
lib/canonical/launchpad/doc/librarian.txt (+6/-9)
lib/canonical/launchpad/doc/login-pages.txt (+0/-139)
lib/canonical/launchpad/doc/loginstatus-pages.txt (+13/-0)
lib/canonical/launchpad/doc/logintoken-pages.txt (+18/-368)
lib/canonical/launchpad/doc/looptuner.txt (+4/-11)
lib/canonical/launchpad/doc/menus.txt (+3/-3)
lib/canonical/launchpad/doc/notification-recipient-set.txt (+1/-1)
lib/canonical/launchpad/doc/oauth.txt (+112/-35)
lib/canonical/launchpad/doc/personroles.txt (+130/-0)
lib/canonical/launchpad/doc/product-update-remote-product-script.txt (+1/-1)
lib/canonical/launchpad/doc/product-update-remote-product.txt (+1/-6)
lib/canonical/launchpad/doc/profiling.txt (+6/-6)
lib/canonical/launchpad/doc/project-scope-widget.txt (+6/-5)
lib/canonical/launchpad/doc/publishing-security.txt (+48/-47)
lib/canonical/launchpad/doc/renamed-view.txt (+1/-1)
lib/canonical/launchpad/doc/security-proxies.txt (+3/-3)
lib/canonical/launchpad/doc/security-teams.txt (+2/-1)
lib/canonical/launchpad/doc/storm.txt (+56/-71)
lib/canonical/launchpad/doc/stripped-text-widget.txt (+29/-4)
lib/canonical/launchpad/doc/tales-macro.txt (+5/-34)
lib/canonical/launchpad/doc/tales.txt (+87/-35)
lib/canonical/launchpad/doc/temporaryblobstorage.txt (+45/-0)
lib/canonical/launchpad/doc/textformatting.txt (+76/-0)
lib/canonical/launchpad/doc/timeout.txt (+1/-1)
lib/canonical/launchpad/doc/unicode_csv.txt (+7/-3)
lib/canonical/launchpad/doc/vocabularies.txt (+25/-21)
lib/canonical/launchpad/doc/vocabulary-json.txt (+21/-1)
lib/canonical/launchpad/doc/webapp-authorization.txt (+6/-6)
lib/canonical/launchpad/doc/webapp-publication.txt (+11/-5)
lib/canonical/launchpad/doc/webservice-error.txt (+6/-1)
lib/canonical/launchpad/doc/webservice-marshallers.txt (+22/-2)
lib/canonical/launchpad/doc/zcmldirectives.txt (+19/-10)
lib/canonical/launchpad/emailtemplates/branch-merge-proposal-created.txt (+1/-1)
lib/canonical/launchpad/emailtemplates/bug-notification-verbose.txt (+2/-0)
lib/canonical/launchpad/emailtemplates/forgottenpassword-neutral.txt (+0/-14)
lib/canonical/launchpad/emailtemplates/forgottenpassword.txt (+0/-11)
lib/canonical/launchpad/emailtemplates/help.txt (+7/-4)
lib/canonical/launchpad/emailtemplates/new-code-import.txt (+3/-1)
lib/canonical/launchpad/emailtemplates/newuser-email-neutral.txt (+0/-15)
lib/canonical/launchpad/emailtemplates/newuser-email.txt (+0/-19)
lib/canonical/launchpad/emailtemplates/person-location-modified.txt (+0/-19)
lib/canonical/launchpad/emailtemplates/person-merged.txt (+15/-0)
lib/canonical/launchpad/emailtemplates/ppa-subscription-new.txt (+3/-1)
lib/canonical/launchpad/emailtemplates/specification-modified.txt (+2/-2)
lib/canonical/launchpad/emailtemplates/team-list-subscribe-block.txt (+1/-1)
lib/canonical/launchpad/emailtemplates/upload-accepted.txt (+1/-0)
lib/canonical/launchpad/emailtemplates/upload-announcement.txt (+1/-0)
lib/canonical/launchpad/emailtemplates/upload-new.txt (+1/-0)
lib/canonical/launchpad/emailtemplates/upload-rejection.txt (+1/-0)
lib/canonical/launchpad/event/interfaces.py (+0/-23)
lib/canonical/launchpad/fields/__init__.py (+72/-36)
lib/canonical/launchpad/fields/tests/__init__.py (+1/-0)
lib/canonical/launchpad/fields/tests/test_fields.py (+49/-0)
lib/canonical/launchpad/ftests/keys_for_tests.py (+1/-1)
lib/canonical/launchpad/ftests/test_system_documentation.py (+12/-12)
lib/canonical/launchpad/helpers.py (+5/-67)
lib/canonical/launchpad/icing-sources/haspatch.svg (+968/-0)
lib/canonical/launchpad/icing/PlotKit_Packed.js (+0/-2177)
lib/canonical/launchpad/icing/icon-sprites.positioning (+476/-0)
lib/canonical/launchpad/icing/print.css (+5/-5)
lib/canonical/launchpad/icing/shipit.css (+2/-2)
lib/canonical/launchpad/icing/style-3-0.css.in (+2084/-563)
lib/canonical/launchpad/icing/style.css (+47/-1679)
lib/canonical/launchpad/icing/yui_2.7.0b/build/assets/skins/sam/autocomplete.css (+1/-1)
lib/canonical/launchpad/icing/yui_2.7.0b/build/assets/skins/sam/calendar.css (+1/-1)
lib/canonical/launchpad/icing/yui_2.7.0b/build/assets/skins/sam/colorpicker.css (+1/-1)
lib/canonical/launchpad/icing/yui_2.7.0b/build/assets/skins/sam/datatable.css (+1/-1)
lib/canonical/launchpad/icing/yui_2.7.0b/build/assets/skins/sam/editor.css (+1/-1)
lib/canonical/launchpad/icing/yui_2.7.0b/build/assets/skins/sam/logger.css (+1/-1)
lib/canonical/launchpad/icing/yui_2.7.0b/build/assets/skins/sam/paginator.css (+1/-1)
lib/canonical/launchpad/icing/yui_2.7.0b/build/assets/skins/sam/profilerviewer.css (+1/-1)
lib/canonical/launchpad/icing/yui_2.7.0b/build/assets/skins/sam/simpleeditor.css (+1/-1)
lib/canonical/launchpad/icing/yui_2.7.0b/build/assets/skins/sam/skin.css (+9/-9)
lib/canonical/launchpad/icing/yui_2.7.0b/build/calendar/assets/skins/sam/calendar-skin.css (+1/-1)
lib/canonical/launchpad/icing/yui_2.7.0b/build/calendar/assets/skins/sam/calendar.css (+1/-1)
lib/canonical/launchpad/images/src/ppa-icon.svg (+188/-0)
lib/canonical/launchpad/interfaces/__init__.py (+6/-7)
lib/canonical/launchpad/interfaces/_schema_circular_imports.py (+140/-34)
lib/canonical/launchpad/interfaces/account.py (+8/-8)
lib/canonical/launchpad/interfaces/authtoken.py (+3/-60)
lib/canonical/launchpad/interfaces/ftests/validation.txt (+12/-12)
lib/canonical/launchpad/interfaces/gpghandler.py (+38/-0)
lib/canonical/launchpad/interfaces/launchpad.py (+112/-24)
lib/canonical/launchpad/interfaces/librarian.py (+3/-7)
lib/canonical/launchpad/interfaces/logintoken.py (+21/-0)
lib/canonical/launchpad/interfaces/message.py (+11/-7)
lib/canonical/launchpad/interfaces/oauth.py (+9/-2)
lib/canonical/launchpad/interfaces/temporaryblobstorage.py (+28/-1)
lib/canonical/launchpad/interfaces/validation.py (+10/-10)
lib/canonical/launchpad/javascript/bugs/bug_tags_entry.js (+29/-30)
lib/canonical/launchpad/javascript/bugs/bugtask-index.js (+467/-339)
lib/canonical/launchpad/javascript/bugs/filebug-dupefinder.js (+337/-158)
lib/canonical/launchpad/javascript/bugs/offical_bug_tags.js (+53/-35)
lib/canonical/launchpad/javascript/bugs/subscriber.js (+13/-14)
lib/canonical/launchpad/javascript/bugs/tests/subscriber.html (+8/-8)
lib/canonical/launchpad/javascript/bugs/tests/test_me_too.html (+7/-7)
lib/canonical/launchpad/javascript/bugs/tests/test_me_too.js (+43/-42)
lib/canonical/launchpad/javascript/bugs/tests/test_subscriber.js (+61/-8)
lib/canonical/launchpad/javascript/client/client.js (+54/-25)
lib/canonical/launchpad/javascript/code/branchsubscription.js (+0/-272)
lib/canonical/launchpad/javascript/lp/calendar.js (+4/-4)
lib/canonical/launchpad/javascript/lp/comment.js (+425/-0)
lib/canonical/launchpad/javascript/lp/dragscroll.js (+132/-81)
lib/canonical/launchpad/javascript/lp/errors.js (+111/-0)
lib/canonical/launchpad/javascript/lp/lp-mochi.js (+383/-0)
lib/canonical/launchpad/javascript/lp/lp.js (+124/-516)
lib/canonical/launchpad/javascript/lp/mapping.js (+41/-41)
lib/canonical/launchpad/javascript/lp/picker.js (+38/-30)
lib/canonical/launchpad/javascript/lp/tests/test_lp_collapsibles.js (+37/-37)
lib/canonical/launchpad/javascript/registry/milestoneoverlay.js (+9/-10)
lib/canonical/launchpad/javascript/registry/milestonetable.js (+38/-31)
lib/canonical/launchpad/javascript/registry/team.js (+137/-0)
lib/canonical/launchpad/javascript/registry/tests/test_milestone_table.html (+5/-5)
lib/canonical/launchpad/javascript/registry/tests/test_milestone_table.js (+13/-7)
lib/canonical/launchpad/javascript/registry/tests/test_timeline.html (+2/-1)
lib/canonical/launchpad/javascript/registry/tests/timeline-iframe.html (+5/-5)
lib/canonical/launchpad/javascript/registry/tests/timeline.js (+53/-22)
lib/canonical/launchpad/javascript/registry/timeline.js (+211/-104)
lib/canonical/launchpad/javascript/soyuz/archivesubscribers_index.js (+6/-6)
lib/canonical/launchpad/javascript/soyuz/base.js (+1/-1)
lib/canonical/launchpad/javascript/soyuz/lp_dynamic_dom_updater.js (+14/-24)
lib/canonical/launchpad/javascript/soyuz/tests/archivesubscribers_index.js (+9/-9)
lib/canonical/launchpad/javascript/soyuz/tests/lp_dynamic_dom_updater.js (+1/-1)
lib/canonical/launchpad/javascript/soyuz/update_archive_build_statuses.js (+19/-21)
lib/canonical/launchpad/javascript/test.css (+5/-11)
lib/canonical/launchpad/javascript/translations/pofile.js (+457/-28)
lib/canonical/launchpad/javascript/translations/translations.js (+105/-11)
lib/canonical/launchpad/layers.py (+12/-2)
lib/canonical/launchpad/mail/commands.py (+4/-4)
lib/canonical/launchpad/mail/errortemplates/branch-creation-exception.txt (+2/-0)
lib/canonical/launchpad/mail/incoming.py (+10/-16)
lib/canonical/launchpad/mail/meta.py (+16/-18)
lib/canonical/launchpad/mail/tests/test_incoming.py (+2/-0)
lib/canonical/launchpad/mailman/monkeypatches/lphandler.py (+3/-2)
lib/canonical/launchpad/mailman/monkeypatches/lpmoderate.py (+16/-0)
lib/canonical/launchpad/mailman/runmailman.py (+0/-4)
lib/canonical/launchpad/mailnotification.py (+55/-35)
lib/canonical/launchpad/mailout/__init__.py (+0/-70)
lib/canonical/launchpad/offline-maintenance-haproxy.html (+32/-0)
lib/canonical/launchpad/offline-maintenance.html (+4/-3)
lib/canonical/launchpad/offline-unplanned-haproxy.html (+32/-0)
lib/canonical/launchpad/offline-unplanned.html (+1/-1)
lib/canonical/launchpad/pagetests/basics/demo-and-lpnet.txt (+7/-15)
lib/canonical/launchpad/pagetests/basics/max-batch-size.txt (+1/-1)
lib/canonical/launchpad/pagetests/basics/notfound-traversals.txt (+2/-5)
lib/canonical/launchpad/pagetests/feeds/xx-authentication.txt (+1/-1)
lib/canonical/launchpad/pagetests/feeds/xx-links.txt (+19/-19)
lib/canonical/launchpad/pagetests/oauth/access-token.txt (+1/-1)
lib/canonical/launchpad/pagetests/oauth/authorize-token.txt (+11/-19)
lib/canonical/launchpad/pagetests/packaging/xx-ubuntu-pkging.txt (+0/-136)
lib/canonical/launchpad/pagetests/standalone/xx-dbpolicy.txt (+1/-1)
lib/canonical/launchpad/pagetests/standalone/xx-form-layout.txt (+8/-5)
lib/canonical/launchpad/pagetests/standalone/xx-invalid-people-cant-login.txt (+0/-56)
lib/canonical/launchpad/pagetests/standalone/xx-login-and-join-links.txt (+0/-65)
lib/canonical/launchpad/pagetests/standalone/xx-login-without-preferredemail.txt (+0/-76)
lib/canonical/launchpad/pagetests/standalone/xx-nameblacklist.txt (+3/-2)
lib/canonical/launchpad/pagetests/standalone/xx-new-account-redirection-url.txt (+0/-62)
lib/canonical/launchpad/pagetests/standalone/xx-notifications.txt (+3/-0)
lib/canonical/launchpad/pagetests/standalone/xx-offsite-form-post.txt (+159/-16)
lib/canonical/launchpad/pagetests/standalone/xx-opstats.txt (+54/-0)
lib/canonical/launchpad/pagetests/standalone/xx-read-only-mode.txt (+10/-18)
lib/canonical/launchpad/pagetests/webservice/apidoc.txt (+18/-3)
lib/canonical/launchpad/pagetests/webservice/conditional-write.txt (+103/-0)
lib/canonical/launchpad/pagetests/webservice/launchpadlib.txt (+115/-0)
lib/canonical/launchpad/pagetests/webservice/multiversion.txt (+32/-0)
lib/canonical/launchpad/pagetests/webservice/xx-branches.txt (+33/-0)
lib/canonical/launchpad/pagetests/webservice/xx-service.txt (+137/-14)
lib/canonical/launchpad/pagetests/webservice/xx-temporary-blob-storage.txt (+81/-0)
lib/canonical/launchpad/pagetests/webservice/xx-wadl.txt (+81/-46)
lib/canonical/launchpad/pagetitles.py (+0/-25)
lib/canonical/launchpad/permissions.zcml (+0/-4)
lib/canonical/launchpad/readonly.py (+86/-0)
lib/canonical/launchpad/rest/configuration.py (+26/-5)
lib/canonical/launchpad/scripts/__init__.py (+27/-48)
lib/canonical/launchpad/scripts/ftests/test_checkwatches.py (+0/-93)
lib/canonical/launchpad/scripts/ftests/test_oops_prune.py (+9/-0)
lib/canonical/launchpad/scripts/garbo.py (+203/-188)
lib/canonical/launchpad/scripts/logger.py (+6/-4)
lib/canonical/launchpad/scripts/oops.py (+16/-12)
lib/canonical/launchpad/scripts/runlaunchpad.py (+26/-18)
lib/canonical/launchpad/scripts/sftracker.py (+2/-2)
lib/canonical/launchpad/scripts/tests/librarianformatter_noca.txt (+6/-9)
lib/canonical/launchpad/scripts/tests/test_garbo.py (+89/-73)
lib/canonical/launchpad/scripts/tests/test_hwdb_submission_parser.py (+564/-161)
lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py (+2083/-251)
lib/canonical/launchpad/scripts/tests/test_librarian_apache_log_parser.py (+6/-0)
lib/canonical/launchpad/scripts/tests/test_logger.txt (+6/-7)
lib/canonical/launchpad/scripts/tests/test_rundoctests.py (+0/-1)
lib/canonical/launchpad/scripts/tests/test_runlaunchpad.py (+2/-4)
lib/canonical/launchpad/security.py (+596/-423)
lib/canonical/launchpad/subscribers/karma.py (+8/-2)
lib/canonical/launchpad/systemhomes.py (+55/-49)
lib/canonical/launchpad/templates/batchnavigator-navigation-links.pt (+7/-2)
lib/canonical/launchpad/templates/bounty-portlet-relateds.pt (+0/-55)
lib/canonical/launchpad/templates/bugbranch-inline-edit.pt (+0/-2)
lib/canonical/launchpad/templates/bugs-listing-table-without-navlinks.pt (+11/-2)
lib/canonical/launchpad/templates/launchpad-forgottenpassword.pt (+0/-65)
lib/canonical/launchpad/templates/launchpad-form.pt (+18/-1)
lib/canonical/launchpad/templates/launchpad-gone.pt (+49/-0)
lib/canonical/launchpad/templates/launchpad-login.pt (+0/-236)
lib/canonical/launchpad/templates/launchpad-menubox.pt (+0/-21)
lib/canonical/launchpad/templates/launchpad-navigation-menutabs.pt (+0/-32)
lib/canonical/launchpad/templates/launchpad-noreferrer.pt (+26/-0)
lib/canonical/launchpad/templates/launchpad-readonlyfailure.pt (+3/-3)
lib/canonical/launchpad/templates/launchpad-requestexpired.pt (+9/-20)
lib/canonical/launchpad/templates/launchpad-restrictedinfo.pt (+0/-45)
lib/canonical/launchpad/templates/launchpad-restrictedlogin.pt (+0/-119)
lib/canonical/launchpad/templates/login-already.pt (+18/-0)
lib/canonical/launchpad/templates/login-error.pt (+17/-0)
lib/canonical/launchpad/templates/login-suspended-account.pt (+20/-0)
lib/canonical/launchpad/templates/logintoken-newaccount.pt (+0/-19)
lib/canonical/launchpad/templates/logintoken-resetpassword.pt (+0/-18)
lib/canonical/launchpad/templates/logintoken-validatesignonlygpg.pt (+1/-1)
lib/canonical/launchpad/templates/main-template-macros.pt (+0/-33)
lib/canonical/launchpad/templates/main-template.pt (+0/-308)
lib/canonical/launchpad/templates/oops-veryplain.pt (+10/-2)
lib/canonical/launchpad/templates/oops.pt (+43/-20)
lib/canonical/launchpad/testing/browser.py (+32/-4)
lib/canonical/launchpad/testing/codeimporthelpers.py (+2/-6)
lib/canonical/launchpad/testing/cookie.py (+0/-67)
lib/canonical/launchpad/testing/googletestservice.py (+2/-2)
lib/canonical/launchpad/testing/pages.py (+118/-27)
lib/canonical/launchpad/testing/systemdocs.py (+24/-7)
lib/canonical/launchpad/testing/tests/test_testcase.py (+0/-163)
lib/canonical/launchpad/tests/readonly.py (+47/-0)
lib/canonical/launchpad/tests/test_helpers.py (+4/-2)
lib/canonical/launchpad/tests/test_login.py (+1/-20)
lib/canonical/launchpad/tests/test_personroles.py (+157/-0)
lib/canonical/launchpad/tests/test_readonly.py (+78/-0)
lib/canonical/launchpad/tests/test_token_creation.py (+2/-2)
lib/canonical/launchpad/tour/api (+1/-1)
lib/canonical/launchpad/tour/branch-hosting-tracking (+9/-8)
lib/canonical/launchpad/tour/bugs (+10/-8)
lib/canonical/launchpad/tour/community (+1/-1)
lib/canonical/launchpad/tour/community-support (+1/-1)
lib/canonical/launchpad/tour/feature-tracking (+1/-1)
lib/canonical/launchpad/tour/index (+3/-3)
lib/canonical/launchpad/tour/join-launchpad (+3/-3)
lib/canonical/launchpad/tour/ppa (+28/-30)
lib/canonical/launchpad/tour/release-management (+1/-1)
lib/canonical/launchpad/tour/translation (+3/-3)
lib/canonical/launchpad/utilities/celebrities.py (+37/-22)
lib/canonical/launchpad/utilities/gpghandler.py (+30/-8)
lib/canonical/launchpad/utilities/looptuner.py (+64/-17)
lib/canonical/launchpad/utilities/personroles.py (+62/-0)
lib/canonical/launchpad/validators/url.py (+7/-1)
lib/canonical/launchpad/vocabularies/configure.zcml (+299/-88)
lib/canonical/launchpad/vocabularies/dbobjects.py (+18/-17)
lib/canonical/launchpad/webapp/adapter.py (+80/-29)
lib/canonical/launchpad/webapp/authentication.py (+10/-7)
lib/canonical/launchpad/webapp/authorization.py (+3/-3)
lib/canonical/launchpad/webapp/badge.py (+1/-0)
lib/canonical/launchpad/webapp/batching.py (+4/-0)
lib/canonical/launchpad/webapp/breadcrumb.py (+5/-3)
lib/canonical/launchpad/webapp/configure.zcml (+28/-19)
lib/canonical/launchpad/webapp/dbpolicy.py (+96/-35)
lib/canonical/launchpad/webapp/error.py (+15/-4)
lib/canonical/launchpad/webapp/errorlog.py (+148/-97)
lib/canonical/launchpad/webapp/ftests/test_adapter.txt (+53/-2)
lib/canonical/launchpad/webapp/ftests/test_adapter_permissions.txt (+1/-24)
lib/canonical/launchpad/webapp/interaction.py (+62/-1)
lib/canonical/launchpad/webapp/interfaces.py (+39/-11)
lib/canonical/launchpad/webapp/launchbag.py (+2/-2)
lib/canonical/launchpad/webapp/launchpadform.py (+66/-3)
lib/canonical/launchpad/webapp/login.py (+295/-315)
lib/canonical/launchpad/webapp/marshallers.py (+21/-0)
lib/canonical/launchpad/webapp/menu.py (+6/-1)
lib/canonical/launchpad/webapp/metazcml.py (+14/-9)
lib/canonical/launchpad/webapp/notifications.py (+3/-2)
lib/canonical/launchpad/webapp/pgsession.py (+2/-19)
lib/canonical/launchpad/webapp/publication.py (+113/-128)
lib/canonical/launchpad/webapp/publisher.py (+6/-24)
lib/canonical/launchpad/webapp/servers.py (+99/-16)
lib/canonical/launchpad/webapp/session.py (+5/-7)
lib/canonical/launchpad/webapp/sigdumpmem.py (+18/-0)
lib/canonical/launchpad/webapp/snapshot.py (+4/-1)
lib/canonical/launchpad/webapp/tales.py (+132/-199)
lib/canonical/launchpad/webapp/tests/__init__.py (+0/-26)
lib/canonical/launchpad/webapp/tests/cookie-authentication.txt (+29/-18)
lib/canonical/launchpad/webapp/tests/login.txt (+47/-0)
lib/canonical/launchpad/webapp/tests/no-anonymous-session-cookies.txt (+30/-25)
lib/canonical/launchpad/webapp/tests/test_authorization.py (+6/-7)
lib/canonical/launchpad/webapp/tests/test_breadcrumbs.py (+24/-36)
lib/canonical/launchpad/webapp/tests/test_cookie_authentication.py (+24/-0)
lib/canonical/launchpad/webapp/tests/test_dbpolicy.py (+57/-15)
lib/canonical/launchpad/webapp/tests/test_encryptor.py (+10/-5)
lib/canonical/launchpad/webapp/tests/test_errorlog.py (+51/-3)
lib/canonical/launchpad/webapp/tests/test_login.py (+0/-34)
lib/canonical/launchpad/webapp/tests/test_menu.py (+1/-0)
lib/canonical/launchpad/webapp/tests/test_no_anonymous_session_cookies.py (+24/-0)
lib/canonical/launchpad/webapp/tests/test_notifications.py (+1/-1)
lib/canonical/launchpad/webapp/tests/test_pgsession.py (+0/-61)
lib/canonical/launchpad/webapp/tests/test_publication.py (+184/-16)
lib/canonical/launchpad/webapp/tests/test_servers.py (+57/-30)
lib/canonical/launchpad/webapp/tests/test_sigdumpmem.py (+45/-0)
lib/canonical/launchpad/webapp/tests/test_tales.py (+4/-137)
lib/canonical/launchpad/webapp/url.py (+15/-15)
lib/canonical/launchpad/webapp/vhosts.py (+5/-0)
lib/canonical/launchpad/webapp/vocabulary.py (+6/-0)
lib/canonical/launchpad/windmill/jstests/launchpad_ajax.js (+17/-17)
lib/canonical/launchpad/windmill/testing/constants.py (+2/-2)
lib/canonical/launchpad/windmill/testing/lpuser.py (+38/-23)
lib/canonical/launchpad/windmill/testing/widgets.py (+6/-5)
lib/canonical/launchpad/xmlrpc/application.py (+4/-10)
lib/canonical/launchpad/xmlrpc/configure.zcml (+9/-22)
lib/canonical/launchpad/xmlrpc/faults.py (+18/-35)
lib/canonical/launchpad/xmlrpc/tests/test_authserver.py (+2/-8)
lib/canonical/launchpad/xmlrpc/tests/test_faults.py (+0/-65)
lib/canonical/launchpad/zcml/account.zcml (+4/-1)
lib/canonical/launchpad/zcml/binaryandsourcepackagename.zcml (+13/-2)
lib/canonical/launchpad/zcml/configure.zcml (+0/-6)
lib/canonical/launchpad/zcml/crowd.zcml (+0/-17)
lib/canonical/launchpad/zcml/hwdb.zcml (+0/-276)
lib/canonical/launchpad/zcml/launchpad.zcml (+48/-91)
lib/canonical/launchpad/zcml/librarian.zcml (+2/-1)
lib/canonical/launchpad/zcml/logintoken.zcml (+0/-23)
lib/canonical/launchpad/zcml/packaging.zcml (+0/-32)
lib/canonical/launchpad/zcml/personnotification.zcml (+0/-19)
lib/canonical/launchpad/zcml/personproduct.zcml (+0/-44)
lib/canonical/launchpad/zcml/structuralsubscription.zcml (+0/-40)
lib/canonical/launchpad/zcml/temporaryblobstorage.zcml (+16/-0)
lib/canonical/launchpad/zcml/webservice.zcml (+13/-1)
lib/canonical/lazr/doc/folder.txt (+13/-13)
lib/canonical/lazr/doc/menus.txt (+2/-2)
lib/canonical/lazr/doc/timeout.txt (+1/-1)
lib/canonical/librarian/Makefile (+0/-18)
lib/canonical/librarian/client.py (+19/-11)
lib/canonical/librarian/db.py (+6/-5)
lib/canonical/librarian/ftests/harness.py (+5/-0)
lib/canonical/librarian/ftests/test_client.py (+2/-2)
lib/canonical/librarian/ftests/test_db.py (+87/-0)
lib/canonical/librarian/ftests/test_gc.py (+139/-121)
lib/canonical/librarian/ftests/test_storage.py (+5/-4)
lib/canonical/librarian/ftests/test_web.py (+14/-12)
lib/canonical/librarian/interfaces.py (+6/-0)
lib/canonical/librarian/librariangc.py (+237/-139)
lib/canonical/librarian/storage.py (+3/-4)
lib/canonical/librarian/tests/librarian-report.txt (+31/-0)
lib/canonical/librarian/tests/test_doc.py (+25/-0)
lib/canonical/librarian/tests/test_sigdumpmem.py (+37/-0)
lib/canonical/librarian/tests/test_storage.py (+0/-1)
lib/canonical/librarian/utils.py (+3/-3)
lib/canonical/librarian/web.py (+1/-5)
lib/canonical/lp/ftests/test_zopeless.py (+12/-6)
lib/canonical/testing/customresult.py (+2/-46)
lib/canonical/testing/ftests/test_layers.py (+25/-2)
lib/canonical/testing/ftests/test_mockdb.py (+4/-4)
lib/canonical/testing/layers.py (+206/-18)
lib/canonical/uuid.py (+3/-3)
lib/canonical/widgets/itemswidgets.py (+40/-0)
lib/canonical/widgets/lazrjs.py (+21/-29)
lib/canonical/widgets/location.py (+1/-1)
lib/canonical/widgets/popup.py (+1/-1)
lib/canonical/widgets/project.py (+1/-1)
lib/canonical/widgets/templates/vocabulary-picker.js.template (+4/-5)
lib/contrib/PlotKit/Base.js (+0/-406)
lib/contrib/PlotKit/Canvas.js (+0/-683)
lib/contrib/PlotKit/EasyPlot.js (+0/-161)
lib/contrib/PlotKit/Layout.js (+0/-756)
lib/contrib/PlotKit/PlotKit.js (+0/-151)
lib/contrib/PlotKit/SVG.js (+0/-705)
lib/contrib/PlotKit/SweetCanvas.js (+0/-348)
lib/contrib/PlotKit/SweetSVG.js (+0/-247)
lib/contrib/PlotKit/dummy.svg (+0/-9)
lib/contrib/PlotKit/excanvas.js (+0/-723)
lib/contrib/glock.py (+1/-1)
lib/contrib/slimmer/README.txt (+0/-27)
lib/contrib/slimmer/__init__.py (+0/-1)
lib/contrib/slimmer/js_function_slimmer.py (+0/-169)
lib/contrib/slimmer/result (+0/-2)
lib/contrib/slimmer/setup.py (+0/-45)
lib/contrib/slimmer/slimmer.py (+0/-684)
lib/contrib/slimmer/slimmer_exp.py (+0/-629)
lib/contrib/slimmer/tests/__init__.py (+0/-2)
lib/contrib/slimmer/tests/codechunks.py (+0/-509)
lib/contrib/slimmer/tests/dummy.py (+0/-14)
lib/contrib/slimmer/tests/moo.ajax.js (+0/-40)
lib/contrib/slimmer/tests/testSlimmer.py (+0/-229)
lib/devscripts/autoland.py (+68/-25)
lib/devscripts/ec2test/account.py (+64/-51)
lib/devscripts/ec2test/builtins.py (+64/-36)
lib/devscripts/ec2test/entrypoint.py (+6/-0)
lib/devscripts/ec2test/instance.py (+66/-35)
lib/devscripts/ec2test/remote.py (+179/-119)
lib/devscripts/ec2test/session.py (+90/-0)
lib/devscripts/ec2test/testrunner.py (+36/-54)
lib/devscripts/ec2test/tests/__init__.py (+2/-0)
lib/devscripts/ec2test/tests/test_ec2instance.py (+143/-0)
lib/devscripts/ec2test/tests/test_remote.py (+29/-0)
lib/devscripts/ec2test/tests/test_session.py (+69/-0)
lib/devscripts/ec2test/tests/test_utils.py (+61/-0)
lib/devscripts/ec2test/utils.py (+55/-0)
lib/devscripts/sourcecode.py (+128/-34)
lib/devscripts/tests/test_autoland.py (+12/-1)
lib/devscripts/tests/test_sourcecode.py (+39/-9)
lib/launchpad_loggerhead/__init__.py (+1/-0)
lib/launchpad_loggerhead/app.py (+215/-0)
lib/launchpad_loggerhead/debug.py (+120/-0)
lib/launchpad_loggerhead/session.py (+73/-0)
lib/launchpad_loggerhead/static/robots.txt (+2/-0)
lib/lp/answers/browser/configure.zcml (+11/-6)
lib/lp/answers/browser/faq.py (+12/-7)
lib/lp/answers/browser/faqcollection.py (+2/-2)
lib/lp/answers/browser/question.py (+50/-37)
lib/lp/answers/browser/questiontarget.py (+13/-10)
lib/lp/answers/browser/tests/test_breadcrumbs.py (+31/-9)
lib/lp/answers/browser/tests/test_menus.py (+58/-0)
lib/lp/answers/browser/tests/views.txt (+34/-15)
lib/lp/answers/configure.zcml (+10/-3)
lib/lp/answers/doc/expiration.txt (+1/-1)
lib/lp/answers/doc/faq-vocabulary.txt (+2/-1)
lib/lp/answers/doc/faq.txt (+3/-2)
lib/lp/answers/doc/faqtarget.txt (+2/-2)
lib/lp/answers/doc/karma.txt (+1/-1)
lib/lp/answers/doc/person.txt (+161/-140)
lib/lp/answers/doc/projectgroup.txt (+47/-39)
lib/lp/answers/doc/question.txt (+162/-132)
lib/lp/answers/doc/questionsets.txt (+148/-139)
lib/lp/answers/doc/questiontarget.txt (+266/-245)
lib/lp/answers/doc/workflow.txt (+209/-193)
lib/lp/answers/interfaces/faq.py (+2/-2)
lib/lp/answers/interfaces/question.py (+1/-1)
lib/lp/answers/interfaces/questionenums.py (+2/-2)
lib/lp/answers/interfaces/questionreopening.py (+1/-0)
lib/lp/answers/interfaces/questiontarget.py (+1/-1)
lib/lp/answers/model/faq.py (+3/-3)
lib/lp/answers/stories/faq-add.txt (+3/-3)
lib/lp/answers/stories/faq-browse-and-search.txt (+1/-1)
lib/lp/answers/stories/faq-edit.txt (+3/-8)
lib/lp/answers/stories/project-add-question.txt (+15/-15)
lib/lp/answers/stories/question-add-in-other-languages.txt (+8/-8)
lib/lp/answers/stories/question-add.txt (+15/-9)
lib/lp/answers/stories/question-answer-contact.txt (+4/-4)
lib/lp/answers/stories/question-answers-vhost.txt (+5/-4)
lib/lp/answers/stories/question-browse-and-search.txt (+7/-7)
lib/lp/answers/stories/question-confirm-url.txt (+2/-2)
lib/lp/answers/stories/question-edit.txt (+4/-4)
lib/lp/answers/stories/question-message.txt (+3/-3)
lib/lp/answers/stories/question-obfuscation.txt (+9/-9)
lib/lp/answers/stories/question-overview.txt (+5/-5)
lib/lp/answers/stories/question-reject-and-change-status.txt (+3/-3)
lib/lp/answers/stories/question-subscriptions.txt (+24/-24)
lib/lp/answers/stories/question-workflow.txt (+17/-16)
lib/lp/answers/stories/this-is-a-faq.txt (+26/-23)
lib/lp/answers/templates/faq-index.pt (+38/-17)
lib/lp/answers/templates/faq-listing.pt (+0/-1)
lib/lp/answers/templates/faq-portlet-lifecycle.pt (+0/-41)
lib/lp/answers/templates/question-history.pt (+1/-9)
lib/lp/answers/templates/question-index.pt (+65/-71)
lib/lp/answers/templates/question-listing.pt (+1/-5)
lib/lp/answers/templates/question-portlet-details.pt (+89/-71)
lib/lp/answers/templates/question-portlet-reopenings.pt (+4/-9)
lib/lp/answers/templates/question-subscription.pt (+11/-7)
lib/lp/answers/tests/test_doc.py (+2/-2)
lib/lp/app/__init__.py (+6/-0)
lib/lp/app/browser/configure.zcml (+46/-0)
lib/lp/app/browser/root.py (+19/-36)
lib/lp/app/browser/tests/base-layout.txt (+51/-11)
lib/lp/app/browser/tests/launchpad-search-pages.txt (+3/-3)
lib/lp/app/browser/tests/menu.txt (+1/-1)
lib/lp/app/browser/tests/root-views.txt (+66/-0)
lib/lp/app/browser/tests/test_launchpadroot.py (+80/-0)
lib/lp/app/browser/tests/test_views.py (+5/-2)
lib/lp/app/browser/tests/watermark.txt (+1/-1)
lib/lp/app/stories/basics/copyright.txt (+2/-2)
lib/lp/app/stories/basics/xx-beta-testers-redirection.txt (+33/-62)
lib/lp/app/stories/launchpad-root/front-pages.txt (+13/-0)
lib/lp/app/stories/launchpad-root/site-search.txt (+3/-13)
lib/lp/app/stories/launchpad-root/xx-featuredprojects.txt (+21/-10)
lib/lp/app/templates/base-layout-macros.pt (+143/-95)
lib/lp/app/templates/base-layout.pt (+13/-1)
lib/lp/app/templates/launchpad-hierarchy.pt (+8/-11)
lib/lp/app/templates/launchpad-search.pt (+12/-11)
lib/lp/app/templates/navigationmenu-actions.pt (+1/-1)
lib/lp/app/templates/root-index.pt (+139/-81)
lib/lp/app/tests/test_doc.py (+17/-0)
lib/lp/archivepublisher/config.py (+20/-7)
lib/lp/archivepublisher/customupload.py (+83/-0)
lib/lp/archivepublisher/deathrow.py (+16/-16)
lib/lp/archivepublisher/debian_installer.py (+0/-3)
lib/lp/archivepublisher/dist_upgrader.py (+0/-3)
lib/lp/archivepublisher/domination.py (+34/-37)
lib/lp/archivepublisher/ftparchive.py (+4/-4)
lib/lp/archivepublisher/library.py (+0/-143)
lib/lp/archivepublisher/publishing.py (+61/-45)
lib/lp/archivepublisher/scripts/generate_ppa_htaccess.py (+9/-2)
lib/lp/archivepublisher/tests/apt-data/Packages (+2/-0)
lib/lp/archivepublisher/tests/archive-signing.txt (+4/-4)
lib/lp/archivepublisher/tests/deathrow.txt (+13/-13)
lib/lp/archivepublisher/tests/publisher-config.txt (+38/-11)
lib/lp/archivepublisher/tests/test_customupload.py (+133/-1)
lib/lp/archivepublisher/tests/test_deathrow.py (+1/-4)
lib/lp/archivepublisher/tests/test_debversion.py (+2/-2)
lib/lp/archivepublisher/tests/test_dominator.py (+12/-16)
lib/lp/archivepublisher/tests/test_ftparchive.py (+10/-25)
lib/lp/archivepublisher/tests/test_generate_ppa_htaccess.py (+69/-25)
lib/lp/archivepublisher/tests/test_librarianwrapper.py (+0/-80)
lib/lp/archivepublisher/tests/test_pool.py (+4/-4)
lib/lp/archivepublisher/tests/test_publisher.py (+78/-114)
lib/lp/archivepublisher/tests/util.py (+6/-34)
lib/lp/archiveuploader/changesfile.py (+15/-1)
lib/lp/archiveuploader/dscfile.py (+301/-34)
lib/lp/archiveuploader/nascentupload.py (+44/-48)
lib/lp/archiveuploader/nascentuploadfile.py (+16/-11)
lib/lp/archiveuploader/permission.py (+129/-13)
lib/lp/archiveuploader/tagfiles.py (+57/-22)
lib/lp/archiveuploader/tests/__init__.py (+9/-3)
lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1.dsc (+10/-0)
lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_1.0-bzip2/bar_1.0-1_source.changes (+20/-0)
lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1.dsc (+22/-0)
lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_3.0-quilt/bar_1.0-1_source.changes (+34/-0)
lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2.dsc (+22/-0)
lib/lp/archiveuploader/tests/data/suite/bar_1.0-2_3.0-quilt_without_orig/bar_1.0-2_source.changes (+25/-0)
lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0.dsc (+13/-0)
lib/lp/archiveuploader/tests/data/suite/bar_1.0_3.0-native/bar_1.0_source.changes (+25/-0)
lib/lp/archiveuploader/tests/data/suite/debug_1.0-1/debug_1.0-1.dsc (+5/-5)
lib/lp/archiveuploader/tests/data/suite/debug_1.0-1/debug_1.0-1_i386.changes (+10/-5)
lib/lp/archiveuploader/tests/data/suite/debug_1.0-1/debug_1.0-1_source.changes (+12/-6)
lib/lp/archiveuploader/tests/data/suite/foocomm_1.0-3/foocomm_1.0-3.dsc (+10/-0)
lib/lp/archiveuploader/tests/data/suite/foocomm_1.0-3/foocomm_1.0-3_source.changes (+27/-0)
lib/lp/archiveuploader/tests/data/test436182_0.1_source.changes (+23/-0)
lib/lp/archiveuploader/tests/nascentupload-ddebs.txt (+16/-16)
lib/lp/archiveuploader/tests/nascentuploadfile.txt (+247/-4)
lib/lp/archiveuploader/tests/test_buildduploads.py (+6/-7)
lib/lp/archiveuploader/tests/test_dscfile.py (+118/-0)
lib/lp/archiveuploader/tests/test_permission.py (+66/-9)
lib/lp/archiveuploader/tests/test_ppauploadprocessor.py (+68/-37)
lib/lp/archiveuploader/tests/test_recipeuploads.py (+74/-0)
lib/lp/archiveuploader/tests/test_securityuploads.py (+8/-12)
lib/lp/archiveuploader/tests/test_signedfiles.py (+1/-1)
lib/lp/archiveuploader/tests/test_tagfiles.py (+102/-38)
lib/lp/archiveuploader/tests/test_uploadprocessor.py (+392/-51)
lib/lp/archiveuploader/tests/test_utils.py (+74/-1)
lib/lp/archiveuploader/tests/upload-karma.txt (+1/-1)
lib/lp/archiveuploader/tests/upload-path-parsing.txt (+2/-2)
lib/lp/archiveuploader/uploadpolicy.py (+43/-28)
lib/lp/archiveuploader/uploadprocessor.py (+47/-28)
lib/lp/archiveuploader/utils.py (+59/-1)
lib/lp/blueprints/browser/configure.zcml (+5/-3)
lib/lp/blueprints/browser/specification.py (+44/-48)
lib/lp/blueprints/browser/specificationtarget.py (+42/-20)
lib/lp/blueprints/browser/sprint.py (+21/-5)
lib/lp/blueprints/browser/sprintattendance.py (+16/-11)
lib/lp/blueprints/browser/tests/sprintattendance-views.txt (+126/-26)
lib/lp/blueprints/browser/tests/test_breadcrumbs.py (+5/-9)
lib/lp/blueprints/browser/tests/test_menus.py (+40/-0)
lib/lp/blueprints/browser/tests/test_specificationtarget.py (+93/-0)
lib/lp/blueprints/browser/tests/test_views.py (+2/-2)
lib/lp/blueprints/doc/spec-mail-exploder.txt (+1/-1)
lib/lp/blueprints/doc/specification-notifications.txt (+10/-10)
lib/lp/blueprints/doc/specification.txt (+12/-8)
lib/lp/blueprints/doc/sprint-meeting-export.txt (+1/-1)
lib/lp/blueprints/doc/sprint.txt (+62/-10)
lib/lp/blueprints/doc/sprintattendance.txt (+60/-0)
lib/lp/blueprints/interfaces/specification.py (+4/-4)
lib/lp/blueprints/interfaces/specificationsubscription.py (+1/-2)
lib/lp/blueprints/interfaces/sprint.py (+1/-1)
lib/lp/blueprints/interfaces/sprintattendance.py (+7/-2)
lib/lp/blueprints/model/sprint.py (+4/-2)
lib/lp/blueprints/model/sprintattendance.py (+2/-4)
lib/lp/blueprints/stories/blueprints/01-creation.txt (+5/-32)
lib/lp/blueprints/stories/blueprints/02-buglinks.txt (+1/-1)
lib/lp/blueprints/stories/blueprints/08-productseries.txt (+4/-0)
lib/lp/blueprints/stories/sprints/01-sprint-overview.txt (+1/-1)
lib/lp/blueprints/stories/sprints/05-sprint-creation.txt (+2/-1)
lib/lp/blueprints/stories/sprints/20-sprint-registration.txt (+0/-6)
lib/lp/blueprints/stories/standalone/subscribing.txt (+2/-2)
lib/lp/blueprints/stories/standalone/xx-overview.txt (+2/-2)
lib/lp/blueprints/templates/hasspecifications-specs.pt (+14/-19)
lib/lp/blueprints/templates/person-specworkload.pt (+1/-1)
lib/lp/blueprints/templates/specification-index.pt (+1/-13)
lib/lp/blueprints/templates/specificationtarget-documentation.pt (+3/-4)
lib/lp/blueprints/templates/sprint-portlet-attendees.pt (+1/-1)
lib/lp/blueprints/templates/sprint-register.pt (+4/-0)
lib/lp/blueprints/tests/test_doc.py (+0/-3)
lib/lp/bugs/adapters/bug.py (+13/-2)
lib/lp/bugs/adapters/bugchange.py (+14/-4)
lib/lp/bugs/browser/bug.py (+64/-31)
lib/lp/bugs/browser/bugalsoaffects.py (+2/-22)
lib/lp/bugs/browser/bugattachment.py (+109/-12)
lib/lp/bugs/browser/bugbranch.py (+46/-3)
lib/lp/bugs/browser/bugcomment.py (+16/-2)
lib/lp/bugs/browser/buglinktarget.py (+7/-16)
lib/lp/bugs/browser/bugmessage.py (+23/-4)
lib/lp/bugs/browser/bugnomination.py (+7/-7)
lib/lp/bugs/browser/bugsubscription.py (+24/-6)
lib/lp/bugs/browser/bugsupervisor.py (+29/-14)
lib/lp/bugs/browser/bugtarget.py (+340/-387)
lib/lp/bugs/browser/bugtask.py (+408/-252)
lib/lp/bugs/browser/bugwatch.py (+61/-5)
lib/lp/bugs/browser/configure.zcml (+72/-22)
lib/lp/bugs/browser/cvereport.py (+2/-1)
lib/lp/bugs/browser/distribution_upstream_bug_report.py (+17/-5)
lib/lp/bugs/browser/tests/bug-heat-view.txt (+119/-0)
lib/lp/bugs/browser/tests/bug-nomination-views.txt (+3/-3)
lib/lp/bugs/browser/tests/bug-portlet-subscribers-content.txt (+1/-1)
lib/lp/bugs/browser/tests/bug-subscription-views.txt (+40/-0)
lib/lp/bugs/browser/tests/bug-views.txt (+30/-4)
lib/lp/bugs/browser/tests/buglinktarget-views.txt (+20/-4)
lib/lp/bugs/browser/tests/bugtarget-filebug-views.txt (+99/-38)
lib/lp/bugs/browser/tests/bugtask-adding-views.txt (+0/-37)
lib/lp/bugs/browser/tests/bugtask-search-views.txt (+3/-155)
lib/lp/bugs/browser/tests/bugwatch-views.txt (+86/-4)
lib/lp/bugs/browser/tests/special/bugs-fixed-elsewhere.txt (+39/-31)
lib/lp/bugs/browser/tests/test_breadcrumbs.py (+36/-52)
lib/lp/bugs/browser/tests/test_bugtarget_patches_view.py (+102/-0)
lib/lp/bugs/browser/tests/test_bugtask.py (+231/-2)
lib/lp/bugs/browser/tests/test_bugview.py (+67/-0)
lib/lp/bugs/configure.zcml (+118/-15)
lib/lp/bugs/doc/bug-branch.txt (+28/-4)
lib/lp/bugs/doc/bug-heat.txt (+241/-0)
lib/lp/bugs/doc/bug-nomination.txt (+4/-4)
lib/lp/bugs/doc/bug-reporting-guidelines.txt (+3/-3)
lib/lp/bugs/doc/bug-tags.txt (+3/-3)
lib/lp/bugs/doc/bug-watch-activity.txt (+148/-0)
lib/lp/bugs/doc/bug.txt (+390/-23)
lib/lp/bugs/doc/bugattachments.txt (+149/-16)
lib/lp/bugs/doc/bugcomment.txt (+43/-0)
lib/lp/bugs/doc/bugnotification-comment-syncing-team.txt (+1/-1)
lib/lp/bugs/doc/bugnotification-email.txt (+41/-4)
lib/lp/bugs/doc/bugnotification-sending.txt (+11/-5)
lib/lp/bugs/doc/bugs-email-affects-path.txt (+1/-1)
lib/lp/bugs/doc/bugsubscription.txt (+16/-4)
lib/lp/bugs/doc/bugtask-expiration.txt (+14/-25)
lib/lp/bugs/doc/bugtask-package-bugcounts.txt (+10/-0)
lib/lp/bugs/doc/bugtask-search.txt (+119/-4)
lib/lp/bugs/doc/bugtask-status-workflow.txt (+8/-1)
lib/lp/bugs/doc/bugtask.txt (+7/-2)
lib/lp/bugs/doc/bugtracker.txt (+30/-27)
lib/lp/bugs/doc/bugwatch.txt (+106/-13)
lib/lp/bugs/doc/bugzilla-import.txt (+3/-7)
lib/lp/bugs/doc/checkwatches-batching.txt (+140/-0)
lib/lp/bugs/doc/checkwatches-cli-switches.txt (+22/-19)
lib/lp/bugs/doc/checkwatches.txt (+175/-52)
lib/lp/bugs/doc/cve-update.txt (+2/-2)
lib/lp/bugs/doc/distribution-upstream-bug-report.txt (+108/-56)
lib/lp/bugs/doc/externalbugtracker-bug-imports.txt (+6/-4)
lib/lp/bugs/doc/externalbugtracker-bugzilla-api.txt (+91/-32)
lib/lp/bugs/doc/externalbugtracker-bugzilla-lp-plugin.txt (+51/-19)
lib/lp/bugs/doc/externalbugtracker-bugzilla-oddities.txt (+5/-3)
lib/lp/bugs/doc/externalbugtracker-bugzilla.txt (+71/-15)
lib/lp/bugs/doc/externalbugtracker-comment-imports.txt (+56/-24)
lib/lp/bugs/doc/externalbugtracker-comment-pushing.txt (+42/-24)
lib/lp/bugs/doc/externalbugtracker-debbugs.txt (+43/-25)
lib/lp/bugs/doc/externalbugtracker-linking-back.txt (+38/-10)
lib/lp/bugs/doc/externalbugtracker-mantis-csv.txt (+13/-11)
lib/lp/bugs/doc/externalbugtracker-mantis.txt (+6/-4)
lib/lp/bugs/doc/externalbugtracker-roundup.txt (+4/-2)
lib/lp/bugs/doc/externalbugtracker-rt.txt (+4/-2)
lib/lp/bugs/doc/externalbugtracker-sourceforge.txt (+6/-2)
lib/lp/bugs/doc/externalbugtracker-trac-lp-plugin.txt (+27/-15)
lib/lp/bugs/doc/externalbugtracker-trac.txt (+40/-7)
lib/lp/bugs/doc/externalbugtracker.txt (+71/-82)
lib/lp/bugs/doc/filebug-data-parser.txt (+3/-3)
lib/lp/bugs/doc/hasbugs.txt (+26/-0)
lib/lp/bugs/doc/malone-karma.txt (+33/-2)
lib/lp/bugs/doc/malone-xmlrpc.txt (+2/-2)
lib/lp/bugs/doc/memory-debug.txt (+0/-185)
lib/lp/bugs/doc/official-bug-tags.txt (+6/-6)
lib/lp/bugs/externalbugtracker/__init__.py (+4/-1)
lib/lp/bugs/externalbugtracker/base.py (+14/-3)
lib/lp/bugs/externalbugtracker/bugzilla.py (+118/-119)
lib/lp/bugs/externalbugtracker/debbugs.py (+22/-16)
lib/lp/bugs/externalbugtracker/isolation.py (+65/-0)
lib/lp/bugs/externalbugtracker/mantis.py (+34/-8)
lib/lp/bugs/externalbugtracker/rt.py (+2/-0)
lib/lp/bugs/externalbugtracker/tests/test_externalbugtracker.py (+92/-0)
lib/lp/bugs/externalbugtracker/tests/test_isolation.py (+99/-0)
lib/lp/bugs/externalbugtracker/trac.py (+46/-20)
lib/lp/bugs/externalbugtracker/xmlrpc.py (+11/-12)
lib/lp/bugs/feed/bug.py (+2/-2)
lib/lp/bugs/help/bug-heat.html (+191/-0)
lib/lp/bugs/help/tag-help.html (+30/-0)
lib/lp/bugs/help/tag-search.html (+5/-5)
lib/lp/bugs/interfaces/apportjob.py (+74/-0)
lib/lp/bugs/interfaces/bug.py (+168/-33)
lib/lp/bugs/interfaces/bugattachment.py (+17/-1)
lib/lp/bugs/interfaces/bugjob.py (+67/-0)
lib/lp/bugs/interfaces/bugmessage.py (+5/-2)
lib/lp/bugs/interfaces/bugnomination.py (+4/-4)
lib/lp/bugs/interfaces/bugsubscription.py (+5/-4)
lib/lp/bugs/interfaces/bugsupervisor.py (+2/-3)
lib/lp/bugs/interfaces/bugtarget.py (+60/-34)
lib/lp/bugs/interfaces/bugtask.py (+68/-11)
lib/lp/bugs/interfaces/bugtracker.py (+48/-18)
lib/lp/bugs/interfaces/bugwatch.py (+135/-5)
lib/lp/bugs/interfaces/cve.py (+6/-0)
lib/lp/bugs/interfaces/externalbugtracker.py (+50/-20)
lib/lp/bugs/model/apportjob.py (+263/-0)
lib/lp/bugs/model/bug.py (+303/-44)
lib/lp/bugs/model/bugattachment.py (+16/-0)
lib/lp/bugs/model/bugheat.py (+54/-0)
lib/lp/bugs/model/bugjob.py (+137/-0)
lib/lp/bugs/model/bugnotification.py (+2/-0)
lib/lp/bugs/model/bugsubscription.py (+3/-0)
lib/lp/bugs/model/bugtarget.py (+118/-7)
lib/lp/bugs/model/bugtask.py (+169/-58)
lib/lp/bugs/model/bugtracker.py (+49/-45)
lib/lp/bugs/model/bugwatch.py (+201/-42)
lib/lp/bugs/scripts/bugexpire.py (+3/-3)
lib/lp/bugs/scripts/bugheat.py (+108/-0)
lib/lp/bugs/scripts/bugimport.py (+1/-1)
lib/lp/bugs/scripts/bugnotification.py (+12/-0)
lib/lp/bugs/scripts/bugzilla.py (+1/-1)
lib/lp/bugs/scripts/checkwatches/__init__.py (+10/-0)
lib/lp/bugs/scripts/checkwatches/base.py (+264/-0)
lib/lp/bugs/scripts/checkwatches/bugwatchupdater.py (+284/-0)
lib/lp/bugs/scripts/checkwatches/core.py (+594/-731)
lib/lp/bugs/scripts/checkwatches/scheduler.py (+92/-0)
lib/lp/bugs/scripts/checkwatches/tests/test_base.py (+178/-0)
lib/lp/bugs/scripts/checkwatches/tests/test_core.py (+441/-0)
lib/lp/bugs/scripts/checkwatches/tests/test_scheduler.py (+110/-0)
lib/lp/bugs/scripts/importdebianbugs.py (+2/-2)
lib/lp/bugs/scripts/tests/test_bugheat.py (+256/-0)
lib/lp/bugs/scripts/tests/test_bugimport.py (+36/-17)
lib/lp/bugs/scripts/tests/test_bugnotification.py (+1/-2)
lib/lp/bugs/stories/bug-also-affects/xx-also-affects-upstream-default-values.txt (+3/-2)
lib/lp/bugs/stories/bug-also-affects/xx-upstream-bugtracker-links.txt (+4/-2)
lib/lp/bugs/stories/bug-privacy/05-set-bug-private-as-admin.txt (+6/-3)
lib/lp/bugs/stories/bug-tags/xx-official-bug-tags.txt (+48/-2)
lib/lp/bugs/stories/bug-tags/xx-tags-on-bug-page.txt (+3/-3)
lib/lp/bugs/stories/bugattachments/10-add-bug-attachment.txt (+185/-0)
lib/lp/bugs/stories/bugattachments/20-edit-bug-attachment.txt (+86/-30)
lib/lp/bugs/stories/bugattachments/xx-attachments-to-bug-report.txt (+20/-0)
lib/lp/bugs/stories/bugattachments/xx-delete-bug-attachment.txt (+7/-3)
lib/lp/bugs/stories/bugs/bug-add-subscriber.txt (+22/-2)
lib/lp/bugs/stories/bugs/xx-bug-activity.txt (+32/-2)
lib/lp/bugs/stories/bugs/xx-bug-affects-me-too.txt (+26/-11)
lib/lp/bugs/stories/bugs/xx-bug-comments-truncated.txt (+1/-1)
lib/lp/bugs/stories/bugs/xx-bug-create-question.txt (+5/-9)
lib/lp/bugs/stories/bugs/xx-bug-edit.txt (+14/-4)
lib/lp/bugs/stories/bugs/xx-bug-heat-on-bug-page.txt (+35/-0)
lib/lp/bugs/stories/bugs/xx-bug-hidden-comments.txt (+37/-6)
lib/lp/bugs/stories/bugs/xx-bug-index.txt (+3/-3)
lib/lp/bugs/stories/bugs/xx-bug-personal-subscriptions.txt (+35/-16)
lib/lp/bugs/stories/bugs/xx-bugtarget-bugs-page.txt (+1/-1)
lib/lp/bugs/stories/bugs/xx-front-page-bug-lists.txt (+97/-8)
lib/lp/bugs/stories/bugs/xx-front-page-info.txt (+112/-0)
lib/lp/bugs/stories/bugs/xx-front-page-search.txt (+1/-1)
lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt (+1/-1)
lib/lp/bugs/stories/bugs/xx-link-bug-to-branch.txt (+2/-13)
lib/lp/bugs/stories/bugs/xx-portlets-bug-series.txt (+2/-18)
lib/lp/bugs/stories/bugs/xx-product-bugs-page.txt (+72/-40)
lib/lp/bugs/stories/bugs/xx-project-bugs-page.txt (+3/-3)
lib/lp/bugs/stories/bugs/xx-remote-bug-comments.txt (+2/-0)
lib/lp/bugs/stories/bugtask-management/xx-bugtask-edit-forms.txt (+55/-0)
lib/lp/bugs/stories/bugtask-management/xx-change-milestone.txt (+2/-2)
lib/lp/bugs/stories/bugtask-searches/xx-advanced-upstream-pending-bugwatch.txt (+1/-35)
lib/lp/bugs/stories/bugtask-searches/xx-filter-by-linked-branches.txt (+64/-0)
lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt (+50/-2)
lib/lp/bugs/stories/bugtask-searches/xx-searching-by-tags.txt (+28/-3)
lib/lp/bugs/stories/bugtracker/bugtrackers-index.txt (+2/-1)
lib/lp/bugs/stories/bugtracker/xx-bugtracker-handshake-tokens.txt (+1/-1)
lib/lp/bugs/stories/bugtracker/xx-bugtracker-remote-bug.txt (+6/-5)
lib/lp/bugs/stories/bugtracker/xx-bugtracker.txt (+37/-13)
lib/lp/bugs/stories/bugwatches/xx-bugwatch-comments.txt (+1/-1)
lib/lp/bugs/stories/bugwatches/xx-bugwatch-errors.txt (+27/-5)
lib/lp/bugs/stories/bugwatches/xx-edit-bugwatch.txt (+165/-1)
lib/lp/bugs/stories/cve/cve-linking.txt (+15/-16)
lib/lp/bugs/stories/distribution/xx-distribution-bug-statistics-portlet-authenticated.txt (+0/-19)
lib/lp/bugs/stories/distribution/xx-distribution-bug-statistics-portlet-unauthenticated.txt (+0/-16)
lib/lp/bugs/stories/distribution/xx-distribution-upstream-bug-report.txt (+39/-22)
lib/lp/bugs/stories/duplicate-bug-handling/10-mark-bug-as-duplicate.txt (+1/-0)
lib/lp/bugs/stories/duplicate-bug-handling/20-show-bug-is-duplicate.txt (+1/-1)
lib/lp/bugs/stories/feeds/xx-bug-atom.txt (+4/-5)
lib/lp/bugs/stories/feeds/xx-bug-html.txt (+4/-5)
lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt (+11/-45)
lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-tools.txt (+37/-0)
lib/lp/bugs/stories/guided-filebug/xx-displaying-similar-bugs.txt (+1/-1)
lib/lp/bugs/stories/guided-filebug/xx-distro-guided-filebug-tags.txt (+1/-1)
lib/lp/bugs/stories/guided-filebug/xx-filebug-tags.txt (+1/-2)
lib/lp/bugs/stories/guided-filebug/xx-filing-security-bugs.txt (+0/-30)
lib/lp/bugs/stories/guided-filebug/xx-frontpage-filebug-distribution.txt (+0/-109)
lib/lp/bugs/stories/guided-filebug/xx-frontpage-filebug-package.txt (+0/-77)
lib/lp/bugs/stories/guided-filebug/xx-frontpage-filebug-product.txt (+0/-123)
lib/lp/bugs/stories/guided-filebug/xx-no-launchpadder.txt (+2/-1)
lib/lp/bugs/stories/guided-filebug/xx-project-guided-filebug.txt (+18/-6)
lib/lp/bugs/stories/guided-filebug/xx-ubuntu-filebug.txt (+20/-11)
lib/lp/bugs/stories/initial-bug-contacts/05-set-distribution-bugcontact.txt (+76/-28)
lib/lp/bugs/stories/initial-bug-contacts/10-set-upstream-bugcontact.txt (+109/-15)
lib/lp/bugs/stories/initial-bug-contacts/20-file-upstream-bug.txt (+5/-4)
lib/lp/bugs/stories/initial-bug-contacts/25-file-distribution-bug.txt (+3/-2)
lib/lp/bugs/stories/patches-view/patches-view.txt (+536/-0)
lib/lp/bugs/stories/structural-subscriptions/xx-bug-subscriptions.txt (+17/-0)
lib/lp/bugs/stories/upstream-bugprivacy/10-file-private-upstream-bug.txt (+5/-8)
lib/lp/bugs/stories/webservice/xx-bug-tracker.txt (+77/-0)
lib/lp/bugs/stories/webservice/xx-bug.txt (+185/-50)
lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt (+412/-0)
lib/lp/bugs/subscribers/bug.py (+7/-6)
lib/lp/bugs/subscribers/bugactivity.py (+12/-9)
lib/lp/bugs/subscribers/buglastupdated.py (+3/-1)
lib/lp/bugs/templates/bug-attachment-confirm-is-patch.pt (+40/-0)
lib/lp/bugs/templates/bug-attachment-edit.pt (+5/-0)
lib/lp/bugs/templates/bug-branch.pt (+33/-0)
lib/lp/bugs/templates/bug-comment-add-form.pt (+3/-1)
lib/lp/bugs/templates/bug-listing-detailed.pt (+1/-1)
lib/lp/bugs/templates/bug-portlet-actions.pt (+1/-1)
lib/lp/bugs/templates/bug-portlet-attachments.pt (+46/-22)
lib/lp/bugs/templates/bug-portlet-dupe-subscribers-content.pt (+27/-0)
lib/lp/bugs/templates/bug-portlet-specs.pt (+1/-1)
lib/lp/bugs/templates/bug-portlet-subscribers-content.pt (+12/-20)
lib/lp/bugs/templates/bug-portlet-subscribers.pt (+22/-49)
lib/lp/bugs/templates/bugcomment-box.pt (+12/-1)
lib/lp/bugs/templates/buglinktarget-portlet-bugs.pt (+11/-18)
lib/lp/bugs/templates/buglisting-embedded-advanced-search.pt (+0/-1)
lib/lp/bugs/templates/bugtarget-bugs.pt (+138/-175)
lib/lp/bugs/templates/bugtarget-filebug-inline-form.pt (+11/-0)
lib/lp/bugs/templates/bugtarget-filebug-search.pt (+112/-34)
lib/lp/bugs/templates/bugtarget-filebug-show-similar.pt (+7/-2)
lib/lp/bugs/templates/bugtarget-filebug-submit-bug.pt (+6/-4)
lib/lp/bugs/templates/bugtarget-macros-filebug.pt (+67/-22)
lib/lp/bugs/templates/bugtarget-macros-search.pt (+4/-0)
lib/lp/bugs/templates/bugtarget-patches.pt (+115/-0)
lib/lp/bugs/templates/bugtarget-portlet-bugfilters-content.pt (+134/-41)
lib/lp/bugs/templates/bugtarget-portlet-bugfilters.pt (+47/-28)
lib/lp/bugs/templates/bugtarget-portlet-bugtags.pt (+5/-5)
lib/lp/bugs/templates/bugtask-edit.pt (+0/-9)
lib/lp/bugs/templates/bugtask-index.pt (+55/-30)
lib/lp/bugs/templates/bugtask-macros-listing.pt (+39/-28)
lib/lp/bugs/templates/bugtask-macros-tableview.pt (+101/-69)
lib/lp/bugs/templates/bugtask-tasks-and-nominations-table-row.pt (+27/-14)
lib/lp/bugs/templates/bugtask-view.pt (+0/-18)
lib/lp/bugs/templates/bugtasks-and-nominations-table.pt (+63/-48)
lib/lp/bugs/templates/bugtracker-portlet-watches.pt (+14/-0)
lib/lp/bugs/templates/bugwatch-editform.pt (+4/-0)
lib/lp/bugs/templates/bugwatch-portlet-activity.pt (+44/-0)
lib/lp/bugs/templates/bugwatch-portlet-details.pt (+21/-7)
lib/lp/bugs/templates/cve-index.pt (+9/-11)
lib/lp/bugs/templates/cve-portlet-bugs2.pt (+1/-1)
lib/lp/bugs/templates/cveset-all.pt (+0/-4)
lib/lp/bugs/templates/distribution-cvereport.pt (+7/-7)
lib/lp/bugs/templates/distribution-upstream-bug-report.pt (+21/-1)
lib/lp/bugs/templates/malone-index.pt (+1/-1)
lib/lp/bugs/templates/malone-portlet-stats.pt (+1/-1)
lib/lp/bugs/templates/official-bug-target-manage-tags.pt (+2/-6)
lib/lp/bugs/templates/person-packagebugs-search.pt (+0/-16)
lib/lp/bugs/tests/bug.py (+73/-12)
lib/lp/bugs/tests/bugs-emailinterface.txt (+22/-6)
lib/lp/bugs/tests/bugtarget-bugcount.txt (+2/-0)
lib/lp/bugs/tests/bugzilla-api-xmlrpc-transport.txt (+96/-39)
lib/lp/bugs/tests/bugzilla-xmlrpc-transport.txt (+28/-35)
lib/lp/bugs/tests/externalbugtracker-xmlrpc-transport.txt (+17/-20)
lib/lp/bugs/tests/externalbugtracker.py (+111/-56)
lib/lp/bugs/tests/test_apportjob.py (+427/-0)
lib/lp/bugs/tests/test_bug_messages.py (+44/-0)
lib/lp/bugs/tests/test_bugchanges.py (+6/-5)
lib/lp/bugs/tests/test_bugcontact.py (+5/-4)
lib/lp/bugs/tests/test_bugheat.py (+300/-0)
lib/lp/bugs/tests/test_bugjob.py (+55/-0)
lib/lp/bugs/tests/test_bugnotification.py (+68/-4)
lib/lp/bugs/tests/test_bugs_webservice.py (+80/-11)
lib/lp/bugs/tests/test_bugtarget.py (+7/-6)
lib/lp/bugs/tests/test_bugtask.py (+1/-1)
lib/lp/bugs/tests/test_bugtask_1.py (+3/-3)
lib/lp/bugs/tests/test_bugtask_status.txt (+52/-4)
lib/lp/bugs/tests/test_bugtracker.py (+162/-7)
lib/lp/bugs/tests/test_bugwatch.py (+373/-49)
lib/lp/bugs/tests/test_doc.py (+12/-0)
lib/lp/bugs/utilities/filebugdataparser.py (+168/-0)
lib/lp/bugs/windmill/tests/test_bug_also_affects_new_upstream.py (+44/-37)
lib/lp/bugs/windmill/tests/test_bug_commenting.py (+4/-5)
lib/lp/bugs/windmill/tests/test_bug_inline_subscriber.py (+235/-248)
lib/lp/bugs/windmill/tests/test_bug_me_too.py (+90/-94)
lib/lp/bugs/windmill/tests/test_bug_privacy_settings.py (+156/-128)
lib/lp/bugs/windmill/tests/test_bug_tags_entry.py (+77/-0)
lib/lp/bugs/windmill/tests/test_bugs/__init__.py (+0/-85)
lib/lp/bugs/windmill/tests/test_bugs/test_bug_tags_entry.py (+0/-80)
lib/lp/bugs/windmill/tests/test_filebug_dupe_finder.py (+97/-99)
lib/lp/bugs/windmill/tests/test_filebug_extra_options.py (+58/-58)
lib/lp/bugs/windmill/tests/test_mark_duplicate.py (+114/-92)
lib/lp/bugs/windmill/tests/test_official_bug_tags_management.py (+202/-161)
lib/lp/buildmaster/buildergroup.py (+0/-537)
lib/lp/buildmaster/configure.zcml (+67/-0)
lib/lp/buildmaster/doc/builder.txt (+175/-145)
lib/lp/buildmaster/doc/buildfarmjob.txt (+43/-0)
lib/lp/buildmaster/doc/buildfarmjobbehavior.txt (+121/-0)
lib/lp/buildmaster/doc/buildqueue.txt (+37/-47)
lib/lp/buildmaster/interfaces/buildbase.py (+264/-0)
lib/lp/buildmaster/interfaces/builder.py (+65/-62)
lib/lp/buildmaster/interfaces/buildfarmbranchjob.py (+20/-0)
lib/lp/buildmaster/interfaces/buildfarmjob.py (+153/-0)
lib/lp/buildmaster/interfaces/buildfarmjobbehavior.py (+76/-0)
lib/lp/buildmaster/interfaces/buildqueue.py (+74/-92)
lib/lp/buildmaster/manager.py (+57/-41)
lib/lp/buildmaster/master.py (+0/-317)
lib/lp/buildmaster/model/buildbase.py (+381/-0)
lib/lp/buildmaster/model/builder.py (+395/-389)
lib/lp/buildmaster/model/buildfarmjob.py (+135/-0)
lib/lp/buildmaster/model/buildfarmjobbehavior.py (+218/-0)
lib/lp/buildmaster/model/buildqueue.py (+438/-266)
lib/lp/buildmaster/model/packagebuildfarmjob.py (+58/-0)
lib/lp/buildmaster/tests/harness.py (+3/-3)
lib/lp/buildmaster/tests/test_buildbase.py (+163/-0)
lib/lp/buildmaster/tests/test_builder.py (+346/-0)
lib/lp/buildmaster/tests/test_buildfarmjobbehavior.py (+150/-0)
lib/lp/buildmaster/tests/test_buildmaster_documentation.py (+30/-10)
lib/lp/buildmaster/tests/test_buildqueue.py (+1340/-0)
lib/lp/buildmaster/tests/test_manager.py (+142/-47)
lib/lp/code/adapters/branch.py (+1/-1)
lib/lp/code/adapters/tests/test_branch.py (+2/-0)
lib/lp/code/browser/bazaar.py (+3/-1)
lib/lp/code/browser/branch.py (+170/-85)
lib/lp/code/browser/branchlisting.py (+49/-45)
lib/lp/code/browser/branchmergeproposal.py (+323/-75)
lib/lp/code/browser/branchmergeproposallisting.py (+33/-1)
lib/lp/code/browser/branchsubscription.py (+6/-29)
lib/lp/code/browser/codeimport.py (+200/-113)
lib/lp/code/browser/codeimportmachine.py (+9/-0)
lib/lp/code/browser/codereviewcomment.py (+52/-41)
lib/lp/code/browser/codereviewvote.py (+11/-3)
lib/lp/code/browser/configure.zcml (+150/-28)
lib/lp/code/browser/diff.py (+95/-0)
lib/lp/code/browser/sourcepackagerecipe.py (+406/-0)
lib/lp/code/browser/sourcepackagerecipelisting.py (+73/-0)
lib/lp/code/browser/summary.py (+1/-1)
lib/lp/code/browser/tests/test_branch.py (+62/-1)
lib/lp/code/browser/tests/test_branchlisting.py (+50/-2)
lib/lp/code/browser/tests/test_branchmergeproposal.py (+262/-56)
lib/lp/code/browser/tests/test_branchmergeproposallisting.py (+53/-1)
lib/lp/code/browser/tests/test_breadcrumbs.py (+25/-0)
lib/lp/code/browser/tests/test_codeimport.py (+60/-0)
lib/lp/code/browser/tests/test_codereviewcomment.py (+1/-60)
lib/lp/code/browser/tests/test_diff.py (+41/-0)
lib/lp/code/browser/tests/test_sourcepackagerecipe.py (+394/-0)
lib/lp/code/browser/tests/test_tales.py (+175/-0)
lib/lp/code/bzr.py (+32/-63)
lib/lp/code/configure.zcml (+235/-57)
lib/lp/code/doc/branch-karma.txt (+2/-1)
lib/lp/code/doc/branch-merge-proposal-notifications.txt (+13/-11)
lib/lp/code/doc/branch-merge-proposals.txt (+4/-5)
lib/lp/code/doc/branch-notifications.txt (+20/-22)
lib/lp/code/doc/branch-visibility-policy.txt (+4/-4)
lib/lp/code/doc/branch-visibility.txt (+6/-6)
lib/lp/code/doc/branch-xmlrpc.txt (+2/-2)
lib/lp/code/doc/branch.txt (+5/-3)
lib/lp/code/doc/codeimport-event.txt (+31/-77)
lib/lp/code/doc/codeimport.txt (+238/-93)
lib/lp/code/doc/codereviewcomment.txt (+20/-8)
lib/lp/code/doc/xmlrpc-branch-filesystem.txt (+0/-31)
lib/lp/code/doc/xmlrpc-branch-puller.txt (+0/-46)
lib/lp/code/doc/xmlrpc-codehosting.txt (+32/-0)
lib/lp/code/doc/xmlrpc-codeimport-scheduler.txt (+5/-8)
lib/lp/code/enums.py (+36/-1)
lib/lp/code/errors.py (+93/-0)
lib/lp/code/event/branchmergeproposal.py (+1/-1)
lib/lp/code/feed/branch.py (+3/-3)
lib/lp/code/help/register-branch.html (+5/-5)
lib/lp/code/interfaces/branch.py (+249/-92)
lib/lp/code/interfaces/branchjob.py (+37/-13)
lib/lp/code/interfaces/branchlookup.py (+19/-0)
lib/lp/code/interfaces/branchmergeproposal.py (+111/-66)
lib/lp/code/interfaces/branchpuller.py (+3/-7)
lib/lp/code/interfaces/branchscanner.py (+0/-18)
lib/lp/code/interfaces/branchtarget.py (+28/-3)
lib/lp/code/interfaces/branchvisibilitypolicy.py (+1/-1)
lib/lp/code/interfaces/codehosting.py (+32/-75)
lib/lp/code/interfaces/codeimport.py (+97/-94)
lib/lp/code/interfaces/codeimportjob.py (+13/-4)
lib/lp/code/interfaces/codeimportmachine.py (+1/-1)
lib/lp/code/interfaces/codeimportscheduler.py (+27/-1)
lib/lp/code/interfaces/codereviewcomment.py (+18/-1)
lib/lp/code/interfaces/codereviewvote.py (+83/-13)
lib/lp/code/interfaces/diff.py (+7/-0)
lib/lp/code/interfaces/event.py (+36/-0)
lib/lp/code/interfaces/hasbranches.py (+87/-6)
lib/lp/code/interfaces/hasrecipes.py (+19/-0)
lib/lp/code/interfaces/linkedbranch.py (+6/-0)
lib/lp/code/interfaces/revision.py (+3/-3)
lib/lp/code/interfaces/sourcepackagerecipe.py (+187/-0)
lib/lp/code/interfaces/sourcepackagerecipebuild.py (+101/-0)
lib/lp/code/interfaces/tests/test_branch.py (+1/-45)
lib/lp/code/interfaces/webservice.py (+11/-1)
lib/lp/code/javascript/branch.bugspeclinks.js (+27/-29)
lib/lp/code/javascript/branch.status.js (+49/-0)
lib/lp/code/javascript/branch.subscription.js (+219/-0)
lib/lp/code/javascript/branchmergeproposal.diff.js (+134/-0)
lib/lp/code/javascript/branchmergeproposal.reviewcomment.js (+175/-19)
lib/lp/code/javascript/branchmergeproposal.status.js (+130/-0)
lib/lp/code/javascript/productseries-setbranch.js (+88/-0)
lib/lp/code/javascript/tests/test_productseries-setbranch.html (+213/-0)
lib/lp/code/javascript/tests/test_productseries_setbranch.js (+249/-0)
lib/lp/code/mail/branch.py (+25/-34)
lib/lp/code/mail/branchmergeproposal.py (+56/-83)
lib/lp/code/mail/codehandler.py (+80/-76)
lib/lp/code/mail/codeimport.py (+31/-17)
lib/lp/code/mail/codereviewcomment.py (+22/-11)
lib/lp/code/mail/tests/test_branch.py (+51/-5)
lib/lp/code/mail/tests/test_branchmergeproposal.py (+188/-82)
lib/lp/code/mail/tests/test_codehandler.py (+201/-116)
lib/lp/code/mail/tests/test_codeimport.py (+144/-0)
lib/lp/code/mail/tests/test_codereviewcomment.py (+22/-4)
lib/lp/code/model/branch.py (+180/-87)
lib/lp/code/model/branchjob.py (+169/-110)
lib/lp/code/model/branchlookup.py (+34/-10)
lib/lp/code/model/branchmergeproposal.py (+78/-41)
lib/lp/code/model/branchmergeproposaljob.py (+438/-77)
lib/lp/code/model/branchnamespace.py (+4/-5)
lib/lp/code/model/branchpuller.py (+5/-25)
lib/lp/code/model/branchscanner.py (+0/-40)
lib/lp/code/model/branchtarget.py (+48/-7)
lib/lp/code/model/branchvisibilitypolicy.py (+4/-4)
lib/lp/code/model/codeimport.py (+74/-106)
lib/lp/code/model/codeimportevent.py (+5/-4)
lib/lp/code/model/codeimportjob.py (+35/-23)
lib/lp/code/model/codeimportmachine.py (+2/-3)
lib/lp/code/model/codereviewcomment.py (+56/-0)
lib/lp/code/model/codereviewvote.py (+58/-0)
lib/lp/code/model/diff.py (+100/-36)
lib/lp/code/model/directbranchcommit.py (+29/-28)
lib/lp/code/model/hasbranches.py (+36/-2)
lib/lp/code/model/linkedbranch.py (+124/-25)
lib/lp/code/model/recipebuilder.py (+184/-0)
lib/lp/code/model/revision.py (+34/-24)
lib/lp/code/model/sourcepackagerecipe.py (+179/-0)
lib/lp/code/model/sourcepackagerecipebuild.py (+234/-0)
lib/lp/code/model/sourcepackagerecipedata.py (+260/-0)
lib/lp/code/model/tests/test_branch.py (+642/-147)
lib/lp/code/model/tests/test_branchcloud.py (+4/-3)
lib/lp/code/model/tests/test_branchcollection.py (+36/-0)
lib/lp/code/model/tests/test_branchjob.py (+185/-170)
lib/lp/code/model/tests/test_branchlookup.py (+58/-2)
lib/lp/code/model/tests/test_branchmergeproposaljobs.py (+446/-0)
lib/lp/code/model/tests/test_branchmergeproposals.py (+188/-264)
lib/lp/code/model/tests/test_branchpuller.py (+61/-109)
lib/lp/code/model/tests/test_branchscanner.py (+0/-100)
lib/lp/code/model/tests/test_branchset.py (+20/-10)
lib/lp/code/model/tests/test_branchtarget.py (+69/-7)
lib/lp/code/model/tests/test_codeimport.py (+201/-235)
lib/lp/code/model/tests/test_codeimportjob.py (+51/-41)
lib/lp/code/model/tests/test_codeimportmachine.py (+9/-11)
lib/lp/code/model/tests/test_codereviewcomment.py (+59/-4)
lib/lp/code/model/tests/test_codereviewkarma.py (+2/-1)
lib/lp/code/model/tests/test_codereviewvote.py (+238/-9)
lib/lp/code/model/tests/test_diff.py (+149/-11)
lib/lp/code/model/tests/test_hasbranches.py (+1/-1)
lib/lp/code/model/tests/test_hasmergeproposals.py (+1/-1)
lib/lp/code/model/tests/test_hasrecipes.py (+77/-0)
lib/lp/code/model/tests/test_linkedbranch.py (+145/-1)
lib/lp/code/model/tests/test_revision.py (+58/-13)
lib/lp/code/model/tests/test_revisionauthor.py (+3/-0)
lib/lp/code/model/tests/test_sourcepackagerecipe.py (+581/-0)
lib/lp/code/model/tests/test_sourcepackagerecipe.py.moved (+40/-0)
lib/lp/code/scripts/revisionkarma.py (+13/-6)
lib/lp/code/scripts/tests/test_create_merge_proposals.py (+8/-14)
lib/lp/code/scripts/tests/test_merge_proposal_jobs.py (+10/-47)
lib/lp/code/scripts/tests/test_reclaim_branch_space.py (+3/-4)
lib/lp/code/scripts/tests/test_scan_branches.py (+78/-0)
lib/lp/code/scripts/tests/test_sendbranchmail.py (+17/-12)
lib/lp/code/scripts/tests/test_update_preview_diffs.py (+0/-48)
lib/lp/code/scripts/tests/test_upgrade_branches.py (+75/-0)
lib/lp/code/stories/branches/xx-bazaar-home.txt (+1/-1)
lib/lp/code/stories/branches/xx-branch-deletion.txt (+1/-1)
lib/lp/code/stories/branches/xx-branch-edit-privacy.txt (+35/-8)
lib/lp/code/stories/branches/xx-branch-edit.txt (+7/-5)
lib/lp/code/stories/branches/xx-branch-index.txt (+2/-1)
lib/lp/code/stories/branches/xx-branch-listings.txt (+1/-4)
lib/lp/code/stories/branches/xx-branch-mirror-failures.txt (+3/-1)
lib/lp/code/stories/branches/xx-branch-tag-cloud.txt (+7/-5)
lib/lp/code/stories/branches/xx-branchmergeproposal-listings.txt (+59/-10)
lib/lp/code/stories/branches/xx-branchmergeproposals.txt (+167/-71)
lib/lp/code/stories/branches/xx-bug-branch-links.txt (+39/-13)
lib/lp/code/stories/branches/xx-claiming-team-code-reviews.txt (+2/-1)
lib/lp/code/stories/branches/xx-code-review-comments.txt (+70/-3)
lib/lp/code/stories/branches/xx-creating-branches.txt (+28/-0)
lib/lp/code/stories/branches/xx-junk-branches.txt (+11/-2)
lib/lp/code/stories/branches/xx-nearby-branches.txt (+25/-0)
lib/lp/code/stories/branches/xx-person-branches.txt (+0/-1)
lib/lp/code/stories/branches/xx-person-portlet-teambranches.txt (+29/-20)
lib/lp/code/stories/branches/xx-private-branch-listings.txt (+1/-1)
lib/lp/code/stories/branches/xx-product-branches.txt (+14/-10)
lib/lp/code/stories/branches/xx-project-branches.txt (+2/-2)
lib/lp/code/stories/branches/xx-propose-for-merging.txt (+61/-0)
lib/lp/code/stories/branches/xx-register-a-branch.txt (+4/-10)
lib/lp/code/stories/branches/xx-reviewing.txt (+39/-0)
lib/lp/code/stories/branches/xx-source-package-branches-listing.txt (+3/-0)
lib/lp/code/stories/branches/xx-subscribing-branches.txt (+129/-3)
lib/lp/code/stories/branches/xx-upgrading-branches.txt (+49/-0)
lib/lp/code/stories/codeimport/xx-admin-codeimport.txt (+357/-0)
lib/lp/code/stories/codeimport/xx-codeimport-list.txt (+0/-62)
lib/lp/code/stories/codeimport/xx-codeimport-machines.txt (+7/-7)
lib/lp/code/stories/codeimport/xx-codeimport-results.txt (+22/-14)
lib/lp/code/stories/codeimport/xx-codeimport-view.txt (+37/-19)
lib/lp/code/stories/codeimport/xx-create-codeimport.txt (+145/-30)
lib/lp/code/stories/codeimport/xx-edit-codeimport.txt (+45/-209)
lib/lp/code/stories/codeimport/xx-failing-codeimport.txt (+5/-4)
lib/lp/code/stories/feeds/xx-revision-atom.txt (+1/-1)
lib/lp/code/stories/sourcepackagerecipes/xx-recipe-listings.txt (+140/-0)
lib/lp/code/stories/webservice/xx-branch.txt (+68/-5)
lib/lp/code/stories/webservice/xx-branchmergeproposal.txt (+197/-37)
lib/lp/code/stories/webservice/xx-code-import.txt (+253/-0)
lib/lp/code/subscribers/branchmergeproposal.py (+55/-0)
lib/lp/code/templates/active-reviews.pt (+6/-0)
lib/lp/code/templates/bazaar-index.pt (+11/-8)
lib/lp/code/templates/branch-delete.pt (+1/-1)
lib/lp/code/templates/branch-import-details.pt (+33/-13)
lib/lp/code/templates/branch-index.pt (+34/-17)
lib/lp/code/templates/branch-information.pt (+9/-4)
lib/lp/code/templates/branch-listing.pt (+5/-173)
lib/lp/code/templates/branch-macros.pt (+29/-31)
lib/lp/code/templates/branch-messages.pt (+6/-0)
lib/lp/code/templates/branch-metadata.pt (+11/-2)
lib/lp/code/templates/branch-pending-merges.pt (+3/-4)
lib/lp/code/templates/branch-portlet-subscribers-content.pt (+5/-4)
lib/lp/code/templates/branch-portlet-subscribers.pt (+7/-34)
lib/lp/code/templates/branch-register-merge.pt (+60/-0)
lib/lp/code/templates/branch-related-bugs-specs.pt (+2/-2)
lib/lp/code/templates/branchmergeproposal-diff.pt (+33/-0)
lib/lp/code/templates/branchmergeproposal-generic-listing.pt (+3/-3)
lib/lp/code/templates/branchmergeproposal-index.pt (+148/-45)
lib/lp/code/templates/branchmergeproposal-link-summary.pt (+2/-1)
lib/lp/code/templates/branchmergeproposal-macros.pt (+5/-1)
lib/lp/code/templates/branchmergeproposal-pagelet-summary.pt (+43/-33)
lib/lp/code/templates/branchmergeproposal-resubmit.pt (+3/-2)
lib/lp/code/templates/branchmergeproposal-summary-fragment.pt (+11/-0)
lib/lp/code/templates/branchmergeproposal-vote-summary.pt (+52/-0)
lib/lp/code/templates/codeimport-list.pt (+24/-4)
lib/lp/code/templates/codeimport-macros.pt (+2/-4)
lib/lp/code/templates/codeimport-new.pt (+23/-2)
lib/lp/code/templates/codereviewcomment-body.pt (+2/-5)
lib/lp/code/templates/codereviewcomment-fragment.pt (+2/-0)
lib/lp/code/templates/codereviewcomment-header.pt (+5/-1)
lib/lp/code/templates/codereviewnewrevisions-footer.pt (+11/-0)
lib/lp/code/templates/codereviewnewrevisions-header.pt (+10/-0)
lib/lp/code/templates/person-portlet-teambranches.pt (+3/-4)
lib/lp/code/templates/product-branch-summary.pt (+2/-2)
lib/lp/code/templates/sourcepackagerecipe-index.pt (+109/-0)
lib/lp/code/templates/sourcepackagerecipe-listing.pt (+55/-0)
lib/lp/code/templates/sourcepackagerecipe-request-builds.pt (+27/-0)
lib/lp/code/templates/sources-list.pt (+2/-2)
lib/lp/code/tests/helpers.py (+89/-10)
lib/lp/code/tests/test_branch.py (+273/-33)
lib/lp/code/tests/test_branchmergeproposal.py (+76/-0)
lib/lp/code/tests/test_directbranchcommit.py (+4/-23)
lib/lp/code/tests/test_doc.py (+2/-3)
lib/lp/code/tests/test_recipebuilder.py (+220/-0)
lib/lp/code/tests/test_sourcepackagerecipebuild.py (+125/-0)
lib/lp/code/windmill/test_branch_sparks.py (+0/-29)
lib/lp/code/windmill/tests/test_branch_bugspeclinks.py (+33/-32)
lib/lp/code/windmill/tests/test_branch_popupdiff.py (+143/-0)
lib/lp/code/windmill/tests/test_branch_status.py (+70/-0)
lib/lp/code/windmill/tests/test_branch_subscriptions.py (+78/-68)
lib/lp/code/windmill/tests/test_branchmergeproposal_commitmessage.py (+126/-0)
lib/lp/code/windmill/tests/test_branchmergeproposal_review.py (+116/-28)
lib/lp/code/windmill/tests/test_productseries_setbranch.py (+58/-0)
lib/lp/code/windmill/tests/test_yuitests.py (+21/-0)
lib/lp/code/xmlrpc/branch.py (+13/-20)
lib/lp/code/xmlrpc/codehosting.py (+121/-184)
lib/lp/code/xmlrpc/codeimportscheduler.py (+69/-7)
lib/lp/code/xmlrpc/tests/test_branch.py (+76/-8)
lib/lp/code/xmlrpc/tests/test_codehosting.py (+275/-489)
lib/lp/code/xmlrpc/tests/test_codeimportscheduler.py (+140/-0)
lib/lp/codehosting/__init__.py (+17/-5)
lib/lp/codehosting/branchdistro.py (+351/-0)
lib/lp/codehosting/bzrutils.py (+77/-29)
lib/lp/codehosting/codeimport/dispatcher.py (+33/-6)
lib/lp/codehosting/codeimport/tests/servers.py (+68/-22)
lib/lp/codehosting/codeimport/tests/test_dispatcher.py (+83/-50)
lib/lp/codehosting/codeimport/tests/test_foreigntree.py (+4/-4)
lib/lp/codehosting/codeimport/tests/test_worker.py (+402/-123)
lib/lp/codehosting/codeimport/tests/test_workermonitor.py (+365/-200)
lib/lp/codehosting/codeimport/worker.py (+281/-107)
lib/lp/codehosting/codeimport/workermonitor.py (+78/-123)
lib/lp/codehosting/inmemory.py (+98/-107)
lib/lp/codehosting/puller/scheduler.py (+39/-49)
lib/lp/codehosting/puller/tests/__init__.py (+52/-1)
lib/lp/codehosting/puller/tests/test_acceptance.py (+92/-212)
lib/lp/codehosting/puller/tests/test_errors.py (+1/-9)
lib/lp/codehosting/puller/tests/test_scheduler.py (+83/-104)
lib/lp/codehosting/puller/tests/test_worker.py (+41/-114)
lib/lp/codehosting/puller/tests/test_worker_formats.py (+2/-60)
lib/lp/codehosting/puller/worker.py (+52/-73)
lib/lp/codehosting/rewrite.py (+14/-19)
lib/lp/codehosting/scanner/branch_scanner.py (+0/-145)
lib/lp/codehosting/scanner/buglinks.py (+2/-4)
lib/lp/codehosting/scanner/bzrsync.py (+18/-92)
lib/lp/codehosting/scanner/email.py (+14/-13)
lib/lp/codehosting/scanner/events.py (+31/-5)
lib/lp/codehosting/scanner/mergedetection.py (+40/-10)
lib/lp/codehosting/scanner/tests/test_acceptance.py (+0/-132)
lib/lp/codehosting/scanner/tests/test_branchscanner.py (+0/-268)
lib/lp/codehosting/scanner/tests/test_buglinks.py (+28/-8)
lib/lp/codehosting/scanner/tests/test_bzrsync.py (+27/-119)
lib/lp/codehosting/scanner/tests/test_email.py (+52/-19)
lib/lp/codehosting/scanner/tests/test_formats.py (+0/-123)
lib/lp/codehosting/scanner/tests/test_mergedetection.py (+70/-11)
lib/lp/codehosting/scripts/modifiedbranches.py (+5/-12)
lib/lp/codehosting/scripts/tests/test_modifiedbranches.py (+5/-31)
lib/lp/codehosting/sftp.py (+12/-30)
lib/lp/codehosting/sshserver/daemon.py (+105/-0)
lib/lp/codehosting/sshserver/session.py (+26/-79)
lib/lp/codehosting/sshserver/tests/test_daemon.py (+93/-0)
lib/lp/codehosting/sshserver/tests/test_session.py (+28/-10)
lib/lp/codehosting/tests/helpers.py (+0/-2)
lib/lp/codehosting/tests/servers.py (+3/-3)
lib/lp/codehosting/tests/test_acceptance.py (+135/-148)
lib/lp/codehosting/tests/test_branchdistro.py (+576/-0)
lib/lp/codehosting/tests/test_bzrutils.py (+103/-14)
lib/lp/codehosting/tests/test_jobs.py (+1/-1)
lib/lp/codehosting/tests/test_lpserve.py (+3/-2)
lib/lp/codehosting/tests/test_rewrite.py (+18/-5)
lib/lp/codehosting/tests/test_sftp.py (+57/-8)
lib/lp/codehosting/vfs/__init__.py (+4/-6)
lib/lp/codehosting/vfs/branchfs.py (+301/-280)
lib/lp/codehosting/vfs/branchfsclient.py (+31/-35)
lib/lp/codehosting/vfs/hooks.py (+25/-0)
lib/lp/codehosting/vfs/tests/test_branchfs.py (+258/-103)
lib/lp/codehosting/vfs/tests/test_branchfsclient.py (+38/-55)
lib/lp/codehosting/vfs/tests/test_filesystem.py (+5/-4)
lib/lp/codehosting/vfs/tests/test_hooks.py (+63/-0)
lib/lp/codehosting/vfs/tests/test_transport.py (+4/-8)
lib/lp/codehosting/vfs/transport.py (+12/-32)
lib/lp/coop/answersbugs/stories/question-buglink.txt (+18/-19)
lib/lp/hardwaredb/browser/configure.zcml (+71/-0)
lib/lp/hardwaredb/browser/hwdb.py (+2/-2)
lib/lp/hardwaredb/browser/tests/test_views.py (+39/-0)
lib/lp/hardwaredb/configure.zcml (+190/-0)
lib/lp/hardwaredb/doc/hwdb-access.txt (+5/-5)
lib/lp/hardwaredb/doc/hwdb-device-tables.txt (+3/-3)
lib/lp/hardwaredb/doc/hwdb-submission.txt (+7/-7)
lib/lp/hardwaredb/doc/hwdb.txt (+8/-8)
lib/lp/hardwaredb/model/hwdb.py (+1/-1)
lib/lp/hardwaredb/scripts/hwdbsubmissions.py (+680/-77)
lib/lp/hardwaredb/scripts/tests/test_hwdb_submission_validation.py (+1/-1)
lib/lp/hardwaredb/stories/hwdb/01-submit-data.txt (+2/-0)
lib/lp/hardwaredb/stories/webservice/xx-hwdb.txt (+1/-1)
lib/lp/hardwaredb/tests/test_doc.py (+36/-0)
lib/lp/poppy/daemon.py (+62/-0)
lib/lp/poppy/filesystem.py (+0/-1)
lib/lp/poppy/hooks.py (+6/-8)
lib/lp/poppy/server.py (+4/-41)
lib/lp/poppy/tests/__init__.py (+5/-0)
lib/lp/poppy/tests/filesystem.txt (+11/-4)
lib/lp/poppy/tests/helpers.py (+8/-16)
lib/lp/poppy/tests/test_poppy.py (+17/-22)
lib/lp/registry/browser/__init__.py (+4/-4)
lib/lp/registry/browser/announcement.py (+3/-2)
lib/lp/registry/browser/configure.zcml (+208/-172)
lib/lp/registry/browser/distribution.py (+18/-31)
lib/lp/registry/browser/distributionmirror.py (+23/-15)
lib/lp/registry/browser/distributionsourcepackage.py (+88/-119)
lib/lp/registry/browser/distroseries.py (+103/-80)
lib/lp/registry/browser/featuredproject.py (+1/-1)
lib/lp/registry/browser/karma.py (+3/-3)
lib/lp/registry/browser/mailinglists.py (+13/-4)
lib/lp/registry/browser/mentoringoffer.py (+3/-3)
lib/lp/registry/browser/menu.py (+1/-1)
lib/lp/registry/browser/milestone.py (+39/-16)
lib/lp/registry/browser/peoplemerge.py (+127/-40)
lib/lp/registry/browser/person.py (+311/-287)
lib/lp/registry/browser/personproduct.py (+1/-1)
lib/lp/registry/browser/pillar.py (+35/-17)
lib/lp/registry/browser/poll.py (+6/-0)
lib/lp/registry/browser/product.py (+494/-214)
lib/lp/registry/browser/productrelease.py (+1/-6)
lib/lp/registry/browser/productseries.py (+671/-152)
lib/lp/registry/browser/project.py (+52/-50)
lib/lp/registry/browser/sourcepackage.py (+269/-37)
lib/lp/registry/browser/structuralsubscription.py (+44/-7)
lib/lp/registry/browser/team.py (+28/-20)
lib/lp/registry/browser/teammembership.py (+14/-11)
lib/lp/registry/browser/tests/announcement-views.txt (+19/-0)
lib/lp/registry/browser/tests/browser-views.txt (+4/-4)
lib/lp/registry/browser/tests/coc-views.txt (+67/-0)
lib/lp/registry/browser/tests/distributionmirror-views.txt (+51/-7)
lib/lp/registry/browser/tests/distributionsourcepackage-views.txt (+41/-12)
lib/lp/registry/browser/tests/distroseries-views.txt (+3/-0)
lib/lp/registry/browser/tests/gpg-views.txt (+3/-3)
lib/lp/registry/browser/tests/karmaaction-views.txt (+1/-1)
lib/lp/registry/browser/tests/mailinglist-message-views.txt (+74/-0)
lib/lp/registry/browser/tests/mailinglist-views.txt (+10/-8)
lib/lp/registry/browser/tests/milestone-views.txt (+32/-6)
lib/lp/registry/browser/tests/packaging-views.txt (+354/-0)
lib/lp/registry/browser/tests/peoplemerge-views.txt (+179/-3)
lib/lp/registry/browser/tests/person-admin-views.txt (+1/-2)
lib/lp/registry/browser/tests/person-karma-views.txt (+1/-1)
lib/lp/registry/browser/tests/person-views.txt (+159/-54)
lib/lp/registry/browser/tests/pillar-views.txt (+80/-26)
lib/lp/registry/browser/tests/poll-views.txt (+134/-0)
lib/lp/registry/browser/tests/product-edit-people-view.txt (+6/-6)
lib/lp/registry/browser/tests/product-files-views.txt (+70/-0)
lib/lp/registry/browser/tests/product-menus.txt (+10/-35)
lib/lp/registry/browser/tests/product-portlet-packages-view.txt (+353/-0)
lib/lp/registry/browser/tests/product-views.txt (+78/-8)
lib/lp/registry/browser/tests/productrelease-views.txt (+1/-7)
lib/lp/registry/browser/tests/productseries-setbranch-view.txt (+417/-0)
lib/lp/registry/browser/tests/productseries-views.txt (+167/-71)
lib/lp/registry/browser/tests/projectgroupset-views.txt (+3/-3)
lib/lp/registry/browser/tests/sourcepackage-views.txt (+294/-14)
lib/lp/registry/browser/tests/team-views.txt (+102/-10)
lib/lp/registry/browser/tests/teammembership-views.txt (+65/-0)
lib/lp/registry/browser/tests/test_breadcrumbs.py (+129/-0)
lib/lp/registry/browser/tests/test_gpgkey.py (+30/-0)
lib/lp/registry/browser/tests/test_packaging.py (+111/-10)
lib/lp/registry/browser/tests/test_person_view.py (+107/-7)
lib/lp/registry/browser/tests/test_person_webservice.py (+42/-0)
lib/lp/registry/browser/tests/test_sshkey.py (+31/-0)
lib/lp/registry/browser/tests/test_structuralsubscription.py (+1/-1)
lib/lp/registry/browser/tests/test_team.py (+37/-0)
lib/lp/registry/browser/tests/test_views.py (+2/-0)
lib/lp/registry/codesofconduct/1.1.txt (+82/-0)
lib/lp/registry/configure.zcml (+231/-42)
lib/lp/registry/doc/announcement.txt (+5/-5)
lib/lp/registry/doc/cache-country-mirrors.txt (+6/-1)
lib/lp/registry/doc/commercialsubscription.txt (+14/-6)
lib/lp/registry/doc/distribution-mirror.txt (+227/-33)
lib/lp/registry/doc/distribution-sourcepackage.txt (+48/-34)
lib/lp/registry/doc/distribution.txt (+38/-3)
lib/lp/registry/doc/distroseries.txt (+145/-79)
lib/lp/registry/doc/featuredproject.txt (+3/-3)
lib/lp/registry/doc/gpg-signatures.txt (+14/-13)
lib/lp/registry/doc/launchpadlib/project-registry.txt.disabled (+374/-0)
lib/lp/registry/doc/mailinglist-email-notification.txt (+8/-5)
lib/lp/registry/doc/mailinglist-subscriptions.txt (+4/-3)
lib/lp/registry/doc/mailinglist-xmlrpc.txt (+36/-69)
lib/lp/registry/doc/mailinglists.txt (+139/-332)
lib/lp/registry/doc/mentoringoffer.txt (+4/-4)
lib/lp/registry/doc/message-holds-xmlrpc.txt (+9/-9)
lib/lp/registry/doc/message-holds.txt (+0/-52)
lib/lp/registry/doc/milestone.txt (+48/-5)
lib/lp/registry/doc/person-account.txt (+8/-18)
lib/lp/registry/doc/person-karma.txt (+13/-10)
lib/lp/registry/doc/person-merge.txt (+35/-7)
lib/lp/registry/doc/person-notification.txt (+3/-4)
lib/lp/registry/doc/person.txt (+188/-85)
lib/lp/registry/doc/personlocation.txt (+15/-53)
lib/lp/registry/doc/pillar.txt (+16/-12)
lib/lp/registry/doc/private-team-roles.txt (+4/-3)
lib/lp/registry/doc/private-team-visibility.txt (+93/-0)
lib/lp/registry/doc/product.txt (+54/-21)
lib/lp/registry/doc/productrelease-file-download.txt (+4/-4)
lib/lp/registry/doc/productseries.txt (+33/-57)
lib/lp/registry/doc/project.txt (+45/-35)
lib/lp/registry/doc/sourceforge-remote-products.txt (+1/-1)
lib/lp/registry/doc/sourcepackage.txt (+147/-147)
lib/lp/registry/doc/standing.txt (+2/-2)
lib/lp/registry/doc/structural-subscriptions.txt (+4/-4)
lib/lp/registry/doc/teammembership-email-notification.txt (+49/-9)
lib/lp/registry/doc/teammembership.txt (+137/-58)
lib/lp/registry/doc/vocabularies.txt (+115/-94)
lib/lp/registry/feed/announcement.py (+5/-4)
lib/lp/registry/help/home-page-staging-help.html (+5/-5)
lib/lp/registry/help/import-pgp-key.html (+5/-5)
lib/lp/registry/help/openid.html (+5/-5)
lib/lp/registry/help/openpgp-keys.html (+7/-7)
lib/lp/registry/help/pgp-key-clearsign.html (+5/-5)
lib/lp/registry/help/verify-downloads.html (+5/-5)
lib/lp/registry/interfaces/distribution.py (+77/-53)
lib/lp/registry/interfaces/distributionmirror.py (+147/-61)
lib/lp/registry/interfaces/distributionsourcepackage.py (+6/-5)
lib/lp/registry/interfaces/distroseries.py (+95/-161)
lib/lp/registry/interfaces/gpg.py (+17/-5)
lib/lp/registry/interfaces/mailinglist.py (+11/-38)
lib/lp/registry/interfaces/milestone.py (+22/-12)
lib/lp/registry/interfaces/packaging.py (+20/-12)
lib/lp/registry/interfaces/person.py (+234/-185)
lib/lp/registry/interfaces/pillar.py (+1/-1)
lib/lp/registry/interfaces/pocket.py (+0/-2)
lib/lp/registry/interfaces/product.py (+69/-49)
lib/lp/registry/interfaces/productrelease.py (+2/-2)
lib/lp/registry/interfaces/productseries.py (+26/-45)
lib/lp/registry/interfaces/projectgroup.py (+43/-43)
lib/lp/registry/interfaces/series.py (+130/-0)
lib/lp/registry/interfaces/sourcepackage.py (+63/-16)
lib/lp/registry/interfaces/ssh.py (+10/-5)
lib/lp/registry/interfaces/structuralsubscription.py (+7/-1)
lib/lp/registry/interfaces/teammembership.py (+20/-4)
lib/lp/registry/model/announcement.py (+7/-6)
lib/lp/registry/model/codeofconduct.py (+1/-1)
lib/lp/registry/model/distribution.py (+176/-114)
lib/lp/registry/model/distributionmirror.py (+137/-45)
lib/lp/registry/model/distributionsourcepackage.py (+108/-30)
lib/lp/registry/model/distroseries.py (+328/-134)
lib/lp/registry/model/gpgkey.py (+18/-0)
lib/lp/registry/model/karma.py (+11/-10)
lib/lp/registry/model/mailinglist.py (+17/-35)
lib/lp/registry/model/mentoringoffer.py (+3/-5)
lib/lp/registry/model/milestone.py (+17/-5)
lib/lp/registry/model/packaging.py (+19/-9)
lib/lp/registry/model/person.py (+160/-103)
lib/lp/registry/model/personnotification.py (+1/-1)
lib/lp/registry/model/personproduct.py (+1/-1)
lib/lp/registry/model/pillar.py (+9/-8)
lib/lp/registry/model/product.py (+102/-52)
lib/lp/registry/model/productrelease.py (+14/-4)
lib/lp/registry/model/productseries.py (+67/-43)
lib/lp/registry/model/projectgroup.py (+75/-67)
lib/lp/registry/model/series.py (+53/-0)
lib/lp/registry/model/sourcepackage.py (+72/-51)
lib/lp/registry/model/sourcepackagename.py (+3/-0)
lib/lp/registry/model/structuralsubscription.py (+31/-11)
lib/lp/registry/model/teammembership.py (+17/-8)
lib/lp/registry/scripts/distributionmirror_prober.py (+30/-9)
lib/lp/registry/scripts/listteammembers.py (+21/-12)
lib/lp/registry/scripts/personnotification.py (+82/-0)
lib/lp/registry/scripts/productreleasefinder/finder.py (+10/-18)
lib/lp/registry/stories/announcements/xx-announcements.txt (+20/-6)
lib/lp/registry/stories/distribution/xx-distribution-all-packages.txt (+0/-40)
lib/lp/registry/stories/distribution/xx-distribution-packages.txt (+47/-24)
lib/lp/registry/stories/distributionmirror/xx-distribution-countrymirrors.txt (+1/-1)
lib/lp/registry/stories/distributionmirror/xx-distribution-mirrors.txt (+15/-11)
lib/lp/registry/stories/distributionmirror/xx-reassign-distributionmirror.txt (+3/-3)
lib/lp/registry/stories/distroseries/xx-distroseries-index.txt (+26/-5)
lib/lp/registry/stories/distroseries/xx-show-distroseries-packaging.txt (+119/-13)
lib/lp/registry/stories/foaf/xx-changepassword.txt (+0/-62)
lib/lp/registry/stories/foaf/xx-createaccount.txt (+0/-166)
lib/lp/registry/stories/foaf/xx-login.txt (+0/-83)
lib/lp/registry/stories/foaf/xx-person-claim.txt (+0/-148)
lib/lp/registry/stories/foaf/xx-reg-with-existing-email.txt (+0/-182)
lib/lp/registry/stories/foaf/xx-resetpassword.txt (+0/-338)
lib/lp/registry/stories/gpg-coc/02-signcoc.txt (+4/-4)
lib/lp/registry/stories/gpg-coc/99-coc-presentation.txt (+3/-3)
lib/lp/registry/stories/gpg-coc/reformatted_11_coc.asc (+84/-81)
lib/lp/registry/stories/location/personlocation-edit.txt (+27/-59)
lib/lp/registry/stories/location/personlocation.txt (+13/-18)
lib/lp/registry/stories/location/team-map.txt (+25/-0)
lib/lp/registry/stories/mailinglists/admin-approval.txt (+0/-221)
lib/lp/registry/stories/mailinglists/lifecycle.txt (+40/-111)
lib/lp/registry/stories/mailinglists/moderation.txt (+3/-5)
lib/lp/registry/stories/mailinglists/subscriptions.txt (+40/-30)
lib/lp/registry/stories/milestone/object-milestones.txt (+31/-17)
lib/lp/registry/stories/milestone/xx-milestone-add-and-edit.txt (+11/-2)
lib/lp/registry/stories/object/xx-object-branding.txt (+3/-5)
lib/lp/registry/stories/packaging/xx-distributionsourcepackage-packaging-concurrent-deletion.txt (+11/-15)
lib/lp/registry/stories/packaging/xx-distributionsourcepackage-packaging.txt (+14/-53)
lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt (+54/-126)
lib/lp/registry/stories/person/merge-people.txt (+63/-6)
lib/lp/registry/stories/person/xx-add-sshkey.txt (+4/-4)
lib/lp/registry/stories/person/xx-admin-person-review.txt (+61/-3)
lib/lp/registry/stories/person/xx-deactivate-account.txt (+8/-44)
lib/lp/registry/stories/person/xx-person-bugs.txt (+20/-0)
lib/lp/registry/stories/person/xx-person-claim-merge.txt (+17/-2)
lib/lp/registry/stories/person/xx-person-edit-jabber-ids.txt (+0/-1)
lib/lp/registry/stories/person/xx-person-edit-wikis.txt (+2/-1)
lib/lp/registry/stories/person/xx-person-edit.txt (+7/-0)
lib/lp/registry/stories/person/xx-person-home.txt (+14/-2)
lib/lp/registry/stories/person/xx-person-karma.txt (+1/-1)
lib/lp/registry/stories/person/xx-person-working-on.txt (+3/-2)
lib/lp/registry/stories/person/xx-user-to-user.txt (+11/-8)
lib/lp/registry/stories/pillar/xx-pillar-deactivation.txt (+15/-8)
lib/lp/registry/stories/pillar/xx-pillar-sprints.txt (+1/-1)
lib/lp/registry/stories/product/xx-launchpad-project-search.txt (+36/-16)
lib/lp/registry/stories/product/xx-product-add.txt (+13/-2)
lib/lp/registry/stories/product/xx-product-development-focus.txt (+175/-0)
lib/lp/registry/stories/product/xx-product-driver.txt (+9/-11)
lib/lp/registry/stories/product/xx-product-edit.txt (+24/-20)
lib/lp/registry/stories/product/xx-product-files.txt (+17/-15)
lib/lp/registry/stories/product/xx-product-index.txt (+47/-2)
lib/lp/registry/stories/product/xx-product-launchpad-usage.txt (+40/-64)
lib/lp/registry/stories/product/xx-product-package-pages.txt (+51/-22)
lib/lp/registry/stories/product/xx-productset.txt (+1/-1)
lib/lp/registry/stories/productrelease/xx-productrelease-basics.txt (+3/-9)
lib/lp/registry/stories/productrelease/xx-productrelease-delete.txt (+3/-2)
lib/lp/registry/stories/productrelease/xx-productrelease-view.txt (+7/-8)
lib/lp/registry/stories/productseries/xx-productseries-delete.txt (+27/-5)
lib/lp/registry/stories/productseries/xx-productseries-index.txt (+14/-7)
lib/lp/registry/stories/productseries/xx-productseries-series.txt (+2/-2)
lib/lp/registry/stories/productseries/xx-productseries-set-branch.txt (+147/-0)
lib/lp/registry/stories/project/xx-project-add-product.txt (+2/-2)
lib/lp/registry/stories/project/xx-project-driver.txt (+2/-3)
lib/lp/registry/stories/project/xx-project-edit.txt (+2/-2)
lib/lp/registry/stories/project/xx-project-index.txt (+9/-12)
lib/lp/registry/stories/standalone/xx-new-profile.txt (+0/-110)
lib/lp/registry/stories/standalone/xx-team-restricted.txt (+0/-137)
lib/lp/registry/stories/team-polls/create-polls.txt (+4/-4)
lib/lp/registry/stories/team-polls/xx-poll-results.txt (+3/-2)
lib/lp/registry/stories/team/xx-adminteammerge.txt (+43/-34)
lib/lp/registry/stories/team/xx-team-add-my-teams.txt (+40/-38)
lib/lp/registry/stories/team/xx-team-claim.txt (+4/-6)
lib/lp/registry/stories/team/xx-team-edit.txt (+0/-1)
lib/lp/registry/stories/team/xx-team-home.txt (+38/-22)
lib/lp/registry/stories/team/xx-team-membership.txt (+31/-6)
lib/lp/registry/stories/teammembership/20-managing-members.txt (+14/-5)
lib/lp/registry/stories/teammembership/private-team.txt (+3/-5)
lib/lp/registry/stories/teammembership/xx-add-member.txt (+16/-14)
lib/lp/registry/stories/teammembership/xx-expire-subscription.txt (+1/-1)
lib/lp/registry/stories/teammembership/xx-member-renewed-membership.txt (+19/-1)
lib/lp/registry/stories/teammembership/xx-private-membership.txt (+16/-16)
lib/lp/registry/stories/teammembership/xx-renew-subscription.txt (+2/-2)
lib/lp/registry/stories/vouchers/xx-voucher-redemption.txt (+2/-1)
lib/lp/registry/stories/webservice/xx-distribution-mirror.txt (+260/-0)
lib/lp/registry/stories/webservice/xx-distribution.txt (+104/-0)
lib/lp/registry/stories/webservice/xx-distroseries.txt (+12/-1)
lib/lp/registry/stories/webservice/xx-people.txt (+6/-0)
lib/lp/registry/stories/webservice/xx-person.txt (+162/-1)
lib/lp/registry/stories/webservice/xx-private-membership.txt (+4/-3)
lib/lp/registry/stories/webservice/xx-project-registry.txt (+84/-21)
lib/lp/registry/stories/webservice/xx-source-package.txt (+23/-5)
lib/lp/registry/stories/webservice/xx-structuralsubscription.txt (+1/-1)
lib/lp/registry/templates/codeofconduct-list.pt (+17/-14)
lib/lp/registry/templates/distribution-allpackages.pt (+0/-25)
lib/lp/registry/templates/distribution-portlet-lifecycle.pt (+0/-29)
lib/lp/registry/templates/distribution-portlet-series.pt (+0/-22)
lib/lp/registry/templates/distribution-series-and-milestones.pt (+3/-3)
lib/lp/registry/templates/distribution-series.pt (+5/-6)
lib/lp/registry/templates/distributionmirror-index.pt (+65/-56)
lib/lp/registry/templates/distributionmirror-macros.pt (+19/-16)
lib/lp/registry/templates/distributionsourcepackage-index.pt (+24/-55)
lib/lp/registry/templates/distributionsourcepackage-portlet-details.pt (+0/-26)
lib/lp/registry/templates/distributionsourcepackage-portlet-releases.pt (+0/-18)
lib/lp/registry/templates/distroseries-details.pt (+3/-3)
lib/lp/registry/templates/distroseries-index.pt (+5/-9)
lib/lp/registry/templates/distroseries-needs-packaging.pt (+91/-0)
lib/lp/registry/templates/distroseries-packaging.pt (+64/-42)
lib/lp/registry/templates/distroseries-portlet-lifecycle.pt (+0/-39)
lib/lp/registry/templates/distroseries-portlet-packaging.pt (+76/-0)
lib/lp/registry/templates/milestone-index.pt (+21/-13)
lib/lp/registry/templates/milestone-portlet-details.pt (+0/-37)
lib/lp/registry/templates/object-milestones.pt (+10/-1)
lib/lp/registry/templates/object-portlet-milestones.pt (+0/-25)
lib/lp/registry/templates/object-portlet-summary.pt (+0/-14)
lib/lp/registry/templates/object-timeline-graph.pt (+11/-8)
lib/lp/registry/templates/people-newperson.pt (+0/-29)
lib/lp/registry/templates/people-requestmerge-multiple.pt (+95/-52)
lib/lp/registry/templates/people-requestmerge.pt (+5/-6)
lib/lp/registry/templates/person-deactivate-account.pt (+0/-5)
lib/lp/registry/templates/person-edit.pt (+3/-21)
lib/lp/registry/templates/person-editpgpkeys.pt (+16/-34)
lib/lp/registry/templates/person-editsshkeys.pt (+0/-2)
lib/lp/registry/templates/person-index.pt (+19/-29)
lib/lp/registry/templates/person-macros.pt (+2/-2)
lib/lp/registry/templates/person-portlet-contact-details.pt (+8/-3)
lib/lp/registry/templates/person-portlet-contributions.pt (+2/-3)
lib/lp/registry/templates/person-portlet-currentfocus.pt (+2/-2)
lib/lp/registry/templates/person-portlet-emails.pt (+0/-46)
lib/lp/registry/templates/person-portlet-map.pt (+10/-10)
lib/lp/registry/templates/person-rdf-contents.pt (+1/-1)
lib/lp/registry/templates/person-related-software-navlinks.pt (+20/-11)
lib/lp/registry/templates/person-review.pt (+2/-1)
lib/lp/registry/templates/pillar-involvement-portlet.pt (+30/-3)
lib/lp/registry/templates/product-admin.pt (+0/-17)
lib/lp/registry/templates/product-distros.pt (+0/-83)
lib/lp/registry/templates/product-edit-people.pt (+0/-18)
lib/lp/registry/templates/product-edit.pt (+0/-23)
lib/lp/registry/templates/product-files.pt (+130/-87)
lib/lp/registry/templates/product-index.pt (+41/-9)
lib/lp/registry/templates/product-new.pt (+15/-15)
lib/lp/registry/templates/product-packages.pt (+108/-43)
lib/lp/registry/templates/product-portlet-packages.pt (+49/-22)
lib/lp/registry/templates/product-portlet-releases.pt (+0/-23)
lib/lp/registry/templates/product-portlet-series.pt (+0/-22)
lib/lp/registry/templates/product-rdf.pt (+1/-1)
lib/lp/registry/templates/product-review-license.pt (+45/-45)
lib/lp/registry/templates/productrelease-add-from-series.pt (+4/-4)
lib/lp/registry/templates/productrelease-portlet-data.pt (+6/-8)
lib/lp/registry/templates/productrelease-portlet-details.pt (+0/-38)
lib/lp/registry/templates/productreleasefile-macros.pt (+1/-1)
lib/lp/registry/templates/products-index.pt (+16/-12)
lib/lp/registry/templates/products-portlet-details.pt (+0/-19)
lib/lp/registry/templates/productseries-codesummary.pt (+5/-5)
lib/lp/registry/templates/productseries-delete.pt (+15/-4)
lib/lp/registry/templates/productseries-index.pt (+19/-52)
lib/lp/registry/templates/productseries-linkbranch.pt (+38/-2)
lib/lp/registry/templates/productseries-milestone-table-row.pt (+9/-6)
lib/lp/registry/templates/productseries-packaging.pt (+0/-43)
lib/lp/registry/templates/productseries-portlet-details.pt (+0/-27)
lib/lp/registry/templates/productseries-portlet-packages.pt (+39/-21)
lib/lp/registry/templates/productseries-portlet-releases.pt (+0/-29)
lib/lp/registry/templates/productseries-setbranch.pt (+129/-0)
lib/lp/registry/templates/productseries-ubuntupkg.pt (+29/-51)
lib/lp/registry/templates/project-index.pt (+6/-25)
lib/lp/registry/templates/project-portlet-lifecycle.pt (+0/-33)
lib/lp/registry/templates/project-series-portlet-details.pt (+0/-7)
lib/lp/registry/templates/projects-index.pt (+8/-7)
lib/lp/registry/templates/signedcodeofconduct-add.pt (+1/-9)
lib/lp/registry/templates/sourcepackage-edit-packaging.pt (+17/-5)
lib/lp/registry/templates/sourcepackage-index.pt (+8/-53)
lib/lp/registry/templates/sourcepackage-packaging.pt (+0/-62)
lib/lp/registry/templates/sourcepackage-portlet-associations.pt (+64/-0)
lib/lp/registry/templates/sourcepackage-portlet-upstream.pt (+0/-17)
lib/lp/registry/templates/sourcepackage-remove-packaging.pt (+34/-0)
lib/lp/registry/templates/sourcepackage-upstream-connections.pt (+63/-0)
lib/lp/registry/templates/structural-subscriptions-manage.pt (+0/-2)
lib/lp/registry/templates/team-add-my-teams.pt (+2/-0)
lib/lp/registry/templates/team-delete.pt (+30/-0)
lib/lp/registry/templates/team-index.pt (+15/-16)
lib/lp/registry/templates/team-mailinglist.pt (+5/-1)
lib/lp/registry/templates/team-members.pt (+64/-57)
lib/lp/registry/templates/team-mugshots.pt (+26/-11)
lib/lp/registry/templates/team-polls.pt (+2/-2)
lib/lp/registry/templates/team-portlet-mailinglist.pt (+15/-13)
lib/lp/registry/templates/team-portlet-membership.pt (+70/-30)
lib/lp/registry/templates/team-portlet-polls.pt (+4/-4)
lib/lp/registry/templates/teammembership-index.pt (+21/-11)
lib/lp/registry/templates/teammembership-listing-simple.pt (+1/-1)
lib/lp/registry/templates/timeline-macros.pt (+5/-4)
lib/lp/registry/tests/bug-249185.txt (+5/-4)
lib/lp/registry/tests/karma.py (+1/-3)
lib/lp/registry/tests/mailinglists_helper.py (+1/-41)
lib/lp/registry/tests/structural-subscription-target.txt (+1/-1)
lib/lp/registry/tests/test_distribution.py (+30/-2)
lib/lp/registry/tests/test_distributionmirror.py (+10/-20)
lib/lp/registry/tests/test_distributionmirror_prober.py (+51/-3)
lib/lp/registry/tests/test_distroseries.py (+137/-5)
lib/lp/registry/tests/test_doc.py (+9/-3)
lib/lp/registry/tests/test_doc_product.py (+1/-1)
lib/lp/registry/tests/test_doc_project.py (+1/-1)
lib/lp/registry/tests/test_karmacache_updater.py (+2/-1)
lib/lp/registry/tests/test_listteammembers.py (+36/-9)
lib/lp/registry/tests/test_milestone_vocabularies.py (+2/-2)
lib/lp/registry/tests/test_mlists.py (+0/-1)
lib/lp/registry/tests/test_packaging.py (+95/-10)
lib/lp/registry/tests/test_person.py (+245/-18)
lib/lp/registry/tests/test_personnotification.py (+78/-0)
lib/lp/registry/tests/test_personproduct.py (+1/-1)
lib/lp/registry/tests/test_personset.py (+59/-21)
lib/lp/registry/tests/test_pillarname_triggers.py (+4/-3)
lib/lp/registry/tests/test_prf_finder.py (+57/-38)
lib/lp/registry/tests/test_prf_walker.py (+3/-0)
lib/lp/registry/tests/test_product.py (+60/-1)
lib/lp/registry/tests/test_productseries.py (+275/-0)
lib/lp/registry/tests/test_productseries_vocabularies.py (+82/-0)
lib/lp/registry/tests/test_project.py (+104/-0)
lib/lp/registry/tests/test_project_milestone.py (+8/-7)
lib/lp/registry/tests/test_sourcepackage.py (+135/-3)
lib/lp/registry/tests/test_structuralsubscriptiontarget.py (+5/-3)
lib/lp/registry/tests/test_team.py (+86/-0)
lib/lp/registry/tests/test_teammembership.py (+12/-14)
lib/lp/registry/vocabularies.py (+71/-63)
lib/lp/registry/vocabularies.zcml (+308/-99)
lib/lp/registry/windmill/testing.py (+18/-0)
lib/lp/registry/windmill/tests/test_add_milestone.py (+86/-89)
lib/lp/registry/windmill/tests/test_datetime_picker.py (+66/-52)
lib/lp/registry/windmill/tests/test_person_picker.py (+50/-0)
lib/lp/registry/windmill/tests/test_plusnew_step1.py (+62/-42)
lib/lp/registry/windmill/tests/test_plusnew_step2.py (+87/-62)
lib/lp/registry/windmill/tests/test_product.py (+43/-21)
lib/lp/registry/windmill/tests/test_product_edit_people.py (+38/-17)
lib/lp/registry/windmill/tests/test_project_licenses.py (+141/-125)
lib/lp/registry/windmill/tests/test_team_index.py (+70/-0)
lib/lp/registry/windmill/tests/test_timeline_graph.py (+76/-62)
lib/lp/registry/windmill/tests/test_yuitests.py (+21/-0)
lib/lp/scripts/helpers.py (+57/-0)
lib/lp/scripts/utilities/apiindex.py (+0/-21)
lib/lp/scripts/utilities/importfascist.py (+71/-32)
lib/lp/scripts/utilities/jssize.py (+21/-0)
lib/lp/scripts/utilities/pageperformancereport.py (+387/-0)
lib/lp/scripts/utilities/sanitizedb.py (+194/-75)
lib/lp/scripts/utilities/tests/test_sanitizedb.py (+1/-0)
lib/lp/services/apachelogparser/base.py (+25/-6)
lib/lp/services/apachelogparser/tests/test_apachelogparser.py (+27/-1)
lib/lp/services/browser_helpers.py (+8/-0)
lib/lp/services/comments/interfaces/conversation.py (+4/-1)
lib/lp/services/comments/templates/comment.pt (+1/-1)
lib/lp/services/database/configure.zcml (+4/-2)
lib/lp/services/database/prejoin.py (+9/-11)
lib/lp/services/database/tests/test_prejoin.py (+34/-26)
lib/lp/services/doc/limitedlist.txt (+124/-0)
lib/lp/services/doc/sprites.txt (+185/-0)
lib/lp/services/inlinehelp/javascript/inlinehelp.js (+1/-1)
lib/lp/services/job/interfaces/job.py (+31/-0)
lib/lp/services/job/model/job.py (+24/-1)
lib/lp/services/job/runner.py (+331/-47)
lib/lp/services/job/tests/test_job.py (+86/-5)
lib/lp/services/job/tests/test_runner.py (+214/-6)
lib/lp/services/limitedlist.py (+76/-0)
lib/lp/services/mail/basemailer.py (+1/-1)
lib/lp/services/mail/mailwrapper.py (+16/-4)
lib/lp/services/mail/notificationrecipientset.py (+2/-1)
lib/lp/services/mail/sendmail.py (+36/-7)
lib/lp/services/mail/tests/test_mailbox.py (+2/-4)
lib/lp/services/mailman/doc/contact-address.txt (+2/-2)
lib/lp/services/mailman/doc/create-lists.txt (+11/-48)
lib/lp/services/mailman/doc/deactivate-lists.txt (+4/-2)
lib/lp/services/mailman/doc/modify-lists.txt (+7/-47)
lib/lp/services/mailman/doc/postings.txt (+50/-7)
lib/lp/services/mailman/doc/reactivate-lists.txt (+1/-1)
lib/lp/services/mailman/doc/staging.txt (+6/-4)
lib/lp/services/mailman/testing/helpers.py (+0/-4)
lib/lp/services/memcache/__init__.py (+4/-0)
lib/lp/services/memcache/client.py (+22/-0)
lib/lp/services/memcache/configure.zcml (+20/-0)
lib/lp/services/memcache/doc/tales-cache.txt (+293/-0)
lib/lp/services/memcache/interfaces.py (+13/-0)
lib/lp/services/memcache/tales.py (+322/-0)
lib/lp/services/memcache/tests/__init__.py (+4/-0)
lib/lp/services/memcache/tests/test_doc.py (+71/-0)
lib/lp/services/memcache/tests/test_memcache_client.py (+42/-0)
lib/lp/services/mime.py (+34/-0)
lib/lp/services/openid/browser/configure.zcml (+0/-59)
lib/lp/services/openid/browser/openidrpconfig.py (+0/-106)
lib/lp/services/openid/configure.zcml (+0/-18)
lib/lp/services/openid/doc/openid-rp-config.txt (+0/-163)
lib/lp/services/openid/interfaces/openidrpconfig.py (+0/-120)
lib/lp/services/openid/model/openidrpconfig.py (+0/-111)
lib/lp/services/openid/stories/rpconfig-admin.txt (+0/-190)
lib/lp/services/openid/templates/openidrpconfig-add.pt (+0/-24)
lib/lp/services/openid/templates/openidrpconfig-edit.pt (+0/-24)
lib/lp/services/openid/templates/openidrpconfigset-index.pt (+0/-35)
lib/lp/services/osutils.py (+11/-1)
lib/lp/services/scripts/base.py (+3/-13)
lib/lp/services/scripts/doc/profile.txt (+2/-2)
lib/lp/services/scripts/tests/__init__.py (+2/-0)
lib/lp/services/scripts/tests/test_all_scripts.py (+4/-2)
lib/lp/services/spriteutils.py (+252/-0)
lib/lp/services/sshserver/__init__.py (+8/-0)
lib/lp/services/sshserver/accesslog.py (+41/-203)
lib/lp/services/sshserver/auth.py (+28/-59)
lib/lp/services/sshserver/events.py (+144/-0)
lib/lp/services/sshserver/service.py (+77/-59)
lib/lp/services/sshserver/session.py (+79/-0)
lib/lp/services/sshserver/sftp.py (+35/-0)
lib/lp/services/sshserver/tests/__init__.py (+8/-0)
lib/lp/services/sshserver/tests/keys/ssh_host_key_rsa (+15/-0)
lib/lp/services/sshserver/tests/keys/ssh_host_key_rsa.pub (+1/-0)
lib/lp/services/sshserver/tests/test_accesslog.py (+72/-151)
lib/lp/services/sshserver/tests/test_auth.py (+22/-104)
lib/lp/services/sshserver/tests/test_events.py (+91/-0)
lib/lp/services/testing/__init__.py (+48/-31)
lib/lp/services/tests/test_doc.py (+27/-0)
lib/lp/services/tests/test_mime.py (+47/-0)
lib/lp/services/tests/test_utils.py (+71/-0)
lib/lp/services/tests/test_vocabularies.py (+37/-0)
lib/lp/services/tests/testfiles/template.css (+20/-0)
lib/lp/services/twistedsupport/processmonitor.py (+69/-0)
lib/lp/services/twistedsupport/task.py (+88/-20)
lib/lp/services/twistedsupport/tests/test_loggingsupport.py (+3/-3)
lib/lp/services/twistedsupport/tests/test_processmonitor.py (+2/-2)
lib/lp/services/twistedsupport/tests/test_task.py (+8/-15)
lib/lp/services/twistedsupport/tests/test_twistedsupport.py (+2/-2)
lib/lp/services/twistedsupport/tests/test_xmlrpc.py (+90/-0)
lib/lp/services/twistedsupport/xmlrpc.py (+27/-0)
lib/lp/services/utils.py (+143/-0)
lib/lp/services/worlddata/browser/configure.zcml (+28/-0)
lib/lp/services/worlddata/browser/country.py (+10/-0)
lib/lp/services/worlddata/configure.zcml (+2/-0)
lib/lp/services/worlddata/doc/language.txt (+60/-3)
lib/lp/services/worlddata/doc/vocabularies.txt (+1/-1)
lib/lp/services/worlddata/interfaces/country.py (+43/-15)
lib/lp/services/worlddata/interfaces/language.py (+69/-35)
lib/lp/services/worlddata/javascript/languages.js (+66/-0)
lib/lp/services/worlddata/model/country.py (+12/-0)
lib/lp/services/worlddata/model/language.py (+40/-12)
lib/lp/services/worlddata/stories/webservice/xx-country.txt (+72/-0)
lib/lp/services/worlddata/stories/webservice/xx-language.txt (+67/-0)
lib/lp/services/worlddata/tests/test_doc.py (+12/-1)
lib/lp/services/worlddata/tests/test_language.py (+21/-0)
lib/lp/services/worlddata/vocabularies.zcml (+5/-2)
lib/lp/services/xmlrpc.py (+40/-0)
lib/lp/soyuz/adapters/archivedependencies.py (+61/-35)
lib/lp/soyuz/browser/archive.py (+224/-62)
lib/lp/soyuz/browser/archivepermission.py (+3/-1)
lib/lp/soyuz/browser/archivesubscription.py (+23/-10)
lib/lp/soyuz/browser/build.py (+67/-26)
lib/lp/soyuz/browser/builder.py (+8/-13)
lib/lp/soyuz/browser/configure.zcml (+76/-35)
lib/lp/soyuz/browser/distributionsourcepackagerelease.py (+15/-5)
lib/lp/soyuz/browser/distroarchseries.py (+2/-8)
lib/lp/soyuz/browser/distroseries.py (+18/-7)
lib/lp/soyuz/browser/packagesearch.py (+3/-0)
lib/lp/soyuz/browser/packageset.py (+19/-0)
lib/lp/soyuz/browser/publishing.py (+1/-1)
lib/lp/soyuz/browser/queue.py (+12/-1)
lib/lp/soyuz/browser/sourcepackagebuilds.py (+0/-4)
lib/lp/soyuz/browser/sourcepackagerelease.py (+122/-96)
lib/lp/soyuz/browser/tests/archive-views.txt (+89/-79)
lib/lp/soyuz/browser/tests/archivesubscription-views.txt (+26/-25)
lib/lp/soyuz/browser/tests/binarypackagerelease-views.txt (+2/-2)
lib/lp/soyuz/browser/tests/build-views.txt (+88/-3)
lib/lp/soyuz/browser/tests/builder-views.txt (+22/-27)
lib/lp/soyuz/browser/tests/distribution-views.txt (+9/-0)
lib/lp/soyuz/browser/tests/distributionsourcepackagerelease-views.txt (+4/-4)
lib/lp/soyuz/browser/tests/publishing-views.txt (+4/-8)
lib/lp/soyuz/browser/tests/sourcepackage-views.txt (+2/-2)
lib/lp/soyuz/browser/tests/test_archive_admin_view.py (+95/-0)
lib/lp/soyuz/browser/tests/test_breadcrumbs.py (+14/-34)
lib/lp/soyuz/browser/tests/test_queue.py (+191/-0)
lib/lp/soyuz/configure.zcml (+125/-104)
lib/lp/soyuz/doc/archive-deletion.txt (+82/-0)
lib/lp/soyuz/doc/archive-dependencies.txt (+154/-63)
lib/lp/soyuz/doc/archive.txt (+323/-196)
lib/lp/soyuz/doc/archiveauthtoken.txt (+51/-39)
lib/lp/soyuz/doc/archivepermission.txt (+4/-3)
lib/lp/soyuz/doc/archivesubscriber.txt (+58/-34)
lib/lp/soyuz/doc/build-estimated-dispatch-time.txt (+31/-29)
lib/lp/soyuz/doc/build-failedtoupload-workflow.txt (+8/-2)
lib/lp/soyuz/doc/build-notification.txt (+11/-9)
lib/lp/soyuz/doc/build.txt (+159/-114)
lib/lp/soyuz/doc/buildd-dbnotes.txt (+0/-35)
lib/lp/soyuz/doc/buildd-dispatching.txt (+59/-67)
lib/lp/soyuz/doc/buildd-mass-retry.txt (+39/-0)
lib/lp/soyuz/doc/buildd-queuebuilder-lookup.txt (+3/-3)
lib/lp/soyuz/doc/buildd-scoring.txt (+28/-18)
lib/lp/soyuz/doc/buildd-sequencer.txt (+0/-243)
lib/lp/soyuz/doc/buildd-slave.txt (+10/-18)
lib/lp/soyuz/doc/buildd-slavescanner.txt (+307/-363)
lib/lp/soyuz/doc/distribution.txt (+27/-9)
lib/lp/soyuz/doc/distroarchseries.txt (+17/-3)
lib/lp/soyuz/doc/distroarchseriesbinarypackage.txt (+8/-11)
lib/lp/soyuz/doc/distroseries-publishing-lookups.txt (+3/-3)
lib/lp/soyuz/doc/distroseriesqueue-dist-upgrader.txt (+1/-1)
lib/lp/soyuz/doc/distroseriesqueue-translations.txt (+52/-18)
lib/lp/soyuz/doc/distroseriesqueue.txt (+21/-30)
lib/lp/soyuz/doc/gina-multiple-arch.txt (+8/-8)
lib/lp/soyuz/doc/gina.txt (+25/-23)
lib/lp/soyuz/doc/hasbuildrecords.txt (+1/-1)
lib/lp/soyuz/doc/initialise-from-parent.txt (+22/-2)
lib/lp/soyuz/doc/manage-chroot.txt (+2/-2)
lib/lp/soyuz/doc/nascentupload-announcements.txt (+8/-8)
lib/lp/soyuz/doc/nascentupload.txt (+5/-5)
lib/lp/soyuz/doc/package-arch-specific.txt (+2/-3)
lib/lp/soyuz/doc/package-cache-script.txt (+1/-1)
lib/lp/soyuz/doc/package-cache.txt (+22/-6)
lib/lp/soyuz/doc/package-diff.txt (+7/-6)
lib/lp/soyuz/doc/packageset.txt (+15/-3)
lib/lp/soyuz/doc/packageupload-lookups.txt (+1/-1)
lib/lp/soyuz/doc/publishing.txt (+275/-135)
lib/lp/soyuz/doc/queuebuilder.txt (+40/-32)
lib/lp/soyuz/doc/sampledata-setup.txt (+23/-0)
lib/lp/soyuz/doc/sourcepackagerelease-build-lookup.txt (+8/-8)
lib/lp/soyuz/doc/sourcepackagerelease.txt (+21/-15)
lib/lp/soyuz/doc/soyuz-files.txt (+4/-4)
lib/lp/soyuz/doc/soyuz-set-of-uploads.txt (+18/-18)
lib/lp/soyuz/doc/soyuz-upload.txt (+22/-27)
lib/lp/soyuz/doc/uploadpolicy.txt (+2/-2)
lib/lp/soyuz/help/ppa-sources-list.html (+169/-42)
lib/lp/soyuz/interfaces/archive.py (+169/-29)
lib/lp/soyuz/interfaces/archivearch.py (+11/-0)
lib/lp/soyuz/interfaces/archivepermission.py (+23/-2)
lib/lp/soyuz/interfaces/binarypackagebuild.py (+40/-234)
lib/lp/soyuz/interfaces/binarypackagename.py (+2/-1)
lib/lp/soyuz/interfaces/binarypackagerelease.py (+37/-4)
lib/lp/soyuz/interfaces/buildfarmbuildjob.py (+21/-0)
lib/lp/soyuz/interfaces/buildpackagejob.py (+35/-0)
lib/lp/soyuz/interfaces/component.py (+2/-2)
lib/lp/soyuz/interfaces/distroarchseries.py (+7/-0)
lib/lp/soyuz/interfaces/files.py (+6/-1)
lib/lp/soyuz/interfaces/packagecloner.py (+1/-1)
lib/lp/soyuz/interfaces/packageset.py (+69/-8)
lib/lp/soyuz/interfaces/packagesetgroup.py (+41/-0)
lib/lp/soyuz/interfaces/processor.py (+24/-1)
lib/lp/soyuz/interfaces/publishing.py (+170/-58)
lib/lp/soyuz/interfaces/queue.py (+4/-20)
lib/lp/soyuz/interfaces/sourcepackageformat.py (+64/-0)
lib/lp/soyuz/interfaces/sourcepackagerelease.py (+20/-0)
lib/lp/soyuz/model/archive.py (+297/-62)
lib/lp/soyuz/model/archivearch.py (+16/-0)
lib/lp/soyuz/model/archivepermission.py (+39/-13)
lib/lp/soyuz/model/archivesubscriber.py (+2/-2)
lib/lp/soyuz/model/binarypackagebuild.py (+202/-239)
lib/lp/soyuz/model/binarypackagebuildbehavior.py (+217/-0)
lib/lp/soyuz/model/binarypackagerelease.py (+46/-3)
lib/lp/soyuz/model/buildpackagejob.py (+274/-0)
lib/lp/soyuz/model/distributionsourcepackagerelease.py (+10/-8)
lib/lp/soyuz/model/distroarchseries.py (+13/-5)
lib/lp/soyuz/model/files.py (+13/-2)
lib/lp/soyuz/model/packagecloner.py (+15/-17)
lib/lp/soyuz/model/packagediff.py (+26/-1)
lib/lp/soyuz/model/packageset.py (+83/-9)
lib/lp/soyuz/model/packagesetgroup.py (+30/-0)
lib/lp/soyuz/model/processor.py (+12/-0)
lib/lp/soyuz/model/publishedpackage.py (+1/-1)
lib/lp/soyuz/model/publishing.py (+401/-316)
lib/lp/soyuz/model/queue.py (+190/-86)
lib/lp/soyuz/model/sourcepackageformat.py (+56/-0)
lib/lp/soyuz/model/sourcepackagerelease.py (+31/-84)
lib/lp/soyuz/pas.py (+94/-0)
lib/lp/soyuz/scripts/buildd.py (+119/-26)
lib/lp/soyuz/scripts/expire_archive_files.py (+90/-21)
lib/lp/soyuz/scripts/ftpmaster.py (+39/-39)
lib/lp/soyuz/scripts/gina/archive.py (+3/-2)
lib/lp/soyuz/scripts/gina/handlers.py (+68/-36)
lib/lp/soyuz/scripts/gina/library.py (+5/-2)
lib/lp/soyuz/scripts/gina/packages.py (+12/-10)
lib/lp/soyuz/scripts/gina/scripts/gina-loggrep (+1/-1)
lib/lp/soyuz/scripts/packagecopier.py (+61/-50)
lib/lp/soyuz/scripts/ppa_add_missing_builds.py (+136/-0)
lib/lp/soyuz/scripts/ppa_apache_log_parser.py (+22/-0)
lib/lp/soyuz/scripts/ppareport.py (+1/-1)
lib/lp/soyuz/scripts/processaccepted.py (+120/-2)
lib/lp/soyuz/scripts/publishdistro.py (+50/-23)
lib/lp/soyuz/scripts/queue.py (+12/-8)
lib/lp/soyuz/scripts/soyuz_process_upload.py (+12/-6)
lib/lp/soyuz/scripts/tests/gina_test_archive/dists/breezy/main/source/Sources (+17/-0)
lib/lp/soyuz/scripts/tests/gina_test_archive/dists/hoary/main/source/Sources (+14/-0)
lib/lp/soyuz/scripts/tests/gina_test_archive/pool/main/b/bar/bar_1.0-1.dsc (+22/-0)
lib/lp/soyuz/scripts/tests/ppa-apache-log-files/ppa.launchpad.net.access-log (+9/-0)
lib/lp/soyuz/scripts/tests/sync_source_home/Debian_incoming_main_Sources (+28/-0)
lib/lp/soyuz/scripts/tests/sync_source_home/sample1_1.0-1.dsc (+37/-0)
lib/lp/soyuz/scripts/tests/test_buildd_cronscripts.py (+11/-15)
lib/lp/soyuz/scripts/tests/test_copypackage.py (+338/-102)
lib/lp/soyuz/scripts/tests/test_expire_archive_files.py (+162/-108)
lib/lp/soyuz/scripts/tests/test_gina.py (+15/-0)
lib/lp/soyuz/scripts/tests/test_lpquerydistro.py (+2/-2)
lib/lp/soyuz/scripts/tests/test_obsoletedistroseries.py (+8/-10)
lib/lp/soyuz/scripts/tests/test_populatearchive.py (+60/-29)
lib/lp/soyuz/scripts/tests/test_ppa_add_missing_builds.py (+155/-0)
lib/lp/soyuz/scripts/tests/test_ppa_apache_log_parser.py (+134/-0)
lib/lp/soyuz/scripts/tests/test_processdeathrow.py (+14/-15)
lib/lp/soyuz/scripts/tests/test_processpendingpackagediffs.py (+4/-71)
lib/lp/soyuz/scripts/tests/test_processupload.py (+18/-1)
lib/lp/soyuz/scripts/tests/test_publishdistro.py (+62/-12)
lib/lp/soyuz/scripts/tests/test_queue.py (+11/-8)
lib/lp/soyuz/scripts/tests/test_removepackage.py (+14/-14)
lib/lp/soyuz/scripts/tests/test_sync_source.py (+106/-29)
lib/lp/soyuz/stories/distroseries/add-architecture.txt (+1/-1)
lib/lp/soyuz/stories/packaging/package-pages-navigation.txt (+8/-8)
lib/lp/soyuz/stories/ppa/xx-copy-packages.txt (+25/-23)
lib/lp/soyuz/stories/ppa/xx-delete-packages.txt (+7/-7)
lib/lp/soyuz/stories/ppa/xx-edit-dependencies.txt (+13/-12)
lib/lp/soyuz/stories/ppa/xx-ppa-files.txt (+43/-35)
lib/lp/soyuz/stories/ppa/xx-ppa-navigation.txt (+3/-3)
lib/lp/soyuz/stories/ppa/xx-ppa-packages.txt (+103/-49)
lib/lp/soyuz/stories/ppa/xx-ppa-private-teams.txt (+2/-2)
lib/lp/soyuz/stories/ppa/xx-ppa-workflow.txt (+169/-31)
lib/lp/soyuz/stories/ppa/xx-private-ppa-presentation.txt (+14/-11)
lib/lp/soyuz/stories/ppa/xx-private-ppa-subscription-stories.txt (+51/-45)
lib/lp/soyuz/stories/ppa/xx-private-ppa-subscriptions.txt (+74/-38)
lib/lp/soyuz/stories/ppa/xx-private-ppas.txt (+20/-14)
lib/lp/soyuz/stories/ppa/xx-ubuntu-ppas.txt (+66/-27)
lib/lp/soyuz/stories/soyuz/xx-binarypackagerelease-index.txt (+3/-2)
lib/lp/soyuz/stories/soyuz/xx-build-record.txt (+37/-14)
lib/lp/soyuz/stories/soyuz/xx-buildfarm-index.txt (+6/-6)
lib/lp/soyuz/stories/soyuz/xx-builds-pages.txt (+6/-6)
lib/lp/soyuz/stories/soyuz/xx-distribution-archives.txt (+7/-3)
lib/lp/soyuz/stories/soyuz/xx-distributionsourcepackagerelease-pages.txt (+39/-4)
lib/lp/soyuz/stories/soyuz/xx-distroarchseries-binpackages.txt (+45/-6)
lib/lp/soyuz/stories/soyuz/xx-distroarchseries.txt (+2/-2)
lib/lp/soyuz/stories/soyuz/xx-distroseries-binary-packages.txt (+5/-5)
lib/lp/soyuz/stories/soyuz/xx-distroseries-index.txt (+2/-2)
lib/lp/soyuz/stories/soyuz/xx-distroseries-sources.txt (+31/-59)
lib/lp/soyuz/stories/soyuz/xx-packagepublishinghistory.txt (+49/-0)
lib/lp/soyuz/stories/soyuz/xx-person-packages.txt (+85/-64)
lib/lp/soyuz/stories/soyuz/xx-private-builds.txt (+48/-78)
lib/lp/soyuz/stories/soyuz/xx-queue-pages-delayed-copies.txt (+13/-13)
lib/lp/soyuz/stories/soyuz/xx-queue-pages-motu.txt (+7/-7)
lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt (+128/-77)
lib/lp/soyuz/stories/soyuz/xx-sourcepackage-changelog.txt (+3/-3)
lib/lp/soyuz/stories/webservice/xx-archive.txt (+73/-54)
lib/lp/soyuz/stories/webservice/xx-archivedependency.txt (+18/-24)
lib/lp/soyuz/stories/webservice/xx-binary-package-publishing.txt (+129/-11)
lib/lp/soyuz/stories/webservice/xx-builds.txt (+8/-7)
lib/lp/soyuz/stories/webservice/xx-distroarchseries.txt (+13/-0)
lib/lp/soyuz/stories/webservice/xx-packageset.txt (+313/-73)
lib/lp/soyuz/stories/webservice/xx-source-package-publishing.txt (+112/-19)
lib/lp/soyuz/templates/archive-activate.pt (+0/-4)
lib/lp/soyuz/templates/archive-builds.pt (+0/-21)
lib/lp/soyuz/templates/archive-delete.pt (+32/-0)
lib/lp/soyuz/templates/archive-edit-dependencies.pt (+20/-33)
lib/lp/soyuz/templates/archive-index.pt (+35/-18)
lib/lp/soyuz/templates/archive-macros.pt (+10/-4)
lib/lp/soyuz/templates/archive-packages.pt (+4/-3)
lib/lp/soyuz/templates/archive-subscribers.pt (+1/-1)
lib/lp/soyuz/templates/build-index.pt (+4/-4)
lib/lp/soyuz/templates/builder-history.pt (+0/-20)
lib/lp/soyuz/templates/builder-index.pt (+6/-40)
lib/lp/soyuz/templates/buildfarmbranchjob-current.pt (+10/-0)
lib/lp/soyuz/templates/buildfarmbuildjob-current.pt (+8/-0)
lib/lp/soyuz/templates/buildfarmjob-current.pt (+9/-0)
lib/lp/soyuz/templates/buildqueue-current.pt (+24/-0)
lib/lp/soyuz/templates/builds-list.pt (+2/-2)
lib/lp/soyuz/templates/builds.pt (+0/-6)
lib/lp/soyuz/templates/distribution-portlet-ppa-architectures.pt (+5/-8)
lib/lp/soyuz/templates/distributionsourcepackagerelease-changes.pt (+5/-4)
lib/lp/soyuz/templates/distroarchseries-builds.pt (+0/-20)
lib/lp/soyuz/templates/distroarchseriesbinarypackagerelease-index.pt (+10/-4)
lib/lp/soyuz/templates/distroseries-builds.pt (+0/-20)
lib/lp/soyuz/templates/distroseries-portlet-latestuploads.pt (+7/-5)
lib/lp/soyuz/templates/distroseries-queue.pt (+6/-0)
lib/lp/soyuz/templates/distroseriessourcepackagerelease-index.pt (+16/-10)
lib/lp/soyuz/templates/packagepublishing-details.pt (+1/-1)
lib/lp/soyuz/templates/person-archive-subscription.pt (+2/-3)
lib/lp/soyuz/templates/person-archive-subscriptions.pt (+12/-4)
lib/lp/soyuz/templates/sourcepackage-builds.pt (+0/-20)
lib/lp/soyuz/templates/sourcepackagepublishinghistory-listing-archive-detailed.pt (+10/-3)
lib/lp/soyuz/templates/sourcepackagerelease-change-summary.pt (+0/-10)
lib/lp/soyuz/tests/ppa.py (+6/-8)
lib/lp/soyuz/tests/soyuz.py (+84/-13)
lib/lp/soyuz/tests/soyuzbuilddhelpers.py (+97/-104)
lib/lp/soyuz/tests/test_archive.py (+649/-25)
lib/lp/soyuz/tests/test_archivearch.py (+57/-0)
lib/lp/soyuz/tests/test_build.py (+116/-11)
lib/lp/soyuz/tests/test_buildpackagejob.py (+240/-0)
lib/lp/soyuz/tests/test_doc.py (+11/-0)
lib/lp/soyuz/tests/test_hasbuildrecords.py (+1/-1)
lib/lp/soyuz/tests/test_packagediff.py (+92/-0)
lib/lp/soyuz/tests/test_packageset.py (+187/-0)
lib/lp/soyuz/tests/test_packageupload.py (+67/-12)
lib/lp/soyuz/tests/test_processaccepted.py (+127/-0)
lib/lp/soyuz/tests/test_processor.py (+32/-0)
lib/lp/soyuz/tests/test_publishing.py (+197/-44)
lib/lp/soyuz/tests/test_publishing_models.py (+15/-2)
lib/lp/soyuz/tests/test_publishing_top_level_api.py (+10/-10)
lib/lp/soyuz/windmill/tests/test_archivesubscribersindex.py (+17/-15)
lib/lp/testing/__init__.py (+464/-250)
lib/lp/testing/_login.py (+25/-38)
lib/lp/testing/_webservice.py (+124/-0)
lib/lp/testing/breadcrumbs.py (+40/-56)
lib/lp/testing/factory.py (+753/-232)
lib/lp/testing/fakemethod.py (+57/-0)
lib/lp/testing/faketransaction.py (+35/-0)
lib/lp/testing/fixture.py (+15/-4)
lib/lp/testing/menu.py (+5/-4)
lib/lp/testing/publication.py (+57/-0)
lib/lp/testing/tests/test_fakemethod.py (+85/-0)
lib/lp/testing/tests/test_fixture.py (+1/-1)
lib/lp/testing/tests/test_inlinetests.py (+20/-0)
lib/lp/testing/tests/test_zope_test_in_subprocess.py (+131/-0)
lib/lp/testing/views.py (+15/-3)
lib/lp/testopenid/adapters/openid.py (+32/-0)
lib/lp/testopenid/browser/configure.zcml (+82/-0)
lib/lp/testopenid/browser/server.py (+287/-0)
lib/lp/testopenid/configure.zcml (+28/-0)
lib/lp/testopenid/interfaces/server.py (+41/-0)
lib/lp/testopenid/stories/basics.txt (+163/-0)
lib/lp/testopenid/stories/logging-in.txt (+64/-0)
lib/lp/testopenid/stories/tests.py (+22/-0)
lib/lp/testopenid/templates/application-index.pt (+5/-0)
lib/lp/testopenid/templates/application-xrds.pt (+14/-0)
lib/lp/testopenid/templates/auth.pt (+18/-0)
lib/lp/testopenid/templates/persistentidentity-index.pt (+14/-0)
lib/lp/testopenid/templates/persistentidentity-xrds.pt (+14/-0)
lib/lp/testopenid/testing/helpers.py (+74/-0)
lib/lp/translations/browser/browser_helpers.py (+4/-6)
lib/lp/translations/browser/configure.zcml (+76/-27)
lib/lp/translations/browser/customlanguagecode.py (+171/-0)
lib/lp/translations/browser/distribution.py (+9/-11)
lib/lp/translations/browser/distroseries.py (+106/-46)
lib/lp/translations/browser/hastranslationimports.py (+43/-42)
lib/lp/translations/browser/language.py (+100/-19)
lib/lp/translations/browser/person.py (+2/-0)
lib/lp/translations/browser/poexportrequest.py (+35/-0)
lib/lp/translations/browser/pofile.py (+20/-2)
lib/lp/translations/browser/potemplate.py (+165/-32)
lib/lp/translations/browser/product.py (+43/-34)
lib/lp/translations/browser/productseries.py (+18/-25)
lib/lp/translations/browser/productserieslanguage.py (+0/-57)
lib/lp/translations/browser/project.py (+9/-9)
lib/lp/translations/browser/serieslanguage.py (+130/-10)
lib/lp/translations/browser/tests/distroseries-views.txt (+72/-14)
lib/lp/translations/browser/tests/language-views.txt (+122/-8)
lib/lp/translations/browser/tests/menu-pages.txt (+0/-230)
lib/lp/translations/browser/tests/pofile-views.txt (+20/-2)
lib/lp/translations/browser/tests/test_baseexportview.py (+69/-2)
lib/lp/translations/browser/tests/test_breadcrumbs.py (+99/-128)
lib/lp/translations/browser/tests/test_distroserieslanguage_views.py (+21/-3)
lib/lp/translations/browser/tests/test_product_view.py (+58/-11)
lib/lp/translations/browser/tests/test_productserieslanguage_views.py (+3/-1)
lib/lp/translations/browser/tests/test_translationgroup.py (+69/-0)
lib/lp/translations/browser/tests/test_translationimportqueueentry.py (+211/-0)
lib/lp/translations/browser/tests/translationmessage-views.txt (+98/-0)
lib/lp/translations/browser/translationgroup.py (+24/-18)
lib/lp/translations/browser/translationimportqueue.py (+109/-18)
lib/lp/translations/browser/translationmessage.py (+49/-2)
lib/lp/translations/browser/translations.py (+1/-1)
lib/lp/translations/configure.zcml (+49/-5)
lib/lp/translations/doc/distroseries-translations-copy.txt (+6/-9)
lib/lp/translations/doc/fix_translation_credits.txt (+23/-0)
lib/lp/translations/doc/gettext-check-messages.txt (+14/-22)
lib/lp/translations/doc/poexport-language-pack.txt (+46/-32)
lib/lp/translations/doc/poexport-queue.txt (+6/-3)
lib/lp/translations/doc/poexport-request-productseries.txt (+8/-8)
lib/lp/translations/doc/poexport-request.txt (+12/-8)
lib/lp/translations/doc/poexportqueue-replication-lag.txt (+89/-0)
lib/lp/translations/doc/pofile-verify-stats.txt (+2/-2)
lib/lp/translations/doc/pofile.txt (+61/-27)
lib/lp/translations/doc/poimport-pofile-not-exported-from-rosetta.txt (+5/-3)
lib/lp/translations/doc/poimport-pofile-old-po-imported.txt (+6/-4)
lib/lp/translations/doc/poimport-pofile-syntax-error.txt (+10/-8)
lib/lp/translations/doc/poimport-potemplate-syntax-error.txt (+5/-3)
lib/lp/translations/doc/poimport.txt (+31/-37)
lib/lp/translations/doc/potemplate.txt (+24/-10)
lib/lp/translations/doc/potmsgset.txt (+48/-26)
lib/lp/translations/doc/preferred-languages.txt (+9/-6)
lib/lp/translations/doc/request_country.txt (+4/-3)
lib/lp/translations/doc/rosetta-karma.txt (+7/-7)
lib/lp/translations/doc/rosetta-poimport-script.txt (+5/-3)
lib/lp/translations/doc/sourcepackagerelease-translations.txt (+3/-2)
lib/lp/translations/doc/translationbranchapprover.txt (+1/-41)
lib/lp/translations/doc/translationbuildapprover.txt (+82/-0)
lib/lp/translations/doc/translationgroup.txt (+37/-0)
lib/lp/translations/doc/translationimportqueue.txt (+74/-76)
lib/lp/translations/doc/translations-export-to-branch.txt (+33/-7)
lib/lp/translations/doc/translationtemplatesbuildbehavior.txt (+111/-0)
lib/lp/translations/help/directory-example.html (+53/-0)
lib/lp/translations/help/getting-started-for-your-project.html (+5/-5)
lib/lp/translations/help/imported-upload.html (+61/-0)
lib/lp/translations/help/importing-from-bzr.html (+37/-0)
lib/lp/translations/help/new-to-translating.html (+44/-0)
lib/lp/translations/help/reviewing.html (+52/-0)
lib/lp/translations/help/successful-imports.html (+46/-0)
lib/lp/translations/help/translation-groups.html (+5/-5)
lib/lp/translations/help/updated-upload.html (+40/-0)
lib/lp/translations/interfaces/customlanguagecode.py (+65/-10)
lib/lp/translations/interfaces/poexportrequest.py (+31/-9)
lib/lp/translations/interfaces/pofile.py (+13/-3)
lib/lp/translations/interfaces/potemplate.py (+44/-13)
lib/lp/translations/interfaces/potmsgset.py (+85/-10)
lib/lp/translations/interfaces/productserieslanguage.py (+7/-2)
lib/lp/translations/interfaces/translationgroup.py (+22/-12)
lib/lp/translations/interfaces/translationimporter.py (+8/-0)
lib/lp/translations/interfaces/translationimportqueue.py (+70/-16)
lib/lp/translations/interfaces/translationsoverview.py (+1/-1)
lib/lp/translations/interfaces/translationtemplatesbuildjob.py (+36/-0)
lib/lp/translations/model/approver.py (+139/-52)
lib/lp/translations/model/customlanguagecode.py (+72/-3)
lib/lp/translations/model/poexportrequest.py (+90/-37)
lib/lp/translations/model/pofile.py (+149/-95)
lib/lp/translations/model/potemplate.py (+150/-94)
lib/lp/translations/model/potmsgset.py (+127/-42)
lib/lp/translations/model/productserieslanguage.py (+10/-1)
lib/lp/translations/model/translatablemessage.py (+1/-1)
lib/lp/translations/model/translationgroup.py (+31/-17)
lib/lp/translations/model/translationimportqueue.py (+186/-101)
lib/lp/translations/model/translationmessage.py (+5/-5)
lib/lp/translations/model/translationsperson.py (+7/-6)
lib/lp/translations/model/translationtemplatesbuildbehavior.py (+121/-0)
lib/lp/translations/model/translationtemplatesbuildjob.py (+151/-0)
lib/lp/translations/pottery/detect_intltool.py (+41/-0)
lib/lp/translations/scripts/fix_translation_credits.py (+96/-0)
lib/lp/translations/scripts/message_sharing_migration.py (+212/-81)
lib/lp/translations/scripts/po_export_queue.py (+10/-24)
lib/lp/translations/scripts/po_import.py (+19/-13)
lib/lp/translations/scripts/remove_obsolete_translations.py (+7/-7)
lib/lp/translations/scripts/reupload_translations.py (+7/-2)
lib/lp/translations/scripts/tests/test-data/minimal.pot (+8/-0)
lib/lp/translations/scripts/tests/test_copy_distroseries_translations.py (+2/-10)
lib/lp/translations/scripts/tests/test_message_sharing_migration.py (+168/-76)
lib/lp/translations/scripts/tests/test_remove_translations.py (+5/-1)
lib/lp/translations/scripts/tests/test_reupload_translations.py (+61/-18)
lib/lp/translations/scripts/tests/test_translations_import.py (+62/-0)
lib/lp/translations/scripts/tests/test_translations_to_branch.py (+72/-6)
lib/lp/translations/scripts/tests/test_validate_translations_file.py (+131/-0)
lib/lp/translations/scripts/translations_to_branch.py (+58/-16)
lib/lp/translations/scripts/validate_translations_file.py (+130/-0)
lib/lp/translations/stories/buildfarm/xx-build-summary.txt (+69/-0)
lib/lp/translations/stories/distribution/xx-distribution-translations.txt (+10/-10)
lib/lp/translations/stories/distroseries/xx-distroseries-language-packs.txt (+87/-24)
lib/lp/translations/stories/distroseries/xx-distroseries-translations.txt (+24/-44)
lib/lp/translations/stories/importqueue/xx-entry-details.txt (+108/-0)
lib/lp/translations/stories/importqueue/xx-entry-error-output.txt (+46/-0)
lib/lp/translations/stories/importqueue/xx-translation-import-queue-edit-autofilling.txt (+4/-2)
lib/lp/translations/stories/importqueue/xx-translation-import-queue-filtering.txt (+1/-0)
lib/lp/translations/stories/importqueue/xx-translation-import-queue.txt (+23/-17)
lib/lp/translations/stories/productseries/xx-productseries-templates.txt (+0/-65)
lib/lp/translations/stories/productseries/xx-productseries-translations-settings.txt (+5/-1)
lib/lp/translations/stories/productseries/xx-productseries-translations.txt (+142/-42)
lib/lp/translations/stories/project/xx-project-translations.txt (+1/-1)
lib/lp/translations/stories/standalone/custom-language-codes.txt (+277/-0)
lib/lp/translations/stories/standalone/xx-language.txt (+73/-11)
lib/lp/translations/stories/standalone/xx-person-editlanguages.txt (+13/-13)
lib/lp/translations/stories/standalone/xx-pofile-details.txt (+53/-1)
lib/lp/translations/stories/standalone/xx-pofile-export.txt (+3/-3)
lib/lp/translations/stories/standalone/xx-pofile-translate-dismiss-suggestions.txt (+1/-1)
lib/lp/translations/stories/standalone/xx-pofile-translate-legal-warning.txt (+1/-1)
lib/lp/translations/stories/standalone/xx-pofile-translate-message-filtering.txt (+2/-2)
lib/lp/translations/stories/standalone/xx-pofile-translate-needs-review-flags-preserved.txt (+62/-3)
lib/lp/translations/stories/standalone/xx-pofile-translate-newlines-check.txt (+2/-2)
lib/lp/translations/stories/standalone/xx-pofile-translate.txt (+87/-11)
lib/lp/translations/stories/standalone/xx-potemplate-admin.txt (+106/-2)
lib/lp/translations/stories/standalone/xx-potemplate-edit.txt (+118/-19)
lib/lp/translations/stories/standalone/xx-potemplate-index.txt (+235/-22)
lib/lp/translations/stories/standalone/xx-product-translations.txt (+90/-45)
lib/lp/translations/stories/standalone/xx-rosetta-homepage.txt (+1/-1)
lib/lp/translations/stories/standalone/xx-rosetta-sourcepackage-list.txt (+1/-1)
lib/lp/translations/stories/standalone/xx-series-templates.txt (+182/-27)
lib/lp/translations/stories/standalone/xx-serieslanguage-index.txt (+189/-1)
lib/lp/translations/stories/standalone/xx-sourcepackage-export.txt (+1/-1)
lib/lp/translations/stories/standalone/xx-translationmessage-translate.txt (+59/-10)
lib/lp/translations/stories/standalone/xx-translations-to-complete.txt (+25/-0)
lib/lp/translations/stories/translationfocus/xx-product-translationfocus.txt (+87/-0)
lib/lp/translations/stories/translationgroups/15-product-translation-group.txt (+3/-2)
lib/lp/translations/stories/translationgroups/30-show-group-translation-targets.txt (+7/-0)
lib/lp/translations/stories/translationgroups/46-test-distro-structured-permissions.txt (+2/-2)
lib/lp/translations/stories/translationgroups/xx-change-translation-policy.txt (+92/-12)
lib/lp/translations/stories/translations/55-rosetta-potemplates.txt (+3/-2)
lib/lp/translations/stories/webservice/xx-translationfocus.txt (+34/-0)
lib/lp/translations/stories/webservice/xx-translationimportqueue.txt (+17/-2)
lib/lp/translations/templates/currenttranslationmessage-translate-one.pt (+22/-25)
lib/lp/translations/templates/customlanguagecode-add.pt (+29/-0)
lib/lp/translations/templates/customlanguagecode-index.pt (+46/-0)
lib/lp/translations/templates/customlanguagecodes-index.pt (+80/-0)
lib/lp/translations/templates/distribution-language-pack-admin-info.pt (+2/-2)
lib/lp/translations/templates/distribution-translations.pt (+19/-15)
lib/lp/translations/templates/distroseries-langchart.pt (+21/-1)
lib/lp/translations/templates/distroseries-language-packs.pt (+59/-22)
lib/lp/translations/templates/distroseries-translations.pt (+27/-20)
lib/lp/translations/templates/hastranslationgroup-portlet-translation-groups-and-permission.pt (+4/-5)
lib/lp/translations/templates/language-index.pt (+19/-33)
lib/lp/translations/templates/language-portlet-top-contributors.pt (+3/-3)
lib/lp/translations/templates/languageset-index.pt (+76/-35)
lib/lp/translations/templates/object-pots.pt (+2/-2)
lib/lp/translations/templates/object-templates.pt (+86/-45)
lib/lp/translations/templates/person-translations-relicensing.pt (+1/-1)
lib/lp/translations/templates/person-translations.pt (+3/-5)
lib/lp/translations/templates/pofile-details.pt (+9/-5)
lib/lp/translations/templates/pofile-export.pt (+11/-5)
lib/lp/translations/templates/pofile-portlet-details.pt (+11/-11)
lib/lp/translations/templates/pofile-translate-contributors.pt (+5/-3)
lib/lp/translations/templates/pofile-translate.pt (+9/-63)
lib/lp/translations/templates/pofile-upload.pt (+3/-3)
lib/lp/translations/templates/potemplate-index.pt (+11/-11)
lib/lp/translations/templates/product-portlet-not-using-launchpad.pt (+23/-0)
lib/lp/translations/templates/product-portlet-obsolete-translatables.pt (+1/-1)
lib/lp/translations/templates/product-portlet-translatables.pt (+15/-3)
lib/lp/translations/templates/product-translations.pt (+42/-87)
lib/lp/translations/templates/productseries-translations-bzr-import.pt (+4/-18)
lib/lp/translations/templates/productseries-translations-languages.pt (+35/-3)
lib/lp/translations/templates/productseries-translations-settings.pt (+37/-21)
lib/lp/translations/templates/productseries-translations-upload.pt (+34/-19)
lib/lp/translations/templates/productseries-translations.pt (+27/-19)
lib/lp/translations/templates/project-translations.pt (+3/-3)
lib/lp/translations/templates/rosetta-index.pt (+1/-9)
lib/lp/translations/templates/serieslanguage-index.pt (+39/-27)
lib/lp/translations/templates/sourcepackage-translations.pt (+16/-8)
lib/lp/translations/templates/translation-import-queue-macros.pt (+63/-37)
lib/lp/translations/templates/translationgroup-index.pt (+3/-2)
lib/lp/translations/templates/translationgroup-portlet-projects.pt (+3/-3)
lib/lp/translations/templates/translationimportqueue-index.pt (+9/-2)
lib/lp/translations/templates/translationimportqueueentry-index.pt (+15/-2)
lib/lp/translations/templates/translationimportqueueentry-portlet-details.pt (+43/-36)
lib/lp/translations/templates/translationmessage-suggestions.pt (+1/-1)
lib/lp/translations/templates/translationmessage-translate.pt (+7/-21)
lib/lp/translations/templates/translations-export.pt (+5/-0)
lib/lp/translations/templates/translations-macros.pt (+74/-4)
lib/lp/translations/tests/test_autoapproval.py (+268/-86)
lib/lp/translations/tests/test_pofile.py (+458/-83)
lib/lp/translations/tests/test_potemplate.py (+13/-0)
lib/lp/translations/tests/test_potmsgset.py (+278/-4)
lib/lp/translations/tests/test_pottery_detect_intltool.py (+293/-0)
lib/lp/translations/tests/test_productserieslanguage.py (+31/-15)
lib/lp/translations/tests/test_rosetta_branches_script.py (+2/-2)
lib/lp/translations/tests/test_shared_potemplate.py (+11/-38)
lib/lp/translations/tests/test_suggestions.py (+11/-1)
lib/lp/translations/tests/test_translatablemessage.py (+4/-1)
lib/lp/translations/tests/test_translationbranchapprover.py (+110/-25)
lib/lp/translations/tests/test_translationbuildapprover.py (+255/-0)
lib/lp/translations/tests/test_translationgroup.py (+65/-0)
lib/lp/translations/tests/test_translationimportqueue.py (+306/-0)
lib/lp/translations/tests/test_translations_to_review.py (+3/-1)
lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py (+287/-0)
lib/lp/translations/tests/test_translationtemplatesbuildjob.py (+283/-0)
lib/lp/translations/tests/test_vpoexport.py (+0/-62)
lib/lp/translations/utilities/doc/gettext_mo_exporter.txt (+7/-5)
lib/lp/translations/utilities/doc/launchpad_write_tarfile.txt (+6/-3)
lib/lp/translations/utilities/doc/pluralforms.txt (+1/-1)
lib/lp/translations/utilities/doc/templatenames.txt (+42/-0)
lib/lp/translations/utilities/gettext_po_exporter.py (+65/-46)
lib/lp/translations/utilities/gettext_po_parser.py (+4/-3)
lib/lp/translations/utilities/mozilla_xpi_importer.py (+4/-1)
lib/lp/translations/utilities/pluralforms.py (+48/-30)
lib/lp/translations/utilities/rosettastats.py (+1/-1)
lib/lp/translations/utilities/template.py (+56/-0)
lib/lp/translations/utilities/tests/helpers.py (+3/-1)
lib/lp/translations/utilities/tests/test_file_importer.py (+24/-0)
lib/lp/translations/utilities/tests/test_gettext_po_exporter.py (+101/-27)
lib/lp/translations/utilities/tests/test_pluralforms.py (+70/-0)
lib/lp/translations/utilities/tests/test_templatenames.py (+61/-0)
lib/lp/translations/utilities/tests/test_translation_importer.py (+25/-0)
lib/lp/translations/utilities/tests/test_xpi_import.py (+3/-1)
lib/lp/translations/utilities/tests/test_xpi_manifest.py (+21/-10)
lib/lp/translations/utilities/tests/test_xpi_po_exporter.py (+3/-1)
lib/lp/translations/utilities/translation_export.py (+1/-1)
lib/lp/translations/utilities/translation_import.py (+21/-18)
lib/lp/translations/utilities/xpi_manifest.py (+7/-0)
lib/lp/translations/windmill/testing.py (+18/-0)
lib/lp/translations/windmill/tests/disabled_test_productseries_templates.py (+25/-42)
lib/lp/translations/windmill/tests/test_documentation_links.py (+50/-71)
lib/lp/translations/windmill/tests/test_import_queue.py (+125/-58)
lib/lp/translations/windmill/tests/test_import_queue_error_output.py.disabled (+14/-29)
lib/lp/translations/windmill/tests/test_languages.py (+102/-0)
lib/lp/translations/windmill/tests/test_pofile_translate.py (+251/-0)
lib/lp/translations/windmill/tests/test_serieslanguages.py (+78/-0)
lib/lp_sitecustomize.py (+30/-0)
lib/pprint25.py (+0/-315)
lib/psycopg.py (+0/-9)
lib/schoolbell/README.txt (+0/-7)
lib/schoolbell/__init__.py (+0/-38)
lib/schoolbell/browser.py (+0/-71)
lib/schoolbell/icalendar.py (+0/-1128)
lib/schoolbell/interfaces.py (+0/-396)
lib/schoolbell/mixins.py (+0/-314)
lib/schoolbell/simple.py (+0/-96)
lib/schoolbell/tests/__init__.py (+0/-1)
lib/schoolbell/tests/test_icalendar.py (+0/-782)
lib/schoolbell/tests/test_schoolbell.py (+0/-74)
lib/schoolbell/utils.py (+0/-164)
lp-sfood-packages (+35/-0)
script-testing.zcml (+8/-0)
script.zcml (+5/-1)
scripts/branch-distro.py (+39/-0)
scripts/branch-rewrite.py (+1/-1)
scripts/bug-export.py (+3/-3)
scripts/bug-import.py (+3/-3)
scripts/bugzilla-import.py (+3/-8)
scripts/cache-country-mirrors.py (+7/-5)
scripts/clean-sourceforge-project-entries.py (+1/-1)
scripts/close-account.py (+21/-13)
scripts/code-import-worker-monitor.py (+20/-9)
scripts/code-import-worker.py (+27/-6)
scripts/convert-person-to-team.py (+1/-1)
scripts/copy-translations-from-parent.py (+1/-1)
scripts/entitlements-to-lp.py (+2/-5)
scripts/find-email-clusters.py (+2/-3)
scripts/ftpmaster-tools/_syncorigins.py (+2/-2)
scripts/ftpmaster-tools/archive-cruft-check.py (+1/-1)
scripts/ftpmaster-tools/archive-integrity-check.py (+1/-1)
scripts/ftpmaster-tools/archive-override-check.py (+1/-1)
scripts/ftpmaster-tools/buildd-mass-retry.py (+10/-4)
scripts/ftpmaster-tools/change-override.py (+1/-1)
scripts/ftpmaster-tools/copy-package.py (+1/-1)
scripts/ftpmaster-tools/dak_utils.py (+4/-154)
scripts/ftpmaster-tools/initialise-from-parent.py (+9/-9)
scripts/ftpmaster-tools/lp-query-distro.py (+1/-1)
scripts/ftpmaster-tools/lp-remove-package.py (+1/-1)
scripts/ftpmaster-tools/manage-chroot.py (+1/-1)
scripts/ftpmaster-tools/obsolete-distroseries.py (+1/-1)
scripts/ftpmaster-tools/ppa-report.py (+1/-1)
scripts/ftpmaster-tools/queue (+1/-1)
scripts/ftpmaster-tools/remove-package.py (+11/-11)
scripts/ftpmaster-tools/sync-source.py (+113/-96)
scripts/ftpmaster-tools/unembargo-package.py (+1/-1)
scripts/get-stacked-on-branches.py (+1/-1)
scripts/gina.py (+41/-45)
scripts/import-debian-bugs.py (+1/-1)
scripts/import-packagenames.py (+2/-2)
scripts/import-zope-specs.py (+4/-4)
scripts/librarian-report.py (+39/-6)
scripts/linkreport.py (+2/-2)
scripts/list-team-members (+6/-5)
scripts/make-static.py (+0/-15)
scripts/memcached-stats.py (+117/-0)
scripts/merge-email-clusters.py (+2/-3)
scripts/migrate-bugzilla-initialcontacts.py (+1/-1)
scripts/migrate-librarian-content-md5.py (+1/-1)
scripts/mirror-branch.py (+1/-2)
scripts/mlist-import.py (+4/-4)
scripts/mlist-sync.py (+4/-4)
scripts/modified-branches.py (+1/-1)
scripts/populate-archive.py (+1/-1)
scripts/ppa-add-missing-builds.py (+16/-0)
scripts/process-accepted.py (+9/-103)
scripts/process-death-row.py (+1/-1)
scripts/process-upload.py (+1/-1)
scripts/publish-distro.py (+1/-1)
scripts/rosetta/check-distroseries-translations-diffs.py (+1/-1)
scripts/rosetta/fix_translation_credits.py (+28/-0)
scripts/rosetta/gettext_check_messages.py (+1/-1)
scripts/rosetta/message-sharing-merge.py (+2/-2)
scripts/rosetta/message-sharing-populate-test.py (+1/-1)
scripts/rosetta/message-sharing-populate.py (+1/-1)
scripts/rosetta/pottery-generate-intltool.py (+15/-0)
scripts/rosetta/remove-obsolete-translations.py (+1/-1)
scripts/rosetta/remove-translations-by.py (+1/-1)
scripts/rosetta/remove-upstream-translations.py (+2/-3)
scripts/rosetta/reupload-translations.py (+1/-1)
scripts/rosetta/share-jaunty-translations.py (+1/-1)
scripts/rosetta/validate-translations-file.py (+18/-0)
scripts/script-monitor-nagios.py (+6/-6)
scripts/script-monitor.py (+4/-4)
scripts/sourceforge-import.py (+6/-11)
scripts/start-loggerhead.py (+177/-0)
scripts/stop-loggerhead.py (+33/-0)
scripts/update-bzr-version-info.sh (+1/-1)
scripts/update-stacked-on.py (+11/-46)
scripts/upload2librarian.py (+3/-2)
setup.py (+14/-2)
sourcecode/Makefile (+11/-4)
standard_template.py (+2/-2)
standard_test_template.py (+2/-3)
test_on_merge.py (+13/-7)
utilities/apidoc-index.pt (+56/-0)
utilities/check-configs.py (+1/-1)
utilities/check-content-interfaces.py (+1/-1)
utilities/check-db-revision.py (+22/-0)
utilities/check-sampledata.py (+1/-1)
utilities/check-scripts.py (+3/-2)
utilities/community-contributions.py (+415/-160)
utilities/create-lp-wadl-and-apidoc.py (+63/-19)
utilities/ec2 (+3/-7)
utilities/findimports.py (+4/-6)
utilities/flaky.py (+1/-1)
utilities/generate-external-bug-status-docs (+1/-1)
utilities/get-branch-info (+1/-1)
utilities/launchpad-database-setup (+6/-5)
utilities/less-oops.sh (+9/-0)
utilities/list-person-references.py (+3/-1)
utilities/lp-deps.py (+35/-0)
utilities/lp.pylintrc (+1/-1)
utilities/lsconf.py (+4/-4)
utilities/make-dummy-hosted-branches (+1/-1)
utilities/make-lp-user (+117/-12)
utilities/migrater/file-ownership.txt (+2/-1)
utilities/migrater/migrater.py (+10/-5)
utilities/mock-code-import (+1/-1)
utilities/on-edge (+160/-0)
utilities/page-performance-report.ini (+35/-0)
utilities/page-performance-report.py (+18/-0)
utilities/paste (+3/-5)
utilities/pgbackup.py (+1/-1)
utilities/pgcreate.py (+1/-1)
utilities/pgkillactive.py (+1/-1)
utilities/pgkillidle.py (+1/-1)
utilities/pglogwatch.py (+1/-1)
utilities/pgmassacre.py (+20/-4)
utilities/pgrestore.py (+1/-1)
utilities/pgstats.py (+1/-1)
utilities/qa-ready (+108/-0)
utilities/rocketfuel-setup (+6/-79)
utilities/sanitize-db.py (+1/-1)
utilities/sourcedeps.conf (+16/-21)
utilities/soyuz-sampledata-setup.py (+422/-0)
utilities/start-dev-soyuz.sh (+21/-0)
utilities/summarizelogs.py (+1/-1)
utilities/top-tests.py (+1/-1)
utilities/update-revisionauthor-email.py (+1/-1)
utilities/update-sourcecode (+1/-1)
utilities/windmill.py (+0/-15)
utilities/xxxreport.py (+1/-1)
version.txt (+1/-1)
versions.cfg (+125/-90)
To merge this branch: bzr merge lp:~bac/launchpad/bug-574142
Reviewer Review Type Date Requested Status
Francis J. Lacoste (community) release-critical Approve
Curtis Hovey (community) Approve
Brad Crittenden Pending
Review via email: mp+24625@code.launchpad.net

Description of the change

A recent change to ProductInvolvedMenu improperly uses the ProductSeries
not the Product. A ProductSeries can not be adapted to IBranchTarget.

Pre-imp:

Call with Curtis.

Tests:

bin/test -vvm lp.registry -t productseries-views.txt \
  -t pillar-views.txt -t xx-productseries-index.txt

Full diff at http://pastebin.ubuntu.com/427182/

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

Thanks for adding the additional tests. I don't think we will make this mistake again. This is good to land and I will as for an RC (Bjorn already agreed that the issue is worthy of an RC).

review: Approve
Revision history for this message
Francis J. Lacoste (flacoste) :
review: Approve (release-critical)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2009-09-10 06:11:21 +0000
3+++ .bzrignore 2010-05-05 01:58:48 +0000
4@@ -30,11 +30,12 @@
5 database/sampledata/newsampledata-dev.sql
6 database/sampledata/lintdata.sql
7 database/sampledata/lintdata-dev.sql
8-lib/canonical/launchpad/apidoc/index.html
9+lib/canonical/launchpad/apidoc/*.html
10 xxx-report.*
11-lib/canonical/launchpad/apidoc/wadl-development.xml
12+lib/canonical/launchpad/apidoc/wadl-development-*.xml
13 lib/canonical/launchpad/apidoc/wadl-test-playground.xml
14 lib/canonical/launchpad/icing/build/*
15+lib/canonical/launchpad/icing/combo.css
16 trace.log
17 test-appserver-layer-trace.log
18 bin
19@@ -51,3 +52,17 @@
20 ./production-configs
21 bzr.dev
22 _trial_temp
23+lazr-js
24+.bazaar
25+.cache
26+.subversion
27+lib/canonical/buildd/launchpad-files
28+.testrepository
29+.memcache.pid
30+./pipes
31+lib/canonical/launchpad/apidoc/wadl-development-*.xml
32+tags.new
33+lp-clustered.dot
34+lp-clustered.sfood
35+lp-clustered.svg
36+lp.sfood
37
38=== added file '.ctags'
39--- .ctags 1970-01-01 00:00:00 +0000
40+++ .ctags 2010-05-05 01:58:48 +0000
41@@ -0,0 +1,1 @@
42+--python-kinds=-iv
43
44=== added file '.testr.conf'
45--- .testr.conf 1970-01-01 00:00:00 +0000
46+++ .testr.conf 2010-05-05 01:58:48 +0000
47@@ -0,0 +1,3 @@
48+[DEFAULT]
49+test_command=./bin/test --subunit $IDOPTION
50+test_id_option=--load-list $IDFILE
51
52=== modified file 'Makefile'
53--- Makefile 2009-10-07 09:55:24 +0000
54+++ Makefile 2010-05-05 01:58:48 +0000
55@@ -1,7 +1,7 @@
56 # This file modified from Zope3/Makefile
57 # Licensed under the ZPL, (c) Zope Corporation and contributors.
58
59-PYTHON_VERSION=2.4
60+PYTHON_VERSION=2.5
61 PYTHON=python${PYTHON_VERSION}
62 WD:=$(shell pwd)
63 PY=$(WD)/bin/py
64@@ -17,18 +17,34 @@
65
66 LPCONFIG=development
67
68+JSFLAGS=
69+ICING=lib/canonical/launchpad/icing
70+LP_BUILT_JS_ROOT=${ICING}/build
71+LAZR_BUILT_JS_ROOT=lazr-js/build
72+
73 MINS_TO_SHUTDOWN=15
74
75 CODEHOSTING_ROOT=/var/tmp/bazaar.launchpad.dev
76
77 BZR_VERSION_INFO = bzr-version-info.py
78
79-WADL_FILE = lib/canonical/launchpad/apidoc/wadl-$(LPCONFIG).xml
80-API_INDEX = lib/canonical/launchpad/apidoc/index.html
81+APIDOC_DIR = lib/canonical/launchpad/apidoc
82+WADL_TEMPLATE = $(APIDOC_DIR).tmp/wadl-$(LPCONFIG)-%(version)s.xml
83+API_INDEX = $(APIDOC_DIR)/index.html
84
85-EXTRA_JS_FILES=lib/canonical/launchpad/icing/MochiKit.js \
86- $(shell $(HERE)/utilities/yui-deps.py) \
87- lib/canonical/launchpad/icing/lazr/build/lazr.js
88+# Do not add bin/buildout to this list.
89+# It is impossible to get buildout to tell us all the files it would
90+# build, since each egg's setup.py doesn't tell us that information.
91+BUILDOUT_BIN = \
92+ $(PY) bin/apiindex bin/combine-css bin/fl-build-report \
93+ bin/fl-credential-ctl bin/fl-install-demo bin/fl-monitor-ctl \
94+ bin/fl-record bin/fl-run-bench bin/fl-run-test bin/googletestservice \
95+ bin/i18ncompile bin/i18nextract bin/i18nmergeall bin/i18nstats \
96+ bin/harness bin/iharness bin/ipy bin/jsbuild bin/jslint bin/jssize \
97+ bin/jstest bin/killservice bin/kill-test-services bin/lint.sh \
98+ bin/lp-windmill bin/retest bin/run bin/sprite-util \
99+ bin/start_librarian bin/stxdocs bin/tags bin/test bin/tracereport \
100+ bin/twistd bin/update-download-cache bin/windmill
101
102 # DO NOT ALTER : this should just build by default
103 default: inplace
104@@ -43,22 +59,14 @@
105 hosted_branches: $(PY)
106 $(PY) ./utilities/make-dummy-hosted-branches
107
108-$(WADL_FILE): $(BZR_VERSION_INFO)
109- LPCONFIG=$(LPCONFIG) $(PY) ./utilities/create-lp-wadl.py > $@.tmp
110- mv $@.tmp $@
111-
112-$(API_INDEX): $(WADL_FILE)
113- bin/apiindex $(WADL_FILE) > $@.tmp
114- mv $@.tmp $@
115+$(API_INDEX): $(BZR_VERSION_INFO)
116+ mkdir -p $(APIDOC_DIR).tmp
117+ LPCONFIG=$(LPCONFIG) $(PY) ./utilities/create-lp-wadl-and-apidoc.py "$(WADL_TEMPLATE)"
118+ mv $(APIDOC_DIR).tmp/* $(APIDOC_DIR)
119+ rmdir $(APIDOC_DIR).tmp
120
121 apidoc: compile $(API_INDEX)
122
123-check_loggerhead_on_merge:
124- # Loggerhead doesn't depend on anything else in rocketfuel and nothing
125- # depends on it (yet).
126- make -C sourcecode/loggerhead check PYTHON=${PYTHON} \
127- PYTHON_VERSION=${PYTHON_VERSION} PYTHONPATH=$(PYTHONPATH)
128-
129 check_merge: $(PY)
130 [ `PYTHONPATH= bzr status -S database/schema/ | \
131 grep -v "\(^P\|pending\|security.cfg\|Makefile\|unautovacuumable\|_pythonpath.py\)" | wc -l` -eq 0 ]
132@@ -67,16 +75,12 @@
133 check_db_merge: $(PY)
134 ${PY} lib/canonical/tests/test_no_conflict_marker.py
135
136-# This can be removed once we move to zc.buildout and we have versioned
137-# dependencies, but for now we run both Launchpad and all other
138-# dependencies tests for any merge to sourcecode.
139-check_sourcecode_merge: check
140- $(MAKE) -C sourcecode check PYTHON=${PYTHON} \
141- PYTHON_VERSION=${PYTHON_VERSION} PYTHONPATH=$(PYTHONPATH)
142-
143 check_config: build
144 bin/test -m canonical.config.tests -vvt test_config
145
146+check_schema: build
147+ ${PY} utilities/check-db-revision.py
148+
149 # Clean before running the test suite, since the build might fail depending
150 # what source changes happened. (e.g. apidoc depends on interfaces)
151 check: clean build
152@@ -90,9 +94,7 @@
153 @echo
154 @echo "Running the JavaScript integration test suite"
155 @echo
156- bin/test $(VERBOSITY) --layer=BugsWindmillLayer
157- bin/test $(VERBOSITY) --layer=CodeWindmillLayer
158- bin/test $(VERBOSITY) --layer=SoyuzWindmillLayer
159+ bin/test $(VERBOSITY) --layer=WindmillLayer
160
161 jscheck_functest: build
162 # Run the old functest Windmill integration tests. The test runner
163@@ -124,37 +126,76 @@
164
165 inplace: build
166
167-build: $(BZR_VERSION_INFO) compile apidoc
168+build: compile apidoc jsbuild css_combine
169+
170+css_combine: sprite_css bin/combine-css
171+ ${SHHH} bin/combine-css
172+
173+sprite_css: ${LP_BUILT_JS_ROOT}/style-3-0.css
174+
175+${LP_BUILT_JS_ROOT}/style-3-0.css: bin/sprite-util ${ICING}/style-3-0.css.in ${ICING}/icon-sprites.positioning
176+ ${SHHH} bin/sprite-util create-css
177+
178+sprite_image:
179+ ${SHHH} bin/sprite-util create-image
180+
181+jsbuild_lazr: bin/jsbuild
182+ # We absolutely do not want to include the lazr.testing module and its
183+ # jsTestDriver test harness modifications in the lazr.js and launchpad.js
184+ # roll-up files. They fiddle with built-in functions! See Bug 482340.
185+ ${SHHH} bin/jsbuild $(JSFLAGS) -b $(LAZR_BUILT_JS_ROOT) -x testing/ -c $(LAZR_BUILT_JS_ROOT)/yui
186+
187+jsbuild: jsbuild_lazr bin/jsbuild bin/jssize
188+ ${SHHH} bin/jsbuild \
189+ $(JSFLAGS) \
190+ -n launchpad \
191+ -s lib/canonical/launchpad/javascript \
192+ -b $(LP_BUILT_JS_ROOT) \
193+ $(shell $(HERE)/utilities/yui-deps.py) \
194+ $(shell $(HERE)/utilities/lp-deps.py) \
195+ lib/canonical/launchpad/icing/lazr/build/lazr.js
196+ ${SHHH} bin/jssize
197
198 eggs:
199 # Usually this is linked via link-external-sourcecode, but in
200 # deployment we create this ourselves.
201 mkdir eggs
202
203+# LP_SOURCEDEPS_PATH should point to the sourcecode directory, but we
204+# want the parent directory where the download-cache and eggs directory
205+# are. We re-use the variable that is using for the rocketfuel-get script.
206 download-cache:
207+ifdef LP_SOURCEDEPS_PATH
208+ utilities/link-external-sourcecode $(LP_SOURCEDEPS_PATH)/..
209+else
210 @echo "Missing ./download-cache."
211 @echo "Developers: please run utilities/link-external-sourcecode."
212 @exit 1
213+endif
214+
215+buildonce_eggs: $(PY)
216+ find eggs -name '*.pyc' -exec rm {} \;
217
218 # The download-cache dependency comes *before* eggs so that developers get the
219 # warning before the eggs directory is made. The target for the eggs directory
220 # is only there for deployment convenience.
221 bin/buildout: download-cache eggs
222 $(SHHH) PYTHONPATH= $(PYTHON) bootstrap.py\
223- --ez_setup-source=ez_setup.py \
224+ --setup-source=ez_setup.py \
225 --download-base=download-cache/dist --eggs=eggs
226
227-$(PY): bin/buildout versions.cfg $(BUILDOUT_CFG) setup.py
228+# This builds bin/py and all the other bin files except bin/buildout.
229+# Remove the target before calling buildout to ensure that buildout
230+# updates the timestamp.
231+$(BUILDOUT_BIN): bin/buildout versions.cfg $(BUILDOUT_CFG) setup.py
232+ $(RM) $@
233 $(SHHH) PYTHONPATH= ./bin/buildout \
234 configuration:instance_name=${LPCONFIG} -c $(BUILDOUT_CFG)
235
236-compile: $(PY)
237+compile: $(PY) $(BZR_VERSION_INFO)
238 ${SHHH} $(MAKE) -C sourcecode build PYTHON=${PYTHON} \
239 PYTHON_VERSION=${PYTHON_VERSION} LPCONFIG=${LPCONFIG}
240- ${SHHH} LPCONFIG=${LPCONFIG} $(PY) -t buildmailman.py
241- ${SHHH} $(PY) sourcecode/lazr-js/tools/build.py \
242- -n launchpad -s lib/canonical/launchpad/javascript \
243- -b lib/canonical/launchpad/icing/build $(EXTRA_JS_FILES)
244+ ${SHHH} LPCONFIG=${LPCONFIG} ${PY} -t buildmailman.py
245
246 test_build: build
247 bin/test $(TESTFLAGS) $(TESTOPTS)
248@@ -168,28 +209,38 @@
249 ftest_inplace: inplace
250 bin/test -f $(TESTFLAGS) $(TESTOPTS)
251
252-run: inplace stop
253+merge-proposal-jobs:
254+ # Handle merge proposal email jobs.
255+ $(PY) cronscripts/merge-proposal-jobs.py -v
256+
257+run: check_schema inplace stop
258 $(RM) thread*.request
259- bin/run -r librarian,google-webservice -i $(LPCONFIG)
260+ bin/run -r librarian,google-webservice,memcached -i $(LPCONFIG)
261
262-start-gdb: inplace stop support_files
263+start-gdb: check_schema inplace stop support_files
264 $(RM) thread*.request
265 nohup gdb -x run.gdb --args bin/run -i $(LPCONFIG) \
266 -r librarian,google-webservice
267 > ${LPCONFIG}-nohup.out 2>&1 &
268
269-run_all: inplace stop hosted_branches
270+run_all: check_schema inplace stop hosted_branches
271 $(RM) thread*.request
272- bin/run -r librarian,buildsequencer,sftp,mailman,codebrowse,google-webservice -i $(LPCONFIG)
273+ bin/run -r librarian,sftp,mailman,codebrowse,google-webservice,memcached \
274+ -i $(LPCONFIG)
275
276 run_codebrowse: build
277- BZR_PLUGIN_PATH=bzrplugins $(PY) sourcecode/launchpad-loggerhead/start-loggerhead.py -f
278+ BZR_PLUGIN_PATH=bzrplugins $(PY) scripts/start-loggerhead.py -f
279
280 start_codebrowse: build
281- BZR_PLUGIN_PATH=$(shell pwd)/bzrplugins $(PY) sourcecode/launchpad-loggerhead/start-loggerhead.py
282+ BZR_PLUGIN_PATH=$(shell pwd)/bzrplugins $(PY) scripts/start-loggerhead.py
283
284 stop_codebrowse:
285- $(PY) sourcecode/launchpad-loggerhead/stop-loggerhead.py
286+ $(PY) scripts/stop-loggerhead.py
287+
288+run_codehosting: check_schema inplace stop hosted_branches
289+ $(RM) thread*.request
290+ bin/run -r librarian,sftp,codebrowse -i $(LPCONFIG)
291+
292
293 start_librarian: build
294 bin/start_librarian
295@@ -202,14 +253,14 @@
296
297 scan_branches:
298 # Scan branches from the filesystem into the database.
299- $(PY) cronscripts/branch-scanner.py
300+ $(PY) cronscripts/scan_branches.py
301
302-sync_branches: pull_branches scan_branches
303+sync_branches: pull_branches scan_branches merge-proposal-jobs
304
305 $(BZR_VERSION_INFO):
306 scripts/update-bzr-version-info.sh
307
308-support_files: $(WADL_FILE) $(BZR_VERSION_INFO)
309+support_files: $(API_INDEX) $(BZR_VERSION_INFO)
310
311 # Intended for use on developer machines
312 start: inplace stop support_files initscript-start
313@@ -231,7 +282,7 @@
314 # servers, where we know we don't need the extra steps in a full
315 # "make stop" because of how the code is deployed/built.
316 initscript-stop:
317- bin/killservice librarian buildsequencer launchpad mailman
318+ bin/killservice librarian launchpad mailman
319
320 shutdown: scheduleoutage stop
321 $(RM) +maintenancetime.txt
322@@ -242,18 +293,26 @@
323 echo Sleeping ${MINS_TO_SHUTDOWN} mins
324 sleep ${MINS_TO_SHUTDOWN}m
325
326-harness:
327+harness: bin/harness
328 bin/harness
329
330-iharness:
331+iharness: bin/iharness
332 bin/iharness
333
334 rebuildfti:
335 @echo Rebuilding FTI indexes on launchpad_dev database
336 $(PY) database/schema/fti.py -d launchpad_dev --force
337
338-clean:
339+clean_js:
340+ $(RM) $(LP_BUILT_JS_ROOT)/launchpad.js
341+ $(RM) -r $(LAZR_BUILT_JS_ROOT)
342+
343+clean: clean_js
344 $(MAKE) -C sourcecode/pygettextpo clean
345+ # XXX gary 2009-11-16 bug 483782
346+ # The pygettextpo Makefile should have this next line in it for its make
347+ # clean, and then we should remove this line.
348+ $(RM) sourcecode/pygpgme/gpgme/*.so
349 if test -f sourcecode/mailman/Makefile; then \
350 $(MAKE) -C sourcecode/mailman clean; \
351 fi
352@@ -263,22 +322,24 @@
353 -print0 | xargs -r0 $(RM)
354 $(RM) -r bin
355 $(RM) -r parts
356+ $(RM) -r develop-eggs
357 $(RM) .installed.cfg
358 $(RM) -r build
359 $(RM) thread*.request
360 $(RM) -r lib/mailman
361 $(RM) -rf lib/canonical/launchpad/icing/build/*
362 $(RM) -r $(CODEHOSTING_ROOT)
363- $(RM) $(WADL_FILE) $(API_INDEX)
364+ $(RM) $(APIDOC_DIR)/wadl*.xml $(APIDOC_DIR)/*.html
365+ $(RM) -rf $(APIDOC_DIR).tmp
366 $(RM) $(BZR_VERSION_INFO)
367 $(RM) _pythonpath.py
368+ $(RM) +config-overrides.zcml
369 $(RM) -rf \
370 /var/tmp/builddmaster \
371 /var/tmp/bzrsync \
372 /var/tmp/codehosting.test \
373 /var/tmp/codeimport \
374 /var/tmp/fatsam.appserver \
375- /var/tmp/launchpad_mailqueue \
376 /var/tmp/lperr \
377 /var/tmp/lperr.test \
378 /var/tmp/mailman \
379@@ -286,6 +347,11 @@
380 /var/tmp/ppa \
381 /var/tmp/ppa.test \
382 /var/tmp/zeca
383+ # /var/tmp/launchpad_mailqueue is created read-only on ec2test
384+ # instances.
385+ if [ -w /var/tmp/launchpad_mailqueue ]; then $(RM) -rf /var/tmp/launchpad_mailqueue; fi
386+ $(RM) -f lp.sfood lp-clustered.sfood lp-clustered.dot lp-clustered.svg
387+
388
389 realclean: clean
390 $(RM) TAGS tags
391@@ -310,6 +376,8 @@
392 launchpad.pot:
393 bin/i18nextract.py
394
395+# Called by the rocketfuel-setup script. You probably don't want to run this
396+# on its own.
397 install: reload-apache
398
399 copy-certificates:
400@@ -328,10 +396,7 @@
401 a2ensite local-launchpad
402
403 reload-apache: enable-apache-launchpad
404- /etc/init.d/apache2 reload
405-
406-static:
407- $(PY) scripts/make-static.py
408+ /etc/init.d/apache2 restart
409
410 TAGS: compile
411 # emacs tags
412@@ -345,8 +410,37 @@
413 # idutils ID file
414 bin/tags -i
415
416+lp.sfood:
417+ # Generate import dependency graph
418+ sfood -i -u -I lib/sqlobject -I lib/schoolbell -I lib/devscripts -I lib/contrib \
419+ -I lib/canonical/not-used lib/canonical lib/lp 2>/dev/null | grep -v contrib/ \
420+ | grep -v sqlobject | grep -v BeautifulSoup | grep -v psycopg \
421+ | grep -v schoolbell > lp.sfood.tmp
422+ mv lp.sfood.tmp lp.sfood
423+
424+
425+lp-clustered.sfood: lp.sfood lp-sfood-packages
426+ # Cluster the import dependency graph
427+ sfood-cluster -f lp-sfood-packages < lp.sfood > lp-clustered.sfood.tmp
428+ mv lp-clustered.sfood.tmp lp-clustered.sfood
429+
430+
431+lp-clustered.dot: lp-clustered.sfood
432+ # Build the visual graph
433+ sfood-graph -p < lp-clustered.sfood > lp-clustered.dot.tmp
434+ mv lp-clustered.dot.tmp lp-clustered.dot
435+
436+
437+lp-clustered.svg: lp-clustered.dot
438+ # Render to svg
439+ dot -Tsvg < lp-clustered.dot > lp-clustered.svg.tmp
440+ mv lp-clustered.svg.tmp lp-clustered.svg
441+
442+
443 .PHONY: apidoc check tags TAGS zcmldocs realclean clean debug stop\
444 start run ftest_build ftest_inplace test_build test_inplace pagetests\
445- check check_loggerhead_on_merge check_merge check_sourcecode_merge \
446+ check check_merge \
447 schema default launchpad.pot check_merge_ui pull scan sync_branches\
448- reload-apache hosted_branches check_db_merge check_mailman check_config
449+ reload-apache hosted_branches check_db_merge check_mailman check_config\
450+ jsbuild jsbuild_lazr clean_js buildonce_eggs \
451+ sprite_css sprite_image css_combine compile check_schema
452
453=== modified file 'bootstrap.py'
454--- bootstrap.py 2009-08-05 18:52:52 +0000
455+++ bootstrap.py 2010-05-05 01:58:48 +0000
456@@ -17,154 +17,190 @@
457 The script accepts buildout command-line options, so you can
458 use the -c option to specify an alternate configuration file.
459
460-$Id: bootstrap.py 101930 2009-07-15 18:34:35Z gary $
461+$Id$
462 """
463
464-import os, re, shutil, sys, tempfile, textwrap, urllib, urllib2
465-
466-# We have to manually parse our options rather than using one of the stdlib
467-# tools because we want to pass the ones we don't recognize along to
468-# zc.buildout.buildout.main.
469-
470-configuration = {
471- '--ez_setup-source': 'http://peak.telecommunity.com/dist/ez_setup.py',
472- '--version': '',
473- '--download-base': None,
474- '--eggs': None}
475-
476-helpstring = __doc__ + textwrap.dedent('''
477- This script recognizes the following options itself. The first option it
478- encounters that is not one of these will cause the script to stop parsing
479- options and pass the rest on to buildout. Therefore, if you want to use
480- any of the following options *and* buildout command-line options like
481- -c, first use the following options, and then use the buildout options.
482-
483- Options:
484- --version=ZC_BUILDOUT_VERSION
485- Specify a version number of the zc.buildout to use
486- --ez_setup-source=URL_OR_FILE
487- Specify a URL or file location for the ez_setup file.
488- Defaults to
489- %(--ez_setup-source)s
490- --download-base=URL_OR_DIRECTORY
491- Specify a URL or directory for downloading setuptools and
492- zc.buildout. Defaults to PyPI.
493- --eggs=DIRECTORY
494- Specify a directory for storing eggs. Defaults to a temporary
495- directory that is deleted when the bootstrap script completes.
496-
497- By using --ez_setup-source and --download-base to point to local resources,
498- you can keep this script from going over the network.
499- ''' % configuration)
500-match_equals = re.compile(r'(%s)=(.*)' % ('|'.join(configuration),)).match
501-args = sys.argv[1:]
502-if args == ['--help']:
503- print helpstring
504- sys.exit(0)
505-
506-# If we end up using a temporary directory for storing our eggs, this will
507-# hold the path of that directory. On the other hand, if an explicit directory
508-# is specified in the argv, this will remain None.
509-tmpeggs = None
510-
511-while args:
512- val = args[0]
513- if val in configuration:
514- del args[0]
515- if not args or args[0].startswith('-'):
516- print "ERROR: %s requires an argument."
517- print helpstring
518- sys.exit(1)
519- configuration[val] = args[0]
520- else:
521- match = match_equals(val)
522- if match and match.group(1) in configuration:
523- configuration[match.group(1)] = match.group(2)
524+import os, shutil, sys, tempfile, textwrap, urllib, urllib2
525+from optparse import OptionParser
526+
527+if sys.platform == 'win32':
528+ def quote(c):
529+ if ' ' in c:
530+ return '"%s"' % c # work around spawn lamosity on windows
531 else:
532- break
533- del args[0]
534-
535-for name in ('--ez_setup-source', '--download-base'):
536- val = configuration[name]
537- if val is not None and '://' not in val: # We're being lazy.
538- configuration[name] = 'file://%s' % (
539- urllib.pathname2url(os.path.abspath(os.path.expanduser(val))),)
540-
541-if (configuration['--download-base'] and
542- not configuration['--download-base'].endswith('/')):
543- # Download base needs a trailing slash to make the world happy.
544- configuration['--download-base'] += '/'
545-
546-if not configuration['--eggs']:
547- configuration['--eggs'] = tmpeggs = tempfile.mkdtemp()
548-else:
549- configuration['--eggs'] = os.path.abspath(
550- os.path.expanduser(configuration['--eggs']))
551-
552-# The requirement is what we will pass to setuptools to specify zc.buildout.
553-requirement = 'zc.buildout'
554-if configuration['--version']:
555- requirement += '==' + configuration['--version']
556+ return c
557+else:
558+ quote = str
559+
560+# In order to be more robust in the face of system Pythons, we want to
561+# run without site-packages loaded. This is somewhat tricky, in
562+# particular because Python 2.6's distutils imports site, so starting
563+# with the -S flag is not sufficient. However, we'll start with that:
564+if 'site' in sys.modules:
565+ # We will restart with python -S.
566+ args = sys.argv[:]
567+ args[0:0] = [sys.executable, '-S']
568+ args = map(quote, args)
569+ os.execv(sys.executable, args)
570+# Now we are running with -S. We'll get the clean sys.path, import site
571+# because distutils will do it later, and then reset the path and clean
572+# out any namespace packages from site-packages that might have been
573+# loaded by .pth files.
574+clean_path = sys.path[:]
575+import site
576+sys.path[:] = clean_path
577+for k, v in sys.modules.items():
578+ if (hasattr(v, '__path__') and
579+ len(v.__path__)==1 and
580+ not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))):
581+ # This is a namespace package. Remove it.
582+ sys.modules.pop(k)
583+
584+is_jython = sys.platform.startswith('java')
585+
586+setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
587+distribute_source = 'http://python-distribute.org/distribute_setup.py'
588+
589+# parsing arguments
590+def normalize_to_url(option, opt_str, value, parser):
591+ if value:
592+ if '://' not in value: # It doesn't smell like a URL.
593+ value = 'file://%s' % (
594+ urllib.pathname2url(
595+ os.path.abspath(os.path.expanduser(value))),)
596+ if opt_str == '--download-base' and not value.endswith('/'):
597+ # Download base needs a trailing slash to make the world happy.
598+ value += '/'
599+ else:
600+ value = None
601+ name = opt_str[2:].replace('-', '_')
602+ setattr(parser.values, name, value)
603+
604+usage = '''\
605+[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
606+
607+Bootstraps a buildout-based project.
608+
609+Simply run this script in a directory containing a buildout.cfg, using the
610+Python that you want bin/buildout to use.
611+
612+Note that by using --setup-source and --download-base to point to
613+local resources, you can keep this script from going over the network.
614+'''
615+
616+parser = OptionParser(usage=usage)
617+parser.add_option("-v", "--version", dest="version",
618+ help="use a specific zc.buildout version")
619+parser.add_option("-d", "--distribute",
620+ action="store_true", dest="use_distribute", default=False,
621+ help="Use Distribute rather than Setuptools.")
622+parser.add_option("--setup-source", action="callback", dest="setup_source",
623+ callback=normalize_to_url, nargs=1, type="string",
624+ help=("Specify a URL or file location for the setup file. "
625+ "If you use Setuptools, this will default to " +
626+ setuptools_source + "; if you use Distribute, this "
627+ "will default to " + distribute_source +"."))
628+parser.add_option("--download-base", action="callback", dest="download_base",
629+ callback=normalize_to_url, nargs=1, type="string",
630+ help=("Specify a URL or directory for downloading "
631+ "zc.buildout and either Setuptools or Distribute. "
632+ "Defaults to PyPI."))
633+parser.add_option("--eggs",
634+ help=("Specify a directory for storing eggs. Defaults to "
635+ "a temporary directory that is deleted when the "
636+ "bootstrap script completes."))
637+parser.add_option("-c", None, action="store", dest="config_file",
638+ help=("Specify the path to the buildout configuration "
639+ "file to be used."))
640+
641+options, args = parser.parse_args()
642+
643+# if -c was provided, we push it back into args for buildout' main function
644+if options.config_file is not None:
645+ args += ['-c', options.config_file]
646+
647+if options.eggs:
648+ eggs_dir = os.path.abspath(os.path.expanduser(options.eggs))
649+else:
650+ eggs_dir = tempfile.mkdtemp()
651+
652+if options.setup_source is None:
653+ if options.use_distribute:
654+ options.setup_source = distribute_source
655+ else:
656+ options.setup_source = setuptools_source
657+
658+args = args + ['bootstrap']
659+
660
661 try:
662+ to_reload = False
663+ import pkg_resources
664+ to_reload = True
665+ if not hasattr(pkg_resources, '_distribute'):
666+ raise ImportError
667 import setuptools # A flag. Sometimes pkg_resources is installed alone.
668- import pkg_resources
669 except ImportError:
670+ ez_code = urllib2.urlopen(
671+ options.setup_source).read().replace('\r\n', '\n')
672 ez = {}
673- exec urllib2.urlopen(configuration['--ez_setup-source']).read() in ez
674- setuptools_args = dict(to_dir=configuration['--eggs'], download_delay=0)
675- if configuration['--download-base']:
676- setuptools_args['download_base'] = configuration['--download-base']
677- ez['use_setuptools'](**setuptools_args)
678- import pkg_resources
679+ exec ez_code in ez
680+ setup_args = dict(to_dir=eggs_dir, download_delay=0)
681+ if options.download_base:
682+ setup_args['download_base'] = options.download_base
683+ if options.use_distribute:
684+ setup_args['no_fake'] = True
685+ ez['use_setuptools'](**setup_args)
686+ if to_reload:
687+ reload(pkg_resources)
688+ else:
689+ import pkg_resources
690 # This does not (always?) update the default working set. We will
691 # do it.
692 for path in sys.path:
693 if path not in pkg_resources.working_set.entries:
694 pkg_resources.working_set.add_entry(path)
695
696-if sys.platform == 'win32':
697- def quote(c):
698- if ' ' in c:
699- return '"%s"' % c # work around spawn lamosity on windows
700- else:
701- return c
702-else:
703- def quote (c):
704- return c
705 cmd = [quote(sys.executable),
706 '-c',
707 quote('from setuptools.command.easy_install import main; main()'),
708 '-mqNxd',
709- quote(configuration['--eggs'])]
710-
711-if configuration['--download-base']:
712- cmd.extend(['-f', quote(configuration['--download-base'])])
713-
714+ quote(eggs_dir)]
715+
716+if options.download_base:
717+ cmd.extend(['-f', quote(options.download_base)])
718+
719+requirement = 'zc.buildout'
720+if options.version:
721+ requirement = '=='.join((requirement, options.version))
722 cmd.append(requirement)
723
724+if options.use_distribute:
725+ setup_requirement = 'distribute'
726+else:
727+ setup_requirement = 'setuptools'
728 ws = pkg_resources.working_set
729 env = dict(
730 os.environ,
731- PYTHONPATH=ws.find(pkg_resources.Requirement.parse('setuptools')).location)
732+ PYTHONPATH=ws.find(
733+ pkg_resources.Requirement.parse(setup_requirement)).location)
734
735-is_jython = sys.platform.startswith('java')
736 if is_jython:
737 import subprocess
738 exitcode = subprocess.Popen(cmd, env=env).wait()
739-else: # Windows needs this, apparently; otherwise we would prefer subprocess
740+else: # Windows prefers this, apparently; otherwise we would prefer subprocess
741 exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
742 if exitcode != 0:
743 sys.stdout.flush()
744+ sys.stderr.flush()
745 print ("An error occured when trying to install zc.buildout. "
746 "Look above this message for any errors that "
747 "were output by easy_install.")
748 sys.exit(exitcode)
749
750-ws.add_entry(configuration['--eggs'])
751+ws.add_entry(eggs_dir)
752 ws.require(requirement)
753 import zc.buildout.buildout
754-args.append('bootstrap')
755 zc.buildout.buildout.main(args)
756-if tmpeggs is not None:
757- shutil.rmtree(tmpeggs)
758+if not options.eggs: # clean up temporary egg directory
759+ shutil.rmtree(eggs_dir)
760
761=== modified file 'buildmailman.py'
762--- buildmailman.py 2009-09-11 02:17:29 +0000
763+++ buildmailman.py 2010-05-05 01:58:48 +0000
764@@ -1,4 +1,4 @@
765-#! /usr/bin/python2.4
766+#! /usr/bin/python2.5
767 #
768 # Copyright 2009 Canonical Ltd. This software is licensed under the
769 # GNU Affero General Public License version 3 (see the file LICENSE).
770@@ -84,25 +84,52 @@
771
772 # Build and install the Mailman software. Note that we don't care about
773 # --with-cgi-gid because we're not going to use that Mailman subsystem.
774+ executable = os.path.abspath('bin/py')
775 configure_args = (
776 './configure',
777 '--prefix', mailman_path,
778 '--with-var-prefix=' + var_dir,
779- '--with-python=' + sys.executable,
780+ '--with-python=' + executable,
781 '--with-username=' + user,
782 '--with-groupname=' + group,
783 '--with-mail-gid=' + group,
784 '--with-mailhost=' + build_host_name,
785 '--with-urlhost=' + build_host_name,
786 )
787+ # Configure.
788 retcode = subprocess.call(configure_args, cwd=mailman_source)
789 if retcode:
790 print >> sys.stderr, 'Could not configure Mailman:'
791 sys.exit(retcode)
792+ # Make.
793 retcode = subprocess.call(('make',), cwd=mailman_source)
794 if retcode:
795 print >> sys.stderr, 'Could not make Mailman.'
796 sys.exit(retcode)
797+ # We have a brief interlude before we install. Hardy will not
798+ # accept a script as the executable for the shebang line--it will
799+ # treat the file as a shell script instead. The ``bin/by``
800+ # executable that we specified in '--with-python' above is a script
801+ # so this behavior causes problems for us. Our work around is to
802+ # prefix the ``bin/py`` script with ``/usr/bin/env``, which makes
803+ # Hardy happy. We need to do this before we install because the
804+ # installation will call Mailman's ``bin/update``, which is a script
805+ # that needs this fix.
806+ build_dir = os.path.join(mailman_source, 'build')
807+ original = '#! %s\n' % (executable,)
808+ modified = '#! /usr/bin/env %s\n' % (executable,)
809+ for (dirpath, dirnames, filenames) in os.walk(build_dir):
810+ for filename in filenames:
811+ filename = os.path.join(dirpath, filename)
812+ f = open(filename, 'r')
813+ if f.readline() == original:
814+ rest = f.read()
815+ f.close()
816+ f = open(filename, 'w')
817+ f.write(modified)
818+ f.write(rest)
819+ f.close()
820+ # Now we actually install.
821 retcode = subprocess.call(('make', 'install'), cwd=mailman_source)
822 if retcode:
823 print >> sys.stderr, 'Could not install Mailman.'
824
825=== modified file 'buildout-templates/_pythonpath.py.in'
826--- buildout-templates/_pythonpath.py.in 2009-08-21 19:13:05 +0000
827+++ buildout-templates/_pythonpath.py.in 2010-05-05 01:58:48 +0000
828@@ -4,17 +4,36 @@
829 # NOTE: This is a generated file. The original is in
830 # buildout-templates/_pythonpath.py.in
831
832-__metaclass__ = type
833-
834-import sys, os
835-
836-sys.path[0:0] = [${string-paths}]
837-# Enable Storm's C extensions
838-os.environ['STORM_CEXTENSIONS'] = '1'
839-
840-# We don't want to bother tests or logs with these.
841+# This file works if the Python has been started with -S, or if bin/py
842+# has been used.
843+
844+# Auto-generated code to handle relative paths
845+${python-relative-path-setup}
846+
847+import os
848+import sys
849 import warnings
850+
851+# XXX: 2010-04-26, Salgado, bug=570246: Silence python2.6 deprecation
852+# warnings.
853 warnings.filterwarnings(
854- 'ignore',
855- 'Module .+ was already imported from .+, but .+ is being added.*',
856- UserWarning)
857+ 'ignore', '.*(md5|sha|sets)', DeprecationWarning,
858+ )
859+
860+site_dir = ${scripts:parts-directory|path-repr}
861+
862+if ('site' in sys.modules and
863+ not sys.modules['site'].__file__.startswith(
864+ os.path.join(site_dir, 'site.py'))):
865+ # We have the wrong site.py, so our paths are not set up correctly.
866+ # We blow up, with a hopefully helpful error message.
867+ raise RuntimeError(
868+ 'The wrong site.py is imported (%r imported, %r expected). '
869+ 'Scripts should usually be '
870+ "started with Launchpad's bin/py, or with a Python invoked with "
871+ 'the -S flag.' % (
872+ sys.modules['site'].__file__, os.path.join(site_dir, 'site.py')))
873+
874+if site_dir not in sys.path:
875+ sys.path.insert(0, site_dir)
876+import site # sets up paths
877
878=== added file 'buildout-templates/bin/combine-css.in'
879--- buildout-templates/bin/combine-css.in 1970-01-01 00:00:00 +0000
880+++ buildout-templates/bin/combine-css.in 2010-05-05 01:58:48 +0000
881@@ -0,0 +1,51 @@
882+#!${buildout:executable} -S
883+
884+# Initialize our paths.
885+${python-relative-path-setup}
886+import sys
887+sys.path.insert(0, ${scripts:parts-directory|path-repr})
888+import site
889+
890+import os
891+
892+from lazr.js.build import ComboFile
893+from lazr.js.combo import combine_files
894+
895+
896+root = ${buildout:directory|path-repr}
897+icing = os.path.join(root, 'lib/canonical/launchpad/icing')
898+target = os.path.join(icing, 'combo.css')
899+# It'd probably be nice to have this script find all the CSS files we might
900+# need and combine them together, but if we do that we'd certainly end up
901+# including lots of styles that we don't need/want, so keeping this hard-coded
902+# list seems like the best option for now.
903+names = [
904+ 'style.css',
905+ 'lazr/build/yui/cssreset/reset.css',
906+ 'lazr/build/yui/cssfonts/fonts.css',
907+ 'lazr/build/yui/cssgrids/grids.css',
908+ 'lazr/build/lazr/assets/skins/sam/lazr.css',
909+ 'lazr/build/inlineedit/assets/skins/sam/editor.css',
910+ 'lazr/build/autocomplete/assets/skins/sam/autocomplete.css',
911+ 'lazr/build/overlay/assets/skins/sam/pretty-overlay.css',
912+ 'lazr/build/formoverlay/assets/formoverlay-core.css',
913+ 'lazr/build/picker/assets/skins/sam/picker.css',
914+ 'lazr/build/activator/assets/skins/sam/activator.css',
915+ 'lazr/build/choiceedit/assets/choiceedit-core.css',
916+ # This one goes at the end because it's our main stylesheet and should
917+ # take precedence over the others.
918+ 'build/style-3-0.css']
919+
920+absolute_names = []
921+for name in names:
922+ absolute_names.append(os.path.join(icing, name))
923+
924+combo = ComboFile(absolute_names, target)
925+if combo.needs_update():
926+ result = ''
927+ for content in combine_files(names, icing):
928+ result += content
929+
930+ f = open(target, 'w')
931+ f.write(result)
932+ f.close()
933
934=== modified file 'buildout-templates/bin/jstest.in'
935--- buildout-templates/bin/jstest.in 2009-10-07 10:19:19 +0000
936+++ buildout-templates/bin/jstest.in 2010-05-05 01:58:48 +0000
937@@ -1,4 +1,4 @@
938-#!${buildout:executable}
939+#!${buildout:executable} -S
940 # Copyright 2009 Canonical Ltd. This software is licensed under the
941 # GNU Affero General Public License version 3 (see the file LICENSE).
942
943@@ -14,10 +14,11 @@
944
945 """
946
947-# Add the buildout sys.path
948+# Initialize our paths.
949+${python-relative-path-setup}
950 import sys
951-sys.path[0:0] = [${string-paths}]
952-
953+sys.path.insert(0, ${scripts:parts-directory|path-repr})
954+import site
955
956 import subprocess
957 import os
958
959=== added file 'buildout-templates/bin/kill-test-services.in'
960--- buildout-templates/bin/kill-test-services.in 1970-01-01 00:00:00 +0000
961+++ buildout-templates/bin/kill-test-services.in 2010-05-05 01:58:48 +0000
962@@ -0,0 +1,42 @@
963+#!${buildout:executable} -S
964+#
965+# Copyright 2009 Canonical Ltd. This software is licensed under the
966+# GNU Affero General Public License version 3 (see the file LICENSE).
967+"""Kill all the test services that may persist between test runs."""
968+
969+# Initialize our paths.
970+${python-relative-path-setup}
971+import sys
972+sys.path.insert(0, ${scripts:parts-directory|path-repr})
973+import site
974+
975+# Tell canonical.config to use the testrunner config instance, so that
976+# we don't kill the real services.
977+from canonical.config import config
978+config.setInstance('testrunner')
979+config.generate_overrides()
980+
981+import sys
982+
983+from canonical.testing.layers import MemcachedLayer
984+from canonical.librarian.ftests.harness import (
985+ LibrarianTestSetup, TacLibrarianTestSetup)
986+from lp.services.osutils import kill_by_pidfile
987+
988+
989+def main(args):
990+ if '-h' in args or '--help' in args:
991+ print __doc__
992+ return 0
993+ print "Killing Memcached....",
994+ kill_by_pidfile(MemcachedLayer.getPidFile())
995+ print "done."
996+ print "Killing Librarian....",
997+ TacLibrarianTestSetup().tearDown()
998+ LibrarianTestSetup().tearDownRoot()
999+ print "done."
1000+ return 0
1001+
1002+
1003+if __name__ == '__main__':
1004+ sys.exit(main(sys.argv[1:]))
1005
1006=== modified file 'buildout-templates/bin/lint.sh.in'
1007--- buildout-templates/bin/lint.sh.in 2009-07-17 00:26:05 +0000
1008+++ buildout-templates/bin/lint.sh.in 2010-05-05 01:58:48 +0000
1009@@ -6,7 +6,9 @@
1010 # Runs xmlint, pyflakes and pylint on files changed from parent branch.
1011 # Use '-v' to run pylint under stricter conditions with additional messages.
1012
1013-utilitiesdir=`dirname $0`/../utilities
1014+${shell-relative-path-setup}
1015+
1016+utilitiesdir=${buildout:directory/utilities|shell-path}
1017 [ -z "$utilitiesdir" ] && utilitiesdir=.
1018
1019 # Fail if any of the required tools are not installed.
1020@@ -56,9 +58,15 @@
1021 # This is a loom, lint changes relative to the lower thread.
1022 rev_option="-r thread:"
1023 else
1024- # Lint changes relative to the parent.
1025- rev=`bzr info | sed '/parent branch:/!d; s/ *parent branch: /ancestor:/'`
1026- rev_option="-r $rev"
1027+ if test "$(bzr pipes | sed -n -e "/^\\*/q;p" | wc -l)" -gt 0 ; then
1028+ # This is a pipeline with at least one pipe before the current,
1029+ # lint changes relative to the previous pipe
1030+ rev_option="-r ancestor::prev"
1031+ else
1032+ # Lint changes relative to the parent.
1033+ rev=`bzr info | sed '/parent branch:/!d; s/ *parent branch: /ancestor:/'`
1034+ rev_option="-r $rev"
1035+ fi
1036 fi
1037 elif [ $diff_status -eq 1 ] ; then
1038 # Uncommitted changes in the tree, lint those changes.
1039@@ -147,7 +155,7 @@
1040 echo " cp $4 $1"
1041 echo " Run make schema again to update the test/dev database."
1042 }
1043-
1044+
1045 if [ -n "$sql_diff" -o -n "$sql_dev_diff" -o -n "$karma_bombs" ]; then
1046 echo ""
1047 echo ""
1048@@ -155,7 +163,7 @@
1049 echo ""
1050 fi
1051
1052-#
1053+#
1054 if [ -n "$sql_diff" -o -n "$karma_bombs" ]; then
1055 echo "$current_sql"
1056 fi
1057@@ -245,7 +253,7 @@
1058
1059 jsfiles=`echo "$files" | grep -E 'js$'`
1060 if [ ! -z "$jsfiles" ]; then
1061- jslint_notices=`$utilitiesdir/../sourcecode/lazr-js/tools/jslint.py 2>&1`
1062+ jslint_notices=`$utilitiesdir/../bin/jslint 2>&1`
1063 if [ ! -z "$jslint_notices" ]; then
1064 echo ""
1065 echo ""
1066@@ -273,7 +281,7 @@
1067 fi
1068
1069 extra_path="/usr/share/pyshared:/usr/share/pycentral/pylint/site-packages"
1070-export PYTHONPATH="${os-paths}:$extra_path:$PYTHONPATH"
1071+export PYTHONPATH=${scripts:parts-directory|shell-path}:"$extra_path":"$PYTHONPATH"
1072 pylint="${buildout:executable} -Wi::DeprecationWarning `which pylint`"
1073
1074 # XXX sinzui 2007-10-18 bug=154140:
1075
1076=== removed file 'buildout-templates/bin/py.in'
1077--- buildout-templates/bin/py.in 2009-06-12 16:36:02 +0000
1078+++ buildout-templates/bin/py.in 1970-01-01 00:00:00 +0000
1079@@ -1,2 +0,0 @@
1080-#!/bin/sh
1081-PYTHONPATH=${os-paths} exec ${buildout:executable} "$@"
1082
1083=== modified file 'buildout-templates/bin/retest.in'
1084--- buildout-templates/bin/retest.in 2009-10-01 10:12:28 +0000
1085+++ buildout-templates/bin/retest.in 2010-05-05 01:58:48 +0000
1086@@ -31,9 +31,10 @@
1087 from itertools import takewhile
1088 from pprint import pprint
1089
1090+${python-relative-path-setup}
1091
1092 # The test script for this branch.
1093-TEST = '${buildout:directory}/bin/test'
1094+TEST = ${buildout:directory/bin/test|path-repr}
1095
1096 # Regular expression to match numbered stories.
1097 STORY_RE = re.compile("(.*)/\d{2}-.*")
1098
1099=== added file 'buildout-templates/bin/sprite-util.in'
1100--- buildout-templates/bin/sprite-util.in 1970-01-01 00:00:00 +0000
1101+++ buildout-templates/bin/sprite-util.in 2010-05-05 01:58:48 +0000
1102@@ -0,0 +1,47 @@
1103+#!${buildout:executable} -S
1104+
1105+import os
1106+import sys
1107+
1108+# Initialize our paths.
1109+${python-relative-path-setup}
1110+sys.path.insert(0, ${scripts:parts-directory|path-repr})
1111+import site
1112+
1113+from lp.services.spriteutils import SpriteUtil
1114+
1115+command_options = ('create-image', 'create-css')
1116+
1117+def usage():
1118+ return " Usage: %s %s" % (sys.argv[0], '|'.join(command_options))
1119+
1120+if len(sys.argv) != 2:
1121+ print >> sys.stderr, "Expected a single argument."
1122+ print >> sys.stderr, usage()
1123+ sys.exit(1)
1124+else:
1125+ command = sys.argv[1]
1126+ if command not in command_options:
1127+ print >> sys.stderr, "Unknown argument: %s" % command
1128+ print >> sys.stderr, usage()
1129+ sys.exit(2)
1130+
1131+icing = ${buildout:directory/lib/canonical/launchpad/icing|path-repr}
1132+combined_image_file = os.path.join(icing, 'icon-sprites')
1133+positioning_file = os.path.join(icing, 'icon-sprites.positioning')
1134+css_template_file = os.path.join(icing, 'style-3-0.css.in')
1135+css_file = os.path.join(icing, 'build/style-3-0.css')
1136+
1137+sprite_util = SpriteUtil(
1138+ css_template_file, 'icon-sprites',
1139+ url_prefix_substitutions={'/@@/': '../images/'})
1140+
1141+if command == 'create-image':
1142+ sprite_util.combineImages(icing)
1143+ sprite_util.savePNG(combined_image_file)
1144+ sprite_util.savePositioning(positioning_file)
1145+elif command == 'create-css':
1146+ sprite_util.loadPositioning(positioning_file)
1147+ # The icing/icon-sprites file is relative to the css file
1148+ # in the icing/build/ directory.
1149+ sprite_util.saveConvertedCSS(css_file, '../icon-sprites')
1150
1151=== modified file 'buildout-templates/bin/test.in'
1152--- buildout-templates/bin/test.in 2009-09-17 17:42:25 +0000
1153+++ buildout-templates/bin/test.in 2010-05-05 01:58:48 +0000
1154@@ -1,4 +1,4 @@
1155-#!${buildout:executable}
1156+#!${buildout:executable} -S
1157 ##############################################################################
1158 #
1159 # Copyright (c) 2004 Zope Corporation and Contributors.
1160@@ -14,9 +14,20 @@
1161 ##############################################################################
1162 """Test script
1163 """
1164-import sys, os, time, logging, warnings, re
1165-
1166-BUILD_DIR = '${buildout:directory}'
1167+
1168+# NOTE: This is a generated file. The original is in
1169+# buildout-templates/bin/test.in
1170+
1171+import logging, os, re, sys, time, warnings
1172+
1173+# Initialize our paths.
1174+${python-relative-path-setup}
1175+import sys
1176+sys.path.insert(0, ${scripts:parts-directory|path-repr})
1177+import site
1178+
1179+BUILD_DIR = ${buildout:directory|path-repr}
1180+CUSTOM_SITE_DIR = ${scripts:parts-directory|path-repr}
1181
1182 if os.getsid(0) == os.getsid(os.getppid()):
1183 # We need to become the process group leader so test_on_merge.py
1184@@ -30,17 +41,16 @@
1185
1186 # Make tests run in a timezone no launchpad developers live in.
1187 # Our tests need to run in any timezone.
1188-# (No longer actually required, as PQM does this)
1189+# (This is no longer actually required, as PQM does this.)
1190 os.environ['TZ'] = 'Asia/Calcutta'
1191 time.tzset()
1192
1193-# Enable Storm's C extensions
1194-os.environ['STORM_CEXTENSIONS'] = '1'
1195-
1196-sys.path[0:0] = [${string-paths}]
1197-
1198-# Set PYTHONPATH environment variable for spawned processes
1199-os.environ['PYTHONPATH'] = ':'.join(sys.path)
1200+# Storm's C extensions should already be enabled from lp_sitecustomize.py,
1201+# which our custom sitecustomize.py ran.
1202+assert os.environ['STORM_CEXTENSIONS'] == '1'
1203+
1204+# Make sure our site.py is the one that subprocesses use.
1205+os.environ['PYTHONPATH'] = CUSTOM_SITE_DIR
1206
1207 # Set a flag if this is the main testrunner process
1208 if len(sys.argv) > 1 and sys.argv[1] == '--resume-layer':
1209@@ -88,14 +98,28 @@
1210 # need to be silenced should have an accompanied Bug reference.
1211 #
1212 warnings.filterwarnings(
1213- 'ignore', 'PyCrypto', RuntimeWarning, 'twisted[.]conch[.]ssh'
1214+ 'ignore', 'PyCrypto', RuntimeWarning, 'twisted[.]conch[.]ssh',
1215 )
1216 warnings.filterwarnings(
1217 'ignore', 'twisted.python.plugin', DeprecationWarning,
1218 )
1219 warnings.filterwarnings(
1220- 'ignore', 'bzrlib.*was deprecated', DeprecationWarning
1221-)
1222+ 'ignore', 'zope.testing.doctest', DeprecationWarning,
1223+ )
1224+warnings.filterwarnings(
1225+ 'ignore', 'bzrlib.*was deprecated', DeprecationWarning,
1226+ )
1227+# XXX: 2010-04-26, Salgado, bug=570246: Silence python2.6 deprecation
1228+# warnings.
1229+# We cannot narrow this warnings filter to just twisted because
1230+# warnings.warn_explicit() sees this import as coming from importfascist, not
1231+# from twisted. It makes no sense to put module='importfascist' here though
1232+# because /everything/ gets imported through it. So, sad as it is, until
1233+# twisted doesn't produce warnings under Python 2.6, just ignore all these
1234+# deprecations.
1235+warnings.filterwarnings(
1236+ 'ignore', '.*(md5|sha|sets)', DeprecationWarning,
1237+ )
1238 # The next one is caused by a lamosity in python-openid. The following change
1239 # to openid/server/server.py would make the warning filter unnecessary:
1240 # 978c974,974
1241@@ -137,9 +161,9 @@
1242 defaults = {
1243 # Find tests in the tests and ftests directories
1244 'tests_pattern': '^f?tests$',
1245- 'test_path': ['${buildout:directory}/lib'],
1246+ 'test_path': [${buildout:directory/lib|path-repr}],
1247 'package': ['canonical', 'lp', 'devscripts'],
1248- 'layer': ['!(MailmanLayer|WindmillLayer)'],
1249+ 'layer': ['!(MailmanLayer)'],
1250 }
1251
1252 # Monkey-patch os.listdir to randomise the results
1253@@ -161,13 +185,7 @@
1254 os.listdir = listdir
1255
1256
1257-from canonical.testing.customresult import (
1258- filter_tests,
1259- list_tests,
1260- patch_find_tests,
1261- patch_zope_testresult,
1262- )
1263-from subunit import TestProtocolClient
1264+from canonical.testing.customresult import filter_tests, patch_find_tests
1265
1266
1267 if __name__ == '__main__':
1268@@ -191,16 +209,6 @@
1269 options.parser.add_option(
1270 '--load-list', type=str, action='callback', callback=load_list)
1271
1272- def list_test_option(option, opt, value, parser):
1273- patch_find_tests(list_tests)
1274- options.parser.add_option(
1275- '--list', action='callback', callback=list_test_option)
1276-
1277- def use_subunit(option, opt, value, parser):
1278- patch_zope_testresult(TestProtocolClient(sys.stdout))
1279- options.parser.add_option(
1280- '--subunit', action='callback', callback=use_subunit)
1281-
1282 # tests_pattern is a regexp, so the parsed value is hard to compare
1283 # with the default value in the loop below.
1284 options.parser.defaults['tests_pattern'] = defaults['tests_pattern']
1285@@ -229,7 +237,7 @@
1286 # e.g. run the test that you are currently editing.
1287 try:
1288 there = os.getcwd()
1289- os.chdir('${buildout:directory}')
1290+ os.chdir(BUILD_DIR)
1291 result = testrunner.run([])
1292 finally:
1293 os.chdir(there)
1294
1295=== modified file 'buildout-templates/bin/update-download-cache.in'
1296--- buildout-templates/bin/update-download-cache.in 2009-05-13 00:29:48 +0000
1297+++ buildout-templates/bin/update-download-cache.in 2010-05-05 01:58:48 +0000
1298@@ -1,2 +1,4 @@
1299-bzr up ${buildout:directory}/buildout/download-cache
1300+${shell-relative-path-setup}
1301+
1302+bzr up ${buildout:directory/buildout/download-cache|shell-path}
1303
1304
1305=== modified file 'buildout.cfg'
1306--- buildout.cfg 2009-09-21 10:45:15 +0000
1307+++ buildout.cfg 2010-05-05 01:58:48 +0000
1308@@ -11,6 +11,7 @@
1309 unzip = true
1310 eggs-directory = eggs
1311 download-cache = download-cache
1312+relative-paths = true
1313
1314 # Disable this option temporarily if you want buildout to find software
1315 # dependencies *other* than those in our download-cache. Once you have the
1316@@ -25,9 +26,6 @@
1317
1318 allow-picked-versions = false
1319
1320-allowed-eggs-from-site-packages =
1321-include-site-packages-for-buildout = false
1322-
1323 prefer-final = true
1324
1325 develop = .
1326@@ -37,42 +35,41 @@
1327
1328 [filetemplates]
1329 recipe = z3c.recipe.filetemplate
1330-eggs = lp
1331- windmill
1332-# XXX gary 2009-5-12 bug 375751:
1333-# Make mailman built and installed in a more normal way.
1334-extra-paths = ${buildout:directory}/lib/mailman
1335 source-directory = buildout-templates
1336
1337 [scripts]
1338-recipe = zc.recipe.egg
1339+recipe = z3c.recipe.scripts
1340 eggs = lp
1341 windmill
1342 funkload
1343+ zc.zservertracelog
1344 # XXX gary 2009-5-12 bug 375751:
1345 # Make mailman built and installed in a more normal way.
1346 extra-paths = ${buildout:directory}/lib/mailman
1347-# note that any indentation is lost in initialization blocks
1348-initialization = import os
1349- os.environ['STORM_CEXTENSIONS'] = '1'
1350- os.environ.setdefault('LPCONFIG', '${configuration:instance_name}')
1351- # XXX 2009-08-21 gary bug 417077
1352- # This can hopefully be removed when Twisted is used as an egg.
1353- import warnings
1354- warnings.filterwarnings(
1355- 'ignore',
1356- 'Module .+ was already imported from .+, but .+ is being added.*',
1357- UserWarning)
1358+include-site-packages = true
1359+allowed-eggs-from-site-packages =
1360+interpreter = py
1361+# Note that any indentation is lost in initialization blocks.
1362+initialization =
1363+ import os
1364+ os.environ.setdefault('LPCONFIG', '${configuration:instance_name}')
1365+ import lp_sitecustomize # Initializes LP environment.
1366 entry-points = stxdocs=zope.configuration.stxdocs:main
1367 googletestservice=canonical.launchpad.testing.googletestservice:main
1368 windmill=windmill.bin.windmill_bin:main
1369 lp-windmill=lp.scripts.utilities.lpwindmill:main
1370+ jsbuild=lazr.js.build:main
1371+ jslint=lazr.js.jslint:main
1372+ tracereport=zc.zservertracelog.tracereport:main
1373+ jssize=lp.scripts.utilities.jssize:main
1374
1375 [iharness]
1376-recipe = zc.recipe.egg
1377+recipe = z3c.recipe.scripts
1378 eggs = ${scripts:eggs}
1379 ipython
1380 extra-paths = ${scripts:extra-paths}
1381+include-site-packages = true
1382+allowed-eggs-from-site-packages =
1383 initialization = ${scripts:initialization}
1384 entry-points = iharness=canonical.database.harness:ipython
1385 scripts = iharness ipython=ipy
1386
1387=== added symlink 'bzrplugins/builder'
1388=== target is u'../sourcecode/bzr-builder/'
1389=== modified file 'bzrplugins/lpserve.py'
1390--- bzrplugins/lpserve.py 2009-07-17 00:26:05 +0000
1391+++ bzrplugins/lpserve.py 2010-05-05 01:58:48 +0000
1392@@ -11,6 +11,7 @@
1393 __all__ = ['cmd_launchpad_server']
1394
1395
1396+import resource
1397 import sys
1398
1399 from bzrlib.commands import Command, register_command
1400@@ -44,9 +45,9 @@
1401 Option('mirror-directory',
1402 help='serve branches from this directory. Defaults to '
1403 'config.codehosting.mirrored_branches_root.'),
1404- Option('branchfs-endpoint',
1405+ Option('codehosting-endpoint',
1406 help='the url of the internal XML-RPC server. Defaults to '
1407- 'config.codehosting.branchfs_endpoint.',
1408+ 'config.codehosting.codehosting_endpoint.',
1409 type=unicode),
1410 ]
1411
1412@@ -84,15 +85,18 @@
1413 finally:
1414 ui.ui_factory = old_factory
1415
1416- def run(self, user_id, port=None, upload_directory=None,
1417- mirror_directory=None, branchfs_endpoint_url=None, inet=False):
1418+ def run(self, user_id, port=None, branch_directory=None,
1419+ codehosting_endpoint_url=None, inet=False):
1420 from lp.codehosting.bzrutils import install_oops_handler
1421- from lp.codehosting.vfs import get_lp_server
1422+ from lp.codehosting.vfs import get_lp_server, hooks
1423 install_oops_handler(user_id)
1424+ four_gig = int(4e9)
1425+ resource.setrlimit(resource.RLIMIT_AS, (four_gig, four_gig))
1426+ seen_new_branch = hooks.SetProcTitleHook()
1427 lp_server = get_lp_server(
1428- int(user_id), branchfs_endpoint_url,
1429- upload_directory, mirror_directory)
1430- lp_server.setUp()
1431+ int(user_id), codehosting_endpoint_url, branch_directory,
1432+ seen_new_branch.seen)
1433+ lp_server.start_server()
1434
1435 old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
1436 try:
1437@@ -102,7 +106,7 @@
1438 self.run_server(smart_server)
1439 finally:
1440 lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
1441- lp_server.tearDown()
1442+ lp_server.stop_server()
1443
1444
1445 register_command(cmd_launchpad_server)
1446
1447=== added file 'configs/development/build-from-branch.zcml'
1448--- configs/development/build-from-branch.zcml 1970-01-01 00:00:00 +0000
1449+++ configs/development/build-from-branch.zcml 2010-05-05 01:58:48 +0000
1450@@ -0,0 +1,119 @@
1451+<!-- Copyright 2010 Canonical Ltd. This software is licensed under the
1452+ GNU Affero General Public License version 3 (see the file LICENSE).
1453+-->
1454+
1455+<configure
1456+ xmlns="http://namespaces.zope.org/zope"
1457+ xmlns:browser="http://namespaces.zope.org/browser"
1458+ xmlns:i18n="http://namespaces.zope.org/i18n"
1459+ xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
1460+ i18n_domain="launchpad">
1461+ <facet facet="branches">
1462+
1463+ <browser:defaultView
1464+ for="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipe"
1465+ name="+index"
1466+ layer="canonical.launchpad.layers.CodeLayer"/>
1467+ <browser:page
1468+ for="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipe"
1469+ class="lp.code.browser.sourcepackagerecipe.SourcePackageRecipeView"
1470+ name="+index"
1471+ template="../../lib/lp/code/templates/sourcepackagerecipe-index.pt"
1472+ permission="launchpad.View"/>
1473+ <browser:page
1474+ for="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipe"
1475+ class="lp.code.browser.sourcepackagerecipe.SourcePackageRecipeRequestBuildsView"
1476+ name="+request-builds"
1477+ template="../../lib/lp/code/templates/sourcepackagerecipe-request-builds.pt"
1478+ permission="launchpad.View"/>
1479+ </facet>
1480+ <facet facet="branches">
1481+ <browser:defaultView
1482+ for="lp.code.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuild"
1483+ name="+index"
1484+ layer="canonical.launchpad.layers.CodeLayer"/>
1485+ <browser:page
1486+ for="lp.code.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuild"
1487+ class="lp.code.browser.sourcepackagerecipe.SourcePackageRecipeBuildView"
1488+ name="+index"
1489+ template="../../lib/lp/code/templates/sourcepackagerecipe-index.pt"
1490+ permission="launchpad.View"/>
1491+ <browser:menus
1492+ classes="
1493+ SourcePackageRecipeNavigationMenu
1494+ SourcePackageRecipeContextMenu"
1495+ module="lp.code.browser.sourcepackagerecipe"/>
1496+
1497+ <browser:page
1498+ for="lp.code.interfaces.branch.IBranch"
1499+ class="lp.code.browser.sourcepackagerecipe.SourcePackageRecipeAddView"
1500+ permission="zope.Public"
1501+ facet="branches"
1502+ name="+new-recipe"
1503+ template="../../lib/lp/app/templates/generic-edit.pt"/>
1504+ <browser:page
1505+ for="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipe"
1506+ class="lp.code.browser.sourcepackagerecipe.SourcePackageRecipeEditView"
1507+ permission="zope.Public"
1508+ facet="branches"
1509+ name="+edit"
1510+ template="../../lib/lp/app/templates/generic-edit.pt"/>
1511+ <browser:page
1512+ for="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipe"
1513+ class="lp.code.browser.sourcepackagerecipe.SourcePackageRecipeDeleteView"
1514+ permission="zope.Public"
1515+ facet="branches"
1516+ name="+delete"
1517+ template="../../lib/lp/app/templates/generic-edit.pt"/>
1518+
1519+
1520+ <browser:page
1521+ for="lp.code.interfaces.branch.IBranch"
1522+ class="lp.code.browser.sourcepackagerecipelisting.BranchRecipeListingView"
1523+ permission="zope.Public"
1524+ facet="branches"
1525+ name="+recipes"
1526+ template="../../lib/lp/code/templates/sourcepackagerecipe-listing.pt"/>
1527+ <browser:page
1528+ for="lp.registry.interfaces.product.IProduct"
1529+ class="lp.code.browser.sourcepackagerecipelisting.ProductRecipeListingView"
1530+ permission="zope.Public"
1531+ facet="branches"
1532+ name="+recipes"
1533+ template="../../lib/lp/code/templates/sourcepackagerecipe-listing.pt"/>
1534+ <browser:page
1535+ for="lp.registry.interfaces.person.IPerson"
1536+ class="lp.code.browser.sourcepackagerecipelisting.PersonRecipeListingView"
1537+ permission="zope.Public"
1538+ facet="branches"
1539+ name="+recipes"
1540+ template="../../lib/lp/code/templates/sourcepackagerecipe-listing.pt"/>
1541+
1542+ <browser:page
1543+ for="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipe"
1544+ name="+hierarchy"
1545+ class="lp.code.browser.sourcepackagerecipe.SourcePackageRecipeHierarchy"
1546+ template="../../lib/lp/app/templates/launchpad-hierarchy.pt"
1547+ permission="zope.Public"/>
1548+
1549+ <adapter
1550+ provides="canonical.launchpad.webapp.interfaces.IBreadcrumb"
1551+ for="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipe"
1552+ factory="canonical.launchpad.webapp.breadcrumb.NameBreadcrumb"
1553+ permission="zope.Public"/>
1554+ </facet>
1555+ <securedutility
1556+ name="BuildableDistroSeries"
1557+ component="lp.code.browser.sourcepackagerecipe.buildable_distroseries_vocabulary"
1558+ provides="zope.schema.interfaces.IVocabularyFactory"
1559+ >
1560+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1561+ </securedutility>
1562+ <securedutility
1563+ name="TargetPPAs"
1564+ component="lp.code.browser.sourcepackagerecipe.target_ppas_vocabulary"
1565+ provides="zope.schema.interfaces.IVocabularyFactory"
1566+ >
1567+ <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
1568+ </securedutility>
1569+</configure>
1570
1571=== modified file 'configs/development/launchpad-lazr.conf'
1572--- configs/development/launchpad-lazr.conf 2009-09-29 15:15:21 +0000
1573+++ configs/development/launchpad-lazr.conf 2010-05-05 01:58:48 +0000
1574@@ -7,6 +7,7 @@
1575
1576 [archivepublisher]
1577 root: /var/tmp/archive
1578+base_url: http://archive.launchpad.dev/
1579
1580 [branchscanner]
1581 oops_prefix: BS
1582@@ -14,7 +15,8 @@
1583
1584 [builddmaster]
1585 root: /var/tmp/builddmaster/
1586-uploader: /bin/echo Uploader invocation of build BUILDID in:
1587+uploader: scripts/process-upload.py -Mvv
1588+bzr_builder_sources_list: None
1589
1590 [buildsequencer]
1591 mailproblemsto: root
1592@@ -44,15 +46,14 @@
1593
1594 [codebrowse]
1595 cachepath: /var/tmp/codebrowse.launchpad.dev/cache
1596-log_folder:
1597+log_folder: /var/tmp/codebrowse.launchpad.dev/logs
1598 launchpad_root: https://code.launchpad.dev/
1599 secret_path: configs/development/codebrowse-secret
1600
1601 [codehosting]
1602 launch: True
1603 authentication_endpoint: http://xmlrpc-private.launchpad.dev:8087/authserver
1604-branchfs_endpoint: http://xmlrpc-private.launchpad.dev:8087/branchfilesystem
1605-branch_puller_endpoint: http://xmlrpc-private.launchpad.dev:8087/branch_puller
1606+codehosting_endpoint: http://xmlrpc-private.launchpad.dev:8087/codehosting
1607 supermirror_root: http://bazaar.launchpad.dev/
1608 hosted_branches_root: /var/tmp/bazaar.launchpad.dev/push-branches/
1609 codebrowse_root: http://bazaar.launchpad.dev/
1610@@ -90,10 +91,17 @@
1611
1612
1613 [database]
1614-main_master: dbname=launchpad_dev
1615-main_slave: dbname=launchpad_dev
1616-auth_master: dbname=launchpad_dev
1617-auth_slave: dbname=launchpad_dev
1618+rw_main_master: dbname=launchpad_dev
1619+rw_main_slave: dbname=launchpad_dev
1620+# Use our _template databases here just so that we have different values from
1621+# the rw_* configs.
1622+ro_main_master: dbname=launchpad_dev_template
1623+ro_main_slave: dbname=launchpad_dev_template
1624+
1625+# XXX stub 20100407 bug=557271: These next two are ignored, and should
1626+# be removed after the May 2010 rollout.
1627+auth_master: bug 557271
1628+auth_slave: bug 557271
1629
1630 [distributionmirrorprober]
1631 use_proxy: False
1632@@ -119,18 +127,21 @@
1633 public_host: keyserver.launchpad.dev
1634
1635 [launchpad]
1636+enable_test_openid_provider: True
1637+openid_provider_vhost: testopenid
1638 code_domain: code.launchpad.dev
1639 default_batch_size: 5
1640 max_attachment_size: 2097152
1641 branchlisting_batch_size: 6
1642+mugshot_batch_size: 8
1643+announcement_batch_size: 4
1644+download_batch_size: 4
1645 openid_preauthorization_acl:
1646 localhost http://launchpad.dev/
1647 max_bug_feed_cache_minutes: 30
1648 bzr_imports_root_url: file:///tmp/bazaar-branches
1649 geoip_database: /usr/share/GeoIP/GeoLiteCity.dat
1650 geonames_identity: lpdev
1651-# Set to True to test read-only mode.
1652-read_only: False
1653 storm_cache: generational
1654 storm_cache_size: 100
1655
1656@@ -180,6 +191,20 @@
1657 soft_max_size: 40000
1658 hard_max_size: 1000000
1659
1660+[memcache]
1661+servers: (127.0.0.1:11217,1)
1662+
1663+[memcached]
1664+launch: True
1665+verbose: False
1666+address: 127.0.0.1
1667+port: 11217
1668+memory_size: 1
1669+
1670+[merge_proposal_jobs]
1671+error_dir: /var/tmp/codehosting.test
1672+oops_prefix: DMPJ
1673+
1674 [personalpackagearchive]
1675 root: /var/tmp/ppa/
1676 private_root: /var/tmp/ppa
1677@@ -192,6 +217,7 @@
1678
1679 [rosetta]
1680 global_suggestions_enabled: True
1681+generate_templates: True
1682
1683 [rosettabranches]
1684 error_dir: /var/tmp/rosettabranches.test
1685@@ -201,6 +227,9 @@
1686 error_dir: /var/tmp/poimport
1687 oops_prefix: POI
1688
1689+[process_apport_blobs]
1690+error_dir: /var/tmp/lperr
1691+
1692 [supermirror_puller]
1693 error_dir: /var/tmp/codehosting.test
1694 oops_prefix: SMP
1695@@ -217,6 +246,10 @@
1696 error_dir: /var/tmp/codehosting.test
1697 oops_prefix: USMP
1698
1699+[upgrade_branches]
1700+oops_prefix: UBJD
1701+error_dir: /var/tmp/codehosting.test
1702+
1703 [uploader]
1704 default_recipient_name: Local Root
1705 default_sender_address: root@localhost
1706@@ -233,7 +266,7 @@
1707
1708 [vhost.api]
1709 hostname: api.launchpad.dev
1710-rooturl: https://api.launchpad.dev/beta/
1711+rooturl: https://api.launchpad.dev/
1712
1713 [vhost.blueprints]
1714 hostname: blueprints.launchpad.dev
1715@@ -253,6 +286,12 @@
1716 [vhost.openid]
1717 hostname: openid.launchpad.dev
1718
1719+[vhost.testopenid]
1720+hostname: testopenid.dev
1721+
1722+[vhost.ubuntu_openid]
1723+hostname: ubuntu-openid.launchpad.dev
1724+
1725 [vhost.shipitubuntu]
1726 hostname: shipit.ubuntu.dev
1727
1728@@ -278,3 +317,6 @@
1729 # so disable that here. note that the testrunner config inherits
1730 # this setting from us.
1731 send_email: false
1732+
1733+[build_from_branch]
1734+enabled = True
1735
1736=== modified file 'configs/development/local-launchpad-apache'
1737--- configs/development/local-launchpad-apache 2009-07-24 01:57:06 +0000
1738+++ configs/development/local-launchpad-apache 2010-05-05 01:58:48 +0000
1739@@ -112,6 +112,19 @@
1740 </Directory>
1741 </VirtualHost>
1742
1743+<VirtualHost 127.0.0.88:80>
1744+ ServerName archive.launchpad.dev
1745+ LogLevel debug
1746+
1747+ DocumentRoot /var/tmp/archive
1748+ <Directory /var/tmp/archive/>
1749+ Order Deny,Allow
1750+ Deny from all
1751+ Allow from 127.0.0.0/255.0.0.0
1752+ Options Indexes
1753+ </Directory>
1754+</VirtualHost>
1755+
1756 <VirtualHost 127.0.0.88:443>
1757 ServerName launchpad.dev
1758 ServerAlias *.launchpad.dev
1759
1760=== modified file 'configs/replicated-development/launchpad-lazr.conf'
1761--- configs/replicated-development/launchpad-lazr.conf 2008-10-14 11:10:35 +0000
1762+++ configs/replicated-development/launchpad-lazr.conf 2010-05-05 01:58:48 +0000
1763@@ -6,8 +6,7 @@
1764 extends: ../development/launchpad-lazr.conf
1765
1766 [database]
1767-main_master: dbname=launchpad_dev
1768-main_slave: dbname=launchpad_dev_slave
1769-auth_master: dbname=launchpad_dev
1770-auth_slave: dbname=launchpad_dev_slave
1771-
1772+rw_main_master: dbname=launchpad_dev
1773+rw_main_slave: dbname=launchpad_dev_slave
1774+ro_main_master: dbname=launchpad_dev
1775+ro_main_slave: dbname=launchpad_dev_slave
1776
1777=== modified file 'configs/test-playground/launchpad-lazr.conf'
1778--- configs/test-playground/launchpad-lazr.conf 2008-11-10 16:12:10 +0000
1779+++ configs/test-playground/launchpad-lazr.conf 2010-05-05 01:58:48 +0000
1780@@ -6,7 +6,7 @@
1781 extends: ../development/launchpad-lazr.conf
1782
1783 [database]
1784-main_master: dbname=launchpad_ftest_playground
1785-main_slave: dbname=launchpad_ftest_playground
1786-auth_master: dbname=launchpad_ftest_playground
1787-auth_slave: dbname=launchpad_ftest_playground
1788+rw_main_master: dbname=launchpad_ftest_playground
1789+rw_main_slave: dbname=launchpad_ftest_playground
1790+ro_main_master: dbname=launchpad_ftest_playground
1791+ro_main_slave: dbname=launchpad_ftest_playground
1792
1793=== modified file 'configs/testrunner-appserver/launchpad-lazr.conf'
1794--- configs/testrunner-appserver/launchpad-lazr.conf 2009-04-29 19:10:17 +0000
1795+++ configs/testrunner-appserver/launchpad-lazr.conf 2010-05-05 01:58:48 +0000
1796@@ -23,7 +23,7 @@
1797 rooturl: http://launchpad.dev:8085/
1798
1799 [vhost.api]
1800-rooturl: http://api.launchpad.dev:8085/beta/
1801+rooturl: http://api.launchpad.dev:8085/
1802
1803 [vhost.blueprints]
1804 rooturl: http://blueprints.launchpad.dev:8085/
1805@@ -43,6 +43,9 @@
1806 [vhost.openid]
1807 rooturl: http://openid.launchpad.dev:8085/
1808
1809+[vhost.testopenid]
1810+rooturl: http://testopenid.dev:8085/
1811+
1812 [vhost.shipitubuntu]
1813 rooturl: http://shipit.ubuntu.dev:8085/
1814
1815
1816=== added file 'configs/testrunner-appserver/yui-unittest.zcml'
1817--- configs/testrunner-appserver/yui-unittest.zcml 1970-01-01 00:00:00 +0000
1818+++ configs/testrunner-appserver/yui-unittest.zcml 2010-05-05 01:58:48 +0000
1819@@ -0,0 +1,16 @@
1820+<!-- Copyright 2010 Canonical Ltd. This software is licensed under the
1821+ GNU Affero General Public License version 3 (see the file LICENSE).
1822+-->
1823+
1824+<configure
1825+ xmlns="http://namespaces.zope.org/zope"
1826+ xmlns:browser="http://namespaces.zope.org/browser">
1827+
1828+ <browser:page
1829+ name="+yui-unittest"
1830+ for="canonical.launchpad.webapp.interfaces.ILaunchpadRoot"
1831+ class="lp.testing.views.YUITestFileView"
1832+ attribute="__call__"
1833+ permission="zope.Public"/>
1834+
1835+</configure>
1836
1837=== added symlink 'configs/testrunner/build-from-branch.zcml'
1838=== target is u'../development/build-from-branch.zcml'
1839=== modified file 'configs/testrunner/launchpad-lazr.conf'
1840--- configs/testrunner/launchpad-lazr.conf 2009-09-29 15:15:21 +0000
1841+++ configs/testrunner/launchpad-lazr.conf 2010-05-05 01:58:48 +0000
1842@@ -8,13 +8,16 @@
1843 [canonical]
1844 chunkydiff: False
1845
1846+[archivepublisher]
1847+base_url: http://ftpmaster.internal/
1848+
1849 [branchscanner]
1850 oops_prefix: TSMS
1851 error_dir: /var/tmp/lperr.test
1852
1853 [builddmaster]
1854 socket_timeout: 10
1855-uploader: scripts/process-upload.py -Mvv --context buildd
1856+uploader: scripts/process-upload.py -Mvv
1857
1858 [buildsequencer]
1859 mailproblemsto: -
1860@@ -31,21 +34,23 @@
1861 bzr_lp_prefix: lp://dev/
1862 hosted_branches_root: /tmp/sftp-test/branches
1863 host_key_pair_path: lib/lp/codehosting/sshserver/tests/keys
1864-port: tcp:22222:interface=127.0.0.1
1865+port: tcp:22222:interface=bazaar.launchpad.dev
1866 error_dir: /var/tmp/codehosting.test
1867 oops_prefix: SMPSSH
1868 access_log: /tmp/test-codehosting-access.log
1869-internal_branch_by_id_root: file:///var/tmp/bzrsync/
1870+internal_branch_by_id_root: file:///var/tmp/bazaar.launchpad.dev/mirrors
1871
1872 [create_merge_proposals]
1873 oops_prefix: TMPCJ
1874 error_dir: /var/tmp/codehosting.test
1875
1876 [database]
1877-main_master: dbname=launchpad_ftest
1878-main_slave: dbname=launchpad_ftest
1879-auth_master: dbname=launchpad_ftest
1880-auth_slave: dbname=launchpad_ftest
1881+rw_main_master: dbname=launchpad_ftest
1882+rw_main_slave: dbname=launchpad_ftest
1883+# Use our _template databases here just so that we have different values from
1884+# the rw_* configs.
1885+ro_main_master: dbname=launchpad_ftest_template
1886+ro_main_slave: dbname=launchpad_ftest_template
1887 randomise_select_results: true
1888
1889 [error_reports]
1890@@ -122,7 +127,6 @@
1891
1892 [launchpad]
1893 max_attachment_size: 1024
1894-bzr_imports_root_url: http://localhost:10899
1895 geoip_database: /usr/share/GeoIP/GeoLiteCity.dat
1896
1897 [launchpad_session]
1898@@ -154,22 +158,45 @@
1899 bugnotification_interval: 5
1900 debbugs_db_location: lib/canonical/launchpad/components/ftests/debbugs_db
1901
1902-
1903-[mpcreationjobs]
1904-oops_prefix: TMPCJ
1905+[memcache]
1906+servers: (127.0.0.1:11242,1)
1907+
1908+[memcached]
1909+# The test suite takes care of launching this as necessary.
1910+launch: false
1911+verbose: false
1912+memory_size: 1
1913+address: 127.0.0.1
1914+# We want a different port to ensure we don't pick up stray memcached
1915+# processes spawned through some other mechanism.
1916+port: 11242
1917+
1918+[merge_proposal_jobs]
1919+oops_prefix: TMPJ
1920 error_dir: /var/tmp/codehosting.test
1921
1922-[update_preview_diffs]
1923-oops_prefix: TUPD
1924+[upgrade_branches]
1925+oops_prefix: TUB
1926 error_dir: /var/tmp/codehosting.test
1927
1928 [personalpackagearchive]
1929 root: /var/tmp/ppa.test/
1930
1931+[ppa_apache_log_parser]
1932+logs_root: lib/lp/soyuz/scripts/tests/ppa-apache-log-files
1933+
1934 [poimport]
1935 error_dir: /var/tmp/poimport.test
1936 oops_prefix: TPOI
1937
1938+[process_apport_blobs]
1939+dbuser: process-apport-blobs
1940+oops_prefix: TAPPORTBLOB
1941+error_dir: /var/tmp/lperr.test
1942+
1943+[rosetta]
1944+generate_templates: True
1945+
1946 [rosettabranches]
1947 oops_prefix: TRSBR
1948 error_dir: /var/tmp/rosettabranches.test
1949@@ -198,10 +225,13 @@
1950 rooturl: http://launchpad.dev/
1951
1952 [vhost.api]
1953-rooturl: http://api.launchpad.dev/beta/
1954+rooturl: http://api.launchpad.dev/
1955
1956 [vhosts]
1957 use_https: False
1958
1959 [zeca]
1960 root: /var/tmp/zeca.test
1961+
1962+[build_from_branch]
1963+enabled = True
1964
1965=== modified file 'cronscripts/allocate-revision-karma.py'
1966--- cronscripts/allocate-revision-karma.py 2009-06-24 20:52:01 +0000
1967+++ cronscripts/allocate-revision-karma.py 2010-05-05 01:58:48 +0000
1968@@ -1,4 +1,4 @@
1969-#!/usr/bin/python2.4
1970+#!/usr/bin/python2.5 -S
1971 #
1972 # Copyright 2009 Canonical Ltd. This software is licensed under the
1973 # GNU Affero General Public License version 3 (see the file LICENSE).
1974
1975=== removed file 'cronscripts/branch-scanner.py'
1976--- cronscripts/branch-scanner.py 2009-06-24 20:52:01 +0000
1977+++ cronscripts/branch-scanner.py 1970-01-01 00:00:00 +0000
1978@@ -1,36 +0,0 @@
1979-#!/usr/bin/python2.4
1980-#
1981-# Copyright 2009 Canonical Ltd. This software is licensed under the
1982-# GNU Affero General Public License version 3 (see the file LICENSE).
1983-
1984-# pylint: disable-msg=C0103,W0403
1985-# Author: Gustavo Niemeyer <gustavo@niemeyer.net>
1986-# David Allouche <david@allouche.net>
1987-
1988-"""Update bzr branches information in the database"""
1989-
1990-
1991-import _pythonpath
1992-import logging
1993-
1994-from lp.codehosting.scanner.branch_scanner import BranchScanner
1995-from canonical.config import config
1996-from lp.services.scripts.base import LaunchpadCronScript
1997-from canonical.launchpad.webapp.errorlog import globalErrorUtility
1998-
1999-
2000-class UpdateBranches(LaunchpadCronScript):
2001- def main(self):
2002- # We don't want debug messages from bzr at that point.
2003- bzr_logger = logging.getLogger("bzr")
2004- bzr_logger.setLevel(logging.INFO)
2005- globalErrorUtility.configure('branchscanner')
2006-
2007- BranchScanner(self.txn, self.logger).scanAllBranches()
2008-
2009-
2010-if __name__ == '__main__':
2011- script = UpdateBranches(
2012- "updatebranches", dbuser=config.branchscanner.dbuser)
2013- script.lock_and_run()
2014-
2015
2016=== modified file 'cronscripts/buildd-queue-builder.py'
2017--- cronscripts/buildd-queue-builder.py 2009-06-24 20:52:01 +0000
2018+++ cronscripts/buildd-queue-builder.py 2010-05-05 01:58:48 +0000
2019@@ -1,4 +1,4 @@
2020-#!/usr/bin/python2.4
2021+#!/usr/bin/python2.5 -S
2022 #
2023 # Copyright 2009 Canonical Ltd. This software is licensed under the
2024 # GNU Affero General Public License version 3 (see the file LICENSE).
2025
2026=== modified file 'cronscripts/buildd-retry-depwait.py'
2027--- cronscripts/buildd-retry-depwait.py 2009-06-24 20:52:01 +0000
2028+++ cronscripts/buildd-retry-depwait.py 2010-05-05 01:58:48 +0000
2029@@ -1,4 +1,4 @@
2030-#!/usr/bin/python2.4
2031+#!/usr/bin/python2.5 -S
2032 #
2033 # Copyright 2009 Canonical Ltd. This software is licensed under the
2034 # GNU Affero General Public License version 3 (see the file LICENSE).
2035
2036=== modified file 'cronscripts/buildd-slave-scanner.py'
2037--- cronscripts/buildd-slave-scanner.py 2009-06-24 20:52:01 +0000
2038+++ cronscripts/buildd-slave-scanner.py 2010-05-05 01:58:48 +0000
2039@@ -1,4 +1,4 @@
2040-#!/usr/bin/python2.4
2041+#!/usr/bin/python2.5 -S
2042 #
2043 # Copyright 2009 Canonical Ltd. This software is licensed under the
2044 # GNU Affero General Public License version 3 (see the file LICENSE).
2045
2046=== added file 'cronscripts/calculate-bug-heat.py'
2047--- cronscripts/calculate-bug-heat.py 1970-01-01 00:00:00 +0000
2048+++ cronscripts/calculate-bug-heat.py 2010-05-05 01:58:48 +0000
2049@@ -0,0 +1,33 @@
2050+#!/usr/bin/python2.5 -S
2051+#
2052+# Copyright 2010 Canonical Ltd. This software is licensed under the
2053+# GNU Affero General Public License version 3 (see the file LICENSE).
2054+
2055+# pylint: disable-msg=W0403
2056+
2057+"""Calculate bug heat."""
2058+
2059+__metaclass__ = type
2060+
2061+import _pythonpath
2062+
2063+from canonical.launchpad.webapp import errorlog
2064+
2065+from lp.services.job.runner import JobCronScript
2066+from lp.bugs.interfaces.bugjob import ICalculateBugHeatJobSource
2067+
2068+
2069+class RunCalculateBugHeat(JobCronScript):
2070+ """Run BranchScanJob jobs."""
2071+
2072+ config_name = 'calculate_bug_heat'
2073+ source_interface = ICalculateBugHeatJobSource
2074+
2075+ def main(self):
2076+ errorlog.globalErrorUtility.configure(self.config_name)
2077+ return super(RunCalculateBugHeat, self).main()
2078+
2079+
2080+if __name__ == '__main__':
2081+ script = RunCalculateBugHeat()
2082+ script.lock_and_run()
2083
2084=== modified file 'cronscripts/check-teamparticipation.py'
2085--- cronscripts/check-teamparticipation.py 2009-07-29 01:14:50 +0000
2086+++ cronscripts/check-teamparticipation.py 2010-05-05 01:58:48 +0000
2087@@ -1,4 +1,4 @@
2088-#!/usr/bin/python2.4
2089+#!/usr/bin/python2.5 -S
2090 #
2091 # Copyright 2009 Canonical Ltd. This software is licensed under the
2092 # GNU Affero General Public License version 3 (see the file LICENSE).
2093@@ -18,11 +18,11 @@
2094 situation, but that's not a simple thing and this should do for now.
2095 """
2096
2097+import _pythonpath
2098+
2099 import optparse
2100 import sys
2101
2102-import _pythonpath
2103-
2104 from canonical.database.sqlbase import cursor
2105 from canonical.launchpad.scripts import (
2106 execute_zcml_for_scripts, logger_options, logger)
2107
2108=== modified file 'cronscripts/checkwatches.py'
2109--- cronscripts/checkwatches.py 2009-10-05 13:08:10 +0000
2110+++ cronscripts/checkwatches.py 2010-05-05 01:58:48 +0000
2111@@ -1,4 +1,4 @@
2112-#!/usr/bin/python2.4
2113+#!/usr/bin/python2.5 -S
2114 #
2115 # Copyright 2009 Canonical Ltd. This software is licensed under the
2116 # GNU Affero General Public License version 3 (see the file LICENSE).
2117
2118=== modified file 'cronscripts/code-import-dispatcher.py'
2119--- cronscripts/code-import-dispatcher.py 2009-06-24 20:52:01 +0000
2120+++ cronscripts/code-import-dispatcher.py 2010-05-05 01:58:48 +0000
2121@@ -1,4 +1,4 @@
2122-#!/usr/bin/python2.4
2123+#!/usr/bin/python2.5 -S
2124 #
2125 # Copyright 2009 Canonical Ltd. This software is licensed under the
2126 # GNU Affero General Public License version 3 (see the file LICENSE).
2127@@ -18,6 +18,12 @@
2128
2129 class CodeImportDispatcherScript(LaunchpadScript):
2130
2131+ def add_my_options(self):
2132+ self.parser.add_option(
2133+ "--max-jobs", dest="max_jobs", type=int,
2134+ default=config.codeimportdispatcher.max_jobs_per_machine,
2135+ help="The maximum number of jobs to run on this machine.")
2136+
2137 def run(self, use_web_security=False, implicit_begin=True,
2138 isolation=None):
2139 """See `LaunchpadScript.run`.
2140@@ -30,7 +36,8 @@
2141 def main(self):
2142 globalErrorUtility.configure('codeimportdispatcher')
2143
2144- CodeImportDispatcher(self.logger).findAndDispatchJob(
2145+ dispatcher = CodeImportDispatcher(self.logger, self.options.max_jobs)
2146+ dispatcher.findAndDispatchJobs(
2147 ServerProxy(config.codeimportdispatcher.codeimportscheduler_url))
2148
2149
2150
2151=== modified file 'cronscripts/create-debwatches.py'
2152--- cronscripts/create-debwatches.py 2009-06-24 20:52:01 +0000
2153+++ cronscripts/create-debwatches.py 2010-05-05 01:58:48 +0000
2154@@ -1,4 +1,4 @@
2155-#!/usr/bin/python2.4
2156+#!/usr/bin/python2.5 -S
2157 #
2158 # Copyright 2009 Canonical Ltd. This software is licensed under the
2159 # GNU Affero General Public License version 3 (see the file LICENSE).
2160@@ -11,9 +11,9 @@
2161
2162 __metaclass__ = type
2163
2164+import _pythonpath
2165 import os
2166 import logging
2167-import _pythonpath
2168
2169 # zope bits
2170 from zope.component import getUtility
2171
2172=== modified file 'cronscripts/create_merge_proposals.py'
2173--- cronscripts/create_merge_proposals.py 2009-09-03 19:46:42 +0000
2174+++ cronscripts/create_merge_proposals.py 2010-05-05 01:58:48 +0000
2175@@ -1,4 +1,4 @@
2176-#!/usr/bin/python2.4
2177+#!/usr/bin/python2.5 -S
2178 #
2179 # Copyright 2009 Canonical Ltd. This software is licensed under the
2180 # GNU Affero General Public License version 3 (see the file LICENSE).
2181
2182=== modified file 'cronscripts/distributionmirror-prober.py'
2183--- cronscripts/distributionmirror-prober.py 2009-06-24 20:52:01 +0000
2184+++ cronscripts/distributionmirror-prober.py 2010-05-05 01:58:48 +0000
2185@@ -1,4 +1,4 @@
2186-#!/usr/bin/python2.4
2187+#!/usr/bin/python2.5 -S
2188 #
2189 # Copyright 2009 Canonical Ltd. This software is licensed under the
2190 # GNU Affero General Public License version 3 (see the file LICENSE).
2191
2192=== renamed file 'cronscripts/expire-ppa-binaries.py' => 'cronscripts/expire-archive-files.py'
2193--- cronscripts/expire-ppa-binaries.py 2009-06-24 20:52:01 +0000
2194+++ cronscripts/expire-archive-files.py 2010-05-05 01:58:48 +0000
2195@@ -1,4 +1,4 @@
2196-#!/usr/bin/python2.4
2197+#!/usr/bin/python2.5 -S
2198 #
2199 # Copyright 2009 Canonical Ltd. This software is licensed under the
2200 # GNU Affero General Public License version 3 (see the file LICENSE).
2201@@ -12,11 +12,11 @@
2202 import _pythonpath
2203
2204 from canonical.config import config
2205-from lp.soyuz.scripts.expire_ppa_binaries import PPABinaryExpirer
2206+from lp.soyuz.scripts.expire_archive_files import ArchiveExpirer
2207
2208
2209 if __name__ == '__main__':
2210- script = PPABinaryExpirer(
2211- 'expire-ppa-binaries', dbuser=config.binaryfile_expire.dbuser)
2212+ script = ArchiveExpirer(
2213+ 'expire-archive-files', dbuser=config.binaryfile_expire.dbuser)
2214 script.lock_and_run()
2215
2216
2217=== modified file 'cronscripts/expire-bugtasks.py'
2218--- cronscripts/expire-bugtasks.py 2009-06-24 20:52:01 +0000
2219+++ cronscripts/expire-bugtasks.py 2010-05-05 01:58:48 +0000
2220@@ -1,4 +1,4 @@
2221-#!/usr/bin/python2.4
2222+#!/usr/bin/python2.5 -S
2223 #
2224 # Copyright 2009 Canonical Ltd. This software is licensed under the
2225 # GNU Affero General Public License version 3 (see the file LICENSE).
2226
2227=== modified file 'cronscripts/expire-questions.py'
2228--- cronscripts/expire-questions.py 2009-06-24 20:52:01 +0000
2229+++ cronscripts/expire-questions.py 2010-05-05 01:58:48 +0000
2230@@ -1,4 +1,4 @@
2231-#!/usr/bin/python2.4
2232+#!/usr/bin/python2.5 -S
2233 #
2234 # Copyright 2009 Canonical Ltd. This software is licensed under the
2235 # GNU Affero General Public License version 3 (see the file LICENSE).
2236
2237=== modified file 'cronscripts/flag-expired-memberships.py'
2238--- cronscripts/flag-expired-memberships.py 2009-06-24 20:52:01 +0000
2239+++ cronscripts/flag-expired-memberships.py 2010-05-05 01:58:48 +0000
2240@@ -1,4 +1,4 @@
2241-#!/usr/bin/python2.4
2242+#!/usr/bin/python2.5 -S
2243 #
2244 # Copyright 2009 Canonical Ltd. This software is licensed under the
2245 # GNU Affero General Public License version 3 (see the file LICENSE).
2246
2247=== modified file 'cronscripts/foaf-update-karma-cache.py'
2248--- cronscripts/foaf-update-karma-cache.py 2009-06-24 20:52:01 +0000
2249+++ cronscripts/foaf-update-karma-cache.py 2010-05-05 01:58:48 +0000
2250@@ -1,4 +1,4 @@
2251-#!/usr/bin/python2.4
2252+#!/usr/bin/python2.5 -S
2253 #
2254 # Copyright 2009 Canonical Ltd. This software is licensed under the
2255 # GNU Affero General Public License version 3 (see the file LICENSE).
2256@@ -10,7 +10,8 @@
2257 from zope.component import getUtility
2258
2259 from canonical.config import config
2260-from canonical.database.sqlbase import ISOLATION_LEVEL_AUTOCOMMIT
2261+from canonical.database.sqlbase import (
2262+ ISOLATION_LEVEL_AUTOCOMMIT, flush_database_updates)
2263 from canonical.launchpad.interfaces import IKarmaCacheManager, NotFoundError
2264 from lp.services.scripts.base import LaunchpadCronScript
2265
2266@@ -83,6 +84,7 @@
2267 scaling = self.calculate_scaling(results)
2268 for entry in results:
2269 self.update_one_karma_cache_entry(entry, scaling)
2270+ flush_database_updates()
2271
2272 # Delete the entries we're going to replace.
2273 self.cur.execute("DELETE FROM KarmaCache WHERE category IS NULL")
2274@@ -121,7 +123,7 @@
2275 # VACUUM KarmaTotalCache since we have just touched every row in it.
2276 self.cur.execute("""VACUUM KarmaTotalCache""")
2277
2278- # Insert new records into the KarmaTotalCache table.
2279+ # Insert new records into the KarmaTotalCache table.
2280
2281 # XXX: salgado 2007-02-06:
2282 # If deadlocks ever become a problem, first LOCK the
2283@@ -146,7 +148,7 @@
2284
2285 def C_add_karmacache_sums(self):
2286 self.logger.info("Step C: Calculating KarmaCache sums")
2287- # We must issue some SUM queries to insert the karma totals for:
2288+ # We must issue some SUM queries to insert the karma totals for:
2289 # - All actions of a person on a given product.
2290 # - All actions of a person on a given distribution.
2291 # - All actions of a person on a given project.
2292@@ -156,7 +158,7 @@
2293
2294 # - All actions with a specific category of a person.
2295 self.cur.execute("""
2296- INSERT INTO KarmaCache
2297+ INSERT INTO KarmaCache
2298 (person, category, karmavalue, product, distribution,
2299 sourcepackagename, project)
2300 SELECT person, category, SUM(karmavalue), NULL, NULL, NULL, NULL
2301@@ -167,7 +169,7 @@
2302
2303 # - All actions of a person on a given product.
2304 self.cur.execute("""
2305- INSERT INTO KarmaCache
2306+ INSERT INTO KarmaCache
2307 (person, category, karmavalue, product, distribution,
2308 sourcepackagename, project)
2309 SELECT person, NULL, SUM(karmavalue), product, NULL, NULL, NULL
2310@@ -178,7 +180,7 @@
2311
2312 # - All actions of a person on a given distribution.
2313 self.cur.execute("""
2314- INSERT INTO KarmaCache
2315+ INSERT INTO KarmaCache
2316 (person, category, karmavalue, product, distribution,
2317 sourcepackagename, project)
2318 SELECT person, NULL, SUM(karmavalue), NULL, distribution, NULL, NULL
2319@@ -189,7 +191,7 @@
2320
2321 # - All actions of a person on a given project.
2322 self.cur.execute("""
2323- INSERT INTO KarmaCache
2324+ INSERT INTO KarmaCache
2325 (person, category, karmavalue, product, distribution,
2326 sourcepackagename, project)
2327 SELECT person, NULL, SUM(karmavalue), NULL, NULL, NULL,
2328@@ -206,7 +208,7 @@
2329 # inserted here will be included in the calculation of the overall
2330 # karma of a person on a given project.
2331 self.cur.execute("""
2332- INSERT INTO KarmaCache
2333+ INSERT INTO KarmaCache
2334 (person, category, karmavalue, product, distribution,
2335 sourcepackagename, project)
2336 SELECT person, category, SUM(karmavalue), NULL, NULL, NULL,
2337@@ -244,15 +246,18 @@
2338 scaling[category] = 1
2339 else:
2340 scaling[category] = float(largest_total) / float(points)
2341- self.logger.debug('Scaling %s by a factor of %0.4f'
2342- % (categories[category], scaling[category]))
2343 max_scaling = config.karmacacheupdater.max_scaling
2344 if scaling[category] > max_scaling:
2345+ self.logger.info(
2346+ 'Scaling %s by a factor of %0.4f (capped to %0.4f)'
2347+ % (categories[category], scaling[category], max_scaling))
2348 scaling[category] = max_scaling
2349- self.logger.debug('Reducing %s scaling to %d to avoid spikes'
2350- % (categories[category], max_scaling))
2351+ else:
2352+ self.logger.info(
2353+ 'Scaling %s by a factor of %0.4f'
2354+ % (categories[category], scaling[category]))
2355 return scaling
2356-
2357+
2358 def update_one_karma_cache_entry(self, entry, scaling):
2359 """Updates an individual (non-summed) KarmaCache entry.
2360
2361@@ -262,7 +267,7 @@
2362 """
2363 (person_id, category_id, product_id, distribution_id, points) = entry
2364 points *= scaling[category_id] # Scaled. wow.
2365- self.logger.debug("Setting person_id=%d, category_id=%d, points=%d"
2366+ self.logger.debug("Setting person_id=%d, category_id=%d, points=%d"
2367 % (person_id, category_id, points))
2368
2369 points = int(points)
2370@@ -285,7 +290,7 @@
2371
2372
2373 if __name__ == '__main__':
2374- script = KarmaCacheUpdater('karma-update',
2375+ script = KarmaCacheUpdater('karma-update',
2376 dbuser=config.karmacacheupdater.dbuser)
2377 script.lock_and_run(implicit_begin=True)
2378
2379
2380=== modified file 'cronscripts/garbo-daily.py'
2381--- cronscripts/garbo-daily.py 2009-06-24 20:52:01 +0000
2382+++ cronscripts/garbo-daily.py 2010-05-05 01:58:48 +0000
2383@@ -1,4 +1,4 @@
2384-#!/usr/bin/python2.4
2385+#!/usr/bin/python2.5 -S
2386 #
2387 # Copyright 2009 Canonical Ltd. This software is licensed under the
2388 # GNU Affero General Public License version 3 (see the file LICENSE).
2389
2390=== modified file 'cronscripts/garbo-hourly.py'
2391--- cronscripts/garbo-hourly.py 2009-06-24 20:52:01 +0000
2392+++ cronscripts/garbo-hourly.py 2010-05-05 01:58:48 +0000
2393@@ -1,4 +1,4 @@
2394-#!/usr/bin/python2.4
2395+#!/usr/bin/python2.5 -S
2396 #
2397 # Copyright 2009 Canonical Ltd. This software is licensed under the
2398 # GNU Affero General Public License version 3 (see the file LICENSE).
2399
2400=== modified file 'cronscripts/generate-ppa-htaccess.py'
2401--- cronscripts/generate-ppa-htaccess.py 2009-06-24 20:52:01 +0000
2402+++ cronscripts/generate-ppa-htaccess.py 2010-05-05 01:58:48 +0000
2403@@ -1,4 +1,4 @@
2404-#!/usr/bin/python2.4
2405+#!/usr/bin/python2.5 -S
2406 #
2407 # Copyright 2009 Canonical Ltd. This software is licensed under the
2408 # GNU Affero General Public License version 3 (see the file LICENSE).
2409
2410=== modified file 'cronscripts/language-pack-exporter.py'
2411--- cronscripts/language-pack-exporter.py 2009-07-17 00:26:05 +0000
2412+++ cronscripts/language-pack-exporter.py 2010-05-05 01:58:48 +0000
2413@@ -1,4 +1,4 @@
2414-#!/usr/bin/python2.4
2415+#!/usr/bin/python2.5 -S
2416 #
2417 # Copyright 2009 Canonical Ltd. This software is licensed under the
2418 # GNU Affero General Public License version 3 (see the file LICENSE).
2419
2420=== modified file 'cronscripts/librarian-gc.py'
2421--- cronscripts/librarian-gc.py 2009-06-24 20:52:01 +0000
2422+++ cronscripts/librarian-gc.py 2010-05-05 01:58:48 +0000
2423@@ -1,4 +1,4 @@
2424-#!/usr/bin/python2.4
2425+#!/usr/bin/python2.5 -S
2426 #
2427 # Copyright 2009 Canonical Ltd. This software is licensed under the
2428 # GNU Affero General Public License version 3 (see the file LICENSE).
2429@@ -46,16 +46,17 @@
2430 help="Skip removing expired TemporaryBlobStorage rows"
2431 )
2432 self.parser.add_option(
2433- '', "--skip-expired", action="store_true", default=False,
2434- dest="skip_expired",
2435- help="Skip flagging expired files for deletion."
2436- )
2437- self.parser.add_option(
2438 '', "--skip-files", action="store_true", default=False,
2439 dest="skip_files",
2440 help="Skip removing files on disk with no database references"
2441 " or flagged for deletion."
2442 )
2443+ self.parser.add_option(
2444+ '', "--skip-expiry", action="store_true", default=False,
2445+ dest="skip_expiry",
2446+ help="Skip expiring aliases with an expiry date in the past."
2447+ )
2448+
2449
2450 def main(self):
2451 librariangc.log = self.logger
2452@@ -71,6 +72,8 @@
2453
2454 # Note that each of these next steps will issue commit commands
2455 # as appropriate to make this script transaction friendly
2456+ if not self.options.skip_expiry:
2457+ librariangc.expire_aliases(conn)
2458 if not self.options.skip_content:
2459 librariangc.delete_unreferenced_content(conn) # first sweep
2460 if not self.options.skip_blobs:
2461@@ -81,8 +84,6 @@
2462 librariangc.delete_unreferenced_aliases(conn)
2463 if not self.options.skip_content:
2464 librariangc.delete_unreferenced_content(conn) # second sweep
2465- if not self.options.skip_expired:
2466- librariangc.flag_expired_files(conn)
2467 if not self.options.skip_files:
2468 librariangc.delete_unwanted_files(conn)
2469
2470
2471=== renamed file 'cronscripts/mpcreationjobs.py' => 'cronscripts/merge-proposal-jobs.py'
2472--- cronscripts/mpcreationjobs.py 2009-09-03 19:04:28 +0000
2473+++ cronscripts/merge-proposal-jobs.py 2010-05-05 01:58:48 +0000
2474@@ -1,48 +1,40 @@
2475-#!/usr/bin/python2.4
2476+#!/usr/bin/python2.5 -S
2477 #
2478-# Copyright 2009 Canonical Ltd. This software is licensed under the
2479+# Copyright 2009, 2010 Canonical Ltd. This software is licensed under the
2480 # GNU Affero General Public License version 3 (see the file LICENSE).
2481
2482 # pylint: disable-msg=W0403
2483
2484-"""Handle new BranchMergeProposals.
2485+"""Handle jobs for BranchMergeProposals.
2486
2487-This script generates a diff for the merge proposal if needed, then notifies
2488-all interested parties about the merge proposal.
2489+This script handles all job types for branch merge proposals.
2490 """
2491
2492 __metaclass__ = type
2493
2494 import _pythonpath
2495-from zope.component import getUtility
2496
2497-from canonical.config import config
2498-from lp.codehosting.vfs import get_scanner_server
2499-from lp.services.job.runner import JobRunner
2500+# The following line is a horrible hack, but unfortunately necessary right now
2501+# to stop import errors from circular imports.
2502+import canonical.launchpad.interfaces
2503 from lp.code.interfaces.branchmergeproposal import (
2504- IMergeProposalCreatedJobSource,)
2505-from lp.services.scripts.base import LaunchpadCronScript
2506-from canonical.launchpad.webapp.errorlog import globalErrorUtility
2507-
2508-
2509-class RunMergeProposalCreatedJobs(LaunchpadCronScript):
2510- """Run merge proposal creation jobs."""
2511-
2512- def main(self):
2513- globalErrorUtility.configure('mpcreationjobs')
2514- job_source = getUtility(IMergeProposalCreatedJobSource)
2515- runner = JobRunner.fromReady(job_source, self.logger)
2516- server = get_scanner_server()
2517- server.setUp()
2518- try:
2519- runner.runAll()
2520- finally:
2521- server.tearDown()
2522- self.logger.info(
2523- 'Ran %d MergeProposalCreatedJobs.', len(runner.completed_jobs))
2524+ IBranchMergeProposalJobSource,
2525+ )
2526+from lp.services.job.runner import JobCronScript, TwistedJobRunner
2527+
2528+
2529+class RunMergeProposalJobs(JobCronScript):
2530+ """Run all merge proposal jobs."""
2531+
2532+ config_name = 'merge_proposal_jobs'
2533+ source_interface = IBranchMergeProposalJobSource
2534+
2535+ def __init__(self):
2536+ super(RunMergeProposalJobs, self).__init__(
2537+ runner_class=TwistedJobRunner,
2538+ script_name='merge-proposal-jobs')
2539
2540
2541 if __name__ == '__main__':
2542- script = RunMergeProposalCreatedJobs(
2543- 'mpcreationjobs', config.mpcreationjobs.dbuser)
2544+ script = RunMergeProposalJobs()
2545 script.lock_and_run()
2546
2547=== modified file 'cronscripts/mirror-prober.sh'
2548--- cronscripts/mirror-prober.sh 2009-06-24 20:52:01 +0000
2549+++ cronscripts/mirror-prober.sh 2010-05-05 01:58:48 +0000
2550@@ -39,10 +39,10 @@
2551 cd /srv/launchpad.net/production/launchpad/cronscripts
2552
2553 echo '== Distribution mirror prober (archive)' `date` ==
2554-python2.4 distributionmirror-prober.py --content-type=archive --max-mirrors=20
2555+python2.5 -S distributionmirror-prober.py --content-type=archive --max-mirrors=20
2556
2557 echo '== Distribution mirror prober (cdimage)' `date` ==
2558-python2.4 distributionmirror-prober.py --content-type=cdimage --max-mirrors=30
2559+python2.5 -S distributionmirror-prober.py --content-type=cdimage --max-mirrors=30
2560
2561 rm -f $LOCK
2562
2563
2564=== modified file 'cronscripts/nightly.sh'
2565--- cronscripts/nightly.sh 2009-08-10 16:57:14 +0000
2566+++ cronscripts/nightly.sh 2010-05-05 01:58:48 +0000
2567@@ -3,11 +3,11 @@
2568 # Copyright 2009 Canonical Ltd. This software is licensed under the
2569 # GNU Affero General Public License version 3 (see the file LICENSE).
2570
2571-# This script performs nightly chores. It should be run from
2572+# This script performs nightly chores. It should be run from
2573 # cron as the launchpad user once a day. Typically the output
2574 # will be sent to an email address for inspection.
2575
2576-# Note that http/ftp proxies are needed by the product
2577+# Note that http/ftp proxies are needed by the product
2578 # release finder
2579
2580 # Only run this script on loganberry
2581@@ -42,41 +42,41 @@
2582 cd /srv/launchpad.net/production/launchpad/cronscripts
2583
2584 echo == Expiring memberships `date` ==
2585-python2.4 flag-expired-memberships.py -q
2586+python2.5 -S flag-expired-memberships.py -q
2587
2588 echo == Allocating revision karma `date` ==
2589-python2.4 allocate-revision-karma.py -q
2590+python2.5 -S allocate-revision-karma.py -q
2591
2592 echo == Recalculating karma `date` ==
2593-python2.4 foaf-update-karma-cache.py -q
2594+python2.5 -S foaf-update-karma-cache.py -q
2595
2596 echo == Updating cached statistics `date` ==
2597-python2.4 update-stats.py -q
2598+python2.5 -S update-stats.py -q
2599
2600 echo == Expiring questions `date` ==
2601-python2.4 expire-questions.py
2602+python2.5 -S expire-questions.py
2603
2604 ### echo == Expiring bugs `date` ==
2605-### python2.4 expire-bugtasks.py
2606+### python2.5 -S expire-bugtasks.py
2607
2608 # checkwatches.py is scheduled in the /code/pqm/launchpad_crontabs branch.
2609 ### echo == Updating bug watches `date` ==
2610-### python2.4 checkwatches.py
2611+### python2.5 -S checkwatches.py
2612
2613 echo == Updating bugtask target name caches `date` ==
2614-python2.4 update-bugtask-targetnamecaches.py -q
2615+python2.5 -S update-bugtask-targetnamecaches.py -q
2616
2617 echo == Updating personal standings `date` ==
2618-python2.4 update-standing.py -q
2619+python2.5 -S update-standing.py -q
2620
2621 echo == Updating CVE database `date` ==
2622-python2.4 update-cve.py -q
2623+python2.5 -S update-cve.py -q
2624
2625 echo == Updating package cache `date` ==
2626-python2.4 update-pkgcache.py -q
2627+python2.5 -S update-pkgcache.py -q
2628
2629 echo == Product Release Finder `date` ==
2630-python2.4 product-release-finder.py -q
2631+python2.5 -S product-release-finder.py -q
2632
2633
2634 rm -f $LOCK
2635
2636=== modified file 'cronscripts/oops-prune.py'
2637--- cronscripts/oops-prune.py 2009-06-24 20:52:01 +0000
2638+++ cronscripts/oops-prune.py 2010-05-05 01:58:48 +0000
2639@@ -1,4 +1,4 @@
2640-#!/usr/bin/python2.4
2641+#!/usr/bin/python2.5 -S
2642 #
2643 # Copyright 2009 Canonical Ltd. This software is licensed under the
2644 # GNU Affero General Public License version 3 (see the file LICENSE).
2645
2646=== modified file 'cronscripts/parse-librarian-apache-access-logs.py'
2647--- cronscripts/parse-librarian-apache-access-logs.py 2009-09-11 12:11:04 +0000
2648+++ cronscripts/parse-librarian-apache-access-logs.py 2010-05-05 01:58:48 +0000
2649@@ -1,4 +1,4 @@
2650-#!/usr/bin/python2.4
2651+#!/usr/bin/python2.5 -S
2652 #
2653 # Copyright 2009 Canonical Ltd. This software is licensed under the
2654 # GNU Affero General Public License version 3 (see the file LICENSE).
2655
2656=== added file 'cronscripts/parse-ppa-apache-access-logs.py'
2657--- cronscripts/parse-ppa-apache-access-logs.py 1970-01-01 00:00:00 +0000
2658+++ cronscripts/parse-ppa-apache-access-logs.py 2010-05-05 01:58:48 +0000
2659@@ -0,0 +1,61 @@
2660+#!/usr/bin/python2.5 -S
2661+#
2662+# Copyright 2010 Canonical Ltd. This software is licensed under the
2663+# GNU Affero General Public License version 3 (see the file LICENSE).
2664+
2665+"""Parse PPA apache logs to find out download counts for each file."""
2666+
2667+__metaclass__ = type
2668+
2669+import _pythonpath
2670+
2671+import functools
2672+
2673+from zope.component import getUtility
2674+
2675+from canonical.config import config
2676+# XXX: wgrant 2010-03-16 bug=539496: Importing directly from
2677+# lp.registry.interfaces.person results in a circular import.
2678+from canonical.launchpad.interfaces import IPersonSet
2679+from lp.soyuz.interfaces.archive import NoSuchPPA
2680+from lp.soyuz.scripts.ppa_apache_log_parser import DBUSER, get_ppa_file_key
2681+from lp.services.apachelogparser.script import ParseApacheLogs
2682+
2683+
2684+class ParsePPAApacheLogs(ParseApacheLogs):
2685+ """An Apache log parser for PPA downloads."""
2686+
2687+ def setUpUtilities(self):
2688+ """See `ParseApacheLogs`."""
2689+ self.person_set = getUtility(IPersonSet)
2690+
2691+ @property
2692+ def root(self):
2693+ """See `ParseApacheLogs`."""
2694+ return config.ppa_apache_log_parser.logs_root
2695+
2696+ def getDownloadKey(self, path):
2697+ """See `ParseApacheLogs`."""
2698+ return get_ppa_file_key(path)
2699+
2700+ def getDownloadCountUpdater(self, file_id):
2701+ """See `ParseApacheLogs`."""
2702+ person = self.person_set.getByName(file_id[0])
2703+ if person is None:
2704+ return
2705+ try:
2706+ archive = person.getPPAByName(file_id[1])
2707+ except NoSuchPPA:
2708+ return None
2709+ # file_id[2] (distro) isn't used yet, since getPPAByName
2710+ # hardcodes Ubuntu.
2711+ bpr = archive.getBinaryPackageReleaseByFileName(file_id[3])
2712+ if bpr is None:
2713+ return None
2714+
2715+ return functools.partial(archive.updatePackageDownloadCount, bpr)
2716+
2717+
2718+if __name__ == '__main__':
2719+ script = ParsePPAApacheLogs('parse-ppa-apache-logs', DBUSER)
2720+ script.lock_and_run()
2721
2722=== modified file 'cronscripts/ppa-generate-keys.py'
2723--- cronscripts/ppa-generate-keys.py 2009-06-24 20:52:01 +0000
2724+++ cronscripts/ppa-generate-keys.py 2010-05-05 01:58:48 +0000
2725@@ -1,4 +1,4 @@
2726-#!/usr/bin/python2.4
2727+#!/usr/bin/python2.5 -S
2728 #
2729 # Copyright 2009 Canonical Ltd. This software is licensed under the
2730 # GNU Affero General Public License version 3 (see the file LICENSE).
2731
2732=== added file 'cronscripts/process-apport-blobs.py'
2733--- cronscripts/process-apport-blobs.py 1970-01-01 00:00:00 +0000
2734+++ cronscripts/process-apport-blobs.py 2010-05-05 01:58:48 +0000
2735@@ -0,0 +1,33 @@
2736+#!/usr/bin/python2.5 -S
2737+#
2738+# Copyright 2010 Canonical Ltd. This software is licensed under the
2739+# GNU Affero General Public License version 3 (see the file LICENSE).
2740+
2741+# pylint: disable-msg=W0403
2742+
2743+"""Process uploaded Apport BLOBs."""
2744+
2745+__metaclass__ = type
2746+
2747+import _pythonpath
2748+
2749+from canonical.launchpad.webapp import errorlog
2750+
2751+from lp.services.job.runner import JobCronScript
2752+from lp.bugs.interfaces.apportjob import IProcessApportBlobJobSource
2753+
2754+
2755+class RunProcessApportBlobs(JobCronScript):
2756+ """Run ProcessApportBlobJobs."""
2757+
2758+ config_name = 'process_apport_blobs'
2759+ source_interface = IProcessApportBlobJobSource
2760+
2761+ def main(self):
2762+ errorlog.globalErrorUtility.configure(self.config_name)
2763+ return super(RunProcessApportBlobs, self).main()
2764+
2765+
2766+if __name__ == '__main__':
2767+ script = RunProcessApportBlobs()
2768+ script.lock_and_run()
2769
2770=== modified file 'cronscripts/process-hwdb-submissions.py'
2771--- cronscripts/process-hwdb-submissions.py 2009-06-24 20:52:01 +0000
2772+++ cronscripts/process-hwdb-submissions.py 2010-05-05 01:58:48 +0000
2773@@ -1,4 +1,4 @@
2774-#!/usr/bin/python2.4
2775+#!/usr/bin/python2.5 -S
2776 #
2777 # Copyright 2009 Canonical Ltd. This software is licensed under the
2778 # GNU Affero General Public License version 3 (see the file LICENSE).
2779@@ -24,7 +24,7 @@
2780 import _pythonpath
2781
2782 from lp.services.scripts.base import LaunchpadCronScript
2783-from canonical.launchpad.scripts.hwdbsubmissions import (
2784+from lp.hardwaredb.scripts.hwdbsubmissions import (
2785 process_pending_submissions)
2786
2787
2788
2789=== modified file 'cronscripts/process-mail.py'
2790--- cronscripts/process-mail.py 2009-06-24 20:52:01 +0000
2791+++ cronscripts/process-mail.py 2010-05-05 01:58:48 +0000
2792@@ -1,4 +1,4 @@
2793-#!/usr/bin/python2.4
2794+#!/usr/bin/python2.5 -S
2795 #
2796 # Copyright 2009 Canonical Ltd. This software is licensed under the
2797 # GNU Affero General Public License version 3 (see the file LICENSE).
2798
2799=== modified file 'cronscripts/process-pending-packagediffs.py'
2800--- cronscripts/process-pending-packagediffs.py 2009-06-24 20:52:01 +0000
2801+++ cronscripts/process-pending-packagediffs.py 2010-05-05 01:58:48 +0000
2802@@ -1,4 +1,4 @@
2803-#!/usr/bin/python2.4
2804+#!/usr/bin/python2.5 -S
2805 #
2806 # Copyright 2009 Canonical Ltd. This software is licensed under the
2807 # GNU Affero General Public License version 3 (see the file LICENSE).
2808
2809=== modified file 'cronscripts/product-release-finder.py'
2810--- cronscripts/product-release-finder.py 2009-06-24 20:52:01 +0000
2811+++ cronscripts/product-release-finder.py 2010-05-05 01:58:48 +0000
2812@@ -1,4 +1,4 @@
2813-#!/usr/bin/python2.4
2814+#!/usr/bin/python2.5 -S
2815 #
2816 # Copyright 2009 Canonical Ltd. This software is licensed under the
2817 # GNU Affero General Public License version 3 (see the file LICENSE).
2818
2819=== modified file 'cronscripts/publishing/cron.germinate'
2820--- cronscripts/publishing/cron.germinate 2009-08-21 09:10:55 +0000
2821+++ cronscripts/publishing/cron.germinate 2010-05-05 01:58:48 +0000
2822@@ -11,6 +11,9 @@
2823 LOCKROOT=$ARCHIVEROOT/..
2824 GERMINATEROOT=$ARCHIVEROOT/../ubuntu-germinate
2825
2826+LAUNCHPADROOT=/srv/launchpad.net/codelines/current
2827+MAINTAINCE_CHECK=$LAUNCHPADROOT/cronscripts/publishing/maintenance-check.py
2828+
2829 ## Check to see if another germinate run is in progress
2830
2831 LOCKFILE=$LOCKROOT/cron.germinate.lock
2832@@ -32,7 +35,7 @@
2833 cd $GERMINATEROOT
2834
2835 # Clean up temporary files
2836-rm -f germinate.output ALL ALL.sources UBUNTU-* KUBUNTU-* EDUBUNTU-* XUBUNTU-* MOBILE-* MYTHBUNTU-* UNR-*
2837+rm -f germinate.output ALL ALL.sources UBUNTU-* KUBUNTU-* EDUBUNTU-* XUBUNTU-* MYTHBUNTU-* NETBOOK-*
2838 rm -f all_* all.sources_*
2839
2840 # Grab a local copy of Sources files
2841@@ -41,11 +44,12 @@
2842 done
2843
2844 > "$MISCROOT/more-extra.override.$suite.main.new"
2845-for distro in ubuntu kubuntu edubuntu xubuntu mobile mythbuntu unr; do
2846+
2847+germinate_components=main,universe,restricted,multiverse
2848+for distro in ubuntu kubuntu edubuntu xubuntu mythbuntu netbook; do
2849 DISTRO="$(echo $distro | tr a-z A-Z)"
2850 germinate_suite="$distro.$suite"
2851- germinate_components=main,universe,restricted,multiverse
2852- for arch in i386 amd64 lpia powerpc sparc ia64 armel; do
2853+ for arch in i386 amd64 powerpc sparc ia64 armel; do
2854 # Grab local copy of Packages and InstallerPackages files
2855 for component in main universe restricted multiverse; do
2856 zcat $ARCHIVEROOT/dists/"$suite"/"$component"/binary-$arch/Packages.gz > archive.ubuntu.com_"$suite"_"$component"_Packages
2857@@ -122,4 +126,10 @@
2858 done
2859 echo " done."
2860
2861+# now generate the Supported extra overrides
2862+$MAINTAINCE_CHECK $suite > "$MISCROOT/more-extra.override.$suite.main.supported" 2> _maintenance-check.stderr
2863+if [ $? -eq 0 ]; then
2864+ cat "$MISCROOT/more-extra.override.$suite.main.supported" >> "$MISCROOT/more-extra.override.$suite.main.new"
2865+fi
2866+
2867 mv -f "$MISCROOT/more-extra.override.$suite.main.new" "$MISCROOT/more-extra.override.$suite.main"
2868
2869=== added file 'cronscripts/publishing/cron.publish-copy-archives'
2870--- cronscripts/publishing/cron.publish-copy-archives 1970-01-01 00:00:00 +0000
2871+++ cronscripts/publishing/cron.publish-copy-archives 2010-05-05 01:58:48 +0000
2872@@ -0,0 +1,83 @@
2873+#!/bin/sh
2874+#
2875+# Copyright 2009 Canonical Ltd. This software is licensed under the
2876+# GNU Affero General Public License version 3 (see the file LICENSE).
2877+
2878+# LPCONFIG will come from the environment so this script can run unaltered
2879+# on dogfood.
2880+if [ -z $LPCONFIG ]; then
2881+ echo LPCONFIG must be set to run this script.
2882+ exit 1
2883+fi
2884+
2885+set -x
2886+set -e
2887+set -u
2888+
2889+#
2890+# This script publishes the COPY (rebuild) archvies *only*.
2891+#
2892+
2893+
2894+# Informational -- this *MUST* match the database.
2895+ARCHIVEROOT=/srv/launchpad.net/ubuntu-archive/ubuntu
2896+DISTSROOT=$ARCHIVEROOT/dists
2897+OVERRIDEROOT=$ARCHIVEROOT/../ubuntu-overrides
2898+INDICES=$ARCHIVEROOT/indices
2899+PRODUCTION_CONFIG=ftpmaster
2900+
2901+if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
2902+ GNUPGHOME=/srv/launchpad.net/ubuntu-archive/gnupg-home
2903+else
2904+ echo GPG keys will come from ~/.gnupg
2905+ # GNUPGHOME does not need to be set, keys can come from ~/.gnupg.
2906+fi
2907+
2908+# Configuration options.
2909+LAUNCHPADROOT=/srv/launchpad.net/codelines/current
2910+LOCKFILE=/srv/launchpad.net/ubuntu-archive/cron.daily.lock
2911+DISTRONAME=ubuntu
2912+TRACEFILE=$ARCHIVEROOT/project/trace/$(hostname --fqdn)
2913+
2914+# Manipulate the environment.
2915+export GNUPGHOME
2916+PATH=$PATH:$LAUNCHPADROOT/scripts:$LAUNCHPADROOT/cronscripts:$LAUNCHPADROOT/cronscripts/publishing:$LAUNCHPADROOT/scripts/ftpmaster-tools
2917+
2918+# Claim the lock.
2919+if ! lockfile -r1 $LOCKFILE; then
2920+ echo "Could not claim lock file."
2921+ exit 1
2922+fi
2923+
2924+# Lock claimed.
2925+
2926+cleanup () {
2927+ echo "Cleaning up lockfile."
2928+ rm -f $LOCKFILE
2929+}
2930+
2931+trap cleanup EXIT
2932+
2933+# Process the accepted queue into the publishing records.
2934+process-accepted.py --copy-archive -v -v -v $DISTRONAME
2935+
2936+# Publish the packages to disk.
2937+publish-distro.py -v -v --copy-archive -d $DISTRONAME
2938+
2939+set +x
2940+
2941+echo Removing uncompressed Packages and Sources files
2942+find ${DISTSROOT} \( -name "Packages" -o -name "Sources" \) -exec rm "{}" \;
2943+
2944+# Copy in the indices.
2945+if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
2946+ echo Copying the indices into place.
2947+ rm -f $INDICES/override.*
2948+ cp $OVERRIDEROOT/override.* $INDICES
2949+fi
2950+
2951+# Timestamp our trace file to track when the last archive publisher run took
2952+# place.
2953+if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
2954+ date -u > "$TRACEFILE"
2955+fi
2956
2957=== modified file 'cronscripts/publishing/cron.publish-ftpmaster'
2958--- cronscripts/publishing/cron.publish-ftpmaster 2009-06-24 20:52:01 +0000
2959+++ cronscripts/publishing/cron.publish-ftpmaster 2010-05-05 01:58:48 +0000
2960@@ -44,10 +44,13 @@
2961 LAUNCHPADROOT=/srv/launchpad.net/codelines/current
2962 LOCKFILE=/srv/launchpad.net/ubuntu-archive/cron.daily.lock
2963 DISTRONAME=ubuntu
2964-TOUCHLIST=$ARCHIVEROOT/project/trace/$(hostname --fqdn)
2965+TRACEFILE=$ARCHIVEROOT/project/trace/$(hostname --fqdn)
2966 DSYNCLIST=$CACHEROOT/dsync.list
2967 MD5LIST=$INDICES/md5sums.gz
2968
2969+# Mirrors to push at the end of the publishing run.
2970+MASTERMIRRORS="syowa frei scandium"
2971+
2972 # Manipulate the environment.
2973 export GNUPGHOME
2974 PATH=$PATH:$LAUNCHPADROOT/scripts:$LAUNCHPADROOT/cronscripts:$LAUNCHPADROOT/cronscripts/publishing:$LAUNCHPADROOT/scripts/ftpmaster-tools
2975@@ -58,12 +61,14 @@
2976 exit 1
2977 fi
2978
2979+echo "$(date -R): Initiating archive publishing operations..."
2980+
2981 DONEPUB=no
2982
2983 cleanup () {
2984- echo "Cleaning up lockfile."
2985+ echo "$(date -R): Cleaning up lockfile."
2986 rm -f $LOCKFILE
2987- echo "Moving dists backup to safe keeping for next time."
2988+ echo "$(date -R): Moving dists backup to safe keeping for next time."
2989 if [ "x$DONEPUB" = "xyes" ]; then
2990 if [ -d ${DISTSROOT}.old ]; then
2991 mv ${DISTSROOT}.old ${DISTSCOPYROOT}/dists
2992@@ -89,11 +94,13 @@
2993 # Lock claimed.
2994
2995 # Process the accepted queue into the publishing records.
2996+echo "$(date -R): Processing the accepted queue into the publishing records..."
2997 process-accepted.py -v -v -v $DISTRONAME
2998
2999 # If doing a security run, find out which suites are pending publication.
3000 SUITEOPTS=""
3001 if [ "$SECURITY_PUBLISHER" = "yes" ]; then
3002+ echo "$(date -R): Querying which suites are pending publication..."
3003 SUITES=$(lp-query-distro.py pending_suites)
3004 SECURITY_SUITES="no"
3005 if [ -n "$SUITES" ]; then
3006@@ -109,7 +116,7 @@
3007 done
3008 fi
3009 if [ "$SECURITY_SUITES" != "yes" ]; then
3010- echo "Nothing to do for security publisher; exiting."
3011+ echo "$(date -R): Nothing to do for security publisher; exiting."
3012 exit 0
3013 fi
3014 fi
3015@@ -122,21 +129,27 @@
3016 # This should achieve the same as copying, only faster.
3017
3018 # Create backup dists folder, if this is the first time.
3019+echo "$(date -R): Creating backup dists directories..."
3020 mkdir -p ${DISTSCOPYROOT}/dists
3021 mkdir -p ${DISTSCOPYROOT_PARTNER}/dists
3022
3023 # Move the backup dists folder into place.
3024+echo "$(date -R): Moving backup dists into place..."
3025 mv ${DISTSCOPYROOT}/dists ${ARCHIVEROOT}/dists.new
3026 mv ${DISTSCOPYROOT_PARTNER}/dists ${ARCHIVEROOT_PARTNER}/dists.new
3027
3028 # Bring it up-to-date efficiently with rsync. --delete is required to
3029 # ensure we don't ressurect things previously deleted, bug 58835.
3030+echo "$(date -R): Updating dists directories..."
3031 rsync -aH --delete ${DISTSROOT}/ ${ARCHIVEROOT}/dists.new
3032 rsync -aH --delete ${DISTSROOT_PARTNER}/ ${ARCHIVEROOT_PARTNER}/dists.new
3033
3034 # Publish the results for all archives (except PPA).
3035 # The -R only affects the primary and the partner archive.
3036+echo "$(date -R): Publishing the $DISTRONAME partner archive..."
3037 publish-distro.py -v -v --partner -d $DISTRONAME -R ${DISTSROOT_PARTNER}.new
3038+
3039+echo "$(date -R): Publishing the $DISTRONAME archive..."
3040 publish-distro.py -v -v -d $DISTRONAME $SUITEOPTS -R ${DISTSROOT}.new
3041
3042 set +x
3043@@ -148,39 +161,40 @@
3044 $(find ${DISTSROOT}.new/*/*/dist-upgrader* -name "*.tar.gz"); do
3045 # [ Release.gpg missing ] or [ Release is newer than Release.gpg ]
3046 if [ ! -f $CANDIDATE.gpg ] || [ $CANDIDATE -nt $CANDIDATE.gpg ]; then
3047- echo "(re-)signing $CANDIDATE"
3048+ echo "$(date -R): (re-)signing $CANDIDATE"
3049 gpg --yes --detach-sign --armor -o $CANDIDATE.gpg --sign $CANDIDATE
3050 else
3051- echo "Not re-signing $CANDIDATE"
3052+ echo "$(date -R): Not re-signing $CANDIDATE"
3053 fi
3054 done
3055 SIGNLIST_PARTNER=$(find ${DISTSROOT_PARTNER}.new -maxdepth 2 -name Release)
3056 for CANDIDATE in $SIGNLIST_PARTNER; do
3057 # [ Release.gpg missing ] or [ Release is newer than Release.gpg ].
3058 if [ ! -f $CANDIDATE.gpg ] || [ $CANDIDATE -nt $CANDIDATE.gpg ]; then
3059- echo "(re-)signing $CANDIDATE"
3060+ echo "$(date -R): (re-)signing $CANDIDATE"
3061 gpg --yes --detach-sign --armor -o $CANDIDATE.gpg --sign $CANDIDATE
3062 else
3063- echo "Not re-signing $CANDIDATE"
3064+ echo "$(date -R): Not re-signing $CANDIDATE"
3065 fi
3066 done
3067
3068 # The Packages and Sources files are very large and would cripple our
3069 # mirrors, so we remove them now that the uncompressed MD5SUMS are in the
3070 # Release files.
3071-echo Removing uncompressed Packages and Sources files
3072+echo "$(date -R): Removing uncompressed Packages and Sources files"
3073 find ${DISTSROOT}.new \( -name "Packages" -o -name "Sources" \) -exec rm "{}" \;
3074 find ${DISTSROOT_PARTNER} \( -name "Packages" -o -name "Sources" \) -exec rm "{}" \;
3075
3076 # Copy in the indices.
3077 if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
3078- echo Copying the indices into place.
3079+ echo "$(date -R): Copying the indices into place."
3080 rm -f $INDICES/override.*
3081 cp $OVERRIDEROOT/override.* $INDICES
3082 fi
3083
3084 # As close to atomically as possible, put the new dists into place for the
3085 # primary and partner archives.
3086+echo "$(date -R): Placing the new dists into place..."
3087 mv $DISTSROOT ${DISTSROOT}.old
3088 mv ${DISTSROOT}.new $DISTSROOT
3089 mv $DISTSROOT_PARTNER ${DISTSROOT_PARTNER}.old
3090@@ -192,19 +206,21 @@
3091 # Generate the -commercial pocket for backwards compatibility with
3092 # dapper, edgy and feisty releases. Don't fail the whole script if it
3093 # fails.
3094+echo "$(date -R): Generating -commerical pocket..."
3095 commercial-compat.sh || true
3096
3097-# Touch everything you asked us to do.
3098+# Timestamp our trace file to track when the last archive publisher run took
3099+# place.
3100 if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
3101- for FILE in $TOUCHLIST; do
3102- touch "$FILE"
3103- done
3104+ echo "$(date -R): Timestamping trace file..."
3105+ date -u > "$TRACEFILE"
3106 fi
3107
3108 # Skip long-running processes when doing a quick security run.
3109 if [ "$SECURITY_PUBLISHER" != "yes" ]; then
3110
3111 # Make the lslr because we all love those.
3112+ echo "$(date -R): Creating ls-lR.gz..."
3113 LSLR=ls-lR.gz
3114 ( cd $ARCHIVEROOT ; \
3115 rm -f .$LSLR.new ; \
3116@@ -216,25 +232,35 @@
3117 mv -f .$LSLR.new $LSLR )
3118
3119 # Run dsync over primary archive only.
3120+ echo "$(date -R): Running dsync over primary archive..."
3121 ( cd $ARCHIVEROOT ; \
3122 dsync-flist -q generate $DSYNCLIST -e 'Packages*' -e 'Sources*' -e 'Release*' --md5 ; \
3123 (dsync-flist -q md5sums $DSYNCLIST; find dists '(' -name 'Packages*' -o -name 'Sources*' -o -name 'Release*' ')' -print | xargs -r md5sum) | gzip -9n > ${MD5LIST} ; \
3124 dsync-flist -q link-dups $DSYNCLIST || true )
3125
3126 # Clear out empty and thus redundant dirs.
3127+ echo "$(date -R): Clearing out empty directories..."
3128 find $ARCHIVEROOT -type d -empty | xargs -r rmdir
3129 find $ARCHIVEROOT_PARTNER -type d -empty | xargs -r rmdir
3130
3131 # Invoke cron.germinate to fill ubuntu tasks and ignore failures,
3132 # the mirrors should be always triggered.
3133- cron.germinate || echo "cron.germinate failed with exit code $?" >&2
3134+ echo "$(date -R): Running cron.germinate..."
3135+ cron.germinate || echo "$(date -R): cron.germinate failed with exit code $?"
3136
3137 # End of block skipped by security publishing.
3138 fi
3139
3140 # Trigger master mirrors.
3141 if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
3142- ssh archvsync@syowa
3143- ssh archvsync@frei
3144- ssh archvsync@rockhopper
3145+ echo "$(date -R): Triggering master mirrors..."
3146+
3147+ for HOST in $MASTERMIRRORS; do
3148+ echo "$(date -R): Triggering $HOST:"
3149+ ssh archvsync@$HOST
3150+ done
3151+
3152+ echo "$(date -R): Master mirror triggers completed."
3153 fi
3154+
3155+echo "$(date -R): Archive publishing operations completed."
3156
3157=== added file 'cronscripts/publishing/maintenance-check.py'
3158--- cronscripts/publishing/maintenance-check.py 1970-01-01 00:00:00 +0000
3159+++ cronscripts/publishing/maintenance-check.py 2010-05-05 01:58:48 +0000
3160@@ -0,0 +1,382 @@
3161+#!/usr/bin/python
3162+#
3163+# python port of the nice maintainace-check script by Nick Barcet
3164+#
3165+# taken from:
3166+# https://code.edge.launchpad.net/~mvo/ubuntu-maintenance-check/python-port
3167+# (where it will vanish once taken here)
3168+
3169+# this warning filter is only needed on older versions of python-apt,
3170+# once the machine runs lucid it can be removed
3171+import warnings
3172+warnings.filterwarnings("ignore","apt API not stable yet")
3173+import apt
3174+warnings.resetwarnings()
3175+
3176+import apt_pkg
3177+import logging
3178+import os
3179+import sys
3180+import urllib2
3181+import urlparse
3182+
3183+from optparse import OptionParser
3184+
3185+# This is fun! We have a bunch of cases for 10.04 LTS
3186+#
3187+# - distro "ubuntu" follows SUPPORT_TIMEFRAME_LTS but only for
3188+# amd64/i386
3189+# - distros "kubuntu", "edubuntu" and "netbook" need to be
3190+# considered *but* only follow SUPPORT_TIMEFRAME
3191+# - anything that is in armel follows SUPPORT_TIMEFRAME
3192+#
3193+
3194+# codename of the lts releases
3195+LTS_RELEASES = [ "dapper", "hardy", "lucid" ]
3196+
3197+# architectures that are full supported (including LTS time)
3198+PRIMARY_ARCHES = ["i386", "amd64"]
3199+
3200+# architectures we support (but not for LTS time)
3201+SUPPORTED_ARCHES = PRIMARY_ARCHES + ["armel"]
3202+
3203+# what defines the seeds is documented in wiki.ubuntu.com/SeedManagement
3204+SERVER_SEEDS = [ "supported-server", "server-ship"]
3205+DESKTOP_SEEDS = ["ship", "supported-desktop", "supported-desktop-extra"]
3206+SUPPORTED_SEEDS = [ "all" ]
3207+
3208+# normal support timeframe
3209+# time, seeds, arches
3210+SUPPORT_TIMEFRAME = [
3211+ ("18m", SUPPORTED_SEEDS),
3212+]
3213+
3214+# lts support timeframe
3215+# time, seeds, arches
3216+SUPPORT_TIMEFRAME_LTS = [
3217+ ("5y", SERVER_SEEDS),
3218+ ("3y", DESKTOP_SEEDS),
3219+ ("18m", SUPPORTED_SEEDS),
3220+]
3221+
3222+# distro names and if they get LTS support (order is important)
3223+DISTRO_NAMES_AND_LTS_SUPPORT = [ ("ubuntu", True),
3224+ ("kubuntu", True),
3225+ ("netbook", False),
3226+ ]
3227+
3228+# germinate output base directory
3229+BASE_URL = "http://people.canonical.com/~ubuntu-archive/germinate-output/"
3230+
3231+# hints dir url, hints file is "$distro.hints" by default
3232+# (e.g. lucid.hints)
3233+HINTS_DIR_URL = "http://people.canonical.com/~ubuntu-archive/seeds/platform.%s/SUPPORTED_HINTS"
3234+
3235+# we need the archive root to parse the Sources file to support
3236+# by-source hints
3237+ARCHIVE_ROOT = "http://archive.ubuntu.com/ubuntu"
3238+
3239+# support timeframe tag used in the Packages file
3240+SUPPORT_TAG = "Supported"
3241+
3242+def get_binaries_for_source_pkg(srcname):
3243+ """ Return all binary package names for the given source package name.
3244+
3245+ :param srcname: The source package name.
3246+ :return: A list of binary package names.
3247+ """
3248+ pkgnames = set()
3249+ recs = apt_pkg.GetPkgSrcRecords()
3250+ while recs.Lookup(srcname):
3251+ for binary in recs.Binaries:
3252+ pkgnames.add(binary)
3253+ return pkgnames
3254+
3255+def expand_src_pkgname(pkgname):
3256+ """ Expand a package name if it is prefixed with src.
3257+
3258+ If the package name is prefixed with src it will be expanded
3259+ to a list of binary package names. Otherwise the original
3260+ package name will be returned.
3261+
3262+ :param pkgname: The package name (that may include src:prefix).
3263+ :return: A list of binary package names (the list may be one element long).
3264+ """
3265+ if not pkgname.startswith("src:"):
3266+ return [pkgname]
3267+ return get_binaries_for_source_pkg(pkgname.split("src:")[1])
3268+
3269+def create_and_update_deb_src_source_list(distroseries):
3270+ """ Create sources.list and update cache.
3271+
3272+ This creates a sources.list file with deb-src entries for a given
3273+ distroseries and apt.Cache.update() to make sure the data is up-to-date.
3274+ :param distro: The code name of the distribution series (e.g. lucid).
3275+ :return: None
3276+ :raises: IOError: When cache update fails.
3277+ """
3278+ # apt root dir
3279+ rootdir="./aptroot.%s" % distroseries
3280+ sources_list_dir = os.path.join(rootdir, "etc","apt")
3281+ if not os.path.exists(sources_list_dir):
3282+ os.makedirs(sources_list_dir)
3283+ sources_list = open(os.path.join(sources_list_dir, "sources.list"),"w")
3284+ for pocket in [
3285+ "%s" % distroseries,
3286+ "%s-updates" % distroseries,
3287+ "%s-security" % distroseries]:
3288+ sources_list.write(
3289+ "deb-src %s %s main restricted\n" % (
3290+ ARCHIVE_ROOT, pocket))
3291+ sources_list.write(
3292+ "deb %s %s main restricted\n" % (
3293+ ARCHIVE_ROOT, pocket))
3294+ sources_list.close()
3295+ # create required dirs/files for apt.Cache(rootdir) to work on older
3296+ # versions of python-apt. once lucid is used it can be removed
3297+ for d in ["var/lib/dpkg",
3298+ "var/cache/apt/archives/partial",
3299+ "var/lib/apt/lists/partial"]:
3300+ if not os.path.exists(os.path.join(rootdir,d)):
3301+ os.makedirs(os.path.join(rootdir,d))
3302+ if not os.path.exists(os.path.join(rootdir,"var/lib/dpkg/status")):
3303+ open(os.path.join(rootdir,"var/lib/dpkg/status"),"w")
3304+ # open cache with our just prepared rootdir
3305+ cache = apt.Cache(rootdir=rootdir)
3306+ try:
3307+ cache.update(apt.progress.FetchProgress())
3308+ except SystemError:
3309+ logging.exception("cache.update() failed")
3310+
3311+def get_structure(distroname, version):
3312+ """ Get structure file conent for named distro and distro version.
3313+
3314+ :param name: Name of the distribution (e.g. kubuntu, ubuntu, xubuntu).
3315+ :param version: Code name of the distribution version (e.g. lucid).
3316+ :return: List of strings with the structure file content
3317+ """
3318+ f = urllib2.urlopen("%s/%s.%s/structure" % (BASE_URL, distroname, version))
3319+ structure = f.readlines()
3320+ f.close()
3321+ return structure
3322+
3323+def expand_seeds(structure, seedname):
3324+ """ Expand seed by its dependencies using the strucure file.
3325+
3326+ :param structure: The content of the STRUCTURE file as string list.
3327+ :param seedname: The name of the seed as string that needs to be expanded.
3328+ :return: a set() for the seed dependencies (excluding the original seedname)
3329+ """
3330+ seeds = []
3331+ for line in structure:
3332+ if line.startswith("%s:" % seedname):
3333+ seeds += line.split(":")[1].split()
3334+ for seed in seeds:
3335+ seeds += expand_seeds(structure, seed)
3336+ return set(seeds)
3337+
3338+def get_packages_for_seeds(name, distro, seeds):
3339+ """
3340+ get packages for the given name (e.g. ubuntu) and distro release
3341+ (e.g. lucid) that are in the given list of seeds
3342+ returns a set() of package names
3343+ """
3344+ pkgs_in_seeds = {}
3345+ for bseed in seeds:
3346+ for seed in [bseed]: #, bseed+".build-depends", bseed+".seed"]:
3347+ pkgs_in_seeds[seed] = set()
3348+ seedurl = "%s/%s.%s/%s" % (BASE_URL,name, distro, seed)
3349+ logging.debug("looking for '%s'" % seedurl)
3350+ try:
3351+ f = urllib2.urlopen(seedurl)
3352+ for line in f:
3353+ # ignore lines that are not a package name (headers etc)
3354+ if line[0] < 'a' or line[0] > 'z':
3355+ continue
3356+ # lines are (package,source,why,maintainer,size,inst-size)
3357+ if options.source_packages:
3358+ pkgname = line.split("|")[1]
3359+ else:
3360+ pkgname = line.split("|")[0]
3361+ pkgs_in_seeds[seed].add(pkgname.strip())
3362+ f.close()
3363+ except Exception, e:
3364+ logging.error("seed %s failed (%s)" % (seedurl, e))
3365+ return pkgs_in_seeds
3366+
3367+def what_seeds(pkgname, seeds):
3368+ in_seeds = set()
3369+ for s in seeds:
3370+ if pkgname in seeds[s]:
3371+ in_seeds.add(s)
3372+ return in_seeds
3373+
3374+def compare_support_level(x, y):
3375+ """
3376+ compare two support level strings of the form 18m, 3y etc
3377+ :parm x: the first support level
3378+ :parm y: the second support level
3379+ :return: negative if x < y, zero if x==y, positive if x > y
3380+ """
3381+ def support_to_int(support_time):
3382+ """
3383+ helper that takes a support time string and converts it to
3384+ a integer for cmp()
3385+ """
3386+ # allow strings like "5y (kubuntu-common)
3387+ x = support_time.split()[0]
3388+ if x.endswith("y"):
3389+ return 12 * int(x[0:-1])
3390+ elif x.endswith("m"):
3391+ return int(x[0:-1])
3392+ else:
3393+ raise ValueError("support time '%s' has to end with y or m" % x)
3394+ return cmp(support_to_int(x), support_to_int(y))
3395+
3396+def get_packages_support_time(structure, name, pkg_support_time, support_timeframe_list):
3397+ """
3398+ input a structure file and a list of pair<timeframe, seedlist>
3399+ return a dict of pkgnames -> support timeframe string
3400+ """
3401+ for (timeframe, seedlist) in support_timeframe_list:
3402+ expanded = set()
3403+ for s in seedlist:
3404+ expanded.add(s)
3405+ expanded |= expand_seeds(structure, s)
3406+ pkgs_in_seeds = get_packages_for_seeds(name, distro, expanded)
3407+ for seed in pkgs_in_seeds:
3408+ for pkg in pkgs_in_seeds[seed]:
3409+ if not pkg in pkg_support_time:
3410+ pkg_support_time[pkg] = timeframe
3411+ else:
3412+ old_timeframe = pkg_support_time[pkg]
3413+ if compare_support_level(old_timeframe, timeframe) < 0:
3414+ logging.debug("overwriting %s from %s to %s" % (
3415+ pkg, old_timeframe, timeframe))
3416+ pkg_support_time[pkg] = timeframe
3417+ if options.with_seeds:
3418+ pkg_support_time[pkg] += " (%s)" % ", ".join(what_seeds(pkg, pkgs_in_seeds))
3419+
3420+
3421+ return pkg_support_time
3422+
3423+if __name__ == "__main__":
3424+ parser = OptionParser()
3425+ parser.add_option("--with-seeds", "", default=False,
3426+ action="store_true",
3427+ help="add seed(s) of the package that are responsible for the maintaince time")
3428+ parser.add_option("--source-packages", "", default=False,
3429+ action="store_true",
3430+ help="show as source pkgs")
3431+ parser.add_option("--hints-file", "", default=None,
3432+ help="use diffenrt use hints file location")
3433+ (options, args) = parser.parse_args()
3434+
3435+ # init
3436+ if len(args) > 0:
3437+ distro = args[0]
3438+ if distro[0] < 'h':
3439+ print "ERROR: only hardy or later is supported"
3440+ sys.exit(1)
3441+ else:
3442+ distro = "lucid"
3443+
3444+ # make sure our deb-src information is up-to-date
3445+ create_and_update_deb_src_source_list(distro)
3446+
3447+ if options.hints_file:
3448+ hints_file = options.hints_file
3449+ (schema, netloc, path, query, fragment) = urlparse.urlsplit(hints_file)
3450+ if not schema:
3451+ hints_file = "file:%s" % path
3452+ else:
3453+ hints_file = HINTS_DIR_URL % distro
3454+
3455+ # go over the distros we need to check
3456+ pkg_support_time = {}
3457+ for (name, lts_supported) in DISTRO_NAMES_AND_LTS_SUPPORT:
3458+
3459+ # get basic structure file
3460+ structure = get_structure(name, distro)
3461+
3462+ # get dicts of pkgname -> support timeframe string
3463+ support_timeframe = SUPPORT_TIMEFRAME
3464+ if lts_supported and distro in LTS_RELEASES:
3465+ support_timeframe = SUPPORT_TIMEFRAME_LTS
3466+ else:
3467+ support_timeframe = SUPPORT_TIMEFRAME
3468+ get_packages_support_time(structure, name, pkg_support_time, support_timeframe)
3469+
3470+ # now go over the bits in main that we have not seen (because
3471+ # they are not in any seed and got added manually into "main"
3472+ for arch in PRIMARY_ARCHES:
3473+ rootdir="./aptroot.%s" % distro
3474+ apt_pkg.Config.Set("APT::Architecture", arch)
3475+ cache = apt.Cache(rootdir=rootdir)
3476+ try:
3477+ cache.update(apt.progress.FetchProgress())
3478+ except SystemError:
3479+ logging.exception("cache.update() failed")
3480+ cache.open(apt.progress.OpProgress())
3481+ for pkg in cache:
3482+ if not pkg.name in pkg_support_time:
3483+ pkg_support_time[pkg.name] = support_timeframe[-1][0]
3484+ logging.warn("add package in main but not in seeds %s with %s" %
3485+ (pkg.name, pkg_support_time[pkg.name]))
3486+
3487+ # now check the hints file that is used to overwrite
3488+ # the default seeds
3489+ try:
3490+ for line in urllib2.urlopen(hints_file):
3491+ line = line.strip()
3492+ if not line or line.startswith("#"):
3493+ continue
3494+ try:
3495+ (raw_pkgname, support_time) = line.split()
3496+ for pkgname in expand_src_pkgname(raw_pkgname):
3497+ if support_time == 'unsupported':
3498+ try:
3499+ del pkg_support_time[pkgname]
3500+ sys.stderr.write("hints-file: marking %s unsupported\n" % pkgname)
3501+ except KeyError:
3502+ pass
3503+ else:
3504+ if pkg_support_time.get(pkgname) != support_time:
3505+ sys.stderr.write(
3506+ "hints-file: changing %s from %s to %s\n" % (
3507+ pkgname, pkg_support_time.get(pkgname),
3508+ support_time))
3509+ pkg_support_time[pkgname] = support_time
3510+ except:
3511+ logging.exception("can not parse line '%s'" % line)
3512+ except urllib2.HTTPError, e:
3513+ if e.getcode() != 404:
3514+ raise
3515+ sys.stderr.write("hints-file: %s gave 404 error\n" % hints_file)
3516+
3517+ # output suitable for the extra-override file
3518+ for pkgname in sorted(pkg_support_time.keys()):
3519+ # special case, the hints file may contain overrides that
3520+ # are arch-specific (like zsh-doc/armel)
3521+ if "/" in pkgname:
3522+ print "%s %s %s" % (
3523+ pkgname, SUPPORT_TAG, pkg_support_time[pkgname])
3524+ else:
3525+ # go over the supported arches, they are divided in
3526+ # first-class (PRIMARY) and second-class with different
3527+ # support levels
3528+ for arch in SUPPORTED_ARCHES:
3529+ # ensure we do not overwrite arch-specific overwrites
3530+ pkgname_and_arch = "%s/%s" % (pkgname, arch)
3531+ if pkgname_and_arch in pkg_support_time:
3532+ break
3533+ if arch in PRIMARY_ARCHES:
3534+ # arch with full LTS support
3535+ print "%s %s %s" % (
3536+ pkgname_and_arch, SUPPORT_TAG, pkg_support_time[pkgname])
3537+ else:
3538+ # not a LTS supported architecture, gets only regular
3539+ # support_timeframe
3540+ print "%s %s %s" % (
3541+ pkgname_and_arch, SUPPORT_TAG, SUPPORT_TIMEFRAME[0][0])
3542+
3543
3544=== modified file 'cronscripts/reclaimbranchspace.py'
3545--- cronscripts/reclaimbranchspace.py 2009-09-03 20:06:45 +0000
3546+++ cronscripts/reclaimbranchspace.py 2010-05-05 01:58:48 +0000
3547@@ -1,4 +1,4 @@
3548-#!/usr/bin/python2.4
3549+#!/usr/bin/python2.5 -S
3550 #
3551 # Copyright 2009 Canonical Ltd. This software is licensed under the
3552 # GNU Affero General Public License version 3 (see the file LICENSE).
3553
3554=== modified file 'cronscripts/rosetta-approve-imports.py'
3555--- cronscripts/rosetta-approve-imports.py 2009-09-26 06:21:08 +0000
3556+++ cronscripts/rosetta-approve-imports.py 2010-05-05 01:58:48 +0000
3557@@ -1,4 +1,4 @@
3558-#! /usr/bin/python2.4
3559+#!/usr/bin/python2.5 -S
3560 #
3561 # Copyright 2009 Canonical Ltd. This software is licensed under the
3562 # GNU Affero General Public License version 3 (see the file LICENSE).
3563
3564=== modified file 'cronscripts/rosetta-branches.py'
3565--- cronscripts/rosetta-branches.py 2009-09-03 20:29:25 +0000
3566+++ cronscripts/rosetta-branches.py 2010-05-05 01:58:48 +0000
3567@@ -1,4 +1,4 @@
3568-#!/usr/bin/python2.4
3569+#!/usr/bin/python2.5 -S
3570 #
3571 # Copyright 2009 Canonical Ltd. This software is licensed under the
3572 # GNU Affero General Public License version 3 (see the file LICENSE).
3573@@ -17,7 +17,7 @@
3574 from zope.component import getUtility
3575
3576 from canonical.config import config
3577-from lp.codehosting.vfs.branchfs import get_scanner_server
3578+from lp.codehosting.vfs.branchfs import get_ro_server
3579 from lp.services.job.runner import JobRunner
3580 from lp.code.interfaces.branchjob import IRosettaUploadJobSource
3581 from lp.services.scripts.base import LaunchpadCronScript
3582@@ -31,12 +31,12 @@
3583 globalErrorUtility.configure('rosettabranches')
3584 runner = JobRunner.fromReady(
3585 getUtility(IRosettaUploadJobSource), self.logger)
3586- server = get_scanner_server()
3587- server.setUp()
3588+ server = get_ro_server()
3589+ server.start_server()
3590 try:
3591 runner.runAll()
3592 finally:
3593- server.tearDown()
3594+ server.stop_server()
3595 self.logger.info('Ran %d RosettaBranchJobs.',
3596 len(runner.completed_jobs))
3597
3598
3599=== modified file 'cronscripts/rosetta-export-queue.py'
3600--- cronscripts/rosetta-export-queue.py 2009-07-17 00:26:05 +0000
3601+++ cronscripts/rosetta-export-queue.py 2010-05-05 01:58:48 +0000
3602@@ -1,4 +1,4 @@
3603-#!/usr/bin/python2.4
3604+#!/usr/bin/python2.5 -S
3605 #
3606 # Copyright 2009 Canonical Ltd. This software is licensed under the
3607 # GNU Affero General Public License version 3 (see the file LICENSE).
3608
3609=== modified file 'cronscripts/rosetta-pofile-stats-daily.py'
3610--- cronscripts/rosetta-pofile-stats-daily.py 2009-08-07 17:58:19 +0000
3611+++ cronscripts/rosetta-pofile-stats-daily.py 2010-05-05 01:58:48 +0000
3612@@ -1,4 +1,4 @@
3613-#!/usr/bin/python2.4
3614+#!/usr/bin/python2.5 -S
3615 #
3616 # Copyright 2009 Canonical Ltd. This software is licensed under the
3617 # GNU Affero General Public License version 3 (see the file LICENSE).
3618
3619=== modified file 'cronscripts/rosetta-pofile-stats.py'
3620--- cronscripts/rosetta-pofile-stats.py 2009-08-06 12:30:58 +0000
3621+++ cronscripts/rosetta-pofile-stats.py 2010-05-05 01:58:48 +0000
3622@@ -1,4 +1,4 @@
3623-#!/usr/bin/python2.4
3624+#!/usr/bin/python2.5 -S
3625 #
3626 # Copyright 2009 Canonical Ltd. This software is licensed under the
3627 # GNU Affero General Public License version 3 (see the file LICENSE).
3628
3629=== modified file 'cronscripts/rosetta-poimport.py'
3630--- cronscripts/rosetta-poimport.py 2009-09-29 15:33:30 +0000
3631+++ cronscripts/rosetta-poimport.py 2010-05-05 01:58:48 +0000
3632@@ -1,4 +1,4 @@
3633-#!/usr/bin/python2.4
3634+#!/usr/bin/python2.5 -S
3635 #
3636 # Copyright 2009 Canonical Ltd. This software is licensed under the
3637 # GNU Affero General Public License version 3 (see the file LICENSE).
3638
3639=== added file 'cronscripts/scan_branches.py'
3640--- cronscripts/scan_branches.py 1970-01-01 00:00:00 +0000
3641+++ cronscripts/scan_branches.py 2010-05-05 01:58:48 +0000
3642@@ -0,0 +1,25 @@
3643+#!/usr/bin/python2.5 -S
3644+#
3645+# Copyright 2010 Canonical Ltd. This software is licensed under the
3646+# GNU Affero General Public License version 3 (see the file LICENSE).
3647+
3648+"""Scan branches for new revisions."""
3649+
3650+__metaclass__ = type
3651+
3652+import _pythonpath
3653+
3654+from lp.services.job.runner import JobCronScript
3655+from lp.code.interfaces.branchjob import IBranchScanJobSource
3656+
3657+
3658+class RunScanBranches(JobCronScript):
3659+ """Run BranchScanJob jobs."""
3660+
3661+ config_name = 'branchscanner'
3662+ source_interface = IBranchScanJobSource
3663+
3664+
3665+if __name__ == '__main__':
3666+ script = RunScanBranches()
3667+ script.lock_and_run()
3668
3669=== modified file 'cronscripts/send-bug-notifications.py'
3670--- cronscripts/send-bug-notifications.py 2009-06-24 20:52:01 +0000
3671+++ cronscripts/send-bug-notifications.py 2010-05-05 01:58:48 +0000
3672@@ -1,4 +1,4 @@
3673-#!/usr/bin/python2.4
3674+#!/usr/bin/python2.5 -S
3675 #
3676 # Copyright 2009 Canonical Ltd. This software is licensed under the
3677 # GNU Affero General Public License version 3 (see the file LICENSE).
3678
3679=== modified file 'cronscripts/send-person-notifications.py'
3680--- cronscripts/send-person-notifications.py 2009-06-24 20:52:01 +0000
3681+++ cronscripts/send-person-notifications.py 2010-05-05 01:58:48 +0000
3682@@ -1,4 +1,4 @@
3683-#!/usr/bin/python2.4
3684+#!/usr/bin/python2.5 -S
3685 #
3686 # Copyright 2009 Canonical Ltd. This software is licensed under the
3687 # GNU Affero General Public License version 3 (see the file LICENSE).
3688@@ -14,15 +14,11 @@
3689 __metaclass__ = type
3690
3691 import _pythonpath
3692-from datetime import timedelta, datetime
3693-import pytz
3694-
3695-from zope.component import getUtility
3696
3697 from canonical.config import config
3698-from canonical.launchpad.interfaces.personnotification import (
3699- IPersonNotificationSet)
3700+
3701 from lp.services.scripts.base import LaunchpadCronScript
3702+from lp.registry.scripts.personnotification import PersonNotificationManager
3703
3704
3705 class SendPersonNotifications(LaunchpadCronScript):
3706@@ -36,39 +32,9 @@
3707 """
3708
3709 def main(self):
3710- notifications_sent = False
3711- notification_set = getUtility(IPersonNotificationSet)
3712- pending_notifications = notification_set.getNotificationsToSend()
3713- self.logger.info(
3714- '%d notification(s) to send.' % pending_notifications.count())
3715- for notification in pending_notifications:
3716- person = notification.person
3717- self.logger.info(
3718- "Sending notification to %s <%s>."
3719- % (person.name, person.preferredemail.email))
3720- notification.send()
3721- notifications_sent = True
3722- # Commit after each email sent, so that we won't re-mail the
3723- # notifications in case of something going wrong in the middle.
3724- self.txn.commit()
3725-
3726- if not notifications_sent:
3727- self.logger.debug("No notifications were sent.")
3728-
3729- # Delete PersonNotifications that are older than the retention
3730- # limit set in the configuration.
3731- retained_days = timedelta(
3732- days=int(config.person_notification.retained_days))
3733- time_limit = (datetime.now(pytz.timezone('UTC')) - retained_days)
3734- to_delete = notification_set.getNotificationsOlderThan(time_limit)
3735- if to_delete.count():
3736- self.logger.info(
3737- "Notification retention limit is %s." % retained_days)
3738- self.logger.info(
3739- "Deleting %d old notification(s)." % to_delete.count())
3740- for notification in to_delete:
3741- notification.destroySelf()
3742- self.txn.commit()
3743+ manager = PersonNotificationManager(self.txn, self.logger)
3744+ unsent_notifications = manager.sendNotifications()
3745+ manager.purgeNotifications(unsent_notifications)
3746
3747
3748 if __name__ == '__main__':
3749
3750=== modified file 'cronscripts/sendbranchmail.py'
3751--- cronscripts/sendbranchmail.py 2009-09-03 19:25:57 +0000
3752+++ cronscripts/sendbranchmail.py 2010-05-05 01:58:48 +0000
3753@@ -1,4 +1,4 @@
3754-#!/usr/bin/python2.4
3755+#!/usr/bin/python2.5 -S
3756 #
3757 # Copyright 2009 Canonical Ltd. This software is licensed under the
3758 # GNU Affero General Public License version 3 (see the file LICENSE).
3759@@ -16,7 +16,7 @@
3760 from zope.component import getUtility
3761
3762 from canonical.config import config
3763-from lp.codehosting.vfs import get_scanner_server
3764+from lp.codehosting.vfs import get_ro_server
3765 from lp.services.job.runner import JobRunner
3766 from lp.code.interfaces.branchjob import (
3767 IRevisionMailJobSource, IRevisionsAddedJobSource)
3768@@ -32,12 +32,12 @@
3769 jobs = list(getUtility(IRevisionMailJobSource).iterReady())
3770 jobs.extend(getUtility(IRevisionsAddedJobSource).iterReady())
3771 runner = JobRunner(jobs, self.logger)
3772- server = get_scanner_server()
3773- server.setUp()
3774+ server = get_ro_server()
3775+ server.start_server()
3776 try:
3777 runner.runAll()
3778 finally:
3779- server.tearDown()
3780+ server.stop_server()
3781 self.logger.info(
3782 'Ran %d RevisionMailJobs.' % len(runner.completed_jobs))
3783
3784
3785=== modified file 'cronscripts/supermirror-pull.py'
3786--- cronscripts/supermirror-pull.py 2009-09-29 00:26:59 +0000
3787+++ cronscripts/supermirror-pull.py 2010-05-05 01:58:48 +0000
3788@@ -1,4 +1,4 @@
3789-#!/usr/bin/python2.4
3790+#!/usr/bin/python2.5 -S
3791 #
3792 # Copyright 2009 Canonical Ltd. This software is licensed under the
3793 # GNU Affero General Public License version 3 (see the file LICENSE).
3794@@ -11,10 +11,10 @@
3795 from twisted.internet import defer, reactor
3796 from twisted.python import log as tplog
3797
3798-from lp.codehosting.puller import mirror, scheduler
3799 from canonical.config import config
3800 from canonical.launchpad.scripts import logger_options
3801-from canonical.twistedsupport.loggingsupport import (
3802+from lp.codehosting.puller import mirror, scheduler
3803+from lp.services.twistedsupport.loggingsupport import (
3804 LoggingProxy, set_up_logging_for_script)
3805
3806 def clean_shutdown(ignored):
3807@@ -38,12 +38,14 @@
3808 if __name__ == '__main__':
3809 parser = OptionParser()
3810 logger_options(parser)
3811+ parser.add_option('--branch-type', action='append', default=[])
3812 (options, arguments) = parser.parse_args()
3813 if arguments:
3814 parser.error("Unhandled arguments %s" % repr(arguments))
3815 log = set_up_logging_for_script(options, 'supermirror_puller')
3816 manager = scheduler.JobScheduler(
3817- LoggingProxy(config.codehosting.branch_puller_endpoint, log), log)
3818+ LoggingProxy(config.codehosting.codehosting_endpoint, log), log,
3819+ options.branch_type)
3820
3821 reactor.callWhenRunning(run_mirror, log, manager)
3822 reactor.run()
3823
3824=== modified file 'cronscripts/translations-export-to-branch.py'
3825--- cronscripts/translations-export-to-branch.py 2009-07-17 18:46:25 +0000
3826+++ cronscripts/translations-export-to-branch.py 2010-05-05 01:58:48 +0000
3827@@ -1,4 +1,4 @@
3828-#!/usr/bin/python2.4
3829+#!/usr/bin/python2.5 -S
3830 # pylint: disable-msg=W0403
3831 #
3832 # Copyright 2009 Canonical Ltd. This software is licensed under the
3833
3834=== modified file 'cronscripts/update-bugtask-targetnamecaches.py'
3835--- cronscripts/update-bugtask-targetnamecaches.py 2009-06-24 20:52:01 +0000
3836+++ cronscripts/update-bugtask-targetnamecaches.py 2010-05-05 01:58:48 +0000
3837@@ -1,4 +1,4 @@
3838-#!/usr/bin/python2.4
3839+#!/usr/bin/python2.5 -S
3840 #
3841 # Copyright 2009 Canonical Ltd. This software is licensed under the
3842 # GNU Affero General Public License version 3 (see the file LICENSE).
3843
3844=== modified file 'cronscripts/update-cve.py'
3845--- cronscripts/update-cve.py 2009-06-24 20:52:01 +0000
3846+++ cronscripts/update-cve.py 2010-05-05 01:58:48 +0000
3847@@ -1,4 +1,4 @@
3848-#!/usr/bin/python2.4
3849+#!/usr/bin/python2.5 -S
3850 #
3851 # Copyright 2009 Canonical Ltd. This software is licensed under the
3852 # GNU Affero General Public License version 3 (see the file LICENSE).
3853
3854=== modified file 'cronscripts/update-debwatches.py'
3855--- cronscripts/update-debwatches.py 2009-06-24 20:52:01 +0000
3856+++ cronscripts/update-debwatches.py 2010-05-05 01:58:48 +0000
3857@@ -1,4 +1,4 @@
3858-#!/usr/bin/python2.4
3859+#!/usr/bin/python2.5 -S
3860 #
3861 # Copyright 2009 Canonical Ltd. This software is licensed under the
3862 # GNU Affero General Public License version 3 (see the file LICENSE).
3863@@ -6,11 +6,11 @@
3864 # This script runs through the set of Debbugs watches, and tries to
3865 # syncronise each of those to the malone bug which is watching it.
3866
3867+import _pythonpath
3868 import os
3869 import sys
3870 import email
3871 import logging
3872-import _pythonpath
3873
3874 # zope bits
3875 from zope.component import getUtility
3876
3877=== modified file 'cronscripts/update-pkgcache.py'
3878--- cronscripts/update-pkgcache.py 2009-06-24 20:52:01 +0000
3879+++ cronscripts/update-pkgcache.py 2010-05-05 01:58:48 +0000
3880@@ -1,4 +1,4 @@
3881-#!/usr/bin/python2.4
3882+#!/usr/bin/python2.5 -S
3883 #
3884 # Copyright 2009 Canonical Ltd. This software is licensed under the
3885 # GNU Affero General Public License version 3 (see the file LICENSE).
3886@@ -47,7 +47,7 @@
3887 PPA archives caches are consolidated in a Archive row to optimize
3888 searches across PPAs.
3889 """
3890- for distroseries in distribution.serieses:
3891+ for distroseries in distribution.series:
3892 self.updateDistroSeriesCache(distroseries, archive)
3893
3894 distribution.removeOldCacheItems(archive, log=self.logger)
3895@@ -101,6 +101,6 @@
3896
3897 if __name__ == '__main__':
3898 script = PackageCacheUpdater(
3899- 'update-cache', dbuser=config.statistician.dbuser)
3900+ 'update-cache', dbuser="update-pkg-cache")
3901 script.lock_and_run()
3902
3903
3904=== modified file 'cronscripts/update-remote-product.py'
3905--- cronscripts/update-remote-product.py 2009-06-24 20:52:01 +0000
3906+++ cronscripts/update-remote-product.py 2010-05-05 01:58:48 +0000
3907@@ -1,14 +1,14 @@
3908-#!/usr/bin/python2.4
3909+#!/usr/bin/python2.5 -S
3910 #
3911 # Copyright 2009 Canonical Ltd. This software is licensed under the
3912 # GNU Affero General Public License version 3 (see the file LICENSE).
3913
3914+"""Cron job to update Product.remote_product using bug watch information. """
3915+
3916 # pylint: disable-msg=W0403
3917-
3918-"""Cron job to update Product.remote_product using bug watch information. """
3919+import _pythonpath
3920
3921 import time
3922-import _pythonpath
3923
3924 from canonical.config import config
3925 from lp.services.scripts.base import LaunchpadCronScript
3926
3927=== modified file 'cronscripts/update-sourceforge-remote-products.py'
3928--- cronscripts/update-sourceforge-remote-products.py 2009-06-24 20:52:01 +0000
3929+++ cronscripts/update-sourceforge-remote-products.py 2010-05-05 01:58:48 +0000
3930@@ -1,14 +1,14 @@
3931-#!/usr/bin/python2.4
3932+#!/usr/bin/python2.5 -S
3933 #
3934 # Copyright 2009 Canonical Ltd. This software is licensed under the
3935 # GNU Affero General Public License version 3 (see the file LICENSE).
3936
3937+"""Cron job to update remote_products using SourceForge project data."""
3938+
3939 # pylint: disable-msg=W0403
3940-
3941-"""Cron job to update remote_products using SourceForge project data."""
3942+import _pythonpath
3943
3944 import time
3945-import _pythonpath
3946
3947 from canonical.config import config
3948 from lp.services.scripts.base import LaunchpadCronScript
3949
3950=== modified file 'cronscripts/update-standing.py'
3951--- cronscripts/update-standing.py 2009-06-24 20:52:01 +0000
3952+++ cronscripts/update-standing.py 2010-05-05 01:58:48 +0000
3953@@ -1,4 +1,4 @@
3954-#!/usr/bin/python2.4
3955+#!/usr/bin/python2.5 -S
3956 #
3957 # Copyright 2009 Canonical Ltd. This software is licensed under the
3958 # GNU Affero General Public License version 3 (see the file LICENSE).
3959
3960=== modified file 'cronscripts/update-stats.py'
3961--- cronscripts/update-stats.py 2009-06-24 20:52:01 +0000
3962+++ cronscripts/update-stats.py 2010-05-05 01:58:48 +0000
3963@@ -1,4 +1,4 @@
3964-#!/usr/bin/python2.4
3965+#!/usr/bin/python2.5 -S
3966 #
3967 # Copyright 2009 Canonical Ltd. This software is licensed under the
3968 # GNU Affero General Public License version 3 (see the file LICENSE).
3969@@ -28,7 +28,7 @@
3970 # objects are responsible for committing.
3971 distroset = getUtility(IDistributionSet)
3972 for distro in distroset:
3973- for distroseries in distro.serieses:
3974+ for distroseries in distro.series:
3975 distroseries.updateStatistics(self.txn)
3976
3977 launchpad_stats = getUtility(ILaunchpadStatisticSet)
3978
3979=== removed file 'cronscripts/update_preview_diffs.py'
3980--- cronscripts/update_preview_diffs.py 2009-09-01 19:00:46 +0000
3981+++ cronscripts/update_preview_diffs.py 1970-01-01 00:00:00 +0000
3982@@ -1,34 +0,0 @@
3983-#!/usr/bin/python2.4
3984-#
3985-# Copyright 2009 Canonical Ltd. This software is licensed under the
3986-# GNU Affero General Public License version 3 (see the file LICENSE).
3987-
3988-# pylint: disable-msg=W0403
3989-
3990-"""Update or create previews diffs for branch merge proposals."""
3991-
3992-__metaclass__ = type
3993-
3994-import _pythonpath
3995-
3996-from lp.codehosting.vfs import get_scanner_server
3997-from lp.services.job.runner import JobCronScript
3998-from lp.code.interfaces.branchmergeproposal import (
3999- IUpdatePreviewDiffJobSource,)
4000-
4001-
4002-class RunUpdatePreviewDiffJobs(JobCronScript):
4003- """Run UpdatePreviewDiff jobs."""
4004-
4005- config_name = 'update_preview_diffs'
4006- source_interface = IUpdatePreviewDiffJobSource
4007-
4008- def setUp(self):
4009- server = get_scanner_server()
4010- server.setUp()
4011- return [server.tearDown]
4012-
4013-
4014-if __name__ == '__main__':
4015- script = RunUpdatePreviewDiffJobs()
4016- script.lock_and_run()
4017
4018=== added file 'cronscripts/upgrade_branches.py'
4019--- cronscripts/upgrade_branches.py 1970-01-01 00:00:00 +0000
4020+++ cronscripts/upgrade_branches.py 2010-05-05 01:58:48 +0000
4021@@ -0,0 +1,25 @@
4022+#!/usr/bin/python2.5 -S
4023+#
4024+# Copyright 2009 Canonical Ltd. This software is licensed under the
4025+# GNU Affero General Public License version 3 (see the file LICENSE).
4026+
4027+"""Upgrade branches to the most recent format."""
4028+
4029+__metaclass__ = type
4030+
4031+import _pythonpath
4032+
4033+from lp.services.job.runner import JobCronScript
4034+from lp.code.interfaces.branchjob import IBranchUpgradeJobSource
4035+
4036+
4037+class RunUpgradeBranches(JobCronScript):
4038+ """Run UpgradeBranchJob jobs."""
4039+
4040+ config_name = 'upgrade_branches'
4041+ source_interface = IBranchUpgradeJobSource
4042+
4043+
4044+if __name__ == '__main__':
4045+ script = RunUpgradeBranches()
4046+ script.lock_and_run()
4047
4048=== added symlink 'daemons/_pythonpath.py'
4049=== target is u'../_pythonpath.py'
4050=== removed file 'daemons/buildd-sequencer.tac'
4051--- daemons/buildd-sequencer.tac 2009-06-24 20:55:31 +0000
4052+++ daemons/buildd-sequencer.tac 1970-01-01 00:00:00 +0000
4053@@ -1,31 +0,0 @@
4054-# Copyright 2009 Canonical Ltd. This software is licensed under the
4055-# GNU Affero General Public License version 3 (see the file LICENSE).
4056-
4057-# Twisted Application Configuration file.
4058-# Use with "twistd -y <file.tac>", e.g. "twistd -noy server.tac"
4059-
4060-from twisted.application import service
4061-
4062-from canonical.buildd.sequencer import BuildSequencer
4063-
4064-# Construct the application
4065-application = service.Application("BuildSequencer")
4066-
4067-class BuildSequencerService(service.Service):
4068- def __init__(self, buildSequencer):
4069- self.buildSequencer = buildSequencer
4070-
4071- def startService(self):
4072- # Kick everything off...
4073- self.buildSequencer.scheduleCallback()
4074-
4075-
4076-# Construct the sequencer. It will automatically schedule the first job.
4077-bseq = BuildSequencer()
4078-# Make a service out of the sequencer
4079-bserv = BuildSequencerService(bseq)
4080-
4081-# Activate the service
4082-BuildSequencerService(bseq).setServiceParent(application)
4083-
4084-# Falling off the end here passes into twisted's reactor.
4085
4086=== modified file 'daemons/buildd-slave.tac'
4087--- daemons/buildd-slave.tac 2009-06-24 20:55:31 +0000
4088+++ daemons/buildd-slave.tac 2010-05-05 01:58:48 +0000
4089@@ -1,4 +1,4 @@
4090-# Copyright 2009 Canonical Ltd. This software is licensed under the
4091+# Copyright 2009, 2010 Canonical Ltd. This software is licensed under the
4092 # GNU Affero General Public License version 3 (see the file LICENSE).
4093
4094 # Author: Daniel Silverstone <daniel.silverstone@canonical.com>
4095@@ -8,7 +8,11 @@
4096 # passed through to the twistd log too. this could get dangerous/big
4097
4098 from twisted.application import service, strports
4099-from canonical.buildd import XMLRPCBuildDSlave, DebianBuildManager
4100+from canonical.buildd import XMLRPCBuildDSlave
4101+from canonical.buildd.binarypackage import BinaryPackageBuildManager
4102+from canonical.buildd.sourcepackagerecipe import (
4103+ SourcePackageRecipeBuildManager)
4104+from canonical.buildd.translationtemplates import TranslationTemplatesBuildManager
4105 from canonical.launchpad.daemons import tachandler
4106
4107 from twisted.web import server, resource, static
4108@@ -22,7 +26,11 @@
4109 conf.read(conffile)
4110 slave = XMLRPCBuildDSlave(conf)
4111
4112-slave.registerBuilder(DebianBuildManager,"debian")
4113+# 'debian' is the old name. It remains here for compatibility.
4114+slave.registerBuilder(BinaryPackageBuildManager, "debian")
4115+slave.registerBuilder(BinaryPackageBuildManager, "binarypackage")
4116+slave.registerBuilder(SourcePackageRecipeBuildManager, "sourcepackagerecipe")
4117+slave.registerBuilder(TranslationTemplatesBuildManager, 'translation-templates')
4118
4119 application = service.Application('BuildDSlave')
4120 builddslaveService = service.IServiceCollection(application)
4121@@ -43,5 +51,5 @@
4122 #
4123 # python
4124 # import xmlrpclib
4125-# s = xmlrpclib.Server("http://localhost:8221/")
4126+# s = xmlrpclib.ServerProxy("http://localhost:8221/rpc")
4127 # s.echo("Hello World")
4128
4129=== added file 'daemons/cache-database-replication-lag.py'
4130--- daemons/cache-database-replication-lag.py 1970-01-01 00:00:00 +0000
4131+++ daemons/cache-database-replication-lag.py 2010-05-05 01:58:48 +0000
4132@@ -0,0 +1,53 @@
4133+#!/usr/bin/python2.5 -S
4134+#
4135+# Copyright 2010 Canonical Ltd. This software is licensed under the
4136+# GNU Affero General Public License version 3 (see the file LICENSE).
4137+
4138+"""Calculate database replication lag and cache it."""
4139+
4140+__metaclass__ = type
4141+__all__ = []
4142+
4143+import _pythonpath
4144+
4145+import sys
4146+import time
4147+
4148+import psycopg2
4149+
4150+from canonical.database.sqlbase import connect, ISOLATION_LEVEL_AUTOCOMMIT
4151+from canonical.launchpad.scripts import db_options, logger
4152+from lp.scripts.helpers import LPOptionParser
4153+
4154+
4155+def main(args=None):
4156+ parser = LPOptionParser()
4157+ db_options(parser)
4158+ parser.add_option(
4159+ "-s", "--sleep", dest="sleep", type="int", default=5,
4160+ metavar="SECS", help="Wait SECS seconds between refreshes.")
4161+
4162+ (options, args) = parser.parse_args(args)
4163+ if len(args) != 0:
4164+ parser.error("Too many arguments.")
4165+
4166+ log = logger(options)
4167+
4168+ while True:
4169+ try:
4170+ con = connect(user="lagmon", isolation=ISOLATION_LEVEL_AUTOCOMMIT)
4171+ cur = con.cursor()
4172+ while True:
4173+ cur.execute("SELECT update_replication_lag_cache()")
4174+ if cur.fetchone()[0]:
4175+ log.info("Updated.")
4176+ else:
4177+ log.error("update_replication_lag_cache() failed.")
4178+ time.sleep(options.sleep)
4179+ except psycopg2.Error, x:
4180+ log.error("%s. Retrying.", str(x).strip())
4181+ time.sleep(options.sleep)
4182+
4183+
4184+if __name__ == '__main__':
4185+ sys.exit(main())
4186
4187=== modified file 'daemons/librarian.tac'
4188--- daemons/librarian.tac 2009-06-24 20:55:31 +0000
4189+++ daemons/librarian.tac 2010-05-05 01:58:48 +0000
4190@@ -4,6 +4,10 @@
4191 # Twisted Application Configuration file.
4192 # Use with "twistd2.4 -y <file.tac>", e.g. "twistd -noy server.tac"
4193
4194+import signal
4195+
4196+from meliae import scanner
4197+
4198 from twisted.application import service, strports
4199 from twisted.web import server
4200
4201@@ -11,6 +15,7 @@
4202 from canonical.launchpad.daemons import tachandler
4203 from canonical.launchpad.scripts import execute_zcml_for_scripts
4204
4205+from canonical.librarian.interfaces import DUMP_FILE, SIGDUMPMEM
4206 from canonical.librarian.libraryprotocol import FileUploadFactory
4207 from canonical.librarian import storage, db
4208 from canonical.librarian import web as fatweb
4209@@ -64,3 +69,9 @@
4210 webPort = config.librarian.restricted_download_port
4211 uploadPort = config.librarian.restricted_upload_port
4212 setUpListener(uploadPort, webPort, restricted=True)
4213+
4214+# Setup a signal handler to dump the process' memory upon 'kill -44'.
4215+def sigdumpmem_handler(signum, frame):
4216+ scanner.dump_all_objects(DUMP_FILE)
4217+
4218+signal.signal(SIGDUMPMEM, sigdumpmem_handler)
4219
4220=== modified file 'daemons/poppy-upload.py'
4221--- daemons/poppy-upload.py 2009-06-30 21:26:26 +0000
4222+++ daemons/poppy-upload.py 2010-05-05 01:58:48 +0000
4223@@ -1,57 +1,10 @@
4224-#!/usr/bin/python2.4
4225+#!/usr/bin/python2.5
4226 #
4227 # Copyright 2009 Canonical Ltd. This software is licensed under the
4228 # GNU Affero General Public License version 3 (see the file LICENSE).
4229
4230 import sys
4231-import logging
4232-import optparse
4233-
4234-from canonical.poppy.server import run_server
4235-from lp.archiveuploader.poppyinterface import PoppyInterface
4236-from canonical.launchpad.scripts import logger, logger_options
4237-
4238-
4239-def main():
4240-
4241- parser = optparse.OptionParser()
4242- logger_options(parser)
4243-
4244- parser.add_option("--cmd", action="store", metavar="CMD",
4245- help="Run CMD after each upload completion")
4246-
4247- parser.add_option("--allow-user", action="store", metavar="USER",
4248- default='ubuntu',
4249- help="Username allowed to log in.")
4250-
4251- parser.add_option("--permissions", action="store", metavar="PERMS",
4252- default='g+rwxs',
4253- help="Permissions to chmod the targetfsroot with "
4254- "before letting go of the directory.")
4255-
4256- options, args = parser.parse_args()
4257-
4258- log = logger(options, "poppy-upload")
4259-
4260- if len(args) != 2:
4261- print "usage: poppy-upload.py rootuploaddirectory port"
4262- return 1
4263-
4264- root, port = args
4265- # host = "127.0.0.1"
4266- # host = "82.211.81.167" # Drescher's public IP
4267- host = "0.0.0.0"
4268- ident = "lucille upload server"
4269- numthreads = 4
4270-
4271- iface = PoppyInterface(root, log, allow_user=options.allow_user,
4272- cmd=options.cmd,
4273- perms=options.permissions)
4274-
4275- run_server(host, int(port), ident, numthreads,
4276- iface.new_client_hook, iface.client_done_hook,
4277- iface.auth_verify_hook)
4278- return 0
4279+from lp.poppy.daemon import main
4280
4281 if __name__ == '__main__':
4282 sys.exit(main())
4283
4284=== modified file 'daemons/sftp.tac'
4285--- daemons/sftp.tac 2009-06-24 20:55:31 +0000
4286+++ daemons/sftp.tac 2010-05-05 01:58:48 +0000
4287@@ -1,4 +1,4 @@
4288-# Copyright 2009 Canonical Ltd. This software is licensed under the
4289+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
4290 # GNU Affero General Public License version 3 (see the file LICENSE).
4291
4292 # This is a Twisted application config file. To run, use:
4293@@ -7,13 +7,28 @@
4294
4295 from twisted.application import service
4296
4297+from canonical.config import config
4298 from canonical.launchpad.daemons import tachandler
4299-from lp.codehosting.sshserver.service import SSHService
4300-
4301-
4302-# Construct an Application that includes a supermirror SFTP service.
4303+
4304+from lp.codehosting.sshserver.daemon import (
4305+ ACCESS_LOG_NAME, get_key_path, LOG_NAME, make_portal, OOPS_CONFIG_SECTION,
4306+ PRIVATE_KEY_FILE, PUBLIC_KEY_FILE)
4307+from lp.services.sshserver.service import SSHService
4308+
4309+
4310+# Construct an Application that has the codehosting SSH server.
4311 application = service.Application('sftponly')
4312-svc = SSHService()
4313+svc = SSHService(
4314+ portal=make_portal(),
4315+ private_key_path=get_key_path(PRIVATE_KEY_FILE),
4316+ public_key_path=get_key_path(PUBLIC_KEY_FILE),
4317+ oops_configuration=OOPS_CONFIG_SECTION,
4318+ main_log=LOG_NAME,
4319+ access_log=ACCESS_LOG_NAME,
4320+ access_log_path=config.codehosting.access_log,
4321+ strport=config.codehosting.port,
4322+ idle_timeout=config.codehosting.idle_timeout,
4323+ banner=config.codehosting.banner)
4324 svc.setServiceParent(application)
4325
4326 # Service that announces when the daemon is ready
4327
4328=== modified file 'database/replication/Makefile'
4329--- database/replication/Makefile 2009-06-24 21:17:33 +0000
4330+++ database/replication/Makefile 2010-05-05 01:58:48 +0000
4331@@ -18,6 +18,11 @@
4332 # $ make stagingsetup STAGING_CONFIG=dev-staging STAGING_DUMP=launchpad.dump
4333 # $ make stagingswitch STAGING_CONFIG=dev-staging
4334 #
4335+# To restore a dogfood database:
4336+#
4337+# $ cd database/replication
4338+# $ make dogfood DOGFOOD_DBNAME=launchpad_dogfood DOGFOOD_DUMP=launchpad.dump
4339+#
4340
4341 # This used to be 10 seconds, so we always ran staging lagged to detect
4342 # replication glitches more easily. However, this does not play well
4343@@ -31,12 +36,24 @@
4344 STAGING_CONFIG=staging # For swapping fresh db into place.
4345 STAGING_DUMP=launchpad.dump # Dumpfile to build new staging from.
4346 STAGING_TABLESPACE=pg_default # 'pg_default' for default
4347+DOGFOOD_DBNAME=launchpad_dogfood
4348+DOGFOOD_DUMP=launchpad.dump
4349
4350 _CONFIG=overridden-on-command-line
4351 _SLAVE_TABLESPACE=pg_default
4352
4353 PGMASSACRE=../../utilities/pgmassacre.py
4354
4355+CREATEDB_83=createdb --encoding=UTF8
4356+CREATEDB_84=createdb --encoding=UTF8 --locale=C --template=template0
4357+CREATEDB=${CREATEDB_83}
4358+
4359+# Turn off output silencing so we can see details of staging deployments.
4360+# Without the timestamps, we are unable to estimate production deployment
4361+# times.
4362+#SHHH=../../utilities/shhh.py
4363+SHHH=
4364+
4365 default:
4366 echo Usage: make [start|stop|restart]
4367
4368@@ -61,7 +78,7 @@
4369
4370 # Replicate it again, so we can test with multiple slaves.
4371 -${PGMASSACRE} launchpad_dev_slave2
4372- createdb --encoding=UTF8 launchpad_dev_slave2
4373+ ${CREATEDB} launchpad_dev_slave2
4374 LPCONFIG=${DEV_CONFIG} ./slon_ctl.py start \
4375 node3_node 'dbname=launchpad_dev_slave2 user=slony'
4376 LPCONFIG=${DEV_CONFIG} ./new-slave.py 3 launchpad_dev_slave2
4377@@ -81,13 +98,12 @@
4378 _MASTER=lpmain_staging_new _SLAVE=lpmain_staging_slave_new \
4379 LAG="0 seconds"
4380 # Create the DB with the desired default tablespace.
4381- createdb --encoding UTF8 --tablespace ${STAGING_TABLESPACE} \
4382- lpmain_staging_new
4383- # Restore the DB schema. Don't restore permissions - it will blow
4384- # up when roles don't exist in this cluster, and we rebuild it later
4385- # with security.py anyway.
4386+ ${CREATEDB} --tablespace ${STAGING_TABLESPACE} lpmain_staging_new
4387+ # Restore the database. We need to restore permissions, despite
4388+ # later running security.py, to pull in permissions granted on
4389+ # production to users not maintained by security.py.
4390 pg_restore --dbname=lpmain_staging_new \
4391- --no-acl --exit-on-error ${STAGING_DUMP}
4392+ --no-owner --exit-on-error ${STAGING_DUMP}
4393 # Uninstall Slony-I if it is installed - a pg_dump of a DB with
4394 # Slony-I installed isn't usable without this step.
4395 LPCONFIG=${NEW_STAGING_CONFIG} ./repair-restored-db.py
4396@@ -118,6 +134,15 @@
4397 # Start the slon daemons, with requested lag.
4398 LPCONFIG=${STAGING_CONFIG} ./slon_ctl.py --lag="${LAG}" start
4399
4400+dogfood:
4401+ ${CREATEDB} ${DOGFOOD_DBNAME}
4402+ pg_restore --dbname=${DOGFOOD_DBNAME} --no-acl --no-owner \
4403+ --exit-on-error ${DOGFOOD_DUMP}
4404+ ./repair-restored-db.py -d ${DOGFOOD_DBNAME}
4405+ ../schema/upgrade.py -d ${DOGFOOD_DBNAME}
4406+ ../schema/fti.py -d ${DOGFOOD_DBNAME}
4407+ ../schema/security.py -d ${DOGFOOD_DBNAME}
4408+
4409 _prelim:
4410 @echo LPCONFIG currently ${LPCONFIG}
4411 # Create the slony PostgreSQL superuser if necessary.
4412@@ -132,25 +157,26 @@
4413 _replicate:
4414 @echo LPCONFIG currently ${LPCONFIG}
4415 # Start the slon daemon for the master.
4416- ./slon_ctl.py start \
4417+ ./slon_ctl.py --lag="0 seconds" start \
4418 node1_node "dbname=${_MASTER} user=slony"
4419 # Initialize the cluster and create replication sets.
4420 ./initialize.py
4421 # Create the soon-to-be-slave database, empty at this point.
4422- createdb --encoding=UTF8 --tablespace=${_SLAVE_TABLESPACE} ${_SLAVE}
4423+ ${CREATEDB} --tablespace=${_SLAVE_TABLESPACE} ${_SLAVE}
4424 # Start the slon daemon for the slave
4425- ./slon_ctl.py start node2_node "dbname=${_SLAVE} user=slony"
4426+ ./slon_ctl.py --lag="0 seconds" start \
4427+ node2_node "dbname=${_SLAVE} user=slony"
4428 # Setup the slave
4429 ./new-slave.py 2 "dbname=${_SLAVE}"
4430 # Upgrade all databases in the cluster and reset security.
4431- ../schema/upgrade.py
4432- ../schema/fti.py
4433- ../schema/security.py --cluster -U slony
4434- # Migrate tables to the authdb replication set, creating the set
4435- # and subscribing nodes to it as necessary.
4436- ./populate_auth_replication_set.py -U slony
4437+ @echo Running upgrade.py `date`
4438+ ${SHHH} ../schema/upgrade.py
4439+ @echo Running fti.py `date`
4440+ ${SHHH} ../schema/fti.py
4441+ @echo Running security.py `date`
4442+ ./slon_ctl.py stop # security.py can deadlock with slony
4443+ ${SHHH} ../schema/security.py --cluster -U slony
4444 # Restart slon daemons with default lag setting.
4445- ./slon_ctl.py stop
4446 ./slon_ctl.py --lag="${LAG}" start
4447 # Generate a preamble for manual slonik(1) usage.
4448 ./preamble.py > preamble.sk
4449
4450=== modified file 'database/replication/helpers.py'
4451--- database/replication/helpers.py 2009-06-24 21:17:33 +0000
4452+++ database/replication/helpers.py 2010-05-05 01:58:48 +0000
4453@@ -26,19 +26,20 @@
4454 # The namespace in the database used to contain all the Slony-I tables.
4455 CLUSTER_NAMESPACE = '_%s' % CLUSTERNAME
4456
4457-# Seed tables for the authdb replication set to be passed to
4458+# Replication set id constants. Don't change these without DBA help.
4459+LPMAIN_SET_ID = 1
4460+HOLDING_SET_ID = 666
4461+LPMIRROR_SET_ID = 4
4462+
4463+# Seed tables for the lpmain replication set to be passed to
4464 # calculate_replication_set().
4465-AUTHDB_SEED = frozenset([
4466+LPMAIN_SEED = frozenset([
4467 ('public', 'account'),
4468+ ('public', 'openidnonce'),
4469 ('public', 'openidassociation'),
4470- ('public', 'openidnonce'),
4471- ])
4472-
4473-# Seed tables for the lpmain replication set to be passed to
4474-# calculate_replication_set().
4475-LPMAIN_SEED = frozenset([
4476 ('public', 'person'),
4477 ('public', 'launchpaddatabaserevision'),
4478+ ('public', 'databasereplicationlag'),
4479 ('public', 'fticache'),
4480 ('public', 'nameblacklist'),
4481 ('public', 'openidconsumerassociation'),
4482@@ -51,14 +52,49 @@
4483 ('public', 'launchpadstatistic'),
4484 ('public', 'parsedapachelog'),
4485 ('public', 'shipitsurvey'),
4486- ('public', 'openidassociations'), # Remove this in April 2009 or later.
4487+ ('public', 'databasereplicationlag'),
4488 ])
4489
4490 # Explicitly list tables that should not be replicated. This includes the
4491 # session tables, as these might exist in developer databases but will not
4492 # exist in the production launchpad database.
4493 IGNORED_TABLES = set([
4494- 'public.secret', 'public.sessiondata', 'public.sessionpkgdata'])
4495+ # Session tables that in some situations will exist in the main lp
4496+ # database.
4497+ 'public.secret', 'public.sessiondata', 'public.sessionpkgdata',
4498+ # Mirror tables, per Bug #489078. These tables have their own private
4499+ # replication set that is setup manually.
4500+ 'public.lp_account',
4501+ 'public.lp_person',
4502+ 'public.lp_personlocation',
4503+ 'public.lp_teamparticipation',
4504+ # Ubuntu SSO database. These tables where created manually by ISD
4505+ # and the Launchpad scripts should not mess with them. Eventually
4506+ # these tables will be in a totally separate database.
4507+ 'public.auth_permission',
4508+ 'public.auth_group',
4509+ 'public.auth_user',
4510+ 'public.auth_message',
4511+ 'public.django_content_type',
4512+ 'public.auth_permission',
4513+ 'public.django_session',
4514+ 'public.django_site',
4515+ 'public.django_admin_log',
4516+ 'public.ssoopenidrpconfig',
4517+ 'public.auth_group_permissions',
4518+ 'public.auth_user_groups',
4519+ 'public.auth_user_user_permissions',
4520+ 'public.oauth_nonce',
4521+ 'public.oauth_consumer',
4522+ 'public.oauth_token',
4523+ 'public.api_user',
4524+ 'public.oauth_consumer_id_seq',
4525+ 'public.api_user_id_seq',
4526+ 'public.oauth_nonce_id_seq',
4527+ ])
4528+
4529+# Calculate IGNORED_SEQUENCES
4530+IGNORED_SEQUENCES = set('%s_id_seq' % table for table in IGNORED_TABLES)
4531
4532
4533 def slony_installed(con):
4534@@ -101,7 +137,7 @@
4535
4536 def sync(timeout):
4537 """Generate a sync event and wait for it to complete on all nodes.
4538-
4539+
4540 This means that all pending events have propagated and are in sync
4541 to the point in time this method was called. This might take several
4542 hours if there is a large backlog of work to replicate.
4543@@ -135,12 +171,13 @@
4544 script = preamble() + script
4545
4546 if sync is not None:
4547- script = script + dedent("""\
4548+ sync_script = dedent("""\
4549 sync (id = @master_node);
4550 wait for event (
4551- origin = ALL, confirmed = ALL,
4552+ origin = @master_node, confirmed = ALL,
4553 wait on = @master_node, timeout = %d);
4554 """ % sync)
4555+ script = script + sync_script
4556
4557 # Copy the script to a NamedTemporaryFile rather than just pumping it
4558 # to slonik via stdin. This way it can be examined if slonik appears
4559@@ -151,7 +188,7 @@
4560
4561 # Run slonik
4562 log.debug("Executing slonik script %s" % script_on_disk.name)
4563- log.log(DEBUG2, script)
4564+ log.log(DEBUG2, 'Running script:\n%s' % script)
4565 returncode = subprocess.call(['slonik', script_on_disk.name])
4566
4567 if returncode != 0:
4568@@ -255,7 +292,7 @@
4569 assert len(node_ids) == 1, "Multiple nodes but no paths."
4570 master_node_id = node_ids[0]
4571 master_connection_string = ConnectionString(
4572- config.database.main_master)
4573+ config.database.rw_main_master)
4574 master_connection_string.user = 'slony'
4575 return [Node(
4576 master_node_id, 'node%d_node' % master_node_id,
4577@@ -282,10 +319,10 @@
4578 cluster name = sl;
4579
4580 # Symbolic ids for replication sets.
4581- define lpmain_set 1;
4582- define authdb_set 2;
4583- define holding_set 666;
4584- """)]
4585+ define lpmain_set %d;
4586+ define holding_set %d;
4587+ define lpmirror_set %d;
4588+ """ % (LPMAIN_SET_ID, HOLDING_SET_ID, LPMIRROR_SET_ID))]
4589
4590 if master_node is not None:
4591 preamble.append(dedent("""\
4592@@ -303,9 +340,9 @@
4593 node.nickname, node.node_id,
4594 node.nickname, node.connection_string,
4595 node.nickname, node.nickname)))
4596-
4597+
4598 return '\n\n'.join(preamble)
4599-
4600+
4601
4602 def calculate_replication_set(cur, seeds):
4603 """Return the minimal set of tables and sequences needed in a
4604@@ -434,7 +471,7 @@
4605
4606 return (
4607 all_tables - replicated_tables - IGNORED_TABLES,
4608- all_sequences - replicated_sequences)
4609+ all_sequences - replicated_sequences - IGNORED_SEQUENCES)
4610
4611
4612 class ReplicationConfigError(Exception):
4613@@ -462,19 +499,6 @@
4614 raise ReplicationConfigError(
4615 "Unreplicated sequences: %s" % repr(unrepl_sequences))
4616
4617- authdb_tables, authdb_sequences = calculate_replication_set(
4618- cur, AUTHDB_SEED)
4619 lpmain_tables, lpmain_sequences = calculate_replication_set(
4620 cur, LPMAIN_SEED)
4621
4622- confused_tables = authdb_tables.intersection(lpmain_tables)
4623- if confused_tables:
4624- raise ReplicationConfigError(
4625- "Tables exist in multiple replication sets: %s"
4626- % repr(confused_tables))
4627- confused_sequences = authdb_sequences.intersection(lpmain_sequences)
4628- if confused_sequences:
4629- raise ReplicationConfigError(
4630- "Sequences exist in multiple replication sets: %s"
4631- % repr(confused_sequences))
4632-
4633
4634=== modified file 'database/replication/initialize.py'
4635--- database/replication/initialize.py 2009-07-19 04:41:14 +0000
4636+++ database/replication/initialize.py 2010-05-05 01:58:48 +0000
4637@@ -1,4 +1,4 @@
4638-#!/usr/bin/python2.4
4639+#!/usr/bin/python2.5 -S
4640 #
4641 # Copyright 2009 Canonical Ltd. This software is licensed under the
4642 # GNU Affero General Public License version 3 (see the file LICENSE).
4643@@ -41,9 +41,9 @@
4644 """Duplicate the master schema into the slaves."""
4645 log.info('Duplicating database schema')
4646
4647- master_cs = ConnectionString(config.database.main_master)
4648+ master_cs = ConnectionString(config.database.rw_main_master)
4649 master_cs.user = options.dbuser
4650- slave1_cs = ConnectionString(config.database.main_slave)
4651+ slave1_cs = ConnectionString(config.database.rw_main_slave)
4652 slave1_cs.user = options.dbuser
4653
4654 # We can't use pg_dump to replicate security as not all of the roles
4655@@ -70,7 +70,7 @@
4656 """Initialize the cluster."""
4657 log.info('Initializing Slony-I cluster')
4658 master_connection_string = ConnectionString(
4659- config.database.main_master)
4660+ config.database.rw_main_master)
4661 master_connection_string.user = 'slony'
4662 helpers.execute_slonik("""
4663 node 1 admin conninfo = '%s';
4664@@ -88,54 +88,13 @@
4665 helpers.sync(120) # Will exit on failure.
4666
4667
4668-def create_replication_sets(
4669- authdb_tables, authdb_sequences, lpmain_tables, lpmain_sequences):
4670+def create_replication_sets(lpmain_tables, lpmain_sequences):
4671 """Create the replication sets."""
4672 log.info('Creating Slony-I replication sets.')
4673
4674- # Instead of creating both the authdb and lpmain replication sets,
4675- # we just create the lpmain replication set containing everything.
4676- # This way, we can then test the populate_auth_replication_set.py
4677- # migration script that moves the relevant tables from the lpmain
4678- # replication set to the authdb replication set.
4679- # We will turn this behavior off once we are running two
4680- # replication sets in production and remove the migration script.
4681- lpmain_tables = lpmain_tables.union(authdb_tables)
4682- lpmain_sequences = lpmain_sequences.union(authdb_sequences)
4683-
4684 script = ["try {"]
4685- # script,append("""
4686- # echo 'Creating AuthDB replication set (@authdb_set)';
4687- # create set (
4688- # id=@authdb_set, origin=@master_node,
4689- # comment='AuthDB tables and sequences');
4690- # """)
4691
4692- # entry_id = 1
4693- # for table in sorted(authdb_tables):
4694- # script.append("""
4695- # echo 'Adding %(table)s to replication set @authdb_set';
4696- # set add table (
4697- # set id=@authdb_set,
4698- # origin=@master_node,
4699- # id=%(entry_id)d,
4700- # fully qualified name='%(table)s');
4701- # """ % vars())
4702- # entry_id += 1
4703- # entry_id = 1
4704- # for sequence in sorted(authdb_sequences):
4705- # script.append("""
4706- # echo 'Adding %(sequence)s to replication set @authdb_set';
4707- # set add sequence (
4708- # set id=@authdb_set,
4709- # origin=@master_node,
4710- # id=%(entry_id)d,
4711- # fully qualified name='%(sequence)s');
4712- # """ % vars())
4713- # entry_id += 1
4714- #
4715- # assert entry_id < 200, 'authdb replcation set has > 200 objects???'
4716- entry_id = 200
4717+ entry_id = 1
4718
4719 script.append("""
4720 echo 'Creating LPMain replication set (@lpmain_set)';
4721@@ -157,7 +116,7 @@
4722 """ % vars())
4723 entry_id += 1
4724
4725- entry_id = 200
4726+ entry_id = 1
4727 script.append(
4728 "echo 'Adding %d sequences to replication set @lpmain_set';"
4729 % len(lpmain_sequences))
4730@@ -199,9 +158,6 @@
4731 con.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
4732 global cur
4733 cur = con.cursor()
4734- log.debug("Calculating authdb replication set.")
4735- authdb_tables, authdb_sequences = helpers.calculate_replication_set(
4736- cur, helpers.AUTHDB_SEED)
4737 log.debug("Calculating lpmain replication set.")
4738 lpmain_tables, lpmain_sequences = helpers.calculate_replication_set(
4739 cur, helpers.LPMAIN_SEED)
4740@@ -212,8 +168,7 @@
4741 fails = 0
4742 for table in all_tables_in_schema(cur, 'public'):
4743 times_seen = 0
4744- for table_set in [
4745- authdb_tables, lpmain_tables, helpers.IGNORED_TABLES]:
4746+ for table_set in [lpmain_tables, helpers.IGNORED_TABLES]:
4747 if table in table_set:
4748 times_seen += 1
4749 if times_seen == 0:
4750@@ -224,7 +179,7 @@
4751 fails += 1
4752 for sequence in all_sequences_in_schema(cur, 'public'):
4753 times_seen = 0
4754- for sequence_set in [authdb_sequences, lpmain_sequences]:
4755+ for sequence_set in [lpmain_sequences, helpers.IGNORED_SEQUENCES]:
4756 if sequence in sequence_set:
4757 times_seen += 1
4758 if times_seen == 0:
4759@@ -241,8 +196,7 @@
4760
4761 ensure_live()
4762
4763- create_replication_sets(
4764- authdb_tables, authdb_sequences, lpmain_tables, lpmain_sequences)
4765+ create_replication_sets(lpmain_tables, lpmain_sequences)
4766
4767 helpers.sync(0)
4768
4769
4770=== modified file 'database/replication/new-slave.py'
4771--- database/replication/new-slave.py 2009-06-24 21:17:33 +0000
4772+++ database/replication/new-slave.py 2010-05-05 01:58:48 +0000
4773@@ -1,4 +1,4 @@
4774-#!/usr/bin/python2.4
4775+#!/usr/bin/python2.5 -S
4776 #
4777 # Copyright 2009 Canonical Ltd. This software is licensed under the
4778 # GNU Affero General Public License version 3 (see the file LICENSE).
4779@@ -24,6 +24,7 @@
4780 from canonical.launchpad.scripts import db_options, logger_options, logger
4781
4782 import replication.helpers
4783+from replication.helpers import LPMAIN_SET_ID
4784
4785 def main():
4786 parser = OptionParser(
4787@@ -72,6 +73,10 @@
4788 if node_id in [node.node_id for node in existing_nodes]:
4789 parser.error("Node %d already exists in the cluster." % node_id)
4790
4791+ # Get the connection string for masters.
4792+ lpmain_connection_string = get_master_connection_string(
4793+ source_connection, parser, LPMAIN_SET_ID) or source_connection_string
4794+
4795 # Sanity check the target connection string.
4796 target_connection_string = ConnectionString(raw_target_connection_string)
4797 if target_connection_string.user is None:
4798@@ -110,11 +115,11 @@
4799 "Database at %s is not empty." % target_connection_string)
4800 target_con.rollback()
4801
4802- # Duplicate the schema. We restore with no-privileges as required
4803+ # Duplicate the full schema. We restore with no-privileges as required
4804 # roles may not yet exist, so we have to run security.py on the
4805 # new slave once it is built.
4806- log.info("Duplicating db schema from '%s' to '%s'" % (
4807- source_connection_string, target_connection_string))
4808+ log.info("Duplicating full db schema from '%s' to '%s'" % (
4809+ lpmain_connection_string, target_connection_string))
4810 cmd = "pg_dump --schema-only --no-privileges %s | psql -1 -q %s" % (
4811 source_connection_string.asPGCommandLineArgs(),
4812 target_connection_string.asPGCommandLineArgs())
4813@@ -123,19 +128,39 @@
4814 return 1
4815
4816 # Trash the broken Slony tables we just duplicated.
4817+ log.debug("Removing slony cruft.")
4818 cur = target_con.cursor()
4819 cur.execute("DROP SCHEMA _sl CASCADE")
4820 target_con.commit()
4821 del target_con
4822
4823- # Get a list of existing set ids.
4824+ # Get a list of existing set ids that can be subscribed too. This
4825+ # is all sets where the origin is the master_node. We
4826+ # don't allow other sets where the master is configured as a
4827+ # forwarding slave as we have to special case rebuilding the database
4828+ # schema, and we want to avoid cascading slave configurations anyway
4829+ # since we are running an antique Slony-I at the moment - keep it
4830+ # simple!
4831+ # We order the sets smallest to largest by number of tables.
4832+ # This should let us subscribe the quickest sets first for more
4833+ # immediate feedback.
4834 source_connection.rollback()
4835 master_node = replication.helpers.get_master_node(source_connection)
4836 cur = source_connection.cursor()
4837- cur.execute(
4838- "SELECT set_id FROM _sl.sl_set WHERE set_origin=%d"
4839- % master_node.node_id)
4840+ cur.execute("""
4841+ SELECT set_id
4842+ FROM _sl.sl_set, (
4843+ SELECT tab_set, count(*) AS tab_count
4844+ FROM _sl.sl_table GROUP BY tab_set
4845+ ) AS TableCounts
4846+ WHERE
4847+ set_origin=%d
4848+ AND tab_set = set_id
4849+ ORDER BY tab_count
4850+ """
4851+ % (master_node.node_id,))
4852 set_ids = [set_id for set_id, in cur.fetchall()]
4853+ log.debug("Discovered set ids %s" % repr(list(set_ids)))
4854
4855 # Generate and run a slonik(1) script to initialize the new node
4856 # and subscribe it to our replication sets.
4857@@ -165,19 +190,32 @@
4858 } on error { echo 'Failed.'; exit 1; }
4859 """)
4860
4861+ full_sync = []
4862+ sync_nicknames = [node.nickname for node in existing_nodes]
4863+ sync_nicknames.append('new_node');
4864+ for nickname in sync_nicknames:
4865+ full_sync.append(dedent("""\
4866+ echo 'Waiting for %(nickname)s sync.';
4867+ sync (id=@%(nickname)s);
4868+ wait for event (
4869+ origin = @%(nickname)s, confirmed=ALL,
4870+ wait on = @%(nickname)s, timeout=0);
4871+ """ % {'nickname': nickname}))
4872+ full_sync = '\n'.join(full_sync)
4873+ script += full_sync
4874+
4875 for set_id in set_ids:
4876-
4877 script += dedent("""\
4878 echo 'Subscribing new node to set %d.';
4879 subscribe set (
4880 id=%d, provider=@master_node, receiver=@new_node, forward=yes);
4881-
4882- echo 'Waiting for sync... this might take a while...';
4883+ echo 'Waiting for subscribe to start processing.';
4884 sync (id = @master_node);
4885 wait for event (
4886- origin = ALL, confirmed = ALL,
4887+ origin = @master_node, confirmed = ALL,
4888 wait on = @master_node, timeout = 0);
4889 """ % (set_id, set_id))
4890+ script += full_sync
4891
4892 replication.helpers.execute_slonik(script)
4893
4894@@ -185,5 +223,33 @@
4895
4896 return 0
4897
4898+
4899+def get_master_connection_string(con, parser, set_id):
4900+ """Return the connection string to the origin for the replication set.
4901+ """
4902+ cur = con.cursor()
4903+ cur.execute("""
4904+ SELECT pa_conninfo FROM _sl.sl_set, _sl.sl_path
4905+ WHERE set_origin = pa_server AND set_id = %d
4906+ LIMIT 1
4907+ """ % set_id)
4908+ row = cur.fetchone()
4909+ if row is None:
4910+ # If we have no paths stored, there is only a single node in the
4911+ # cluster.
4912+ return None
4913+ else:
4914+ connection_string = ConnectionString(row[0])
4915+
4916+ # Confirm we can connect from here.
4917+ try:
4918+ test_con = psycopg2.connect(str(connection_string))
4919+ except psycopg2.Error, exception:
4920+ parser.error("Failed to connect to using '%s' (%s)" % (
4921+ connection_string, str(exception).strip()))
4922+
4923+ return connection_string
4924+
4925+
4926 if __name__ == '__main__':
4927 sys.exit(main())
4928
4929=== removed file 'database/replication/populate_auth_replication_set.py'
4930--- database/replication/populate_auth_replication_set.py 2009-06-24 21:17:33 +0000
4931+++ database/replication/populate_auth_replication_set.py 1970-01-01 00:00:00 +0000
4932@@ -1,177 +0,0 @@
4933-#!/usr/bin/python2.4
4934-#
4935-# Copyright 2009 Canonical Ltd. This software is licensed under the
4936-# GNU Affero General Public License version 3 (see the file LICENSE).
4937-
4938-"""Populate the auth replication set.
4939-
4940-This script moves the the SSO tables from the main replication set to
4941-the auth replication set.
4942-
4943-Once it has been run on production, these tables can no longer be
4944-maintained using the Launchpad database maintenance scripts
4945-(upgrade.py, security.py etc.).
4946-
4947-We do this so Launchpad database upgrades do not lock the SSO tables,
4948-allowing the SSO service to continue to operate.
4949-
4950-This is a single shot script.
4951-"""
4952-
4953-__metaclass__ = type
4954-__all__ = []
4955-
4956-import _pythonpath
4957-
4958-import sys
4959-from textwrap import dedent
4960-from optparse import OptionParser
4961-
4962-from canonical.database.sqlbase import (
4963- connect, ISOLATION_LEVEL_AUTOCOMMIT, sqlvalues)
4964-from canonical.launchpad.scripts import db_options, logger_options, logger
4965-
4966-import replication.helpers
4967-
4968-def create_auth_set(cur):
4969- """Create the auth replication set if it doesn't already exist."""
4970- cur.execute("SELECT TRUE FROM _sl.sl_set WHERE set_id=2")
4971- if cur.fetchone() is not None:
4972- log.info("Auth set already exists.")
4973- return
4974- slonik_script = dedent("""\
4975- create set (
4976- id=@authdb_set, origin=@master_node,
4977- comment='SSO service tables');
4978- """)
4979- log.info("Creating authdb replication set.")
4980- replication.helpers.execute_slonik(slonik_script, sync=0)
4981-
4982-
4983-def subscribe_auth_set(cur):
4984- """The authdb set subscription much match the lpmain set subscription.
4985-
4986- This is a requirement to move stuff between replication sets. It
4987- is also what we want (all nodes replicating everything).
4988- """
4989- cur.execute("""
4990- SELECT sub_receiver FROM _sl.sl_subscribe WHERE sub_set = 1
4991- EXCEPT
4992- SELECT sub_receiver FROM _sl.sl_subscribe WHERE sub_set = 2
4993- """)
4994- for node_id in (node_id for node_id, in cur.fetchall()):
4995- log.info("Subscribing Node #%d to authdb replication set" % node_id)
4996- success = replication.helpers.execute_slonik(dedent("""\
4997- subscribe set (
4998- id = @authdb_set, provider = @master_node,
4999- receiver = %d, forward = yes);
5000- """ % node_id), sync=0)
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: