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
=== modified file '.bzrignore'
--- .bzrignore 2009-09-10 06:11:21 +0000
+++ .bzrignore 2010-05-05 01:58:48 +0000
@@ -30,11 +30,12 @@
30database/sampledata/newsampledata-dev.sql30database/sampledata/newsampledata-dev.sql
31database/sampledata/lintdata.sql31database/sampledata/lintdata.sql
32database/sampledata/lintdata-dev.sql32database/sampledata/lintdata-dev.sql
33lib/canonical/launchpad/apidoc/index.html33lib/canonical/launchpad/apidoc/*.html
34xxx-report.*34xxx-report.*
35lib/canonical/launchpad/apidoc/wadl-development.xml35lib/canonical/launchpad/apidoc/wadl-development-*.xml
36lib/canonical/launchpad/apidoc/wadl-test-playground.xml36lib/canonical/launchpad/apidoc/wadl-test-playground.xml
37lib/canonical/launchpad/icing/build/*37lib/canonical/launchpad/icing/build/*
38lib/canonical/launchpad/icing/combo.css
38trace.log39trace.log
39test-appserver-layer-trace.log40test-appserver-layer-trace.log
40bin41bin
@@ -51,3 +52,17 @@
51./production-configs52./production-configs
52bzr.dev53bzr.dev
53_trial_temp54_trial_temp
55lazr-js
56.bazaar
57.cache
58.subversion
59lib/canonical/buildd/launchpad-files
60.testrepository
61.memcache.pid
62./pipes
63lib/canonical/launchpad/apidoc/wadl-development-*.xml
64tags.new
65lp-clustered.dot
66lp-clustered.sfood
67lp-clustered.svg
68lp.sfood
5469
=== added file '.ctags'
--- .ctags 1970-01-01 00:00:00 +0000
+++ .ctags 2010-05-05 01:58:48 +0000
@@ -0,0 +1,1 @@
1--python-kinds=-iv
02
=== added file '.testr.conf'
--- .testr.conf 1970-01-01 00:00:00 +0000
+++ .testr.conf 2010-05-05 01:58:48 +0000
@@ -0,0 +1,3 @@
1[DEFAULT]
2test_command=./bin/test --subunit $IDOPTION
3test_id_option=--load-list $IDFILE
04
=== modified file 'Makefile'
--- Makefile 2009-10-07 09:55:24 +0000
+++ Makefile 2010-05-05 01:58:48 +0000
@@ -1,7 +1,7 @@
1# This file modified from Zope3/Makefile1# This file modified from Zope3/Makefile
2# Licensed under the ZPL, (c) Zope Corporation and contributors.2# Licensed under the ZPL, (c) Zope Corporation and contributors.
33
4PYTHON_VERSION=2.44PYTHON_VERSION=2.5
5PYTHON=python${PYTHON_VERSION}5PYTHON=python${PYTHON_VERSION}
6WD:=$(shell pwd)6WD:=$(shell pwd)
7PY=$(WD)/bin/py7PY=$(WD)/bin/py
@@ -17,18 +17,34 @@
1717
18LPCONFIG=development18LPCONFIG=development
1919
20JSFLAGS=
21ICING=lib/canonical/launchpad/icing
22LP_BUILT_JS_ROOT=${ICING}/build
23LAZR_BUILT_JS_ROOT=lazr-js/build
24
20MINS_TO_SHUTDOWN=1525MINS_TO_SHUTDOWN=15
2126
22CODEHOSTING_ROOT=/var/tmp/bazaar.launchpad.dev27CODEHOSTING_ROOT=/var/tmp/bazaar.launchpad.dev
2328
24BZR_VERSION_INFO = bzr-version-info.py29BZR_VERSION_INFO = bzr-version-info.py
2530
26WADL_FILE = lib/canonical/launchpad/apidoc/wadl-$(LPCONFIG).xml31APIDOC_DIR = lib/canonical/launchpad/apidoc
27API_INDEX = lib/canonical/launchpad/apidoc/index.html32WADL_TEMPLATE = $(APIDOC_DIR).tmp/wadl-$(LPCONFIG)-%(version)s.xml
33API_INDEX = $(APIDOC_DIR)/index.html
2834
29EXTRA_JS_FILES=lib/canonical/launchpad/icing/MochiKit.js \35# Do not add bin/buildout to this list.
30 $(shell $(HERE)/utilities/yui-deps.py) \36# It is impossible to get buildout to tell us all the files it would
31 lib/canonical/launchpad/icing/lazr/build/lazr.js37# build, since each egg's setup.py doesn't tell us that information.
38BUILDOUT_BIN = \
39 $(PY) bin/apiindex bin/combine-css bin/fl-build-report \
40 bin/fl-credential-ctl bin/fl-install-demo bin/fl-monitor-ctl \
41 bin/fl-record bin/fl-run-bench bin/fl-run-test bin/googletestservice \
42 bin/i18ncompile bin/i18nextract bin/i18nmergeall bin/i18nstats \
43 bin/harness bin/iharness bin/ipy bin/jsbuild bin/jslint bin/jssize \
44 bin/jstest bin/killservice bin/kill-test-services bin/lint.sh \
45 bin/lp-windmill bin/retest bin/run bin/sprite-util \
46 bin/start_librarian bin/stxdocs bin/tags bin/test bin/tracereport \
47 bin/twistd bin/update-download-cache bin/windmill
3248
33# DO NOT ALTER : this should just build by default49# DO NOT ALTER : this should just build by default
34default: inplace50default: inplace
@@ -43,22 +59,14 @@
43hosted_branches: $(PY)59hosted_branches: $(PY)
44 $(PY) ./utilities/make-dummy-hosted-branches60 $(PY) ./utilities/make-dummy-hosted-branches
4561
46$(WADL_FILE): $(BZR_VERSION_INFO)62$(API_INDEX): $(BZR_VERSION_INFO)
47 LPCONFIG=$(LPCONFIG) $(PY) ./utilities/create-lp-wadl.py > $@.tmp63 mkdir -p $(APIDOC_DIR).tmp
48 mv $@.tmp $@64 LPCONFIG=$(LPCONFIG) $(PY) ./utilities/create-lp-wadl-and-apidoc.py "$(WADL_TEMPLATE)"
4965 mv $(APIDOC_DIR).tmp/* $(APIDOC_DIR)
50$(API_INDEX): $(WADL_FILE)66 rmdir $(APIDOC_DIR).tmp
51 bin/apiindex $(WADL_FILE) > $@.tmp
52 mv $@.tmp $@
5367
54apidoc: compile $(API_INDEX)68apidoc: compile $(API_INDEX)
5569
56check_loggerhead_on_merge:
57 # Loggerhead doesn't depend on anything else in rocketfuel and nothing
58 # depends on it (yet).
59 make -C sourcecode/loggerhead check PYTHON=${PYTHON} \
60 PYTHON_VERSION=${PYTHON_VERSION} PYTHONPATH=$(PYTHONPATH)
61
62check_merge: $(PY)70check_merge: $(PY)
63 [ `PYTHONPATH= bzr status -S database/schema/ | \71 [ `PYTHONPATH= bzr status -S database/schema/ | \
64 grep -v "\(^P\|pending\|security.cfg\|Makefile\|unautovacuumable\|_pythonpath.py\)" | wc -l` -eq 0 ]72 grep -v "\(^P\|pending\|security.cfg\|Makefile\|unautovacuumable\|_pythonpath.py\)" | wc -l` -eq 0 ]
@@ -67,16 +75,12 @@
67check_db_merge: $(PY)75check_db_merge: $(PY)
68 ${PY} lib/canonical/tests/test_no_conflict_marker.py76 ${PY} lib/canonical/tests/test_no_conflict_marker.py
6977
70# This can be removed once we move to zc.buildout and we have versioned
71# dependencies, but for now we run both Launchpad and all other
72# dependencies tests for any merge to sourcecode.
73check_sourcecode_merge: check
74 $(MAKE) -C sourcecode check PYTHON=${PYTHON} \
75 PYTHON_VERSION=${PYTHON_VERSION} PYTHONPATH=$(PYTHONPATH)
76
77check_config: build78check_config: build
78 bin/test -m canonical.config.tests -vvt test_config79 bin/test -m canonical.config.tests -vvt test_config
7980
81check_schema: build
82 ${PY} utilities/check-db-revision.py
83
80# Clean before running the test suite, since the build might fail depending84# Clean before running the test suite, since the build might fail depending
81# what source changes happened. (e.g. apidoc depends on interfaces)85# what source changes happened. (e.g. apidoc depends on interfaces)
82check: clean build86check: clean build
@@ -90,9 +94,7 @@
90 @echo94 @echo
91 @echo "Running the JavaScript integration test suite"95 @echo "Running the JavaScript integration test suite"
92 @echo96 @echo
93 bin/test $(VERBOSITY) --layer=BugsWindmillLayer97 bin/test $(VERBOSITY) --layer=WindmillLayer
94 bin/test $(VERBOSITY) --layer=CodeWindmillLayer
95 bin/test $(VERBOSITY) --layer=SoyuzWindmillLayer
9698
97jscheck_functest: build99jscheck_functest: build
98 # Run the old functest Windmill integration tests. The test runner100 # Run the old functest Windmill integration tests. The test runner
@@ -124,37 +126,76 @@
124126
125inplace: build127inplace: build
126128
127build: $(BZR_VERSION_INFO) compile apidoc129build: compile apidoc jsbuild css_combine
130
131css_combine: sprite_css bin/combine-css
132 ${SHHH} bin/combine-css
133
134sprite_css: ${LP_BUILT_JS_ROOT}/style-3-0.css
135
136${LP_BUILT_JS_ROOT}/style-3-0.css: bin/sprite-util ${ICING}/style-3-0.css.in ${ICING}/icon-sprites.positioning
137 ${SHHH} bin/sprite-util create-css
138
139sprite_image:
140 ${SHHH} bin/sprite-util create-image
141
142jsbuild_lazr: bin/jsbuild
143 # We absolutely do not want to include the lazr.testing module and its
144 # jsTestDriver test harness modifications in the lazr.js and launchpad.js
145 # roll-up files. They fiddle with built-in functions! See Bug 482340.
146 ${SHHH} bin/jsbuild $(JSFLAGS) -b $(LAZR_BUILT_JS_ROOT) -x testing/ -c $(LAZR_BUILT_JS_ROOT)/yui
147
148jsbuild: jsbuild_lazr bin/jsbuild bin/jssize
149 ${SHHH} bin/jsbuild \
150 $(JSFLAGS) \
151 -n launchpad \
152 -s lib/canonical/launchpad/javascript \
153 -b $(LP_BUILT_JS_ROOT) \
154 $(shell $(HERE)/utilities/yui-deps.py) \
155 $(shell $(HERE)/utilities/lp-deps.py) \
156 lib/canonical/launchpad/icing/lazr/build/lazr.js
157 ${SHHH} bin/jssize
128158
129eggs:159eggs:
130 # Usually this is linked via link-external-sourcecode, but in160 # Usually this is linked via link-external-sourcecode, but in
131 # deployment we create this ourselves.161 # deployment we create this ourselves.
132 mkdir eggs162 mkdir eggs
133163
164# LP_SOURCEDEPS_PATH should point to the sourcecode directory, but we
165# want the parent directory where the download-cache and eggs directory
166# are. We re-use the variable that is using for the rocketfuel-get script.
134download-cache:167download-cache:
168ifdef LP_SOURCEDEPS_PATH
169 utilities/link-external-sourcecode $(LP_SOURCEDEPS_PATH)/..
170else
135 @echo "Missing ./download-cache."171 @echo "Missing ./download-cache."
136 @echo "Developers: please run utilities/link-external-sourcecode."172 @echo "Developers: please run utilities/link-external-sourcecode."
137 @exit 1173 @exit 1
174endif
175
176buildonce_eggs: $(PY)
177 find eggs -name '*.pyc' -exec rm {} \;
138178
139# The download-cache dependency comes *before* eggs so that developers get the179# The download-cache dependency comes *before* eggs so that developers get the
140# warning before the eggs directory is made. The target for the eggs directory180# warning before the eggs directory is made. The target for the eggs directory
141# is only there for deployment convenience.181# is only there for deployment convenience.
142bin/buildout: download-cache eggs182bin/buildout: download-cache eggs
143 $(SHHH) PYTHONPATH= $(PYTHON) bootstrap.py\183 $(SHHH) PYTHONPATH= $(PYTHON) bootstrap.py\
144 --ez_setup-source=ez_setup.py \184 --setup-source=ez_setup.py \
145 --download-base=download-cache/dist --eggs=eggs185 --download-base=download-cache/dist --eggs=eggs
146186
147$(PY): bin/buildout versions.cfg $(BUILDOUT_CFG) setup.py187# This builds bin/py and all the other bin files except bin/buildout.
188# Remove the target before calling buildout to ensure that buildout
189# updates the timestamp.
190$(BUILDOUT_BIN): bin/buildout versions.cfg $(BUILDOUT_CFG) setup.py
191 $(RM) $@
148 $(SHHH) PYTHONPATH= ./bin/buildout \192 $(SHHH) PYTHONPATH= ./bin/buildout \
149 configuration:instance_name=${LPCONFIG} -c $(BUILDOUT_CFG)193 configuration:instance_name=${LPCONFIG} -c $(BUILDOUT_CFG)
150194
151compile: $(PY)195compile: $(PY) $(BZR_VERSION_INFO)
152 ${SHHH} $(MAKE) -C sourcecode build PYTHON=${PYTHON} \196 ${SHHH} $(MAKE) -C sourcecode build PYTHON=${PYTHON} \
153 PYTHON_VERSION=${PYTHON_VERSION} LPCONFIG=${LPCONFIG}197 PYTHON_VERSION=${PYTHON_VERSION} LPCONFIG=${LPCONFIG}
154 ${SHHH} LPCONFIG=${LPCONFIG} $(PY) -t buildmailman.py198 ${SHHH} LPCONFIG=${LPCONFIG} ${PY} -t buildmailman.py
155 ${SHHH} $(PY) sourcecode/lazr-js/tools/build.py \
156 -n launchpad -s lib/canonical/launchpad/javascript \
157 -b lib/canonical/launchpad/icing/build $(EXTRA_JS_FILES)
158199
159test_build: build200test_build: build
160 bin/test $(TESTFLAGS) $(TESTOPTS)201 bin/test $(TESTFLAGS) $(TESTOPTS)
@@ -168,28 +209,38 @@
168ftest_inplace: inplace209ftest_inplace: inplace
169 bin/test -f $(TESTFLAGS) $(TESTOPTS)210 bin/test -f $(TESTFLAGS) $(TESTOPTS)
170211
171run: inplace stop212merge-proposal-jobs:
213 # Handle merge proposal email jobs.
214 $(PY) cronscripts/merge-proposal-jobs.py -v
215
216run: check_schema inplace stop
172 $(RM) thread*.request217 $(RM) thread*.request
173 bin/run -r librarian,google-webservice -i $(LPCONFIG)218 bin/run -r librarian,google-webservice,memcached -i $(LPCONFIG)
174219
175start-gdb: inplace stop support_files220start-gdb: check_schema inplace stop support_files
176 $(RM) thread*.request221 $(RM) thread*.request
177 nohup gdb -x run.gdb --args bin/run -i $(LPCONFIG) \222 nohup gdb -x run.gdb --args bin/run -i $(LPCONFIG) \
178 -r librarian,google-webservice223 -r librarian,google-webservice
179 > ${LPCONFIG}-nohup.out 2>&1 &224 > ${LPCONFIG}-nohup.out 2>&1 &
180225
181run_all: inplace stop hosted_branches226run_all: check_schema inplace stop hosted_branches
182 $(RM) thread*.request227 $(RM) thread*.request
183 bin/run -r librarian,buildsequencer,sftp,mailman,codebrowse,google-webservice -i $(LPCONFIG)228 bin/run -r librarian,sftp,mailman,codebrowse,google-webservice,memcached \
229 -i $(LPCONFIG)
184230
185run_codebrowse: build231run_codebrowse: build
186 BZR_PLUGIN_PATH=bzrplugins $(PY) sourcecode/launchpad-loggerhead/start-loggerhead.py -f232 BZR_PLUGIN_PATH=bzrplugins $(PY) scripts/start-loggerhead.py -f
187233
188start_codebrowse: build234start_codebrowse: build
189 BZR_PLUGIN_PATH=$(shell pwd)/bzrplugins $(PY) sourcecode/launchpad-loggerhead/start-loggerhead.py235 BZR_PLUGIN_PATH=$(shell pwd)/bzrplugins $(PY) scripts/start-loggerhead.py
190236
191stop_codebrowse:237stop_codebrowse:
192 $(PY) sourcecode/launchpad-loggerhead/stop-loggerhead.py238 $(PY) scripts/stop-loggerhead.py
239
240run_codehosting: check_schema inplace stop hosted_branches
241 $(RM) thread*.request
242 bin/run -r librarian,sftp,codebrowse -i $(LPCONFIG)
243
193244
194start_librarian: build245start_librarian: build
195 bin/start_librarian246 bin/start_librarian
@@ -202,14 +253,14 @@
202253
203scan_branches:254scan_branches:
204 # Scan branches from the filesystem into the database.255 # Scan branches from the filesystem into the database.
205 $(PY) cronscripts/branch-scanner.py256 $(PY) cronscripts/scan_branches.py
206257
207sync_branches: pull_branches scan_branches258sync_branches: pull_branches scan_branches merge-proposal-jobs
208259
209$(BZR_VERSION_INFO):260$(BZR_VERSION_INFO):
210 scripts/update-bzr-version-info.sh261 scripts/update-bzr-version-info.sh
211262
212support_files: $(WADL_FILE) $(BZR_VERSION_INFO)263support_files: $(API_INDEX) $(BZR_VERSION_INFO)
213264
214# Intended for use on developer machines265# Intended for use on developer machines
215start: inplace stop support_files initscript-start266start: inplace stop support_files initscript-start
@@ -231,7 +282,7 @@
231# servers, where we know we don't need the extra steps in a full282# servers, where we know we don't need the extra steps in a full
232# "make stop" because of how the code is deployed/built.283# "make stop" because of how the code is deployed/built.
233initscript-stop:284initscript-stop:
234 bin/killservice librarian buildsequencer launchpad mailman285 bin/killservice librarian launchpad mailman
235286
236shutdown: scheduleoutage stop287shutdown: scheduleoutage stop
237 $(RM) +maintenancetime.txt288 $(RM) +maintenancetime.txt
@@ -242,18 +293,26 @@
242 echo Sleeping ${MINS_TO_SHUTDOWN} mins293 echo Sleeping ${MINS_TO_SHUTDOWN} mins
243 sleep ${MINS_TO_SHUTDOWN}m294 sleep ${MINS_TO_SHUTDOWN}m
244295
245harness:296harness: bin/harness
246 bin/harness297 bin/harness
247298
248iharness:299iharness: bin/iharness
249 bin/iharness300 bin/iharness
250301
251rebuildfti:302rebuildfti:
252 @echo Rebuilding FTI indexes on launchpad_dev database303 @echo Rebuilding FTI indexes on launchpad_dev database
253 $(PY) database/schema/fti.py -d launchpad_dev --force304 $(PY) database/schema/fti.py -d launchpad_dev --force
254305
255clean:306clean_js:
307 $(RM) $(LP_BUILT_JS_ROOT)/launchpad.js
308 $(RM) -r $(LAZR_BUILT_JS_ROOT)
309
310clean: clean_js
256 $(MAKE) -C sourcecode/pygettextpo clean311 $(MAKE) -C sourcecode/pygettextpo clean
312 # XXX gary 2009-11-16 bug 483782
313 # The pygettextpo Makefile should have this next line in it for its make
314 # clean, and then we should remove this line.
315 $(RM) sourcecode/pygpgme/gpgme/*.so
257 if test -f sourcecode/mailman/Makefile; then \316 if test -f sourcecode/mailman/Makefile; then \
258 $(MAKE) -C sourcecode/mailman clean; \317 $(MAKE) -C sourcecode/mailman clean; \
259 fi318 fi
@@ -263,22 +322,24 @@
263 -print0 | xargs -r0 $(RM)322 -print0 | xargs -r0 $(RM)
264 $(RM) -r bin323 $(RM) -r bin
265 $(RM) -r parts324 $(RM) -r parts
325 $(RM) -r develop-eggs
266 $(RM) .installed.cfg326 $(RM) .installed.cfg
267 $(RM) -r build327 $(RM) -r build
268 $(RM) thread*.request328 $(RM) thread*.request
269 $(RM) -r lib/mailman329 $(RM) -r lib/mailman
270 $(RM) -rf lib/canonical/launchpad/icing/build/*330 $(RM) -rf lib/canonical/launchpad/icing/build/*
271 $(RM) -r $(CODEHOSTING_ROOT)331 $(RM) -r $(CODEHOSTING_ROOT)
272 $(RM) $(WADL_FILE) $(API_INDEX)332 $(RM) $(APIDOC_DIR)/wadl*.xml $(APIDOC_DIR)/*.html
333 $(RM) -rf $(APIDOC_DIR).tmp
273 $(RM) $(BZR_VERSION_INFO)334 $(RM) $(BZR_VERSION_INFO)
274 $(RM) _pythonpath.py335 $(RM) _pythonpath.py
336 $(RM) +config-overrides.zcml
275 $(RM) -rf \337 $(RM) -rf \
276 /var/tmp/builddmaster \338 /var/tmp/builddmaster \
277 /var/tmp/bzrsync \339 /var/tmp/bzrsync \
278 /var/tmp/codehosting.test \340 /var/tmp/codehosting.test \
279 /var/tmp/codeimport \341 /var/tmp/codeimport \
280 /var/tmp/fatsam.appserver \342 /var/tmp/fatsam.appserver \
281 /var/tmp/launchpad_mailqueue \
282 /var/tmp/lperr \343 /var/tmp/lperr \
283 /var/tmp/lperr.test \344 /var/tmp/lperr.test \
284 /var/tmp/mailman \345 /var/tmp/mailman \
@@ -286,6 +347,11 @@
286 /var/tmp/ppa \347 /var/tmp/ppa \
287 /var/tmp/ppa.test \348 /var/tmp/ppa.test \
288 /var/tmp/zeca349 /var/tmp/zeca
350 # /var/tmp/launchpad_mailqueue is created read-only on ec2test
351 # instances.
352 if [ -w /var/tmp/launchpad_mailqueue ]; then $(RM) -rf /var/tmp/launchpad_mailqueue; fi
353 $(RM) -f lp.sfood lp-clustered.sfood lp-clustered.dot lp-clustered.svg
354
289355
290realclean: clean356realclean: clean
291 $(RM) TAGS tags357 $(RM) TAGS tags
@@ -310,6 +376,8 @@
310launchpad.pot:376launchpad.pot:
311 bin/i18nextract.py377 bin/i18nextract.py
312378
379# Called by the rocketfuel-setup script. You probably don't want to run this
380# on its own.
313install: reload-apache381install: reload-apache
314382
315copy-certificates:383copy-certificates:
@@ -328,10 +396,7 @@
328 a2ensite local-launchpad396 a2ensite local-launchpad
329397
330reload-apache: enable-apache-launchpad398reload-apache: enable-apache-launchpad
331 /etc/init.d/apache2 reload399 /etc/init.d/apache2 restart
332
333static:
334 $(PY) scripts/make-static.py
335400
336TAGS: compile401TAGS: compile
337 # emacs tags402 # emacs tags
@@ -345,8 +410,37 @@
345 # idutils ID file410 # idutils ID file
346 bin/tags -i411 bin/tags -i
347412
413lp.sfood:
414 # Generate import dependency graph
415 sfood -i -u -I lib/sqlobject -I lib/schoolbell -I lib/devscripts -I lib/contrib \
416 -I lib/canonical/not-used lib/canonical lib/lp 2>/dev/null | grep -v contrib/ \
417 | grep -v sqlobject | grep -v BeautifulSoup | grep -v psycopg \
418 | grep -v schoolbell > lp.sfood.tmp
419 mv lp.sfood.tmp lp.sfood
420
421
422lp-clustered.sfood: lp.sfood lp-sfood-packages
423 # Cluster the import dependency graph
424 sfood-cluster -f lp-sfood-packages < lp.sfood > lp-clustered.sfood.tmp
425 mv lp-clustered.sfood.tmp lp-clustered.sfood
426
427
428lp-clustered.dot: lp-clustered.sfood
429 # Build the visual graph
430 sfood-graph -p < lp-clustered.sfood > lp-clustered.dot.tmp
431 mv lp-clustered.dot.tmp lp-clustered.dot
432
433
434lp-clustered.svg: lp-clustered.dot
435 # Render to svg
436 dot -Tsvg < lp-clustered.dot > lp-clustered.svg.tmp
437 mv lp-clustered.svg.tmp lp-clustered.svg
438
439
348.PHONY: apidoc check tags TAGS zcmldocs realclean clean debug stop\440.PHONY: apidoc check tags TAGS zcmldocs realclean clean debug stop\
349 start run ftest_build ftest_inplace test_build test_inplace pagetests\441 start run ftest_build ftest_inplace test_build test_inplace pagetests\
350 check check_loggerhead_on_merge check_merge check_sourcecode_merge \442 check check_merge \
351 schema default launchpad.pot check_merge_ui pull scan sync_branches\443 schema default launchpad.pot check_merge_ui pull scan sync_branches\
352 reload-apache hosted_branches check_db_merge check_mailman check_config444 reload-apache hosted_branches check_db_merge check_mailman check_config\
445 jsbuild jsbuild_lazr clean_js buildonce_eggs \
446 sprite_css sprite_image css_combine compile check_schema
353447
=== modified file 'bootstrap.py'
--- bootstrap.py 2009-08-05 18:52:52 +0000
+++ bootstrap.py 2010-05-05 01:58:48 +0000
@@ -17,154 +17,190 @@
17The script accepts buildout command-line options, so you can17The script accepts buildout command-line options, so you can
18use the -c option to specify an alternate configuration file.18use the -c option to specify an alternate configuration file.
1919
20$Id: bootstrap.py 101930 2009-07-15 18:34:35Z gary $20$Id$
21"""21"""
2222
23import os, re, shutil, sys, tempfile, textwrap, urllib, urllib223import os, shutil, sys, tempfile, textwrap, urllib, urllib2
2424from optparse import OptionParser
25# We have to manually parse our options rather than using one of the stdlib25
26# tools because we want to pass the ones we don't recognize along to26if sys.platform == 'win32':
27# zc.buildout.buildout.main.27 def quote(c):
2828 if ' ' in c:
29configuration = {29 return '"%s"' % c # work around spawn lamosity on windows
30 '--ez_setup-source': 'http://peak.telecommunity.com/dist/ez_setup.py',
31 '--version': '',
32 '--download-base': None,
33 '--eggs': None}
34
35helpstring = __doc__ + textwrap.dedent('''
36 This script recognizes the following options itself. The first option it
37 encounters that is not one of these will cause the script to stop parsing
38 options and pass the rest on to buildout. Therefore, if you want to use
39 any of the following options *and* buildout command-line options like
40 -c, first use the following options, and then use the buildout options.
41
42 Options:
43 --version=ZC_BUILDOUT_VERSION
44 Specify a version number of the zc.buildout to use
45 --ez_setup-source=URL_OR_FILE
46 Specify a URL or file location for the ez_setup file.
47 Defaults to
48 %(--ez_setup-source)s
49 --download-base=URL_OR_DIRECTORY
50 Specify a URL or directory for downloading setuptools and
51 zc.buildout. Defaults to PyPI.
52 --eggs=DIRECTORY
53 Specify a directory for storing eggs. Defaults to a temporary
54 directory that is deleted when the bootstrap script completes.
55
56 By using --ez_setup-source and --download-base to point to local resources,
57 you can keep this script from going over the network.
58 ''' % configuration)
59match_equals = re.compile(r'(%s)=(.*)' % ('|'.join(configuration),)).match
60args = sys.argv[1:]
61if args == ['--help']:
62 print helpstring
63 sys.exit(0)
64
65# If we end up using a temporary directory for storing our eggs, this will
66# hold the path of that directory. On the other hand, if an explicit directory
67# is specified in the argv, this will remain None.
68tmpeggs = None
69
70while args:
71 val = args[0]
72 if val in configuration:
73 del args[0]
74 if not args or args[0].startswith('-'):
75 print "ERROR: %s requires an argument."
76 print helpstring
77 sys.exit(1)
78 configuration[val] = args[0]
79 else:
80 match = match_equals(val)
81 if match and match.group(1) in configuration:
82 configuration[match.group(1)] = match.group(2)
83 else:30 else:
84 break31 return c
85 del args[0]32else:
8633 quote = str
87for name in ('--ez_setup-source', '--download-base'):34
88 val = configuration[name]35# In order to be more robust in the face of system Pythons, we want to
89 if val is not None and '://' not in val: # We're being lazy.36# run without site-packages loaded. This is somewhat tricky, in
90 configuration[name] = 'file://%s' % (37# particular because Python 2.6's distutils imports site, so starting
91 urllib.pathname2url(os.path.abspath(os.path.expanduser(val))),)38# with the -S flag is not sufficient. However, we'll start with that:
9239if 'site' in sys.modules:
93if (configuration['--download-base'] and40 # We will restart with python -S.
94 not configuration['--download-base'].endswith('/')):41 args = sys.argv[:]
95 # Download base needs a trailing slash to make the world happy.42 args[0:0] = [sys.executable, '-S']
96 configuration['--download-base'] += '/'43 args = map(quote, args)
9744 os.execv(sys.executable, args)
98if not configuration['--eggs']:45# Now we are running with -S. We'll get the clean sys.path, import site
99 configuration['--eggs'] = tmpeggs = tempfile.mkdtemp()46# because distutils will do it later, and then reset the path and clean
100else:47# out any namespace packages from site-packages that might have been
101 configuration['--eggs'] = os.path.abspath(48# loaded by .pth files.
102 os.path.expanduser(configuration['--eggs']))49clean_path = sys.path[:]
10350import site
104# The requirement is what we will pass to setuptools to specify zc.buildout.51sys.path[:] = clean_path
105requirement = 'zc.buildout'52for k, v in sys.modules.items():
106if configuration['--version']:53 if (hasattr(v, '__path__') and
107 requirement += '==' + configuration['--version']54 len(v.__path__)==1 and
55 not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))):
56 # This is a namespace package. Remove it.
57 sys.modules.pop(k)
58
59is_jython = sys.platform.startswith('java')
60
61setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
62distribute_source = 'http://python-distribute.org/distribute_setup.py'
63
64# parsing arguments
65def normalize_to_url(option, opt_str, value, parser):
66 if value:
67 if '://' not in value: # It doesn't smell like a URL.
68 value = 'file://%s' % (
69 urllib.pathname2url(
70 os.path.abspath(os.path.expanduser(value))),)
71 if opt_str == '--download-base' and not value.endswith('/'):
72 # Download base needs a trailing slash to make the world happy.
73 value += '/'
74 else:
75 value = None
76 name = opt_str[2:].replace('-', '_')
77 setattr(parser.values, name, value)
78
79usage = '''\
80[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
81
82Bootstraps a buildout-based project.
83
84Simply run this script in a directory containing a buildout.cfg, using the
85Python that you want bin/buildout to use.
86
87Note that by using --setup-source and --download-base to point to
88local resources, you can keep this script from going over the network.
89'''
90
91parser = OptionParser(usage=usage)
92parser.add_option("-v", "--version", dest="version",
93 help="use a specific zc.buildout version")
94parser.add_option("-d", "--distribute",
95 action="store_true", dest="use_distribute", default=False,
96 help="Use Distribute rather than Setuptools.")
97parser.add_option("--setup-source", action="callback", dest="setup_source",
98 callback=normalize_to_url, nargs=1, type="string",
99 help=("Specify a URL or file location for the setup file. "
100 "If you use Setuptools, this will default to " +
101 setuptools_source + "; if you use Distribute, this "
102 "will default to " + distribute_source +"."))
103parser.add_option("--download-base", action="callback", dest="download_base",
104 callback=normalize_to_url, nargs=1, type="string",
105 help=("Specify a URL or directory for downloading "
106 "zc.buildout and either Setuptools or Distribute. "
107 "Defaults to PyPI."))
108parser.add_option("--eggs",
109 help=("Specify a directory for storing eggs. Defaults to "
110 "a temporary directory that is deleted when the "
111 "bootstrap script completes."))
112parser.add_option("-c", None, action="store", dest="config_file",
113 help=("Specify the path to the buildout configuration "
114 "file to be used."))
115
116options, args = parser.parse_args()
117
118# if -c was provided, we push it back into args for buildout' main function
119if options.config_file is not None:
120 args += ['-c', options.config_file]
121
122if options.eggs:
123 eggs_dir = os.path.abspath(os.path.expanduser(options.eggs))
124else:
125 eggs_dir = tempfile.mkdtemp()
126
127if options.setup_source is None:
128 if options.use_distribute:
129 options.setup_source = distribute_source
130 else:
131 options.setup_source = setuptools_source
132
133args = args + ['bootstrap']
134
108135
109try:136try:
137 to_reload = False
138 import pkg_resources
139 to_reload = True
140 if not hasattr(pkg_resources, '_distribute'):
141 raise ImportError
110 import setuptools # A flag. Sometimes pkg_resources is installed alone.142 import setuptools # A flag. Sometimes pkg_resources is installed alone.
111 import pkg_resources
112except ImportError:143except ImportError:
144 ez_code = urllib2.urlopen(
145 options.setup_source).read().replace('\r\n', '\n')
113 ez = {}146 ez = {}
114 exec urllib2.urlopen(configuration['--ez_setup-source']).read() in ez147 exec ez_code in ez
115 setuptools_args = dict(to_dir=configuration['--eggs'], download_delay=0)148 setup_args = dict(to_dir=eggs_dir, download_delay=0)
116 if configuration['--download-base']:149 if options.download_base:
117 setuptools_args['download_base'] = configuration['--download-base']150 setup_args['download_base'] = options.download_base
118 ez['use_setuptools'](**setuptools_args)151 if options.use_distribute:
119 import pkg_resources152 setup_args['no_fake'] = True
153 ez['use_setuptools'](**setup_args)
154 if to_reload:
155 reload(pkg_resources)
156 else:
157 import pkg_resources
120 # This does not (always?) update the default working set. We will158 # This does not (always?) update the default working set. We will
121 # do it.159 # do it.
122 for path in sys.path:160 for path in sys.path:
123 if path not in pkg_resources.working_set.entries:161 if path not in pkg_resources.working_set.entries:
124 pkg_resources.working_set.add_entry(path)162 pkg_resources.working_set.add_entry(path)
125163
126if sys.platform == 'win32':
127 def quote(c):
128 if ' ' in c:
129 return '"%s"' % c # work around spawn lamosity on windows
130 else:
131 return c
132else:
133 def quote (c):
134 return c
135cmd = [quote(sys.executable),164cmd = [quote(sys.executable),
136 '-c',165 '-c',
137 quote('from setuptools.command.easy_install import main; main()'),166 quote('from setuptools.command.easy_install import main; main()'),
138 '-mqNxd',167 '-mqNxd',
139 quote(configuration['--eggs'])]168 quote(eggs_dir)]
140169
141if configuration['--download-base']:170if options.download_base:
142 cmd.extend(['-f', quote(configuration['--download-base'])])171 cmd.extend(['-f', quote(options.download_base)])
143172
173requirement = 'zc.buildout'
174if options.version:
175 requirement = '=='.join((requirement, options.version))
144cmd.append(requirement)176cmd.append(requirement)
145177
178if options.use_distribute:
179 setup_requirement = 'distribute'
180else:
181 setup_requirement = 'setuptools'
146ws = pkg_resources.working_set182ws = pkg_resources.working_set
147env = dict(183env = dict(
148 os.environ,184 os.environ,
149 PYTHONPATH=ws.find(pkg_resources.Requirement.parse('setuptools')).location)185 PYTHONPATH=ws.find(
186 pkg_resources.Requirement.parse(setup_requirement)).location)
150187
151is_jython = sys.platform.startswith('java')
152if is_jython:188if is_jython:
153 import subprocess189 import subprocess
154 exitcode = subprocess.Popen(cmd, env=env).wait()190 exitcode = subprocess.Popen(cmd, env=env).wait()
155else: # Windows needs this, apparently; otherwise we would prefer subprocess191else: # Windows prefers this, apparently; otherwise we would prefer subprocess
156 exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))192 exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
157if exitcode != 0:193if exitcode != 0:
158 sys.stdout.flush()194 sys.stdout.flush()
195 sys.stderr.flush()
159 print ("An error occured when trying to install zc.buildout. "196 print ("An error occured when trying to install zc.buildout. "
160 "Look above this message for any errors that "197 "Look above this message for any errors that "
161 "were output by easy_install.")198 "were output by easy_install.")
162 sys.exit(exitcode)199 sys.exit(exitcode)
163200
164ws.add_entry(configuration['--eggs'])201ws.add_entry(eggs_dir)
165ws.require(requirement)202ws.require(requirement)
166import zc.buildout.buildout203import zc.buildout.buildout
167args.append('bootstrap')
168zc.buildout.buildout.main(args)204zc.buildout.buildout.main(args)
169if tmpeggs is not None:205if not options.eggs: # clean up temporary egg directory
170 shutil.rmtree(tmpeggs)206 shutil.rmtree(eggs_dir)
171207
=== modified file 'buildmailman.py'
--- buildmailman.py 2009-09-11 02:17:29 +0000
+++ buildmailman.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#! /usr/bin/python2.41#! /usr/bin/python2.5
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -84,25 +84,52 @@
8484
85 # Build and install the Mailman software. Note that we don't care about85 # Build and install the Mailman software. Note that we don't care about
86 # --with-cgi-gid because we're not going to use that Mailman subsystem.86 # --with-cgi-gid because we're not going to use that Mailman subsystem.
87 executable = os.path.abspath('bin/py')
87 configure_args = (88 configure_args = (
88 './configure',89 './configure',
89 '--prefix', mailman_path,90 '--prefix', mailman_path,
90 '--with-var-prefix=' + var_dir,91 '--with-var-prefix=' + var_dir,
91 '--with-python=' + sys.executable,92 '--with-python=' + executable,
92 '--with-username=' + user,93 '--with-username=' + user,
93 '--with-groupname=' + group,94 '--with-groupname=' + group,
94 '--with-mail-gid=' + group,95 '--with-mail-gid=' + group,
95 '--with-mailhost=' + build_host_name,96 '--with-mailhost=' + build_host_name,
96 '--with-urlhost=' + build_host_name,97 '--with-urlhost=' + build_host_name,
97 )98 )
99 # Configure.
98 retcode = subprocess.call(configure_args, cwd=mailman_source)100 retcode = subprocess.call(configure_args, cwd=mailman_source)
99 if retcode:101 if retcode:
100 print >> sys.stderr, 'Could not configure Mailman:'102 print >> sys.stderr, 'Could not configure Mailman:'
101 sys.exit(retcode)103 sys.exit(retcode)
104 # Make.
102 retcode = subprocess.call(('make',), cwd=mailman_source)105 retcode = subprocess.call(('make',), cwd=mailman_source)
103 if retcode:106 if retcode:
104 print >> sys.stderr, 'Could not make Mailman.'107 print >> sys.stderr, 'Could not make Mailman.'
105 sys.exit(retcode)108 sys.exit(retcode)
109 # We have a brief interlude before we install. Hardy will not
110 # accept a script as the executable for the shebang line--it will
111 # treat the file as a shell script instead. The ``bin/by``
112 # executable that we specified in '--with-python' above is a script
113 # so this behavior causes problems for us. Our work around is to
114 # prefix the ``bin/py`` script with ``/usr/bin/env``, which makes
115 # Hardy happy. We need to do this before we install because the
116 # installation will call Mailman's ``bin/update``, which is a script
117 # that needs this fix.
118 build_dir = os.path.join(mailman_source, 'build')
119 original = '#! %s\n' % (executable,)
120 modified = '#! /usr/bin/env %s\n' % (executable,)
121 for (dirpath, dirnames, filenames) in os.walk(build_dir):
122 for filename in filenames:
123 filename = os.path.join(dirpath, filename)
124 f = open(filename, 'r')
125 if f.readline() == original:
126 rest = f.read()
127 f.close()
128 f = open(filename, 'w')
129 f.write(modified)
130 f.write(rest)
131 f.close()
132 # Now we actually install.
106 retcode = subprocess.call(('make', 'install'), cwd=mailman_source)133 retcode = subprocess.call(('make', 'install'), cwd=mailman_source)
107 if retcode:134 if retcode:
108 print >> sys.stderr, 'Could not install Mailman.'135 print >> sys.stderr, 'Could not install Mailman.'
109136
=== modified file 'buildout-templates/_pythonpath.py.in'
--- buildout-templates/_pythonpath.py.in 2009-08-21 19:13:05 +0000
+++ buildout-templates/_pythonpath.py.in 2010-05-05 01:58:48 +0000
@@ -4,17 +4,36 @@
4# NOTE: This is a generated file. The original is in4# NOTE: This is a generated file. The original is in
5# buildout-templates/_pythonpath.py.in5# buildout-templates/_pythonpath.py.in
66
7__metaclass__ = type7# This file works if the Python has been started with -S, or if bin/py
88# has been used.
9import sys, os9
1010# Auto-generated code to handle relative paths
11sys.path[0:0] = [${string-paths}]11${python-relative-path-setup}
12# Enable Storm's C extensions12
13os.environ['STORM_CEXTENSIONS'] = '1'13import os
1414import sys
15# We don't want to bother tests or logs with these.
16import warnings15import warnings
16
17# XXX: 2010-04-26, Salgado, bug=570246: Silence python2.6 deprecation
18# warnings.
17warnings.filterwarnings(19warnings.filterwarnings(
18 'ignore',20 'ignore', '.*(md5|sha|sets)', DeprecationWarning,
19 'Module .+ was already imported from .+, but .+ is being added.*',21 )
20 UserWarning)22
23site_dir = ${scripts:parts-directory|path-repr}
24
25if ('site' in sys.modules and
26 not sys.modules['site'].__file__.startswith(
27 os.path.join(site_dir, 'site.py'))):
28 # We have the wrong site.py, so our paths are not set up correctly.
29 # We blow up, with a hopefully helpful error message.
30 raise RuntimeError(
31 'The wrong site.py is imported (%r imported, %r expected). '
32 'Scripts should usually be '
33 "started with Launchpad's bin/py, or with a Python invoked with "
34 'the -S flag.' % (
35 sys.modules['site'].__file__, os.path.join(site_dir, 'site.py')))
36
37if site_dir not in sys.path:
38 sys.path.insert(0, site_dir)
39import site # sets up paths
2140
=== added file 'buildout-templates/bin/combine-css.in'
--- buildout-templates/bin/combine-css.in 1970-01-01 00:00:00 +0000
+++ buildout-templates/bin/combine-css.in 2010-05-05 01:58:48 +0000
@@ -0,0 +1,51 @@
1#!${buildout:executable} -S
2
3# Initialize our paths.
4${python-relative-path-setup}
5import sys
6sys.path.insert(0, ${scripts:parts-directory|path-repr})
7import site
8
9import os
10
11from lazr.js.build import ComboFile
12from lazr.js.combo import combine_files
13
14
15root = ${buildout:directory|path-repr}
16icing = os.path.join(root, 'lib/canonical/launchpad/icing')
17target = os.path.join(icing, 'combo.css')
18# It'd probably be nice to have this script find all the CSS files we might
19# need and combine them together, but if we do that we'd certainly end up
20# including lots of styles that we don't need/want, so keeping this hard-coded
21# list seems like the best option for now.
22names = [
23 'style.css',
24 'lazr/build/yui/cssreset/reset.css',
25 'lazr/build/yui/cssfonts/fonts.css',
26 'lazr/build/yui/cssgrids/grids.css',
27 'lazr/build/lazr/assets/skins/sam/lazr.css',
28 'lazr/build/inlineedit/assets/skins/sam/editor.css',
29 'lazr/build/autocomplete/assets/skins/sam/autocomplete.css',
30 'lazr/build/overlay/assets/skins/sam/pretty-overlay.css',
31 'lazr/build/formoverlay/assets/formoverlay-core.css',
32 'lazr/build/picker/assets/skins/sam/picker.css',
33 'lazr/build/activator/assets/skins/sam/activator.css',
34 'lazr/build/choiceedit/assets/choiceedit-core.css',
35 # This one goes at the end because it's our main stylesheet and should
36 # take precedence over the others.
37 'build/style-3-0.css']
38
39absolute_names = []
40for name in names:
41 absolute_names.append(os.path.join(icing, name))
42
43combo = ComboFile(absolute_names, target)
44if combo.needs_update():
45 result = ''
46 for content in combine_files(names, icing):
47 result += content
48
49 f = open(target, 'w')
50 f.write(result)
51 f.close()
052
=== modified file 'buildout-templates/bin/jstest.in'
--- buildout-templates/bin/jstest.in 2009-10-07 10:19:19 +0000
+++ buildout-templates/bin/jstest.in 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!${buildout:executable}1#!${buildout:executable} -S
2# Copyright 2009 Canonical Ltd. This software is licensed under the2# Copyright 2009 Canonical Ltd. This software is licensed under the
3# GNU Affero General Public License version 3 (see the file LICENSE).3# GNU Affero General Public License version 3 (see the file LICENSE).
44
@@ -14,10 +14,11 @@
1414
15"""15"""
1616
17# Add the buildout sys.path17# Initialize our paths.
18${python-relative-path-setup}
18import sys19import sys
19sys.path[0:0] = [${string-paths}]20sys.path.insert(0, ${scripts:parts-directory|path-repr})
2021import site
2122
22import subprocess23import subprocess
23import os24import os
2425
=== added file 'buildout-templates/bin/kill-test-services.in'
--- buildout-templates/bin/kill-test-services.in 1970-01-01 00:00:00 +0000
+++ buildout-templates/bin/kill-test-services.in 2010-05-05 01:58:48 +0000
@@ -0,0 +1,42 @@
1#!${buildout:executable} -S
2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).
5"""Kill all the test services that may persist between test runs."""
6
7# Initialize our paths.
8${python-relative-path-setup}
9import sys
10sys.path.insert(0, ${scripts:parts-directory|path-repr})
11import site
12
13# Tell canonical.config to use the testrunner config instance, so that
14# we don't kill the real services.
15from canonical.config import config
16config.setInstance('testrunner')
17config.generate_overrides()
18
19import sys
20
21from canonical.testing.layers import MemcachedLayer
22from canonical.librarian.ftests.harness import (
23 LibrarianTestSetup, TacLibrarianTestSetup)
24from lp.services.osutils import kill_by_pidfile
25
26
27def main(args):
28 if '-h' in args or '--help' in args:
29 print __doc__
30 return 0
31 print "Killing Memcached....",
32 kill_by_pidfile(MemcachedLayer.getPidFile())
33 print "done."
34 print "Killing Librarian....",
35 TacLibrarianTestSetup().tearDown()
36 LibrarianTestSetup().tearDownRoot()
37 print "done."
38 return 0
39
40
41if __name__ == '__main__':
42 sys.exit(main(sys.argv[1:]))
043
=== modified file 'buildout-templates/bin/lint.sh.in'
--- buildout-templates/bin/lint.sh.in 2009-07-17 00:26:05 +0000
+++ buildout-templates/bin/lint.sh.in 2010-05-05 01:58:48 +0000
@@ -6,7 +6,9 @@
6# Runs xmlint, pyflakes and pylint on files changed from parent branch.6# Runs xmlint, pyflakes and pylint on files changed from parent branch.
7# Use '-v' to run pylint under stricter conditions with additional messages.7# Use '-v' to run pylint under stricter conditions with additional messages.
88
9utilitiesdir=`dirname $0`/../utilities9${shell-relative-path-setup}
10
11utilitiesdir=${buildout:directory/utilities|shell-path}
10[ -z "$utilitiesdir" ] && utilitiesdir=.12[ -z "$utilitiesdir" ] && utilitiesdir=.
1113
12# Fail if any of the required tools are not installed.14# Fail if any of the required tools are not installed.
@@ -56,9 +58,15 @@
56 # This is a loom, lint changes relative to the lower thread.58 # This is a loom, lint changes relative to the lower thread.
57 rev_option="-r thread:"59 rev_option="-r thread:"
58 else60 else
59 # Lint changes relative to the parent.61 if test "$(bzr pipes | sed -n -e "/^\\*/q;p" | wc -l)" -gt 0 ; then
60 rev=`bzr info | sed '/parent branch:/!d; s/ *parent branch: /ancestor:/'`62 # This is a pipeline with at least one pipe before the current,
61 rev_option="-r $rev"63 # lint changes relative to the previous pipe
64 rev_option="-r ancestor::prev"
65 else
66 # Lint changes relative to the parent.
67 rev=`bzr info | sed '/parent branch:/!d; s/ *parent branch: /ancestor:/'`
68 rev_option="-r $rev"
69 fi
62 fi70 fi
63 elif [ $diff_status -eq 1 ] ; then71 elif [ $diff_status -eq 1 ] ; then
64 # Uncommitted changes in the tree, lint those changes.72 # Uncommitted changes in the tree, lint those changes.
@@ -147,7 +155,7 @@
147 echo " cp $4 $1"155 echo " cp $4 $1"
148 echo " Run make schema again to update the test/dev database."156 echo " Run make schema again to update the test/dev database."
149}157}
150 158
151if [ -n "$sql_diff" -o -n "$sql_dev_diff" -o -n "$karma_bombs" ]; then159if [ -n "$sql_diff" -o -n "$sql_dev_diff" -o -n "$karma_bombs" ]; then
152 echo ""160 echo ""
153 echo ""161 echo ""
@@ -155,7 +163,7 @@
155 echo ""163 echo ""
156fi164fi
157165
158# 166#
159if [ -n "$sql_diff" -o -n "$karma_bombs" ]; then167if [ -n "$sql_diff" -o -n "$karma_bombs" ]; then
160 echo "$current_sql"168 echo "$current_sql"
161fi169fi
@@ -245,7 +253,7 @@
245253
246jsfiles=`echo "$files" | grep -E 'js$'`254jsfiles=`echo "$files" | grep -E 'js$'`
247if [ ! -z "$jsfiles" ]; then255if [ ! -z "$jsfiles" ]; then
248 jslint_notices=`$utilitiesdir/../sourcecode/lazr-js/tools/jslint.py 2>&1`256 jslint_notices=`$utilitiesdir/../bin/jslint 2>&1`
249 if [ ! -z "$jslint_notices" ]; then257 if [ ! -z "$jslint_notices" ]; then
250 echo ""258 echo ""
251 echo ""259 echo ""
@@ -273,7 +281,7 @@
273fi281fi
274282
275extra_path="/usr/share/pyshared:/usr/share/pycentral/pylint/site-packages"283extra_path="/usr/share/pyshared:/usr/share/pycentral/pylint/site-packages"
276export PYTHONPATH="${os-paths}:$extra_path:$PYTHONPATH"284export PYTHONPATH=${scripts:parts-directory|shell-path}:"$extra_path":"$PYTHONPATH"
277pylint="${buildout:executable} -Wi::DeprecationWarning `which pylint`"285pylint="${buildout:executable} -Wi::DeprecationWarning `which pylint`"
278286
279# XXX sinzui 2007-10-18 bug=154140:287# XXX sinzui 2007-10-18 bug=154140:
280288
=== removed file 'buildout-templates/bin/py.in'
--- buildout-templates/bin/py.in 2009-06-12 16:36:02 +0000
+++ buildout-templates/bin/py.in 1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
1#!/bin/sh
2PYTHONPATH=${os-paths} exec ${buildout:executable} "$@"
30
=== modified file 'buildout-templates/bin/retest.in'
--- buildout-templates/bin/retest.in 2009-10-01 10:12:28 +0000
+++ buildout-templates/bin/retest.in 2010-05-05 01:58:48 +0000
@@ -31,9 +31,10 @@
31from itertools import takewhile31from itertools import takewhile
32from pprint import pprint32from pprint import pprint
3333
34${python-relative-path-setup}
3435
35# The test script for this branch.36# The test script for this branch.
36TEST = '${buildout:directory}/bin/test'37TEST = ${buildout:directory/bin/test|path-repr}
3738
38# Regular expression to match numbered stories.39# Regular expression to match numbered stories.
39STORY_RE = re.compile("(.*)/\d{2}-.*")40STORY_RE = re.compile("(.*)/\d{2}-.*")
4041
=== added file 'buildout-templates/bin/sprite-util.in'
--- buildout-templates/bin/sprite-util.in 1970-01-01 00:00:00 +0000
+++ buildout-templates/bin/sprite-util.in 2010-05-05 01:58:48 +0000
@@ -0,0 +1,47 @@
1#!${buildout:executable} -S
2
3import os
4import sys
5
6# Initialize our paths.
7${python-relative-path-setup}
8sys.path.insert(0, ${scripts:parts-directory|path-repr})
9import site
10
11from lp.services.spriteutils import SpriteUtil
12
13command_options = ('create-image', 'create-css')
14
15def usage():
16 return " Usage: %s %s" % (sys.argv[0], '|'.join(command_options))
17
18if len(sys.argv) != 2:
19 print >> sys.stderr, "Expected a single argument."
20 print >> sys.stderr, usage()
21 sys.exit(1)
22else:
23 command = sys.argv[1]
24 if command not in command_options:
25 print >> sys.stderr, "Unknown argument: %s" % command
26 print >> sys.stderr, usage()
27 sys.exit(2)
28
29icing = ${buildout:directory/lib/canonical/launchpad/icing|path-repr}
30combined_image_file = os.path.join(icing, 'icon-sprites')
31positioning_file = os.path.join(icing, 'icon-sprites.positioning')
32css_template_file = os.path.join(icing, 'style-3-0.css.in')
33css_file = os.path.join(icing, 'build/style-3-0.css')
34
35sprite_util = SpriteUtil(
36 css_template_file, 'icon-sprites',
37 url_prefix_substitutions={'/@@/': '../images/'})
38
39if command == 'create-image':
40 sprite_util.combineImages(icing)
41 sprite_util.savePNG(combined_image_file)
42 sprite_util.savePositioning(positioning_file)
43elif command == 'create-css':
44 sprite_util.loadPositioning(positioning_file)
45 # The icing/icon-sprites file is relative to the css file
46 # in the icing/build/ directory.
47 sprite_util.saveConvertedCSS(css_file, '../icon-sprites')
048
=== modified file 'buildout-templates/bin/test.in'
--- buildout-templates/bin/test.in 2009-09-17 17:42:25 +0000
+++ buildout-templates/bin/test.in 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!${buildout:executable}1#!${buildout:executable} -S
2##############################################################################2##############################################################################
3#3#
4# Copyright (c) 2004 Zope Corporation and Contributors.4# Copyright (c) 2004 Zope Corporation and Contributors.
@@ -14,9 +14,20 @@
14##############################################################################14##############################################################################
15"""Test script15"""Test script
16"""16"""
17import sys, os, time, logging, warnings, re17
1818# NOTE: This is a generated file. The original is in
19BUILD_DIR = '${buildout:directory}'19# buildout-templates/bin/test.in
20
21import logging, os, re, sys, time, warnings
22
23# Initialize our paths.
24${python-relative-path-setup}
25import sys
26sys.path.insert(0, ${scripts:parts-directory|path-repr})
27import site
28
29BUILD_DIR = ${buildout:directory|path-repr}
30CUSTOM_SITE_DIR = ${scripts:parts-directory|path-repr}
2031
21if os.getsid(0) == os.getsid(os.getppid()):32if os.getsid(0) == os.getsid(os.getppid()):
22 # We need to become the process group leader so test_on_merge.py33 # We need to become the process group leader so test_on_merge.py
@@ -30,17 +41,16 @@
3041
31# Make tests run in a timezone no launchpad developers live in.42# Make tests run in a timezone no launchpad developers live in.
32# Our tests need to run in any timezone.43# Our tests need to run in any timezone.
33# (No longer actually required, as PQM does this)44# (This is no longer actually required, as PQM does this.)
34os.environ['TZ'] = 'Asia/Calcutta'45os.environ['TZ'] = 'Asia/Calcutta'
35time.tzset()46time.tzset()
3647
37# Enable Storm's C extensions48# Storm's C extensions should already be enabled from lp_sitecustomize.py,
38os.environ['STORM_CEXTENSIONS'] = '1'49# which our custom sitecustomize.py ran.
3950assert os.environ['STORM_CEXTENSIONS'] == '1'
40sys.path[0:0] = [${string-paths}]51
4152# Make sure our site.py is the one that subprocesses use.
42# Set PYTHONPATH environment variable for spawned processes53os.environ['PYTHONPATH'] = CUSTOM_SITE_DIR
43os.environ['PYTHONPATH'] = ':'.join(sys.path)
4454
45# Set a flag if this is the main testrunner process55# Set a flag if this is the main testrunner process
46if len(sys.argv) > 1 and sys.argv[1] == '--resume-layer':56if len(sys.argv) > 1 and sys.argv[1] == '--resume-layer':
@@ -88,14 +98,28 @@
88# need to be silenced should have an accompanied Bug reference.98# need to be silenced should have an accompanied Bug reference.
89#99#
90warnings.filterwarnings(100warnings.filterwarnings(
91 'ignore', 'PyCrypto', RuntimeWarning, 'twisted[.]conch[.]ssh'101 'ignore', 'PyCrypto', RuntimeWarning, 'twisted[.]conch[.]ssh',
92 )102 )
93warnings.filterwarnings(103warnings.filterwarnings(
94 'ignore', 'twisted.python.plugin', DeprecationWarning,104 'ignore', 'twisted.python.plugin', DeprecationWarning,
95 )105 )
96warnings.filterwarnings(106warnings.filterwarnings(
97 'ignore', 'bzrlib.*was deprecated', DeprecationWarning107 'ignore', 'zope.testing.doctest', DeprecationWarning,
98)108 )
109warnings.filterwarnings(
110 'ignore', 'bzrlib.*was deprecated', DeprecationWarning,
111 )
112# XXX: 2010-04-26, Salgado, bug=570246: Silence python2.6 deprecation
113# warnings.
114# We cannot narrow this warnings filter to just twisted because
115# warnings.warn_explicit() sees this import as coming from importfascist, not
116# from twisted. It makes no sense to put module='importfascist' here though
117# because /everything/ gets imported through it. So, sad as it is, until
118# twisted doesn't produce warnings under Python 2.6, just ignore all these
119# deprecations.
120warnings.filterwarnings(
121 'ignore', '.*(md5|sha|sets)', DeprecationWarning,
122 )
99# The next one is caused by a lamosity in python-openid. The following change123# The next one is caused by a lamosity in python-openid. The following change
100# to openid/server/server.py would make the warning filter unnecessary:124# to openid/server/server.py would make the warning filter unnecessary:
101# 978c974,974125# 978c974,974
@@ -137,9 +161,9 @@
137defaults = {161defaults = {
138 # Find tests in the tests and ftests directories162 # Find tests in the tests and ftests directories
139 'tests_pattern': '^f?tests$',163 'tests_pattern': '^f?tests$',
140 'test_path': ['${buildout:directory}/lib'],164 'test_path': [${buildout:directory/lib|path-repr}],
141 'package': ['canonical', 'lp', 'devscripts'],165 'package': ['canonical', 'lp', 'devscripts'],
142 'layer': ['!(MailmanLayer|WindmillLayer)'],166 'layer': ['!(MailmanLayer)'],
143 }167 }
144168
145# Monkey-patch os.listdir to randomise the results169# Monkey-patch os.listdir to randomise the results
@@ -161,13 +185,7 @@
161os.listdir = listdir185os.listdir = listdir
162186
163187
164from canonical.testing.customresult import (188from canonical.testing.customresult import filter_tests, patch_find_tests
165 filter_tests,
166 list_tests,
167 patch_find_tests,
168 patch_zope_testresult,
169 )
170from subunit import TestProtocolClient
171189
172190
173if __name__ == '__main__':191if __name__ == '__main__':
@@ -191,16 +209,6 @@
191 options.parser.add_option(209 options.parser.add_option(
192 '--load-list', type=str, action='callback', callback=load_list)210 '--load-list', type=str, action='callback', callback=load_list)
193211
194 def list_test_option(option, opt, value, parser):
195 patch_find_tests(list_tests)
196 options.parser.add_option(
197 '--list', action='callback', callback=list_test_option)
198
199 def use_subunit(option, opt, value, parser):
200 patch_zope_testresult(TestProtocolClient(sys.stdout))
201 options.parser.add_option(
202 '--subunit', action='callback', callback=use_subunit)
203
204 # tests_pattern is a regexp, so the parsed value is hard to compare212 # tests_pattern is a regexp, so the parsed value is hard to compare
205 # with the default value in the loop below.213 # with the default value in the loop below.
206 options.parser.defaults['tests_pattern'] = defaults['tests_pattern']214 options.parser.defaults['tests_pattern'] = defaults['tests_pattern']
@@ -229,7 +237,7 @@
229 # e.g. run the test that you are currently editing.237 # e.g. run the test that you are currently editing.
230 try:238 try:
231 there = os.getcwd()239 there = os.getcwd()
232 os.chdir('${buildout:directory}')240 os.chdir(BUILD_DIR)
233 result = testrunner.run([])241 result = testrunner.run([])
234 finally:242 finally:
235 os.chdir(there)243 os.chdir(there)
236244
=== modified file 'buildout-templates/bin/update-download-cache.in'
--- buildout-templates/bin/update-download-cache.in 2009-05-13 00:29:48 +0000
+++ buildout-templates/bin/update-download-cache.in 2010-05-05 01:58:48 +0000
@@ -1,2 +1,4 @@
1bzr up ${buildout:directory}/buildout/download-cache1${shell-relative-path-setup}
2
3bzr up ${buildout:directory/buildout/download-cache|shell-path}
24
35
=== modified file 'buildout.cfg'
--- buildout.cfg 2009-09-21 10:45:15 +0000
+++ buildout.cfg 2010-05-05 01:58:48 +0000
@@ -11,6 +11,7 @@
11unzip = true11unzip = true
12eggs-directory = eggs12eggs-directory = eggs
13download-cache = download-cache13download-cache = download-cache
14relative-paths = true
1415
15# Disable this option temporarily if you want buildout to find software16# Disable this option temporarily if you want buildout to find software
16# dependencies *other* than those in our download-cache. Once you have the17# dependencies *other* than those in our download-cache. Once you have the
@@ -25,9 +26,6 @@
2526
26allow-picked-versions = false27allow-picked-versions = false
2728
28allowed-eggs-from-site-packages =
29include-site-packages-for-buildout = false
30
31prefer-final = true29prefer-final = true
3230
33develop = .31develop = .
@@ -37,42 +35,41 @@
3735
38[filetemplates]36[filetemplates]
39recipe = z3c.recipe.filetemplate37recipe = z3c.recipe.filetemplate
40eggs = lp
41 windmill
42# XXX gary 2009-5-12 bug 375751:
43# Make mailman built and installed in a more normal way.
44extra-paths = ${buildout:directory}/lib/mailman
45source-directory = buildout-templates38source-directory = buildout-templates
4639
47[scripts]40[scripts]
48recipe = zc.recipe.egg41recipe = z3c.recipe.scripts
49eggs = lp42eggs = lp
50 windmill43 windmill
51 funkload44 funkload
45 zc.zservertracelog
52# XXX gary 2009-5-12 bug 375751:46# XXX gary 2009-5-12 bug 375751:
53# Make mailman built and installed in a more normal way.47# Make mailman built and installed in a more normal way.
54extra-paths = ${buildout:directory}/lib/mailman48extra-paths = ${buildout:directory}/lib/mailman
55# note that any indentation is lost in initialization blocks49include-site-packages = true
56initialization = import os50allowed-eggs-from-site-packages =
57 os.environ['STORM_CEXTENSIONS'] = '1'51interpreter = py
58 os.environ.setdefault('LPCONFIG', '${configuration:instance_name}')52# Note that any indentation is lost in initialization blocks.
59 # XXX 2009-08-21 gary bug 41707753initialization =
60 # This can hopefully be removed when Twisted is used as an egg.54 import os
61 import warnings55 os.environ.setdefault('LPCONFIG', '${configuration:instance_name}')
62 warnings.filterwarnings(56 import lp_sitecustomize # Initializes LP environment.
63 'ignore',
64 'Module .+ was already imported from .+, but .+ is being added.*',
65 UserWarning)
66entry-points = stxdocs=zope.configuration.stxdocs:main57entry-points = stxdocs=zope.configuration.stxdocs:main
67 googletestservice=canonical.launchpad.testing.googletestservice:main58 googletestservice=canonical.launchpad.testing.googletestservice:main
68 windmill=windmill.bin.windmill_bin:main59 windmill=windmill.bin.windmill_bin:main
69 lp-windmill=lp.scripts.utilities.lpwindmill:main60 lp-windmill=lp.scripts.utilities.lpwindmill:main
61 jsbuild=lazr.js.build:main
62 jslint=lazr.js.jslint:main
63 tracereport=zc.zservertracelog.tracereport:main
64 jssize=lp.scripts.utilities.jssize:main
7065
71[iharness]66[iharness]
72recipe = zc.recipe.egg67recipe = z3c.recipe.scripts
73eggs = ${scripts:eggs}68eggs = ${scripts:eggs}
74 ipython69 ipython
75extra-paths = ${scripts:extra-paths}70extra-paths = ${scripts:extra-paths}
71include-site-packages = true
72allowed-eggs-from-site-packages =
76initialization = ${scripts:initialization}73initialization = ${scripts:initialization}
77entry-points = iharness=canonical.database.harness:ipython74entry-points = iharness=canonical.database.harness:ipython
78scripts = iharness ipython=ipy75scripts = iharness ipython=ipy
7976
=== added symlink 'bzrplugins/builder'
=== target is u'../sourcecode/bzr-builder/'
=== modified file 'bzrplugins/lpserve.py'
--- bzrplugins/lpserve.py 2009-07-17 00:26:05 +0000
+++ bzrplugins/lpserve.py 2010-05-05 01:58:48 +0000
@@ -11,6 +11,7 @@
11__all__ = ['cmd_launchpad_server']11__all__ = ['cmd_launchpad_server']
1212
1313
14import resource
14import sys15import sys
1516
16from bzrlib.commands import Command, register_command17from bzrlib.commands import Command, register_command
@@ -44,9 +45,9 @@
44 Option('mirror-directory',45 Option('mirror-directory',
45 help='serve branches from this directory. Defaults to '46 help='serve branches from this directory. Defaults to '
46 'config.codehosting.mirrored_branches_root.'),47 'config.codehosting.mirrored_branches_root.'),
47 Option('branchfs-endpoint',48 Option('codehosting-endpoint',
48 help='the url of the internal XML-RPC server. Defaults to '49 help='the url of the internal XML-RPC server. Defaults to '
49 'config.codehosting.branchfs_endpoint.',50 'config.codehosting.codehosting_endpoint.',
50 type=unicode),51 type=unicode),
51 ]52 ]
5253
@@ -84,15 +85,18 @@
84 finally:85 finally:
85 ui.ui_factory = old_factory86 ui.ui_factory = old_factory
8687
87 def run(self, user_id, port=None, upload_directory=None,88 def run(self, user_id, port=None, branch_directory=None,
88 mirror_directory=None, branchfs_endpoint_url=None, inet=False):89 codehosting_endpoint_url=None, inet=False):
89 from lp.codehosting.bzrutils import install_oops_handler90 from lp.codehosting.bzrutils import install_oops_handler
90 from lp.codehosting.vfs import get_lp_server91 from lp.codehosting.vfs import get_lp_server, hooks
91 install_oops_handler(user_id)92 install_oops_handler(user_id)
93 four_gig = int(4e9)
94 resource.setrlimit(resource.RLIMIT_AS, (four_gig, four_gig))
95 seen_new_branch = hooks.SetProcTitleHook()
92 lp_server = get_lp_server(96 lp_server = get_lp_server(
93 int(user_id), branchfs_endpoint_url,97 int(user_id), codehosting_endpoint_url, branch_directory,
94 upload_directory, mirror_directory)98 seen_new_branch.seen)
95 lp_server.setUp()99 lp_server.start_server()
96100
97 old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS101 old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
98 try:102 try:
@@ -102,7 +106,7 @@
102 self.run_server(smart_server)106 self.run_server(smart_server)
103 finally:107 finally:
104 lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout108 lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
105 lp_server.tearDown()109 lp_server.stop_server()
106110
107111
108register_command(cmd_launchpad_server)112register_command(cmd_launchpad_server)
109113
=== added file 'configs/development/build-from-branch.zcml'
--- configs/development/build-from-branch.zcml 1970-01-01 00:00:00 +0000
+++ configs/development/build-from-branch.zcml 2010-05-05 01:58:48 +0000
@@ -0,0 +1,119 @@
1<!-- Copyright 2010 Canonical Ltd. This software is licensed under the
2 GNU Affero General Public License version 3 (see the file LICENSE).
3-->
4
5<configure
6 xmlns="http://namespaces.zope.org/zope"
7 xmlns:browser="http://namespaces.zope.org/browser"
8 xmlns:i18n="http://namespaces.zope.org/i18n"
9 xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
10 i18n_domain="launchpad">
11 <facet facet="branches">
12
13 <browser:defaultView
14 for="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipe"
15 name="+index"
16 layer="canonical.launchpad.layers.CodeLayer"/>
17 <browser:page
18 for="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipe"
19 class="lp.code.browser.sourcepackagerecipe.SourcePackageRecipeView"
20 name="+index"
21 template="../../lib/lp/code/templates/sourcepackagerecipe-index.pt"
22 permission="launchpad.View"/>
23 <browser:page
24 for="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipe"
25 class="lp.code.browser.sourcepackagerecipe.SourcePackageRecipeRequestBuildsView"
26 name="+request-builds"
27 template="../../lib/lp/code/templates/sourcepackagerecipe-request-builds.pt"
28 permission="launchpad.View"/>
29 </facet>
30 <facet facet="branches">
31 <browser:defaultView
32 for="lp.code.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuild"
33 name="+index"
34 layer="canonical.launchpad.layers.CodeLayer"/>
35 <browser:page
36 for="lp.code.interfaces.sourcepackagerecipebuild.ISourcePackageRecipeBuild"
37 class="lp.code.browser.sourcepackagerecipe.SourcePackageRecipeBuildView"
38 name="+index"
39 template="../../lib/lp/code/templates/sourcepackagerecipe-index.pt"
40 permission="launchpad.View"/>
41 <browser:menus
42 classes="
43 SourcePackageRecipeNavigationMenu
44 SourcePackageRecipeContextMenu"
45 module="lp.code.browser.sourcepackagerecipe"/>
46
47 <browser:page
48 for="lp.code.interfaces.branch.IBranch"
49 class="lp.code.browser.sourcepackagerecipe.SourcePackageRecipeAddView"
50 permission="zope.Public"
51 facet="branches"
52 name="+new-recipe"
53 template="../../lib/lp/app/templates/generic-edit.pt"/>
54 <browser:page
55 for="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipe"
56 class="lp.code.browser.sourcepackagerecipe.SourcePackageRecipeEditView"
57 permission="zope.Public"
58 facet="branches"
59 name="+edit"
60 template="../../lib/lp/app/templates/generic-edit.pt"/>
61 <browser:page
62 for="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipe"
63 class="lp.code.browser.sourcepackagerecipe.SourcePackageRecipeDeleteView"
64 permission="zope.Public"
65 facet="branches"
66 name="+delete"
67 template="../../lib/lp/app/templates/generic-edit.pt"/>
68
69
70 <browser:page
71 for="lp.code.interfaces.branch.IBranch"
72 class="lp.code.browser.sourcepackagerecipelisting.BranchRecipeListingView"
73 permission="zope.Public"
74 facet="branches"
75 name="+recipes"
76 template="../../lib/lp/code/templates/sourcepackagerecipe-listing.pt"/>
77 <browser:page
78 for="lp.registry.interfaces.product.IProduct"
79 class="lp.code.browser.sourcepackagerecipelisting.ProductRecipeListingView"
80 permission="zope.Public"
81 facet="branches"
82 name="+recipes"
83 template="../../lib/lp/code/templates/sourcepackagerecipe-listing.pt"/>
84 <browser:page
85 for="lp.registry.interfaces.person.IPerson"
86 class="lp.code.browser.sourcepackagerecipelisting.PersonRecipeListingView"
87 permission="zope.Public"
88 facet="branches"
89 name="+recipes"
90 template="../../lib/lp/code/templates/sourcepackagerecipe-listing.pt"/>
91
92 <browser:page
93 for="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipe"
94 name="+hierarchy"
95 class="lp.code.browser.sourcepackagerecipe.SourcePackageRecipeHierarchy"
96 template="../../lib/lp/app/templates/launchpad-hierarchy.pt"
97 permission="zope.Public"/>
98
99 <adapter
100 provides="canonical.launchpad.webapp.interfaces.IBreadcrumb"
101 for="lp.code.interfaces.sourcepackagerecipe.ISourcePackageRecipe"
102 factory="canonical.launchpad.webapp.breadcrumb.NameBreadcrumb"
103 permission="zope.Public"/>
104 </facet>
105 <securedutility
106 name="BuildableDistroSeries"
107 component="lp.code.browser.sourcepackagerecipe.buildable_distroseries_vocabulary"
108 provides="zope.schema.interfaces.IVocabularyFactory"
109 >
110 <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
111 </securedutility>
112 <securedutility
113 name="TargetPPAs"
114 component="lp.code.browser.sourcepackagerecipe.target_ppas_vocabulary"
115 provides="zope.schema.interfaces.IVocabularyFactory"
116 >
117 <allow interface="zope.schema.interfaces.IVocabularyFactory"/>
118 </securedutility>
119</configure>
0120
=== modified file 'configs/development/launchpad-lazr.conf'
--- configs/development/launchpad-lazr.conf 2009-09-29 15:15:21 +0000
+++ configs/development/launchpad-lazr.conf 2010-05-05 01:58:48 +0000
@@ -7,6 +7,7 @@
77
8[archivepublisher]8[archivepublisher]
9root: /var/tmp/archive9root: /var/tmp/archive
10base_url: http://archive.launchpad.dev/
1011
11[branchscanner]12[branchscanner]
12oops_prefix: BS13oops_prefix: BS
@@ -14,7 +15,8 @@
1415
15[builddmaster]16[builddmaster]
16root: /var/tmp/builddmaster/17root: /var/tmp/builddmaster/
17uploader: /bin/echo Uploader invocation of build BUILDID in:18uploader: scripts/process-upload.py -Mvv
19bzr_builder_sources_list: None
1820
19[buildsequencer]21[buildsequencer]
20mailproblemsto: root22mailproblemsto: root
@@ -44,15 +46,14 @@
4446
45[codebrowse]47[codebrowse]
46cachepath: /var/tmp/codebrowse.launchpad.dev/cache48cachepath: /var/tmp/codebrowse.launchpad.dev/cache
47log_folder:49log_folder: /var/tmp/codebrowse.launchpad.dev/logs
48launchpad_root: https://code.launchpad.dev/50launchpad_root: https://code.launchpad.dev/
49secret_path: configs/development/codebrowse-secret51secret_path: configs/development/codebrowse-secret
5052
51[codehosting]53[codehosting]
52launch: True54launch: True
53authentication_endpoint: http://xmlrpc-private.launchpad.dev:8087/authserver55authentication_endpoint: http://xmlrpc-private.launchpad.dev:8087/authserver
54branchfs_endpoint: http://xmlrpc-private.launchpad.dev:8087/branchfilesystem56codehosting_endpoint: http://xmlrpc-private.launchpad.dev:8087/codehosting
55branch_puller_endpoint: http://xmlrpc-private.launchpad.dev:8087/branch_puller
56supermirror_root: http://bazaar.launchpad.dev/57supermirror_root: http://bazaar.launchpad.dev/
57hosted_branches_root: /var/tmp/bazaar.launchpad.dev/push-branches/58hosted_branches_root: /var/tmp/bazaar.launchpad.dev/push-branches/
58codebrowse_root: http://bazaar.launchpad.dev/59codebrowse_root: http://bazaar.launchpad.dev/
@@ -90,10 +91,17 @@
9091
9192
92[database]93[database]
93main_master: dbname=launchpad_dev94rw_main_master: dbname=launchpad_dev
94main_slave: dbname=launchpad_dev95rw_main_slave: dbname=launchpad_dev
95auth_master: dbname=launchpad_dev96# Use our _template databases here just so that we have different values from
96auth_slave: dbname=launchpad_dev97# the rw_* configs.
98ro_main_master: dbname=launchpad_dev_template
99ro_main_slave: dbname=launchpad_dev_template
100
101# XXX stub 20100407 bug=557271: These next two are ignored, and should
102# be removed after the May 2010 rollout.
103auth_master: bug 557271
104auth_slave: bug 557271
97105
98[distributionmirrorprober]106[distributionmirrorprober]
99use_proxy: False107use_proxy: False
@@ -119,18 +127,21 @@
119public_host: keyserver.launchpad.dev127public_host: keyserver.launchpad.dev
120128
121[launchpad]129[launchpad]
130enable_test_openid_provider: True
131openid_provider_vhost: testopenid
122code_domain: code.launchpad.dev132code_domain: code.launchpad.dev
123default_batch_size: 5133default_batch_size: 5
124max_attachment_size: 2097152134max_attachment_size: 2097152
125branchlisting_batch_size: 6135branchlisting_batch_size: 6
136mugshot_batch_size: 8
137announcement_batch_size: 4
138download_batch_size: 4
126openid_preauthorization_acl:139openid_preauthorization_acl:
127 localhost http://launchpad.dev/140 localhost http://launchpad.dev/
128max_bug_feed_cache_minutes: 30141max_bug_feed_cache_minutes: 30
129bzr_imports_root_url: file:///tmp/bazaar-branches142bzr_imports_root_url: file:///tmp/bazaar-branches
130geoip_database: /usr/share/GeoIP/GeoLiteCity.dat143geoip_database: /usr/share/GeoIP/GeoLiteCity.dat
131geonames_identity: lpdev144geonames_identity: lpdev
132# Set to True to test read-only mode.
133read_only: False
134storm_cache: generational145storm_cache: generational
135storm_cache_size: 100146storm_cache_size: 100
136147
@@ -180,6 +191,20 @@
180soft_max_size: 40000191soft_max_size: 40000
181hard_max_size: 1000000192hard_max_size: 1000000
182193
194[memcache]
195servers: (127.0.0.1:11217,1)
196
197[memcached]
198launch: True
199verbose: False
200address: 127.0.0.1
201port: 11217
202memory_size: 1
203
204[merge_proposal_jobs]
205error_dir: /var/tmp/codehosting.test
206oops_prefix: DMPJ
207
183[personalpackagearchive]208[personalpackagearchive]
184root: /var/tmp/ppa/209root: /var/tmp/ppa/
185private_root: /var/tmp/ppa210private_root: /var/tmp/ppa
@@ -192,6 +217,7 @@
192217
193[rosetta]218[rosetta]
194global_suggestions_enabled: True219global_suggestions_enabled: True
220generate_templates: True
195221
196[rosettabranches]222[rosettabranches]
197error_dir: /var/tmp/rosettabranches.test223error_dir: /var/tmp/rosettabranches.test
@@ -201,6 +227,9 @@
201error_dir: /var/tmp/poimport227error_dir: /var/tmp/poimport
202oops_prefix: POI228oops_prefix: POI
203229
230[process_apport_blobs]
231error_dir: /var/tmp/lperr
232
204[supermirror_puller]233[supermirror_puller]
205error_dir: /var/tmp/codehosting.test234error_dir: /var/tmp/codehosting.test
206oops_prefix: SMP235oops_prefix: SMP
@@ -217,6 +246,10 @@
217error_dir: /var/tmp/codehosting.test246error_dir: /var/tmp/codehosting.test
218oops_prefix: USMP247oops_prefix: USMP
219248
249[upgrade_branches]
250oops_prefix: UBJD
251error_dir: /var/tmp/codehosting.test
252
220[uploader]253[uploader]
221default_recipient_name: Local Root254default_recipient_name: Local Root
222default_sender_address: root@localhost255default_sender_address: root@localhost
@@ -233,7 +266,7 @@
233266
234[vhost.api]267[vhost.api]
235hostname: api.launchpad.dev268hostname: api.launchpad.dev
236rooturl: https://api.launchpad.dev/beta/269rooturl: https://api.launchpad.dev/
237270
238[vhost.blueprints]271[vhost.blueprints]
239hostname: blueprints.launchpad.dev272hostname: blueprints.launchpad.dev
@@ -253,6 +286,12 @@
253[vhost.openid]286[vhost.openid]
254hostname: openid.launchpad.dev287hostname: openid.launchpad.dev
255288
289[vhost.testopenid]
290hostname: testopenid.dev
291
292[vhost.ubuntu_openid]
293hostname: ubuntu-openid.launchpad.dev
294
256[vhost.shipitubuntu]295[vhost.shipitubuntu]
257hostname: shipit.ubuntu.dev296hostname: shipit.ubuntu.dev
258297
@@ -278,3 +317,6 @@
278# so disable that here. note that the testrunner config inherits317# so disable that here. note that the testrunner config inherits
279# this setting from us.318# this setting from us.
280send_email: false319send_email: false
320
321[build_from_branch]
322enabled = True
281323
=== modified file 'configs/development/local-launchpad-apache'
--- configs/development/local-launchpad-apache 2009-07-24 01:57:06 +0000
+++ configs/development/local-launchpad-apache 2010-05-05 01:58:48 +0000
@@ -112,6 +112,19 @@
112 </Directory>112 </Directory>
113</VirtualHost>113</VirtualHost>
114114
115<VirtualHost 127.0.0.88:80>
116 ServerName archive.launchpad.dev
117 LogLevel debug
118
119 DocumentRoot /var/tmp/archive
120 <Directory /var/tmp/archive/>
121 Order Deny,Allow
122 Deny from all
123 Allow from 127.0.0.0/255.0.0.0
124 Options Indexes
125 </Directory>
126</VirtualHost>
127
115<VirtualHost 127.0.0.88:443>128<VirtualHost 127.0.0.88:443>
116 ServerName launchpad.dev129 ServerName launchpad.dev
117 ServerAlias *.launchpad.dev130 ServerAlias *.launchpad.dev
118131
=== modified file 'configs/replicated-development/launchpad-lazr.conf'
--- configs/replicated-development/launchpad-lazr.conf 2008-10-14 11:10:35 +0000
+++ configs/replicated-development/launchpad-lazr.conf 2010-05-05 01:58:48 +0000
@@ -6,8 +6,7 @@
6extends: ../development/launchpad-lazr.conf6extends: ../development/launchpad-lazr.conf
77
8[database]8[database]
9main_master: dbname=launchpad_dev9rw_main_master: dbname=launchpad_dev
10main_slave: dbname=launchpad_dev_slave10rw_main_slave: dbname=launchpad_dev_slave
11auth_master: dbname=launchpad_dev11ro_main_master: dbname=launchpad_dev
12auth_slave: dbname=launchpad_dev_slave12ro_main_slave: dbname=launchpad_dev_slave
13
1413
=== modified file 'configs/test-playground/launchpad-lazr.conf'
--- configs/test-playground/launchpad-lazr.conf 2008-11-10 16:12:10 +0000
+++ configs/test-playground/launchpad-lazr.conf 2010-05-05 01:58:48 +0000
@@ -6,7 +6,7 @@
6extends: ../development/launchpad-lazr.conf6extends: ../development/launchpad-lazr.conf
77
8[database]8[database]
9main_master: dbname=launchpad_ftest_playground9rw_main_master: dbname=launchpad_ftest_playground
10main_slave: dbname=launchpad_ftest_playground10rw_main_slave: dbname=launchpad_ftest_playground
11auth_master: dbname=launchpad_ftest_playground11ro_main_master: dbname=launchpad_ftest_playground
12auth_slave: dbname=launchpad_ftest_playground12ro_main_slave: dbname=launchpad_ftest_playground
1313
=== modified file 'configs/testrunner-appserver/launchpad-lazr.conf'
--- configs/testrunner-appserver/launchpad-lazr.conf 2009-04-29 19:10:17 +0000
+++ configs/testrunner-appserver/launchpad-lazr.conf 2010-05-05 01:58:48 +0000
@@ -23,7 +23,7 @@
23rooturl: http://launchpad.dev:8085/23rooturl: http://launchpad.dev:8085/
2424
25[vhost.api]25[vhost.api]
26rooturl: http://api.launchpad.dev:8085/beta/26rooturl: http://api.launchpad.dev:8085/
2727
28[vhost.blueprints]28[vhost.blueprints]
29rooturl: http://blueprints.launchpad.dev:8085/29rooturl: http://blueprints.launchpad.dev:8085/
@@ -43,6 +43,9 @@
43[vhost.openid]43[vhost.openid]
44rooturl: http://openid.launchpad.dev:8085/44rooturl: http://openid.launchpad.dev:8085/
4545
46[vhost.testopenid]
47rooturl: http://testopenid.dev:8085/
48
46[vhost.shipitubuntu]49[vhost.shipitubuntu]
47rooturl: http://shipit.ubuntu.dev:8085/50rooturl: http://shipit.ubuntu.dev:8085/
4851
4952
=== added file 'configs/testrunner-appserver/yui-unittest.zcml'
--- configs/testrunner-appserver/yui-unittest.zcml 1970-01-01 00:00:00 +0000
+++ configs/testrunner-appserver/yui-unittest.zcml 2010-05-05 01:58:48 +0000
@@ -0,0 +1,16 @@
1<!-- Copyright 2010 Canonical Ltd. This software is licensed under the
2 GNU Affero General Public License version 3 (see the file LICENSE).
3-->
4
5<configure
6 xmlns="http://namespaces.zope.org/zope"
7 xmlns:browser="http://namespaces.zope.org/browser">
8
9 <browser:page
10 name="+yui-unittest"
11 for="canonical.launchpad.webapp.interfaces.ILaunchpadRoot"
12 class="lp.testing.views.YUITestFileView"
13 attribute="__call__"
14 permission="zope.Public"/>
15
16</configure>
017
=== added symlink 'configs/testrunner/build-from-branch.zcml'
=== target is u'../development/build-from-branch.zcml'
=== modified file 'configs/testrunner/launchpad-lazr.conf'
--- configs/testrunner/launchpad-lazr.conf 2009-09-29 15:15:21 +0000
+++ configs/testrunner/launchpad-lazr.conf 2010-05-05 01:58:48 +0000
@@ -8,13 +8,16 @@
8[canonical]8[canonical]
9chunkydiff: False9chunkydiff: False
1010
11[archivepublisher]
12base_url: http://ftpmaster.internal/
13
11[branchscanner]14[branchscanner]
12oops_prefix: TSMS15oops_prefix: TSMS
13error_dir: /var/tmp/lperr.test16error_dir: /var/tmp/lperr.test
1417
15[builddmaster]18[builddmaster]
16socket_timeout: 1019socket_timeout: 10
17uploader: scripts/process-upload.py -Mvv --context buildd20uploader: scripts/process-upload.py -Mvv
1821
19[buildsequencer]22[buildsequencer]
20mailproblemsto: -23mailproblemsto: -
@@ -31,21 +34,23 @@
31bzr_lp_prefix: lp://dev/34bzr_lp_prefix: lp://dev/
32hosted_branches_root: /tmp/sftp-test/branches35hosted_branches_root: /tmp/sftp-test/branches
33host_key_pair_path: lib/lp/codehosting/sshserver/tests/keys36host_key_pair_path: lib/lp/codehosting/sshserver/tests/keys
34port: tcp:22222:interface=127.0.0.137port: tcp:22222:interface=bazaar.launchpad.dev
35error_dir: /var/tmp/codehosting.test38error_dir: /var/tmp/codehosting.test
36oops_prefix: SMPSSH39oops_prefix: SMPSSH
37access_log: /tmp/test-codehosting-access.log40access_log: /tmp/test-codehosting-access.log
38internal_branch_by_id_root: file:///var/tmp/bzrsync/41internal_branch_by_id_root: file:///var/tmp/bazaar.launchpad.dev/mirrors
3942
40[create_merge_proposals]43[create_merge_proposals]
41oops_prefix: TMPCJ44oops_prefix: TMPCJ
42error_dir: /var/tmp/codehosting.test45error_dir: /var/tmp/codehosting.test
4346
44[database]47[database]
45main_master: dbname=launchpad_ftest48rw_main_master: dbname=launchpad_ftest
46main_slave: dbname=launchpad_ftest49rw_main_slave: dbname=launchpad_ftest
47auth_master: dbname=launchpad_ftest50# Use our _template databases here just so that we have different values from
48auth_slave: dbname=launchpad_ftest51# the rw_* configs.
52ro_main_master: dbname=launchpad_ftest_template
53ro_main_slave: dbname=launchpad_ftest_template
49randomise_select_results: true54randomise_select_results: true
5055
51[error_reports]56[error_reports]
@@ -122,7 +127,6 @@
122127
123[launchpad]128[launchpad]
124max_attachment_size: 1024129max_attachment_size: 1024
125bzr_imports_root_url: http://localhost:10899
126geoip_database: /usr/share/GeoIP/GeoLiteCity.dat130geoip_database: /usr/share/GeoIP/GeoLiteCity.dat
127131
128[launchpad_session]132[launchpad_session]
@@ -154,22 +158,45 @@
154bugnotification_interval: 5158bugnotification_interval: 5
155debbugs_db_location: lib/canonical/launchpad/components/ftests/debbugs_db159debbugs_db_location: lib/canonical/launchpad/components/ftests/debbugs_db
156160
157161[memcache]
158[mpcreationjobs]162servers: (127.0.0.1:11242,1)
159oops_prefix: TMPCJ163
164[memcached]
165# The test suite takes care of launching this as necessary.
166launch: false
167verbose: false
168memory_size: 1
169address: 127.0.0.1
170# We want a different port to ensure we don't pick up stray memcached
171# processes spawned through some other mechanism.
172port: 11242
173
174[merge_proposal_jobs]
175oops_prefix: TMPJ
160error_dir: /var/tmp/codehosting.test176error_dir: /var/tmp/codehosting.test
161177
162[update_preview_diffs]178[upgrade_branches]
163oops_prefix: TUPD179oops_prefix: TUB
164error_dir: /var/tmp/codehosting.test180error_dir: /var/tmp/codehosting.test
165181
166[personalpackagearchive]182[personalpackagearchive]
167root: /var/tmp/ppa.test/183root: /var/tmp/ppa.test/
168184
185[ppa_apache_log_parser]
186logs_root: lib/lp/soyuz/scripts/tests/ppa-apache-log-files
187
169[poimport]188[poimport]
170error_dir: /var/tmp/poimport.test189error_dir: /var/tmp/poimport.test
171oops_prefix: TPOI190oops_prefix: TPOI
172191
192[process_apport_blobs]
193dbuser: process-apport-blobs
194oops_prefix: TAPPORTBLOB
195error_dir: /var/tmp/lperr.test
196
197[rosetta]
198generate_templates: True
199
173[rosettabranches]200[rosettabranches]
174oops_prefix: TRSBR201oops_prefix: TRSBR
175error_dir: /var/tmp/rosettabranches.test202error_dir: /var/tmp/rosettabranches.test
@@ -198,10 +225,13 @@
198rooturl: http://launchpad.dev/225rooturl: http://launchpad.dev/
199226
200[vhost.api]227[vhost.api]
201rooturl: http://api.launchpad.dev/beta/228rooturl: http://api.launchpad.dev/
202229
203[vhosts]230[vhosts]
204use_https: False231use_https: False
205232
206[zeca]233[zeca]
207root: /var/tmp/zeca.test234root: /var/tmp/zeca.test
235
236[build_from_branch]
237enabled = True
208238
=== modified file 'cronscripts/allocate-revision-karma.py'
--- cronscripts/allocate-revision-karma.py 2009-06-24 20:52:01 +0000
+++ cronscripts/allocate-revision-karma.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== removed file 'cronscripts/branch-scanner.py'
--- cronscripts/branch-scanner.py 2009-06-24 20:52:01 +0000
+++ cronscripts/branch-scanner.py 1970-01-01 00:00:00 +0000
@@ -1,36 +0,0 @@
1#!/usr/bin/python2.4
2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).
5
6# pylint: disable-msg=C0103,W0403
7# Author: Gustavo Niemeyer <gustavo@niemeyer.net>
8# David Allouche <david@allouche.net>
9
10"""Update bzr branches information in the database"""
11
12
13import _pythonpath
14import logging
15
16from lp.codehosting.scanner.branch_scanner import BranchScanner
17from canonical.config import config
18from lp.services.scripts.base import LaunchpadCronScript
19from canonical.launchpad.webapp.errorlog import globalErrorUtility
20
21
22class UpdateBranches(LaunchpadCronScript):
23 def main(self):
24 # We don't want debug messages from bzr at that point.
25 bzr_logger = logging.getLogger("bzr")
26 bzr_logger.setLevel(logging.INFO)
27 globalErrorUtility.configure('branchscanner')
28
29 BranchScanner(self.txn, self.logger).scanAllBranches()
30
31
32if __name__ == '__main__':
33 script = UpdateBranches(
34 "updatebranches", dbuser=config.branchscanner.dbuser)
35 script.lock_and_run()
36
370
=== modified file 'cronscripts/buildd-queue-builder.py'
--- cronscripts/buildd-queue-builder.py 2009-06-24 20:52:01 +0000
+++ cronscripts/buildd-queue-builder.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/buildd-retry-depwait.py'
--- cronscripts/buildd-retry-depwait.py 2009-06-24 20:52:01 +0000
+++ cronscripts/buildd-retry-depwait.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/buildd-slave-scanner.py'
--- cronscripts/buildd-slave-scanner.py 2009-06-24 20:52:01 +0000
+++ cronscripts/buildd-slave-scanner.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== added file 'cronscripts/calculate-bug-heat.py'
--- cronscripts/calculate-bug-heat.py 1970-01-01 00:00:00 +0000
+++ cronscripts/calculate-bug-heat.py 2010-05-05 01:58:48 +0000
@@ -0,0 +1,33 @@
1#!/usr/bin/python2.5 -S
2#
3# Copyright 2010 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).
5
6# pylint: disable-msg=W0403
7
8"""Calculate bug heat."""
9
10__metaclass__ = type
11
12import _pythonpath
13
14from canonical.launchpad.webapp import errorlog
15
16from lp.services.job.runner import JobCronScript
17from lp.bugs.interfaces.bugjob import ICalculateBugHeatJobSource
18
19
20class RunCalculateBugHeat(JobCronScript):
21 """Run BranchScanJob jobs."""
22
23 config_name = 'calculate_bug_heat'
24 source_interface = ICalculateBugHeatJobSource
25
26 def main(self):
27 errorlog.globalErrorUtility.configure(self.config_name)
28 return super(RunCalculateBugHeat, self).main()
29
30
31if __name__ == '__main__':
32 script = RunCalculateBugHeat()
33 script.lock_and_run()
034
=== modified file 'cronscripts/check-teamparticipation.py'
--- cronscripts/check-teamparticipation.py 2009-07-29 01:14:50 +0000
+++ cronscripts/check-teamparticipation.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -18,11 +18,11 @@
18situation, but that's not a simple thing and this should do for now.18situation, but that's not a simple thing and this should do for now.
19"""19"""
2020
21import _pythonpath
22
21import optparse23import optparse
22import sys24import sys
2325
24import _pythonpath
25
26from canonical.database.sqlbase import cursor26from canonical.database.sqlbase import cursor
27from canonical.launchpad.scripts import (27from canonical.launchpad.scripts import (
28 execute_zcml_for_scripts, logger_options, logger)28 execute_zcml_for_scripts, logger_options, logger)
2929
=== modified file 'cronscripts/checkwatches.py'
--- cronscripts/checkwatches.py 2009-10-05 13:08:10 +0000
+++ cronscripts/checkwatches.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/code-import-dispatcher.py'
--- cronscripts/code-import-dispatcher.py 2009-06-24 20:52:01 +0000
+++ cronscripts/code-import-dispatcher.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -18,6 +18,12 @@
1818
19class CodeImportDispatcherScript(LaunchpadScript):19class CodeImportDispatcherScript(LaunchpadScript):
2020
21 def add_my_options(self):
22 self.parser.add_option(
23 "--max-jobs", dest="max_jobs", type=int,
24 default=config.codeimportdispatcher.max_jobs_per_machine,
25 help="The maximum number of jobs to run on this machine.")
26
21 def run(self, use_web_security=False, implicit_begin=True,27 def run(self, use_web_security=False, implicit_begin=True,
22 isolation=None):28 isolation=None):
23 """See `LaunchpadScript.run`.29 """See `LaunchpadScript.run`.
@@ -30,7 +36,8 @@
30 def main(self):36 def main(self):
31 globalErrorUtility.configure('codeimportdispatcher')37 globalErrorUtility.configure('codeimportdispatcher')
3238
33 CodeImportDispatcher(self.logger).findAndDispatchJob(39 dispatcher = CodeImportDispatcher(self.logger, self.options.max_jobs)
40 dispatcher.findAndDispatchJobs(
34 ServerProxy(config.codeimportdispatcher.codeimportscheduler_url))41 ServerProxy(config.codeimportdispatcher.codeimportscheduler_url))
3542
3643
3744
=== modified file 'cronscripts/create-debwatches.py'
--- cronscripts/create-debwatches.py 2009-06-24 20:52:01 +0000
+++ cronscripts/create-debwatches.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -11,9 +11,9 @@
1111
12__metaclass__ = type12__metaclass__ = type
1313
14import _pythonpath
14import os15import os
15import logging16import logging
16import _pythonpath
1717
18# zope bits18# zope bits
19from zope.component import getUtility19from zope.component import getUtility
2020
=== modified file 'cronscripts/create_merge_proposals.py'
--- cronscripts/create_merge_proposals.py 2009-09-03 19:46:42 +0000
+++ cronscripts/create_merge_proposals.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/distributionmirror-prober.py'
--- cronscripts/distributionmirror-prober.py 2009-06-24 20:52:01 +0000
+++ cronscripts/distributionmirror-prober.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== renamed file 'cronscripts/expire-ppa-binaries.py' => 'cronscripts/expire-archive-files.py'
--- cronscripts/expire-ppa-binaries.py 2009-06-24 20:52:01 +0000
+++ cronscripts/expire-archive-files.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -12,11 +12,11 @@
12import _pythonpath12import _pythonpath
1313
14from canonical.config import config14from canonical.config import config
15from lp.soyuz.scripts.expire_ppa_binaries import PPABinaryExpirer15from lp.soyuz.scripts.expire_archive_files import ArchiveExpirer
1616
1717
18if __name__ == '__main__':18if __name__ == '__main__':
19 script = PPABinaryExpirer(19 script = ArchiveExpirer(
20 'expire-ppa-binaries', dbuser=config.binaryfile_expire.dbuser)20 'expire-archive-files', dbuser=config.binaryfile_expire.dbuser)
21 script.lock_and_run()21 script.lock_and_run()
2222
2323
=== modified file 'cronscripts/expire-bugtasks.py'
--- cronscripts/expire-bugtasks.py 2009-06-24 20:52:01 +0000
+++ cronscripts/expire-bugtasks.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/expire-questions.py'
--- cronscripts/expire-questions.py 2009-06-24 20:52:01 +0000
+++ cronscripts/expire-questions.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/flag-expired-memberships.py'
--- cronscripts/flag-expired-memberships.py 2009-06-24 20:52:01 +0000
+++ cronscripts/flag-expired-memberships.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/foaf-update-karma-cache.py'
--- cronscripts/foaf-update-karma-cache.py 2009-06-24 20:52:01 +0000
+++ cronscripts/foaf-update-karma-cache.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -10,7 +10,8 @@
10from zope.component import getUtility10from zope.component import getUtility
1111
12from canonical.config import config12from canonical.config import config
13from canonical.database.sqlbase import ISOLATION_LEVEL_AUTOCOMMIT13from canonical.database.sqlbase import (
14 ISOLATION_LEVEL_AUTOCOMMIT, flush_database_updates)
14from canonical.launchpad.interfaces import IKarmaCacheManager, NotFoundError15from canonical.launchpad.interfaces import IKarmaCacheManager, NotFoundError
15from lp.services.scripts.base import LaunchpadCronScript16from lp.services.scripts.base import LaunchpadCronScript
1617
@@ -83,6 +84,7 @@
83 scaling = self.calculate_scaling(results)84 scaling = self.calculate_scaling(results)
84 for entry in results:85 for entry in results:
85 self.update_one_karma_cache_entry(entry, scaling)86 self.update_one_karma_cache_entry(entry, scaling)
87 flush_database_updates()
8688
87 # Delete the entries we're going to replace.89 # Delete the entries we're going to replace.
88 self.cur.execute("DELETE FROM KarmaCache WHERE category IS NULL")90 self.cur.execute("DELETE FROM KarmaCache WHERE category IS NULL")
@@ -121,7 +123,7 @@
121 # VACUUM KarmaTotalCache since we have just touched every row in it.123 # VACUUM KarmaTotalCache since we have just touched every row in it.
122 self.cur.execute("""VACUUM KarmaTotalCache""")124 self.cur.execute("""VACUUM KarmaTotalCache""")
123125
124 # Insert new records into the KarmaTotalCache table. 126 # Insert new records into the KarmaTotalCache table.
125127
126 # XXX: salgado 2007-02-06:128 # XXX: salgado 2007-02-06:
127 # If deadlocks ever become a problem, first LOCK the129 # If deadlocks ever become a problem, first LOCK the
@@ -146,7 +148,7 @@
146148
147 def C_add_karmacache_sums(self):149 def C_add_karmacache_sums(self):
148 self.logger.info("Step C: Calculating KarmaCache sums")150 self.logger.info("Step C: Calculating KarmaCache sums")
149 # We must issue some SUM queries to insert the karma totals for: 151 # We must issue some SUM queries to insert the karma totals for:
150 # - All actions of a person on a given product.152 # - All actions of a person on a given product.
151 # - All actions of a person on a given distribution.153 # - All actions of a person on a given distribution.
152 # - All actions of a person on a given project.154 # - All actions of a person on a given project.
@@ -156,7 +158,7 @@
156158
157 # - All actions with a specific category of a person.159 # - All actions with a specific category of a person.
158 self.cur.execute("""160 self.cur.execute("""
159 INSERT INTO KarmaCache 161 INSERT INTO KarmaCache
160 (person, category, karmavalue, product, distribution,162 (person, category, karmavalue, product, distribution,
161 sourcepackagename, project)163 sourcepackagename, project)
162 SELECT person, category, SUM(karmavalue), NULL, NULL, NULL, NULL164 SELECT person, category, SUM(karmavalue), NULL, NULL, NULL, NULL
@@ -167,7 +169,7 @@
167169
168 # - All actions of a person on a given product.170 # - All actions of a person on a given product.
169 self.cur.execute("""171 self.cur.execute("""
170 INSERT INTO KarmaCache 172 INSERT INTO KarmaCache
171 (person, category, karmavalue, product, distribution,173 (person, category, karmavalue, product, distribution,
172 sourcepackagename, project)174 sourcepackagename, project)
173 SELECT person, NULL, SUM(karmavalue), product, NULL, NULL, NULL175 SELECT person, NULL, SUM(karmavalue), product, NULL, NULL, NULL
@@ -178,7 +180,7 @@
178180
179 # - All actions of a person on a given distribution.181 # - All actions of a person on a given distribution.
180 self.cur.execute("""182 self.cur.execute("""
181 INSERT INTO KarmaCache 183 INSERT INTO KarmaCache
182 (person, category, karmavalue, product, distribution,184 (person, category, karmavalue, product, distribution,
183 sourcepackagename, project)185 sourcepackagename, project)
184 SELECT person, NULL, SUM(karmavalue), NULL, distribution, NULL, NULL186 SELECT person, NULL, SUM(karmavalue), NULL, distribution, NULL, NULL
@@ -189,7 +191,7 @@
189191
190 # - All actions of a person on a given project.192 # - All actions of a person on a given project.
191 self.cur.execute("""193 self.cur.execute("""
192 INSERT INTO KarmaCache 194 INSERT INTO KarmaCache
193 (person, category, karmavalue, product, distribution,195 (person, category, karmavalue, product, distribution,
194 sourcepackagename, project)196 sourcepackagename, project)
195 SELECT person, NULL, SUM(karmavalue), NULL, NULL, NULL,197 SELECT person, NULL, SUM(karmavalue), NULL, NULL, NULL,
@@ -206,7 +208,7 @@
206 # inserted here will be included in the calculation of the overall208 # inserted here will be included in the calculation of the overall
207 # karma of a person on a given project.209 # karma of a person on a given project.
208 self.cur.execute("""210 self.cur.execute("""
209 INSERT INTO KarmaCache 211 INSERT INTO KarmaCache
210 (person, category, karmavalue, product, distribution,212 (person, category, karmavalue, product, distribution,
211 sourcepackagename, project)213 sourcepackagename, project)
212 SELECT person, category, SUM(karmavalue), NULL, NULL, NULL,214 SELECT person, category, SUM(karmavalue), NULL, NULL, NULL,
@@ -244,15 +246,18 @@
244 scaling[category] = 1246 scaling[category] = 1
245 else:247 else:
246 scaling[category] = float(largest_total) / float(points)248 scaling[category] = float(largest_total) / float(points)
247 self.logger.debug('Scaling %s by a factor of %0.4f'
248 % (categories[category], scaling[category]))
249 max_scaling = config.karmacacheupdater.max_scaling249 max_scaling = config.karmacacheupdater.max_scaling
250 if scaling[category] > max_scaling:250 if scaling[category] > max_scaling:
251 self.logger.info(
252 'Scaling %s by a factor of %0.4f (capped to %0.4f)'
253 % (categories[category], scaling[category], max_scaling))
251 scaling[category] = max_scaling254 scaling[category] = max_scaling
252 self.logger.debug('Reducing %s scaling to %d to avoid spikes' 255 else:
253 % (categories[category], max_scaling))256 self.logger.info(
257 'Scaling %s by a factor of %0.4f'
258 % (categories[category], scaling[category]))
254 return scaling259 return scaling
255 260
256 def update_one_karma_cache_entry(self, entry, scaling):261 def update_one_karma_cache_entry(self, entry, scaling):
257 """Updates an individual (non-summed) KarmaCache entry.262 """Updates an individual (non-summed) KarmaCache entry.
258263
@@ -262,7 +267,7 @@
262 """267 """
263 (person_id, category_id, product_id, distribution_id, points) = entry268 (person_id, category_id, product_id, distribution_id, points) = entry
264 points *= scaling[category_id] # Scaled. wow.269 points *= scaling[category_id] # Scaled. wow.
265 self.logger.debug("Setting person_id=%d, category_id=%d, points=%d" 270 self.logger.debug("Setting person_id=%d, category_id=%d, points=%d"
266 % (person_id, category_id, points))271 % (person_id, category_id, points))
267272
268 points = int(points)273 points = int(points)
@@ -285,7 +290,7 @@
285290
286291
287if __name__ == '__main__':292if __name__ == '__main__':
288 script = KarmaCacheUpdater('karma-update', 293 script = KarmaCacheUpdater('karma-update',
289 dbuser=config.karmacacheupdater.dbuser)294 dbuser=config.karmacacheupdater.dbuser)
290 script.lock_and_run(implicit_begin=True)295 script.lock_and_run(implicit_begin=True)
291296
292297
=== modified file 'cronscripts/garbo-daily.py'
--- cronscripts/garbo-daily.py 2009-06-24 20:52:01 +0000
+++ cronscripts/garbo-daily.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/garbo-hourly.py'
--- cronscripts/garbo-hourly.py 2009-06-24 20:52:01 +0000
+++ cronscripts/garbo-hourly.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/generate-ppa-htaccess.py'
--- cronscripts/generate-ppa-htaccess.py 2009-06-24 20:52:01 +0000
+++ cronscripts/generate-ppa-htaccess.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/language-pack-exporter.py'
--- cronscripts/language-pack-exporter.py 2009-07-17 00:26:05 +0000
+++ cronscripts/language-pack-exporter.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/librarian-gc.py'
--- cronscripts/librarian-gc.py 2009-06-24 20:52:01 +0000
+++ cronscripts/librarian-gc.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -46,16 +46,17 @@
46 help="Skip removing expired TemporaryBlobStorage rows"46 help="Skip removing expired TemporaryBlobStorage rows"
47 )47 )
48 self.parser.add_option(48 self.parser.add_option(
49 '', "--skip-expired", action="store_true", default=False,
50 dest="skip_expired",
51 help="Skip flagging expired files for deletion."
52 )
53 self.parser.add_option(
54 '', "--skip-files", action="store_true", default=False,49 '', "--skip-files", action="store_true", default=False,
55 dest="skip_files",50 dest="skip_files",
56 help="Skip removing files on disk with no database references"51 help="Skip removing files on disk with no database references"
57 " or flagged for deletion."52 " or flagged for deletion."
58 )53 )
54 self.parser.add_option(
55 '', "--skip-expiry", action="store_true", default=False,
56 dest="skip_expiry",
57 help="Skip expiring aliases with an expiry date in the past."
58 )
59
5960
60 def main(self):61 def main(self):
61 librariangc.log = self.logger62 librariangc.log = self.logger
@@ -71,6 +72,8 @@
7172
72 # Note that each of these next steps will issue commit commands73 # Note that each of these next steps will issue commit commands
73 # as appropriate to make this script transaction friendly74 # as appropriate to make this script transaction friendly
75 if not self.options.skip_expiry:
76 librariangc.expire_aliases(conn)
74 if not self.options.skip_content:77 if not self.options.skip_content:
75 librariangc.delete_unreferenced_content(conn) # first sweep78 librariangc.delete_unreferenced_content(conn) # first sweep
76 if not self.options.skip_blobs:79 if not self.options.skip_blobs:
@@ -81,8 +84,6 @@
81 librariangc.delete_unreferenced_aliases(conn)84 librariangc.delete_unreferenced_aliases(conn)
82 if not self.options.skip_content:85 if not self.options.skip_content:
83 librariangc.delete_unreferenced_content(conn) # second sweep86 librariangc.delete_unreferenced_content(conn) # second sweep
84 if not self.options.skip_expired:
85 librariangc.flag_expired_files(conn)
86 if not self.options.skip_files:87 if not self.options.skip_files:
87 librariangc.delete_unwanted_files(conn)88 librariangc.delete_unwanted_files(conn)
8889
8990
=== renamed file 'cronscripts/mpcreationjobs.py' => 'cronscripts/merge-proposal-jobs.py'
--- cronscripts/mpcreationjobs.py 2009-09-03 19:04:28 +0000
+++ cronscripts/merge-proposal-jobs.py 2010-05-05 01:58:48 +0000
@@ -1,48 +1,40 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009, 2010 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
6# pylint: disable-msg=W04036# pylint: disable-msg=W0403
77
8"""Handle new BranchMergeProposals.8"""Handle jobs for BranchMergeProposals.
99
10This script generates a diff for the merge proposal if needed, then notifies10This script handles all job types for branch merge proposals.
11all interested parties about the merge proposal.
12"""11"""
1312
14__metaclass__ = type13__metaclass__ = type
1514
16import _pythonpath15import _pythonpath
17from zope.component import getUtility
1816
19from canonical.config import config17# The following line is a horrible hack, but unfortunately necessary right now
20from lp.codehosting.vfs import get_scanner_server18# to stop import errors from circular imports.
21from lp.services.job.runner import JobRunner19import canonical.launchpad.interfaces
22from lp.code.interfaces.branchmergeproposal import (20from lp.code.interfaces.branchmergeproposal import (
23 IMergeProposalCreatedJobSource,)21 IBranchMergeProposalJobSource,
24from lp.services.scripts.base import LaunchpadCronScript22 )
25from canonical.launchpad.webapp.errorlog import globalErrorUtility23from lp.services.job.runner import JobCronScript, TwistedJobRunner
2624
2725
28class RunMergeProposalCreatedJobs(LaunchpadCronScript):26class RunMergeProposalJobs(JobCronScript):
29 """Run merge proposal creation jobs."""27 """Run all merge proposal jobs."""
3028
31 def main(self):29 config_name = 'merge_proposal_jobs'
32 globalErrorUtility.configure('mpcreationjobs')30 source_interface = IBranchMergeProposalJobSource
33 job_source = getUtility(IMergeProposalCreatedJobSource)31
34 runner = JobRunner.fromReady(job_source, self.logger)32 def __init__(self):
35 server = get_scanner_server()33 super(RunMergeProposalJobs, self).__init__(
36 server.setUp()34 runner_class=TwistedJobRunner,
37 try:35 script_name='merge-proposal-jobs')
38 runner.runAll()
39 finally:
40 server.tearDown()
41 self.logger.info(
42 'Ran %d MergeProposalCreatedJobs.', len(runner.completed_jobs))
4336
4437
45if __name__ == '__main__':38if __name__ == '__main__':
46 script = RunMergeProposalCreatedJobs(39 script = RunMergeProposalJobs()
47 'mpcreationjobs', config.mpcreationjobs.dbuser)
48 script.lock_and_run()40 script.lock_and_run()
4941
=== modified file 'cronscripts/mirror-prober.sh'
--- cronscripts/mirror-prober.sh 2009-06-24 20:52:01 +0000
+++ cronscripts/mirror-prober.sh 2010-05-05 01:58:48 +0000
@@ -39,10 +39,10 @@
39cd /srv/launchpad.net/production/launchpad/cronscripts39cd /srv/launchpad.net/production/launchpad/cronscripts
4040
41echo '== Distribution mirror prober (archive)' `date` ==41echo '== Distribution mirror prober (archive)' `date` ==
42python2.4 distributionmirror-prober.py --content-type=archive --max-mirrors=2042python2.5 -S distributionmirror-prober.py --content-type=archive --max-mirrors=20
4343
44echo '== Distribution mirror prober (cdimage)' `date` ==44echo '== Distribution mirror prober (cdimage)' `date` ==
45python2.4 distributionmirror-prober.py --content-type=cdimage --max-mirrors=3045python2.5 -S distributionmirror-prober.py --content-type=cdimage --max-mirrors=30
4646
47rm -f $LOCK47rm -f $LOCK
4848
4949
=== modified file 'cronscripts/nightly.sh'
--- cronscripts/nightly.sh 2009-08-10 16:57:14 +0000
+++ cronscripts/nightly.sh 2010-05-05 01:58:48 +0000
@@ -3,11 +3,11 @@
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
6# This script performs nightly chores. It should be run from 6# This script performs nightly chores. It should be run from
7# cron as the launchpad user once a day. Typically the output7# cron as the launchpad user once a day. Typically the output
8# will be sent to an email address for inspection.8# will be sent to an email address for inspection.
99
10# Note that http/ftp proxies are needed by the product 10# Note that http/ftp proxies are needed by the product
11# release finder11# release finder
1212
13# Only run this script on loganberry13# Only run this script on loganberry
@@ -42,41 +42,41 @@
42cd /srv/launchpad.net/production/launchpad/cronscripts42cd /srv/launchpad.net/production/launchpad/cronscripts
4343
44echo == Expiring memberships `date` ==44echo == Expiring memberships `date` ==
45python2.4 flag-expired-memberships.py -q45python2.5 -S flag-expired-memberships.py -q
4646
47echo == Allocating revision karma `date` ==47echo == Allocating revision karma `date` ==
48python2.4 allocate-revision-karma.py -q48python2.5 -S allocate-revision-karma.py -q
4949
50echo == Recalculating karma `date` ==50echo == Recalculating karma `date` ==
51python2.4 foaf-update-karma-cache.py -q51python2.5 -S foaf-update-karma-cache.py -q
5252
53echo == Updating cached statistics `date` ==53echo == Updating cached statistics `date` ==
54python2.4 update-stats.py -q54python2.5 -S update-stats.py -q
5555
56echo == Expiring questions `date` ==56echo == Expiring questions `date` ==
57python2.4 expire-questions.py57python2.5 -S expire-questions.py
5858
59### echo == Expiring bugs `date` ==59### echo == Expiring bugs `date` ==
60### python2.4 expire-bugtasks.py60### python2.5 -S expire-bugtasks.py
6161
62# checkwatches.py is scheduled in the /code/pqm/launchpad_crontabs branch.62# checkwatches.py is scheduled in the /code/pqm/launchpad_crontabs branch.
63### echo == Updating bug watches `date` ==63### echo == Updating bug watches `date` ==
64### python2.4 checkwatches.py64### python2.5 -S checkwatches.py
6565
66echo == Updating bugtask target name caches `date` ==66echo == Updating bugtask target name caches `date` ==
67python2.4 update-bugtask-targetnamecaches.py -q67python2.5 -S update-bugtask-targetnamecaches.py -q
6868
69echo == Updating personal standings `date` ==69echo == Updating personal standings `date` ==
70python2.4 update-standing.py -q70python2.5 -S update-standing.py -q
7171
72echo == Updating CVE database `date` ==72echo == Updating CVE database `date` ==
73python2.4 update-cve.py -q73python2.5 -S update-cve.py -q
7474
75echo == Updating package cache `date` ==75echo == Updating package cache `date` ==
76python2.4 update-pkgcache.py -q76python2.5 -S update-pkgcache.py -q
7777
78echo == Product Release Finder `date` ==78echo == Product Release Finder `date` ==
79python2.4 product-release-finder.py -q79python2.5 -S product-release-finder.py -q
8080
8181
82rm -f $LOCK82rm -f $LOCK
8383
=== modified file 'cronscripts/oops-prune.py'
--- cronscripts/oops-prune.py 2009-06-24 20:52:01 +0000
+++ cronscripts/oops-prune.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/parse-librarian-apache-access-logs.py'
--- cronscripts/parse-librarian-apache-access-logs.py 2009-09-11 12:11:04 +0000
+++ cronscripts/parse-librarian-apache-access-logs.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== added file 'cronscripts/parse-ppa-apache-access-logs.py'
--- cronscripts/parse-ppa-apache-access-logs.py 1970-01-01 00:00:00 +0000
+++ cronscripts/parse-ppa-apache-access-logs.py 2010-05-05 01:58:48 +0000
@@ -0,0 +1,61 @@
1#!/usr/bin/python2.5 -S
2#
3# Copyright 2010 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).
5
6"""Parse PPA apache logs to find out download counts for each file."""
7
8__metaclass__ = type
9
10import _pythonpath
11
12import functools
13
14from zope.component import getUtility
15
16from canonical.config import config
17# XXX: wgrant 2010-03-16 bug=539496: Importing directly from
18# lp.registry.interfaces.person results in a circular import.
19from canonical.launchpad.interfaces import IPersonSet
20from lp.soyuz.interfaces.archive import NoSuchPPA
21from lp.soyuz.scripts.ppa_apache_log_parser import DBUSER, get_ppa_file_key
22from lp.services.apachelogparser.script import ParseApacheLogs
23
24
25class ParsePPAApacheLogs(ParseApacheLogs):
26 """An Apache log parser for PPA downloads."""
27
28 def setUpUtilities(self):
29 """See `ParseApacheLogs`."""
30 self.person_set = getUtility(IPersonSet)
31
32 @property
33 def root(self):
34 """See `ParseApacheLogs`."""
35 return config.ppa_apache_log_parser.logs_root
36
37 def getDownloadKey(self, path):
38 """See `ParseApacheLogs`."""
39 return get_ppa_file_key(path)
40
41 def getDownloadCountUpdater(self, file_id):
42 """See `ParseApacheLogs`."""
43 person = self.person_set.getByName(file_id[0])
44 if person is None:
45 return
46 try:
47 archive = person.getPPAByName(file_id[1])
48 except NoSuchPPA:
49 return None
50 # file_id[2] (distro) isn't used yet, since getPPAByName
51 # hardcodes Ubuntu.
52 bpr = archive.getBinaryPackageReleaseByFileName(file_id[3])
53 if bpr is None:
54 return None
55
56 return functools.partial(archive.updatePackageDownloadCount, bpr)
57
58
59if __name__ == '__main__':
60 script = ParsePPAApacheLogs('parse-ppa-apache-logs', DBUSER)
61 script.lock_and_run()
062
=== modified file 'cronscripts/ppa-generate-keys.py'
--- cronscripts/ppa-generate-keys.py 2009-06-24 20:52:01 +0000
+++ cronscripts/ppa-generate-keys.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== added file 'cronscripts/process-apport-blobs.py'
--- cronscripts/process-apport-blobs.py 1970-01-01 00:00:00 +0000
+++ cronscripts/process-apport-blobs.py 2010-05-05 01:58:48 +0000
@@ -0,0 +1,33 @@
1#!/usr/bin/python2.5 -S
2#
3# Copyright 2010 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).
5
6# pylint: disable-msg=W0403
7
8"""Process uploaded Apport BLOBs."""
9
10__metaclass__ = type
11
12import _pythonpath
13
14from canonical.launchpad.webapp import errorlog
15
16from lp.services.job.runner import JobCronScript
17from lp.bugs.interfaces.apportjob import IProcessApportBlobJobSource
18
19
20class RunProcessApportBlobs(JobCronScript):
21 """Run ProcessApportBlobJobs."""
22
23 config_name = 'process_apport_blobs'
24 source_interface = IProcessApportBlobJobSource
25
26 def main(self):
27 errorlog.globalErrorUtility.configure(self.config_name)
28 return super(RunProcessApportBlobs, self).main()
29
30
31if __name__ == '__main__':
32 script = RunProcessApportBlobs()
33 script.lock_and_run()
034
=== modified file 'cronscripts/process-hwdb-submissions.py'
--- cronscripts/process-hwdb-submissions.py 2009-06-24 20:52:01 +0000
+++ cronscripts/process-hwdb-submissions.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -24,7 +24,7 @@
24import _pythonpath24import _pythonpath
2525
26from lp.services.scripts.base import LaunchpadCronScript26from lp.services.scripts.base import LaunchpadCronScript
27from canonical.launchpad.scripts.hwdbsubmissions import (27from lp.hardwaredb.scripts.hwdbsubmissions import (
28 process_pending_submissions)28 process_pending_submissions)
2929
3030
3131
=== modified file 'cronscripts/process-mail.py'
--- cronscripts/process-mail.py 2009-06-24 20:52:01 +0000
+++ cronscripts/process-mail.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/process-pending-packagediffs.py'
--- cronscripts/process-pending-packagediffs.py 2009-06-24 20:52:01 +0000
+++ cronscripts/process-pending-packagediffs.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/product-release-finder.py'
--- cronscripts/product-release-finder.py 2009-06-24 20:52:01 +0000
+++ cronscripts/product-release-finder.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/publishing/cron.germinate'
--- cronscripts/publishing/cron.germinate 2009-08-21 09:10:55 +0000
+++ cronscripts/publishing/cron.germinate 2010-05-05 01:58:48 +0000
@@ -11,6 +11,9 @@
11LOCKROOT=$ARCHIVEROOT/..11LOCKROOT=$ARCHIVEROOT/..
12GERMINATEROOT=$ARCHIVEROOT/../ubuntu-germinate12GERMINATEROOT=$ARCHIVEROOT/../ubuntu-germinate
1313
14LAUNCHPADROOT=/srv/launchpad.net/codelines/current
15MAINTAINCE_CHECK=$LAUNCHPADROOT/cronscripts/publishing/maintenance-check.py
16
14## Check to see if another germinate run is in progress17## Check to see if another germinate run is in progress
1518
16LOCKFILE=$LOCKROOT/cron.germinate.lock19LOCKFILE=$LOCKROOT/cron.germinate.lock
@@ -32,7 +35,7 @@
32cd $GERMINATEROOT35cd $GERMINATEROOT
3336
34# Clean up temporary files37# Clean up temporary files
35rm -f germinate.output ALL ALL.sources UBUNTU-* KUBUNTU-* EDUBUNTU-* XUBUNTU-* MOBILE-* MYTHBUNTU-* UNR-*38rm -f germinate.output ALL ALL.sources UBUNTU-* KUBUNTU-* EDUBUNTU-* XUBUNTU-* MYTHBUNTU-* NETBOOK-*
36rm -f all_* all.sources_*39rm -f all_* all.sources_*
3740
38# Grab a local copy of Sources files41# Grab a local copy of Sources files
@@ -41,11 +44,12 @@
41done44done
4245
43> "$MISCROOT/more-extra.override.$suite.main.new"46> "$MISCROOT/more-extra.override.$suite.main.new"
44for distro in ubuntu kubuntu edubuntu xubuntu mobile mythbuntu unr; do47
48germinate_components=main,universe,restricted,multiverse
49for distro in ubuntu kubuntu edubuntu xubuntu mythbuntu netbook; do
45 DISTRO="$(echo $distro | tr a-z A-Z)"50 DISTRO="$(echo $distro | tr a-z A-Z)"
46 germinate_suite="$distro.$suite"51 germinate_suite="$distro.$suite"
47 germinate_components=main,universe,restricted,multiverse52 for arch in i386 amd64 powerpc sparc ia64 armel; do
48 for arch in i386 amd64 lpia powerpc sparc ia64 armel; do
49 # Grab local copy of Packages and InstallerPackages files53 # Grab local copy of Packages and InstallerPackages files
50 for component in main universe restricted multiverse; do54 for component in main universe restricted multiverse; do
51 zcat $ARCHIVEROOT/dists/"$suite"/"$component"/binary-$arch/Packages.gz > archive.ubuntu.com_"$suite"_"$component"_Packages55 zcat $ARCHIVEROOT/dists/"$suite"/"$component"/binary-$arch/Packages.gz > archive.ubuntu.com_"$suite"_"$component"_Packages
@@ -122,4 +126,10 @@
122done126done
123echo " done."127echo " done."
124128
129# now generate the Supported extra overrides
130$MAINTAINCE_CHECK $suite > "$MISCROOT/more-extra.override.$suite.main.supported" 2> _maintenance-check.stderr
131if [ $? -eq 0 ]; then
132 cat "$MISCROOT/more-extra.override.$suite.main.supported" >> "$MISCROOT/more-extra.override.$suite.main.new"
133fi
134
125mv -f "$MISCROOT/more-extra.override.$suite.main.new" "$MISCROOT/more-extra.override.$suite.main"135mv -f "$MISCROOT/more-extra.override.$suite.main.new" "$MISCROOT/more-extra.override.$suite.main"
126136
=== added file 'cronscripts/publishing/cron.publish-copy-archives'
--- cronscripts/publishing/cron.publish-copy-archives 1970-01-01 00:00:00 +0000
+++ cronscripts/publishing/cron.publish-copy-archives 2010-05-05 01:58:48 +0000
@@ -0,0 +1,83 @@
1#!/bin/sh
2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).
5
6# LPCONFIG will come from the environment so this script can run unaltered
7# on dogfood.
8if [ -z $LPCONFIG ]; then
9 echo LPCONFIG must be set to run this script.
10 exit 1
11fi
12
13set -x
14set -e
15set -u
16
17#
18# This script publishes the COPY (rebuild) archvies *only*.
19#
20
21
22# Informational -- this *MUST* match the database.
23ARCHIVEROOT=/srv/launchpad.net/ubuntu-archive/ubuntu
24DISTSROOT=$ARCHIVEROOT/dists
25OVERRIDEROOT=$ARCHIVEROOT/../ubuntu-overrides
26INDICES=$ARCHIVEROOT/indices
27PRODUCTION_CONFIG=ftpmaster
28
29if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
30 GNUPGHOME=/srv/launchpad.net/ubuntu-archive/gnupg-home
31else
32 echo GPG keys will come from ~/.gnupg
33 # GNUPGHOME does not need to be set, keys can come from ~/.gnupg.
34fi
35
36# Configuration options.
37LAUNCHPADROOT=/srv/launchpad.net/codelines/current
38LOCKFILE=/srv/launchpad.net/ubuntu-archive/cron.daily.lock
39DISTRONAME=ubuntu
40TRACEFILE=$ARCHIVEROOT/project/trace/$(hostname --fqdn)
41
42# Manipulate the environment.
43export GNUPGHOME
44PATH=$PATH:$LAUNCHPADROOT/scripts:$LAUNCHPADROOT/cronscripts:$LAUNCHPADROOT/cronscripts/publishing:$LAUNCHPADROOT/scripts/ftpmaster-tools
45
46# Claim the lock.
47if ! lockfile -r1 $LOCKFILE; then
48 echo "Could not claim lock file."
49 exit 1
50fi
51
52# Lock claimed.
53
54cleanup () {
55 echo "Cleaning up lockfile."
56 rm -f $LOCKFILE
57}
58
59trap cleanup EXIT
60
61# Process the accepted queue into the publishing records.
62process-accepted.py --copy-archive -v -v -v $DISTRONAME
63
64# Publish the packages to disk.
65publish-distro.py -v -v --copy-archive -d $DISTRONAME
66
67set +x
68
69echo Removing uncompressed Packages and Sources files
70find ${DISTSROOT} \( -name "Packages" -o -name "Sources" \) -exec rm "{}" \;
71
72# Copy in the indices.
73if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
74 echo Copying the indices into place.
75 rm -f $INDICES/override.*
76 cp $OVERRIDEROOT/override.* $INDICES
77fi
78
79# Timestamp our trace file to track when the last archive publisher run took
80# place.
81if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
82 date -u > "$TRACEFILE"
83fi
084
=== modified file 'cronscripts/publishing/cron.publish-ftpmaster'
--- cronscripts/publishing/cron.publish-ftpmaster 2009-06-24 20:52:01 +0000
+++ cronscripts/publishing/cron.publish-ftpmaster 2010-05-05 01:58:48 +0000
@@ -44,10 +44,13 @@
44LAUNCHPADROOT=/srv/launchpad.net/codelines/current44LAUNCHPADROOT=/srv/launchpad.net/codelines/current
45LOCKFILE=/srv/launchpad.net/ubuntu-archive/cron.daily.lock45LOCKFILE=/srv/launchpad.net/ubuntu-archive/cron.daily.lock
46DISTRONAME=ubuntu46DISTRONAME=ubuntu
47TOUCHLIST=$ARCHIVEROOT/project/trace/$(hostname --fqdn)47TRACEFILE=$ARCHIVEROOT/project/trace/$(hostname --fqdn)
48DSYNCLIST=$CACHEROOT/dsync.list48DSYNCLIST=$CACHEROOT/dsync.list
49MD5LIST=$INDICES/md5sums.gz49MD5LIST=$INDICES/md5sums.gz
5050
51# Mirrors to push at the end of the publishing run.
52MASTERMIRRORS="syowa frei scandium"
53
51# Manipulate the environment.54# Manipulate the environment.
52export GNUPGHOME55export GNUPGHOME
53PATH=$PATH:$LAUNCHPADROOT/scripts:$LAUNCHPADROOT/cronscripts:$LAUNCHPADROOT/cronscripts/publishing:$LAUNCHPADROOT/scripts/ftpmaster-tools56PATH=$PATH:$LAUNCHPADROOT/scripts:$LAUNCHPADROOT/cronscripts:$LAUNCHPADROOT/cronscripts/publishing:$LAUNCHPADROOT/scripts/ftpmaster-tools
@@ -58,12 +61,14 @@
58 exit 161 exit 1
59fi62fi
6063
64echo "$(date -R): Initiating archive publishing operations..."
65
61DONEPUB=no66DONEPUB=no
6267
63cleanup () {68cleanup () {
64 echo "Cleaning up lockfile."69 echo "$(date -R): Cleaning up lockfile."
65 rm -f $LOCKFILE70 rm -f $LOCKFILE
66 echo "Moving dists backup to safe keeping for next time."71 echo "$(date -R): Moving dists backup to safe keeping for next time."
67 if [ "x$DONEPUB" = "xyes" ]; then72 if [ "x$DONEPUB" = "xyes" ]; then
68 if [ -d ${DISTSROOT}.old ]; then73 if [ -d ${DISTSROOT}.old ]; then
69 mv ${DISTSROOT}.old ${DISTSCOPYROOT}/dists74 mv ${DISTSROOT}.old ${DISTSCOPYROOT}/dists
@@ -89,11 +94,13 @@
89# Lock claimed.94# Lock claimed.
9095
91# Process the accepted queue into the publishing records.96# Process the accepted queue into the publishing records.
97echo "$(date -R): Processing the accepted queue into the publishing records..."
92process-accepted.py -v -v -v $DISTRONAME98process-accepted.py -v -v -v $DISTRONAME
9399
94# If doing a security run, find out which suites are pending publication.100# If doing a security run, find out which suites are pending publication.
95SUITEOPTS=""101SUITEOPTS=""
96if [ "$SECURITY_PUBLISHER" = "yes" ]; then102if [ "$SECURITY_PUBLISHER" = "yes" ]; then
103 echo "$(date -R): Querying which suites are pending publication..."
97 SUITES=$(lp-query-distro.py pending_suites)104 SUITES=$(lp-query-distro.py pending_suites)
98 SECURITY_SUITES="no"105 SECURITY_SUITES="no"
99 if [ -n "$SUITES" ]; then106 if [ -n "$SUITES" ]; then
@@ -109,7 +116,7 @@
109 done116 done
110 fi117 fi
111 if [ "$SECURITY_SUITES" != "yes" ]; then118 if [ "$SECURITY_SUITES" != "yes" ]; then
112 echo "Nothing to do for security publisher; exiting."119 echo "$(date -R): Nothing to do for security publisher; exiting."
113 exit 0120 exit 0
114 fi121 fi
115fi122fi
@@ -122,21 +129,27 @@
122# This should achieve the same as copying, only faster.129# This should achieve the same as copying, only faster.
123130
124# Create backup dists folder, if this is the first time.131# Create backup dists folder, if this is the first time.
132echo "$(date -R): Creating backup dists directories..."
125mkdir -p ${DISTSCOPYROOT}/dists133mkdir -p ${DISTSCOPYROOT}/dists
126mkdir -p ${DISTSCOPYROOT_PARTNER}/dists134mkdir -p ${DISTSCOPYROOT_PARTNER}/dists
127135
128# Move the backup dists folder into place.136# Move the backup dists folder into place.
137echo "$(date -R): Moving backup dists into place..."
129mv ${DISTSCOPYROOT}/dists ${ARCHIVEROOT}/dists.new138mv ${DISTSCOPYROOT}/dists ${ARCHIVEROOT}/dists.new
130mv ${DISTSCOPYROOT_PARTNER}/dists ${ARCHIVEROOT_PARTNER}/dists.new139mv ${DISTSCOPYROOT_PARTNER}/dists ${ARCHIVEROOT_PARTNER}/dists.new
131140
132# Bring it up-to-date efficiently with rsync. --delete is required to141# Bring it up-to-date efficiently with rsync. --delete is required to
133# ensure we don't ressurect things previously deleted, bug 58835.142# ensure we don't ressurect things previously deleted, bug 58835.
143echo "$(date -R): Updating dists directories..."
134rsync -aH --delete ${DISTSROOT}/ ${ARCHIVEROOT}/dists.new144rsync -aH --delete ${DISTSROOT}/ ${ARCHIVEROOT}/dists.new
135rsync -aH --delete ${DISTSROOT_PARTNER}/ ${ARCHIVEROOT_PARTNER}/dists.new145rsync -aH --delete ${DISTSROOT_PARTNER}/ ${ARCHIVEROOT_PARTNER}/dists.new
136146
137# Publish the results for all archives (except PPA).147# Publish the results for all archives (except PPA).
138# The -R only affects the primary and the partner archive.148# The -R only affects the primary and the partner archive.
149echo "$(date -R): Publishing the $DISTRONAME partner archive..."
139publish-distro.py -v -v --partner -d $DISTRONAME -R ${DISTSROOT_PARTNER}.new150publish-distro.py -v -v --partner -d $DISTRONAME -R ${DISTSROOT_PARTNER}.new
151
152echo "$(date -R): Publishing the $DISTRONAME archive..."
140publish-distro.py -v -v -d $DISTRONAME $SUITEOPTS -R ${DISTSROOT}.new153publish-distro.py -v -v -d $DISTRONAME $SUITEOPTS -R ${DISTSROOT}.new
141154
142set +x155set +x
@@ -148,39 +161,40 @@
148 $(find ${DISTSROOT}.new/*/*/dist-upgrader* -name "*.tar.gz"); do161 $(find ${DISTSROOT}.new/*/*/dist-upgrader* -name "*.tar.gz"); do
149 # [ Release.gpg missing ] or [ Release is newer than Release.gpg ]162 # [ Release.gpg missing ] or [ Release is newer than Release.gpg ]
150 if [ ! -f $CANDIDATE.gpg ] || [ $CANDIDATE -nt $CANDIDATE.gpg ]; then163 if [ ! -f $CANDIDATE.gpg ] || [ $CANDIDATE -nt $CANDIDATE.gpg ]; then
151 echo "(re-)signing $CANDIDATE"164 echo "$(date -R): (re-)signing $CANDIDATE"
152 gpg --yes --detach-sign --armor -o $CANDIDATE.gpg --sign $CANDIDATE165 gpg --yes --detach-sign --armor -o $CANDIDATE.gpg --sign $CANDIDATE
153 else166 else
154 echo "Not re-signing $CANDIDATE"167 echo "$(date -R): Not re-signing $CANDIDATE"
155 fi168 fi
156done169done
157SIGNLIST_PARTNER=$(find ${DISTSROOT_PARTNER}.new -maxdepth 2 -name Release)170SIGNLIST_PARTNER=$(find ${DISTSROOT_PARTNER}.new -maxdepth 2 -name Release)
158for CANDIDATE in $SIGNLIST_PARTNER; do171for CANDIDATE in $SIGNLIST_PARTNER; do
159 # [ Release.gpg missing ] or [ Release is newer than Release.gpg ].172 # [ Release.gpg missing ] or [ Release is newer than Release.gpg ].
160 if [ ! -f $CANDIDATE.gpg ] || [ $CANDIDATE -nt $CANDIDATE.gpg ]; then173 if [ ! -f $CANDIDATE.gpg ] || [ $CANDIDATE -nt $CANDIDATE.gpg ]; then
161 echo "(re-)signing $CANDIDATE"174 echo "$(date -R): (re-)signing $CANDIDATE"
162 gpg --yes --detach-sign --armor -o $CANDIDATE.gpg --sign $CANDIDATE175 gpg --yes --detach-sign --armor -o $CANDIDATE.gpg --sign $CANDIDATE
163 else176 else
164 echo "Not re-signing $CANDIDATE"177 echo "$(date -R): Not re-signing $CANDIDATE"
165 fi178 fi
166done179done
167180
168# The Packages and Sources files are very large and would cripple our181# The Packages and Sources files are very large and would cripple our
169# mirrors, so we remove them now that the uncompressed MD5SUMS are in the182# mirrors, so we remove them now that the uncompressed MD5SUMS are in the
170# Release files.183# Release files.
171echo Removing uncompressed Packages and Sources files184echo "$(date -R): Removing uncompressed Packages and Sources files"
172find ${DISTSROOT}.new \( -name "Packages" -o -name "Sources" \) -exec rm "{}" \;185find ${DISTSROOT}.new \( -name "Packages" -o -name "Sources" \) -exec rm "{}" \;
173find ${DISTSROOT_PARTNER} \( -name "Packages" -o -name "Sources" \) -exec rm "{}" \;186find ${DISTSROOT_PARTNER} \( -name "Packages" -o -name "Sources" \) -exec rm "{}" \;
174187
175# Copy in the indices.188# Copy in the indices.
176if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then189if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
177 echo Copying the indices into place.190 echo "$(date -R): Copying the indices into place."
178 rm -f $INDICES/override.*191 rm -f $INDICES/override.*
179 cp $OVERRIDEROOT/override.* $INDICES192 cp $OVERRIDEROOT/override.* $INDICES
180fi193fi
181194
182# As close to atomically as possible, put the new dists into place for the195# As close to atomically as possible, put the new dists into place for the
183# primary and partner archives.196# primary and partner archives.
197echo "$(date -R): Placing the new dists into place..."
184mv $DISTSROOT ${DISTSROOT}.old198mv $DISTSROOT ${DISTSROOT}.old
185mv ${DISTSROOT}.new $DISTSROOT199mv ${DISTSROOT}.new $DISTSROOT
186mv $DISTSROOT_PARTNER ${DISTSROOT_PARTNER}.old200mv $DISTSROOT_PARTNER ${DISTSROOT_PARTNER}.old
@@ -192,19 +206,21 @@
192# Generate the -commercial pocket for backwards compatibility with206# Generate the -commercial pocket for backwards compatibility with
193# dapper, edgy and feisty releases. Don't fail the whole script if it207# dapper, edgy and feisty releases. Don't fail the whole script if it
194# fails.208# fails.
209echo "$(date -R): Generating -commerical pocket..."
195commercial-compat.sh || true210commercial-compat.sh || true
196211
197# Touch everything you asked us to do.212# Timestamp our trace file to track when the last archive publisher run took
213# place.
198if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then214if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
199 for FILE in $TOUCHLIST; do215 echo "$(date -R): Timestamping trace file..."
200 touch "$FILE"216 date -u > "$TRACEFILE"
201 done
202fi217fi
203218
204# Skip long-running processes when doing a quick security run.219# Skip long-running processes when doing a quick security run.
205if [ "$SECURITY_PUBLISHER" != "yes" ]; then220if [ "$SECURITY_PUBLISHER" != "yes" ]; then
206221
207 # Make the lslr because we all love those.222 # Make the lslr because we all love those.
223 echo "$(date -R): Creating ls-lR.gz..."
208 LSLR=ls-lR.gz224 LSLR=ls-lR.gz
209 ( cd $ARCHIVEROOT ; \225 ( cd $ARCHIVEROOT ; \
210 rm -f .$LSLR.new ; \226 rm -f .$LSLR.new ; \
@@ -216,25 +232,35 @@
216 mv -f .$LSLR.new $LSLR )232 mv -f .$LSLR.new $LSLR )
217233
218 # Run dsync over primary archive only.234 # Run dsync over primary archive only.
235 echo "$(date -R): Running dsync over primary archive..."
219 ( cd $ARCHIVEROOT ; \236 ( cd $ARCHIVEROOT ; \
220 dsync-flist -q generate $DSYNCLIST -e 'Packages*' -e 'Sources*' -e 'Release*' --md5 ; \237 dsync-flist -q generate $DSYNCLIST -e 'Packages*' -e 'Sources*' -e 'Release*' --md5 ; \
221 (dsync-flist -q md5sums $DSYNCLIST; find dists '(' -name 'Packages*' -o -name 'Sources*' -o -name 'Release*' ')' -print | xargs -r md5sum) | gzip -9n > ${MD5LIST} ; \238 (dsync-flist -q md5sums $DSYNCLIST; find dists '(' -name 'Packages*' -o -name 'Sources*' -o -name 'Release*' ')' -print | xargs -r md5sum) | gzip -9n > ${MD5LIST} ; \
222 dsync-flist -q link-dups $DSYNCLIST || true )239 dsync-flist -q link-dups $DSYNCLIST || true )
223240
224 # Clear out empty and thus redundant dirs.241 # Clear out empty and thus redundant dirs.
242 echo "$(date -R): Clearing out empty directories..."
225 find $ARCHIVEROOT -type d -empty | xargs -r rmdir243 find $ARCHIVEROOT -type d -empty | xargs -r rmdir
226 find $ARCHIVEROOT_PARTNER -type d -empty | xargs -r rmdir244 find $ARCHIVEROOT_PARTNER -type d -empty | xargs -r rmdir
227245
228 # Invoke cron.germinate to fill ubuntu tasks and ignore failures,246 # Invoke cron.germinate to fill ubuntu tasks and ignore failures,
229 # the mirrors should be always triggered.247 # the mirrors should be always triggered.
230 cron.germinate || echo "cron.germinate failed with exit code $?" >&2248 echo "$(date -R): Running cron.germinate..."
249 cron.germinate || echo "$(date -R): cron.germinate failed with exit code $?"
231250
232# End of block skipped by security publishing.251# End of block skipped by security publishing.
233fi252fi
234253
235# Trigger master mirrors.254# Trigger master mirrors.
236if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then255if [ "$LPCONFIG" = "$PRODUCTION_CONFIG" ]; then
237 ssh archvsync@syowa256 echo "$(date -R): Triggering master mirrors..."
238 ssh archvsync@frei257
239 ssh archvsync@rockhopper258 for HOST in $MASTERMIRRORS; do
259 echo "$(date -R): Triggering $HOST:"
260 ssh archvsync@$HOST
261 done
262
263 echo "$(date -R): Master mirror triggers completed."
240fi264fi
265
266echo "$(date -R): Archive publishing operations completed."
241267
=== added file 'cronscripts/publishing/maintenance-check.py'
--- cronscripts/publishing/maintenance-check.py 1970-01-01 00:00:00 +0000
+++ cronscripts/publishing/maintenance-check.py 2010-05-05 01:58:48 +0000
@@ -0,0 +1,382 @@
1#!/usr/bin/python
2#
3# python port of the nice maintainace-check script by Nick Barcet
4#
5# taken from:
6# https://code.edge.launchpad.net/~mvo/ubuntu-maintenance-check/python-port
7# (where it will vanish once taken here)
8
9# this warning filter is only needed on older versions of python-apt,
10# once the machine runs lucid it can be removed
11import warnings
12warnings.filterwarnings("ignore","apt API not stable yet")
13import apt
14warnings.resetwarnings()
15
16import apt_pkg
17import logging
18import os
19import sys
20import urllib2
21import urlparse
22
23from optparse import OptionParser
24
25# This is fun! We have a bunch of cases for 10.04 LTS
26#
27# - distro "ubuntu" follows SUPPORT_TIMEFRAME_LTS but only for
28# amd64/i386
29# - distros "kubuntu", "edubuntu" and "netbook" need to be
30# considered *but* only follow SUPPORT_TIMEFRAME
31# - anything that is in armel follows SUPPORT_TIMEFRAME
32#
33
34# codename of the lts releases
35LTS_RELEASES = [ "dapper", "hardy", "lucid" ]
36
37# architectures that are full supported (including LTS time)
38PRIMARY_ARCHES = ["i386", "amd64"]
39
40# architectures we support (but not for LTS time)
41SUPPORTED_ARCHES = PRIMARY_ARCHES + ["armel"]
42
43# what defines the seeds is documented in wiki.ubuntu.com/SeedManagement
44SERVER_SEEDS = [ "supported-server", "server-ship"]
45DESKTOP_SEEDS = ["ship", "supported-desktop", "supported-desktop-extra"]
46SUPPORTED_SEEDS = [ "all" ]
47
48# normal support timeframe
49# time, seeds, arches
50SUPPORT_TIMEFRAME = [
51 ("18m", SUPPORTED_SEEDS),
52]
53
54# lts support timeframe
55# time, seeds, arches
56SUPPORT_TIMEFRAME_LTS = [
57 ("5y", SERVER_SEEDS),
58 ("3y", DESKTOP_SEEDS),
59 ("18m", SUPPORTED_SEEDS),
60]
61
62# distro names and if they get LTS support (order is important)
63DISTRO_NAMES_AND_LTS_SUPPORT = [ ("ubuntu", True),
64 ("kubuntu", True),
65 ("netbook", False),
66 ]
67
68# germinate output base directory
69BASE_URL = "http://people.canonical.com/~ubuntu-archive/germinate-output/"
70
71# hints dir url, hints file is "$distro.hints" by default
72# (e.g. lucid.hints)
73HINTS_DIR_URL = "http://people.canonical.com/~ubuntu-archive/seeds/platform.%s/SUPPORTED_HINTS"
74
75# we need the archive root to parse the Sources file to support
76# by-source hints
77ARCHIVE_ROOT = "http://archive.ubuntu.com/ubuntu"
78
79# support timeframe tag used in the Packages file
80SUPPORT_TAG = "Supported"
81
82def get_binaries_for_source_pkg(srcname):
83 """ Return all binary package names for the given source package name.
84
85 :param srcname: The source package name.
86 :return: A list of binary package names.
87 """
88 pkgnames = set()
89 recs = apt_pkg.GetPkgSrcRecords()
90 while recs.Lookup(srcname):
91 for binary in recs.Binaries:
92 pkgnames.add(binary)
93 return pkgnames
94
95def expand_src_pkgname(pkgname):
96 """ Expand a package name if it is prefixed with src.
97
98 If the package name is prefixed with src it will be expanded
99 to a list of binary package names. Otherwise the original
100 package name will be returned.
101
102 :param pkgname: The package name (that may include src:prefix).
103 :return: A list of binary package names (the list may be one element long).
104 """
105 if not pkgname.startswith("src:"):
106 return [pkgname]
107 return get_binaries_for_source_pkg(pkgname.split("src:")[1])
108
109def create_and_update_deb_src_source_list(distroseries):
110 """ Create sources.list and update cache.
111
112 This creates a sources.list file with deb-src entries for a given
113 distroseries and apt.Cache.update() to make sure the data is up-to-date.
114 :param distro: The code name of the distribution series (e.g. lucid).
115 :return: None
116 :raises: IOError: When cache update fails.
117 """
118 # apt root dir
119 rootdir="./aptroot.%s" % distroseries
120 sources_list_dir = os.path.join(rootdir, "etc","apt")
121 if not os.path.exists(sources_list_dir):
122 os.makedirs(sources_list_dir)
123 sources_list = open(os.path.join(sources_list_dir, "sources.list"),"w")
124 for pocket in [
125 "%s" % distroseries,
126 "%s-updates" % distroseries,
127 "%s-security" % distroseries]:
128 sources_list.write(
129 "deb-src %s %s main restricted\n" % (
130 ARCHIVE_ROOT, pocket))
131 sources_list.write(
132 "deb %s %s main restricted\n" % (
133 ARCHIVE_ROOT, pocket))
134 sources_list.close()
135 # create required dirs/files for apt.Cache(rootdir) to work on older
136 # versions of python-apt. once lucid is used it can be removed
137 for d in ["var/lib/dpkg",
138 "var/cache/apt/archives/partial",
139 "var/lib/apt/lists/partial"]:
140 if not os.path.exists(os.path.join(rootdir,d)):
141 os.makedirs(os.path.join(rootdir,d))
142 if not os.path.exists(os.path.join(rootdir,"var/lib/dpkg/status")):
143 open(os.path.join(rootdir,"var/lib/dpkg/status"),"w")
144 # open cache with our just prepared rootdir
145 cache = apt.Cache(rootdir=rootdir)
146 try:
147 cache.update(apt.progress.FetchProgress())
148 except SystemError:
149 logging.exception("cache.update() failed")
150
151def get_structure(distroname, version):
152 """ Get structure file conent for named distro and distro version.
153
154 :param name: Name of the distribution (e.g. kubuntu, ubuntu, xubuntu).
155 :param version: Code name of the distribution version (e.g. lucid).
156 :return: List of strings with the structure file content
157 """
158 f = urllib2.urlopen("%s/%s.%s/structure" % (BASE_URL, distroname, version))
159 structure = f.readlines()
160 f.close()
161 return structure
162
163def expand_seeds(structure, seedname):
164 """ Expand seed by its dependencies using the strucure file.
165
166 :param structure: The content of the STRUCTURE file as string list.
167 :param seedname: The name of the seed as string that needs to be expanded.
168 :return: a set() for the seed dependencies (excluding the original seedname)
169 """
170 seeds = []
171 for line in structure:
172 if line.startswith("%s:" % seedname):
173 seeds += line.split(":")[1].split()
174 for seed in seeds:
175 seeds += expand_seeds(structure, seed)
176 return set(seeds)
177
178def get_packages_for_seeds(name, distro, seeds):
179 """
180 get packages for the given name (e.g. ubuntu) and distro release
181 (e.g. lucid) that are in the given list of seeds
182 returns a set() of package names
183 """
184 pkgs_in_seeds = {}
185 for bseed in seeds:
186 for seed in [bseed]: #, bseed+".build-depends", bseed+".seed"]:
187 pkgs_in_seeds[seed] = set()
188 seedurl = "%s/%s.%s/%s" % (BASE_URL,name, distro, seed)
189 logging.debug("looking for '%s'" % seedurl)
190 try:
191 f = urllib2.urlopen(seedurl)
192 for line in f:
193 # ignore lines that are not a package name (headers etc)
194 if line[0] < 'a' or line[0] > 'z':
195 continue
196 # lines are (package,source,why,maintainer,size,inst-size)
197 if options.source_packages:
198 pkgname = line.split("|")[1]
199 else:
200 pkgname = line.split("|")[0]
201 pkgs_in_seeds[seed].add(pkgname.strip())
202 f.close()
203 except Exception, e:
204 logging.error("seed %s failed (%s)" % (seedurl, e))
205 return pkgs_in_seeds
206
207def what_seeds(pkgname, seeds):
208 in_seeds = set()
209 for s in seeds:
210 if pkgname in seeds[s]:
211 in_seeds.add(s)
212 return in_seeds
213
214def compare_support_level(x, y):
215 """
216 compare two support level strings of the form 18m, 3y etc
217 :parm x: the first support level
218 :parm y: the second support level
219 :return: negative if x < y, zero if x==y, positive if x > y
220 """
221 def support_to_int(support_time):
222 """
223 helper that takes a support time string and converts it to
224 a integer for cmp()
225 """
226 # allow strings like "5y (kubuntu-common)
227 x = support_time.split()[0]
228 if x.endswith("y"):
229 return 12 * int(x[0:-1])
230 elif x.endswith("m"):
231 return int(x[0:-1])
232 else:
233 raise ValueError("support time '%s' has to end with y or m" % x)
234 return cmp(support_to_int(x), support_to_int(y))
235
236def get_packages_support_time(structure, name, pkg_support_time, support_timeframe_list):
237 """
238 input a structure file and a list of pair<timeframe, seedlist>
239 return a dict of pkgnames -> support timeframe string
240 """
241 for (timeframe, seedlist) in support_timeframe_list:
242 expanded = set()
243 for s in seedlist:
244 expanded.add(s)
245 expanded |= expand_seeds(structure, s)
246 pkgs_in_seeds = get_packages_for_seeds(name, distro, expanded)
247 for seed in pkgs_in_seeds:
248 for pkg in pkgs_in_seeds[seed]:
249 if not pkg in pkg_support_time:
250 pkg_support_time[pkg] = timeframe
251 else:
252 old_timeframe = pkg_support_time[pkg]
253 if compare_support_level(old_timeframe, timeframe) < 0:
254 logging.debug("overwriting %s from %s to %s" % (
255 pkg, old_timeframe, timeframe))
256 pkg_support_time[pkg] = timeframe
257 if options.with_seeds:
258 pkg_support_time[pkg] += " (%s)" % ", ".join(what_seeds(pkg, pkgs_in_seeds))
259
260
261 return pkg_support_time
262
263if __name__ == "__main__":
264 parser = OptionParser()
265 parser.add_option("--with-seeds", "", default=False,
266 action="store_true",
267 help="add seed(s) of the package that are responsible for the maintaince time")
268 parser.add_option("--source-packages", "", default=False,
269 action="store_true",
270 help="show as source pkgs")
271 parser.add_option("--hints-file", "", default=None,
272 help="use diffenrt use hints file location")
273 (options, args) = parser.parse_args()
274
275 # init
276 if len(args) > 0:
277 distro = args[0]
278 if distro[0] < 'h':
279 print "ERROR: only hardy or later is supported"
280 sys.exit(1)
281 else:
282 distro = "lucid"
283
284 # make sure our deb-src information is up-to-date
285 create_and_update_deb_src_source_list(distro)
286
287 if options.hints_file:
288 hints_file = options.hints_file
289 (schema, netloc, path, query, fragment) = urlparse.urlsplit(hints_file)
290 if not schema:
291 hints_file = "file:%s" % path
292 else:
293 hints_file = HINTS_DIR_URL % distro
294
295 # go over the distros we need to check
296 pkg_support_time = {}
297 for (name, lts_supported) in DISTRO_NAMES_AND_LTS_SUPPORT:
298
299 # get basic structure file
300 structure = get_structure(name, distro)
301
302 # get dicts of pkgname -> support timeframe string
303 support_timeframe = SUPPORT_TIMEFRAME
304 if lts_supported and distro in LTS_RELEASES:
305 support_timeframe = SUPPORT_TIMEFRAME_LTS
306 else:
307 support_timeframe = SUPPORT_TIMEFRAME
308 get_packages_support_time(structure, name, pkg_support_time, support_timeframe)
309
310 # now go over the bits in main that we have not seen (because
311 # they are not in any seed and got added manually into "main"
312 for arch in PRIMARY_ARCHES:
313 rootdir="./aptroot.%s" % distro
314 apt_pkg.Config.Set("APT::Architecture", arch)
315 cache = apt.Cache(rootdir=rootdir)
316 try:
317 cache.update(apt.progress.FetchProgress())
318 except SystemError:
319 logging.exception("cache.update() failed")
320 cache.open(apt.progress.OpProgress())
321 for pkg in cache:
322 if not pkg.name in pkg_support_time:
323 pkg_support_time[pkg.name] = support_timeframe[-1][0]
324 logging.warn("add package in main but not in seeds %s with %s" %
325 (pkg.name, pkg_support_time[pkg.name]))
326
327 # now check the hints file that is used to overwrite
328 # the default seeds
329 try:
330 for line in urllib2.urlopen(hints_file):
331 line = line.strip()
332 if not line or line.startswith("#"):
333 continue
334 try:
335 (raw_pkgname, support_time) = line.split()
336 for pkgname in expand_src_pkgname(raw_pkgname):
337 if support_time == 'unsupported':
338 try:
339 del pkg_support_time[pkgname]
340 sys.stderr.write("hints-file: marking %s unsupported\n" % pkgname)
341 except KeyError:
342 pass
343 else:
344 if pkg_support_time.get(pkgname) != support_time:
345 sys.stderr.write(
346 "hints-file: changing %s from %s to %s\n" % (
347 pkgname, pkg_support_time.get(pkgname),
348 support_time))
349 pkg_support_time[pkgname] = support_time
350 except:
351 logging.exception("can not parse line '%s'" % line)
352 except urllib2.HTTPError, e:
353 if e.getcode() != 404:
354 raise
355 sys.stderr.write("hints-file: %s gave 404 error\n" % hints_file)
356
357 # output suitable for the extra-override file
358 for pkgname in sorted(pkg_support_time.keys()):
359 # special case, the hints file may contain overrides that
360 # are arch-specific (like zsh-doc/armel)
361 if "/" in pkgname:
362 print "%s %s %s" % (
363 pkgname, SUPPORT_TAG, pkg_support_time[pkgname])
364 else:
365 # go over the supported arches, they are divided in
366 # first-class (PRIMARY) and second-class with different
367 # support levels
368 for arch in SUPPORTED_ARCHES:
369 # ensure we do not overwrite arch-specific overwrites
370 pkgname_and_arch = "%s/%s" % (pkgname, arch)
371 if pkgname_and_arch in pkg_support_time:
372 break
373 if arch in PRIMARY_ARCHES:
374 # arch with full LTS support
375 print "%s %s %s" % (
376 pkgname_and_arch, SUPPORT_TAG, pkg_support_time[pkgname])
377 else:
378 # not a LTS supported architecture, gets only regular
379 # support_timeframe
380 print "%s %s %s" % (
381 pkgname_and_arch, SUPPORT_TAG, SUPPORT_TIMEFRAME[0][0])
382
0383
=== modified file 'cronscripts/reclaimbranchspace.py'
--- cronscripts/reclaimbranchspace.py 2009-09-03 20:06:45 +0000
+++ cronscripts/reclaimbranchspace.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/rosetta-approve-imports.py'
--- cronscripts/rosetta-approve-imports.py 2009-09-26 06:21:08 +0000
+++ cronscripts/rosetta-approve-imports.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#! /usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/rosetta-branches.py'
--- cronscripts/rosetta-branches.py 2009-09-03 20:29:25 +0000
+++ cronscripts/rosetta-branches.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -17,7 +17,7 @@
17from zope.component import getUtility17from zope.component import getUtility
1818
19from canonical.config import config19from canonical.config import config
20from lp.codehosting.vfs.branchfs import get_scanner_server20from lp.codehosting.vfs.branchfs import get_ro_server
21from lp.services.job.runner import JobRunner21from lp.services.job.runner import JobRunner
22from lp.code.interfaces.branchjob import IRosettaUploadJobSource22from lp.code.interfaces.branchjob import IRosettaUploadJobSource
23from lp.services.scripts.base import LaunchpadCronScript23from lp.services.scripts.base import LaunchpadCronScript
@@ -31,12 +31,12 @@
31 globalErrorUtility.configure('rosettabranches')31 globalErrorUtility.configure('rosettabranches')
32 runner = JobRunner.fromReady(32 runner = JobRunner.fromReady(
33 getUtility(IRosettaUploadJobSource), self.logger)33 getUtility(IRosettaUploadJobSource), self.logger)
34 server = get_scanner_server()34 server = get_ro_server()
35 server.setUp()35 server.start_server()
36 try:36 try:
37 runner.runAll()37 runner.runAll()
38 finally:38 finally:
39 server.tearDown()39 server.stop_server()
40 self.logger.info('Ran %d RosettaBranchJobs.',40 self.logger.info('Ran %d RosettaBranchJobs.',
41 len(runner.completed_jobs))41 len(runner.completed_jobs))
4242
4343
=== modified file 'cronscripts/rosetta-export-queue.py'
--- cronscripts/rosetta-export-queue.py 2009-07-17 00:26:05 +0000
+++ cronscripts/rosetta-export-queue.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/rosetta-pofile-stats-daily.py'
--- cronscripts/rosetta-pofile-stats-daily.py 2009-08-07 17:58:19 +0000
+++ cronscripts/rosetta-pofile-stats-daily.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/rosetta-pofile-stats.py'
--- cronscripts/rosetta-pofile-stats.py 2009-08-06 12:30:58 +0000
+++ cronscripts/rosetta-pofile-stats.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/rosetta-poimport.py'
--- cronscripts/rosetta-poimport.py 2009-09-29 15:33:30 +0000
+++ cronscripts/rosetta-poimport.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== added file 'cronscripts/scan_branches.py'
--- cronscripts/scan_branches.py 1970-01-01 00:00:00 +0000
+++ cronscripts/scan_branches.py 2010-05-05 01:58:48 +0000
@@ -0,0 +1,25 @@
1#!/usr/bin/python2.5 -S
2#
3# Copyright 2010 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).
5
6"""Scan branches for new revisions."""
7
8__metaclass__ = type
9
10import _pythonpath
11
12from lp.services.job.runner import JobCronScript
13from lp.code.interfaces.branchjob import IBranchScanJobSource
14
15
16class RunScanBranches(JobCronScript):
17 """Run BranchScanJob jobs."""
18
19 config_name = 'branchscanner'
20 source_interface = IBranchScanJobSource
21
22
23if __name__ == '__main__':
24 script = RunScanBranches()
25 script.lock_and_run()
026
=== modified file 'cronscripts/send-bug-notifications.py'
--- cronscripts/send-bug-notifications.py 2009-06-24 20:52:01 +0000
+++ cronscripts/send-bug-notifications.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/send-person-notifications.py'
--- cronscripts/send-person-notifications.py 2009-06-24 20:52:01 +0000
+++ cronscripts/send-person-notifications.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -14,15 +14,11 @@
14__metaclass__ = type14__metaclass__ = type
1515
16import _pythonpath16import _pythonpath
17from datetime import timedelta, datetime
18import pytz
19
20from zope.component import getUtility
2117
22from canonical.config import config18from canonical.config import config
23from canonical.launchpad.interfaces.personnotification import (19
24 IPersonNotificationSet)
25from lp.services.scripts.base import LaunchpadCronScript20from lp.services.scripts.base import LaunchpadCronScript
21from lp.registry.scripts.personnotification import PersonNotificationManager
2622
2723
28class SendPersonNotifications(LaunchpadCronScript):24class SendPersonNotifications(LaunchpadCronScript):
@@ -36,39 +32,9 @@
36 """32 """
3733
38 def main(self):34 def main(self):
39 notifications_sent = False35 manager = PersonNotificationManager(self.txn, self.logger)
40 notification_set = getUtility(IPersonNotificationSet)36 unsent_notifications = manager.sendNotifications()
41 pending_notifications = notification_set.getNotificationsToSend()37 manager.purgeNotifications(unsent_notifications)
42 self.logger.info(
43 '%d notification(s) to send.' % pending_notifications.count())
44 for notification in pending_notifications:
45 person = notification.person
46 self.logger.info(
47 "Sending notification to %s <%s>."
48 % (person.name, person.preferredemail.email))
49 notification.send()
50 notifications_sent = True
51 # Commit after each email sent, so that we won't re-mail the
52 # notifications in case of something going wrong in the middle.
53 self.txn.commit()
54
55 if not notifications_sent:
56 self.logger.debug("No notifications were sent.")
57
58 # Delete PersonNotifications that are older than the retention
59 # limit set in the configuration.
60 retained_days = timedelta(
61 days=int(config.person_notification.retained_days))
62 time_limit = (datetime.now(pytz.timezone('UTC')) - retained_days)
63 to_delete = notification_set.getNotificationsOlderThan(time_limit)
64 if to_delete.count():
65 self.logger.info(
66 "Notification retention limit is %s." % retained_days)
67 self.logger.info(
68 "Deleting %d old notification(s)." % to_delete.count())
69 for notification in to_delete:
70 notification.destroySelf()
71 self.txn.commit()
7238
7339
74if __name__ == '__main__':40if __name__ == '__main__':
7541
=== modified file 'cronscripts/sendbranchmail.py'
--- cronscripts/sendbranchmail.py 2009-09-03 19:25:57 +0000
+++ cronscripts/sendbranchmail.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -16,7 +16,7 @@
16from zope.component import getUtility16from zope.component import getUtility
1717
18from canonical.config import config18from canonical.config import config
19from lp.codehosting.vfs import get_scanner_server19from lp.codehosting.vfs import get_ro_server
20from lp.services.job.runner import JobRunner20from lp.services.job.runner import JobRunner
21from lp.code.interfaces.branchjob import (21from lp.code.interfaces.branchjob import (
22 IRevisionMailJobSource, IRevisionsAddedJobSource)22 IRevisionMailJobSource, IRevisionsAddedJobSource)
@@ -32,12 +32,12 @@
32 jobs = list(getUtility(IRevisionMailJobSource).iterReady())32 jobs = list(getUtility(IRevisionMailJobSource).iterReady())
33 jobs.extend(getUtility(IRevisionsAddedJobSource).iterReady())33 jobs.extend(getUtility(IRevisionsAddedJobSource).iterReady())
34 runner = JobRunner(jobs, self.logger)34 runner = JobRunner(jobs, self.logger)
35 server = get_scanner_server()35 server = get_ro_server()
36 server.setUp()36 server.start_server()
37 try:37 try:
38 runner.runAll()38 runner.runAll()
39 finally:39 finally:
40 server.tearDown()40 server.stop_server()
41 self.logger.info(41 self.logger.info(
42 'Ran %d RevisionMailJobs.' % len(runner.completed_jobs))42 'Ran %d RevisionMailJobs.' % len(runner.completed_jobs))
4343
4444
=== modified file 'cronscripts/supermirror-pull.py'
--- cronscripts/supermirror-pull.py 2009-09-29 00:26:59 +0000
+++ cronscripts/supermirror-pull.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -11,10 +11,10 @@
11from twisted.internet import defer, reactor11from twisted.internet import defer, reactor
12from twisted.python import log as tplog12from twisted.python import log as tplog
1313
14from lp.codehosting.puller import mirror, scheduler
15from canonical.config import config14from canonical.config import config
16from canonical.launchpad.scripts import logger_options15from canonical.launchpad.scripts import logger_options
17from canonical.twistedsupport.loggingsupport import (16from lp.codehosting.puller import mirror, scheduler
17from lp.services.twistedsupport.loggingsupport import (
18 LoggingProxy, set_up_logging_for_script)18 LoggingProxy, set_up_logging_for_script)
1919
20def clean_shutdown(ignored):20def clean_shutdown(ignored):
@@ -38,12 +38,14 @@
38if __name__ == '__main__':38if __name__ == '__main__':
39 parser = OptionParser()39 parser = OptionParser()
40 logger_options(parser)40 logger_options(parser)
41 parser.add_option('--branch-type', action='append', default=[])
41 (options, arguments) = parser.parse_args()42 (options, arguments) = parser.parse_args()
42 if arguments:43 if arguments:
43 parser.error("Unhandled arguments %s" % repr(arguments))44 parser.error("Unhandled arguments %s" % repr(arguments))
44 log = set_up_logging_for_script(options, 'supermirror_puller')45 log = set_up_logging_for_script(options, 'supermirror_puller')
45 manager = scheduler.JobScheduler(46 manager = scheduler.JobScheduler(
46 LoggingProxy(config.codehosting.branch_puller_endpoint, log), log)47 LoggingProxy(config.codehosting.codehosting_endpoint, log), log,
48 options.branch_type)
4749
48 reactor.callWhenRunning(run_mirror, log, manager)50 reactor.callWhenRunning(run_mirror, log, manager)
49 reactor.run()51 reactor.run()
5052
=== modified file 'cronscripts/translations-export-to-branch.py'
--- cronscripts/translations-export-to-branch.py 2009-07-17 18:46:25 +0000
+++ cronscripts/translations-export-to-branch.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2# pylint: disable-msg=W04032# pylint: disable-msg=W0403
3#3#
4# Copyright 2009 Canonical Ltd. This software is licensed under the4# Copyright 2009 Canonical Ltd. This software is licensed under the
55
=== modified file 'cronscripts/update-bugtask-targetnamecaches.py'
--- cronscripts/update-bugtask-targetnamecaches.py 2009-06-24 20:52:01 +0000
+++ cronscripts/update-bugtask-targetnamecaches.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/update-cve.py'
--- cronscripts/update-cve.py 2009-06-24 20:52:01 +0000
+++ cronscripts/update-cve.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/update-debwatches.py'
--- cronscripts/update-debwatches.py 2009-06-24 20:52:01 +0000
+++ cronscripts/update-debwatches.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -6,11 +6,11 @@
6# This script runs through the set of Debbugs watches, and tries to6# This script runs through the set of Debbugs watches, and tries to
7# syncronise each of those to the malone bug which is watching it.7# syncronise each of those to the malone bug which is watching it.
88
9import _pythonpath
9import os10import os
10import sys11import sys
11import email12import email
12import logging13import logging
13import _pythonpath
1414
15# zope bits15# zope bits
16from zope.component import getUtility16from zope.component import getUtility
1717
=== modified file 'cronscripts/update-pkgcache.py'
--- cronscripts/update-pkgcache.py 2009-06-24 20:52:01 +0000
+++ cronscripts/update-pkgcache.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -47,7 +47,7 @@
47 PPA archives caches are consolidated in a Archive row to optimize47 PPA archives caches are consolidated in a Archive row to optimize
48 searches across PPAs.48 searches across PPAs.
49 """49 """
50 for distroseries in distribution.serieses:50 for distroseries in distribution.series:
51 self.updateDistroSeriesCache(distroseries, archive)51 self.updateDistroSeriesCache(distroseries, archive)
5252
53 distribution.removeOldCacheItems(archive, log=self.logger)53 distribution.removeOldCacheItems(archive, log=self.logger)
@@ -101,6 +101,6 @@
101101
102if __name__ == '__main__':102if __name__ == '__main__':
103 script = PackageCacheUpdater(103 script = PackageCacheUpdater(
104 'update-cache', dbuser=config.statistician.dbuser)104 'update-cache', dbuser="update-pkg-cache")
105 script.lock_and_run()105 script.lock_and_run()
106106
107107
=== modified file 'cronscripts/update-remote-product.py'
--- cronscripts/update-remote-product.py 2009-06-24 20:52:01 +0000
+++ cronscripts/update-remote-product.py 2010-05-05 01:58:48 +0000
@@ -1,14 +1,14 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
6"""Cron job to update Product.remote_product using bug watch information. """
7
6# pylint: disable-msg=W04038# pylint: disable-msg=W0403
79import _pythonpath
8"""Cron job to update Product.remote_product using bug watch information. """
910
10import time11import time
11import _pythonpath
1212
13from canonical.config import config13from canonical.config import config
14from lp.services.scripts.base import LaunchpadCronScript14from lp.services.scripts.base import LaunchpadCronScript
1515
=== modified file 'cronscripts/update-sourceforge-remote-products.py'
--- cronscripts/update-sourceforge-remote-products.py 2009-06-24 20:52:01 +0000
+++ cronscripts/update-sourceforge-remote-products.py 2010-05-05 01:58:48 +0000
@@ -1,14 +1,14 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
6"""Cron job to update remote_products using SourceForge project data."""
7
6# pylint: disable-msg=W04038# pylint: disable-msg=W0403
79import _pythonpath
8"""Cron job to update remote_products using SourceForge project data."""
910
10import time11import time
11import _pythonpath
1212
13from canonical.config import config13from canonical.config import config
14from lp.services.scripts.base import LaunchpadCronScript14from lp.services.scripts.base import LaunchpadCronScript
1515
=== modified file 'cronscripts/update-standing.py'
--- cronscripts/update-standing.py 2009-06-24 20:52:01 +0000
+++ cronscripts/update-standing.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
=== modified file 'cronscripts/update-stats.py'
--- cronscripts/update-stats.py 2009-06-24 20:52:01 +0000
+++ cronscripts/update-stats.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -28,7 +28,7 @@
28 # objects are responsible for committing.28 # objects are responsible for committing.
29 distroset = getUtility(IDistributionSet)29 distroset = getUtility(IDistributionSet)
30 for distro in distroset:30 for distro in distroset:
31 for distroseries in distro.serieses:31 for distroseries in distro.series:
32 distroseries.updateStatistics(self.txn)32 distroseries.updateStatistics(self.txn)
3333
34 launchpad_stats = getUtility(ILaunchpadStatisticSet)34 launchpad_stats = getUtility(ILaunchpadStatisticSet)
3535
=== removed file 'cronscripts/update_preview_diffs.py'
--- cronscripts/update_preview_diffs.py 2009-09-01 19:00:46 +0000
+++ cronscripts/update_preview_diffs.py 1970-01-01 00:00:00 +0000
@@ -1,34 +0,0 @@
1#!/usr/bin/python2.4
2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).
5
6# pylint: disable-msg=W0403
7
8"""Update or create previews diffs for branch merge proposals."""
9
10__metaclass__ = type
11
12import _pythonpath
13
14from lp.codehosting.vfs import get_scanner_server
15from lp.services.job.runner import JobCronScript
16from lp.code.interfaces.branchmergeproposal import (
17 IUpdatePreviewDiffJobSource,)
18
19
20class RunUpdatePreviewDiffJobs(JobCronScript):
21 """Run UpdatePreviewDiff jobs."""
22
23 config_name = 'update_preview_diffs'
24 source_interface = IUpdatePreviewDiffJobSource
25
26 def setUp(self):
27 server = get_scanner_server()
28 server.setUp()
29 return [server.tearDown]
30
31
32if __name__ == '__main__':
33 script = RunUpdatePreviewDiffJobs()
34 script.lock_and_run()
350
=== added file 'cronscripts/upgrade_branches.py'
--- cronscripts/upgrade_branches.py 1970-01-01 00:00:00 +0000
+++ cronscripts/upgrade_branches.py 2010-05-05 01:58:48 +0000
@@ -0,0 +1,25 @@
1#!/usr/bin/python2.5 -S
2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).
5
6"""Upgrade branches to the most recent format."""
7
8__metaclass__ = type
9
10import _pythonpath
11
12from lp.services.job.runner import JobCronScript
13from lp.code.interfaces.branchjob import IBranchUpgradeJobSource
14
15
16class RunUpgradeBranches(JobCronScript):
17 """Run UpgradeBranchJob jobs."""
18
19 config_name = 'upgrade_branches'
20 source_interface = IBranchUpgradeJobSource
21
22
23if __name__ == '__main__':
24 script = RunUpgradeBranches()
25 script.lock_and_run()
026
=== added symlink 'daemons/_pythonpath.py'
=== target is u'../_pythonpath.py'
=== removed file 'daemons/buildd-sequencer.tac'
--- daemons/buildd-sequencer.tac 2009-06-24 20:55:31 +0000
+++ daemons/buildd-sequencer.tac 1970-01-01 00:00:00 +0000
@@ -1,31 +0,0 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4# Twisted Application Configuration file.
5# Use with "twistd -y <file.tac>", e.g. "twistd -noy server.tac"
6
7from twisted.application import service
8
9from canonical.buildd.sequencer import BuildSequencer
10
11# Construct the application
12application = service.Application("BuildSequencer")
13
14class BuildSequencerService(service.Service):
15 def __init__(self, buildSequencer):
16 self.buildSequencer = buildSequencer
17
18 def startService(self):
19 # Kick everything off...
20 self.buildSequencer.scheduleCallback()
21
22
23# Construct the sequencer. It will automatically schedule the first job.
24bseq = BuildSequencer()
25# Make a service out of the sequencer
26bserv = BuildSequencerService(bseq)
27
28# Activate the service
29BuildSequencerService(bseq).setServiceParent(application)
30
31# Falling off the end here passes into twisted's reactor.
320
=== modified file 'daemons/buildd-slave.tac'
--- daemons/buildd-slave.tac 2009-06-24 20:55:31 +0000
+++ daemons/buildd-slave.tac 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the1# Copyright 2009, 2010 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4# Author: Daniel Silverstone <daniel.silverstone@canonical.com>4# Author: Daniel Silverstone <daniel.silverstone@canonical.com>
@@ -8,7 +8,11 @@
8# passed through to the twistd log too. this could get dangerous/big8# passed through to the twistd log too. this could get dangerous/big
99
10from twisted.application import service, strports10from twisted.application import service, strports
11from canonical.buildd import XMLRPCBuildDSlave, DebianBuildManager11from canonical.buildd import XMLRPCBuildDSlave
12from canonical.buildd.binarypackage import BinaryPackageBuildManager
13from canonical.buildd.sourcepackagerecipe import (
14 SourcePackageRecipeBuildManager)
15from canonical.buildd.translationtemplates import TranslationTemplatesBuildManager
12from canonical.launchpad.daemons import tachandler16from canonical.launchpad.daemons import tachandler
1317
14from twisted.web import server, resource, static18from twisted.web import server, resource, static
@@ -22,7 +26,11 @@
22conf.read(conffile)26conf.read(conffile)
23slave = XMLRPCBuildDSlave(conf)27slave = XMLRPCBuildDSlave(conf)
2428
25slave.registerBuilder(DebianBuildManager,"debian")29# 'debian' is the old name. It remains here for compatibility.
30slave.registerBuilder(BinaryPackageBuildManager, "debian")
31slave.registerBuilder(BinaryPackageBuildManager, "binarypackage")
32slave.registerBuilder(SourcePackageRecipeBuildManager, "sourcepackagerecipe")
33slave.registerBuilder(TranslationTemplatesBuildManager, 'translation-templates')
2634
27application = service.Application('BuildDSlave')35application = service.Application('BuildDSlave')
28builddslaveService = service.IServiceCollection(application)36builddslaveService = service.IServiceCollection(application)
@@ -43,5 +51,5 @@
43#51#
44# python52# python
45# import xmlrpclib53# import xmlrpclib
46# s = xmlrpclib.Server("http://localhost:8221/")54# s = xmlrpclib.ServerProxy("http://localhost:8221/rpc")
47# s.echo("Hello World")55# s.echo("Hello World")
4856
=== added file 'daemons/cache-database-replication-lag.py'
--- daemons/cache-database-replication-lag.py 1970-01-01 00:00:00 +0000
+++ daemons/cache-database-replication-lag.py 2010-05-05 01:58:48 +0000
@@ -0,0 +1,53 @@
1#!/usr/bin/python2.5 -S
2#
3# Copyright 2010 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).
5
6"""Calculate database replication lag and cache it."""
7
8__metaclass__ = type
9__all__ = []
10
11import _pythonpath
12
13import sys
14import time
15
16import psycopg2
17
18from canonical.database.sqlbase import connect, ISOLATION_LEVEL_AUTOCOMMIT
19from canonical.launchpad.scripts import db_options, logger
20from lp.scripts.helpers import LPOptionParser
21
22
23def main(args=None):
24 parser = LPOptionParser()
25 db_options(parser)
26 parser.add_option(
27 "-s", "--sleep", dest="sleep", type="int", default=5,
28 metavar="SECS", help="Wait SECS seconds between refreshes.")
29
30 (options, args) = parser.parse_args(args)
31 if len(args) != 0:
32 parser.error("Too many arguments.")
33
34 log = logger(options)
35
36 while True:
37 try:
38 con = connect(user="lagmon", isolation=ISOLATION_LEVEL_AUTOCOMMIT)
39 cur = con.cursor()
40 while True:
41 cur.execute("SELECT update_replication_lag_cache()")
42 if cur.fetchone()[0]:
43 log.info("Updated.")
44 else:
45 log.error("update_replication_lag_cache() failed.")
46 time.sleep(options.sleep)
47 except psycopg2.Error, x:
48 log.error("%s. Retrying.", str(x).strip())
49 time.sleep(options.sleep)
50
51
52if __name__ == '__main__':
53 sys.exit(main())
054
=== modified file 'daemons/librarian.tac'
--- daemons/librarian.tac 2009-06-24 20:55:31 +0000
+++ daemons/librarian.tac 2010-05-05 01:58:48 +0000
@@ -4,6 +4,10 @@
4# Twisted Application Configuration file.4# Twisted Application Configuration file.
5# Use with "twistd2.4 -y <file.tac>", e.g. "twistd -noy server.tac"5# Use with "twistd2.4 -y <file.tac>", e.g. "twistd -noy server.tac"
66
7import signal
8
9from meliae import scanner
10
7from twisted.application import service, strports11from twisted.application import service, strports
8from twisted.web import server12from twisted.web import server
913
@@ -11,6 +15,7 @@
11from canonical.launchpad.daemons import tachandler15from canonical.launchpad.daemons import tachandler
12from canonical.launchpad.scripts import execute_zcml_for_scripts16from canonical.launchpad.scripts import execute_zcml_for_scripts
1317
18from canonical.librarian.interfaces import DUMP_FILE, SIGDUMPMEM
14from canonical.librarian.libraryprotocol import FileUploadFactory19from canonical.librarian.libraryprotocol import FileUploadFactory
15from canonical.librarian import storage, db20from canonical.librarian import storage, db
16from canonical.librarian import web as fatweb21from canonical.librarian import web as fatweb
@@ -64,3 +69,9 @@
64webPort = config.librarian.restricted_download_port69webPort = config.librarian.restricted_download_port
65uploadPort = config.librarian.restricted_upload_port70uploadPort = config.librarian.restricted_upload_port
66setUpListener(uploadPort, webPort, restricted=True)71setUpListener(uploadPort, webPort, restricted=True)
72
73# Setup a signal handler to dump the process' memory upon 'kill -44'.
74def sigdumpmem_handler(signum, frame):
75 scanner.dump_all_objects(DUMP_FILE)
76
77signal.signal(SIGDUMPMEM, sigdumpmem_handler)
6778
=== modified file 'daemons/poppy-upload.py'
--- daemons/poppy-upload.py 2009-06-30 21:26:26 +0000
+++ daemons/poppy-upload.py 2010-05-05 01:58:48 +0000
@@ -1,57 +1,10 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
55
6import sys6import sys
7import logging7from lp.poppy.daemon import main
8import optparse
9
10from canonical.poppy.server import run_server
11from lp.archiveuploader.poppyinterface import PoppyInterface
12from canonical.launchpad.scripts import logger, logger_options
13
14
15def main():
16
17 parser = optparse.OptionParser()
18 logger_options(parser)
19
20 parser.add_option("--cmd", action="store", metavar="CMD",
21 help="Run CMD after each upload completion")
22
23 parser.add_option("--allow-user", action="store", metavar="USER",
24 default='ubuntu',
25 help="Username allowed to log in.")
26
27 parser.add_option("--permissions", action="store", metavar="PERMS",
28 default='g+rwxs',
29 help="Permissions to chmod the targetfsroot with "
30 "before letting go of the directory.")
31
32 options, args = parser.parse_args()
33
34 log = logger(options, "poppy-upload")
35
36 if len(args) != 2:
37 print "usage: poppy-upload.py rootuploaddirectory port"
38 return 1
39
40 root, port = args
41 # host = "127.0.0.1"
42 # host = "82.211.81.167" # Drescher's public IP
43 host = "0.0.0.0"
44 ident = "lucille upload server"
45 numthreads = 4
46
47 iface = PoppyInterface(root, log, allow_user=options.allow_user,
48 cmd=options.cmd,
49 perms=options.permissions)
50
51 run_server(host, int(port), ident, numthreads,
52 iface.new_client_hook, iface.client_done_hook,
53 iface.auth_verify_hook)
54 return 0
558
56if __name__ == '__main__':9if __name__ == '__main__':
57 sys.exit(main())10 sys.exit(main())
5811
=== modified file 'daemons/sftp.tac'
--- daemons/sftp.tac 2009-06-24 20:55:31 +0000
+++ daemons/sftp.tac 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the1# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4# This is a Twisted application config file. To run, use:4# This is a Twisted application config file. To run, use:
@@ -7,13 +7,28 @@
77
8from twisted.application import service8from twisted.application import service
99
10from canonical.config import config
10from canonical.launchpad.daemons import tachandler11from canonical.launchpad.daemons import tachandler
11from lp.codehosting.sshserver.service import SSHService12
1213from lp.codehosting.sshserver.daemon import (
1314 ACCESS_LOG_NAME, get_key_path, LOG_NAME, make_portal, OOPS_CONFIG_SECTION,
14# Construct an Application that includes a supermirror SFTP service. 15 PRIVATE_KEY_FILE, PUBLIC_KEY_FILE)
16from lp.services.sshserver.service import SSHService
17
18
19# Construct an Application that has the codehosting SSH server.
15application = service.Application('sftponly')20application = service.Application('sftponly')
16svc = SSHService()21svc = SSHService(
22 portal=make_portal(),
23 private_key_path=get_key_path(PRIVATE_KEY_FILE),
24 public_key_path=get_key_path(PUBLIC_KEY_FILE),
25 oops_configuration=OOPS_CONFIG_SECTION,
26 main_log=LOG_NAME,
27 access_log=ACCESS_LOG_NAME,
28 access_log_path=config.codehosting.access_log,
29 strport=config.codehosting.port,
30 idle_timeout=config.codehosting.idle_timeout,
31 banner=config.codehosting.banner)
17svc.setServiceParent(application)32svc.setServiceParent(application)
1833
19# Service that announces when the daemon is ready34# Service that announces when the daemon is ready
2035
=== modified file 'database/replication/Makefile'
--- database/replication/Makefile 2009-06-24 21:17:33 +0000
+++ database/replication/Makefile 2010-05-05 01:58:48 +0000
@@ -18,6 +18,11 @@
18# $ make stagingsetup STAGING_CONFIG=dev-staging STAGING_DUMP=launchpad.dump18# $ make stagingsetup STAGING_CONFIG=dev-staging STAGING_DUMP=launchpad.dump
19# $ make stagingswitch STAGING_CONFIG=dev-staging19# $ make stagingswitch STAGING_CONFIG=dev-staging
20#20#
21# To restore a dogfood database:
22#
23# $ cd database/replication
24# $ make dogfood DOGFOOD_DBNAME=launchpad_dogfood DOGFOOD_DUMP=launchpad.dump
25#
2126
22# This used to be 10 seconds, so we always ran staging lagged to detect27# This used to be 10 seconds, so we always ran staging lagged to detect
23# replication glitches more easily. However, this does not play well28# replication glitches more easily. However, this does not play well
@@ -31,12 +36,24 @@
31STAGING_CONFIG=staging # For swapping fresh db into place.36STAGING_CONFIG=staging # For swapping fresh db into place.
32STAGING_DUMP=launchpad.dump # Dumpfile to build new staging from.37STAGING_DUMP=launchpad.dump # Dumpfile to build new staging from.
33STAGING_TABLESPACE=pg_default # 'pg_default' for default38STAGING_TABLESPACE=pg_default # 'pg_default' for default
39DOGFOOD_DBNAME=launchpad_dogfood
40DOGFOOD_DUMP=launchpad.dump
3441
35_CONFIG=overridden-on-command-line42_CONFIG=overridden-on-command-line
36_SLAVE_TABLESPACE=pg_default43_SLAVE_TABLESPACE=pg_default
3744
38PGMASSACRE=../../utilities/pgmassacre.py45PGMASSACRE=../../utilities/pgmassacre.py
3946
47CREATEDB_83=createdb --encoding=UTF8
48CREATEDB_84=createdb --encoding=UTF8 --locale=C --template=template0
49CREATEDB=${CREATEDB_83}
50
51# Turn off output silencing so we can see details of staging deployments.
52# Without the timestamps, we are unable to estimate production deployment
53# times.
54#SHHH=../../utilities/shhh.py
55SHHH=
56
40default:57default:
41 echo Usage: make [start|stop|restart]58 echo Usage: make [start|stop|restart]
4259
@@ -61,7 +78,7 @@
61 78
62 # Replicate it again, so we can test with multiple slaves.79 # Replicate it again, so we can test with multiple slaves.
63 -${PGMASSACRE} launchpad_dev_slave280 -${PGMASSACRE} launchpad_dev_slave2
64 createdb --encoding=UTF8 launchpad_dev_slave281 ${CREATEDB} launchpad_dev_slave2
65 LPCONFIG=${DEV_CONFIG} ./slon_ctl.py start \82 LPCONFIG=${DEV_CONFIG} ./slon_ctl.py start \
66 node3_node 'dbname=launchpad_dev_slave2 user=slony'83 node3_node 'dbname=launchpad_dev_slave2 user=slony'
67 LPCONFIG=${DEV_CONFIG} ./new-slave.py 3 launchpad_dev_slave284 LPCONFIG=${DEV_CONFIG} ./new-slave.py 3 launchpad_dev_slave2
@@ -81,13 +98,12 @@
81 _MASTER=lpmain_staging_new _SLAVE=lpmain_staging_slave_new \98 _MASTER=lpmain_staging_new _SLAVE=lpmain_staging_slave_new \
82 LAG="0 seconds"99 LAG="0 seconds"
83 # Create the DB with the desired default tablespace.100 # Create the DB with the desired default tablespace.
84 createdb --encoding UTF8 --tablespace ${STAGING_TABLESPACE} \101 ${CREATEDB} --tablespace ${STAGING_TABLESPACE} lpmain_staging_new
85 lpmain_staging_new102 # Restore the database. We need to restore permissions, despite
86 # Restore the DB schema. Don't restore permissions - it will blow103 # later running security.py, to pull in permissions granted on
87 # up when roles don't exist in this cluster, and we rebuild it later104 # production to users not maintained by security.py.
88 # with security.py anyway.
89 pg_restore --dbname=lpmain_staging_new \105 pg_restore --dbname=lpmain_staging_new \
90 --no-acl --exit-on-error ${STAGING_DUMP}106 --no-owner --exit-on-error ${STAGING_DUMP}
91 # Uninstall Slony-I if it is installed - a pg_dump of a DB with107 # Uninstall Slony-I if it is installed - a pg_dump of a DB with
92 # Slony-I installed isn't usable without this step.108 # Slony-I installed isn't usable without this step.
93 LPCONFIG=${NEW_STAGING_CONFIG} ./repair-restored-db.py109 LPCONFIG=${NEW_STAGING_CONFIG} ./repair-restored-db.py
@@ -118,6 +134,15 @@
118 # Start the slon daemons, with requested lag.134 # Start the slon daemons, with requested lag.
119 LPCONFIG=${STAGING_CONFIG} ./slon_ctl.py --lag="${LAG}" start135 LPCONFIG=${STAGING_CONFIG} ./slon_ctl.py --lag="${LAG}" start
120136
137dogfood:
138 ${CREATEDB} ${DOGFOOD_DBNAME}
139 pg_restore --dbname=${DOGFOOD_DBNAME} --no-acl --no-owner \
140 --exit-on-error ${DOGFOOD_DUMP}
141 ./repair-restored-db.py -d ${DOGFOOD_DBNAME}
142 ../schema/upgrade.py -d ${DOGFOOD_DBNAME}
143 ../schema/fti.py -d ${DOGFOOD_DBNAME}
144 ../schema/security.py -d ${DOGFOOD_DBNAME}
145
121_prelim:146_prelim:
122 @echo LPCONFIG currently ${LPCONFIG}147 @echo LPCONFIG currently ${LPCONFIG}
123 # Create the slony PostgreSQL superuser if necessary.148 # Create the slony PostgreSQL superuser if necessary.
@@ -132,25 +157,26 @@
132_replicate:157_replicate:
133 @echo LPCONFIG currently ${LPCONFIG}158 @echo LPCONFIG currently ${LPCONFIG}
134 # Start the slon daemon for the master.159 # Start the slon daemon for the master.
135 ./slon_ctl.py start \160 ./slon_ctl.py --lag="0 seconds" start \
136 node1_node "dbname=${_MASTER} user=slony"161 node1_node "dbname=${_MASTER} user=slony"
137 # Initialize the cluster and create replication sets.162 # Initialize the cluster and create replication sets.
138 ./initialize.py163 ./initialize.py
139 # Create the soon-to-be-slave database, empty at this point.164 # Create the soon-to-be-slave database, empty at this point.
140 createdb --encoding=UTF8 --tablespace=${_SLAVE_TABLESPACE} ${_SLAVE}165 ${CREATEDB} --tablespace=${_SLAVE_TABLESPACE} ${_SLAVE}
141 # Start the slon daemon for the slave166 # Start the slon daemon for the slave
142 ./slon_ctl.py start node2_node "dbname=${_SLAVE} user=slony"167 ./slon_ctl.py --lag="0 seconds" start \
168 node2_node "dbname=${_SLAVE} user=slony"
143 # Setup the slave169 # Setup the slave
144 ./new-slave.py 2 "dbname=${_SLAVE}"170 ./new-slave.py 2 "dbname=${_SLAVE}"
145 # Upgrade all databases in the cluster and reset security.171 # Upgrade all databases in the cluster and reset security.
146 ../schema/upgrade.py172 @echo Running upgrade.py `date`
147 ../schema/fti.py173 ${SHHH} ../schema/upgrade.py
148 ../schema/security.py --cluster -U slony174 @echo Running fti.py `date`
149 # Migrate tables to the authdb replication set, creating the set175 ${SHHH} ../schema/fti.py
150 # and subscribing nodes to it as necessary.176 @echo Running security.py `date`
151 ./populate_auth_replication_set.py -U slony177 ./slon_ctl.py stop # security.py can deadlock with slony
178 ${SHHH} ../schema/security.py --cluster -U slony
152 # Restart slon daemons with default lag setting.179 # Restart slon daemons with default lag setting.
153 ./slon_ctl.py stop
154 ./slon_ctl.py --lag="${LAG}" start180 ./slon_ctl.py --lag="${LAG}" start
155 # Generate a preamble for manual slonik(1) usage.181 # Generate a preamble for manual slonik(1) usage.
156 ./preamble.py > preamble.sk182 ./preamble.py > preamble.sk
157183
=== modified file 'database/replication/helpers.py'
--- database/replication/helpers.py 2009-06-24 21:17:33 +0000
+++ database/replication/helpers.py 2010-05-05 01:58:48 +0000
@@ -26,19 +26,20 @@
26# The namespace in the database used to contain all the Slony-I tables.26# The namespace in the database used to contain all the Slony-I tables.
27CLUSTER_NAMESPACE = '_%s' % CLUSTERNAME27CLUSTER_NAMESPACE = '_%s' % CLUSTERNAME
2828
29# Seed tables for the authdb replication set to be passed to29# Replication set id constants. Don't change these without DBA help.
30LPMAIN_SET_ID = 1
31HOLDING_SET_ID = 666
32LPMIRROR_SET_ID = 4
33
34# Seed tables for the lpmain replication set to be passed to
30# calculate_replication_set().35# calculate_replication_set().
31AUTHDB_SEED = frozenset([36LPMAIN_SEED = frozenset([
32 ('public', 'account'),37 ('public', 'account'),
38 ('public', 'openidnonce'),
33 ('public', 'openidassociation'),39 ('public', 'openidassociation'),
34 ('public', 'openidnonce'),
35 ])
36
37# Seed tables for the lpmain replication set to be passed to
38# calculate_replication_set().
39LPMAIN_SEED = frozenset([
40 ('public', 'person'),40 ('public', 'person'),
41 ('public', 'launchpaddatabaserevision'),41 ('public', 'launchpaddatabaserevision'),
42 ('public', 'databasereplicationlag'),
42 ('public', 'fticache'),43 ('public', 'fticache'),
43 ('public', 'nameblacklist'),44 ('public', 'nameblacklist'),
44 ('public', 'openidconsumerassociation'),45 ('public', 'openidconsumerassociation'),
@@ -51,14 +52,49 @@
51 ('public', 'launchpadstatistic'),52 ('public', 'launchpadstatistic'),
52 ('public', 'parsedapachelog'),53 ('public', 'parsedapachelog'),
53 ('public', 'shipitsurvey'),54 ('public', 'shipitsurvey'),
54 ('public', 'openidassociations'), # Remove this in April 2009 or later.55 ('public', 'databasereplicationlag'),
55 ])56 ])
5657
57# Explicitly list tables that should not be replicated. This includes the58# Explicitly list tables that should not be replicated. This includes the
58# session tables, as these might exist in developer databases but will not59# session tables, as these might exist in developer databases but will not
59# exist in the production launchpad database.60# exist in the production launchpad database.
60IGNORED_TABLES = set([61IGNORED_TABLES = set([
61 'public.secret', 'public.sessiondata', 'public.sessionpkgdata'])62 # Session tables that in some situations will exist in the main lp
63 # database.
64 'public.secret', 'public.sessiondata', 'public.sessionpkgdata',
65 # Mirror tables, per Bug #489078. These tables have their own private
66 # replication set that is setup manually.
67 'public.lp_account',
68 'public.lp_person',
69 'public.lp_personlocation',
70 'public.lp_teamparticipation',
71 # Ubuntu SSO database. These tables where created manually by ISD
72 # and the Launchpad scripts should not mess with them. Eventually
73 # these tables will be in a totally separate database.
74 'public.auth_permission',
75 'public.auth_group',
76 'public.auth_user',
77 'public.auth_message',
78 'public.django_content_type',
79 'public.auth_permission',
80 'public.django_session',
81 'public.django_site',
82 'public.django_admin_log',
83 'public.ssoopenidrpconfig',
84 'public.auth_group_permissions',
85 'public.auth_user_groups',
86 'public.auth_user_user_permissions',
87 'public.oauth_nonce',
88 'public.oauth_consumer',
89 'public.oauth_token',
90 'public.api_user',
91 'public.oauth_consumer_id_seq',
92 'public.api_user_id_seq',
93 'public.oauth_nonce_id_seq',
94 ])
95
96# Calculate IGNORED_SEQUENCES
97IGNORED_SEQUENCES = set('%s_id_seq' % table for table in IGNORED_TABLES)
6298
6399
64def slony_installed(con):100def slony_installed(con):
@@ -101,7 +137,7 @@
101137
102def sync(timeout):138def sync(timeout):
103 """Generate a sync event and wait for it to complete on all nodes.139 """Generate a sync event and wait for it to complete on all nodes.
104 140
105 This means that all pending events have propagated and are in sync141 This means that all pending events have propagated and are in sync
106 to the point in time this method was called. This might take several142 to the point in time this method was called. This might take several
107 hours if there is a large backlog of work to replicate.143 hours if there is a large backlog of work to replicate.
@@ -135,12 +171,13 @@
135 script = preamble() + script171 script = preamble() + script
136172
137 if sync is not None:173 if sync is not None:
138 script = script + dedent("""\174 sync_script = dedent("""\
139 sync (id = @master_node);175 sync (id = @master_node);
140 wait for event (176 wait for event (
141 origin = ALL, confirmed = ALL,177 origin = @master_node, confirmed = ALL,
142 wait on = @master_node, timeout = %d);178 wait on = @master_node, timeout = %d);
143 """ % sync)179 """ % sync)
180 script = script + sync_script
144181
145 # Copy the script to a NamedTemporaryFile rather than just pumping it182 # Copy the script to a NamedTemporaryFile rather than just pumping it
146 # to slonik via stdin. This way it can be examined if slonik appears183 # to slonik via stdin. This way it can be examined if slonik appears
@@ -151,7 +188,7 @@
151188
152 # Run slonik189 # Run slonik
153 log.debug("Executing slonik script %s" % script_on_disk.name)190 log.debug("Executing slonik script %s" % script_on_disk.name)
154 log.log(DEBUG2, script)191 log.log(DEBUG2, 'Running script:\n%s' % script)
155 returncode = subprocess.call(['slonik', script_on_disk.name])192 returncode = subprocess.call(['slonik', script_on_disk.name])
156193
157 if returncode != 0:194 if returncode != 0:
@@ -255,7 +292,7 @@
255 assert len(node_ids) == 1, "Multiple nodes but no paths."292 assert len(node_ids) == 1, "Multiple nodes but no paths."
256 master_node_id = node_ids[0]293 master_node_id = node_ids[0]
257 master_connection_string = ConnectionString(294 master_connection_string = ConnectionString(
258 config.database.main_master)295 config.database.rw_main_master)
259 master_connection_string.user = 'slony'296 master_connection_string.user = 'slony'
260 return [Node(297 return [Node(
261 master_node_id, 'node%d_node' % master_node_id,298 master_node_id, 'node%d_node' % master_node_id,
@@ -282,10 +319,10 @@
282 cluster name = sl;319 cluster name = sl;
283320
284 # Symbolic ids for replication sets.321 # Symbolic ids for replication sets.
285 define lpmain_set 1;322 define lpmain_set %d;
286 define authdb_set 2;323 define holding_set %d;
287 define holding_set 666;324 define lpmirror_set %d;
288 """)]325 """ % (LPMAIN_SET_ID, HOLDING_SET_ID, LPMIRROR_SET_ID))]
289326
290 if master_node is not None:327 if master_node is not None:
291 preamble.append(dedent("""\328 preamble.append(dedent("""\
@@ -303,9 +340,9 @@
303 node.nickname, node.node_id,340 node.nickname, node.node_id,
304 node.nickname, node.connection_string,341 node.nickname, node.connection_string,
305 node.nickname, node.nickname)))342 node.nickname, node.nickname)))
306 343
307 return '\n\n'.join(preamble)344 return '\n\n'.join(preamble)
308 345
309346
310def calculate_replication_set(cur, seeds):347def calculate_replication_set(cur, seeds):
311 """Return the minimal set of tables and sequences needed in a348 """Return the minimal set of tables and sequences needed in a
@@ -434,7 +471,7 @@
434471
435 return (472 return (
436 all_tables - replicated_tables - IGNORED_TABLES,473 all_tables - replicated_tables - IGNORED_TABLES,
437 all_sequences - replicated_sequences)474 all_sequences - replicated_sequences - IGNORED_SEQUENCES)
438475
439476
440class ReplicationConfigError(Exception):477class ReplicationConfigError(Exception):
@@ -462,19 +499,6 @@
462 raise ReplicationConfigError(499 raise ReplicationConfigError(
463 "Unreplicated sequences: %s" % repr(unrepl_sequences))500 "Unreplicated sequences: %s" % repr(unrepl_sequences))
464501
465 authdb_tables, authdb_sequences = calculate_replication_set(
466 cur, AUTHDB_SEED)
467 lpmain_tables, lpmain_sequences = calculate_replication_set(502 lpmain_tables, lpmain_sequences = calculate_replication_set(
468 cur, LPMAIN_SEED)503 cur, LPMAIN_SEED)
469504
470 confused_tables = authdb_tables.intersection(lpmain_tables)
471 if confused_tables:
472 raise ReplicationConfigError(
473 "Tables exist in multiple replication sets: %s"
474 % repr(confused_tables))
475 confused_sequences = authdb_sequences.intersection(lpmain_sequences)
476 if confused_sequences:
477 raise ReplicationConfigError(
478 "Sequences exist in multiple replication sets: %s"
479 % repr(confused_sequences))
480
481505
=== modified file 'database/replication/initialize.py'
--- database/replication/initialize.py 2009-07-19 04:41:14 +0000
+++ database/replication/initialize.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -41,9 +41,9 @@
41 """Duplicate the master schema into the slaves."""41 """Duplicate the master schema into the slaves."""
42 log.info('Duplicating database schema')42 log.info('Duplicating database schema')
4343
44 master_cs = ConnectionString(config.database.main_master)44 master_cs = ConnectionString(config.database.rw_main_master)
45 master_cs.user = options.dbuser45 master_cs.user = options.dbuser
46 slave1_cs = ConnectionString(config.database.main_slave)46 slave1_cs = ConnectionString(config.database.rw_main_slave)
47 slave1_cs.user = options.dbuser47 slave1_cs.user = options.dbuser
4848
49 # We can't use pg_dump to replicate security as not all of the roles49 # We can't use pg_dump to replicate security as not all of the roles
@@ -70,7 +70,7 @@
70 """Initialize the cluster."""70 """Initialize the cluster."""
71 log.info('Initializing Slony-I cluster')71 log.info('Initializing Slony-I cluster')
72 master_connection_string = ConnectionString(72 master_connection_string = ConnectionString(
73 config.database.main_master)73 config.database.rw_main_master)
74 master_connection_string.user = 'slony'74 master_connection_string.user = 'slony'
75 helpers.execute_slonik("""75 helpers.execute_slonik("""
76 node 1 admin conninfo = '%s';76 node 1 admin conninfo = '%s';
@@ -88,54 +88,13 @@
88 helpers.sync(120) # Will exit on failure.88 helpers.sync(120) # Will exit on failure.
8989
9090
91def create_replication_sets(91def create_replication_sets(lpmain_tables, lpmain_sequences):
92 authdb_tables, authdb_sequences, lpmain_tables, lpmain_sequences):
93 """Create the replication sets."""92 """Create the replication sets."""
94 log.info('Creating Slony-I replication sets.')93 log.info('Creating Slony-I replication sets.')
9594
96 # Instead of creating both the authdb and lpmain replication sets,
97 # we just create the lpmain replication set containing everything.
98 # This way, we can then test the populate_auth_replication_set.py
99 # migration script that moves the relevant tables from the lpmain
100 # replication set to the authdb replication set.
101 # We will turn this behavior off once we are running two
102 # replication sets in production and remove the migration script.
103 lpmain_tables = lpmain_tables.union(authdb_tables)
104 lpmain_sequences = lpmain_sequences.union(authdb_sequences)
105
106 script = ["try {"]95 script = ["try {"]
107 # script,append("""
108 # echo 'Creating AuthDB replication set (@authdb_set)';
109 # create set (
110 # id=@authdb_set, origin=@master_node,
111 # comment='AuthDB tables and sequences');
112 # """)
11396
114 # entry_id = 197 entry_id = 1
115 # for table in sorted(authdb_tables):
116 # script.append("""
117 # echo 'Adding %(table)s to replication set @authdb_set';
118 # set add table (
119 # set id=@authdb_set,
120 # origin=@master_node,
121 # id=%(entry_id)d,
122 # fully qualified name='%(table)s');
123 # """ % vars())
124 # entry_id += 1
125 # entry_id = 1
126 # for sequence in sorted(authdb_sequences):
127 # script.append("""
128 # echo 'Adding %(sequence)s to replication set @authdb_set';
129 # set add sequence (
130 # set id=@authdb_set,
131 # origin=@master_node,
132 # id=%(entry_id)d,
133 # fully qualified name='%(sequence)s');
134 # """ % vars())
135 # entry_id += 1
136 #
137 # assert entry_id < 200, 'authdb replcation set has > 200 objects???'
138 entry_id = 200
13998
140 script.append("""99 script.append("""
141 echo 'Creating LPMain replication set (@lpmain_set)';100 echo 'Creating LPMain replication set (@lpmain_set)';
@@ -157,7 +116,7 @@
157 """ % vars())116 """ % vars())
158 entry_id += 1117 entry_id += 1
159118
160 entry_id = 200119 entry_id = 1
161 script.append(120 script.append(
162 "echo 'Adding %d sequences to replication set @lpmain_set';"121 "echo 'Adding %d sequences to replication set @lpmain_set';"
163 % len(lpmain_sequences))122 % len(lpmain_sequences))
@@ -199,9 +158,6 @@
199 con.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)158 con.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
200 global cur159 global cur
201 cur = con.cursor()160 cur = con.cursor()
202 log.debug("Calculating authdb replication set.")
203 authdb_tables, authdb_sequences = helpers.calculate_replication_set(
204 cur, helpers.AUTHDB_SEED)
205 log.debug("Calculating lpmain replication set.")161 log.debug("Calculating lpmain replication set.")
206 lpmain_tables, lpmain_sequences = helpers.calculate_replication_set(162 lpmain_tables, lpmain_sequences = helpers.calculate_replication_set(
207 cur, helpers.LPMAIN_SEED)163 cur, helpers.LPMAIN_SEED)
@@ -212,8 +168,7 @@
212 fails = 0168 fails = 0
213 for table in all_tables_in_schema(cur, 'public'):169 for table in all_tables_in_schema(cur, 'public'):
214 times_seen = 0170 times_seen = 0
215 for table_set in [171 for table_set in [lpmain_tables, helpers.IGNORED_TABLES]:
216 authdb_tables, lpmain_tables, helpers.IGNORED_TABLES]:
217 if table in table_set:172 if table in table_set:
218 times_seen += 1173 times_seen += 1
219 if times_seen == 0:174 if times_seen == 0:
@@ -224,7 +179,7 @@
224 fails += 1179 fails += 1
225 for sequence in all_sequences_in_schema(cur, 'public'):180 for sequence in all_sequences_in_schema(cur, 'public'):
226 times_seen = 0181 times_seen = 0
227 for sequence_set in [authdb_sequences, lpmain_sequences]:182 for sequence_set in [lpmain_sequences, helpers.IGNORED_SEQUENCES]:
228 if sequence in sequence_set:183 if sequence in sequence_set:
229 times_seen += 1184 times_seen += 1
230 if times_seen == 0:185 if times_seen == 0:
@@ -241,8 +196,7 @@
241196
242 ensure_live()197 ensure_live()
243198
244 create_replication_sets(199 create_replication_sets(lpmain_tables, lpmain_sequences)
245 authdb_tables, authdb_sequences, lpmain_tables, lpmain_sequences)
246200
247 helpers.sync(0)201 helpers.sync(0)
248202
249203
=== modified file 'database/replication/new-slave.py'
--- database/replication/new-slave.py 2009-06-24 21:17:33 +0000
+++ database/replication/new-slave.py 2010-05-05 01:58:48 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/python2.41#!/usr/bin/python2.5 -S
2#2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).4# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -24,6 +24,7 @@
24from canonical.launchpad.scripts import db_options, logger_options, logger24from canonical.launchpad.scripts import db_options, logger_options, logger
2525
26import replication.helpers26import replication.helpers
27from replication.helpers import LPMAIN_SET_ID
2728
28def main():29def main():
29 parser = OptionParser(30 parser = OptionParser(
@@ -72,6 +73,10 @@
72 if node_id in [node.node_id for node in existing_nodes]:73 if node_id in [node.node_id for node in existing_nodes]:
73 parser.error("Node %d already exists in the cluster." % node_id)74 parser.error("Node %d already exists in the cluster." % node_id)
7475
76 # Get the connection string for masters.
77 lpmain_connection_string = get_master_connection_string(
78 source_connection, parser, LPMAIN_SET_ID) or source_connection_string
79
75 # Sanity check the target connection string.80 # Sanity check the target connection string.
76 target_connection_string = ConnectionString(raw_target_connection_string)81 target_connection_string = ConnectionString(raw_target_connection_string)
77 if target_connection_string.user is None:82 if target_connection_string.user is None:
@@ -110,11 +115,11 @@
110 "Database at %s is not empty." % target_connection_string)115 "Database at %s is not empty." % target_connection_string)
111 target_con.rollback()116 target_con.rollback()
112117
113 # Duplicate the schema. We restore with no-privileges as required118 # Duplicate the full schema. We restore with no-privileges as required
114 # roles may not yet exist, so we have to run security.py on the119 # roles may not yet exist, so we have to run security.py on the
115 # new slave once it is built.120 # new slave once it is built.
116 log.info("Duplicating db schema from '%s' to '%s'" % (121 log.info("Duplicating full db schema from '%s' to '%s'" % (
117 source_connection_string, target_connection_string))122 lpmain_connection_string, target_connection_string))
118 cmd = "pg_dump --schema-only --no-privileges %s | psql -1 -q %s" % (123 cmd = "pg_dump --schema-only --no-privileges %s | psql -1 -q %s" % (
119 source_connection_string.asPGCommandLineArgs(),124 source_connection_string.asPGCommandLineArgs(),
120 target_connection_string.asPGCommandLineArgs())125 target_connection_string.asPGCommandLineArgs())
@@ -123,19 +128,39 @@
123 return 1128 return 1
124129
125 # Trash the broken Slony tables we just duplicated.130 # Trash the broken Slony tables we just duplicated.
131 log.debug("Removing slony cruft.")
126 cur = target_con.cursor()132 cur = target_con.cursor()
127 cur.execute("DROP SCHEMA _sl CASCADE")133 cur.execute("DROP SCHEMA _sl CASCADE")
128 target_con.commit()134 target_con.commit()
129 del target_con135 del target_con
130136
131 # Get a list of existing set ids.137 # Get a list of existing set ids that can be subscribed too. This
138 # is all sets where the origin is the master_node. We
139 # don't allow other sets where the master is configured as a
140 # forwarding slave as we have to special case rebuilding the database
141 # schema, and we want to avoid cascading slave configurations anyway
142 # since we are running an antique Slony-I at the moment - keep it
143 # simple!
144 # We order the sets smallest to largest by number of tables.
145 # This should let us subscribe the quickest sets first for more
146 # immediate feedback.
132 source_connection.rollback()147 source_connection.rollback()
133 master_node = replication.helpers.get_master_node(source_connection)148 master_node = replication.helpers.get_master_node(source_connection)
134 cur = source_connection.cursor()149 cur = source_connection.cursor()
135 cur.execute(150 cur.execute("""
136 "SELECT set_id FROM _sl.sl_set WHERE set_origin=%d"151 SELECT set_id
137 % master_node.node_id)152 FROM _sl.sl_set, (
153 SELECT tab_set, count(*) AS tab_count
154 FROM _sl.sl_table GROUP BY tab_set
155 ) AS TableCounts
156 WHERE
157 set_origin=%d
158 AND tab_set = set_id
159 ORDER BY tab_count
160 """
161 % (master_node.node_id,))
138 set_ids = [set_id for set_id, in cur.fetchall()]162 set_ids = [set_id for set_id, in cur.fetchall()]
163 log.debug("Discovered set ids %s" % repr(list(set_ids)))
139164
140 # Generate and run a slonik(1) script to initialize the new node165 # Generate and run a slonik(1) script to initialize the new node
141 # and subscribe it to our replication sets.166 # and subscribe it to our replication sets.
@@ -165,19 +190,32 @@
165 } on error { echo 'Failed.'; exit 1; }190 } on error { echo 'Failed.'; exit 1; }
166 """)191 """)
167192
193 full_sync = []
194 sync_nicknames = [node.nickname for node in existing_nodes]
195 sync_nicknames.append('new_node');
196 for nickname in sync_nicknames:
197 full_sync.append(dedent("""\
198 echo 'Waiting for %(nickname)s sync.';
199 sync (id=@%(nickname)s);
200 wait for event (
201 origin = @%(nickname)s, confirmed=ALL,
202 wait on = @%(nickname)s, timeout=0);
203 """ % {'nickname': nickname}))
204 full_sync = '\n'.join(full_sync)
205 script += full_sync
206
168 for set_id in set_ids:207 for set_id in set_ids:
169
170 script += dedent("""\208 script += dedent("""\
171 echo 'Subscribing new node to set %d.';209 echo 'Subscribing new node to set %d.';
172 subscribe set (210 subscribe set (
173 id=%d, provider=@master_node, receiver=@new_node, forward=yes);211 id=%d, provider=@master_node, receiver=@new_node, forward=yes);
174212 echo 'Waiting for subscribe to start processing.';
175 echo 'Waiting for sync... this might take a while...';
176 sync (id = @master_node);213 sync (id = @master_node);
177 wait for event (214 wait for event (
178 origin = ALL, confirmed = ALL,215 origin = @master_node, confirmed = ALL,
179 wait on = @master_node, timeout = 0);216 wait on = @master_node, timeout = 0);
180 """ % (set_id, set_id))217 """ % (set_id, set_id))
218 script += full_sync
181219
182 replication.helpers.execute_slonik(script)220 replication.helpers.execute_slonik(script)
183221
@@ -185,5 +223,33 @@
185223
186 return 0224 return 0
187225
226
227def get_master_connection_string(con, parser, set_id):
228 """Return the connection string to the origin for the replication set.
229 """
230 cur = con.cursor()
231 cur.execute("""
232 SELECT pa_conninfo FROM _sl.sl_set, _sl.sl_path
233 WHERE set_origin = pa_server AND set_id = %d
234 LIMIT 1
235 """ % set_id)
236 row = cur.fetchone()
237 if row is None:
238 # If we have no paths stored, there is only a single node in the
239 # cluster.
240 return None
241 else:
242 connection_string = ConnectionString(row[0])
243
244 # Confirm we can connect from here.
245 try:
246 test_con = psycopg2.connect(str(connection_string))
247 except psycopg2.Error, exception:
248 parser.error("Failed to connect to using '%s' (%s)" % (
249 connection_string, str(exception).strip()))
250
251 return connection_string
252
253
188if __name__ == '__main__':254if __name__ == '__main__':
189 sys.exit(main())255 sys.exit(main())
190256
=== removed file 'database/replication/populate_auth_replication_set.py'
--- database/replication/populate_auth_replication_set.py 2009-06-24 21:17:33 +0000
+++ database/replication/populate_auth_replication_set.py 1970-01-01 00:00:00 +0000
@@ -1,177 +0,0 @@
1#!/usr/bin/python2.4
2#
3# Copyright 2009 Canonical Ltd. This software is licensed under the
4# GNU Affero General Public License version 3 (see the file LICENSE).
5
6"""Populate the auth replication set.
7
8This script moves the the SSO tables from the main replication set to
9the auth replication set.
10
11Once it has been run on production, these tables can no longer be
12maintained using the Launchpad database maintenance scripts
13(upgrade.py, security.py etc.).
14
15We do this so Launchpad database upgrades do not lock the SSO tables,
16allowing the SSO service to continue to operate.
17
18This is a single shot script.
19"""
20
21__metaclass__ = type
22__all__ = []
23
24import _pythonpath
25
26import sys
27from textwrap import dedent
28from optparse import OptionParser
29
30from canonical.database.sqlbase import (
31 connect, ISOLATION_LEVEL_AUTOCOMMIT, sqlvalues)
32from canonical.launchpad.scripts import db_options, logger_options, logger
33
34import replication.helpers
35
36def create_auth_set(cur):
37 """Create the auth replication set if it doesn't already exist."""
38 cur.execute("SELECT TRUE FROM _sl.sl_set WHERE set_id=2")
39 if cur.fetchone() is not None:
40 log.info("Auth set already exists.")
41 return
42 slonik_script = dedent("""\
43 create set (
44 id=@authdb_set, origin=@master_node,
45 comment='SSO service tables');
46 """)
47 log.info("Creating authdb replication set.")
48 replication.helpers.execute_slonik(slonik_script, sync=0)
49
50
51def subscribe_auth_set(cur):
52 """The authdb set subscription much match the lpmain set subscription.
53
54 This is a requirement to move stuff between replication sets. It
55 is also what we want (all nodes replicating everything).
56 """
57 cur.execute("""
58 SELECT sub_receiver FROM _sl.sl_subscribe WHERE sub_set = 1
59 EXCEPT
60 SELECT sub_receiver FROM _sl.sl_subscribe WHERE sub_set = 2
61 """)
62 for node_id in (node_id for node_id, in cur.fetchall()):
63 log.info("Subscribing Node #%d to authdb replication set" % node_id)
64 success = replication.helpers.execute_slonik(dedent("""\
65 subscribe set (
66 id = @authdb_set, provider = @master_node,
67 receiver = %d, forward = yes);
68 """ % node_id), sync=0)
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: