← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~jml/launchpad/flush-top-level into lp:launchpad

 

Jonathan Lange has proposed merging lp:~jml/launchpad/flush-top-level into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~jml/launchpad/flush-top-level/+merge/50374

This branch aims to clean up the top level directory of the Launchpad tree.

For a very long time now, it has been full of all sorts of things that no one really understands. The more clutter that's there, the harder it is for anyone trying to explore the project.


Move zcml files into 'zcml/':
  This is with the exception of 'site.zcml', which is referred to by external
  configuration files. I've had to change some code to look for zcml files in 
  the right place.

Delete 'todo':
  Anything that's still todo from four years ago can safely be said to have been 
  forgotten.

Delete BRANCH.TODO:
  This was a neat little mechanism, but there are other ways of achieving the same
  thing that don't put an extra cognitive load on people navigating the Launchpad
  code base.

Delete benchmarks:
  Francis says these were added for a sprint and are not needed any more.

Delete version.txt:
  We no longer put the version of Launchpad in the tree. I changed 
  lp.app.versioninfo accordingly.

Delete test.config, zdaemon.conf:
  Simply unused.

Delete 'logs/':
  This directory *is* used when we run stuff in development environments, but it contains 
  no versioned data. I've removed it from the tree and changed the Makefile to generate it
  when necessary.

Delete 'run.gdb':
  This was just a file that said 'run', because gdb doesn't let you specify commands
  for it in any other way. I've deleted the file and had the relevant make target create 
  one.

Moved 'optionalbzrplugins' to 'bzrplugins/optional':
  This seems to be just as clear and less clutter in the top level.

Moved snakefood stuff:
  The "snakefood" stuff is Python package dependency analysis that I added ages ago. 
  It's not important enough to clutter the root of the tree.

I've updated or added documentation where I could.

This change is potentially disruptive, both to developers and to production deployments. I'll start a full test suite run now.
-- 
https://code.launchpad.net/~jml/launchpad/flush-top-level/+merge/50374
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~jml/launchpad/flush-top-level into lp:launchpad.
=== modified file '.bzrignore'
--- .bzrignore	2011-02-04 17:21:05 +0000
+++ .bzrignore	2011-02-18 18:56:20 +0000
@@ -78,3 +78,4 @@
 configs/testrunner-appserver_*
 doc/_build
 .idea
+run.gdb

=== removed file 'BRANCH.TODO'
--- BRANCH.TODO	2011-02-10 15:43:21 +0000
+++ BRANCH.TODO	1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-# Put your TODOs for this branch here, then make sure it is empty before
-# landing. There is a test to ensure it is empty in trunk. If there is
-# stuff still here when you are ready to land, the items should probably
-# be converted to bugs so they can be scheduled.
-

=== modified file 'Makefile'
--- Makefile	2011-02-17 13:28:38 +0000
+++ Makefile	2011-02-18 18:56:20 +0000
@@ -125,6 +125,9 @@
 lint-verbose: ${PY}
 	@bash ./bin/lint.sh -v
 
+logs:
+	mkdir logs
+
 xxxreport: $(PY)
 	${PY} -t ./utilities/xxxreport.py -f csv -o xxx-report.csv ./
 
@@ -134,7 +137,7 @@
 pagetests: build
 	env PYTHONPATH=$(PYTHONPATH) bin/test test_pages
 
-inplace: build
+inplace: build logs clean_logs
 	mkdir -p $(CODEHOSTING_ROOT)/mirrors
 	mkdir -p $(CODEHOSTING_ROOT)/config
 	mkdir -p /var/tmp/bzrsync
@@ -260,17 +263,17 @@
 	$(PY) cronscripts/merge-proposal-jobs.py -v
 
 run: check_schema inplace stop
-	$(RM) logs/thread*.request
 	bin/run -r librarian,google-webservice,memcached -i $(LPCONFIG)
 
-start-gdb: check_schema inplace stop support_files
-	$(RM) logs/thread*.request
+run.gdb:
+	echo 'run' > run.gdb
+
+start-gdb: check_schema inplace stop support_files run.gdb
 	nohup gdb -x run.gdb --args bin/run -i $(LPCONFIG) \
 		-r librarian,google-webservice
 		> ${LPCONFIG}-nohup.out 2>&1 &
 
 run_all: check_schema inplace stop
-	$(RM) logs/thread*.request
 	bin/run -r librarian,sftp,forker,mailman,codebrowse,google-webservice,memcached \
 	    -i $(LPCONFIG)
 
@@ -284,7 +287,6 @@
 	$(PY) scripts/stop-loggerhead.py
 
 run_codehosting: check_schema inplace stop
-	$(RM) logs/thread*.request
 	bin/run -r librarian,sftp,forker,codebrowse -i $(LPCONFIG)
 
 start_librarian: compile
@@ -360,7 +362,10 @@
 	$(RM) -r build
 	$(RM) _pythonpath.py
 
-clean: clean_js clean_buildout
+clean_logs:
+	$(RM) logs/thread*.request
+
+clean: clean_js clean_buildout clean_logs
 	$(MAKE) -C sourcecode/pygettextpo clean
 	# XXX gary 2009-11-16 bug 483782
 	# The pygettextpo Makefile should have this next line in it for its make
@@ -374,7 +379,6 @@
 	    -name '*.lo' -o -name '*.py[co]' -o -name '*.dll' -o \
 	    -name '*.pt.py' \) \
 	    -print0 | xargs -r0 $(RM)
-	$(RM) logs/thread*.request
 	$(RM) -r lib/mailman
 	$(RM) -rf lib/canonical/launchpad/icing/build/*
 	$(RM) -rf $(CODEHOSTING_ROOT)
@@ -398,7 +402,6 @@
 	# /var/tmp/launchpad_mailqueue is created read-only on ec2test
 	# instances.
 	if [ -w /var/tmp/launchpad_mailqueue ]; then $(RM) -rf /var/tmp/launchpad_mailqueue; fi
-	$(RM) -f lp.sfood lp-clustered.sfood lp-clustered.dot lp-clustered.svg
 
 
 realclean: clean
@@ -453,33 +456,6 @@
 	# idutils ID file
 	bin/tags -i
 
-lp.sfood:
-	# Generate import dependency graph
-	sfood -i -u -I lib/sqlobject -I lib/schoolbell -I lib/devscripts \
-	-I lib/contrib -I lib/canonical/not-used lib/canonical \
-	lib/lp 2>/dev/null | grep -v contrib/ \
-	| grep -v sqlobject | grep -v BeautifulSoup | grep -v psycopg \
-	| grep -v schoolbell > lp.sfood.tmp
-	mv lp.sfood.tmp lp.sfood
-
-
-lp-clustered.sfood: lp.sfood lp-sfood-packages
-	# Cluster the import dependency graph
-	sfood-cluster -f lp-sfood-packages < lp.sfood > lp-clustered.sfood.tmp
-	mv lp-clustered.sfood.tmp lp-clustered.sfood
-
-
-lp-clustered.dot: lp-clustered.sfood
-	# Build the visual graph
-	sfood-graph -p < lp-clustered.sfood > lp-clustered.dot.tmp
-	mv lp-clustered.dot.tmp lp-clustered.dot
-
-
-lp-clustered.svg: lp-clustered.dot
-	# Render to svg
-	dot -Tsvg < lp-clustered.dot > lp-clustered.svg.tmp
-	mv lp-clustered.svg.tmp lp-clustered.svg
-
 PYDOCTOR = pydoctor
 PYDOCTOR_OPTIONS =
 
@@ -495,4 +471,4 @@
 	check_merge_ui pull scan sync_branches reload-apache hosted_branches \
 	check_db_merge check_mailman check_config jsbuild jsbuild_lazr \
 	clean_js clean_buildout buildonce_eggs build_eggs sprite_css \
-	sprite_image css_combine compile check_schema pydoctor
+	sprite_image css_combine compile check_schema pydoctor clean_logs \

=== modified file 'README'
--- README	2010-08-10 18:20:12 +0000
+++ README	2011-02-18 18:56:20 +0000
@@ -95,12 +95,12 @@
     when buildout is run. If you want to change the behaviour of bin/test,
     look here.
 
-  bzrplugins/, optionalbzrplugins/
+  bzrplugins/
     Bazaar plugins used in running Launchpad.
 
   sourcecode/
     A directory into which we symlink branches of some of Launchpad's
     dependencies.  Don't ask.
 
-You never have to care about 'benchmarks', 'override-includes' or
-'package-includes'.
+  zcml/
+    Various configuration files for the Zope services. Angels fear to tread.

=== removed directory 'benchmarks'
=== removed file 'benchmarks/Auth.conf'
--- benchmarks/Auth.conf	2009-08-07 07:33:56 +0000
+++ benchmarks/Auth.conf	1970-01-01 00:00:00 +0000
@@ -1,101 +0,0 @@
-# FunkLoad test configuration file
-# $Id: $
-
-
-# ------------------------------------------------------------
-# Main section
-#
-[main]
-title=Auth
-description=Testing load with basic authentication to Launchpad
-login=foo@xxxxxxxxxxxxxx
-password=test
-
-# the server url to test.
-url=https://staging.launchpad.net
-
-# ------------------------------------------------------------
-# Tests description and configuration
-#
-[test_auth]
-description=Does the login to Launchpad page.
-
-
-# ------------------------------------------------------------
-# Credential access
-#
-[credential]
-host=localhost
-port=8007
-
-
-# ------------------------------------------------------------
-# Monitoring configuration
-#
-[monitor]
-#hosts=localhost
-
-# Each host in [monitor]hosts should have a section
-# with a 'port' and 'description' keys
-[localhost]
-port=8008
-description=The benching machine
-
-
-# ------------------------------------------------------------
-# Configuration for unit test mode fl-run-test
-#
-[ftest]
-
-# log_to destination =
-# console - to the screen
-# file - to a file
-log_to = console file
-
-# log_path = path and file name to store log file
-log_path = auth-test.log
-
-# result_path = path to store the xml result file
-result_path = auth-test.xml
-
-# ok_codes = list of successfull HTTP response code default is 200:301:302
-# ok_codes =  200:301:302
-
-# sleeptime_min = minimum amount of time in seconds to sleep between requests
-#                 to the host
-sleep_time_min = 0
-
-# sleeptime_max = maximum amount of time in seconds to sleep between requests
-#                 to the host
-sleep_time_max = 0
-
-
-# ------------------------------------------------------------
-# Configuration for bench mode fl-run-bench
-#
-[bench]
-
-# cycles = list of cycles with their number of concurrent users
-cycles =  1:5:10:20:40:80:160:200
-
-# duration = duration of a cycle in seconds
-duration = 60
-
-# startup_delay = time to wait between starting-up threads in seconds
-startup_delay = 0.2
-
-# sleep_time = time to wait between test in seconds
-sleep_time = 1
-
-# cycle_time = time to wait between cycle in seconds
-# We have a significant delay in case we had to terminate the previous
-# cycle by restarting the service.
-cycle_time = 45
-
-# same keys than in [ftest] section
-log_to = file
-log_path = auth-bench.log
-result_path = auth-bench.xml
-#ok_codes =  200:301:302
-sleep_time_min = 0
-sleep_time_max = 2

=== removed file 'benchmarks/Frontpage.conf'
--- benchmarks/Frontpage.conf	2009-07-16 17:58:57 +0000
+++ benchmarks/Frontpage.conf	1970-01-01 00:00:00 +0000
@@ -1,103 +0,0 @@
-# FunkLoad test configuration file
-# $Id: $
-
-
-# ------------------------------------------------------------
-# Main section
-#
-[main]
-title=Front Page
-description=Launchpad Front Page
-
-# the server url to test
-url=http://launchpad.net
-
-# the User-Agent header to send default is 'FunkLoad/1.xx' examples:
-#user_agent = Opera/8.0 (Windows NT 5.1; U; en)
-#user_agent = Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
-#user_agent = Mozilla/5.0 (X11; U; Linux i686; en; rv:1.7.10) Gecko/20050912 Firefox/1.0.6
-
-
-# ------------------------------------------------------------
-# Tests description and configuration
-#
-[test_frontpage]
-description=Load the Launchpad front page.
-
-
-# ------------------------------------------------------------
-# Credential access
-#
-[credential]
-host=localhost
-port=8007
-
-
-# ------------------------------------------------------------
-# Monitoring configuration
-#
-[monitor]
-#hosts=localhost
-
-# Each host in [monitor]hosts should have a section
-# with a 'port' and 'description' keys
-[localhost]
-port=8008
-description=The benching machine
-
-
-# ------------------------------------------------------------
-# Configuration for unit test mode fl-run-test
-#
-[ftest]
-
-# log_to destination =
-# console - to the screen
-# file - to a file
-log_to = console file
-
-# log_path = path and file name to store log file
-log_path = frontpage-test.log
-
-# result_path = path to store the xml result file
-result_path = frontpage-test.xml
-
-# ok_codes = list of successfull HTTP response code default is 200:301:302
-# ok_codes =  200:301:302
-
-# sleeptime_min = minimum amount of time in seconds to sleep between requests
-#                 to the host
-sleep_time_min = 0
-
-# sleeptime_max = maximum amount of time in seconds to sleep between requests
-#                 to the host
-sleep_time_max = 0
-
-
-# ------------------------------------------------------------
-# Configuration for bench mode fl-run-bench
-#
-[bench]
-
-# cycles = list of cycles with their number of concurrent users
-cycles =  1:2:3
-
-# duration = duration of a cycle in seconds
-duration = 30
-
-# startup_delay = time to wait between starting-up threads in seconds
-startup_delay = 0.2
-
-# sleep_time = time to wait between test in seconds
-sleep_time = 1
-
-# cycle_time = time to wait between cycle in seconds
-cycle_time = 1
-
-# same keys than in [ftest] section
-log_to = file
-log_path = frontpage-bench.log
-result_path = frontpage-bench.xml
-#ok_codes =  200:301:302
-sleep_time_min = 0
-sleep_time_max = 2

=== removed file 'benchmarks/ShipIt.conf'
--- benchmarks/ShipIt.conf	2009-07-17 12:50:54 +0000
+++ benchmarks/ShipIt.conf	1970-01-01 00:00:00 +0000
@@ -1,102 +0,0 @@
-# FunkLoad test configuration file
-# $Id: $
-
-
-# ------------------------------------------------------------
-# Main section
-#
-[main]
-title=ShipIt
-description=ShipIt load test
-
-# the server url to test.
-url=https://shipit.staging.launchpad.net
-
-# Database connection string to the Launchpad database.
-database_conninfo=dbname=lpmain_staging host=localhost port=55435
-
-# ------------------------------------------------------------
-# Tests description and configuration
-#
-[test_shipit]
-description=Create an account, request cds, cancel order.
-
-
-# ------------------------------------------------------------
-# Credential access
-#
-[credential]
-host=localhost
-port=8007
-
-
-# ------------------------------------------------------------
-# Monitoring configuration
-#
-[monitor]
-#hosts=localhost
-
-# Each host in [monitor]hosts should have a section
-# with a 'port' and 'description' keys
-[localhost]
-port=8008
-description=The benching machine
-
-
-# ------------------------------------------------------------
-# Configuration for unit test mode fl-run-test
-#
-[ftest]
-
-# log_to destination =
-# console - to the screen
-# file - to a file
-log_to = console file
-
-# log_path = path and file name to store log file
-log_path = shipit-test.log
-
-# result_path = path to store the xml result file
-result_path = shipit-test.xml
-
-# ok_codes = list of successfull HTTP response code default is 200:301:302
-# ok_codes =  200:301:302
-
-# sleeptime_min = minimum amount of time in seconds to sleep between requests
-#                 to the host
-sleep_time_min = 0
-
-# sleeptime_max = maximum amount of time in seconds to sleep between requests
-#                 to the host
-sleep_time_max = 0
-
-
-# ------------------------------------------------------------
-# Configuration for bench mode fl-run-bench
-#
-[bench]
-
-# cycles = list of cycles with their number of concurrent users
-cycles =  1:5:10:20:40:80:160:200
-
-# duration = duration of a cycle in seconds
-duration = 60
-
-# startup_delay = time to wait between starting-up threads in seconds
-startup_delay = 0.2
-
-# sleep_time = time to wait between test in seconds
-sleep_time = 1
-
-# cycle_time = time to wait between cycle in seconds
-# We have a significant delay in case we had to terminate the previous
-# cycle by restarting the service.
-cycle_time = 45
-
-# same keys than in [ftest] section
-log_to = file
-log_path = shipit-bench.log
-result_path = shipit-bench.xml
-#ok_codes =  200:301:302
-sleep_time_min = 0
-sleep_time_max = 2

=== removed file 'benchmarks/test_auth.py'
--- benchmarks/test_auth.py	2009-08-07 07:45:09 +0000
+++ benchmarks/test_auth.py	1970-01-01 00:00:00 +0000
@@ -1,83 +0,0 @@
-# Copyright 2009 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Basic login to launchpad test."""
-
-__metaclass__ = type
-__all__ = []
-
-import re
-import threading
-import unittest
-
-from funkload.FunkLoadTestCase import FunkLoadTestCase
-
-
-class Auth(FunkLoadTestCase):
-
-    def setUp(self):
-        """Setting up test."""
-        self.logd("setUp")
-        self.server_url = self.conf_get('main', 'url')
-
-    _error_re = re.compile('(?s)class="error message">(.*?)</')
-
-    def assertNoFormErrors(self, response):
-        """Checks if the page returned ok and the login was sucessful."""
-        self.assertEquals(response.code, 200)
-        match = self._error_re.search(response.body)
-        if match is not None:
-            self.fail('Form contained error: %s' % match.group(1))
-
-    def assertIsNotLoggedIn(self, response):
-        # Not sure if this checking is needed.
-        self.assertEquals(response.code, 200)
-        match = response.body.find('If this is not you, please'
-            '<a href="/+logout">log out now</a>')
-        if match != -1:
-            self.fail('Test failed: this user is already logged in.')
-
-    def test_auth(self):
-        """Runs the steps of a simple Launchpad login."""
-        self.logd("test_auth")
-
-        server_url = self.server_url
-
-        # Get the login page
-        response = self.get(server_url + "/+login", description="GET /+login")
-        self.assertNoFormErrors(response)
-        self.assertIsNotLoggedIn(response)
-
-        # The credentials of foo user, the loginator
-        email = self.conf_get('main', 'login')
-        password = self.conf_get('main', 'password')
-
-        # Get only the first form of the page, the login one,
-        # and fill it
-        fields = response.extractForm(path=[('form',0)], include_submit=True)
-        fields['loginpage_email'] = email
-        fields['loginpage_password'] = password
-
-        # Submit the login form.
-        response = self.post(
-            self.absolute_url(response, '/+login'),
-            fields, "POST /+login")
-        self.assertNoFormErrors(response)
-        self.assertIsNotLoggedIn(response)
-        self.logd("logged in sucessfully")
-
-    def absolute_url(self, response, path):
-        """Calculate an absolute URL using the response and the path."""
-        return '%s://%s:%s%s' % (
-            response.protocol, response.server, response.port, path)
-
-    def tearDown(self):
-        """Finishes the test."""
-        self.logd("tearDown.\n")
-
-
-if __name__ in ('main', '__main__'):
-    unittest.main()
-
-
-

=== removed file 'benchmarks/test_frontpage.py'
--- benchmarks/test_frontpage.py	2009-07-18 21:21:06 +0000
+++ benchmarks/test_frontpage.py	1970-01-01 00:00:00 +0000
@@ -1,31 +0,0 @@
-# Copyright 2009 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Launchpad frontpage FunkLoad test"""
-
-__metaclass__ = type
-__all__ = []
-
-import unittest
-
-from funkload.FunkLoadTestCase import FunkLoadTestCase
-
-
-class Frontpage(FunkLoadTestCase):
-    """Test anonymous access to the Launchpad front page."""
-
-    def setUp(self):
-        """Setting up test."""
-        self.logd("setUp")
-        self.server_url = self.conf_get('main', 'url')
-
-    def test_frontpage(self):
-        self.get(self.server_url, description="Get /")
-
-    def tearDown(self):
-        """Setting up test."""
-        self.logd("tearDown.\n")
-
-
-if __name__ in ('main', '__main__'):
-    unittest.main()

=== removed file 'benchmarks/test_shipit.py'
--- benchmarks/test_shipit.py	2009-07-18 21:21:06 +0000
+++ benchmarks/test_shipit.py	1970-01-01 00:00:00 +0000
@@ -1,219 +0,0 @@
-# Copyright 2009 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Basic ShipIt usage test."""
-
-__metaclass__ = type
-__all__ = []
-
-import re
-import threading
-import unittest
-
-from funkload.FunkLoadTestCase import FunkLoadTestCase
-from funkload.Lipsum import Lipsum
-import psycopg2
-
-
-class ShipIt(FunkLoadTestCase):
-
-    db_connection = None
-    db_connection_lock = threading.Lock()
-
-    def setUp(self):
-        """Setting up test."""
-        self.logd("setUp")
-
-        self.server_url = self.conf_get('main', 'url')
-        self.database_conninfo = self.conf_get('main', 'database_conninfo')
-
-        self.lipsum = Lipsum()
-
-        if ShipIt.db_connection is None:
-            # We use a class variable for the database connection so the
-            # same connection is shared between threads. This is important
-            # for when we are running with hundreds of threads.
-            ShipIt.db_connection_lock.acquire()
-            try:
-                if ShipIt.db_connection is None:
-                    assert psycopg2.threadsafety >= 2, (
-                        "psycopg2 cannot share connections between threads")
-                    self.logi(
-                        'Opening database connection "%s".'
-                        % self.database_conninfo)
-                    ShipIt.db_connection = psycopg2.connect(
-                        self.database_conninfo)
-                    ShipIt.db_connection.set_isolation_level(0)
-            finally:
-                ShipIt.db_connection_lock.release()
-
-    def cursor(self):
-        return ShipIt.db_connection.cursor()
-
-    def get_email_validation_token(self, email):
-        cur = self.cursor()
-        cur.execute("""
-            SELECT token FROM AuthToken
-            WHERE date_consumed IS NULL AND token_type=12 AND email=%s
-            """, (email,))
-        row = cur.fetchone()
-        if row is None:
-            return None
-        return row[0]
-
-    _error_re = re.compile('(?s)class="error">.*?class="message">(.*?)</')
-
-    def assertNoFormErrors(self, response):
-        self.assertEquals(response.code, 200)
-        match = self._error_re.search(response.body)
-        if match is not None:
-            self.fail('Form contained error "%s"' % match.group(1))
-
-    def test_shipit(self):
-        server_url = self.server_url
-
-        self.get(server_url + "/", description="GET /")
-
-        response = self.get(server_url + "/login", description="Get /login")
-        response = response.postForm(
-            0, self.post, {'submit': 'Continue'},
-            'Post /+openid - OpenID authentication request')
-        self.assertNoFormErrors(response)
-
-        # User is not logged on
-        email = 'user_%s@lp%s.example.com' % (
-            self.lipsum.getUniqWord(), self.lipsum.getUniqWord())
-        # response.postForm fails here - looks like a bug. The action
-        # on the form is a relative URL and response.postForm tries
-        # to retrieve it from localhost.
-        params = response.extractForm(include_submit=True)
-        params['field.email'] = email
-        params['field.action'] = 'createaccount'
-        response = self.post(
-            self.absolute_url(response, '/+login-register'),
-            params, "Post /+login-register - Create account")
-        self.assertNoFormErrors(response)
-
-        # Pull the email validation token from the database and
-        # validate it.
-        token = self.get_email_validation_token(email)
-        self.assert_(token is not None, "No login token created")
-        newaccount_url = self.absolute_url(
-            response, '/token/%s/+newaccount' % token)
-        response = self.get(
-            newaccount_url, description="Get /token/[...]/+newaccount")
-
-        # Complete the registration process.
-        displayname = self.lipsum.getSubject(2)
-        password = self.lipsum.getWord()
-        params = response.extractForm(include_submit=True)
-
-        params.update({
-            'field.displayname': displayname,
-            'field.hide_email_addresses': 'on',
-            'field.password': password,
-            'field.password_dupe': password,
-            'field.actions.continue': 'Continue'})
-        # At the moment, creating your account doesn't log you in
-        # immidiately so you might end up at a 403 page - Bug #400610
-        response = self.post(
-            newaccount_url, params, ok_codes=[200, 302, 303, 403],
-            description="Post /token/[...]/+newaccount")
-        # Keep hitting the /login link until it works.
-        while response.code == 403:
-            login_url = self.absolute_url(response, '/login')
-            response = self.get(login_url, description="Get /login")
-            if response.get_base_url() == '/myrequest':
-                break
-            response = response.postForm(
-                0, self.post, {}, "Post /+openid")
-            if response.get_base_url() == '/+openid':
-                params = response.extractForm()
-                params['field.actions.auth'] = 'Sign In'
-                response = self.post(
-                    self.absolute_url(response, '/+decide'), params,
-                    description = "Post /+decide",
-                    ok_codes=[200, 302, 303, 403])
-
-        # Registration succeeded - should be on the order details page now.
-        self.assertEquals(response.get_base_url(), '/myrequest')
-
-        # Request some CDs.
-        params = response.extractForm(include_submit=True)
-        params.update({
-            'field.recipientdisplayname': displayname[:20],
-            'field.addressline1': self.lipsum.getSubject(3)[:30],
-            'field.addressline2': self.lipsum.getSubject(3)[:30],
-            'field.city': self.lipsum.getSubject(1)[:30],
-            'field.province': self.lipsum.getSubject(2)[:30],
-            'field.postcode': self.lipsum.getSubject(1)[:20],
-            'field.country': '212',
-            'field.country-empty-marker': '1',
-            'field.phone': self.lipsum.getPhoneNumber()[:16],
-            'field.actions.continue': 'Submit Request'})
-        response = self.post(
-            self.absolute_url(response, '/myrequest'),
-            params, "Post /myrequest - Request CDs")
-        self.assertNoFormErrors(response)
-
-        if response.body.find('Cancel Request') == -1:
-            open('dud.html', 'w').write(response.body)
-
-        # Confirm the request worked.
-        self.assert_(
-            response.body.find('Cancel Request') != -1,
-            "Cancel button not found.")
-
-        # Logout.
-        response = self.post(
-            server_url + "/+logout", description="Post /+logout")
-        self.assert_(
-            response.body.find('You have been logged out') != -1,
-            "No logged out notification.")
-
-        # Attempt to login again, bringing up the login form.
-        response = self.get(server_url, description="Get /")
-        response = self.get(
-            server_url + "/login", description="Get /login")
-        response = response.postForm(
-            0, self.post, {'submit': 'Continue'},
-            'Post /+openid - OpenID authentication request')
-        self.assertNoFormErrors(response)
-
-        # Submit the login form.
-        params = response.extractForm(include_submit=True)
-        params['field.email'] = email
-        params['field.password'] = password
-        params['field.action'] = 'login'
-        response = self.post(
-            self.absolute_url(response, '/+login-register'),
-            params, "Post /+login-register - Login to existing account")
-        self.assertNoFormErrors(response)
-        self.assertEquals(response.url, '/myrequest')
-
-        # Cancel the CD request.
-        params = response.extractForm([('form', 1)], include_submit=True)
-        response = self.post(
-            self.absolute_url(response, '/myrequest'),
-            params, description="Post /myrequest - Cancel CD order.")
-        self.assertNoFormErrors(response)
-        self.assert_(
-            response.body.find('Cancel Request') == -1,
-            "Cancel button found.")
-
-        # Don't log out - leave the session dangling like most real users
-        # do.
-
-    def absolute_url(self, response, path):
-        """Calculate an absolute URL using the response and the path."""
-        return '%s://%s:%s%s' % (
-            response.protocol, response.server, response.port, path)
-
-    def tearDown(self):
-        """Setting up test."""
-        self.logd("tearDown.\n")
-
-
-
-if __name__ in ('main', '__main__'):
-    unittest.main()

=== renamed directory 'optionalbzrplugins' => 'bzrplugins/optional'
=== added file 'bzrplugins/optional/README'
--- bzrplugins/optional/README	1970-01-01 00:00:00 +0000
+++ bzrplugins/optional/README	2011-02-18 18:56:20 +0000
@@ -0,0 +1,4 @@
+These are for plugins that we do *not* want loaded all of the time.
+
+Specifically, the code import system loads these plugins, but we do not want
+the branch puller or scanner loading them.

=== modified symlink 'bzrplugins/optional/git'
=== target changed u'../sourcecode/bzr-git' => u'../../sourcecode/bzr-git/'
=== modified symlink 'bzrplugins/optional/hg'
=== target changed u'../sourcecode/bzr-hg' => u'../../sourcecode/bzr-hg'
=== modified symlink 'bzrplugins/optional/svn'
=== target changed u'../sourcecode/bzr-svn' => u'../../sourcecode/bzr-svn'
=== modified file 'lib/canonical/config/__init__.py'
--- lib/canonical/config/__init__.py	2010-10-25 12:11:43 +0000
+++ lib/canonical/config/__init__.py	2011-02-18 18:56:20 +0000
@@ -239,7 +239,7 @@
 
         Call this method before letting any ZCML processing occur.
         """
-        loader_file = os.path.join(self.root, '+config-overrides.zcml')
+        loader_file = os.path.join(self.root, 'zcml/+config-overrides.zcml')
         loader = open(loader_file, 'w')
 
         print >> loader, """

=== modified file 'lib/canonical/config/tests/test_config_lookup.py'
--- lib/canonical/config/tests/test_config_lookup.py	2010-01-07 06:00:00 +0000
+++ lib/canonical/config/tests/test_config_lookup.py	2011-02-18 18:56:20 +0000
@@ -139,7 +139,7 @@
         # Set that root to the temporary directory.
         cfg.root = self.temp_config_root_dir
         cfg.generate_overrides()
-        override_file = os.path.join(cfg.root, '+config-overrides.zcml')
+        override_file = os.path.join(cfg.root, 'zcml/+config-overrides.zcml')
         self.failUnless(
             os.path.isfile(override_file), "Overrides file wasn't created.")
 

=== removed file 'lib/canonical/launchpad/doc/todo.txt'
--- lib/canonical/launchpad/doc/todo.txt	2008-06-19 02:55:59 +0000
+++ lib/canonical/launchpad/doc/todo.txt	1970-01-01 00:00:00 +0000
@@ -1,10 +0,0 @@
-
-= Ensure there are no outstanding TODO's =
-
- >>> todos = open('BRANCH.TODO').read()
- >>> print todos
- # Put your TODOs for this branch here, then make sure it is empty before
- # landing. There is a test to ensure it is empty in trunk. If there is
- # stuff still here when you are ready to land, the items should probably
- # be converted to bugs so they can be scheduled.
-

=== modified file 'lib/canonical/launchpad/scripts/__init__.py'
--- lib/canonical/launchpad/scripts/__init__.py	2010-12-20 03:21:03 +0000
+++ lib/canonical/launchpad/scripts/__init__.py	2011-02-18 18:56:20 +0000
@@ -71,7 +71,7 @@
         scriptzcmlfilename = 'script.zcml'
 
     scriptzcmlfilename = os.path.abspath(
-        os.path.join(config.root, scriptzcmlfilename))
+        os.path.join(config.root, 'zcml', scriptzcmlfilename))
 
     from zope.configuration import xmlconfig
 

=== modified file 'lib/canonical/launchpad/testing/googletestservice.py'
--- lib/canonical/launchpad/testing/googletestservice.py	2010-08-20 20:31:18 +0000
+++ lib/canonical/launchpad/testing/googletestservice.py	2011-02-18 18:56:20 +0000
@@ -29,6 +29,8 @@
     pidfile_path,
     )
 
+from lp.services.osutils import ensure_directory_exists
+
 # Set up basic logging.
 log = logging.getLogger(__name__)
 
@@ -107,7 +109,7 @@
     try:
         try:
             sock.connect((host, port))
-        except socket.error, err:
+        except socket.error:
             return False
         else:
             return True
@@ -255,6 +257,7 @@
     # Redirect our service output to a log file.
     # pylint: disable-msg=W0602
     global log
+    ensure_directory_exists(os.path.dirname(config.google_test_service.log))
     filelog = logging.FileHandler(config.google_test_service.log)
     log.addHandler(filelog)
     log.setLevel(logging.DEBUG)

=== modified file 'lib/canonical/testing/layers.py'
--- lib/canonical/testing/layers.py	2011-02-01 15:57:56 +0000
+++ lib/canonical/testing/layers.py	2011-02-18 18:56:20 +0000
@@ -139,6 +139,10 @@
 WAIT_INTERVAL = datetime.timedelta(seconds=180)
 
 
+def set_up_functional_test():
+    return FunctionalTestSetup('zcml/ftesting.zcml')
+
+
 class LayerError(Exception):
     pass
 
@@ -1018,7 +1022,7 @@
     # zope.publisher.paste.Application.
     request_cls, publication_cls = chooseClasses(
         environ['REQUEST_METHOD'], environ)
-    publication = publication_cls(FunctionalTestSetup().db)
+    publication = publication_cls(set_up_functional_test().db)
     request = request_cls(environ['wsgi.input'], environ)
     request.setPublication(publication)
     # The rest of this function is an amalgam of
@@ -1048,14 +1052,14 @@
     @profiled
     def setUp(cls):
         FunctionalLayer.isSetUp = True
-        FunctionalTestSetup().setUp()
+        set_up_functional_test().setUp()
 
-        # Assert that FunctionalTestSetup did what it says it does
+        # Assert that set_up_functional_test did what it says it does
         if not is_ca_available():
             raise LayerInvariantError("Component architecture failed to load")
 
         # If our request publication factories were defined using ZCML,
-        # they'd be set up by FunctionalTestSetup().setUp(). Since
+        # they'd be set up by set_up_functional_test().setUp(). Since
         # they're defined by Python code, we need to call that code
         # here.
         register_launchpad_request_publication_factories()
@@ -1083,7 +1087,7 @@
         transaction.begin()
 
         # Fake a root folder to keep Z3 ZODB dependencies happy.
-        fs = FunctionalTestSetup()
+        fs = set_up_functional_test()
         if not fs.connection:
             fs.connection = fs.db.open()
         root = fs.connection.root()

=== modified file 'lib/lp/app/versioninfo.py'
--- lib/lp/app/versioninfo.py	2010-12-14 09:45:07 +0000
+++ lib/lp/app/versioninfo.py	2011-02-18 18:56:20 +0000
@@ -20,12 +20,8 @@
 will have appropriate values from version_info.
 
 If that file exists, and contains invalid Python, there will be an error when
-this module is loaded.  This module is imported into
-canonical/launchpad/__init__.py so that such errors are caught at start-up.
-
-This module also reads version.txt at the top of the tree (i.e. a sibling of
-bzr-version-info.py), which contains the Launchpad release number.  If that
-file does not exist, we make something up.
+this module is loaded.  This module is imported into lp/app/__init__.py so
+that such errors are caught at start-up.
 """
 
 __all__ = [
@@ -56,15 +52,3 @@
     revno = versioninfo.get('revno')
     date = versioninfo.get('date')
     branch_nick = versioninfo.get('branch_nick')
-
-
-try:
-    version_file = open('version.txt')
-except IOError:
-    release = 'x.y.z'
-else:
-    try:
-        version_data = version_file.read()
-        release = version_data.strip()
-    finally:
-        version_file.close()

=== modified file 'lib/lp/codehosting/__init__.py'
--- lib/lp/codehosting/__init__.py	2010-02-21 22:01:19 +0000
+++ lib/lp/codehosting/__init__.py	2011-02-18 18:56:20 +0000
@@ -74,7 +74,7 @@
 def load_optional_plugin(plugin_name):
     """Load the plugin named `plugin_name` from optionalbzrplugins/."""
     from bzrlib import plugins
-    optional_plugin_dir = os.path.join(config.root, 'optionalbzrplugins')
+    optional_plugin_dir = os.path.join(config.root, 'bzrplugins/optional')
     if optional_plugin_dir not in plugins.__path__:
         plugins.__path__.append(optional_plugin_dir)
     __import__("bzrlib.plugins.%s" % plugin_name)

=== modified file 'lib/lp/services/osutils.py'
--- lib/lp/services/osutils.py	2010-08-20 20:31:18 +0000
+++ lib/lp/services/osutils.py	2011-02-18 18:56:20 +0000
@@ -89,3 +89,17 @@
             raise
     else:
         raise
+
+
+def ensure_directory_exists(directory, mode=0777):
+    """Create 'directory' if it doesn't exist.
+
+    :return: True if the directory had to be created, False otherwise.
+    """
+    try:
+        os.makedirs(directory, mode=mode)
+    except OSError, e:
+        if e.errno == errno.EEXIST:
+            return False
+        raise
+    return True

=== modified file 'lib/lp/services/tests/test_osutils.py'
--- lib/lp/services/tests/test_osutils.py	2010-08-19 11:29:36 +0000
+++ lib/lp/services/tests/test_osutils.py	2011-02-18 18:56:20 +0000
@@ -12,6 +12,7 @@
 import unittest
 
 from lp.services.osutils import (
+    ensure_directory_exists,
     remove_tree,
     until_no_eintr,
     )
@@ -46,6 +47,19 @@
         self.assertRaises(OSError, remove_tree, filename)
 
 
+class TestEnsureDirectoryExists(TestCase):
+    """Tests for 'ensure_directory_exists'."""
+
+    def test_directory_exists(self):
+        directory = self.makeTemporaryDirectory()
+        self.assertFalse(ensure_directory_exists(directory))
+
+    def test_directory_doesnt_exist(self):
+        directory = os.path.join(self.makeTemporaryDirectory(), 'foo/bar/baz')
+        self.assertTrue(ensure_directory_exists(directory))
+        self.assertTrue(os.path.isdir(directory))
+
+
 class TestUntilNoEINTR(TestCase):
     """Tests for until_no_eintr."""
 

=== removed directory 'logs'
=== removed file 'run.gdb'
--- run.gdb	2008-07-31 21:47:45 +0000
+++ run.gdb	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-run

=== modified file 'setup.py'
--- setup.py	2011-01-06 22:21:02 +0000
+++ setup.py	2011-02-18 18:56:20 +0000
@@ -81,7 +81,7 @@
         'zope.app.apidoc',
         'zope.app.appsetup',
         'zope.app.component',
-        'zope.app.dav', # ./package-includes/dav-configure.zcml
+        'zope.app.dav', # ./zcml/package-includes/dav-configure.zcml
         'zope.app.error',
         'zope.app.exception',
         'zope.app.file',

=== modified file 'site.zcml'
--- site.zcml	2010-07-21 10:26:48 +0000
+++ site.zcml	2011-02-18 18:56:20 +0000
@@ -4,20 +4,20 @@
 
 <configure xmlns="http://namespaces.zope.org/zope";>
 
-    <include file="zopeapp.zcml" />
+    <include file="zcml/zopeapp.zcml" />
     <!--<include package="zope.app" />-->
 
     <!-- Session machinery -->
-    <include file="zopeappsession.zcml" />
+    <include file="zcml/zopeappsession.zcml" />
 
     <!-- Browser Configurations -->
-    <include file="zopeappbrowser.zcml" />
+    <include file="zcml/zopeappbrowser.zcml" />
     <!-- <include package="zope.app" file="browser.zcml" /> -->
 
     <include package="canonical" />
 
-    <include files="package-includes/*-meta.zcml" />
-    <includeOverrides file="override-meta.zcml" />
+    <include files="zcml/package-includes/*-meta.zcml" />
+    <includeOverrides file="zcml/override-meta.zcml" />
 
     <!-- package-includes/*-configure.zcml contains package configuration
         shared between a normal launchpad instance and the test suite.
@@ -25,17 +25,17 @@
         package-includes/*-configure-testing.zcml contain configuration
         that needs to be different between normal and test modes.
     -->
-    <include files="package-includes/*-configure.zcml" />
-    <include files="package-includes/*-configure-normal.zcml" />
+    <include files="zcml/package-includes/*-configure.zcml" />
+    <include files="zcml/package-includes/*-configure-normal.zcml" />
 
     <!-- Provide local overrides of standard configurations-->
-    <includeOverrides file="override-configure.zcml" />
-    <includeOverrides file="override-configure-normal.zcml" />
+    <includeOverrides file="zcml/override-configure.zcml" />
+    <includeOverrides file="zcml/override-configure-normal.zcml" />
 
-    <include file="securitypolicy.zcml" />
+    <include file="zcml/securitypolicy.zcml" />
 
     <!-- include request summarizer here so it only affects webapp -->
-    <include file="summarizerequests.zcml" />
+    <include file="zcml/summarizerequests.zcml" />
 
     <include package="zc.zservertracelog" />
 

=== removed file 'test.config'
--- test.config	2005-10-31 18:29:12 +0000
+++ test.config	1970-01-01 00:00:00 +0000
@@ -1,116 +0,0 @@
-# test.config: options for Zope Test Runner.
-# Use this file to set Test Runner options that you would
-# otherwise set at the command line.
-
-# LEVEL=<int>
-# Run the tests at the given level.  See -a, --all.
-# LEVEL = 1
-
-# BUILD=<boolean>
-# Build extensions before testing. See -b.
-# BUILD = False
-
-# BUILD=<boolean>
-# Build extensions before testing. See -b.
-# BUILD = False
-
-# BUILD_INPLACE=<boolean>
-# With BUILD==True, tests will be run from src directory.
-# See -B.
-# BUILD_INPLACE = False
-
-# PYCHECKER=<boolean>
-# Use pychecker. See -c.
-# PYCHECKER = False
-
-# DEBUG=<boolean>
-# Run a debug version of test harness.
-# See -d.
-# DEBUG = False
-
-# DEBUGGER=<boolean>
-# whether to post-mortem with pdb.
-# See -D.
-# DEBUGGER = False
-
-# RUN_UNIT=<boolean>
-# RUN_FUNCTIONAL=<boolean>
-# Whether to run functional tests and/or unit tests.
-# Default behaviour is RUN_UNIT and RUN_FUNCTIONAL.
-# RUN_UNIT = True
-# RUN_FUNCTIONAL = True
-
-# GC_THRESHOLD=<None>|<int>
-# Set the garbage collection threshold.
-# See -g.
-# GC_THRESHOLD = None
-
-# GC_FLAGS=<list-of-str>
-# list of garbage collection flags to set.
-# See -G.
-# GC_FLAGS = []
-
-# KEEP_STALE_BYTECODE=<boolean>
-# Do not delete all stale bytecode before running tests.
-# See -k.
-
-# LIBDIR=<dirpath>
-# Search for tests starting in the specified start directory.
-# See -l.
-# LIBDIR = '/path/to/dir/'
-LIBDIR='lib'
-
-# LOOP=<boolean>
-# Keep running the selected tests in a loop.
-# See -L.
-# LOOP = False
-
-# PROGRESS=<boolean>
-# Show running PROGRESS.  It can be combined with -v or -vv.
-# See -p.
-# PROGRESS = False
-
-# REFCOUNT=<boolean>
-# Look for refcount problems.
-# See -r.
-# REFCOUNT = False
-
-# TRACE=<boolean>
-# Use the trace module from Python for code coverage.
-# See -T.
-# TRACE = False
-
-# TIMETESTS=<int>
-# Time the individual tests and print a list of the top <int>, sorted from
-# longest to shortest.
-# See -t (which sets TIMETESTS=50).
-# TIMETESTS = 0
-
-# TIMESFN=<filepath>
-# File to which to write timing information.
-# See -t.
-# TIMESFN = '/path/to/file'
-
-# VERBOSE=<int>
-# Verbosity level. Set VERBOSE=0 for quiet.
-# VERBOSE = 0
-
-# TEST_DIRS=<list>
-# List of paths, limiting where tests are searched for.
-# See --dir.
-# TEST_DIRS = ['/path/to/tests/']
-TEST_DIRS=["canonical"]
-
-# GUI=<boolean>|"minimal"
-# Whether to run unittest GUI. Use string value "minimal" for the minimal GUI.
-# GUI = False
-
-
-# MODULE_FILTER=<str>
-# Regular expression (in string format) for matching test module paths
-# MODULE_FILTER = None
-
-# TEST_FILTER=<str>
-# Regular expression (in string format) for matching test names
-# TEST_FILTER = None
-

=== removed directory 'todo'
=== removed file 'todo/debbugssync.txt'
--- todo/debbugssync.txt	2005-10-31 18:29:12 +0000
+++ todo/debbugssync.txt	1970-01-01 00:00:00 +0000
@@ -1,9 +0,0 @@
-
-test:
-
-  * that malone bugs are never linked debian packages more than once, no
-    matter how many times the sync process happens.
-  * that the "Mark all merged bugs as duplicates of the lowest-numbered bug"
-    logic works correctly in all cases
-  * that the watch last checked and last updated timestamps are updated
-

=== removed file 'todo/malone.txt'
--- todo/malone.txt	2009-02-18 09:05:32 +0000
+++ todo/malone.txt	1970-01-01 00:00:00 +0000
@@ -1,8 +0,0 @@
-
- - a proper CVE - Distro report
- - CVE relevance indicator
- - watch relevance indicator
- - make BugWatchSet.fromText find sourceforge
- - make it tell the user what changed when it returns to the bug page
-   after editing a bug task
-

=== added directory 'utilities/snakefood'
=== added file 'utilities/snakefood/Makefile'
--- utilities/snakefood/Makefile	1970-01-01 00:00:00 +0000
+++ utilities/snakefood/Makefile	2011-02-18 18:56:20 +0000
@@ -0,0 +1,38 @@
+LIB_DIR=../../lib
+
+default: lp-clustered.svg
+
+# Generate import dependency graph
+lp.sfood:
+	sfood -i -u -I $(LIB_DIR)/sqlobject -I $(LIB_DIR)/schoolbell \
+	-I $(LIB_DIR)/devscripts -I $(LIB_DIR)/contrib \
+	-I $(LIB_DIR)/canonical/not-used $(LIB_DIR)/canonical \
+	$(LIB_DIR)/lp 2>/dev/null | grep -v contrib/ \
+	| grep -v sqlobject | grep -v BeautifulSoup | grep -v psycopg \
+	| grep -v schoolbell | grep -v '/tests/' | grep -v '/ftests/' \
+    | grep -v 'canonical/config' > lp.sfood.tmp
+	mv lp.sfood.tmp lp.sfood
+
+
+# Cluster the import dependency graph
+lp-clustered.sfood: lp.sfood lp-sfood-packages
+	sfood-cluster -f lp-sfood-packages < lp.sfood > lp-clustered.sfood.tmp
+	mv lp-clustered.sfood.tmp lp-clustered.sfood
+
+
+# Build the visual graph
+lp-clustered.dot: lp-clustered.sfood
+	sfood-graph -p < lp-clustered.sfood > lp-clustered.dot.tmp
+	mv lp-clustered.dot.tmp lp-clustered.dot
+
+
+# Render to svg
+lp-clustered.svg: lp-clustered.dot
+	dot -Tsvg < lp-clustered.dot > lp-clustered.svg.tmp
+	mv lp-clustered.svg.tmp lp-clustered.svg
+
+clean:
+	$(RM) -f lp.sfood lp-clustered.sfood lp-clustered.dot lp-clustered.svg
+
+
+.PHONY: clean

=== added file 'utilities/snakefood/README'
--- utilities/snakefood/README	1970-01-01 00:00:00 +0000
+++ utilities/snakefood/README	2011-02-18 18:56:20 +0000
@@ -0,0 +1,4 @@
+Uses snakefood to generate dependency graphs of Launchpad, i.e. which packages
+use which other packages.
+
+To make the picture, run 'make', which will generate a nice SVG.

=== renamed file 'lp-sfood-packages' => 'utilities/snakefood/lp-sfood-packages'
--- lp-sfood-packages	2011-02-17 12:54:12 +0000
+++ utilities/snakefood/lp-sfood-packages	2011-02-18 18:56:20 +0000
@@ -1,3 +1,4 @@
+lp/vostok
 lp/translations
 lp/testopenid
 lp/testing
@@ -25,6 +26,7 @@
 canonical/lp
 canonical/librarian
 canonical/lazr
+canonical/launchpad/webapp
 canonical/launchpad
 canonical/ftests
 canonical/doap

=== removed file 'version.txt'
--- version.txt	2010-06-02 15:33:26 +0000
+++ version.txt	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-10.05

=== added directory 'zcml'
=== added file 'zcml/README'
--- zcml/README	1970-01-01 00:00:00 +0000
+++ zcml/README	2011-02-18 18:56:20 +0000
@@ -0,0 +1,24 @@
+This is all a bit speculative.
+
+Entry points
+============
+
+These are the bits of ZCML that are explicitly loaded by Python code. These
+ZCML files in turn load other parts.
+
+  site.zcml
+    The big kahuna. Various config files (e.g. launchpad.conf) refer
+    to this file.  For the time being, this must be available in the root
+    directory of the Launchpad tree, since production configuration files
+    depend on it being there.
+
+  ftesting.zcml
+    Used to configure the functional testing layer.  Look in
+    canonical.testing.layers to see how it gets hooked in.
+
+  script.zcml
+    The main ZCML used for "scripts". Anything that runs in the Zopeless layer
+    uses this.  See ``execute_zcml_for_scripts``.
+
+  script-testing.zcml
+    As for script.zcml, but for testing said scripts.

=== renamed file 'ftesting.zcml' => 'zcml/ftesting.zcml'
--- ftesting.zcml	2009-07-13 18:15:02 +0000
+++ zcml/ftesting.zcml	2011-02-18 18:56:20 +0000
@@ -2,6 +2,8 @@
      GNU Affero General Public License version 3 (see the file LICENSE).
 -->
 
+<!-- Used by the FunctionalLayer in canonical.testing.layers. -->
+
 <configure
     xmlns="http://namespaces.zope.org/zope";
     xmlns:rdb="http://namespaces.zope.org/rdb";

=== renamed file 'override-configure-normal.zcml' => 'zcml/override-configure-normal.zcml'
=== renamed file 'override-configure-testing.zcml' => 'zcml/override-configure-testing.zcml'
=== renamed file 'override-configure.zcml' => 'zcml/override-configure.zcml'
=== renamed directory 'override-includes' => 'zcml/override-includes'
=== renamed file 'override-meta.zcml' => 'zcml/override-meta.zcml'
=== renamed directory 'package-includes' => 'zcml/package-includes'
=== renamed file 'script-testing.zcml' => 'zcml/script-testing.zcml'
=== renamed file 'script.zcml' => 'zcml/script.zcml'
=== renamed file 'securitypolicy.zcml' => 'zcml/securitypolicy.zcml'
=== renamed file 'summarizerequests.zcml' => 'zcml/summarizerequests.zcml'
=== renamed file 'zopeapp.zcml' => 'zcml/zopeapp.zcml'
=== renamed file 'zopeappbrowser.zcml' => 'zcml/zopeappbrowser.zcml'
=== renamed file 'zopeappsession.zcml' => 'zcml/zopeappsession.zcml'
=== removed file 'zdaemon.conf'
--- zdaemon.conf	2005-10-31 18:29:12 +0000
+++ zdaemon.conf	1970-01-01 00:00:00 +0000
@@ -1,17 +0,0 @@
-<runner>
-  program bin/runzope
-</runner>
-
-<eventlog>
-  # This sets up logging to both a file (z3.log) and to standard
-  # output (STDOUT).  The "path" setting can be a relative or absolute
-  # filesystem path or the tokens STDOUT or STDERR.
-
-  <logfile>
-    path z3.log
-  </logfile>
-
-  <logfile>
-    path STDOUT
-  </logfile>
-</eventlog>