[#8336] Remove dead code root_page_name.setter, and very old migrations up to one that used that setter
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index f0f2030..ed1043a 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -150,17 +150,6 @@
             page_name = self.default_root_page_name
         return page_name
 
-    @root_page_name.setter
-    def root_page_name(self, new_root_page_name):
-        globals = WM.Globals.query.get(app_config_id=self.config._id)
-        if globals is not None:
-            globals.root = new_root_page_name
-        elif new_root_page_name != self.default_root_page_name:
-            globals = WM.Globals(
-                app_config_id=self.config._id, root=new_root_page_name)
-        if globals is not None:
-            session(globals).flush(globals)
-
     def default_root_page_text(self):
         return """Welcome to your wiki!
 
diff --git a/scripts/migrations/000-fix-tracker-fields.py b/scripts/migrations/000-fix-tracker-fields.py
deleted file mode 100644
index 072aeb9..0000000
--- a/scripts/migrations/000-fix-tracker-fields.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-import sys
-import logging
-
-from tg import tmpl_context as c
-
-from ming.orm import session
-
-from allura import model as M
-from forgetracker import model as TM
-
-log = logging.getLogger(__name__)
-
-
-def main():
-    test = sys.argv[-1] == 'test'
-    projects = M.Project.query.find().all()
-    log.info('Fixing tracker fields')
-    for p in projects:
-        if p.parent_id:
-            continue
-        c.project = p
-        q = TM.Globals.query.find()
-        if not q.count():
-            continue
-        for g in q:
-            if g.open_status_names:
-                continue
-            if g.status_names is None:
-                old_names = ['open', 'closed']
-            else:
-                old_names = g.status_names.split() or ['open', 'closed']
-            if g.open_status_names is None:
-                g.open_status_names = ' '.join(
-                    name for name in old_names if name != 'closed')
-            if g.closed_status_names is None:
-                g.closed_status_names = 'closed'
-        if test:
-            log.info('... would fix tracker(s) in %s', p.shortname)
-        else:
-            log.info('... fixing tracker(s) in %s', p.shortname)
-            session(g).flush()
-        session(g).clear()
-
-if __name__ == '__main__':
-    main()
diff --git a/scripts/migrations/001-restore-labels.py b/scripts/migrations/001-restore-labels.py
deleted file mode 100644
index 2e33da7..0000000
--- a/scripts/migrations/001-restore-labels.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-import sys
-import json
-import logging
-
-from tg import tmpl_context as c
-
-from ming.orm import session, MappedClass
-
-from allura import model as M
-
-log = logging.getLogger(__name__)
-
-
-def main():
-    test = sys.argv[-1] == 'test'
-    projects = M.Project.query.find().all()
-    log.info('Restoring labels on projects')
-    for p in projects:
-        restore_labels(p, test)
-    if not test:
-        session(p).flush()
-    log.info('Restoring labels on artifacts')
-    for p in projects:
-        if p.parent_id:
-            continue
-        c.project = p
-        for name, cls in MappedClass._registry.iteritems():
-            if not issubclass(cls, M.Artifact):
-                continue
-            if session(cls) is None:
-                continue
-            for a in cls.query.find():
-                restore_labels(a, test)
-        if not test:
-            M.artifact_orm_session.flush()
-        M.artifact_orm_session.clear()
-
-
-def restore_labels(obj, test=True):
-    if not obj.labels:
-        return
-    labels = obj.labels
-    while True:
-        if not labels or labels[0] != '[':
-            return
-        lbllen = map(len, labels)
-        if max(lbllen) != 1:
-            return
-        if min(lbllen) != 1:
-            return
-        s = ''.join(labels)
-        s = s.replace("u'", "'")
-        s = s.replace('u"', '"')
-        jobj = '{"obj":' + s.replace("'", '"') + '}'
-        try:
-            new_labels = json.loads(jobj)['obj']
-        except ValueError:
-            # some weird problem with json decoding, just erase the labels
-            new_labels = []
-        if not isinstance(new_labels, list):
-            return
-        for lbl in new_labels:
-            if not isinstance(lbl, basestring):
-                return
-        log.info('%s: %s => %s', obj.__class__, labels, new_labels)
-        labels = new_labels
-        if not test:
-            log.info('...actually restoring labels')
-            obj.labels = new_labels
-
-if __name__ == '__main__':
-    main()
diff --git a/scripts/migrations/002-fix-tracker-thread-subjects.py b/scripts/migrations/002-fix-tracker-thread-subjects.py
deleted file mode 100644
index df42446..0000000
--- a/scripts/migrations/002-fix-tracker-thread-subjects.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-import sys
-import logging
-
-from tg import tmpl_context as c
-
-from ming.orm import session
-
-from allura import model as M
-from forgetracker import model as TM
-
-log = logging.getLogger(__name__)
-
-
-def main():
-    test = sys.argv[-1] == 'test'
-    all_projects = M.Project.query.find().all()
-    log.info('Fixing tracker thread subjects')
-    for project in all_projects:
-        if project.parent_id:
-            continue
-        c.project = project
-        # will find all tickets for all trackers in this project
-        all_tickets = TM.Ticket.query.find()
-        if not all_tickets.count():
-            continue
-        for ticket in all_tickets:
-            thread = ticket.get_discussion_thread()
-            thread.subject = ''
-        if test:
-            log.info('... would fix ticket threads in %s', project.shortname)
-        else:
-            log.info('... fixing ticket threads in %s', project.shortname)
-            session(project).flush()
-        session(project).clear()
-
-if __name__ == '__main__':
-    main()
diff --git a/scripts/migrations/003-migrate_project_roles.py b/scripts/migrations/003-migrate_project_roles.py
deleted file mode 100644
index 32bcc57..0000000
--- a/scripts/migrations/003-migrate_project_roles.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-'''Merge all the OldProjectRole collections in into a ProjectRole collection.
-'''
-import logging
-
-from ming.orm import session, state
-from allura import model as M
-
-log = logging.getLogger(__name__)
-
-log.info('Moving project roles in database %s to main DB',
-         M.Project.database_uri())
-for opr in M.OldProjectRole.query.find():
-    pr = M.ProjectRole(**state(opr).document)
-session(opr).clear()
-session(pr).flush()
-session(pr).clear()
diff --git a/scripts/migrations/004-make-attachments-polymorphic.py b/scripts/migrations/004-make-attachments-polymorphic.py
deleted file mode 100644
index e6133ec..0000000
--- a/scripts/migrations/004-make-attachments-polymorphic.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-import logging
-
-from ming.orm import ThreadLocalORMSession
-from allura import model as M
-from forgetracker import model as TM
-from forgewiki import model as WM
-from forgediscussion import model as DM
-
-log = logging.getLogger(__name__)
-
-
-def main():
-    db = M.project_doc_session.db
-    log.info('=== Making attachments in %s polymorphic ===', db)
-    log.info('Fixing %d discussions', M.Discussion.query.find().count())
-    for d in M.Discussion.query.find():
-        for a in M.DiscussionAttachment.query.find(dict(
-                discussion_id=d._id)):
-            log.info('%s: %s', d.url(), a.filename)
-    log.info('Fixing %d forums', DM.Forum.query.find().count())
-    for d in DM.Forum.query.find():
-        for a in DM.ForumAttachment.query.find(dict(
-                discussion_id=d._id)):
-            log.info('%s: %s', d.url(), a.filename)
-    log.info('Fixing %d tickets', TM.Ticket.query.find().count())
-    for t in TM.Ticket.query.find():
-        for a in TM.TicketAttachment.query.find(dict(
-                artifact_id=t._id)):
-            log.info('%s: %s', t.url(), a.filename)
-    log.info('Fixing %d wikis', WM.Page.query.find().count())
-    for p in WM.Page.query.find():
-        for a in WM.WikiAttachment.query.find(dict(
-                artifact_id=p._id)):
-            log.info('%s: %s', p.url(), a.filename)
-    ThreadLocalORMSession.flush_all()
-
-if __name__ == '__main__':
-    main()
diff --git a/scripts/migrations/005-remove_duplicate_ticket_notifications.py b/scripts/migrations/005-remove_duplicate_ticket_notifications.py
deleted file mode 100644
index 716c604..0000000
--- a/scripts/migrations/005-remove_duplicate_ticket_notifications.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-import sys
-import logging
-import re
-from itertools import groupby
-
-import pymongo
-from ming.orm import ThreadLocalORMSession
-
-from allura import model as M
-
-log = logging.getLogger(__name__)
-
-# Given a list of subscriptions, try to find one with a proper artifact_url, and delete the rest
-# If none of them have artifact_urls, delete them all
-
-
-def trim_subs(subs, test):
-    prime = False
-
-    print "Found %d '%s' subs with for user '%s'" % (len(subs), subs[0].artifact_title, str(subs[0].user_id))
-    for sub in subs:
-        if sub.artifact_url and not prime:
-            prime = True
-            print "   Keeping good subscription with a URL of '%s'" % sub.artifact_url
-        else:
-            if not sub.artifact_url:
-                print "   Found subscription with no artifact URL, deleting."
-            else:
-                print "   Subscription has URL, but is a duplicate, deleting."
-            if not test:
-                sub.delete()
-
-
-def main():
-    test = sys.argv[-1] == 'test'
-    title = re.compile('Ticket .*')
-    all_subscriptions = M.Mailbox.query.find(dict(artifact_title=title, type='direct')).sort(
-        [('artifact_title', pymongo.ASCENDING), ('user_id', pymongo.DESCENDING)]).all()
-    log.info('Fixing duplicate tracker subscriptions')
-
-    for (key, group) in groupby(
-            all_subscriptions,
-            key=lambda sub: (sub.artifact_title, sub.user_id)):
-        group = list(group)
-        if group:
-            trim_subs(group, test)
-    if not test:
-        ThreadLocalORMSession.flush_all()
-
-
-if __name__ == '__main__':
-    main()
diff --git a/scripts/migrations/006-migrate-artifact-refs.py b/scripts/migrations/006-migrate-artifact-refs.py
deleted file mode 100644
index aeae677..0000000
--- a/scripts/migrations/006-migrate-artifact-refs.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-import sys
-import logging
-from cPickle import loads
-
-from allura import model as M
-
-log = logging.getLogger('allura.migrate-artifact-refs')
-
-# Threads have artifact references that must be migrated to the new system
-
-
-def main():
-    test = sys.argv[-1] == 'test'
-    log.info('Fixing artifact references in threads')
-    db = M.project_doc_session.db
-    for thread in db.thread.find():
-        ref = thread.pop('artifact_reference', None)
-        if ref is None:
-            continue
-        Artifact = loads(ref['artifact_type'])
-        artifact = Artifact.query.get(_id=ref['artifact_id'])
-        M.ArtifactReference.from_artifact(artifact)
-        thread['ref_id'] = artifact.index_id()
-        if not test:
-            db.thread.save(thread)
-            log.info('saving thread %s', thread['_id'])
-        else:
-            log.info('would save thread %s', thread['_id'])
-        M.artifact_orm_session.clear()
-
-if __name__ == '__main__':
-    main()
diff --git a/scripts/migrations/007-update-acls.py b/scripts/migrations/007-update-acls.py
deleted file mode 100644
index 1cc8f3b..0000000
--- a/scripts/migrations/007-update-acls.py
+++ /dev/null
@@ -1,242 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-import logging
-from optparse import OptionParser
-from pprint import pformat
-
-import bson
-from tg import tmpl_context as c
-from ming.base import Object
-
-from allura import model as M
-from allura.command.show_models import dfs, build_model_inheritance_graph
-
-log = logging.getLogger('update-acls')
-
-options = None
-optparser = OptionParser(
-    usage='allurapaste script <ini file> -- %prog [options] [neighborhood1...]')
-optparser.add_option('-t', '--test',  dest='test', action='store_true')
-
-main_db = M.main_doc_session.db
-c_neighborhood = main_db.neighborhood
-c_project = main_db.project
-c_user = main_db.user
-c_project_role = main_db.project_role
-c.project = Object(
-    database_uri=M.Project.database_uri())
-
-project_db = M.project_doc_session.db
-c_app_config = project_db.config
-
-
-def main():
-    global options
-    options, neighborhoods = optparser.parse_args()
-    if neighborhoods:
-        log.info('Updating neighborhoods: %s', neighborhoods)
-        q_neighborhoods = list(
-            c_neighborhood.find(dict(name={'$in': neighborhoods})))
-        neighborhood_ids = [n['_id'] for n in q_neighborhoods]
-        q_projects = list(
-            c_project.find(dict(neighborhood_id={'$in': neighborhood_ids})))
-        project_ids = list(p['_id'] for p in q_projects)
-        q_app_config = list(
-            c_app_config.find(dict(project_id={'$in': project_ids})))
-        log.info('... %d neighborhoods', len(q_neighborhoods))
-        log.info('... %d projects', len(q_projects))
-        log.info('... %d app configs', len(q_app_config))
-    else:
-        q_neighborhoods = c_neighborhood.find()
-        q_projects = c_project.find()
-        q_app_config = c_app_config.find()
-        log.info('Updating all neighborhoods')
-    # Update project acls
-    log.info('====================================')
-    log.info('Update project ACLs')
-    for p in q_projects:
-        update_project_acl(p)
-        if not options.test:
-            c_project.save(p)
-    # Update neighborhood acls
-    log.info('====================================')
-    log.info('Update neighborhood ACLs')
-    for n in q_neighborhoods:
-        p = c_project.find(dict(
-            neighborhood_id=n['_id'], shortname='--init--')).next()
-        update_neighborhood_acl(n, p)
-        if not options.test:
-            c_neighborhood.save(n)
-            c_project.save(p)
-    graph = build_model_inheritance_graph()
-    # Update app config acls
-    log.info('====================================')
-    log.info('Update appconfig ACLs')
-    for ac in q_app_config:
-        simple_acl_update(ac, 'app_config')
-        if not options.test:
-            c_app_config.save(ac)
-        # Update artifact acls
-        log.info('====================================')
-        log.info('Update artifact ACLs for %s', ac['_id'])
-        for _, a_cls in dfs(M.Artifact, graph):
-            c_artifact = project_db[a_cls.__mongometa__.name]
-            for a in c_artifact.find(dict(app_config_id=ac['_id'])):
-                empty_acl = a['acl'] == []
-                simple_acl_update(a, a_cls.__mongometa__.name)
-                if not options.test and not empty_acl:
-                    c_artifact.save(a)
-
-
-def update_project_acl(project_doc):
-    '''Convert the old dict-style ACL to a list of ALLOW ACEs. Also move the
-    security,tool,delete perms to 'admin'
-    '''
-    if not isinstance(project_doc['acl'], dict):
-        log.warning('Project %s is already updated', project_doc['shortname'])
-        return
-    perm_map = dict(
-        read='read',
-        create='create',
-        update='update',
-        security='admin',
-        tool='admin',
-        delete='admin')
-    new_acl = []
-    for perm, role_ids in sorted(project_doc['acl'].iteritems()):
-        perm = perm_map[perm]
-        for rid in role_ids:
-            if c_project_role.find(dict(_id=rid)).count() == 0:
-                continue
-            _grant(new_acl, perm, rid)
-    if options.test:
-        log.info('--- update %s\n%s\n%s\n---',
-                 project_doc['shortname'],
-                 pformat(_format_acd(project_doc['acl'])),
-                 pformat(map(_format_ace, new_acl)))
-    project_doc['acl'] = new_acl
-
-
-def update_neighborhood_acl(neighborhood_doc, init_doc):
-    '''Convert nbhd admins users to --init-- project admins'''
-    if options.test:
-        log.info('Update nbhd %s', neighborhood_doc['name'])
-    if 'acl' not in neighborhood_doc:
-        log.warning('Neighborhood %s already updated',
-                    neighborhood_doc['name'])
-        return
-    p = Object(init_doc)
-    p.root_project = p
-    r_anon = _project_role(init_doc['_id'], '*anonymous')
-    r_auth = _project_role(init_doc['_id'], '*authenticated')
-    r_admin = _project_role(init_doc['_id'], 'Admin')
-    acl = neighborhood_doc['acl']
-    new_acl = list(init_doc['acl'])
-    assert acl['read'] == [None]  # nbhd should be public
-    for uid in acl['admin'] + acl['moderate']:
-        u = c_user.find(dict(_id=uid)).next()
-        if options.test:
-            log.info('... grant nbhd admin to: %s', u['username'])
-            continue
-        role = _project_role(init_doc['_id'], user_id=uid)
-        if r_admin['_id'] not in role['roles']:
-            role['roles'].append(r_admin['_id'])
-            c_project_role.save(role)
-    _grant(new_acl, 'read', r_anon['_id'])
-    _grant(new_acl, 'admin', r_admin['_id'])
-    _grant(new_acl, 'register', r_admin['_id'])
-    if acl['create'] == []:
-        if options.test:
-            log.info('grant register to auth')
-        _grant(new_acl, 'register', r_auth['_id'])
-    del neighborhood_doc['acl']
-    if options.test:
-        log.info('--- new init acl:\n%s\n%s\n---',
-                 pformat(_format_acd(init_doc['acl'])),
-                 pformat(map(_format_ace, new_acl)))
-    init_doc['acl'] = new_acl
-
-
-def _project_role(project_id, name=None, user_id=None):
-    doc = dict(project_id=project_id)
-    if name:
-        doc['name'] = name
-    else:
-        doc['user_id'] = user_id
-    for role in c_project_role.find(doc):
-        return role
-    assert name is None
-    doc.update(
-        _id=bson.ObjectId(),
-        roles=[])
-    c_project_role.save(doc)
-    return doc
-
-
-def simple_acl_update(doc, collection_name):
-    '''Update dict-style to list-style ACL'''
-    if not isinstance(doc['acl'], dict):
-        log.warning('Already upgraded %s: %s', collection_name, doc)
-        return
-
-    new_acl = []
-    for perm, role_ids in sorted(doc['acl'].iteritems()):
-        for rid in role_ids:
-            _grant(new_acl, perm, rid)
-    if options.test and doc['acl']:
-        log.info('--- update %s %s\n%s\n%s\n---',
-                 collection_name, doc['_id'],
-                 pformat(_format_acd(doc['acl'])),
-                 pformat(map(_format_ace, new_acl)))
-    doc['acl'] = new_acl
-
-
-def _grant(acl, permission, role_id):
-    ace = dict(
-        access='ALLOW',
-        permission=permission,
-        role_id=role_id)
-    if ace not in acl:
-        acl.append(ace)
-
-
-def _format_ace(ace):
-    if isinstance(ace, basestring):
-        return ace
-    return '(%s, %s, %s)' % (
-        ace['access'], ace['permission'], _format_role(ace['role_id']))
-
-
-def _format_role(rid):
-    for role in c_project_role.find(dict(_id=rid)):
-        if role['name']:
-            return role['name']
-        if role['user_id']:
-            u = c_user.find(_id=role['user_id']).next()
-            return u['username']
-        break
-    return '--invalid--'
-
-
-def _format_acd(acd):
-    return dict(
-        (k, map(_format_role, v))
-        for k, v in acd.iteritems())
-
-if __name__ == '__main__':
-    main()
diff --git a/scripts/migrations/008-remove-forumpost-subject.py b/scripts/migrations/008-remove-forumpost-subject.py
deleted file mode 100644
index af344d5..0000000
--- a/scripts/migrations/008-remove-forumpost-subject.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-"""
-Remove the subject FieldProperty from all ForumPost objects. [#2071]
-"""
-
-import logging
-import sys
-
-from allura import model as M
-
-log = logging.getLogger(__name__)
-
-c_forumpost = M.project_doc_session.db.forum_post
-
-
-def main():
-    test = sys.argv[-1] == 'test'
-
-    forum_posts = c_forumpost.find()
-    for fp in forum_posts:
-        try:
-            s = fp['subject']
-            if test:
-                log.info('... would remove subject "%s" from %s', s, fp['_id'])
-            else:
-                log.info('... removing subject "%s" from %s', s, fp['_id'])
-                del fp['subject']
-                c_forumpost.save(fp)
-        except KeyError:
-            log.info('... no subject property on %s', fp['_id'])
-
-if __name__ == '__main__':
-    main()
diff --git a/scripts/migrations/009-set_landing_page.py b/scripts/migrations/009-set_landing_page.py
deleted file mode 100644
index 65ca7a1..0000000
--- a/scripts/migrations/009-set_landing_page.py
+++ /dev/null
@@ -1,140 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-from allura.model import Neighborhood
-from ming.orm import ThreadLocalORMSession
-
-
-homepage = """<style type="text/css">
-ul.ui-tab { display: none; }
-div.content {
-    font-family: Helvetica;
-}
-div.content div.row > div.column {
-    width: 100%
-}
-div.welcome { margin: 2em 0; }
-div.welcome p {
-    display: block;
-    position: relative;
-    left: 8em;
-    width: 80%;
-}
-div.welcome a {
-    display: inline-block;
-    font-weight: 600;
-    color: white;
-    margin-left: 1.5em;
-    padding: 0.5em 1.5em 0.45em 1.5em;
-    text-decoration: none;
-    -webkit-border-radius: 5px;
-    -moz-border-radius: 5px;
-	background: rgb(0,0,0);
-		background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, to(rgb(0,0,0)), from(rgb(90,90,90)));
-		background-image: -moz-linear-gradient(100% 100% 90deg, rgb(0,0,0), rgb(90,90,90) 100%);
-    border: 1px solid black;
-}
-div.inner-row { 
-    display: block;
-    position: relative;
-    padding: 1em 1em 1em 10em;
-}
-div.inner-row + div.inner-row { padding-top: 4.8em; }
-div.tool {
-    display: inline-block;
-    position: relative;
-    width: 30%;
-    padding: 0 1em 3em 0;
-}
-div.tool img {
-    position: absolute;
-    left: -64px;
-    top: 0;
-}
-div.tool h1, div.welcome {
-    font-size:18px;
-    font-weight: 300;
-}
-div.tool h1 {
-    position: relative;
-    top: -15px;
-}
-div.tool p {
-    display: block;
-    font-size: 13px;
-    line-height: 18px;
-    position: absolute;
-    padding-right: 6em;
-    top: 12px;
-}
-</style>
-<div class="welcome">
-    <p>We provide the tools.  You create great open source software.
-    <a href="/p/add_project">Start&nbsp;Your&nbsp;Project</a>
-    </p>
-</div>
-<div class="inner-row">
-    <div class="tool">
-        <img src="/nf/allura/images/wiki_48.png" alt=""/>
-        <h1>Wikis</h1>
-        <p>
-            Documentation is key to your project and the wiki tool helps make it easy for anyone to contribute.
-        </p>
-    </div>
-    <div class="tool">
-        <img src="/nf/allura/images/code_48.png" alt=""/>
-        <h1>Code</h1>
-        <p>
-            SVN, Git and Mercurial will help you keep track of your changes.
-        </p>
-    </div>
-    <div class="tool">
-        <img src="/nf/allura/images/tickets_48.png" alt=""/>
-        <h1>Tickets</h1>
-        <p>
-            Bugs, enhancements, tasks, etc., will help you plan and manage your development.
-        </p>
-    </div>
-</div>
-<div class="inner-row">
-    <div class="tool">
-        <img src="/nf/allura/images/downloads_48.png" alt=""/>
-        <h1>Downloads</h1>
-        <p>
-            Use the largest free, managed, global mirror network to distribute your files.
-        </p>
-    </div>
-    <div class="tool">
-        <img src="/nf/allura/images/stats_48.png" alt=""/>
-        <h1>Stats</h1>
-        <p>
-            Follow the download trends that enable you to develop better software.
-        </p>
-    </div>
-    <div class="tool">
-        <img src="/nf/allura/images/forums_48.png" alt=""/>
-        <h1>Forums</h1>
-        <p>
-            Collaborate with your community in your forums.
-        </p>
-    </div>
-</div>
-"""
-
-projects_neighborhood = Neighborhood.query.find(dict(name='Projects')).first()
-projects_neighborhood.homepage = homepage
-ThreadLocalORMSession.flush_all()
diff --git a/scripts/migrations/010-fix-home-permissions.py b/scripts/migrations/010-fix-home-permissions.py
deleted file mode 100644
index 1b669d5..0000000
--- a/scripts/migrations/010-fix-home-permissions.py
+++ /dev/null
@@ -1,96 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-import sys
-import logging
-from collections import OrderedDict
-
-from tg import tmpl_context as c
-from ming.orm import session
-from bson import ObjectId
-
-from allura import model as M
-from allura.lib import utils
-from forgewiki.wiki_main import ForgeWikiApp
-
-log = logging.getLogger('fix-home-permissions')
-handler = logging.StreamHandler(sys.stdout)
-log.addHandler(handler)
-
-TEST = sys.argv[-1].lower() == 'test'
-
-
-def main():
-
-    if TEST:
-        log.info('Examining permissions for all Home Wikis')
-    else:
-        log.info('Fixing permissions for all Home Wikis')
-
-    for some_projects in utils.chunked_find(M.Project, {'neighborhood_id': {
-        '$nin': [ObjectId('4be2faf8898e33156f00003e'),      # /u
-                 ObjectId('4dbf2563bfc09e6362000005')]}}):  # /motorola
-        for project in some_projects:
-            c.project = project
-            home_app = project.app_instance('home')
-            if isinstance(home_app, ForgeWikiApp):
-                log.info('Examining permissions in project "%s".' %
-                         project.shortname)
-                root_project = project.root_project or project
-                authenticated_role = project_role(
-                    root_project, '*authenticated')
-                member_role = project_role(root_project, 'Member')
-
-                # remove *authenticated create/update permissions
-                new_acl = OrderedDict(
-                    ((ace.role_id, ace.access, ace.permission), ace)
-                    for ace in home_app.acl
-                    if not (
-                        ace.role_id == authenticated_role._id and ace.access == M.ACE.ALLOW and ace.permission in (
-                            'create', 'edit', 'delete', 'unmoderated_post')
-                    )
-                )
-                if (member_role._id, M.ACE.ALLOW, 'update') in new_acl:
-                    del new_acl[(member_role._id, M.ACE.ALLOW, 'update')]
-
-                # add member create/edit permissions
-                new_acl[(member_role._id, M.ACE.ALLOW, 'create')
-                        ] = M.ACE.allow(member_role._id, 'create')
-                new_acl[(member_role._id, M.ACE.ALLOW, 'edit')
-                        ] = M.ACE.allow(member_role._id, 'edit')
-                new_acl[(member_role._id, M.ACE.ALLOW, 'unmoderated_post')] = M.ACE.allow(
-                    member_role._id, 'unmoderated_post')
-
-                if TEST:
-                    log.info(
-                        '...would update acl for home app in project "%s".' %
-                        project.shortname)
-                else:
-                    log.info('...updating acl for home app in project "%s".' %
-                             project.shortname)
-                    home_app.config.acl = map(dict, new_acl.values())
-                    session(home_app.config).flush()
-
-
-def project_role(project, name):
-    role = M.ProjectRole.query.get(project_id=project._id, name=name)
-    if role is None:
-        role = M.ProjectRole(project_id=project._id, name=name)
-    return role
-
-if __name__ == '__main__':
-    main()
diff --git a/scripts/migrations/011-fix-subroles.py b/scripts/migrations/011-fix-subroles.py
deleted file mode 100644
index cb63c6b..0000000
--- a/scripts/migrations/011-fix-subroles.py
+++ /dev/null
@@ -1,103 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-"""
-For projects:
-    * Admin role.roles should contain Developer, and Developer only
-    * Developer role.roles should contain Member, and Member only
-
-For project.users:
-    * user.project_role().roles, if it contains Admin, should not contain
-      Developer or Member
-    * user.project_role().roles, if it contains Developer, should not contain
-      Member
-"""
-import sys
-import logging
-
-from ming.orm import session
-from ming.orm.ormsession import ThreadLocalORMSession
-
-from allura import model as M
-from allura.lib import utils
-
-log = logging.getLogger('fix-subroles')
-log.addHandler(logging.StreamHandler(sys.stdout))
-
-
-def main():
-    test = sys.argv[-1] == 'test'
-    num_projects_examined = 0
-    log.info('Examining subroles in all non-user projects.')
-    n_users = M.Neighborhood.query.get(name='Users')
-    project_filter = dict(neighborhood_id={'$ne': n_users._id})
-    for some_projects in utils.chunked_find(M.Project, project_filter):
-        for project in some_projects:
-            project_name = '%s.%s' % (
-                project.neighborhood.name, project.shortname)
-            project_roles = {}
-            for parent, child in [('Admin', 'Developer'), ('Developer', 'Member')]:
-                parent_role = M.ProjectRole.by_name(parent, project=project)
-                child_role = M.ProjectRole.by_name(child, project=project)
-                project_roles[parent] = parent_role
-                project_roles[child] = child_role
-                if not (parent_role and child_role):
-                    break
-                if len(parent_role.roles) != 1 or parent_role.roles[0] != child_role._id:
-                    if test:
-                        log.info('Would reset %s subroles for project "%s".' %
-                                 (parent, project_name))
-                        log.info('- Existing %s subrole(s): %s' %
-                                 (parent, parent_role.roles))
-                    else:
-                        log.info('Resetting %s subroles for project "%s".' %
-                                 (parent, project_name))
-                        parent_role.roles = [child_role._id]
-                        ThreadLocalORMSession.flush_all()
-            if not (project_roles['Admin'] and project_roles['Developer']
-                    and project_roles['Member']):
-                log.info(
-                    'Skipping "%s": missing Admin, Developer, or Member roles' %
-                    project_name)
-                continue
-            for user in project.users():
-                pr = user.project_role(project=project)
-                if not pr.roles:
-                    continue
-                for parent, children in [('Admin', ('Developer', 'Member')),
-                                         ('Developer', ('Member',))]:
-                    if project_roles[parent]._id not in pr.roles:
-                        continue
-                    for role_name in children:
-                        extra_role = project_roles[role_name]
-                        if extra_role._id in pr.roles:
-                            if test:
-                                log.info('Would remove %s role from user "%s" in project "%s" (already has %s role).'
-                                         % (role_name, user.username, project_name, parent))
-                                pr.roles.remove(extra_role._id)
-                            else:
-                                log.info('Removing %s role from user "%s" in project "%s" (already has %s role).'
-                                         % (role_name, user.username, project_name, parent))
-                                pr.roles.remove(extra_role._id)
-                                ThreadLocalORMSession.flush_all()
-            num_projects_examined += 1
-            session(project).clear()
-
-        log.info('%s projects examined.' % num_projects_examined)
-
-if __name__ == '__main__':
-    main()
diff --git a/scripts/migrations/012-uninstall-home.py b/scripts/migrations/012-uninstall-home.py
deleted file mode 100644
index 9c5bd79..0000000
--- a/scripts/migrations/012-uninstall-home.py
+++ /dev/null
@@ -1,139 +0,0 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you under the Apache License, Version 2.0 (the
-#       "License"); you may not use this file except in compliance
-#       with the License.  You may obtain a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#       Unless required by applicable law or agreed to in writing,
-#       software distributed under the License is distributed on an
-#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#       KIND, either express or implied.  See the License for the
-#       specific language governing permissions and limitations
-#       under the License.
-
-import sys
-import logging
-
-from tg import tmpl_context as c
-from ming.orm import session
-from bson import ObjectId
-from mock import Mock, patch
-
-from allura.lib import helpers as h
-from allura.lib import utils
-from allura import model as M
-from forgewiki import model as WM
-from allura.ext.project_home import ProjectHomeApp
-
-log = logging.getLogger('uninstall-home')
-log.addHandler(logging.StreamHandler(sys.stdout))
-
-
-def main():
-    test = sys.argv[-1] == 'test'
-    log.info('Removing "home" tools')
-    affected_projects = 0
-    possibly_orphaned_projects = 0
-    solr_delete = Mock()
-    notification_post = Mock()
-    for some_projects in utils.chunked_find(M.Project, {'neighborhood_id': {
-            '$ne': ObjectId("4be2faf8898e33156f00003e")}}):
-        for project in some_projects:
-            c.project = project
-            old_home_app = project.app_instance('home')
-            if isinstance(old_home_app, ProjectHomeApp):
-
-                # would we actually be able to install a wiki?
-                if M.ProjectRole.by_name('Admin') is None:
-                    log.warning('project %s may be orphaned' %
-                                project.shortname)
-                    possibly_orphaned_projects += 1
-                    continue
-
-                affected_projects += 1
-
-                # remove the existing home tool
-                if test:
-                    log.info('would remove "home" tool from project ' +
-                             project.shortname)
-                else:
-                    log.info('removing "home" tool from project ' +
-                             project.shortname)
-                    with patch('allura.app.g.solr.delete', solr_delete):
-                        project.uninstall_app('home')
-
-                # ...and put a Wiki in its place (note we only create a Wiki if we deleted the old home)
-                if test:
-                    log.info('would create Wiki "home" for project ' +
-                             project.shortname)
-                else:
-                    log.info('creating Wiki "home" for project ' +
-                             project.shortname)
-                    home_title = project.homepage_title or 'Home'
-                    wiki_text = project.description or ''
-                    if wiki_text == 'You can edit this description in the admin page':
-                        wiki_text = 'You can edit this description'
-
-                    # re-number all the mounts so the new Wiki comes first
-                    mounts = project.ordered_mounts()
-                    with patch('forgewiki.model.wiki.Notification.post', notification_post):
-                        new_home_app = project.install_app(
-                            'Wiki', 'home', 'Home')
-                    mounts = [{'ordinal': 0, 'ac': new_home_app.config}] + \
-                        mounts
-                    for i, mount in enumerate(mounts):
-                        if 'ac' in mount:
-                            mount['ac'].options['ordinal'] = i
-                            session(mount['ac']).flush()
-                        elif 'sub' in mount:
-                            mount['sub'].ordinal = i
-                            session(mount['sub']).flush()
-
-                    # make it look as much like the old home tool as possible
-                    new_home_app.config.options['show_left_bar'] = False
-                    new_home_app.config.options['show_discussion'] = False
-
-                    # now let's fix the home page itself
-                    log.info('updating home page to "%s"' % home_title)
-                    new_home_page = WM.Page.query.find(
-                        dict(app_config_id=new_home_app.config._id)).first()
-                    with h.push_config(c, app=new_home_app):
-                        if new_home_page is None:
-                            # weird: we didn't find the existing home page
-                            log.warning(
-                                'hmmm, actually creating the home page ("%s") for project "%s" from scratch' %
-                                (home_title, project.shortname))
-                            new_home_page = WM.Page.upsert(home_title)
-                            new_home_page.viewable_by = ['all']
-                        new_home_page.title = home_title
-                        new_home_page.text = wiki_text
-                        with patch('forgewiki.model.wiki.Notification.post', notification_post):
-                            new_home_page.commit()
-                    assert new_home_page is not None
-                    assert new_home_page.title == home_title
-                    assert new_home_page.version == 2
-
-                    # if we changed the home page name, make sure the Wiki
-                    # knows that's the root page
-                    new_home_app.root_page_name = home_title
-
-                session(project).flush()
-            session(project).clear()
-    if test:
-        log.info('%s projects would be updated' % affected_projects)
-    else:
-        log.info('%s projects were updated' % affected_projects)
-    if possibly_orphaned_projects:
-        log.warning('%s possibly orphaned projects found' %
-                    possibly_orphaned_projects)
-    if not test:
-        assert solr_delete.call_count == affected_projects, solr_delete.call_count
-        assert notification_post.call_count == 2 * \
-            affected_projects, notification_post.call_count
-
-if __name__ == '__main__':
-    main()